taskjuggler 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (415) hide show
  1. data/CHANGELOG +119 -0
  2. data/benchmarks/allocatedSlots.tjp +1602 -0
  3. data/benchmarks/booking.tjp +40 -30
  4. data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/css/tjmanual.css +0 -0
  5. data/{test/TestSuite/Scheduler/Correct → benchmarks}/css/tjreport.css +1 -0
  6. data/benchmarks/gantt.tjp +57 -0
  7. data/benchmarks/htmltaskreport.tjp +26 -1
  8. data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/details.png +0 -0
  9. data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/flag-green.png +0 -0
  10. data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/flag-red.png +0 -0
  11. data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/flag-yellow.png +0 -0
  12. data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/resource.png +0 -0
  13. data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/resourcegroup.png +0 -0
  14. data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/task.png +0 -0
  15. data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/taskgroup.png +0 -0
  16. data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/trend-down.png +0 -0
  17. data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/trend-flat.png +0 -0
  18. data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/trend-up.png +0 -0
  19. data/benchmarks/profile.clt +36082 -0
  20. data/benchmarks/profile.html +58182 -0
  21. data/benchmarks/runbench.rb +6 -0
  22. data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/scripts/wz_tooltip.js +0 -0
  23. data/doc/AppConfig.html +85 -37
  24. data/doc/Arguments.html +11 -1
  25. data/doc/CHANGELOG.html +131 -2
  26. data/doc/COPYING.html +11 -1
  27. data/doc/Object.html +12 -3
  28. data/doc/README.html +11 -1
  29. data/doc/RuntimeConfig.html +11 -1
  30. data/doc/String.html +11 -1
  31. data/doc/StringIO.html +11 -1
  32. data/doc/TaskJuggler.html +250 -219
  33. data/doc/TaskJuggler/Account.html +11 -1
  34. data/doc/TaskJuggler/AccountAttribute.html +11 -1
  35. data/doc/TaskJuggler/AccountScenario.html +11 -1
  36. data/doc/TaskJuggler/Allocation.html +11 -1
  37. data/doc/TaskJuggler/AllocationAttribute.html +11 -1
  38. data/doc/TaskJuggler/AttributeBase.html +11 -1
  39. data/doc/TaskJuggler/AttributeDefinition.html +11 -1
  40. data/doc/TaskJuggler/BatchProcessor.html +11 -1
  41. data/doc/TaskJuggler/Booking.html +11 -1
  42. data/doc/TaskJuggler/BookingListAttribute.html +11 -1
  43. data/doc/TaskJuggler/BooleanAttribute.html +11 -1
  44. data/doc/TaskJuggler/CSVFile.html +12 -2
  45. data/doc/TaskJuggler/CellSettingPattern.html +11 -1
  46. data/doc/TaskJuggler/CellSettingPatternList.html +11 -1
  47. data/doc/TaskJuggler/Charge.html +11 -1
  48. data/doc/TaskJuggler/ChargeListAttribute.html +11 -1
  49. data/doc/TaskJuggler/ChargeSet.html +11 -1
  50. data/doc/TaskJuggler/ChargeSetListAttribute.html +11 -1
  51. data/doc/TaskJuggler/CollisionDetector.html +1063 -0
  52. data/doc/TaskJuggler/ColumnListAttribute.html +11 -1
  53. data/doc/TaskJuggler/ColumnTable.html +11 -1
  54. data/doc/TaskJuggler/Daemon.html +11 -1
  55. data/doc/TaskJuggler/{OnShiftCache.html → DataCache.html} +127 -139
  56. data/doc/TaskJuggler/DataCacheEntry.html +711 -0
  57. data/doc/TaskJuggler/DateAttribute.html +11 -1
  58. data/doc/TaskJuggler/DefinitionListAttribute.html +11 -1
  59. data/doc/TaskJuggler/DependencyListAttribute.html +11 -1
  60. data/doc/TaskJuggler/DurationAttribute.html +16 -5
  61. data/doc/TaskJuggler/FileList.html +11 -1
  62. data/doc/TaskJuggler/FileRecord.html +11 -1
  63. data/doc/TaskJuggler/FixnumAttribute.html +19 -9
  64. data/doc/TaskJuggler/FlagListAttribute.html +29 -19
  65. data/doc/TaskJuggler/FloatAttribute.html +23 -13
  66. data/doc/TaskJuggler/FormatListAttribute.html +19 -9
  67. data/doc/TaskJuggler/GanttChart.html +94 -133
  68. data/doc/TaskJuggler/GanttContainer.html +11 -1
  69. data/doc/TaskJuggler/GanttHeader.html +11 -1
  70. data/doc/TaskJuggler/GanttHeaderScaleItem.html +11 -1
  71. data/doc/TaskJuggler/GanttLine.html +11 -1
  72. data/doc/TaskJuggler/GanttLoadStack.html +11 -1
  73. data/doc/TaskJuggler/GanttMilestone.html +11 -1
  74. data/doc/TaskJuggler/GanttRouter.html +247 -596
  75. data/doc/TaskJuggler/GanttTaskBar.html +11 -1
  76. data/doc/TaskJuggler/HTMLDocument.html +11 -1
  77. data/doc/TaskJuggler/HTMLGraphics.html +11 -1
  78. data/doc/TaskJuggler/Interval.html +11 -1
  79. data/doc/TaskJuggler/IntervalListAttribute.html +33 -23
  80. data/doc/TaskJuggler/JobInfo.html +11 -1
  81. data/doc/TaskJuggler/Journal.html +11 -1
  82. data/doc/TaskJuggler/JournalEntry.html +11 -1
  83. data/doc/TaskJuggler/JournalEntryList.html +11 -1
  84. data/doc/TaskJuggler/KeywordArray.html +11 -1
  85. data/doc/TaskJuggler/KeywordDocumentation.html +16 -6
  86. data/doc/TaskJuggler/Limits.html +11 -1
  87. data/doc/TaskJuggler/Limits/Limit.html +11 -1
  88. data/doc/TaskJuggler/LimitsAttribute.html +24 -14
  89. data/doc/TaskJuggler/ListAttributeBase.html +11 -1
  90. data/doc/TaskJuggler/Log.html +11 -1
  91. data/doc/TaskJuggler/LogFile.html +11 -1
  92. data/doc/TaskJuggler/LogicalAttribute.html +11 -1
  93. data/doc/TaskJuggler/LogicalExpression.html +11 -1
  94. data/doc/TaskJuggler/LogicalExpressionAttribute.html +19 -9
  95. data/doc/TaskJuggler/LogicalFlag.html +11 -1
  96. data/doc/TaskJuggler/LogicalFunction.html +11 -1
  97. data/doc/TaskJuggler/LogicalOperation.html +11 -1
  98. data/doc/TaskJuggler/Macro.html +11 -1
  99. data/doc/TaskJuggler/MacroTable.html +11 -1
  100. data/doc/TaskJuggler/ManagerResponsibilities.html +11 -1
  101. data/doc/TaskJuggler/ManagerStatusRecord.html +11 -1
  102. data/doc/TaskJuggler/Message.html +11 -1
  103. data/doc/TaskJuggler/MessageHandler.html +11 -1
  104. data/doc/TaskJuggler/Navigator.html +12 -2
  105. data/doc/TaskJuggler/NavigatorElement.html +11 -1
  106. data/doc/TaskJuggler/NikuProject.html +11 -1
  107. data/doc/TaskJuggler/NikuReport.html +11 -1
  108. data/doc/TaskJuggler/NikuResource.html +11 -1
  109. data/doc/TaskJuggler/NodeListAttribute.html +17 -7
  110. data/doc/TaskJuggler/PlaceHolderCell.html +722 -0
  111. data/doc/TaskJuggler/ProcessIntercom.html +11 -1
  112. data/doc/TaskJuggler/ProcessIntercomIface.html +11 -1
  113. data/doc/TaskJuggler/Project.html +587 -500
  114. data/doc/TaskJuggler/ProjectBroker.html +11 -1
  115. data/doc/TaskJuggler/ProjectBrokerIface.html +11 -1
  116. data/doc/TaskJuggler/ProjectFileParser.html +205 -192
  117. data/doc/TaskJuggler/ProjectFileScanner.html +230 -207
  118. data/doc/TaskJuggler/ProjectRecord.html +11 -1
  119. data/doc/TaskJuggler/ProjectServer.html +11 -1
  120. data/doc/TaskJuggler/ProjectServerIface.html +11 -1
  121. data/doc/TaskJuggler/PropertyAttribute.html +19 -9
  122. data/doc/TaskJuggler/PropertyList.html +95 -83
  123. data/doc/TaskJuggler/PropertySet.html +11 -1
  124. data/doc/TaskJuggler/PropertyTreeNode.html +11 -1
  125. data/doc/TaskJuggler/Query.html +234 -232
  126. data/doc/TaskJuggler/RTFHandlers.html +11 -1
  127. data/doc/TaskJuggler/RTFNavigator.html +11 -1
  128. data/doc/TaskJuggler/RTFQuery.html +11 -1
  129. data/doc/TaskJuggler/RTFReport.html +11 -1
  130. data/doc/TaskJuggler/RTFReportLink.html +11 -1
  131. data/doc/TaskJuggler/RTFWithQuerySupport.html +11 -1
  132. data/doc/TaskJuggler/RealFormat.html +12 -2
  133. data/doc/TaskJuggler/RealFormatAttribute.html +15 -5
  134. data/doc/TaskJuggler/ReferenceAttribute.html +38 -28
  135. data/doc/TaskJuggler/Report.html +96 -113
  136. data/doc/TaskJuggler/ReportBase.html +161 -152
  137. data/doc/TaskJuggler/ReportContext.html +11 -1
  138. data/doc/TaskJuggler/ReportServer.html +59 -48
  139. data/doc/TaskJuggler/ReportServerIface.html +51 -41
  140. data/doc/TaskJuggler/ReportServerRecord.html +11 -1
  141. data/doc/TaskJuggler/ReportServlet.html +11 -1
  142. data/doc/TaskJuggler/ReportTable.html +46 -25
  143. data/doc/TaskJuggler/ReportTableCell.html +296 -275
  144. data/doc/TaskJuggler/ReportTableColumn.html +14 -4
  145. data/doc/TaskJuggler/ReportTableLegend.html +11 -1
  146. data/doc/TaskJuggler/ReportTableLine.html +19 -7
  147. data/doc/TaskJuggler/Resource.html +12 -2
  148. data/doc/TaskJuggler/ResourceListAttribute.html +40 -30
  149. data/doc/TaskJuggler/ResourceListRE.html +11 -1
  150. data/doc/TaskJuggler/ResourceScenario.html +708 -565
  151. data/doc/TaskJuggler/RichText.html +54 -36
  152. data/doc/TaskJuggler/RichTextAttribute.html +31 -21
  153. data/doc/TaskJuggler/RichTextDocument.html +11 -1
  154. data/doc/TaskJuggler/RichTextElement.html +11 -1
  155. data/doc/TaskJuggler/RichTextFunctionExample.html +11 -1
  156. data/doc/TaskJuggler/RichTextFunctionHandler.html +11 -1
  157. data/doc/TaskJuggler/RichTextImage.html +11 -1
  158. data/doc/TaskJuggler/RichTextIntermediate.html +81 -71
  159. data/doc/TaskJuggler/RichTextParser.html +88 -33
  160. data/doc/TaskJuggler/RichTextScanner.html +45 -35
  161. data/doc/TaskJuggler/RichTextSnip.html +11 -1
  162. data/doc/TaskJuggler/RichTextSyntaxRules.html +436 -389
  163. data/doc/TaskJuggler/Scenario.html +11 -1
  164. data/doc/TaskJuggler/ScenarioData.html +11 -1
  165. data/doc/TaskJuggler/ScenarioListAttribute.html +23 -13
  166. data/doc/TaskJuggler/Scoreboard.html +92 -73
  167. data/doc/TaskJuggler/SheetHandlerBase.html +11 -1
  168. data/doc/TaskJuggler/SheetReceiver.html +11 -1
  169. data/doc/TaskJuggler/SheetSender.html +11 -1
  170. data/doc/TaskJuggler/Shift.html +11 -1
  171. data/doc/TaskJuggler/ShiftAssignment.html +11 -1
  172. data/doc/TaskJuggler/ShiftAssignments.html +11 -1
  173. data/doc/TaskJuggler/ShiftAssignmentsAttribute.html +24 -14
  174. data/doc/TaskJuggler/ShiftScenario.html +11 -1
  175. data/doc/TaskJuggler/SimpleQueryExpander.html +11 -1
  176. data/doc/TaskJuggler/SortListAttribute.html +21 -11
  177. data/doc/TaskJuggler/SourceFileInfo.html +11 -1
  178. data/doc/TaskJuggler/StatusSheetReceiver.html +11 -1
  179. data/doc/TaskJuggler/StatusSheetReport.html +11 -1
  180. data/doc/TaskJuggler/StatusSheetSender.html +112 -11
  181. data/doc/TaskJuggler/StringAttribute.html +23 -13
  182. data/doc/TaskJuggler/SymbolAttribute.html +19 -9
  183. data/doc/TaskJuggler/SyntaxReference.html +80 -71
  184. data/doc/TaskJuggler/TOCEntry.html +11 -1
  185. data/doc/TaskJuggler/TSResourceRecord.html +11 -1
  186. data/doc/TaskJuggler/TSTaskRecord.html +11 -1
  187. data/doc/TaskJuggler/TableColumnDefinition.html +11 -1
  188. data/doc/TaskJuggler/TableOfContents.html +11 -1
  189. data/doc/TaskJuggler/TableReport.html +422 -411
  190. data/doc/TaskJuggler/Task.html +11 -1
  191. data/doc/TaskJuggler/TaskDependency.html +11 -1
  192. data/doc/TaskJuggler/TaskListAttribute.html +33 -23
  193. data/doc/TaskJuggler/TaskListRE.html +11 -1
  194. data/doc/TaskJuggler/TaskScenario.html +2007 -1919
  195. data/doc/TaskJuggler/TextFormatter.html +11 -1
  196. data/doc/TaskJuggler/TextParser.html +421 -612
  197. data/doc/TaskJuggler/TextParser/Pattern.html +410 -211
  198. data/doc/TaskJuggler/TextParser/Rule.html +224 -152
  199. data/doc/TaskJuggler/TextParser/StackElement.html +190 -28
  200. data/doc/TaskJuggler/TextParser/State.html +989 -0
  201. data/doc/TaskJuggler/TextParser/StateTransition.html +782 -0
  202. data/doc/TaskJuggler/TextParser/TextParserResultArray.html +25 -14
  203. data/doc/TaskJuggler/TextParser/TokenDoc.html +11 -1
  204. data/doc/TaskJuggler/TextReport.html +11 -1
  205. data/doc/TaskJuggler/TextScanner.html +285 -273
  206. data/doc/TaskJuggler/TextScanner/BufferStreamHandle.html +17 -7
  207. data/doc/TaskJuggler/TextScanner/FileStreamHandle.html +24 -14
  208. data/doc/TaskJuggler/TextScanner/MacroStackEntry.html +11 -1
  209. data/doc/TaskJuggler/TextScanner/StreamHandle.html +64 -52
  210. data/doc/TaskJuggler/TimeSheet.html +11 -1
  211. data/doc/TaskJuggler/TimeSheetReceiver.html +11 -1
  212. data/doc/TaskJuggler/TimeSheetRecord.html +11 -1
  213. data/doc/TaskJuggler/TimeSheetReport.html +11 -1
  214. data/doc/TaskJuggler/TimeSheetSender.html +11 -1
  215. data/doc/TaskJuggler/TimeSheetSummary.html +11 -1
  216. data/doc/TaskJuggler/TimeSheets.html +11 -1
  217. data/doc/TaskJuggler/Tj3AppBase.html +11 -1
  218. data/doc/TaskJuggler/Tj3Client.html +11 -1
  219. data/doc/TaskJuggler/Tj3Daemon.html +11 -1
  220. data/doc/TaskJuggler/Tj3SheetAppBase.html +11 -1
  221. data/doc/TaskJuggler/Tj3SsReceiver.html +11 -1
  222. data/doc/TaskJuggler/Tj3SsSender.html +11 -1
  223. data/doc/TaskJuggler/Tj3TsReceiver.html +11 -1
  224. data/doc/TaskJuggler/Tj3TsSender.html +11 -1
  225. data/doc/TaskJuggler/Tj3TsSummary.html +11 -1
  226. data/doc/TaskJuggler/TjException.html +11 -1
  227. data/doc/TaskJuggler/TjTime.html +474 -324
  228. data/doc/TaskJuggler/TjpExample.html +11 -1
  229. data/doc/TaskJuggler/TjpExportRE.html +11 -1
  230. data/doc/TaskJuggler/TjpSyntaxRules.html +3731 -3662
  231. data/doc/TaskJuggler/URLParameter.html +11 -1
  232. data/doc/TaskJuggler/UserManual.html +11 -1
  233. data/doc/TaskJuggler/VimSyntax.html +11 -1
  234. data/doc/TaskJuggler/WebServer.html +11 -1
  235. data/doc/TaskJuggler/WorkingHours.html +295 -221
  236. data/doc/TaskJuggler/WorkingHoursAttribute.html +11 -1
  237. data/doc/TaskJuggler/XMLBlob.html +11 -1
  238. data/doc/TaskJuggler/XMLComment.html +11 -1
  239. data/doc/TaskJuggler/XMLDocument.html +11 -1
  240. data/doc/TaskJuggler/XMLElement.html +11 -1
  241. data/doc/TaskJuggler/XMLNamedText.html +11 -1
  242. data/doc/TaskJuggler/XMLText.html +11 -1
  243. data/doc/index.html +694 -624
  244. data/doc/lib/AppConfig_rb.html +1 -1
  245. data/doc/lib/Attributes_rb.html +1 -1
  246. data/doc/lib/Booking_rb.html +1 -1
  247. data/doc/lib/DataCache_rb.html +69 -0
  248. data/doc/lib/KeywordDocumentation_rb.html +1 -1
  249. data/doc/lib/ProjectFileParser_rb.html +1 -1
  250. data/doc/lib/ProjectFileScanner_rb.html +1 -1
  251. data/doc/lib/Project_rb.html +1 -1
  252. data/doc/lib/PropertyList_rb.html +1 -1
  253. data/doc/lib/Query_rb.html +1 -1
  254. data/doc/lib/RealFormat_rb.html +1 -1
  255. data/doc/lib/ResourceScenario_rb.html +1 -1
  256. data/doc/lib/Resource_rb.html +1 -1
  257. data/doc/lib/RichTextParser_rb.html +1 -1
  258. data/doc/lib/RichTextScanner_rb.html +1 -1
  259. data/doc/lib/RichTextSyntaxRules_rb.html +1 -1
  260. data/doc/lib/RichText_rb.html +1 -1
  261. data/doc/lib/Scoreboard_rb.html +1 -1
  262. data/doc/lib/StatusSheetSender_rb.html +1 -1
  263. data/doc/lib/SyntaxReference_rb.html +1 -1
  264. data/doc/lib/TaskJuggler_rb.html +1 -1
  265. data/doc/lib/TaskScenario_rb.html +3 -1
  266. data/doc/lib/TextParser/Pattern_rb.html +3 -1
  267. data/doc/lib/TextParser/Rule_rb.html +3 -1
  268. data/doc/lib/TextParser/StackElement_rb.html +3 -1
  269. data/doc/lib/TextParser/State_rb.html +65 -0
  270. data/doc/lib/TextParser_rb.html +1 -1
  271. data/doc/lib/TextScanner_rb.html +1 -1
  272. data/doc/lib/Tj3Config_rb.html +1 -1
  273. data/doc/lib/TjTime_rb.html +1 -1
  274. data/doc/lib/TjpSyntaxRules_rb.html +1 -1
  275. data/doc/lib/WorkingHours_rb.html +3 -1
  276. data/doc/lib/daemon/ReportServer_rb.html +1 -1
  277. data/doc/lib/reports/CSVFile_rb.html +1 -1
  278. data/doc/lib/reports/CollisionDetector_rb.html +67 -0
  279. data/doc/lib/reports/GanttChart_rb.html +1 -1
  280. data/doc/lib/reports/GanttRouter_rb.html +3 -1
  281. data/doc/lib/reports/Navigator_rb.html +1 -1
  282. data/doc/lib/reports/ReportBase_rb.html +1 -1
  283. data/doc/lib/reports/ReportTableCell_rb.html +1 -1
  284. data/doc/lib/reports/ReportTableColumn_rb.html +1 -1
  285. data/doc/lib/reports/ReportTableLine_rb.html +1 -1
  286. data/doc/lib/reports/ReportTable_rb.html +1 -1
  287. data/doc/lib/reports/Report_rb.html +1 -1
  288. data/doc/lib/reports/TableReport_rb.html +1 -1
  289. data/doc/lib/taskjuggler3_rb.html +1 -1
  290. data/examples/tutorial.tjp +1 -2
  291. data/lib/AppConfig.rb +10 -4
  292. data/lib/Attributes.rb +4 -4
  293. data/lib/DataCache.rb +124 -0
  294. data/lib/KeywordDocumentation.rb +5 -5
  295. data/lib/Project.rb +54 -10
  296. data/lib/ProjectFileParser.rb +10 -9
  297. data/lib/ProjectFileScanner.rb +38 -25
  298. data/lib/PropertyList.rb +6 -4
  299. data/lib/Query.rb +0 -8
  300. data/lib/RealFormat.rb +1 -1
  301. data/lib/Resource.rb +1 -1
  302. data/lib/ResourceScenario.rb +96 -31
  303. data/lib/RichText.rb +17 -5
  304. data/lib/RichTextParser.rb +22 -9
  305. data/lib/RichTextScanner.rb +34 -34
  306. data/lib/RichTextSyntaxRules.rb +41 -36
  307. data/lib/Scoreboard.rb +16 -7
  308. data/lib/StatusSheetSender.rb +63 -0
  309. data/lib/SyntaxReference.rb +9 -10
  310. data/lib/TaskJuggler.rb +28 -4
  311. data/lib/TaskScenario.rb +66 -19
  312. data/lib/TextParser.rb +219 -384
  313. data/lib/TextParser/Pattern.rb +168 -49
  314. data/lib/TextParser/Rule.rb +33 -17
  315. data/lib/TextParser/StackElement.rb +42 -2
  316. data/lib/TextParser/State.rb +175 -0
  317. data/lib/TextScanner.rb +19 -15
  318. data/lib/Tj3Config.rb +1 -1
  319. data/lib/TjTime.rb +111 -3
  320. data/lib/TjpSyntaxRules.rb +122 -66
  321. data/lib/WorkingHours.rb +91 -186
  322. data/lib/daemon/ReportServer.rb +3 -2
  323. data/lib/reports/CSVFile.rb +1 -1
  324. data/lib/reports/CollisionDetector.rb +177 -0
  325. data/lib/reports/GanttChart.rb +25 -41
  326. data/lib/reports/GanttRouter.rb +104 -233
  327. data/lib/reports/Navigator.rb +1 -1
  328. data/lib/reports/Report.rb +9 -33
  329. data/lib/reports/ReportBase.rb +0 -1
  330. data/lib/reports/ReportTable.rb +19 -8
  331. data/lib/reports/ReportTableCell.rb +61 -25
  332. data/lib/reports/ReportTableColumn.rb +2 -2
  333. data/lib/reports/ReportTableLine.rb +4 -2
  334. data/lib/reports/TableReport.rb +1 -0
  335. data/lib/taskjuggler3.rb +0 -1
  336. data/manual/Installation +7 -3
  337. data/manual/Intro +12 -10
  338. data/manual/The_TaskJuggler_Syntax +4 -4
  339. data/test/TestSuite/CSV-Reports/celltext-Reference.csv +14 -14
  340. data/test/TestSuite/CSV-Reports/genrefs +1 -1
  341. data/test/TestSuite/CSV-Reports/resourcereport-Reference.csv +4 -4
  342. data/test/TestSuite/CSV-Reports/resourcereport_with_tasks-Reference.csv +22 -22
  343. data/test/TestSuite/CSV-Reports/sortByTree-Reference.csv +14 -14
  344. data/test/TestSuite/CSV-Reports/sortBy_duration.down-Reference.csv +14 -14
  345. data/test/TestSuite/CSV-Reports/sortBy_effort.up-Reference.csv +14 -14
  346. data/test/TestSuite/CSV-Reports/sortBy_plan.start.down-Reference.csv +14 -14
  347. data/test/TestSuite/CSV-Reports/taskreport-Reference.csv +14 -14
  348. data/test/TestSuite/CSV-Reports/taskreport_with_resources-Reference.csv +32 -24
  349. data/test/TestSuite/CSV-Reports/weekly-Reference.csv +13 -0
  350. data/test/TestSuite/CSV-Reports/weekly.tjp +9 -0
  351. data/test/TestSuite/HTML-Reports/css/tjreport.css +7 -2
  352. data/test/TestSuite/HTML-Reports/depArrows.html +839 -830
  353. data/test/TestSuite/HTML-Reports/depArrows.tjp +12 -12
  354. data/test/TestSuite/HTML-Reports/profile.html +37581 -0
  355. data/test/TestSuite/ReportGenerator/Errors/no_report_defined.tjp +7 -0
  356. data/test/TestSuite/ReportGenerator/Errors/rtp_report_recursion.tjp +1 -1
  357. data/test/TestSuite/StatusSheets/TimeSheets/2002-03-01/missing-reports +2 -0
  358. data/test/TestSuite/StatusSheets/run +2 -0
  359. data/test/TestSuite/Syntax/Correct/Booking.tjp +13 -5
  360. data/test/TestSuite/Syntax/Correct/ResourceRoot.tjp +21 -0
  361. data/test/TestSuite/Syntax/Correct/RollupResource.tjp +21 -0
  362. data/test/TestSuite/Syntax/Correct/TaskRoot.tjp +1 -1
  363. data/test/TestSuite/Syntax/Errors/empty.tjp +1 -1
  364. data/test/TestSuite/Syntax/Errors/include_before_project.tjp +2 -0
  365. data/test/TestSuite/Syntax/Errors/no_reduce.tjp +6 -0
  366. data/test/TestSuite/Syntax/Errors/unsupported_token.tjp +1 -1
  367. data/test/TestSuite/TimeSheets/run +1 -1
  368. data/test/test_CSV-Reports.rb +2 -4
  369. data/test/test_CollisionDetector.rb +85 -0
  370. data/test/test_Project.rb +2 -2
  371. data/test/test_ProjectFileScanner.rb +73 -31
  372. data/test/test_Query.rb +2 -2
  373. data/test/test_ReportGenerator.rb +1 -1
  374. data/test/test_RichText.rb +4 -4
  375. data/test/test_WorkingHours.rb +150 -11
  376. metadata +75 -67
  377. data/test/TestSuite/ReportGenerator/Errors/css/tjreport.css +0 -407
  378. data/test/TestSuite/ReportGenerator/Errors/rtp_report_recursion.html +0 -26
  379. data/test/TestSuite/Scheduler/Correct/Allocate.html +0 -3210
  380. data/test/TestSuite/Scheduler/Correct/Container.html +0 -349
  381. data/test/TestSuite/Scheduler/Correct/Limits.html +0 -4964
  382. data/test/TestSuite/Scheduler/Correct/Shift.html +0 -1719
  383. data/test/TestSuite/Scheduler/Correct/Shift2.html +0 -476
  384. data/test/TestSuite/Scheduler/Correct/css/tjmanual.css +0 -66
  385. data/test/TestSuite/Scheduler/Correct/icons/details.png +0 -0
  386. data/test/TestSuite/Scheduler/Correct/icons/flag-green.png +0 -0
  387. data/test/TestSuite/Scheduler/Correct/icons/flag-red.png +0 -0
  388. data/test/TestSuite/Scheduler/Correct/icons/flag-yellow.png +0 -0
  389. data/test/TestSuite/Scheduler/Correct/icons/resource.png +0 -0
  390. data/test/TestSuite/Scheduler/Correct/icons/resourcegroup.png +0 -0
  391. data/test/TestSuite/Scheduler/Correct/icons/task.png +0 -0
  392. data/test/TestSuite/Scheduler/Correct/icons/taskgroup.png +0 -0
  393. data/test/TestSuite/Scheduler/Correct/icons/trend-down.png +0 -0
  394. data/test/TestSuite/Scheduler/Correct/icons/trend-flat.png +0 -0
  395. data/test/TestSuite/Scheduler/Correct/icons/trend-up.png +0 -0
  396. data/test/TestSuite/Scheduler/Correct/scripts/wz_tooltip.js +0 -1301
  397. data/test/TestSuite/Scheduler/Errors/css/tjmanual.css +0 -66
  398. data/test/TestSuite/Scheduler/Errors/css/tjreport.css +0 -407
  399. data/test/TestSuite/Scheduler/Errors/icons/details.png +0 -0
  400. data/test/TestSuite/Scheduler/Errors/icons/flag-green.png +0 -0
  401. data/test/TestSuite/Scheduler/Errors/icons/flag-red.png +0 -0
  402. data/test/TestSuite/Scheduler/Errors/icons/flag-yellow.png +0 -0
  403. data/test/TestSuite/Scheduler/Errors/icons/resource.png +0 -0
  404. data/test/TestSuite/Scheduler/Errors/icons/resourcegroup.png +0 -0
  405. data/test/TestSuite/Scheduler/Errors/icons/task.png +0 -0
  406. data/test/TestSuite/Scheduler/Errors/icons/taskgroup.png +0 -0
  407. data/test/TestSuite/Scheduler/Errors/icons/trend-down.png +0 -0
  408. data/test/TestSuite/Scheduler/Errors/icons/trend-flat.png +0 -0
  409. data/test/TestSuite/Scheduler/Errors/icons/trend-up.png +0 -0
  410. data/test/TestSuite/Scheduler/Errors/scripts/wz_tooltip.js +0 -1301
  411. data/test/TestSuite/StatusSheets/resrep.tji +0 -7
  412. data/test/TestSuite/StatusSheets/tj3d.log +0 -312
  413. data/test/TestSuite/Syntax/Correct/Managers.html +0 -263
  414. data/test/TestSuite/TimeSheets/acceptable_intervals +0 -1
  415. data/test/TestSuite/TimeSheets/statussheets.log +0 -1
