taskjuggler 0.0.2

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 (571) hide show
  1. data/COPYING +280 -0
  2. data/README +31 -0
  3. data/Rakefile +20 -0
  4. data/benchmarks/UTF-8-Strings.rb +58 -0
  5. data/benchmarks/allocate.tjp +30 -0
  6. data/benchmarks/booking.tjp +62 -0
  7. data/benchmarks/depends.tjp +112 -0
  8. data/benchmarks/htmltaskreport.tjp +45 -0
  9. data/benchmarks/runbench.rb +24 -0
  10. data/bin/tj3 +3 -0
  11. data/bin/tj3man +3 -0
  12. data/doc/classes/AppConfig.html +808 -0
  13. data/doc/classes/Arguments.html +226 -0
  14. data/doc/classes/String.html +395 -0
  15. data/doc/classes/TaskJuggler.html +1358 -0
  16. data/doc/classes/TaskJuggler/Account.html +257 -0
  17. data/doc/classes/TaskJuggler/AccountScenario.html +218 -0
  18. data/doc/classes/TaskJuggler/Allocation.html +419 -0
  19. data/doc/classes/TaskJuggler/AllocationAttribute.html +291 -0
  20. data/doc/classes/TaskJuggler/AttributeBase.html +608 -0
  21. data/doc/classes/TaskJuggler/AttributeDefinition.html +259 -0
  22. data/doc/classes/TaskJuggler/Booking.html +307 -0
  23. data/doc/classes/TaskJuggler/BookingListAttribute.html +263 -0
  24. data/doc/classes/TaskJuggler/BooleanAttribute.html +261 -0
  25. data/doc/classes/TaskJuggler/CSVFile.html +325 -0
  26. data/doc/classes/TaskJuggler/Charge.html +279 -0
  27. data/doc/classes/TaskJuggler/ChargeListAttribute.html +229 -0
  28. data/doc/classes/TaskJuggler/ChargeSet.html +440 -0
  29. data/doc/classes/TaskJuggler/ChargeSetListAttribute.html +276 -0
  30. data/doc/classes/TaskJuggler/ColumnTable.html +260 -0
  31. data/doc/classes/TaskJuggler/DateAttribute.html +194 -0
  32. data/doc/classes/TaskJuggler/DependencyListAttribute.html +267 -0
  33. data/doc/classes/TaskJuggler/DurationAttribute.html +229 -0
  34. data/doc/classes/TaskJuggler/FixnumAttribute.html +194 -0
  35. data/doc/classes/TaskJuggler/FlagListAttribute.html +263 -0
  36. data/doc/classes/TaskJuggler/FloatAttribute.html +229 -0
  37. data/doc/classes/TaskJuggler/GanttChart.html +667 -0
  38. data/doc/classes/TaskJuggler/GanttContainer.html +441 -0
  39. data/doc/classes/TaskJuggler/GanttHeader.html +280 -0
  40. data/doc/classes/TaskJuggler/GanttHeaderScaleItem.html +245 -0
  41. data/doc/classes/TaskJuggler/GanttLine.html +398 -0
  42. data/doc/classes/TaskJuggler/GanttLoadStack.html +327 -0
  43. data/doc/classes/TaskJuggler/GanttMilestone.html +415 -0
  44. data/doc/classes/TaskJuggler/GanttRouter.html +425 -0
  45. data/doc/classes/TaskJuggler/GanttTaskBar.html +429 -0
  46. data/doc/classes/TaskJuggler/HTMLDocument.html +240 -0
  47. data/doc/classes/TaskJuggler/HTMLGraphics.html +231 -0
  48. data/doc/classes/TaskJuggler/Interval.html +552 -0
  49. data/doc/classes/TaskJuggler/IntervalListAttribute.html +267 -0
  50. data/doc/classes/TaskJuggler/KeywordDocumentation.html +796 -0
  51. data/doc/classes/TaskJuggler/Limits.html +416 -0
  52. data/doc/classes/TaskJuggler/Limits/Limit.html +381 -0
  53. data/doc/classes/TaskJuggler/LimitsAttribute.html +261 -0
  54. data/doc/classes/TaskJuggler/Log.html +613 -0
  55. data/doc/classes/TaskJuggler/LogicalAttribute.html +226 -0
  56. data/doc/classes/TaskJuggler/LogicalExpression.html +251 -0
  57. data/doc/classes/TaskJuggler/LogicalFlag.html +229 -0
  58. data/doc/classes/TaskJuggler/LogicalFunction.html +324 -0
  59. data/doc/classes/TaskJuggler/LogicalOperation.html +299 -0
  60. data/doc/classes/TaskJuggler/Macro.html +194 -0
  61. data/doc/classes/TaskJuggler/MacroParser.html +360 -0
  62. data/doc/classes/TaskJuggler/MacroTable.html +366 -0
  63. data/doc/classes/TaskJuggler/Message.html +281 -0
  64. data/doc/classes/TaskJuggler/MessageHandler.html +215 -0
  65. data/doc/classes/TaskJuggler/Project.html +1606 -0
  66. data/doc/classes/TaskJuggler/ProjectFileParser.html +412 -0
  67. data/doc/classes/TaskJuggler/PropertyList.html +597 -0
  68. data/doc/classes/TaskJuggler/PropertySet.html +1200 -0
  69. data/doc/classes/TaskJuggler/PropertyTreeNode.html +1449 -0
  70. data/doc/classes/TaskJuggler/Query.html +600 -0
  71. data/doc/classes/TaskJuggler/RealFormat.html +252 -0
  72. data/doc/classes/TaskJuggler/ReferenceAttribute.html +194 -0
  73. data/doc/classes/TaskJuggler/Report.html +528 -0
  74. data/doc/classes/TaskJuggler/ReportElement.html +1070 -0
  75. data/doc/classes/TaskJuggler/ReportTable.html +497 -0
  76. data/doc/classes/TaskJuggler/ReportTableCell.html +518 -0
  77. data/doc/classes/TaskJuggler/ReportTableColumn.html +364 -0
  78. data/doc/classes/TaskJuggler/ReportTableElement.html +644 -0
  79. data/doc/classes/TaskJuggler/ReportTableLegend.html +343 -0
  80. data/doc/classes/TaskJuggler/ReportTableLine.html +431 -0
  81. data/doc/classes/TaskJuggler/Resource.html +211 -0
  82. data/doc/classes/TaskJuggler/ResourceListAttribute.html +267 -0
  83. data/doc/classes/TaskJuggler/ResourceListRE.html +249 -0
  84. data/doc/classes/TaskJuggler/ResourceScenario.html +1137 -0
  85. data/doc/classes/TaskJuggler/RichText.html +537 -0
  86. data/doc/classes/TaskJuggler/RichTextAttribute.html +229 -0
  87. data/doc/classes/TaskJuggler/RichTextDocument.html +418 -0
  88. data/doc/classes/TaskJuggler/RichTextElement.html +829 -0
  89. data/doc/classes/TaskJuggler/RichTextException.html +212 -0
  90. data/doc/classes/TaskJuggler/RichTextParser.html +317 -0
  91. data/doc/classes/TaskJuggler/RichTextProtocolExample.html +303 -0
  92. data/doc/classes/TaskJuggler/RichTextProtocolHandler.html +194 -0
  93. data/doc/classes/TaskJuggler/RichTextScanner.html +561 -0
  94. data/doc/classes/TaskJuggler/RichTextSnip.html +364 -0
  95. data/doc/classes/TaskJuggler/RichTextSyntaxRules.html +883 -0
  96. data/doc/classes/TaskJuggler/Scenario.html +163 -0
  97. data/doc/classes/TaskJuggler/ScenarioData.html +354 -0
  98. data/doc/classes/TaskJuggler/Scoreboard.html +638 -0
  99. data/doc/classes/TaskJuggler/Shift.html +255 -0
  100. data/doc/classes/TaskJuggler/ShiftAssignment.html +488 -0
  101. data/doc/classes/TaskJuggler/ShiftAssignments.html +715 -0
  102. data/doc/classes/TaskJuggler/ShiftAssignmentsAttribute.html +261 -0
  103. data/doc/classes/TaskJuggler/ShiftScenario.html +282 -0
  104. data/doc/classes/TaskJuggler/SourceFileInfo.html +247 -0
  105. data/doc/classes/TaskJuggler/StringAttribute.html +229 -0
  106. data/doc/classes/TaskJuggler/SymbolAttribute.html +194 -0
  107. data/doc/classes/TaskJuggler/SyntaxReference.html +516 -0
  108. data/doc/classes/TaskJuggler/TOCEntry.html +242 -0
  109. data/doc/classes/TaskJuggler/TableColumnDefinition.html +273 -0
  110. data/doc/classes/TaskJuggler/TableOfContents.html +256 -0
  111. data/doc/classes/TaskJuggler/Task.html +203 -0
  112. data/doc/classes/TaskJuggler/TaskDependency.html +251 -0
  113. data/doc/classes/TaskJuggler/TaskListAttribute.html +267 -0
  114. data/doc/classes/TaskJuggler/TaskListRE.html +250 -0
  115. data/doc/classes/TaskJuggler/TaskScenario.html +2206 -0
  116. data/doc/classes/TaskJuggler/TextParser.html +670 -0
  117. data/doc/classes/TaskJuggler/TextParser/Pattern.html +923 -0
  118. data/doc/classes/TaskJuggler/TextParser/Rule.html +779 -0
  119. data/doc/classes/TaskJuggler/TextParser/StackElement.html +267 -0
  120. data/doc/classes/TaskJuggler/TextParser/TextParserResultArray.html +212 -0
  121. data/doc/classes/TaskJuggler/TextParser/TokenDoc.html +221 -0
  122. data/doc/classes/TaskJuggler/TextScanner.html +708 -0
  123. data/doc/classes/TaskJuggler/TextScanner/BufferStreamHandle.html +355 -0
  124. data/doc/classes/TaskJuggler/TextScanner/FileStreamHandle.html +341 -0
  125. data/doc/classes/TaskJuggler/TextScanner/StreamHandle.html +260 -0
  126. data/doc/classes/TaskJuggler/TjException.html +185 -0
  127. data/doc/classes/TaskJuggler/TjTime.html +1845 -0
  128. data/doc/classes/TaskJuggler/TjpExample.html +310 -0
  129. data/doc/classes/TaskJuggler/TjpExportRE.html +329 -0
  130. data/doc/classes/TaskJuggler/TjpSyntaxRules.html +8928 -0
  131. data/doc/classes/TaskJuggler/UserManual.html +606 -0
  132. data/doc/classes/TaskJuggler/WorkingHours.html +582 -0
  133. data/doc/classes/TaskJuggler/WorkingHoursAttribute.html +284 -0
  134. data/doc/classes/TaskJuggler/XMLBlob.html +207 -0
  135. data/doc/classes/TaskJuggler/XMLComment.html +206 -0
  136. data/doc/classes/TaskJuggler/XMLDocument.html +293 -0
  137. data/doc/classes/TaskJuggler/XMLElement.html +341 -0
  138. data/doc/classes/TaskJuggler/XMLNamedText.html +174 -0
  139. data/doc/classes/TaskJuggler/XMLText.html +221 -0
  140. data/doc/files/COPYING.html +448 -0
  141. data/doc/files/README.html +134 -0
  142. data/doc/files/lib/AccountScenario_rb.html +116 -0
  143. data/doc/files/lib/Account_rb.html +118 -0
  144. data/doc/files/lib/Allocation_rb.html +118 -0
  145. data/doc/files/lib/AppConfig_rb.html +116 -0
  146. data/doc/files/lib/AttributeBase_rb.html +106 -0
  147. data/doc/files/lib/AttributeDefinition_rb.html +106 -0
  148. data/doc/files/lib/Attributes_rb.html +130 -0
  149. data/doc/files/lib/Booking_rb.html +106 -0
  150. data/doc/files/lib/ChargeSet_rb.html +116 -0
  151. data/doc/files/lib/Charge_rb.html +116 -0
  152. data/doc/files/lib/HTMLDocument_rb.html +116 -0
  153. data/doc/files/lib/Interval_rb.html +116 -0
  154. data/doc/files/lib/KeywordDocumentation_rb.html +122 -0
  155. data/doc/files/lib/Limits_rb.html +116 -0
  156. data/doc/files/lib/Log_rb.html +116 -0
  157. data/doc/files/lib/LogicalExpression_rb.html +122 -0
  158. data/doc/files/lib/LogicalFlag_rb.html +116 -0
  159. data/doc/files/lib/LogicalFunction_rb.html +116 -0
  160. data/doc/files/lib/LogicalOperation_rb.html +116 -0
  161. data/doc/files/lib/MacroParser_rb.html +118 -0
  162. data/doc/files/lib/MacroTable_rb.html +122 -0
  163. data/doc/files/lib/MessageHandler_rb.html +106 -0
  164. data/doc/files/lib/Message_rb.html +116 -0
  165. data/doc/files/lib/ProjectFileParser_rb.html +122 -0
  166. data/doc/files/lib/Project_rb.html +148 -0
  167. data/doc/files/lib/PropertyList_rb.html +106 -0
  168. data/doc/files/lib/PropertySet_rb.html +118 -0
  169. data/doc/files/lib/PropertyTreeNode_rb.html +106 -0
  170. data/doc/files/lib/Query_rb.html +116 -0
  171. data/doc/files/lib/RealFormat_rb.html +106 -0
  172. data/doc/files/lib/ResourceScenario_rb.html +116 -0
  173. data/doc/files/lib/Resource_rb.html +118 -0
  174. data/doc/files/lib/RichTextDocument_rb.html +120 -0
  175. data/doc/files/lib/RichTextElement_rb.html +120 -0
  176. data/doc/files/lib/RichTextParser_rb.html +120 -0
  177. data/doc/files/lib/RichTextProtocolExample_rb.html +120 -0
  178. data/doc/files/lib/RichTextProtocolHandler_rb.html +106 -0
  179. data/doc/files/lib/RichTextScanner_rb.html +116 -0
  180. data/doc/files/lib/RichTextSnip_rb.html +118 -0
  181. data/doc/files/lib/RichTextSyntaxRules_rb.html +106 -0
  182. data/doc/files/lib/RichText_rb.html +118 -0
  183. data/doc/files/lib/ScenarioData_rb.html +118 -0
  184. data/doc/files/lib/Scenario_rb.html +116 -0
  185. data/doc/files/lib/Scoreboard_rb.html +106 -0
  186. data/doc/files/lib/ShiftAssignments_rb.html +116 -0
  187. data/doc/files/lib/ShiftScenario_rb.html +116 -0
  188. data/doc/files/lib/Shift_rb.html +118 -0
  189. data/doc/files/lib/SourceFileInfo_rb.html +106 -0
  190. data/doc/files/lib/SyntaxReference_rb.html +122 -0
  191. data/doc/files/lib/TOCEntry_rb.html +118 -0
  192. data/doc/files/lib/TableColumnDefinition_rb.html +106 -0
  193. data/doc/files/lib/TableOfContents_rb.html +118 -0
  194. data/doc/files/lib/TaskDependency_rb.html +106 -0
  195. data/doc/files/lib/TaskJuggler_rb.html +120 -0
  196. data/doc/files/lib/TaskScenario_rb.html +116 -0
  197. data/doc/files/lib/Task_rb.html +118 -0
  198. data/doc/files/lib/TextParser/Pattern_rb.html +116 -0
  199. data/doc/files/lib/TextParser/Rule_rb.html +106 -0
  200. data/doc/files/lib/TextParser/StackElement_rb.html +106 -0
  201. data/doc/files/lib/TextParser/TokenDoc_rb.html +106 -0
  202. data/doc/files/lib/TextParser_rb.html +124 -0
  203. data/doc/files/lib/TextScanner_rb.html +128 -0
  204. data/doc/files/lib/Tj3Config_rb.html +118 -0
  205. data/doc/files/lib/TjException_rb.html +106 -0
  206. data/doc/files/lib/TjTime_rb.html +118 -0
  207. data/doc/files/lib/TjpExample_rb.html +116 -0
  208. data/doc/files/lib/TjpSyntaxRules_rb.html +106 -0
  209. data/doc/files/lib/UTF8String_rb.html +132 -0
  210. data/doc/files/lib/UserManual_rb.html +124 -0
  211. data/doc/files/lib/WorkingHours_rb.html +116 -0
  212. data/doc/files/lib/XMLDocument_rb.html +116 -0
  213. data/doc/files/lib/XMLElement_rb.html +116 -0
  214. data/doc/files/lib/reports/CSVFile_rb.html +116 -0
  215. data/doc/files/lib/reports/ColumnTable_rb.html +116 -0
  216. data/doc/files/lib/reports/GanttChart_rb.html +122 -0
  217. data/doc/files/lib/reports/GanttContainer_rb.html +116 -0
  218. data/doc/files/lib/reports/GanttHeaderScaleItem_rb.html +106 -0
  219. data/doc/files/lib/reports/GanttHeader_rb.html +116 -0
  220. data/doc/files/lib/reports/GanttLine_rb.html +126 -0
  221. data/doc/files/lib/reports/GanttLoadStack_rb.html +116 -0
  222. data/doc/files/lib/reports/GanttMilestone_rb.html +116 -0
  223. data/doc/files/lib/reports/GanttRouter_rb.html +106 -0
  224. data/doc/files/lib/reports/GanttTaskBar_rb.html +116 -0
  225. data/doc/files/lib/reports/HTMLGraphics_rb.html +106 -0
  226. data/doc/files/lib/reports/ReportElement_rb.html +118 -0
  227. data/doc/files/lib/reports/ReportTableCell_rb.html +106 -0
  228. data/doc/files/lib/reports/ReportTableColumn_rb.html +106 -0
  229. data/doc/files/lib/reports/ReportTableElement_rb.html +122 -0
  230. data/doc/files/lib/reports/ReportTableLegend_rb.html +106 -0
  231. data/doc/files/lib/reports/ReportTableLine_rb.html +116 -0
  232. data/doc/files/lib/reports/ReportTable_rb.html +118 -0
  233. data/doc/files/lib/reports/Report_rb.html +126 -0
  234. data/doc/files/lib/reports/ResourceListRE_rb.html +122 -0
  235. data/doc/files/lib/reports/TaskListRE_rb.html +122 -0
  236. data/doc/files/lib/reports/TjpExportRE_rb.html +116 -0
  237. data/doc/files/lib/taskjuggler3_rb.html +276 -0
  238. data/doc/files/lib/tj3man_rb.html +189 -0
  239. data/doc/fr_class_index.html +285 -0
  240. data/doc/fr_file_index.html +223 -0
  241. data/doc/fr_method_index.html +1953 -0
  242. data/doc/index.html +21 -0
  243. data/doc/rdoc-style.css +299 -0
  244. data/examples/tutorial.tjp +361 -0
  245. data/gem_spec.rb +30 -0
  246. data/lib/Account.rb +50 -0
  247. data/lib/AccountScenario.rb +39 -0
  248. data/lib/Allocation.rb +102 -0
  249. data/lib/AppConfig.rb +134 -0
  250. data/lib/AttributeBase.rb +131 -0
  251. data/lib/AttributeDefinition.rb +47 -0
  252. data/lib/Attributes.rb +478 -0
  253. data/lib/BatchProcessor.rb +209 -0
  254. data/lib/Booking.rb +59 -0
  255. data/lib/Charge.rb +71 -0
  256. data/lib/ChargeSet.rb +126 -0
  257. data/lib/HTMLDocument.rb +59 -0
  258. data/lib/Interval.rb +127 -0
  259. data/lib/KeywordDocumentation.rb +560 -0
  260. data/lib/Limits.rb +219 -0
  261. data/lib/Log.rb +160 -0
  262. data/lib/LogicalExpression.rb +71 -0
  263. data/lib/LogicalFlag.rb +34 -0
  264. data/lib/LogicalFunction.rb +102 -0
  265. data/lib/LogicalOperation.rb +118 -0
  266. data/lib/MacroParser.rb +77 -0
  267. data/lib/MacroTable.rb +84 -0
  268. data/lib/Message.rb +56 -0
  269. data/lib/MessageHandler.rb +34 -0
  270. data/lib/Project.rb +662 -0
  271. data/lib/ProjectFileParser.rb +333 -0
  272. data/lib/PropertyList.rb +181 -0
  273. data/lib/PropertySet.rb +304 -0
  274. data/lib/PropertyTreeNode.rb +461 -0
  275. data/lib/Query.rb +227 -0
  276. data/lib/RealFormat.rb +73 -0
  277. data/lib/Resource.rb +42 -0
  278. data/lib/ResourceScenario.rb +511 -0
  279. data/lib/RichText.rb +147 -0
  280. data/lib/RichTextDocument.rb +139 -0
  281. data/lib/RichTextElement.rb +391 -0
  282. data/lib/RichTextParser.rb +66 -0
  283. data/lib/RichTextProtocolExample.rb +65 -0
  284. data/lib/RichTextProtocolHandler.rb +35 -0
  285. data/lib/RichTextScanner.rb +390 -0
  286. data/lib/RichTextSnip.rb +104 -0
  287. data/lib/RichTextSyntaxRules.rb +265 -0
  288. data/lib/Scenario.rb +27 -0
  289. data/lib/ScenarioData.rb +65 -0
  290. data/lib/Scoreboard.rb +141 -0
  291. data/lib/Shift.rb +48 -0
  292. data/lib/ShiftAssignments.rb +291 -0
  293. data/lib/ShiftScenario.rb +46 -0
  294. data/lib/SourceFileInfo.rb +37 -0
  295. data/lib/SyntaxReference.rb +284 -0
  296. data/lib/TOCEntry.rb +76 -0
  297. data/lib/TableColumnDefinition.rb +54 -0
  298. data/lib/TableOfContents.rb +46 -0
  299. data/lib/Task.rb +37 -0
  300. data/lib/TaskDependency.rb +39 -0
  301. data/lib/TaskJuggler.rb +84 -0
  302. data/lib/TaskScenario.rb +1622 -0
  303. data/lib/TextParser.rb +416 -0
  304. data/lib/TextParser/Pattern.rb +263 -0
  305. data/lib/TextParser/Rule.rb +171 -0
  306. data/lib/TextParser/StackElement.rb +45 -0
  307. data/lib/TextParser/TokenDoc.rb +38 -0
  308. data/lib/TextScanner.rb +682 -0
  309. data/lib/Tj3Config.rb +27 -0
  310. data/lib/TjException.rb +27 -0
  311. data/lib/TjTime.rb +395 -0
  312. data/lib/TjpExample.rb +119 -0
  313. data/lib/TjpSyntaxRules.rb +4022 -0
  314. data/lib/UTF8String.rb +100 -0
  315. data/lib/UserManual.rb +282 -0
  316. data/lib/WorkingHours.rb +323 -0
  317. data/lib/XMLDocument.rb +54 -0
  318. data/lib/XMLElement.rb +175 -0
  319. data/lib/reports/CSVFile.rb +146 -0
  320. data/lib/reports/ColumnTable.rb +66 -0
  321. data/lib/reports/GanttChart.rb +308 -0
  322. data/lib/reports/GanttContainer.rb +107 -0
  323. data/lib/reports/GanttHeader.rb +141 -0
  324. data/lib/reports/GanttHeaderScaleItem.rb +42 -0
  325. data/lib/reports/GanttLine.rb +329 -0
  326. data/lib/reports/GanttLoadStack.rb +113 -0
  327. data/lib/reports/GanttMilestone.rb +80 -0
  328. data/lib/reports/GanttRouter.rb +375 -0
  329. data/lib/reports/GanttTaskBar.rb +95 -0
  330. data/lib/reports/HTMLGraphics.rb +65 -0
  331. data/lib/reports/Report.rb +344 -0
  332. data/lib/reports/ReportElement.rb +427 -0
  333. data/lib/reports/ReportTable.rb +144 -0
  334. data/lib/reports/ReportTableCell.rb +142 -0
  335. data/lib/reports/ReportTableColumn.rb +82 -0
  336. data/lib/reports/ReportTableElement.rb +852 -0
  337. data/lib/reports/ReportTableLegend.rb +167 -0
  338. data/lib/reports/ReportTableLine.rb +87 -0
  339. data/lib/reports/ResourceListRE.rb +72 -0
  340. data/lib/reports/TaskListRE.rb +73 -0
  341. data/lib/reports/TjpExportRE.rb +394 -0
  342. data/lib/taskjuggler3.rb +106 -0
  343. data/lib/tj3man.rb +88 -0
  344. data/manual/Day_To_Day_Juggling +168 -0
  345. data/manual/Getting_Started +61 -0
  346. data/manual/How_To_Contribute +185 -0
  347. data/manual/Installation +68 -0
  348. data/manual/Intro +102 -0
  349. data/manual/Reporting_Bugs +26 -0
  350. data/manual/Rich_Text_Attributes +90 -0
  351. data/manual/TaskJuggler_2x_Migration +40 -0
  352. data/manual/Tutorial +579 -0
  353. data/manual/fdl +450 -0
  354. data/prj_cfg.rb +43 -0
  355. data/setup.rb +1585 -0
  356. data/tasks/csts.rake +72 -0
  357. data/tasks/gem.rake +14 -0
  358. data/tasks/manual.rake +10 -0
  359. data/tasks/missing.rake +21 -0
  360. data/tasks/rcov.rake +14 -0
  361. data/tasks/rdoc.rake +17 -0
  362. data/tasks/rexml_fix.rb +16 -0
  363. data/tasks/rexml_fix_19.rb +49 -0
  364. data/tasks/show.rake +21 -0
  365. data/tasks/stats.rake +25 -0
  366. data/tasks/test.rake +11 -0
  367. data/test/MessageChecker.rb +53 -0
  368. data/test/TestSuite/CSV-Reports/celltext-Reference.csv +14 -0
  369. data/test/TestSuite/CSV-Reports/celltext.tjp +7 -0
  370. data/test/TestSuite/CSV-Reports/genrefs +6 -0
  371. data/test/TestSuite/CSV-Reports/project-1.tji +57 -0
  372. data/test/TestSuite/CSV-Reports/resourcereport-Reference.csv +4 -0
  373. data/test/TestSuite/CSV-Reports/resourcereport.tjp +10 -0
  374. data/test/TestSuite/CSV-Reports/resourcereport_with_tasks-Reference.csv +22 -0
  375. data/test/TestSuite/CSV-Reports/resourcereport_with_tasks.tjp +11 -0
  376. data/test/TestSuite/CSV-Reports/sortByTree-Reference.csv +14 -0
  377. data/test/TestSuite/CSV-Reports/sortByTree.tjp +8 -0
  378. data/test/TestSuite/CSV-Reports/sortBy_duration.down-Reference.csv +14 -0
  379. data/test/TestSuite/CSV-Reports/sortBy_duration.down.tjp +10 -0
  380. data/test/TestSuite/CSV-Reports/sortBy_effort.up-Reference.csv +14 -0
  381. data/test/TestSuite/CSV-Reports/sortBy_effort.up.tjp +10 -0
  382. data/test/TestSuite/CSV-Reports/sortBy_plan.start.down-Reference.csv +14 -0
  383. data/test/TestSuite/CSV-Reports/sortBy_plan.start.down.tjp +10 -0
  384. data/test/TestSuite/CSV-Reports/taskreport-Reference.csv +14 -0
  385. data/test/TestSuite/CSV-Reports/taskreport.tjp +10 -0
  386. data/test/TestSuite/CSV-Reports/taskreport_with_resources-Reference.csv +24 -0
  387. data/test/TestSuite/CSV-Reports/taskreport_with_resources.tjp +11 -0
  388. data/test/TestSuite/Scheduler/Correct/Allocate.tjp +86 -0
  389. data/test/TestSuite/Scheduler/Correct/AutomaticMilestones.tjp +63 -0
  390. data/test/TestSuite/Scheduler/Correct/Booking.tjp +161 -0
  391. data/test/TestSuite/Scheduler/Correct/Depends.tjp +50 -0
  392. data/test/TestSuite/Scheduler/Correct/Duration.tjp +34 -0
  393. data/test/TestSuite/Scheduler/Correct/InheritStartEnd.tjp +129 -0
  394. data/test/TestSuite/Scheduler/Correct/Limits.tjp +81 -0
  395. data/test/TestSuite/Scheduler/Correct/MultipleMandatories.tjp +43 -0
  396. data/test/TestSuite/Scheduler/Correct/Optimize-1.tjp +28 -0
  397. data/test/TestSuite/Scheduler/Correct/Optimize-2.tjp +33 -0
  398. data/test/TestSuite/Scheduler/Correct/Optimize-3.tjp +33 -0
  399. data/test/TestSuite/Scheduler/Correct/Optimize-4.tjp +34 -0
  400. data/test/TestSuite/Scheduler/Correct/Optimize-5.tjp +62 -0
  401. data/test/TestSuite/Scheduler/Correct/Precedes.tjp +50 -0
  402. data/test/TestSuite/Scheduler/Correct/Shift.tjp +102 -0
  403. data/test/TestSuite/Scheduler/Errors/account_no_leaf.tjp +13 -0
  404. data/test/TestSuite/Scheduler/Errors/booking_conflict.tjp +10 -0
  405. data/test/TestSuite/Scheduler/Errors/booking_no_duty.tjp +9 -0
  406. data/test/TestSuite/Scheduler/Errors/booking_on_vacation.tjp +9 -0
  407. data/test/TestSuite/Scheduler/Errors/container_booking.tjp +14 -0
  408. data/test/TestSuite/Scheduler/Errors/container_duration.tjp +11 -0
  409. data/test/TestSuite/Scheduler/Errors/effort_no_allocations.tjp +7 -0
  410. data/test/TestSuite/Scheduler/Errors/loop_detected_1.tjp +19 -0
  411. data/test/TestSuite/Scheduler/Errors/loop_detected_10.tjp +36 -0
  412. data/test/TestSuite/Scheduler/Errors/loop_detected_11.tjp +27 -0
  413. data/test/TestSuite/Scheduler/Errors/loop_detected_12.tjp +20 -0
  414. data/test/TestSuite/Scheduler/Errors/loop_detected_13.tjp +27 -0
  415. data/test/TestSuite/Scheduler/Errors/loop_detected_14.tjp +26 -0
  416. data/test/TestSuite/Scheduler/Errors/loop_detected_2.tjp +24 -0
  417. data/test/TestSuite/Scheduler/Errors/loop_detected_3.tjp +18 -0
  418. data/test/TestSuite/Scheduler/Errors/loop_detected_4.tjp +36 -0
  419. data/test/TestSuite/Scheduler/Errors/loop_detected_5.tjp +37 -0
  420. data/test/TestSuite/Scheduler/Errors/loop_detected_6.tjp +35 -0
  421. data/test/TestSuite/Scheduler/Errors/loop_detected_7.tjp +46 -0
  422. data/test/TestSuite/Scheduler/Errors/loop_detected_8.tjp +51 -0
  423. data/test/TestSuite/Scheduler/Errors/loop_detected_9.tjp +20 -0
  424. data/test/TestSuite/Scheduler/Errors/maxend.tjp +8 -0
  425. data/test/TestSuite/Scheduler/Errors/maxstart.tjp +8 -0
  426. data/test/TestSuite/Scheduler/Errors/milestone_booking.tjp +10 -0
  427. data/test/TestSuite/Scheduler/Errors/milestone_duration.tjp +8 -0
  428. data/test/TestSuite/Scheduler/Errors/milestone_start_end.tjp +8 -0
  429. data/test/TestSuite/Scheduler/Errors/minend.tjp +8 -0
  430. data/test/TestSuite/Scheduler/Errors/minstart.tjp +8 -0
  431. data/test/TestSuite/Scheduler/Errors/multiple_durations.tjp +11 -0
  432. data/test/TestSuite/Scheduler/Errors/no_tasks.tjp +6 -0
  433. data/test/TestSuite/Scheduler/Errors/not_scheduled.tjp +8 -0
  434. data/test/TestSuite/Scheduler/Errors/task_depend_child.tjp +10 -0
  435. data/test/TestSuite/Scheduler/Errors/task_depend_multi.tjp +13 -0
  436. data/test/TestSuite/Scheduler/Errors/task_depend_parent.tjp +11 -0
  437. data/test/TestSuite/Scheduler/Errors/task_depend_self.tjp +10 -0
  438. data/test/TestSuite/Scheduler/Errors/task_depend_unknown.tjp +10 -0
  439. data/test/TestSuite/Scheduler/Errors/task_overspecified_1.tjp +9 -0
  440. data/test/TestSuite/Scheduler/Errors/task_overspecified_2.tjp +14 -0
  441. data/test/TestSuite/Scheduler/Errors/task_overspecified_3.tjp +14 -0
  442. data/test/TestSuite/Scheduler/Errors/task_underspecified_1.tjp +8 -0
  443. data/test/TestSuite/Scheduler/Errors/task_underspecified_2.tjp +8 -0
  444. data/test/TestSuite/Scheduler/Errors/task_underspecified_3.tjp +9 -0
  445. data/test/TestSuite/Syntax/Correct/Account.tjp +53 -0
  446. data/test/TestSuite/Syntax/Correct/Allocate-1.tjp +24 -0
  447. data/test/TestSuite/Syntax/Correct/Alternative.tjp +13 -0
  448. data/test/TestSuite/Syntax/Correct/AutoMacros.tjp +14 -0
  449. data/test/TestSuite/Syntax/Correct/Booking.tjp +26 -0
  450. data/test/TestSuite/Syntax/Correct/Caption.tjp +33 -0
  451. data/test/TestSuite/Syntax/Correct/Celltext.tjp +28 -0
  452. data/test/TestSuite/Syntax/Correct/Comments.tjp +29 -0
  453. data/test/TestSuite/Syntax/Correct/Complete.tjp +16 -0
  454. data/test/TestSuite/Syntax/Correct/CompletedWork.tji +20 -0
  455. data/test/TestSuite/Syntax/Correct/CriticalPath.tjp +31 -0
  456. data/test/TestSuite/Syntax/Correct/Currencyformat.tjp +12 -0
  457. data/test/TestSuite/Syntax/Correct/CustomAttributes.tjp +14 -0
  458. data/test/TestSuite/Syntax/Correct/Depends1.tjp +22 -0
  459. data/test/TestSuite/Syntax/Correct/Durations.tjp +29 -0
  460. data/test/TestSuite/Syntax/Correct/Efficiency.tjp +19 -0
  461. data/test/TestSuite/Syntax/Correct/Export.tjp +40 -0
  462. data/test/TestSuite/Syntax/Correct/Flags.tjp +32 -0
  463. data/test/TestSuite/Syntax/Correct/Freeze.tjp +28 -0
  464. data/test/TestSuite/Syntax/Correct/Gap.tjp +15 -0
  465. data/test/TestSuite/Syntax/Correct/HtmlTaskReport.tjp +33 -0
  466. data/test/TestSuite/Syntax/Correct/Limits-1.tjp +71 -0
  467. data/test/TestSuite/Syntax/Correct/LoadUnits.tjp +31 -0
  468. data/test/TestSuite/Syntax/Correct/Macro-1.tjp +19 -0
  469. data/test/TestSuite/Syntax/Correct/Mandatory.tjp +17 -0
  470. data/test/TestSuite/Syntax/Correct/Milestone.tjp +12 -0
  471. data/test/TestSuite/Syntax/Correct/MinMax.tjp +17 -0
  472. data/test/TestSuite/Syntax/Correct/Numberformat.tjp +12 -0
  473. data/test/TestSuite/Syntax/Correct/Period.tjp +16 -0
  474. data/test/TestSuite/Syntax/Correct/Persistent.tjp +11 -0
  475. data/test/TestSuite/Syntax/Correct/Precedes1.tjp +17 -0
  476. data/test/TestSuite/Syntax/Correct/Priority.tjp +30 -0
  477. data/test/TestSuite/Syntax/Correct/Project.tjp +21 -0
  478. data/test/TestSuite/Syntax/Correct/ProjectIDs.tjp +23 -0
  479. data/test/TestSuite/Syntax/Correct/RawHTML.tjp +29 -0
  480. data/test/TestSuite/Syntax/Correct/Reports.tjp +54 -0
  481. data/test/TestSuite/Syntax/Correct/Resource.tjp +20 -0
  482. data/test/TestSuite/Syntax/Correct/Responsible.tjp +16 -0
  483. data/test/TestSuite/Syntax/Correct/Scenario.tjp +15 -0
  484. data/test/TestSuite/Syntax/Correct/Scheduling.tjp +26 -0
  485. data/test/TestSuite/Syntax/Correct/Select.tjp +27 -0
  486. data/test/TestSuite/Syntax/Correct/Shift.tjp +55 -0
  487. data/test/TestSuite/Syntax/Correct/Simple.tjp +25 -0
  488. data/test/TestSuite/Syntax/Correct/String.tjp +12 -0
  489. data/test/TestSuite/Syntax/Correct/Supplement.tjp +24 -0
  490. data/test/TestSuite/Syntax/Correct/TaskRoot.tjp +34 -0
  491. data/test/TestSuite/Syntax/Correct/TimeFrame.tjp +19 -0
  492. data/test/TestSuite/Syntax/Correct/Timezone.tjp +8 -0
  493. data/test/TestSuite/Syntax/Correct/Vacation.tjp +33 -0
  494. data/test/TestSuite/Syntax/Correct/csvtest +16 -0
  495. data/test/TestSuite/Syntax/Correct/manual2example.rb +24 -0
  496. data/test/TestSuite/Syntax/Correct/tutorial.tjp +485 -0
  497. data/test/TestSuite/Syntax/Errors/bad_include.tjp +11 -0
  498. data/test/TestSuite/Syntax/Errors/booking_group.tjp +14 -0
  499. data/test/TestSuite/Syntax/Errors/booking_milestone.tjp +13 -0
  500. data/test/TestSuite/Syntax/Errors/booking_no_leaf.tjp +13 -0
  501. data/test/TestSuite/Syntax/Errors/chargeset.tjp +14 -0
  502. data/test/TestSuite/Syntax/Errors/chargeset_master.tjp +15 -0
  503. data/test/TestSuite/Syntax/Errors/container_attribute.tjp +13 -0
  504. data/test/TestSuite/Syntax/Errors/cost_acct_no_top.tjp +24 -0
  505. data/test/TestSuite/Syntax/Errors/cost_rev_same.tjp +24 -0
  506. data/test/TestSuite/Syntax/Errors/date_in_range.tjp +7 -0
  507. data/test/TestSuite/Syntax/Errors/effort_zero.tjp +8 -0
  508. data/test/TestSuite/Syntax/Errors/empty.tjp +1 -0
  509. data/test/TestSuite/Syntax/Errors/export_bad_extn.tjp +9 -0
  510. data/test/TestSuite/Syntax/Errors/extend_id_cap.tjp +7 -0
  511. data/test/TestSuite/Syntax/Errors/interval_end_in_range.tjp +7 -0
  512. data/test/TestSuite/Syntax/Errors/interval_start_in_range.tjp +7 -0
  513. data/test/TestSuite/Syntax/Errors/leaf_resource_id_expected.tjp +12 -0
  514. data/test/TestSuite/Syntax/Errors/misaligned_date.tjp +7 -0
  515. data/test/TestSuite/Syntax/Errors/no_csv_suffix.tjp +10 -0
  516. data/test/TestSuite/Syntax/Errors/no_html_suffix.tjp +10 -0
  517. data/test/TestSuite/Syntax/Errors/operand_attribute.tjp +11 -0
  518. data/test/TestSuite/Syntax/Errors/operand_unkn_flag.tjp +11 -0
  519. data/test/TestSuite/Syntax/Errors/operand_unkn_scen.tjp +11 -0
  520. data/test/TestSuite/Syntax/Errors/overtime_range.tjp +13 -0
  521. data/test/TestSuite/Syntax/Errors/purge_no_list.tjp +8 -0
  522. data/test/TestSuite/Syntax/Errors/purge_unknown_id.tjp +8 -0
  523. data/test/TestSuite/Syntax/Errors/report_end.tjp +10 -0
  524. data/test/TestSuite/Syntax/Errors/report_redifinition.tjp +10 -0
  525. data/test/TestSuite/Syntax/Errors/report_start.tjp +10 -0
  526. data/test/TestSuite/Syntax/Errors/resource_exists.tjp +7 -0
  527. data/test/TestSuite/Syntax/Errors/resource_id_expected.tjp +8 -0
  528. data/test/TestSuite/Syntax/Errors/rev_acct_no_top.tjp +24 -0
  529. data/test/TestSuite/Syntax/Errors/scenario_exists.tjp +7 -0
  530. data/test/TestSuite/Syntax/Errors/shift_assignment_overlap.tjp +15 -0
  531. data/test/TestSuite/Syntax/Errors/shift_exists.tjp +7 -0
  532. data/test/TestSuite/Syntax/Errors/shift_id_expected.tjp +7 -0
  533. data/test/TestSuite/Syntax/Errors/sloppy_range.tjp +13 -0
  534. data/test/TestSuite/Syntax/Errors/sort_direction.tjp +11 -0
  535. data/test/TestSuite/Syntax/Errors/sort_unknown_scen.tjp +11 -0
  536. data/test/TestSuite/Syntax/Errors/sorting_crit_exptd1.tjp +11 -0
  537. data/test/TestSuite/Syntax/Errors/sorting_crit_exptd2.tjp +11 -0
  538. data/test/TestSuite/Syntax/Errors/sorting_wbs.tjp +11 -0
  539. data/test/TestSuite/Syntax/Errors/start_before_end1.tjp +7 -0
  540. data/test/TestSuite/Syntax/Errors/start_before_end2.tjp +6 -0
  541. data/test/TestSuite/Syntax/Errors/task_complete.tjp +8 -0
  542. data/test/TestSuite/Syntax/Errors/task_exists.tjp +7 -0
  543. data/test/TestSuite/Syntax/Errors/task_priority.tjp +8 -0
  544. data/test/TestSuite/Syntax/Errors/task_without_chargeset.tjp +9 -0
  545. data/test/TestSuite/Syntax/Errors/time_interval.tjp +12 -0
  546. data/test/TestSuite/Syntax/Errors/too_many_bangs.tjp +10 -0
  547. data/test/TestSuite/Syntax/Errors/undecl_flag.tjp +6 -0
  548. data/test/TestSuite/Syntax/Errors/unknown_projectid.tjp +7 -0
  549. data/test/TestSuite/Syntax/Errors/unknown_scenario_id.tjp +6 -0
  550. data/test/TestSuite/Syntax/Errors/unknown_scenario_idx.tjp +11 -0
  551. data/test/TestSuite/Syntax/Errors/unknown_task.tjp +10 -0
  552. data/test/all.rb +31 -0
  553. data/test/test_BatchProcessor.rb +54 -0
  554. data/test/test_CSV-Reports.rb +101 -0
  555. data/test/test_Limits.rb +104 -0
  556. data/test/test_LogicalExpression.rb +110 -0
  557. data/test/test_MacroTable.rb +51 -0
  558. data/test/test_Project.rb +57 -0
  559. data/test/test_PropertySet.rb +71 -0
  560. data/test/test_Query.rb +83 -0
  561. data/test/test_RealFormat.rb +83 -0
  562. data/test/test_RichText.rb +869 -0
  563. data/test/test_Scheduler.rb +42 -0
  564. data/test/test_ShiftAssignments.rb +77 -0
  565. data/test/test_Syntax.rb +41 -0
  566. data/test/test_TextScanner.rb +95 -0
  567. data/test/test_TjTime.rb +114 -0
  568. data/test/test_TjpExample.rb +169 -0
  569. data/test/test_UTF8String.rb +84 -0
  570. data/test/test_WorkingHours.rb +56 -0
  571. metadata +649 -0
