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/Project.rb CHANGED
@@ -78,7 +78,7 @@ class TaskJuggler
78
78
  'flags' => [],
79
79
  'journal' => Journal.new,
80
80
  'limits' => nil,
81
- 'loadUnit' => :shortauto,
81
+ 'loadUnit' => :days,
82
82
  'name' => name,
83
83
  'navigators' => {},
84
84
  'now' => TjTime.now.align(3600),
@@ -97,7 +97,7 @@ class TaskJuggler
97
97
  'vacations' => [],
98
98
  'version' => version || "1.0",
99
99
  'weekStartsMonday' => true,
100
- 'workinghours' => WorkingHours.new,
100
+ 'workinghours' => nil,
101
101
  'yearlyworkingdays' => 260.714
102
102
  }
103
103
 
@@ -430,6 +430,23 @@ class TaskJuggler
430
430
  raise "Unknown project attribute #{name}"
431
431
  end
432
432
  @attributes[name] = value
433
+
434
+ # If the start, end or schedule granularity have been changed, we have
435
+ # to reset the working hours.
436
+ if %w(start end scheduleGranularity timezone timingresolution).
437
+ include?(name)
438
+ if @attributes['start'] && @attributes['end']
439
+ @attributes['workinghours'] =
440
+ WorkingHours.new(@attributes['scheduleGranularity'],
441
+ @attributes['start'], @attributes['end'])
442
+ # WorkingHours is using a copy-on-write scheme to prevent multiple
443
+ # copies of the same Scoreboard. All other WorkingHours objects are
444
+ # created as copies of this object. By calling
445
+ # WorkingHours::onShift? we make sure this instance has got a
446
+ # Scoreboard than gets reused by the other instances.
447
+ @attributes['workinghours'].onShift?(@attributes['start'])
448
+ end
449
+ end
433
450
  end
434
451
 
435
452
  # Return the number of defined scenarios for the project.
@@ -440,7 +457,7 @@ class TaskJuggler
440
457
  # Try to match _levelName_ to a defined alert level name and return the
441
458
  # index of it. If no level is found, nil is returned.
442
459
  def alertLevelIndex(levelName)
443
- 0.upto(@attributes['alertLevels'].length - 1) do |i|
460
+ @attributes['alertLevels'].length.times do |i|
444
461
  if @attributes['alertLevels'][i][0] == levelName
445
462
  return i
446
463
  end
@@ -602,6 +619,24 @@ class TaskJuggler
602
619
  true
603
620
  end
604
621
 
622
+ # Make sure that we have a least one report defined that has an output
623
+ # format.
624
+ def checkReports
625
+ if @reports.empty?
626
+ @messageHandler.warning('no_report_defined',
627
+ "This project has no reports defined. " +
628
+ "No output data will be generated.")
629
+ end
630
+
631
+ @reports.each do |report|
632
+ return unless report.get('formats').empty?
633
+ end
634
+
635
+ @messageHandler.warning('all_formats_empty',
636
+ "None of the reports has a 'formats' attribute. " +
637
+ "No output data will be generated.")
638
+ end
639
+
605
640
  # Call this function to generate the reports based on the scheduling result.
606
641
  # This function may only be called after Project#schedule has been called.
607
642
  def generateReports(maxCpuCores)
@@ -652,6 +687,12 @@ class TaskJuggler
652
687
  error('unknown_report_id',
653
688
  "Request to generate unknown report #{id}")
654
689
  end
690
+ if report.get('formats').empty?
691
+ @messageHandler.error('formats_empty',
692
+ "The report #{report.fullId} has no 'formats' attribute. " +
693
+ "No output data will be generated.")
694
+ end
695
+
655
696
  Log.startProgressMeter("Report #{report.name}")
656
697
  @reportContexts.push(context = ReportContext.new(self, report))
657
698
 
@@ -834,7 +875,7 @@ class TaskJuggler
834
875
 
835
876
  # Print the attribute values. It's used for debugging only.
836
877
  def to_s