data/lib/WorkingHours.rb CHANGED
@@ -11,140 +11,31 @@
11
11
  #
12
12
 
13
13
  require 'Interval'
14
+ require 'Scoreboard'
14
15
 
15
16
  class TaskJuggler
16
17
 
17
- # This cache class is used to speedup accesses to the frequently used
18
- # WorkingHours::onShift? function. It saves the result the first time the
19
- # function is called for a particular date and working hour set and returns
20
- # it on subsequent calls again. Each partucular set of working hours needs
21
- # its separate cache. The OnShiftCache object is shared amongst all
22
- # WorkingHours objects so that WorkingHours objects with identical working
23
- # hours can share the cache.
24
- class OnShiftCache
25
-
26
- # Create the OnShiftCache object. There should be only one for the
27
- # application.
28
- def initialize
29
- @caches = []
30
- @workingHoursTable = []
31
- # The cache is an array with entries for each date. To minimize the
32
- # necessary storage space, we need to guess the smallest used date
33
- # (which gets index 0 then) and the smallest distance between dates.
34
- @minDate = nil
35
- # We assume a timing resolution of 1 hour (the TaskJuggler default)
36
- # first.
37
- @minDateDelta = 60 * 60
38
- end
39
-
40
- # Register the WorkingHours object with the caches. The function will
41
- # return the actual cache used for this particular set of working hours.
42
- # The WorkingHours object may not change its working hours after this
43
- # call. The returned cache reference is used as a handle for subsequent
44
- # OnShiftCache::set and OnShiftCache::get calls.
45
- def register(wh)
46
- # Search the list of already registered caches for an identical set of
47
- # WorkingHours. In case one is found, return the reference to this
48
- # cache.
49
- @workingHoursTable.length.times do |i|
50
- if @workingHoursTable[i] == wh
51
- return @caches[i]
52
- end
53
- end
54
- # If this is a new set of WorkingHours we create a new cache for it.
55
- @workingHoursTable << WorkingHours.new(wh)
56
- @caches << []
57
- @caches.last
58
- end
59
-
60
- # Set the +value+ for a given +cache+ and +date+.
61
- def set(cache, date, value)
62
- cache[dateToIndex(date)] = value
63
- end
64
-
65
- # Get the value for a given +cache+ and +date+.
66
- def get(cache, date)
67
- cache[dateToIndex(date)]
68
- end
69
-
70
- private
71
-
72
- # When the @minDate or @minDateDelta values need to be changed, we have to
73
- # clear all the caches again.
74
- def resetCaches
75
- @caches.each { |c| c.clear }
76
- end
77
-
78
- # Convert a TjTime +date+ to an index in the cache Array. To optimize the
79
- # size of the cache, we have to guess the smallest used date and the
80
- # regular distance between the date values. If we have to correct these
81
- # guessed values, we have to clear the caches.
82
- def dateToIndex(date)
83
- if @minDate.nil? || date < @minDate
84
- @minDate = date
85
- resetCaches
86
- end
87
- startDate = date - @minDate
88
- div, mod = startDate.divmod(@minDateDelta)
89
- if mod != 0
90
- resetCaches
91
- # We have to guess the timingresolution of the project here. Possible
92
- # values are 5, 10, 15, 20, 30 or 60 minutes.
93
- case @minDateDelta / 60
94
- when 60
95
- @minDateDelta = 30
96
- when 30
97
- @minDateDelta = 20
98
- when 20
99
- @minDateDelta = 15
100
- when 15
101
- @minDateDelta = 10
102
- when 10
103
- @minDateDelta = 5
104
- else
105
- raise "Illegal timing resolution!"
106
- end
107
- @minDateDelta *= 60
108
- div = startDate / @minDateDelta
109
- end
110
-
111
- div
112
- end
113
-
114
- end
115
-
116
18
  # Class to store the working hours for each day of the week. The working hours