@@ -0,0 +1,227 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: UTF-8
3
+ #
4
+ # = Query.rb -- The TaskJuggler III Project Management Software
5
+ #
6
+ # Copyright (c) 2006, 2007, 2008, 2009 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 'TjException'
14
+
15
+ class TaskJuggler
16
+
17
+ # A query can be used to retrieve any property attribute after the scheduling
18
+ # run has been completed. It is possible to make a Query before the scheduling
19
+ # run has been completed, but it only produces good results for static
20
+ # attributes. And for such queries, the PropertyTreeNode.get and [] functions
21
+ # are a lot more efficient.
22
+ # # When constructing a Query, a set of variables need to be set that is
23
+ # sufficient enough to identify a unique attribute. Some attribute are
24
+ # computed dynamically and further variables such as a start and end time will
25
+ # be incorporated into the result computation.
26
+ #
27
+ # The result is returned as String (Query#result), in numerical form
28
+ # (Query#numericalResult) if available as number, and as an entity that can be
29
+ # used for sorting (Query#sortableResult). To get the result, Query#process
30
+ # needs to be called. In case an error occured, Query#ok is set to false and
31
+ # Query#errorMessage contains an error message.
32
+ class Query
33
+
34
+ attr_accessor :project, :propertyType, :propertyId, :property,
35
+ :scopePropertyType, :scopePropertyId, :scopeProperty,
36
+ :attributeId, :scenarioIdx, :start, :end, :startIdx, :endIdx,
37
+ :numberFormat, :currencyFormat, :costAccount, :revenueAccount,
38
+ :loadUnit,
39
+ :result, :numericalResult, :sortableResult, :ok, :errorMessage
40
+
41
+ # Create a new Query object. The _parameters_ need to be sufficent to
42
+ # uniquely identify an attribute.
43
+ def initialize(parameters = { })
44
+ ps = %w( project propertyType propertyId property scopePropertyId
45
+ scopeProperty attributeId scenarioIdx start end startIdx endIdx
46
+ loadUnit numberFormat currencyFormat costAccount revenueAccount)
47
+ ps.each do |p|
48
+ instance_variable_set('@' + p, parameters[p] ? parameters[p] : nil)
49
+ end
50
+
51
+ reset
52
+ end
53
+
54
+ # Queries object can be reused. Calling this function will clear the query
55
+ # result data.
56
+ def reset
57
+ @result = nil
58
+ @numericalResult = nil
59
+ @sortableResult = nil
60
+ @loadUnit = :days
61
+ @ok = nil
62
+ @errorMessage = nil
63
+ end
64
+
65
+ # This method tries to resolve the query and return a result. In case it
66
+ # finds an attribute that matches the query, it returns true; false
67
+ # otherwise. The actual result data is put into the Query object.
68
+ def process
69
+ begin
70
+ # Resolve property reference from property ID.
71
+ if !@property.nil? && !@propertyId.nil?
72
+ @property = resolvePropertyId(@propertyType, @propertyId)
73
+ end
74
+ # Same for the scope property.
75
+ if !@scopeProperty.nil? && !@scopePropertyId.nil?
76
+ @scopeProperty = resolvePropertyId(@scopePropertyType, @scopePropertyId)
77
+ end
78
+ # Make sure the have a reference to the project.
79
+ @project = @property.project unless @project
80
+
81
+ @startIdx = @project.dateToIdx(@start, true) if @startIdx.nil? && @start
82
+ @endIdx = @project.dateToIdx(@end, true) - 1 if @endIdx.nil? && @end
83
+
84
+ if @property.hasQuery?(@attributeId, @scenarioIdx)
85
+ # Call the property query function to get the result.
86
+ if @scenarioIdx
87
+ @property.send('query_' + @attributeId, scenarioIdx, self)
88
+ else
89
+ @property.send('query_' + @attributeId, self)
90
+ end
91
+ else
92
+ # There is no query function. We simply use the property attribute
93
+ # value.
94
+ @sortableResult =
95
+ if @scenarioIdx
96
+ @property[@attributeId, @scenarioIdx]
97
+ else
98
+ @property.get(@attributeId)
99
+ end
100
+ if @sortableResult.is_a?(Array)
101
+ # This ugly special case is needed for custom attributes of type
102
+ # reference.
103
+ @sortableResult = @sortableResult[0]
104
+ end
105
+ @result = @sortableResult.to_s
106
+ @numericalResult = @result if @result.is_a?(Fixnum) or
107
+ @result.is_a?(Float)
108
+ end
109
+ rescue TjException
110
+ @errorMessage = $!
111
+ @result = ''
112
+ return @ok = false
113
+ end
114
+ @ok = true
115
+ end
116
+
117
+ # Convert a duration to the format specified by @loadUnit. _work_ is the
118
+ # effort in man days. The return value is the converted value with optional
119
+ # unit as a String.
120
+ def scaleDuration(value)
121
+ scaleValue(value, [ 24 * 60, 24, 1, 1.0 / 7, 1.0 / 30.42, 1.0 / 365 ])
122
+ end
123
+
124
+ # Convert a load or effort value to the format specified by @loadUnit.
125
+ # _work_ is the effort in man days. The return value is the converted value
126
+ # with optional unit as a String.
127
+ def scaleLoad(value)
128
+ scaleValue(value, [ @project.dailyWorkingHours * 60,
129
+ @project.dailyWorkingHours,
130
+ 1.0,
131
+ 1.0 / @project.weeklyWorkingDays,
132
+ 1.0 / @project.monthlyWorkingDays,
133
+ 1.0 / @project.yearlyWorkingDays ])
134
+ end
135
+
136
+ private
137
+
138
+ def resolvePropertyId(pType, pId)
139
+ unless @project
140
+ raise TjException.new, "Need Project reference to process the query"
141
+ end
142
+ case pType
143
+ when :Account
144
+ @project.account[pId]
145
+ when :Task
146
+ @project.task[pId]
147
+ when:Resource
148
+ @project.resource[pId]
149
+ else
150
+ raise TjException.new, "Unknown property type #{pType}"
151
+ end
152
+ end
153
+
154
+ # This function converts number to strings that may include a unit. The
155
+ # unit is determined by @loadUnit. In the automatic modes, the shortest
156
+ # possible result is shown and the unit is always appended. _value_ is the
157
+ # value to convert. _factors_ determines the conversion factors for the
158
+ # different units.
159
+ def scaleValue(value, factors)
160
+ if @loadUnit == :shortauto || @loadUnit == :longauto
161
+ # We try all possible units and store the resulting strings here.
162
+ options = []
163
+ # For each option we also save the delta between the String value and
164
+ # the original value.
165
+ delta = []
166
+ # For each of the units we can define a maximum value that the value
167
+ # should not exceed. nil means no limit.
168
+ max = [ 60, 48, nil, 8, 24, nil ]
169
+
170
+ i = 0
171
+ factors.each do |factor|
172
+ scaledValue = value * factor
173
+ str = @numberFormat.format(scaledValue)
174
+ delta[i] = ((scaledValue - str.to_f).abs * 1000).to_i
175
+ # We ignore results that are 0 or exceed the maximum. To ensure that
176
+ # we have at least one result the unscaled value is always taken.
177
+ if (factor != 1.0 && /^[0.]*$/ =~ str) ||
178
+ (max[i] && scaledValue > max[i])
179
+ options << nil
180
+ else
181
+ options << str
182
+ end
183
+ i += 1
184
+ end
185
+
186
+ # Find the value that is the closest to the original value. This will be
187
+ # the default if all values have the same length.
188
+ shortest = 2
189
+ delta.length.times do |j|
190
+ shortest = j if options[j] && options[j][0, 2] != '0.' &&
191
+ delta[j] <= delta[shortest]
192
+ end
193
+
194
+ # Find the shortest option.
195
+ 6.times do |j|
196
+ shortest = j if options[j] && options[j][0, 2] != '0.' &&
197
+ options[j].length < options[shortest].length
198
+ end
199
+
200
+ str = options[shortest]
201
+ if @loadUnit == :longauto
202
+ # For the long units we handle singular and plural properly. For
203
+ # English we just need to append an 's', but this code will work for
204
+ # other languages as well.
205
+ units = []
206
+ if str == "1"
207
+ units = %w( minute hour day week month year )
208
+ else
209
+ units = %w( minutes hours days weeks months years )
210
+ end
211
+ str += ' ' + units[shortest]
212
+ else
213
+ str += %w( min h d w m y )[shortest]
214
+ end
215
+ else
216
+ # For fixed units we just need to do the conversion. No unit is
217
+ # included.
218
+ units = [ :minutes, :hours, :days, :weeks, :months, :years ]
219
+ str = @numberFormat.format(value * factors[units.index(@loadUnit)])
220
+ end
221
+ str
222
+ end
223
+
224
+ end
225
+
226
+ end
227
+
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: UTF-8
3
+ #
4
+ # = RealFormat.rb -- The TaskJuggler III Project Management Software
5
+ #
6
+ # Copyright (c) 2006, 2007, 2008, 2009 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
+ class TaskJuggler
14
+
15
+ # This class provides the functionality to format a Float according to certain
16
+ # rules. These rules determine how negative values are represented, how the
17
+ # fractional part is shown and how to structure the mantissa. The result is
18
+ # always a String.
19
+ class RealFormat
20
+
21
+ # Create a new RealFormat object and define the formating rules.
22
+ def initialize(args)
23
+ # Prefix used for negative numbers. (String)
24
+ @signPrefix = args[0]
25
+ # Suffix used for negative numbers. (String)
26
+ @signSuffix = args[1]
27
+ # Separator used after 3 integer digits. (String)
28
+ @thousandsSeparator = args[2]
29
+ # Separator used between the inter part and the fractional part. (String)
30
+ @fractionSeparator = args[3]
31
+ # Number of fractional digits to show. (Fixnum)
32
+ @fractionDigits = args[4]
33
+ end
34
+
35
+ # Converts the Float _number_ into a String representation according to the
36
+ # formating rules.
37
+ def format(number)
38
+ # Check for negative number. Continue with the absolute part.
39
+ if number < 0
40
+ negate = true
41
+ number = -number
42
+ else
43
+ negate = false
44
+ end
45
+
46
+ # Determine the integer part.
47
+ intNumber = (number * (10 ** @fractionDigits)).round.to_i.to_s
48
+ if intNumber.length <= @fractionDigits
49
+ intNumber = '0' * (@fractionDigits - intNumber.length + 1) + intNumber
50
+ end
51
+ intPart = intNumber[0..-(@fractionDigits + 1)]
52
+ fracPart =
53
+ @fractionDigits > 0 ? '.' + intNumber[-(@fractionDigits)..-1] : ''
54
+
55
+ if @thousandsSeparator.empty?
56
+ out = intPart
57
+ else
58
+ out = ''
59
+ 1.upto(intPart.length) do |i|
60
+ out = intPart[-i, 1] + out
61
+ out = @thousandsSeparator + out if i % 3 == 0 && i < intPart.length
62
+ end
63
+ end
64
+ out += fracPart
65
+ # Now compose the result.
66
+ out = @signPrefix + out + @signSuffix if negate
67
+ out
68
+ end
69
+
70
+ end
71
+
72
+ end
73
+
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: UTF-8
3
+ #
4
+ # = Resource.rb -- The TaskJuggler III Project Management Software
5
+ #
6
+ # Copyright (c) 2006, 2007, 2008, 2009 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
+
14
+ require 'PropertyTreeNode'
15
+ require 'ResourceScenario'
16
+
17
+ class TaskJuggler
18
+
19
+ class Resource < PropertyTreeNode
20
+
21
+ def initialize(project, id, name, parent)
22
+ super(project.resources, id, name, parent)
23
+ project.addResource(self)
24
+
25
+ @data = Array.new(@project.scenarioCount, nil)
26
+ @project.scenarioCount.times do |i|
27
+ @data[i] = ResourceScenario.new(self, i, @scenarioAttributes[i])
28
+ end
29
+ end
30
+
31
+ # Many Resource functions are scenario specific. These functions are
32
+ # provided by the class ResourceScenario. In case we can't find a
33
+ # function called for the Resource class we try to find it in
34
+ # ResourceScenario.
35
+ def method_missing(func, scenarioIdx, *args)
36
+ @data[scenarioIdx].method(func).call(*args)
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+
@@ -0,0 +1,511 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: UTF-8
3
+ #
4
+ # = ResourceScenario.rb -- The TaskJuggler III Project Management Software
5
+ #
6
+ # Copyright (c) 2006, 2007, 2008, 2009 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
+
14
+ require 'ScenarioData'
15
+
16
+ class TaskJuggler
17
+
18
+ class ResourceScenario < ScenarioData
19
+
20
+ def initialize(resource, scenarioIdx, attributes)
21
+ super
22
+
23
+ # The scoreboard entries are either nil, a number or a task reference. nil
24
+ # means the slot is unassigned. The task reference means assigned to this
25
+ # task. The numbers have the following values:
26
+ # 1: Off hour
27
+ # 2: Vacation
28
+ # The scoreboard is only created when needed to save memory for projects
29
+ # which read-in the coporate employee database but only need a small
30
+ # subset.
31
+ @scoreboard = nil
32
+
33
+ @firstBookedSlot = nil
34
+ @lastBookedSlot = nil
35
+ end
36
+
37
+ # This method must be called at the beginning of each scheduling run. It
38
+ # initializes variables used during the scheduling process.
39
+ def prepareScheduling
40
+ @property['effort', @scenarioIdx] = 0
41
+ initScoreboard
42
+ end
43
+
44
+ # The criticalness of a resource is a measure for the probabilty that all
45
+ # allocations can be fullfilled. The smaller the value, the more likely
46
+ # will the tasks get the resource. A value above 1.0 means that
47
+ # statistically some tasks will not get their resources. A value between
48
+ # 0 and 1 implies no guarantee, though.
49
+ def calcCriticalness
50
+ if @scoreboard.nil?
51
+ # Resources that are not allocated are not critical at all.
52
+ @property['criticalness', @scenarioIdx] = 0.0
53
+ else
54
+ freeSlots = 0
55
+ @scoreboard.each do |slot|
56
+ freeSlots += 1 if slot.nil?
57
+ end
58
+ @property['criticalness', @scenarioIdx] = freeSlots == 0 ? 1.0 :
59
+ a('alloctdeffort') / freeSlots
60
+ end
61
+ end
62
+
63
+ # Returns true if the resource is available at the time specified by
64
+ # _sbIdx_.
65
+ def available?(sbIdx)
66
+ return false unless @scoreboard[sbIdx].nil?
67
+
68
+ limits = a('limits')
69
+ return false if limits && !limits.ok?(@scoreboard.idxToDate(sbIdx))
70
+
71
+ true
72
+ end
73
+
74
+ # Return true if the resource is booked for a tasks at the time specified by
75
+ # _sbIdx_.
76
+ def booked?(sbIdx)
77
+ @scoreboard[sbIdx].is_a?(Task)
78
+ end
79
+
80
+ # Book the slot indicated by the scoreboard index +sbIdx+ for Task +task+.
81
+ # If +force+ is true, overwrite the existing booking for this slot. The
82
+ # method returns true if the slot was available.
83
+ def book(sbIdx, task, force = false)
84
+ return false if !force && !available?(sbIdx)
85
+
86
+ #puts "Booking resource #{@property.fullId} at " +
87
+ # "#{@scoreboard.idxToDate(sbIdx)}/#{sbIdx} for task #{task.fullId}\n"
88
+ @scoreboard[sbIdx] = task
89
+ # Track the total allocated slots for this resource and all parent
90
+ # resources.
91
+ t = @property
92
+ while t
93
+ t['effort', @scenarioIdx] += 1
94
+ t = t.parent
95
+ end
96
+ a('limits').inc(@scoreboard.idxToDate(sbIdx)) if a('limits')
97
+
98
+ # Make sure the task is in the list of duties.
99
+ @property['duties', @scenarioIdx] << task unless a('duties').include?(task)
100
+
101
+ if @firstBookedSlot.nil? || @firstBookedSlot > sbIdx
102
+ @firstBookedSlot = sbIdx
103
+ end
104
+ if @lastBookedSlot.nil? || @lastBookedSlot < sbIdx
105
+ @lastBookedSlot = sbIdx
106
+ end
107
+ true
108
+ end
109
+
110
+ def bookBooking(sbIdx, booking)
111
+ initScoreboard if @scoreboard.nil?
112
+
113
+ unless @scoreboard[sbIdx].nil?
114
+ if booked?(sbIdx)
115
+ error('booking_conflict',
116
+ "Resource #{@property.fullId} has multiple conflicting " +
117
+ "bookings for #{@scoreboard.idxToDate(sbIdx)}. The " +
118
+ "conflicting tasks are #{@scoreboard[sbIdx].fullId} and " +
119
+ "#{booking.task.fullId}.", true, booking.sourceFileInfo)
120
+ end
121
+ if @scoreboard[sbIdx] > booking.overtime
122
+ if @scoreboard[sbIdx] == 1 && booking.sloppy == 0
123
+ error('booking_no_duty',
124
+ "Resource #{@property.fullId} has no duty at " +
125
+ "#{@scoreboard.idxToDate(sbIdx)}.", true,
126
+ booking.sourceFileInfo)
127
+ end
128
+ if @scoreboard[sbIdx] == 2 && booking.sloppy <= 1
129
+ error('booking_on_vacation',
130
+ "Resource #{@property.fullId} is on vacation at " +
131
+ "#{@scoreboard.idxToDate(sbIdx)}.", true,
132
+ booking.sourceFileInfo)
133
+ end
134
+ return false
135
+ end
136
+ end
137
+
138
+ book(sbIdx, booking.task, true)
139
+ end
140
+
141
+ # Compute the cost generated by this Resource for a given Account during a
142
+ # given interval. If a Task is provided as scopeProperty only the turnover
143
+ # directly assiciated with the Task is taken into account.
144
+ def query_cost(query)
145
+ if query.costAccount
146
+ query.sortableResult = query.numericalResult =
147
+ turnover(query.startIdx, query.endIdx, query.costAccount,
148
+ query.scopeProperty)
149
+ query.result = query.currencyFormat.format(query.sortableResult)
150
+ else
151
+ query.result = 'No cost account'
152
+ end
153
+ end
154
+
155
+ # The effort allocated to the Resource in the specified interval. In case a
156
+ # Task is given as scope property only the effort allocated to this Task is
157
+ # taken into account.
158
+ def query_effort(query)
159
+ query.sortableResult = query.numericalResult =
160
+ getEffectiveWork(query.startIdx, query.endIdx, query.scopeProperty)
161
+ query.result = query.scaleLoad(query.sortableResult)
162
+ end
163
+
164
+ # The unallocated effort of the Resource in the specified interval.
165
+ def query_freework(query)
166
+ query.sortableResult = query.numericalResult =
167
+ getEffectiveFreeWork(query.startIdx, query.endIdx)
168
+ query.result = query.scaleLoad(query.sortableResult)
169
+ end
170
+
171
+ # Get the rate of the resource.
172
+ def query_rate(query)
173
+ query.sortableResult = query.numericalResult = rate
174
+ query.result = query.currencyFormat.format(query.sortableResult)
175
+ end
176
+
177
+ # Compute the revenue generated by this Resource for a given Account during
178
+ # a given interval. If a Task is provided as scopeProperty only the
179
+ # revenue directly associated to this Task is taken into account.
180
+ def query_revenue(query)
181
+ if query.revenueAccount
182
+ query.sortableResult = query.numericalResult =
183
+ turnover(query.startIdx, query.endIdx, query.revenueAccount,
184
+ query.scopeProperty)
185
+ query.result = query.currencyFormat.format(query.sortableResult)
186
+ else
187
+ query.result = 'No revenue account'
188
+ end
189
+ end
190
+
191
+ # Returns the work of the resource (and its children) weighted by their
192
+ # efficiency.
193
+ def getEffectiveWork(startIdx, endIdx, task = nil)
194
+ # Convert the interval dates to indexes if needed.
195
+ startIdx = @project.dateToIdx(startIdx, true) if startIdx.is_a?(TjTime)
196
+ endIdx = @project.dateToIdx(endIdx, true) if endIdx.is_a?(TjTime)
197
+
198
+ work = 0.0
199
+ if @property.container?
200
+ @property.children.each do |resource|
201
+ work += resource.getEffectiveWork(@scenarioIdx, startIdx, endIdx, task)
202
+ end
203
+ else
204
+ return 0.0 if @scoreboard.nil?
205
+
206
+ work = @project.convertToDailyLoad(
207
+ getAllocatedSlots(startIdx, endIdx, task) *
208
+ @project['scheduleGranularity']) * a('efficiency')
209
+ end
210
+ work
211
+ end
212
+
213
+ # Returns the allocated work of the resource (and its children).
214
+ def getAllocatedWork(startIdx, endIdx, task = nil)
215
+ # Convert the interval dates to indexes if needed.
216
+ startIdx = @project.dateToIdx(startIdx, true) if startIdx.is_a?(TjTime)
217
+ endIdx = @project.dateToIdx(endIdx, true) if endIdx.is_a?(TjTime)
218
+
219
+ work = 0.0
220
+ if @property.container?
221
+ @property.children.each do |resource|
222
+ work += resource.getAllocatedWork(@scenarioIdx, startIdx, endIdx, task)
223
+ end
224
+ else
225
+ return 0.0 if @scoreboard.nil?
226
+
227
+ work = @project.convertToDailyLoad(
228
+ getAllocatedSlots(startIdx, endIdx, task) *
229
+ @project['scheduleGranularity'])
230
+ end
231
+ work
232
+ end
233
+
234
+ # Returns the allocated accumulated time of this resource and its children.
235
+ def getAllocatedTime(startIdx, endIdx, task = nil)
236
+ # Convert the interval dates to indexes if needed.
237
+ startIdx = @project.dateToIdx(startIdx, true) if startIdx.is_a?(TjTime)
238
+ endIdx = @project.dateToIdx(endIdx, true) if endIdx.is_a?(TjTime)
239
+
240
+ time = 0
241
+ if @property.container?
242
+ @property.children.each do |resource|
243
+ time += resource.getAllocatedWork(@scenarioIdx, startIdx, endIdx, task)
244
+ end
245
+ else
246
+ return 0 if @scoreboard.nil?
247
+
248
+ time = @project.convertToDailyLoad(@project['scheduleGranularity'] *
249
+ getAllocatedSlots(startIdx, endIdx, task))
250
+ end
251
+ time
252
+ end
253
+
254
+ # Return the unallocated work of the resource and its children wheighted by
255
+ # their efficiency.
256
+ def getEffectiveFreeWork(startIdx, endIdx)
257
+ # Convert the interval dates to indexes if needed.
258
+ startIdx = @project.dateToIdx(startIdx, true) if startIdx.is_a?(TjTime)
259
+ endIdx = @project.dateToIdx(endIdx, true) if endIdx.is_a?(TjTime)
260
+
261
+ work = 0.0
262
+ if @property.container?
263
+ @property.children.each do |resource|
264
+ work += resource.getEffectiveFreeWork(@scenarioIdx, startIdx, endIdx)
265
+ end
266
+ else
267
+ initScoreboard if @scoreboard.nil?
268
+
269
+ work = @project.convertToDailyLoad(
270
+ getFreeSlots(startIdx, endIdx) *
271
+ @project['scheduleGranularity']) * a('efficiency')
272
+ end
273
+ work
274
+ end
275
+
276
+ def turnover(startIdx, endIdx, account, task = nil)
277
+ amount = 0.0
278
+ if @property.container?
279
+ @property.children.each do |child|
280
+ amount += child.turnover(@scenarioIdx, startIdx, endIdx, account, task)
281
+ end
282
+ else
283
+ a('duties').each do |duty|
284
+ amount += duty.turnover(@scenarioIdx, startIdx, endIdx, account,
285
+ @property)
286
+ end
287
+ end
288
+
289
+ amount
290
+ end
291
+
292
+ # Returns the cost for using this resource during the specified Interval
293
+ # _period_. If a Task _task_ is provided, only the work on this particular
294
+ # task is considered.
295
+ def cost(startIdx, endIdx, task = nil)
296
+ getAllocatedTime(startIdx, endIdx, task) * a('rate')
297
+ end
298
+
299
+ # Returns true if the resource or any of its children is allocated during
300
+ # the period specified with the Interval _iv_. If task is not nil
301
+ # only allocations to this tasks are respected.
302
+ def allocated?(iv, task = nil)
303
+ initScoreboard if @scoreboard.nil?
304
+
305
+ startIdx = @scoreboard.dateToIdx(iv.start, true)
306
+ endIdx = @scoreboard.dateToIdx(iv.end, true)
307
+
308
+ startIdx = @firstBookedSlot if @firstBookedSlot &&
309
+ startIdx < @firstBookedSlot
310
+ endIdx = @lastBookedSlot + 1 if @lastBookedSlot &&
311
+ endIdx < @lastBookedSlot + 1
312
+ return false if startIdx > endIdx
313
+
314
+ return allocatedSub(startIdx, endIdx, task)
315
+ end
316
+
317
+ # Iterate over the scoreboard and turn its content into a set of Bookings.
318
+ def getBookings
319
+ return {} if @property.container? || @scoreboard.nil? ||
320
+ @firstBookedSlot.nil? || @lastBookedSlot.nil?
321
+
322
+ bookings = {}
323
+ lastTask = nil
324
+ bookingStart = nil
325
+
326
+ # To speedup the collection we start with the first booked slot and end
327
+ # with the last booked slot.
328
+ startIdx = @firstBookedSlot
329
+ endIdx = @lastBookedSlot + 1
330
+
331
+ # In case the index markers are still uninitialized, we have no bookings.
332
+ return [] if startIdx.nil? || endIdx.nil?
333
+
334
+ startIdx.upto(endIdx - 1) do |idx|
335
+ task = @scoreboard[idx]
336
+ # Now we watch for task changes.
337
+ if task != lastTask || (lastTask == nil && task.is_a?(Task)) ||
338
+ (task.is_a?(Task) && idx == endIdx - 1)
339
+ unless lastTask.nil?
340
+ # If we don't have a Booking for the task yet, we create one.
341
+ if bookings[lastTask].nil?
342
+ bookings[lastTask] = Booking.new(@property, lastTask, [])
343
+ end
344
+
345
+ # Make sure the index is correct even for the last task block.
346
+ idx += 1 if idx == endIdx - 1
347
+ # Append the new interval to the Booking.
348
+ bookings[lastTask].intervals <<
349
+ Interval.new(@scoreboard.idxToDate(bookingStart),
350
+ @scoreboard.idxToDate(idx))
351
+ end
352
+ # Get ready for the next task booking interval
353
+ if task.is_a?(Task)
354
+ lastTask = task
355
+ bookingStart = idx
356
+ else
357
+ lastTask = bookingStart = nil
358
+ end
359
+ end
360
+ end
361
+ bookings
362
+ end
363
+
364
+ # Return a list of scoreboard intervals that are at least _minDuration_ long
365
+ # and contain only 1 and 2. These values determine off-hours of the
366
+ # resource. The result is an Array of [ start, end ] TjTime values.
367
+ def collectTimeOffIntervals(iv, minDuration)
368
+ initScoreboard if @scoreboard.nil?
369
+
370
+ @scoreboard.collectTimeOffIntervals(iv, minDuration, [ 1, 2 ])
371
+ end
372
+
373
+ private
374
+
375
+ def initScoreboard
376
+ # Create scoreboard and mark all slots as unavailable
377
+ @scoreboard = Scoreboard.new(@project['start'], @project['end'],
378
+ @project['scheduleGranularity'], 1)
379
+
380
+ # We'll need this frequently and can savely cache it here.
381
+ @shifts = a('shifts')
382
+ @workinghours = a('workinghours')
383
+
384
+ # Change all work time slots to nil (available) again.
385
+ date = @scoreboard.idxToDate(0)
386
+ delta = @project['scheduleGranularity']
387
+ @project.scoreboardSize.times do |i|
388
+ @scoreboard[i] = nil if onShift?(date)
389
+ date += delta
390
+ end
391
+
392
+ # Mark all resource specific vacation slots as such (2)
393
+ a('vacations').each do |vacation|
394
+ startIdx = @scoreboard.dateToIdx(vacation.start, true)
395
+ endIdx = @scoreboard.dateToIdx(vacation.end, true)
396
+ startIdx.upto(endIdx - 1) do |i|
397
+ @scoreboard[i] = 2
398
+ end
399
+ end
400
+
401
+ # Mark all global vacation slots as such (2)
402
+ @project['vacations'].each do |vacation|
403
+ startIdx = @scoreboard.dateToIdx(vacation.start, true)
404
+ endIdx = @scoreboard.dateToIdx(vacation.end, true)
405
+ startIdx.upto(endIdx - 1) do |i|
406
+ @scoreboard[i] = 2
407
+ end
408
+ end
409
+
410
+ unless @shifts.nil?
411
+ # Mark the vacations from all the shifts the resource is assigned to.
412
+ @project.scoreboardSize.times do |i|
413
+ v = @shifts.getSbSlot(@scoreboard.idxToDate(i))
414
+ # Check if the vacation replacement bit is set. In that case we copy
415
+ # the while interval over to the resource scoreboard overriding any
416
+ # global vacations.
417
+ if (v & (1 << 8)) > 0
418
+ # The ShiftAssignments scoreboard and the ResourceScenario scoreboard
419
+ # unfortunately can't use the same values for a certain meaning. So,
420
+ # we have to use a map to translate the values.
421
+ map = [ nil, nil, 1, 2 ]
422
+ @scoreboard[i] = map[v & 0xFF]
423
+ elsif (v & 0xFF) == 3
424
+ # 3 in ShiftAssignments means 2 in ResourceScenario (on vacation)
425
+ @scoreboard[i] = 2
426
+ end
427
+ end
428
+ end
429
+ end
430
+
431
+ def onShift?(date)
432
+ # The more redable but slower form would be:
433
+ # if @shifts.assigned?(date)
434
+ # return @shifts.onShift?(date)
435
+ # else
436
+ # @workinghours.onShift?(date)
437
+ # end
438
+ if @shifts && (v = (@shifts.getSbSlot(date) & 0xFF)) > 0
439
+ v == 1
440
+ else
441
+ @workinghours.onShift?(date)
442
+ end
443
+ end
444
+
445
+ # Count the booked slots between the start and end index. If _task_ is not
446
+ # nil count only those slots that are assigned to this particular task.
447
+ def getAllocatedSlots(startIdx, endIdx, task)
448
+ # To speedup the counting we start with the first booked slot and end
449
+ # with the last booked slot.
450
+ startIdx = @firstBookedSlot if @firstBookedSlot &&
451
+ startIdx < @firstBookedSlot
452
+ endIdx = @lastBookedSlot + 1 if @lastBookedSlot &&
453
+ endIdx > @lastBookedSlot + 1
454
+
455
+ bookedSlots = 0
456
+ startIdx.upto(endIdx - 1) do |idx|
457
+ if (task.nil? && @scoreboard[idx].is_a?(Task)) ||
458
+ (task && @scoreboard[idx] == task)
459
+ bookedSlots += 1
460
+ end
461
+ end
462
+
463
+ bookedSlots
464
+ end
465
+
466
+ # Count the free slots between the start and end index.
467
+ def getFreeSlots(startIdx, endIdx)
468
+ freeSlots = 0
469
+ startIdx.upto(endIdx - 1) do |idx|
470
+ freeSlots += 1 if @scoreboard[idx].nil?
471
+ end
472
+
473
+ freeSlots
474
+ end
475
+
476
+ # Returns true if the resource or any of its children is allocated during
477
+ # the period specified with _startIdx_ and _endIdx_. If task is not nil
478
+ # only allocations to this tasks are respected.
479
+ def allocatedSub(startIdx, endIdx, task)
480
+ if @property.container?
481
+ @property.children.each do |resource|
482
+ return true if resource.allocatedSub(@scenarioIdx, startIdx, endIdx,
483
+ task)
484
+ end
485
+ else
486
+ return false unless a('duties').include?(task)
487
+
488
+ startIdx.upto(endIdx - 1) do |idx|
489
+ return true if @scoreboard[idx] == task
490
+ end
491
+ end
492
+ false
493
+ end
494
+
495
+ # Return the daily cost of a resource or resource group.
496
+ def rate
497
+ if @property.container?
498
+ dailyRate = 0.0
499
+ @property.children.each do |resource|
500
+ dailyRate += resource.rate(@scenarioIdx)
501
+ end
502
+ dailyRate
503
+ else
504
+ a('rate')
505
+ end
506
+ end
507
+
508
+ end
509
+
510
+ end
511
+