837
- raise "STOP!"
878
+ #raise "STOP!"
838
879
  str = ''
839
880
  @attributes.each do |attribute, value|
840
881
  if value
@@ -921,19 +962,22 @@ class TaskJuggler
921
962
 
922
963
  def finishScenario(scIdx)
923
964
  Log.startProgressMeter("Checking scenario #{scenario(scIdx).get('name')}")
924
- total = @tasks.items
925
- i = 0
926
965
  @tasks.each do |task|
927
- task.finishScheduling(scIdx)
928
- i += 1
929
- Log.progress((i.to_f / total) * 0.5)
966
+ # Recursively traverse the top-level tasks to finish all tasks.
967
+ task.finishScheduling(scIdx) unless task.parent
968
+ end
969
+
970
+ @resources.each do |resource|
971
+ # Recursively traverse the top-level resources to finish them all.
972
+ resource.finishScheduling(scIdx) unless resource.parent
930
973
  end
931
974
 
932
975
  i = 0
976
+ total = @tasks.items
933
977
  @tasks.each do |task|
934
978
  task.postScheduleCheck(scIdx) if task.parent.nil?
935
979
  i += 1
936
- Log.progress(0.5 + (i.to_f / total) * 0.5)
980
+ Log.progress(i.to_f / total)
937
981
  end
938
982
 
939
983
  # This should be really fast so we don't log progess.
@@ -39,10 +39,11 @@ class TaskJuggler
39
39
 
40
40
  # Define the token types that the ProjectFileScanner may return for
41
41
  # variable elements.
42
- @variables = %w( INTEGER FLOAT DATE TIME STRING LITERAL ID ID_WITH_COLON
43
- ABSOLUTE_ID MACRO )
42
+ @variables = [ :INTEGER, :FLOAT, :DATE, :TIME, :STRING, :LITERAL,
43
+ :ID, :ID_WITH_COLON, :ABSOLUTE_ID, :MACRO ]
44
44
 
45
45
  initRules
46
+ updateParserTables
46
47
 
47
48
  @project = nil
48
49
  end
@@ -196,7 +197,7 @@ class TaskJuggler
196
197
  # Add the new user-defined attribute as reportable attribute to the parser
197
198
  # rule.
198
199
  oldCurrentRule = @cr
199
- @cr = @rules['reportableAttributes']
200
+ @cr = @rules[:reportableAttributes]
200
201
  singlePattern('_' + @val[1])
201
202
  descr(@val[2])
202
203
  @cr = oldCurrentRule
@@ -209,11 +210,10 @@ class TaskJuggler
209
210
  # data into a MessageHandler message that points to the correct location.
210
211
  # This is necessary, because the RichText parser knows nothing about the
211
212
  # actual input file. So we have to map the error location in the RichText
212
- # input stream back to the position in the project file.
213
- # To limit the supported set of variable tokens, a subset can be provided
214
- # by _tokenSet_.
215
- def newRichText(text, tokenSet = nil)
216
- sfi = sourceFileInfo
213
+ # input stream back to the position in the project file. _sfi_ is the
214
+ # SourceFileInfo of the input string. To limit the supported set of
215
+ # variable tokens, a subset can be provided by _tokenSet_.
216
+ def newRichText(text, sfi, tokenSet = nil)
217
217
  rText = RichText.new(text, RTFHandlers.create(@project, sfi))
218
218
  unless (rti = rText.generateIntermediateFormat( [ 0, 0, 0], tokenSet))
219
219
  rText.messageHandler.messages.each do |msg|
@@ -357,7 +357,8 @@ class TaskJuggler
357
357
  # token.
358
358
  def descr(text)
359
359
  if @cr.patterns[-1].length != 1 ||
360
- (@cr.patterns[-1][0][0] != ?_ && @cr.patterns[-1][0][0] != ?$)
360
+ (@cr.patterns[-1][0][0] != :literal &&
361
+ @cr.patterns[-1][0][0] != :variable)
361
362
  raise 'descr() may only be used for patterns with terminal tokens.'