117
19
  # are stored as Arrays of Fixnum intervals for each day of the week. A day off
118
20
  # is modelled as empty Array for that week day. The start end end times of
119
21
  # each working period are stored as seconds after midnight.
120
22
  class WorkingHours
121
23
 
122
- attr_reader :days
123
- attr_accessor :timezone
124
-
125
- # All WorkingHours objects share the same cache to speedup the onShift?
126
- # method.
127
- @@onShiftCache = OnShiftCache.new
24
+ attr_reader :days, :startDate, :endDate, :slotDuration, :timezone,
25
+ :scoreboard
128
26
 
129
27
  # Create a new WorkingHours object. The method accepts a reference to an
130
28
  # existing WorkingHours object in +wh+. When it's present, the new object
131
- # will be a deep copy of the given object.
132
- def initialize(wh = nil)
29
+ # will be a deep copy of the given object. The Scoreboard object is _not_
30
+ # deep copied. It will be copied on write.
31
+ def initialize(arg1 = nil, startDate = nil, endDate = nil)
133
32
  # One entry for every day of the week. Sunday === 0.
134
33
  @days = Array.new(7, [])
135
- @cache = nil
34
+ @scoreboard = nil
136
35
 
137
- if wh.nil?
138
- # Create a new object with default working hours.
139
- @timezone = nil
140
- # Set the default working hours. Monday to Friday 9am - 12pm, 1pm - 6pm.
141
- # Saturday and Sunday are days off.
142
- 1.upto(5) do |day|
143
- @days[day] = [ [ 9 * 60 * 60, 12 * 60 * 60 ],
144
- [ 13 * 60 * 60, 18 * 60 * 60 ] ]
145
- end
146
- else
147
- # Copy the values from the given object.
36
+ if arg1.is_a?(WorkingHours)
37
+ # Create a copy of the passed WorkingHours object.
38
+ wh = arg1
148
39
  @timezone = wh.timezone
149
40
  7.times do |day|
150
41
  hours = []
@@ -153,13 +44,37 @@ class TaskJuggler
153
44
  end
154
45
  setWorkingHours(day, hours)
155
46
  end
47
+ @startDate = wh.startDate
48
+ @endDate = wh.endDate
49
+ @slotDuration = wh.slotDuration
50
+ @scoreboard = wh.scoreboard
51
+ else
52
+ slotDuration = arg1
53
+ if arg1.nil? || startDate.nil? || endDate.nil?
54
+ raise "You must supply values for slotDuration, start and end dates"
55
+ end
56
+ @startDate = startDate
57
+ @endDate = endDate
58
+ @slotDuration = slotDuration
59
+
60
+ # Create a new object with default working hours.
61
+ @timezone = nil
62
+ # Set the default working hours. Monday to Friday 9am - 12pm, 1pm - 6pm.
63
+ # Saturday and Sunday are days off.
64
+ 1.upto(5) do |day|
65
+ @days[day] = [ [ 9 * 60 * 60, 12 * 60 * 60 ],
66
+ [ 13 * 60 * 60, 18 * 60 * 60 ] ]
67
+ end
156
68
  end
157
69
  end
158
70
 
159
71
  # Return true of the given WorkingHours object +wh+ is identical to this