362
363
  end
363
364
  arg(0, nil, text)
@@ -71,25 +71,25 @@ class TaskJuggler
71
71
  [ nil, /.*\n/, :macroCall, method('midMacroCall') ],
72
72
 
73
73
  # An ID with a colon suffix: foo:
74
- [ 'ID_WITH_COLON', /[a-zA-Z_]\w*:/, :tjp, method('chop') ],
74
+ [ :ID_WITH_COLON, /[a-zA-Z_]\w*:/, :tjp, method('chop') ],
75
75
 
76
76
  # An absolute ID: a.b.c
77
- [ 'ABSOLUTE_ID', /[a-zA-Z_]\w*(\.[a-zA-Z_]\w*)+/ ],
77
+ [ :ABSOLUTE_ID, /[a-zA-Z_]\w*(\.[a-zA-Z_]\w*)+/ ],
78
78
 
79
79
  # A normal ID: bar
80
- [ 'ID', /[a-zA-Z_]\w*/ ],
80
+ [ :ID, /[a-zA-Z_]\w*/ ],
81
81
 
82
82
  # A date
83
- [ 'DATE', /\d{4}-\d{1,2}-\d{1,2}(-\d{1,2}:\d{1,2}(:\d{1,2})?(-[-+]?\d{4})?)?/, :tjp, method('to_date') ],
83
+ [ :DATE, /\d{4}-\d{1,2}-\d{1,2}(-\d{1,2}:\d{1,2}(:\d{1,2})?(-[-+]?\d{4})?)?/, :tjp, method('to_date') ],
84
84
 
85
85
  # A time of day
86
- [ 'TIME', /\d{1,2}:\d{2}/, :tjp, method('to_time') ],
86
+ [ :TIME, /\d{1,2}:\d{2}/, :tjp, method('to_time') ],
87
87
 
88
88
  # A floating point number (e. g. 3.143)
89
- [ 'FLOAT', /\d*\.\d+/, :tjp, method('to_f') ],
89
+ [ :FLOAT, /\d*\.\d+/, :tjp, method('to_f') ],
90
90
 
91
91
  # An integer number
92
- [ 'INTEGER', /\d+/, :tjp, method('to_i') ],
92
+ [ :INTEGER, /\d+/, :tjp, method('to_i') ],
93
93
 
94
94
  # Multi line string enclosed with double quotes. The string may
95
95
  # contain double quotes prefixed by a backslash. The first rule
@@ -98,14 +98,14 @@ class TaskJuggler
98
98
  # Any line not containing the start or end.
99
99
  [ 'nil', /^(\\"|[^"])*\n/, :dqString, method('midStringDQ') ],
100
100
  # The end of the string.
101
- [ 'STRING', /(\\"|[^"])*"/, :dqString, method('endStringDQ') ],
101
+ [ :STRING, /(\\"|[^"])*"/, :dqString, method('endStringDQ') ],
102
102
 
103
103
  # Multi line string enclosed with single quotes.