160
72
  # object.
161
73
  def ==(wh)
162
- return false if wh.nil? || @timezone != wh.timezone
74
+ return false if wh.nil? || @timezone != wh.timezone ||
75
+ @startDate != wh.startDate ||
76
+ @endDate != wh.endDate ||
77
+ @slotDuration != wh.slotDuration
163
78
 
164
79
  7.times do |d|
165
80
  return false if @days[d].length != wh.days[d].length
@@ -178,10 +93,8 @@ class TaskJuggler
178
93
  # specifies the time of day as minutes after midnight. The first value is
179
94
  # the start time of the interval, the second the end time.
180
95
  def setWorkingHours(dayOfWeek, intervals)
181
- if @cache
182
- raise 'You cannot change the working hours after onShift? has been ' +
183
- 'called.'
184
- end
96
+ # Changing the working hours requires the score board to be regenerated.
97
+ @scoreboard = nil
185
98
 
186
99
  # Legal values range from 0 Sunday to 6 Saturday.
187
100
  if dayOfWeek < 0 || dayOfWeek > 6
@@ -199,6 +112,13 @@ class TaskJuggler
199
112
  @days[dayOfWeek] = intervals
200
113
  end
201
114
 
115
+ # Set the time zone _zone_ for the working hours. This will reset the
116
+ # @scoreboard.
117
+ def timezone=(zone)
118
+ @scoreboard = nil
119
+ @timezone = zone
120
+ end
121
+
202
122
  # Return the working hour intervals for a given day of the week.