104
104
  [ 'nil', /'(\\'|[^'])*/, :tjp, method('startStringSQ') ],
105
105
  # Any line not containing the start or end.
106
106
  [ 'nil', /^(\\'|[^'])*\n/, :sqString, method('midStringSQ') ],
107
107
  # The end of the string.
108
- [ 'STRING', /(\\'|[^'])*'/, :sqString, method('endStringSQ') ],
108
+ [ :STRING, /(\\'|[^'])*'/, :sqString, method('endStringSQ') ],
109
109
 
110
110
  # Scizzors marked string -8<- ... ->8-: The opening mark must be the
111
111
  # last thing in the line. The indentation of the first line after the
@@ -115,8 +115,8 @@ class TaskJuggler
115
115
  # Since the first line can be the last line (empty string case), we
116
116
  # need to detect the end in szrString1 and szrString mode. The
117
117
  # patterns switch the scanner back to tjp mode.
118
- [ 'STRING', /\s*->8-/, :szrString1, method('endStringSZR') ],
119
- [ 'STRING', /\s*->8-/, :szrString, method('endStringSZR') ],
118
+ [ :STRING, /\s*->8-/, :szrString1, method('endStringSZR') ],
119
+ [ :STRING, /\s*->8-/, :szrString, method('endStringSZR') ],
120
120
  # This rule handles macros inside of sizzors strings.
121
121
  [ nil, /.*?\$\{\s*([a-zA-Z_]\w*)(\s*"(\\"|[^"])*")*/,
122
122
  [ :szrString, :szrString1 ], method('startMacroCall') ],
@@ -125,24 +125,24 @@ class TaskJuggler
125
125
  [ 'nil', /.*\n/, :szrString, method('midStringSZR') ],
126
126
 
127
127
  # Single line macro definition
128
- [ 'MACRO', /\[.*\]\n/, :tjp, method('chop2nl') ],
128
+ [ :MACRO, /\[.*\]\n/, :tjp, method('chop2nl') ],
129
129
 
130
130
  # Multi line macro definition: The pattern switches the scanner into
131
131
  # macroDef mode.
132
132
  [ nil, /\[.*\n/, :tjp, method('startMacroDef') ],
133
133
  # The end of the macro is marked by a ']' that is immediately followed
134
134
  # by a line break. It switches the scanner back to tjp mode.
135
- [ 'MACRO', /.*\]\n/, :macroDef, method('endMacroDef') ],
135
+ [ :MACRO, /.*\]\n/, :macroDef, method('endMacroDef') ],
136
136
  # Any line not containing the start or end.
137
137
  [ nil, /.*\n/, :macroDef, method('midMacroDef') ],
138
138
 
139
139
  # Some multi-char literals.
140
- [ 'LITERAL', /<=?/ ],
141
- [ 'LITERAL', />=?/ ],
142
- [ 'LITERAL', /!=?/ ],
140
+ [ :LITERAL, /<=?/ ],
141
+ [ :LITERAL, />=?/ ],
142
+ [ :LITERAL, /!=?/ ],
143
143
 
144
144
  # Everything else is returned as a single-char literal.
145
- [ 'LITERAL', /./ ]
145
+ [ :LITERAL, /./ ]
146
146
  ]
147
147
 
148
148
  super(masterFile, messageHandler, tokenPatterns, :tjp)
@@ -159,15 +159,28 @@ class TaskJuggler
159
159
  end
160
160
 
161
161
  def to_time(type, match)
162
- h, m, s = match.split(':')
162
+ h, m = match.split(':')
163
163
  h = h.to_i
164
+ if h < 0 || h > 24
165
+ error('time_bad_hour', "Hour #{h} out of range (0 - 24)")
166
+ end
164
167
  m = m.to_i
165
- s = 0 if s.nil?
166
- [ type, h * 3600 + m * 60 + s ]
168
+ if m < 0 || h > 59
169
+ error('time_bad_minute', "Minute #{m} out of range (0 - 59)")
170
+ end
171
+ if h == 24 && m != 0
172
+ error('time_bad_time', "Time #{match} cannot be larger then 24:00")
173
+ end
174
+
175
+ [ type, (h * 60 + m) * 60 ]
167
176
  end
168
177
 
169
178
  def to_date(type, match)
170
- [ type, TjTime.new(match) ]
179
+ begin
180
+ [ type, TjTime.new(match) ]
181
+ rescue TjException => msg
182
+ error('time_error', msg)
183
+ end
171
184
  end
172
185
 
173
186
  def newPos(type, match)
@@ -216,7 +229,7 @@ class TaskJuggler
216
229
  self.mode = :tjp
217
230
  # Remove the trailing " and remove the backslashes from escaped ".
218
231
  @string += match[0..-2].gsub(/\\"/, '"')
219
- [ 'STRING', @string ]
232
+ [ :STRING, @string ]
220
233
  end
221
234
 
222
235
  def startStringSQ(type, match)
@@ -236,7 +249,7 @@ class TaskJuggler
236
249
  self.mode = :tjp
237
250
  # Remove the trailing ' and remove the backslashes from escaped '.
238
251
  @string += match[0..-2].gsub(/\\'/, "'")
239
- [ 'STRING', @string ]
252
+ [ :STRING, @string ]
240
253
  end
241
254
 
242
255
  def startStringSZR(type, match)
@@ -274,7 +287,7 @@ class TaskJuggler
274
287
 
275
288
  def endStringSZR(type, match)
276
289
  self.mode = :tjp
277
- [ 'STRING', @string ]
290
+ [ :STRING, @string ]
278
291
  end
279
292
 
280
293
  def startMacroDef(type, match)
@@ -293,7 +306,7 @@ class TaskJuggler
293
306
  self.mode = :tjp
294
307
  # Remove "]\n"
295
308
  @macroDef += match[0..-3]
296
- [ 'MACRO', @macroDef ]
309
+ [ :MACRO, @macroDef ]
297
310
  end
298
311
 
299
312
  def startMacroCall(type, match)
data/lib/PropertyList.rb CHANGED
@@ -168,19 +168,21 @@ class TaskJuggler
168
168
  def addSortingCriteria(criteria, up, scIdx)
169
169
  unless @propertySet.knownAttribute?(criteria) ||
170
170
  @propertySet.hasQuery?(criteria, scIdx)
171
- raise "Unknown attribute #{criteria} used for sorting criterium"
171
+ raise TjException.new,
172
+ "Unknown attribute #{criteria} used for sorting criterium"
172
173
  end
173
174
  if scIdx == -1
174
175
  if @propertySet.scenarioSpecific?(criteria)
175
- raise "Attribute #{criteria} is scenario specific." +
176
+ raise TjException.new,
177
+ "Attribute #{criteria} is scenario specific." +
176
178
  "You must specify a scenario id."
177
179
  end
178
180
  else
179
181
  if @propertySet.project.scenario(scIdx).nil?
180
- raise "Unknown scenario index #{scIdx} used."
182
+ raise TjException.new, "Unknown scenario index #{scIdx} used."
181
183
  end
182
184
  if !@propertySet.scenarioSpecific?(criteria)
183
- raise "Attribute #{criteria} is not scenario specific"
185
+ raise TjException.new, "Attribute #{criteria} is not scenario specific"
184
186
  end
185
187
  end
186
188
  @sortingCriteria.push(criteria)
data/lib/Query.rb CHANGED
@@ -70,8 +70,6 @@ class TaskJuggler
70
70
  if date.is_a?(TjTime)
71
71
  @start = date
72
72
  @startIdx = @project.dateToIdx(date, true)
73
- #elsif date.is_a?(Fixnum)
74
- # self.startIdx=(date)
75
73
  else
76
74
  raise "Unsupported type #{date.class}"
77
75
  end
@@ -81,8 +79,6 @@ class TaskJuggler
81
79
  if idx.is_a?(Fixnum)
82
80
  @startIdx = idx
83
81
  @start = @project.idxToDate(idx)
84
- #elsif idx.is_a?(TjTime)
85
- # self.start=(idx)
86
82
  else
87
83
  raise "Unsupported type #{idx.class}"
88
84
  end
@@ -92,8 +88,6 @@ class TaskJuggler
92
88
  if date.is_a?(TjTime)
93
89
  @end = date
94
90
  @endIdx = @project.dateToIdx(date, true)
95
- #elsif date.is_a?(Fixnum)
96
- # self.endIdx=(date)
97
91
  else
98
92
  raise "Unsupported type #{date.class}"
99
93
  end
@@ -103,8 +97,6 @@ class TaskJuggler
103
97
  if idx.is_a?(Fixnum)
104
98
  @endIdx = idx
105
99
  @end = @project.idxToDate(idx)
106
- #elsif idx.is_a?(TjTime)
107
- # self.end=(idx)
108
100
  else
109
101
  raise "Unsupported type #{idx.class}"
110
102
  end
data/lib/RealFormat.rb CHANGED
@@ -37,7 +37,7 @@ class TaskJuggler
37
37
  end
38
38
  elsif args.length == 5
39
39
  # The argument is a list of values.
40
- 0.upto(4) do |i|
40
+ args.length.times do |i|
41
41
  instance_variable_set(iVars[i], args[i])
42
42
  end
43
43
  else
data/lib/Resource.rb CHANGED
@@ -56,7 +56,7 @@ class TaskJuggler
56
56
  # Sort all entries in buckets by their alert level.
57
57
  numberOfLevels = project['alertLevels'].length
58
58
  listByLevel = []
59
- 0.upto(numberOfLevels - 1) { |i| listByLevel[i] = [] }
59
+ numberOfLevels.times { |i| listByLevel[i] = [] }
60
60
  list.each do |entry|
61
61
  listByLevel[entry.alertLevel] << entry
62
62
  end
@@ -37,15 +37,23 @@ class TaskJuggler
37
37
  # subset.
38
38
  @scoreboard = nil
39
39
 
40
+ # The index of the earliest booked time slot.
40
41
  @firstBookedSlot = nil
42
+ # Same but for each assigned resource.
43
+ @firstBookedSlots = {}
44
+ # The index of the last booked time Slot.
41
45
  @lastBookedSlot = nil
46
+ # Same but for each assigned resource.
47
+ @lastBookedSlots = {}
48
+
49
+ @dCache = DataCache.instance
42
50
  end
43
51
 
44
52
  # This method must be called at the beginning of each scheduling run. It
45
53
  # initializes variables used during the scheduling process.
46
54
  def prepareScheduling
47
55
  @property['effort', @scenarioIdx] = 0
48
- initScoreboard
56
+ initScoreboard if @property.leaf?
49
57
 
50
58
  setDirectReports
51
59
  end
@@ -91,7 +99,6 @@ class TaskJuggler
91
99
  end
92
100
  end
93
101
 
94
-
95
102
  def preScheduleCheck
96
103
  a('managers').each do |manager|
97
104
  unless manager.leaf?
@@ -106,6 +113,25 @@ class TaskJuggler
106
113
  end
107
114
  end
108
115
 
116
+ # This method does some housekeeping work after the scheduling is
117
+ # completed. It's meant to be called for top-level resources and then
118
+ # recursively descends into all child resources.
119
+ def finishScheduling
120
+ # Recursively descend into all child resources.
121
+ @property.children.each do |resource|
122
+ resource.finishScheduling(@scenarioIdx)
123
+ end
124
+
125
+ if (parent = @property.parent)
126
+ # Add the assigned task to the parent duties list.
127
+ a('duties').each do |task|
128
+ unless parent['duties', @scenarioIdx].include?(task)
129
+ parent['duties', @scenarioIdx] << task
130
+ end
131
+ end
132
+ end
133
+ end
134
+
109
135
  def postScheduleCheck
110
136
  if a('fail') || a('warn')
111
137
  queryAttrs = { 'project' => @project,
@@ -158,6 +184,11 @@ class TaskJuggler
158
184
  def book(sbIdx, task, force = false)
159
185
  return false if !force && !available?(sbIdx)
160
186
 
187
+ # Make sure the task is in the list of duties.
188
+ unless a('duties').include?(task)
189
+ @property['duties', @scenarioIdx] << task
190
+ end
191
+
161
192
  #puts "Booking resource #{@property.fullId} at " +
162
193
  # "#{@scoreboard.idxToDate(sbIdx)}/#{sbIdx} for task #{task.fullId}\n"
163
194
  @scoreboard[sbIdx] = task
@@ -170,17 +201,24 @@ class TaskJuggler
170
201
  end
171
202
  a('limits').inc(@scoreboard.idxToDate(sbIdx)) if a('limits')
172
203
 
173
- # Make sure the task is in the list of duties.
174
- unless a('duties').include?(task)
175
- @property['duties', @scenarioIdx] << task
176
- end
177
-
204
+ # Scoreboard iterations are fairly expensive but they are very frequent
205
+ # operations in later processing. To limit the interations to the
206
+ # relevant intervals, we store the interval for all bookings and for
207
+ # each individual task.
178
208
  if @firstBookedSlot.nil? || @firstBookedSlot > sbIdx
179
209
  @firstBookedSlot = sbIdx
180
210
  end
181
211
  if @lastBookedSlot.nil? || @lastBookedSlot < sbIdx
182
212
  @lastBookedSlot = sbIdx
183
213
  end
214
+ if task
215
+ if @firstBookedSlots[task].nil? || @firstBookedSlots[task] > sbIdx
216
+ @firstBookedSlots[task] = sbIdx
217
+ end
218
+ if @lastBookedSlots[task].nil? || @lastBookedSlots[task] < sbIdx
219
+ @lastBookedSlots[task] = sbIdx
220
+ end
221
+ end
184
222
  true
185
223
  end
186
224
 
@@ -291,6 +329,16 @@ class TaskJuggler
291
329
  # Returns the work of the resource (and its children) weighted by their
292
330
  # efficiency.
293
331
  def getEffectiveWork(startIdx, endIdx, task = nil)
332
+ # There can't be any effective work if the start is after the end or the
333
+ # todo list doesn't contain the specified task.
334
+ return 0.0 if startIdx >= endIdx || (task && !a('duties').include?(task))
335
+
336
+ # The unique key we use to address the result in the cache.
337
+ key = [ self, :ResourceScenarioEffectiveWork, startIdx, endIdx,
338
+ task ].hash
339
+ work = @dCache.load(key)
340
+ return work if work
341
+
294
342
  # Convert the interval dates to indexes if needed.
295
343
  startIdx = @project.dateToIdx(startIdx, true) if startIdx.is_a?(TjTime)
296
344
  endIdx = @project.dateToIdx(endIdx, true) if endIdx.is_a?(TjTime)
@@ -307,7 +355,7 @@ class TaskJuggler
307
355
  getAllocatedSlots(startIdx, endIdx, task) *
308
356
  @project['scheduleGranularity']) * a('efficiency')
309
357
  end
310
- work
358
+ @dCache.store(work, key)
311
359
  end
312
360
 
313
361
  # Returns the allocated accumulated time of this resource and its children.
@@ -419,16 +467,13 @@ class TaskJuggler
419
467
  # the period specified with the Interval _iv_. If task is not nil
420
468
  # only allocations to this tasks are respected.
421
469
  def allocated?(iv, task = nil)
422
- initScoreboard if @scoreboard.nil?
470
+ return false if task && !a('duties').include?(task)
423
471
 
424
- startIdx = @scoreboard.dateToIdx(iv.start, true)
425
- endIdx = @scoreboard.dateToIdx(iv.end, true)
472
+ startIdx = @project.dateToIdx(iv.start, true)
473
+ endIdx = @project.dateToIdx(iv.end, true)
426
474
 
427
- startIdx = @firstBookedSlot if @firstBookedSlot &&
428
- startIdx < @firstBookedSlot
429
- endIdx = @lastBookedSlot + 1 if @lastBookedSlot &&
430
- endIdx < @lastBookedSlot + 1
431
- return false if startIdx > endIdx
475
+ startIdx, endIdx = fitIndicies(startIdx, endIdx, task)
476
+ return false if startIdx >= endIdx
432
477
 
433
478
  return allocatedSub(startIdx, endIdx, task)
434
479
  end
@@ -461,8 +506,6 @@ class TaskJuggler
461
506
  bookings[lastTask] = Booking.new(@property, lastTask, [])
462
507
  end
463
508
 
464
- # Make sure the index is correct even for the last task block.
465
- idx += 1 if idx == endIdx
466
509
  # Append the new interval to the Booking.
467
510
  bookings[lastTask].intervals <<
468
511
  Interval.new(@scoreboard.idxToDate(bookingStart),
@@ -494,18 +537,15 @@ class TaskJuggler
494
537
  # Count the booked slots between the start and end index. If _task_ is not
495
538
  # nil count only those slots that are assigned to this particular task.
496
539
  def getAllocatedSlots(startIdx, endIdx, task)
497
- # To speedup the counting we start with the first booked slot and end
498
- # with the last booked slot.
499
- startIdx = @firstBookedSlot if @firstBookedSlot &&
500
- startIdx < @firstBookedSlot
501
- endIdx = @lastBookedSlot + 1 if @lastBookedSlot &&
502
- endIdx > @lastBookedSlot + 1
540
+ # If there is no scoreboard, we don't have any allocations.
541
+ return 0 unless @scoreboard
542
+
543
+ startIdx, endIdx = fitIndicies(startIdx, endIdx, task)
544
+ return 0 if startIdx >= endIdx
503
545
 
504
- initScoreboard if @scoreboard.nil?
505
546
  bookedSlots = 0
506
- startIdx.upto(endIdx - 1) do |idx|
507
- if (task.nil? && @scoreboard[idx].is_a?(Task)) ||
508
- (task && @scoreboard[idx] == task)
547
+ @scoreboard.each(startIdx, endIdx) do |slot|
548
+ if (task.nil? && slot.is_a?(Task)) || (task && slot == task)
509
549
  bookedSlots += 1
510
550
  end
511
551
  end
@@ -515,7 +555,9 @@ class TaskJuggler
515
555
 
516
556
  # Count the free slots between the start and end index.
517
557
  def getFreeSlots(startIdx, endIdx)
518
- initScoreboard if @scoreboard.nil?
558
+ return 0 if startIdx >= endIdx
559
+
560
+ initScoreboard unless @scoreboard
519
561
 
520
562
  freeSlots = 0
521
563
  startIdx.upto(endIdx - 1) do |idx|
@@ -528,7 +570,9 @@ class TaskJuggler
528
570
  # Count the regular work time slots between the start and end index that
529
571
  # have been blocked by a vacation.
530
572
  def getVacationSlots(startIdx, endIdx)
531
- initScoreboard if @scoreboard.nil?
573
+ return 0 if startIdx >= endIdx
574
+
575
+ initScoreboard unless @scoreboard
532
576
 
533
577
  vacationSlots = 0
534
578
  startIdx.upto(endIdx - 1) do |idx|
@@ -603,6 +647,24 @@ class TaskJuggler
603
647
  end
604
648
  end
605
649
 
650
+ # Limit the _startIdx_ and _endIdx_ to the actually assigned interval.
651
+ # If _task_ is provided, fit it for the bookings of this particular task.
652
+ def fitIndicies(startIdx, endIdx, task = nil)
653
+ if task
654
+ startIdx = @firstBookedSlots[task] if @firstBookedSlots[task] &&
655
+ startIdx < @firstBookedSlots[task]
656
+ endIdx = @lastBookedSlots[task] + 1 if @lastBookedSlots[task] &&
657
+ endIdx >
658
+ @lastBookedSlots[task] + 1
659
+ else
660
+ startIdx = @firstBookedSlot if @firstBookedSlot &&
661
+ startIdx < @firstBookedSlot
662
+ endIdx = @lastBookedSlot + 1 if @lastBookedSlot &&
663
+ endIdx > @lastBookedSlot + 1
664
+ end
665
+ [ startIdx, endIdx ]
666
+ end
667
+
606
668
  def setReports_i(reports)
607
669
  if reports.include?(@property)
608
670
  # A manager must never show up in the list of his/her own reports.
@@ -638,7 +700,10 @@ class TaskJuggler
638
700
  task)
639
701
  end
640
702
  else
641
- return false unless a('duties').include?(task)
703
+ return false unless @scoreboard && a('duties').include?(task)
704
+
705
+ startIdx, endIdx = fitIndicies(startIdx, endIdx, task)
706
+ return false if startIdx >= endIdx
642
707
 
643
708
  startIdx.upto(endIdx - 1) do |idx|
644
709
  return true if @scoreboard[idx] == task