203
123
  # +dayOfWeek+ must 0 for Sunday, 1 for Monday and so on. The result is an
204
124
  # Array that contains Arrays of 2 Fixnums.
@@ -208,64 +128,24 @@ class TaskJuggler
208
128
 
209
129
  # Return true if _date_ is within the defined working hours.
210
130
  def onShift?(date)
211
- @cache = @@onShiftCache.register(self) unless @cache
212
-
213
- # If we have the result cached already, return it.
214
- unless (os = @@onShiftCache.get(@cache, date)).nil?
215
- return os
216
- end
217
-
218
- # The date is in UTC. The weekday needs to be calculated according to the
219
- # timezone of the project.
220
- projectDate = toLocaltime(date)
221
- dow = projectDate.wday
222
-
223
- # The working hours need to be put into the proper time zone.
224
- localDate = toLocaltime(date, @timezone)
225
- secondsOfDay = localDate.secondsOfDay
226
-
227
- @days[dow].each do |iv|
228
- # Check the working hours of that day if they overlap with +date+.
229
- if iv[0] <= secondsOfDay && secondsOfDay < iv[1]
230
- # Store the result in the cache.
231
- @@onShiftCache.set(@cache, date, true)
232
- return true
233
- end
234
- end
131
+ initScoreboard unless @scoreboard
235
132
 
236
- # Store the result in the cache.
237
- @@onShiftCache.set(@cache, date, false)
238
- false
133
+ @scoreboard.get(date)
239
134
  end
240
135
 
241
- # This function does not belong here! It should be handled via the
242
- # ShiftAssignment.
136
+ # Return true only if all slots in the _interval_ are offhour slots.
243
137
  def timeOff?(interval)
244
- t = interval.start.midnight
245
- while t < interval.end
246
- dow = t.wday
247
- unless @days[dow].empty?
248
- dayStart = t < interval.start ? interval.start.secondsOfDay :
249
- t.secondsOfDay
250
- dayEnd = t.sameTimeNextDay > interval.end ? interval.end.secondsOfDay :
251
- 60 * 60 * 24;
252
- @days[dow].each do |iv|
253
- return false if (dayStart <= iv[0] && iv[0] < dayEnd) ||
254
- (iv[0] <= dayStart && dayStart < iv[1])
255
- end
256
- end
257
- t = t.sameTimeNextDay
138
+ initScoreboard unless @scoreboard
139
+
140
+ startIdx = @scoreboard.dateToIdx(interval.start, true)
141
+ endIdx = @scoreboard.dateToIdx(interval.end, true)
142
+
143
+ startIdx.upto(endIdx - 1) do |i|
144
+ return false if @scoreboard[i]
258
145
  end
259
146
  true
260
147
  end
261
148
 
262
- # Probably should be put into ShiftAssignment as well.
263
- def dayOff?(date)
264
- projectDate = toLocaltime(date)
265
- dow = projectDate.wday
266
- @days[dow].empty?
267
- end
268
-
269
149
  # Returns the time interval settings for each day in a human readable form.
270
150
  def to_s
271
151
  dayNames = %w( Sun Mon Tue Wed Thu Fri Sat )
@@ -295,26 +175,51 @@ class TaskJuggler
295
175
 
296
176
  private
297
177
 
298
- # Convert a UTC date into the corresponding date in the local time zone.
299
- # This is either the current system setting or the time zone specified by
300
- # _tz_.
301
- def toLocaltime(date, tz = nil)
178
+ def initScoreboard
179
+ # The scoreboard is an Array of True/False values. It spans a certain
180
+ # time period with one entry per time slot.
181
+ @scoreboard = Scoreboard.new(@startDate, @endDate, @slotDuration, false)
182
+
302
183
  oldTimezone = nil
303
184
  # Set environment variable TZ to appropriate time zone
304
185
  if @timezone
305
- oldTimezone = ENV['tz']
306
- ENV['tz'] = @timezone
186
+ oldTimezone = ENV['TZ']
187
+ ENV['TZ'] = @timezone
307
188
  end
308
189
 
309
- localDate = date.dup
310
- localDate.localtime
190
+ date = @startDate
191
+ @scoreboard.collect! do |slot|
192
+ localDate = date.dup
193
+ localDate.localtime
194
+
195
+ # The date is in UTC. The weekday needs to be calculated according to
196
+ # the local timezone.
197
+ weekday = localDate.wday
198
+ secondsOfDay = localDate.secondsOfDay
199
+
200
+ result = false
201
+ @days[weekday].each do |iv|
202
+ # Check the working hours of that day if they overlap with +date+.
203
+ if iv[0] <= secondsOfDay && secondsOfDay < iv[1]
204
+ # The time slot is a working slot.
205
+ result = true
206
+ break
207
+ end
208
+ end
209
+ # Calculate date of next scoreboard slot
210
+ date += @slotDuration
311
211
 
312
- # Restore environment
313
- if oldTimezone
314
- ENV['tz'] = oldTimezone
212
+ result
315
213
  end
316
214
 
317
- localDate
215
+ # Restore environment
216
+ if @timezone
217
+ if oldTimezone
218
+ ENV['TZ'] = oldTimezone
219
+ else
220
+ ENV.delete('TZ')
221
+ end
222
+ end
318
223
  end
319
224
 
320
225
  end
@@ -98,7 +98,7 @@ class TaskJuggler
98
98
 
99
99
  def addFile(file)
100
100
  begin
101
- @tj.parseFile(file, 'properties')
101
+ @tj.parseFile(file, :properties)
102
102
  rescue TjException
103
103
  return false
104
104
  end
@@ -108,8 +108,9 @@ class TaskJuggler
108
108
 
109
109
  def generateReport(id, regExpMode, dynamicAttributes)
110
110
  @log.info("Generating report #{id}")
111
+ startTime = Time.now
111
112
  if (ok = @tj.generateReport(id, regExpMode, dynamicAttributes))
112
- @log.debug("Report #{id} generated")
113
+ @log.info("Report #{id} generated in #{Time.now - startTime} seconds")
113
114
  else
114
115
  @log.error("Report generation of #{id} failed")
115
116
  end
@@ -55,7 +55,7 @@ class TaskJuggler
55
55
  file = File.open(fileName, 'r')
56
56
  end
57
57
 
58
- @data = parse(file.read)
58
+ parse(file.read)
59
59
 
60
60
  file.close unless fileName == '.'
61
61
  @data
@@ -0,0 +1,177 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: UTF-8
3
+ #
4
+ # = CollisionDetector.rb -- The TaskJuggler III Project Management Software
5
+ #
6
+ # Copyright (c) 2006, 2007, 2008, 2009, 2010 by Chris Schlaeger <cs@kde.org>
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of version 2 of the GNU General Public License as
10
+ # published by the Free Software Foundation.
11
+ #
12
+
13
+ require 'reports/HTMLGraphics'
14
+
15
+ class TaskJuggler
16
+
17
+ class CollisionDetector
18
+
19
+ include HTMLGraphics
20
+
21
+ def initialize(width, height)
22
+ @width = width
23
+ @height = height
24
+
25
+ # The zones are stored as Arrays of line segments. Horizontal blocks are
26
+ # stored separately from vertical blocks. Blocked segments for a
27
+ # particular x coordinate are stored in @vLines, for y coordinates in
28
+ # @hLines. Each entry is an Array of [ start, end ] values that describe
29
+ # the blocked segments of that particular line. Start and end point are
30
+ # part of the segment. A listed segment will not be overwritten during
31
+ # routing.
32
+ @hLines = Array.new(@height) { |i| i = [] }
33
+ @vLines = Array.new(@width) { |i| i = [] }
34
+ end
35
+
36
+ # This function registers an area as don't-cross-zone. The rectangular zone
37
+ # is described by _x_, _y_, _w_ and _h_. If _horiz_ is true, the zone will
38
+ # be blocked for horizontal lines, if _vert_ is true the zone will be
39
+ # blocked for vertical lines.
40
+ def addBlockedZone(x, y, w, h, horiz, vert)
41
+ # Clip the input rectangle to fit within the handled area of this router.
42
+ x = clip(x.to_i, @width - 1)
43
+ y = clip(y.to_i, @height - 1)
44
+ w = clip(w.to_i, @width - x)
45
+ h = clip(h.to_i, @height - y)
46
+
47
+ # We can ignore empty zones.
48
+ return if w == 0 || h == 0
49
+
50
+ # Break the rectangle into line segments and add them to the appropriate
51
+ # line Arrays.
52
+ if horiz
53
+ y.upto(y + h - 1) do |i|
54
+ addSegment(@hLines[i], [ x, x + w - 1 ])
55
+ end
56
+ end
57
+ if vert
58
+ x.upto(x + w - 1) do |i|
59
+ addSegment(@vLines[i], [ y, y + h - 1 ])
60
+ end
61
+ end
62
+ end
63
+
64
+ # Find out if there is a block at line _pos_ for the start/end coordinates
65
+ # given by _segment_. If _horizontal_ is true, we are looking for a
66
+ # horizontal block, otherwise a vertical.
67
+ def collision?(pos, segment, horizontal)
68
+ line = (horizontal ? @hLines : @vLines)[pos]
69
+
70
+ # For complex charts, the segment lists can be rather long. We use a
71
+ # binary search to be fairly efficient.
72
+ l = 0
73
+ u = line.length - 1
74
+ while l <= u
75
+ # Look at the element in the middle between l and u.
76
+ p = l + ((u - l) / 2).to_i
77
+ return true if overlaps?(line[p], segment)
78
+
79
+ if segment[0] > line[p][1]
80
+ # The potential target is above p. Adjust lower bound.
81
+ l = p + 1
82
+ else
83
+ # The potential target is below p. Adjust upper bound.
84
+ u = p - 1
85
+ end
86
+ end
87
+ false
88
+ end
89
+
90
+ def to_html
91
+ html = []
92
+ # Change this to determine what zones you want to see.
93
+ if true
94
+ # Show vertical blocks
95
+ x = 0
96
+ @vLines.each do |line|
97
+ line.each do |segment|
98
+ html << lineToHTML(x, segment[0], x, segment[1], 'white')
99
+ end
100
+ x += 1
101
+ end
102
+ else
103
+ # Show horizontal blocks
104
+ y = 0
105
+ @hLines.each do |line|
106
+ line.each do |segment|
107
+ html << lineToHTML(segment[0], y, segment[1], y, 'white')
108
+ end
109
+ y += 1
110
+ end
111
+ end
112
+ html
113
+ end
114
+
115
+ private
116
+
117
+ # Simple utility function to limit _v_ between 0 and _max_.
118
+ def clip(v, max)
119
+ v = 0 if v < 0
120
+ v = max if v > max
121
+ v
122
+ end
123
+
124
+ # This function adds a new segment to the line. In case the new segment
125
+ # overlaps with or directly attaches to existing segments, these segments
126
+ # are merged into a single segment.
127
+ def addSegment(line, newSegment)
128
+ # Search for overlaping or directly attaching segments in the list.
129
+ i = 0
130
+ while (i < line.length)
131
+ segment = line[i]
132
+ if mergeable?(newSegment, segment)
133
+ # Merge exiting segment into new one
134
+ merge(newSegment, segment)
135
+ # Remove the old one from the list and restart with the newly created
136
+ # one at the same position.
137
+ line.delete_at(i)
138
+ next
139
+ elsif segment[0] > newSegment[1]
140
+ # Segments are stored in ascending order. If the next segment starts
141
+ # with a larger value, we insert the new segment before the larger
142
+ # one.
143
+ line.insert(i, newSegment)
144
+ return
145
+ end
146
+ i += 1
147
+ end
148
+ # Append new segment
149
+ line << newSegment
150
+ end
151
+
152
+ # Return true if the two segments described by _s1_ and _s2_ overlap each
153
+ # other. A segment is a [ start, end ] Array. The two points are part of the
154
+ # segment.
155
+ def overlaps?(s1, s2)
156
+ (s1[0] <= s2[0] && s2[0] <= s1[1]) ||
157
+ (s2[0] <= s1[0] && s1[0] <= s2[1])
158
+ end
159
+
160
+ # Return true if the two segments described by _s1_ and _s2_ overlap each
161
+ # other or are directly attached to each other.
162
+ def mergeable?(s1, s2)
163
+ overlaps?(s1, s2) ||
164
+ (s1[1] + 1 == s2[0]) ||
165
+ (s2[1] + 1 == s1[0])
166
+ end
167
+
168
+ # Merge the two segments described by _dst_ and _src_ into _dst_.
169
+ def merge(dst, seg)
170
+ dst[0] = seg[0] if seg[0] < dst[0]
171
+ dst[1] = seg[1] if seg[1] > dst[1]
172
+ end
173
+
174
+ end
175
+
176
+ end
177
+