taskjuggler 3.1.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (410) hide show
  1. data/CHANGELOG +44 -0
  2. data/bin/tj3webd +4 -0
  3. data/data/css/tjreport.css +14 -5
  4. data/data/tjp.vim +22 -7
  5. data/examples/Fedora-20/reports.tji +2 -4
  6. data/examples/Scrum/Product Burndown.csv +26 -0
  7. data/examples/Scrum/Sprint 1 Burndown.csv +26 -0
  8. data/examples/Scrum/Sprint 2 Burndown.csv +26 -0
  9. data/examples/Scrum/Sprint 3 Burndown.csv +26 -0
  10. data/examples/Scrum/scrum.tjp +141 -0
  11. data/examples/Tutorial/tutorial.tjp +13 -7
  12. data/lib/taskjuggler/Attributes.rb +2 -3
  13. data/lib/taskjuggler/HTMLDocument.rb +25 -18
  14. data/lib/taskjuggler/Journal.rb +85 -65
  15. data/lib/taskjuggler/KeywordDocumentation.rb +25 -13
  16. data/lib/taskjuggler/LeaveList.rb +1 -1
  17. data/lib/taskjuggler/Limits.rb +3 -5
  18. data/lib/taskjuggler/MessageHandler.rb +173 -19
  19. data/lib/taskjuggler/Painter.rb +75 -0
  20. data/lib/taskjuggler/Painter/BasicShapes.rb +76 -0
  21. data/lib/taskjuggler/Painter/Color.rb +273 -0
  22. data/lib/taskjuggler/Painter/Element.rb +56 -0
  23. data/lib/taskjuggler/Painter/FontData.rb +221 -0
  24. data/lib/taskjuggler/Painter/FontMetrics.rb +125 -0
  25. data/lib/taskjuggler/Painter/FontMetricsData.rb +151 -0
  26. data/lib/taskjuggler/Painter/Group.rb +77 -0
  27. data/lib/taskjuggler/Painter/Points.rb +47 -0
  28. data/lib/taskjuggler/Painter/Primitives.rb +100 -0
  29. data/lib/taskjuggler/Painter/SVGSupport.rb +36 -0
  30. data/lib/taskjuggler/Painter/Text.rb +36 -0
  31. data/lib/taskjuggler/Project.rb +46 -29
  32. data/lib/taskjuggler/ProjectFileParser.rb +24 -22
  33. data/lib/taskjuggler/ProjectFileScanner.rb +2 -2
  34. data/lib/taskjuggler/PropertyTreeNode.rb +26 -34
  35. data/lib/taskjuggler/Query.rb +8 -5
  36. data/lib/taskjuggler/RealFormat.rb +3 -0
  37. data/lib/taskjuggler/Resource.rb +3 -5
  38. data/lib/taskjuggler/ResourceScenario.rb +19 -7
  39. data/lib/taskjuggler/RichText.rb +4 -6
  40. data/lib/taskjuggler/RichText/FunctionExample.rb +1 -1
  41. data/lib/taskjuggler/RichText/FunctionHandler.rb +5 -6
  42. data/lib/taskjuggler/RichText/Parser.rb +4 -6
  43. data/lib/taskjuggler/RichText/RTFNavigator.rb +1 -1
  44. data/lib/taskjuggler/RichText/RTFQuery.rb +2 -3
  45. data/lib/taskjuggler/RichText/RTFReport.rb +1 -1
  46. data/lib/taskjuggler/RichText/RTFReportLink.rb +1 -2
  47. data/lib/taskjuggler/RichText/RTFWithQuerySupport.rb +1 -1
  48. data/lib/taskjuggler/RichText/Scanner.rb +6 -6
  49. data/lib/taskjuggler/RichText/Snip.rb +1 -2
  50. data/lib/taskjuggler/RuntimeConfig.rb +9 -6
  51. data/lib/taskjuggler/ScenarioData.rb +4 -3
  52. data/lib/taskjuggler/Scoreboard.rb +6 -0
  53. data/lib/taskjuggler/SheetHandlerBase.rb +25 -8
  54. data/lib/taskjuggler/SimpleQueryExpander.rb +14 -5
  55. data/lib/taskjuggler/SyntaxReference.rb +1 -2
  56. data/lib/taskjuggler/TableColumnSorter.rb +84 -0
  57. data/lib/taskjuggler/Task.rb +3 -5
  58. data/lib/taskjuggler/TaskJuggler.rb +36 -29
  59. data/lib/taskjuggler/TaskScenario.rb +154 -66
  60. data/lib/taskjuggler/TextParser.rb +24 -17
  61. data/lib/taskjuggler/TextParser/Scanner.rb +16 -11
  62. data/lib/taskjuggler/TextParser/SourceFileInfo.rb +20 -15
  63. data/lib/taskjuggler/TimeSheets.rb +6 -12
  64. data/lib/taskjuggler/Tj3AppBase.rb +35 -16
  65. data/lib/taskjuggler/Tj3Config.rb +1 -1
  66. data/lib/taskjuggler/TjpSyntaxRules.rb +239 -49
  67. data/lib/taskjuggler/XMLElement.rb +9 -2
  68. data/lib/taskjuggler/apps/Tj3.rb +43 -37
  69. data/lib/taskjuggler/apps/Tj3Client.rb +62 -112
  70. data/lib/taskjuggler/apps/Tj3Daemon.rb +66 -29
  71. data/lib/taskjuggler/apps/Tj3Man.rb +5 -5
  72. data/lib/taskjuggler/apps/Tj3SsReceiver.rb +10 -13
  73. data/lib/taskjuggler/apps/Tj3SsSender.rb +13 -16
  74. data/lib/taskjuggler/apps/Tj3TsReceiver.rb +10 -13
  75. data/lib/taskjuggler/apps/Tj3TsSender.rb +12 -15
  76. data/lib/taskjuggler/apps/Tj3TsSummary.rb +12 -15
  77. data/lib/taskjuggler/apps/Tj3WebD.rb +99 -0
  78. data/lib/taskjuggler/daemon/Daemon.rb +50 -10
  79. data/lib/taskjuggler/daemon/DaemonConnector.rb +127 -0
  80. data/lib/taskjuggler/daemon/ProcessIntercom.rb +36 -21
  81. data/lib/taskjuggler/daemon/ProjectBroker.rb +122 -112
  82. data/lib/taskjuggler/daemon/ProjectServer.rb +78 -46
  83. data/lib/taskjuggler/daemon/ReportServer.rb +52 -28
  84. data/lib/taskjuggler/daemon/ReportServlet.rb +92 -21
  85. data/lib/taskjuggler/daemon/WebServer.rb +75 -22
  86. data/lib/taskjuggler/daemon/WelcomePage.rb +1 -0
  87. data/lib/taskjuggler/reports/AccountListRE.rb +3 -3
  88. data/lib/taskjuggler/reports/CSVFile.rb +9 -2
  89. data/lib/taskjuggler/reports/ChartPlotter.rb +453 -0
  90. data/lib/taskjuggler/reports/Navigator.rb +1 -0
  91. data/lib/taskjuggler/reports/NikuReport.rb +4 -4
  92. data/lib/taskjuggler/reports/Report.rb +6 -18
  93. data/lib/taskjuggler/reports/ReportBase.rb +9 -9
  94. data/lib/taskjuggler/reports/ReportContext.rb +2 -2
  95. data/lib/taskjuggler/reports/StatusSheetReport.rb +6 -6
  96. data/lib/taskjuggler/reports/TableReport.rb +24 -15
  97. data/lib/taskjuggler/reports/TimeSheetReport.rb +5 -5
  98. data/lib/taskjuggler/reports/TraceReport.rb +251 -0
  99. data/lib/tj3webd.rb +17 -0
  100. data/manual/Day_To_Day_Juggling +10 -3
  101. data/manual/Installation +38 -19
  102. data/manual/Software +25 -19
  103. data/manual/Tutorial +119 -110
  104. data/manual/html/Day_To_Day_Juggling.html +7 -5
  105. data/manual/html/Getting_Started.html +4 -4
  106. data/manual/html/How_To_Contribute.html +4 -4
  107. data/manual/html/Installation.html +19 -11
  108. data/manual/html/Intro.html +4 -4
  109. data/manual/html/Reporting_Bugs.html +4 -4
  110. data/manual/html/Rich_Text_Attributes.html +4 -4
  111. data/manual/html/Software.html +15 -11
  112. data/manual/html/TaskJuggler_2x_Migration.html +4 -4
  113. data/manual/html/TaskJuggler_Internals.html +4 -4
  114. data/manual/html/The_TaskJuggler_Syntax.html +4 -4
  115. data/manual/html/Tutorial.html +41 -32
  116. data/manual/html/account.html +4 -4
  117. data/manual/html/account.task.html +4 -4
  118. data/manual/html/accountprefix.html +4 -4
  119. data/manual/html/accountreport.html +27 -9
  120. data/manual/html/accountroot.html +5 -5
  121. data/manual/html/active.html +4 -4
  122. data/manual/html/adopt.task.html +4 -4
  123. data/manual/html/aggregate.html +4 -4
  124. data/manual/html/alert.html +4 -4
  125. data/manual/html/alertlevels.html +4 -4
  126. data/manual/html/allocate.html +5 -5
  127. data/manual/html/alphabet.html +4 -4
  128. data/manual/html/alternative.html +4 -4
  129. data/manual/html/author.html +4 -4
  130. data/manual/html/balance.html +5 -5
  131. data/manual/html/booking.resource.html +4 -4
  132. data/manual/html/booking.task.html +4 -4
  133. data/manual/html/caption.html +5 -5
  134. data/manual/html/cellcolor.column.html +43 -8
  135. data/manual/html/celltext.column.html +4 -4
  136. data/manual/html/center.html +5 -5
  137. data/manual/html/charge.html +4 -4
  138. data/manual/html/chargeset.html +4 -4
  139. data/manual/html/columnid.html +27 -15
  140. data/manual/html/columns.html +5 -5
  141. data/manual/html/complete.html +4 -4
  142. data/manual/html/copyright.html +4 -4
  143. data/manual/html/credits.html +4 -4
  144. data/manual/html/css/tjreport.css +14 -5
  145. data/manual/html/currency.html +4 -4
  146. data/manual/html/currencyformat.html +5 -5
  147. data/manual/html/dailymax.html +5 -5
  148. data/manual/html/dailymin.html +5 -5
  149. data/manual/html/dailyworkinghours.html +4 -4
  150. data/manual/html/date.extend.html +4 -4
  151. data/manual/html/date.html +5 -5
  152. data/manual/html/definitions.html +4 -4
  153. data/manual/html/depends.html +4 -4
  154. data/manual/html/details.html +4 -4
  155. data/manual/html/disabled.html +4 -4
  156. data/manual/html/duration.html +4 -4
  157. data/manual/html/efficiency.html +4 -4
  158. data/manual/html/effort.html +4 -4
  159. data/manual/html/email.html +4 -4
  160. data/manual/html/enabled.html +4 -4
  161. data/manual/html/end.column.html +4 -4
  162. data/manual/html/end.html +4 -4
  163. data/manual/html/end.limit.html +4 -4
  164. data/manual/html/end.report.html +5 -5
  165. data/manual/html/end.timesheet.html +4 -4
  166. data/manual/html/endcredit.html +4 -4
  167. data/manual/html/epilog.html +5 -5
  168. data/manual/html/export.html +4 -4
  169. data/manual/html/extend.html +4 -4
  170. data/manual/html/fail.html +43 -8
  171. data/manual/html/fdl.html +4 -4
  172. data/manual/html/flags.account.html +4 -4
  173. data/manual/html/flags.html +4 -4
  174. data/manual/html/flags.journalentry.html +4 -4
  175. data/manual/html/flags.report.html +5 -5
  176. data/manual/html/flags.resource.html +4 -4
  177. data/manual/html/flags.statussheet.html +4 -4
  178. data/manual/html/flags.task.html +4 -4
  179. data/manual/html/flags.timesheet.html +4 -4
  180. data/manual/html/fontcolor.column.html +43 -8
  181. data/manual/html/footer.html +5 -5
  182. data/manual/html/formats.html +5 -5
  183. data/manual/html/functions.html +4 -4
  184. data/manual/html/gapduration.html +4 -4
  185. data/manual/html/gaplength.html +4 -4
  186. data/manual/html/halign.center.html +4 -4
  187. data/manual/html/halign.column.html +43 -8
  188. data/manual/html/halign.left.html +4 -4
  189. data/manual/html/halign.right.html +4 -4
  190. data/manual/html/hasalert.html +4 -4
  191. data/manual/html/header.html +5 -5
  192. data/manual/html/headline.html +7 -7
  193. data/manual/html/height.html +72 -0
  194. data/manual/html/hideaccount.html +46 -11
  195. data/manual/html/hidejournalentry.html +5 -5
  196. data/manual/html/hidereport.html +43 -8
  197. data/manual/html/hideresource.html +44 -9
  198. data/manual/html/hidetask.html +44 -9
  199. data/manual/html/icalreport.html +4 -4
  200. data/manual/html/include.macro.html +4 -4
  201. data/manual/html/include.project.html +4 -4
  202. data/manual/html/include.properties.html +4 -4
  203. data/manual/html/index.html +2 -1
  204. data/manual/html/inherit.extend.html +4 -4
  205. data/manual/html/interval1.html +4 -4
  206. data/manual/html/interval2.html +4 -4
  207. data/manual/html/interval3.html +4 -4
  208. data/manual/html/interval4.html +4 -4
  209. data/manual/html/isactive.html +4 -4
  210. data/manual/html/ischildof.html +4 -4
  211. data/manual/html/isdependencyof.html +4 -4
  212. data/manual/html/isdutyof.html +4 -4
  213. data/manual/html/isfeatureof.html +4 -4
  214. data/manual/html/isleaf.html +4 -4
  215. data/manual/html/ismilestone.html +4 -4
  216. data/manual/html/isongoing.html +4 -4
  217. data/manual/html/isresource.html +4 -4
  218. data/manual/html/isresponsibilityof.html +4 -4
  219. data/manual/html/istask.html +4 -4
  220. data/manual/html/journalattributes.html +11 -7
  221. data/manual/html/journalentry.html +4 -4
  222. data/manual/html/journalmode.html +5 -5
  223. data/manual/html/leaveallowance.html +5 -5
  224. data/manual/html/leaves.html +5 -6
  225. data/manual/html/left.html +5 -5
  226. data/manual/html/length.html +4 -4
  227. data/manual/html/limits.allocate.html +4 -4
  228. data/manual/html/limits.html +4 -4
  229. data/manual/html/limits.resource.html +4 -4
  230. data/manual/html/limits.task.html +4 -4
  231. data/manual/html/listitem.column.html +4 -4
  232. data/manual/html/listtype.column.html +4 -4
  233. data/manual/html/loadunit.html +5 -5
  234. data/manual/html/logicalexpression.html +8 -44
  235. data/manual/html/logicalflagexpression.html +4 -4
  236. data/manual/html/macro.html +4 -4
  237. data/manual/html/managers.html +4 -4
  238. data/manual/html/mandatory.html +4 -4
  239. data/manual/html/maxend.html +4 -4
  240. data/manual/html/maximum.html +5 -5
  241. data/manual/html/maxstart.html +4 -4
  242. data/manual/html/milestone.html +4 -4
  243. data/manual/html/minend.html +4 -4
  244. data/manual/html/minimum.html +5 -5
  245. data/manual/html/minstart.html +4 -4
  246. data/manual/html/monthlymax.html +5 -5
  247. data/manual/html/monthlymin.html +5 -5
  248. data/manual/html/navbar.html +10 -4
  249. data/manual/html/navigator.html +4 -4
  250. data/manual/html/newtask.html +4 -4
  251. data/manual/html/nikureport.html +4 -4
  252. data/manual/html/note.task.html +4 -4
  253. data/manual/html/now.html +4 -4
  254. data/manual/html/numberformat.html +5 -5
  255. data/manual/html/onend.html +4 -4
  256. data/manual/html/onstart.html +4 -4
  257. data/manual/html/opennodes.html +5 -5
  258. data/manual/html/overtime.booking.html +4 -4
  259. data/manual/html/period.column.html +4 -4
  260. data/manual/html/period.limit.html +4 -4
  261. data/manual/html/period.report.html +5 -5
  262. data/manual/html/period.task.html +4 -4
  263. data/manual/html/persistent.html +4 -4
  264. data/manual/html/precedes.html +4 -4
  265. data/manual/html/priority.html +4 -4
  266. data/manual/html/priority.timesheet.html +4 -4
  267. data/manual/html/project.html +4 -4
  268. data/manual/html/projectid.html +4 -4
  269. data/manual/html/projectid.task.html +4 -4
  270. data/manual/html/projectids.html +4 -4
  271. data/manual/html/projection.html +5 -7
  272. data/manual/html/prolog.html +5 -5
  273. data/manual/html/properties.html +11 -5
  274. data/manual/html/purge.html +5 -5
  275. data/manual/html/rate.html +4 -4
  276. data/manual/html/rate.resource.html +4 -4
  277. data/manual/html/reference.extend.html +4 -4
  278. data/manual/html/remaining.html +4 -4
  279. data/manual/html/replace.html +4 -4
  280. data/manual/html/reportprefix.html +4 -4
  281. data/manual/html/resource.html +4 -10
  282. data/manual/html/resourceattributes.html +4 -4
  283. data/manual/html/resourceprefix.html +4 -4
  284. data/manual/html/resourcereport.html +28 -10
  285. data/manual/html/resourceroot.html +5 -5
  286. data/manual/html/resources.limit.html +4 -4
  287. data/manual/html/responsible.html +4 -4
  288. data/manual/html/richtext.extend.html +4 -4
  289. data/manual/html/right.html +5 -5
  290. data/manual/html/rollupaccount.html +44 -9
  291. data/manual/html/rollupresource.html +44 -9
  292. data/manual/html/rolluptask.html +44 -9
  293. data/manual/html/scale.column.html +4 -4
  294. data/manual/html/scenario.html +4 -22
  295. data/manual/html/scenario.ical.html +4 -4
  296. data/manual/html/scenarios.export.html +4 -4
  297. data/manual/html/scenarios.html +5 -5
  298. data/manual/html/scenariospecific.extend.html +4 -4
  299. data/manual/html/scheduled.html +4 -4
  300. data/manual/html/scheduling.html +4 -4
  301. data/manual/html/select.html +4 -4
  302. data/manual/html/selfcontained.html +5 -5
  303. data/manual/html/shift.allocate.html +4 -4
  304. data/manual/html/shift.html +4 -4
  305. data/manual/html/shift.resource.html +5 -5
  306. data/manual/html/shift.task.html +4 -4
  307. data/manual/html/shift.timesheet.html +4 -4
  308. data/manual/html/shifts.allocate.html +4 -4
  309. data/manual/html/shifts.resource.html +4 -4
  310. data/manual/html/shifts.task.html +4 -4
  311. data/manual/html/shorttimeformat.html +4 -4
  312. data/manual/html/sloppy.booking.html +4 -4
  313. data/manual/html/sloppy.projection.html +5 -5
  314. data/manual/html/sortaccounts.html +5 -5
  315. data/manual/html/sortjournalentries.html +5 -5
  316. data/manual/html/sortresources.html +5 -5
  317. data/manual/html/sorttasks.html +5 -5
  318. data/manual/html/start.column.html +4 -4
  319. data/manual/html/start.html +4 -4
  320. data/manual/html/start.limit.html +4 -4
  321. data/manual/html/start.report.html +5 -5
  322. data/manual/html/startcredit.html +4 -4
  323. data/manual/html/status.statussheet.html +4 -4
  324. data/manual/html/status.timesheet.html +4 -4
  325. data/manual/html/statussheet.html +4 -4
  326. data/manual/html/statussheetreport.html +4 -4
  327. data/manual/html/strict.projection.html +5 -5
  328. data/manual/html/summary.html +4 -4
  329. data/manual/html/supplement.html +4 -4
  330. data/manual/html/supplement.resource.html +4 -10
  331. data/manual/html/supplement.task.html +4 -28
  332. data/manual/html/tagfile.html +4 -4
  333. data/manual/html/task.html +4 -28
  334. data/manual/html/task.statussheet.html +4 -4
  335. data/manual/html/task.timesheet.html +4 -4
  336. data/manual/html/taskattributes.html +4 -4
  337. data/manual/html/taskprefix.html +4 -4
  338. data/manual/html/taskreport.html +28 -10
  339. data/manual/html/taskroot.html +5 -5
  340. data/manual/html/text.extend.html +4 -4
  341. data/manual/html/textreport.html +27 -9
  342. data/manual/html/timeformat.html +5 -5
  343. data/manual/html/timeoff.nikureport.html +4 -4
  344. data/manual/html/timesheet.html +4 -4
  345. data/manual/html/timesheetreport.html +23 -5
  346. data/manual/html/timezone.export.html +4 -4
  347. data/manual/html/timezone.html +4 -4
  348. data/manual/html/timezone.report.html +5 -5
  349. data/manual/html/timezone.shift.html +4 -4
  350. data/manual/html/timingresolution.html +4 -4
  351. data/manual/html/title.column.html +4 -4
  352. data/manual/html/title.html +5 -5
  353. data/manual/html/toc.html +207 -179
  354. data/manual/html/tooltip.column.html +45 -10
  355. data/manual/html/tracereport.html +405 -0
  356. data/manual/html/trackingscenario.html +6 -6
  357. data/manual/html/treelevel.html +4 -4
  358. data/manual/html/vacation.html +4 -4
  359. data/manual/html/vacation.resource.html +4 -4
  360. data/manual/html/vacation.shift.html +4 -4
  361. data/manual/html/warn.html +43 -8
  362. data/manual/html/weeklymax.html +5 -5
  363. data/manual/html/weeklymin.html +5 -5
  364. data/manual/html/weekstartsmonday.html +4 -4
  365. data/manual/html/weekstartssunday.html +6 -6
  366. data/manual/html/width.column.html +6 -6
  367. data/manual/html/width.html +72 -0
  368. data/manual/html/work.html +4 -4
  369. data/manual/html/workinghours.project.html +4 -4
  370. data/manual/html/workinghours.resource.html +4 -4
  371. data/manual/html/workinghours.shift.html +4 -4
  372. data/manual/html/yearlyworkingdays.html +4 -4
  373. data/spec/Color_spec.rb +60 -0
  374. data/spec/ProjectBroker_spec.rb +3 -2
  375. data/spec/StatusSheets_spec.rb +5 -4
  376. data/spec/TableColumnSorter_spec.rb +78 -0
  377. data/spec/TimeSheets_spec.rb +6 -2
  378. data/spec/Tj3Daemon_spec.rb +2 -2
  379. data/spec/TraceReport_spec.rb +117 -0
  380. data/taskjuggler.gemspec +1 -1
  381. data/test/MessageChecker.rb +3 -1
  382. data/test/ReferenceGenerator.rb +1 -1
  383. data/test/TestSuite/CSV-Reports/Leave.tjp +1 -1
  384. data/test/TestSuite/CSV-Reports/refs/resourcereport_with_tasks.csv +3 -0
  385. data/test/TestSuite/CSV-Reports/refs/taskcounter.csv +9 -0
  386. data/test/TestSuite/CSV-Reports/refs/taskreport_with_resources.csv +19 -16
  387. data/test/TestSuite/CSV-Reports/refs/weekly.csv +1 -0
  388. data/test/TestSuite/Export-Reports/refs/LogicalExpression.tjp +14 -2
  389. data/test/TestSuite/Export-Reports/refs/tutorial.tjp +98 -86
  390. data/test/TestSuite/Scheduler/Correct/Leaves.tjp +25 -0
  391. data/test/TestSuite/Syntax/Correct/Leave.tjp +1 -1
  392. data/test/TestSuite/Syntax/Correct/LogicalExpression.tjp +9 -1
  393. data/test/TestSuite/Syntax/Correct/TraceReport.tjp +10 -0
  394. data/test/TestSuite/Syntax/Correct/tutorial.tjp +10 -4
  395. data/test/test_CSV-Reports.rb +3 -3
  396. data/test/test_Export-Reports.rb +91 -86
  397. data/test/test_Journal.rb +15 -12
  398. data/test/test_Limits.rb +3 -3
  399. data/test/test_Project.rb +1 -2
  400. data/test/test_ProjectFileScanner.rb +1 -1
  401. data/test/test_PropertySet.rb +1 -1
  402. data/test/test_Query.rb +5 -6
  403. data/test/test_ReportGenerator.rb +15 -7
  404. data/test/test_RichText.rb +4 -3
  405. data/test/test_Scheduler.rb +19 -7
  406. data/test/test_ShiftAssignments.rb +2 -2
  407. data/test/test_SimpleQueryExpander.rb +29 -2
  408. data/test/test_Syntax.rb +14 -5
  409. metadata +49 -10
  410. data/lib/taskjuggler/LogFile.rb +0 -73
@@ -57,6 +57,7 @@ class TaskJuggler
57
57
  @doneEffort = 0.0
58
58
 
59
59
  @projectionMode = @project.scenario(@scenarioIdx).get('projection')
60
+ @nowIdx = @project.dateToIdx(@project['now'])
60
61
 
61
62
  @startIsDetermed = nil
62
63
  @endIsDetermed = nil
@@ -367,11 +368,11 @@ class TaskJuggler
367
368
  task.finishScheduling(@scenarioIdx)
368
369
  end
369
370
 
370
- if (parent = @property.parent)
371
- # Add the assigned resources to the parent task list.
371
+ @property.parents.each do |pTask|
372
+ # Add the assigned resources to the parent task's list.
372
373
  @assignedresources.each do |resource|
373
- unless parent['assignedresources', @scenarioIdx].include?(resource)
374
- parent['assignedresources', @scenarioIdx] << resource
374
+ unless pTask['assignedresources', @scenarioIdx].include?(resource)
375
+ pTask['assignedresources', @scenarioIdx] << resource
375
376
  end
376
377
  end
377
378
  end
@@ -558,7 +559,7 @@ class TaskJuggler
558
559
  "end date.")
559
560
  end
560
561
 
561
- if @effort == 0 && !@milestone && !@allocate.empty? &&
562
+ if @property.leaf? && @effort == 0 && !@milestone && !@allocate.empty? &&
562
563
  @assignedresources.empty?
563
564
  # The user used an 'allocate' for the task, but did not specify any
564
565
  # 'effort'. Actual allocations will only happen when resources are
@@ -1241,6 +1242,22 @@ class TaskJuggler
1241
1242
  @booking << booking
1242
1243
  end
1243
1244
 
1245
+ def query_activetasks(query)
1246
+ count = activeTasks(query)
1247
+
1248
+ query.sortable = query.numerical = count
1249
+ # For the string output, we only use integer numbers.
1250
+ query.string = "#{count.to_i}"
1251
+ end
1252
+
1253
+ def query_closedtasks(query)
1254
+ count = closedTasks(query)
1255
+
1256
+ query.sortable = query.numerical = count
1257
+ # For the string output, we only use integer numbers.
1258
+ query.string = "#{count.to_i}"
1259
+ end
1260
+
1244
1261
  def query_complete(query)
1245
1262
  # If we haven't calculated the value yet, calculate it first.
1246
1263
  unless @complete
@@ -1337,6 +1354,13 @@ class TaskJuggler
1337
1354
  query.assignList(list)
1338
1355
  end
1339
1356
 
1357
+ def query_gauge(query)
1358
+ # If we haven't calculated the schedule status yet, calculate it first.
1359
+ calcGauge unless @gauge
1360
+
1361
+ query.string = @gauge
1362
+ end
1363
+
1340
1364
  # The number of different resources assigned to the task during the query
1341
1365
  # interval. Each resource is counted based on their mathematically rounded
1342
1366
  # efficiency.
@@ -1350,22 +1374,41 @@ class TaskJuggler
1350
1374
  query.string = query.numberFormat.format(headcount)
1351
1375
  end
1352
1376
 
1353
- def query_maxend(query)
1354
- queryDateLimit(query, @maxend)
1377
+ def query_inputs(query)
1378
+ inputList = PropertyList.new(@project.tasks, false)
1379
+ inputs(inputList, true)
1380
+ inputList.delete(@property)
1381
+ inputList.setSorting([['start', true, @scenarioIdx],
1382
+ ['seqno', true, -1 ]])
1383
+ inputList.sort!
1384
+
1385
+ query.assignList(generateTaskList(inputList, query))
1355
1386
  end
1356
1387
 
1357
- def query_minend(query)
1358
- queryDateLimit(query, @minend)
1388
+ def query_maxend(query)
1389
+ queryDateLimit(query, @maxend)
1359
1390
  end
1360
1391
 
1361
1392
  def query_maxstart(query)
1362
1393
  queryDateLimit(query, @maxstart)
1363
1394
  end
1364
1395
 
1396
+ def query_minend(query)
1397
+ queryDateLimit(query, @minend)
1398
+ end
1399
+
1365
1400
  def query_minstart(query)
1366
1401
  queryDateLimit(query, @minstart)
1367
1402
  end
1368
1403
 
1404
+ def query_opentasks(query)
1405
+ count = openTasks(query)
1406
+
1407
+ query.sortable = query.numerical = count
1408
+ # For the string output, we only use integer numbers.
1409
+ query.string = "#{count.to_i}"
1410
+ end
1411
+
1369
1412
  def query_precursors(query)
1370
1413
  list = []
1371
1414
 
@@ -1403,9 +1446,8 @@ class TaskJuggler
1403
1446
  assignedResources(iv).each do |resource|
1404
1447
  if resource.allocated?(@scenarioIdx, iv, @property)
1405
1448
  if query.listItem
1406
- rti = RichText.new(query.listItem, RTFHandlers.create(@project),
1407
- @project.messageHandler).
1408
- generateIntermediateFormat
1449
+ rti = RichText.new(query.listItem, RTFHandlers.create(@project)).
1450
+ generateIntermediateFormat
1409
1451
  unless rti
1410
1452
  error('bad_resource_ts_query',
1411
1453
  "Syntax error in query statement for task attribute " +
@@ -1444,24 +1486,6 @@ class TaskJuggler
1444
1486
  query.string = @status
1445
1487
  end
1446
1488
 
1447
- def query_gauge(query)
1448
- # If we haven't calculated the schedule status yet, calculate it first.
1449
- calcGauge unless @gauge
1450
-
1451
- query.string = @gauge
1452
- end
1453
-
1454
- def query_inputs(query)
1455
- inputList = PropertyList.new(@project.tasks, false)
1456
- inputs(inputList, true)
1457
- inputList.delete(@property)
1458
- inputList.setSorting([['start', true, @scenarioIdx],
1459
- ['seqno', true, -1 ]])
1460
- inputList.sort!
1461
-
1462
- query.assignList(generateTaskList(inputList, query))
1463
- end
1464
-
1465
1489
  def query_targets(query)
1466
1490
  targetList = PropertyList.new(@project.tasks, false)
1467
1491
  targets(targetList, true)
@@ -1507,10 +1531,13 @@ class TaskJuggler
1507
1531
  # interval specified by _startIdx_ and _endIdx_. The effective work is the
1508
1532
  # actual work multiplied by the efficiency of the resource.
1509
1533
  def getEffectiveWork(startIdx, endIdx, resource = nil)
1534
+ # Make sure we have the real Resource and not a proxy.
1535
+ resource = resource.ptn if resource
1510
1536
  return 0.0 if @milestone || startIdx >= endIdx ||
1511
1537
  (resource && !@assignedresources.include?(resource))
1512
1538
 
1513
- @dCache.cached(self, :TaskScenarioEffectiveWork, startIdx, endIdx, resource) do
1539
+ @dCache.cached(self, :TaskScenarioEffectiveWork, startIdx, endIdx,
1540
+ resource) do
1514
1541
  workLoad = 0.0
1515
1542
  if @property.container?
1516
1543
  @property.kids.each do |task|
@@ -1519,8 +1546,8 @@ class TaskJuggler
1519
1546
  end
1520
1547
  else
1521
1548
  if resource
1522
- workLoad += resource.getEffectiveWork(@scenarioIdx, startIdx, endIdx,
1523
- @property)
1549
+ workLoad += resource.getEffectiveWork(@scenarioIdx, startIdx,
1550
+ endIdx, @property)
1524
1551
  else
1525
1552
  @assignedresources.each do |r|
1526
1553
  workLoad += r.getEffectiveWork(@scenarioIdx, startIdx, endIdx,
@@ -1538,7 +1565,8 @@ class TaskJuggler
1538
1565
  # This function is often called recursively for the same parameters. We
1539
1566
  # store the results in the cache to avoid repeated computations of the
1540
1567
  # same results.
1541
- @dCache.cached(self, :TaskScenarioCollectTimeOffIntervals, iv, minDuration) do
1568
+ @dCache.cached(self, :TaskScenarioCollectTimeOffIntervals, iv,
1569
+ minDuration) do
1542
1570
  il = IntervalList.new
1543
1571
  il << TimeInterval.new(@project['start'], @project['end'])
1544
1572
  if @property.leaf?
@@ -1567,31 +1595,41 @@ class TaskJuggler
1567
1595
  # Check if the Task _task_ depends on this task. _depth_ specifies how
1568
1596
  # many dependent task are traversed at max. A value of 0 means no limit.
1569
1597
  # TODO: Change this to a non-recursive implementation.
1570
- def isDependencyOf(task, depth)
1598
+ def isDependencyOf(task, depth, list = [])
1571
1599
  return true if task == @property
1572
1600
 
1601
+ # If this task is already in the list of traversed task, we can ignore
1602
+ # it.
1603
+ return false if list.include?(@property)
1604
+ list << @property
1605
+
1606
+ @startsuccs.each do |t, onEnd|
1607
+ unless onEnd
1608
+ # must be a start->start dependency
1609
+ return true if t.isDependencyOf(@scenarioIdx, task, depth, list)
1610
+ end
1611
+ end
1612
+
1613
+ # For task to depend on this task, the start of task must be after the
1614
+ # end of this task.
1615
+ if task['start', @scenarioIdx] && @end
1616
+ return false if task['start', @scenarioIdx] < @end
1617
+ end
1618
+
1573
1619
  # Check if any of the parent tasks is a dependency of _task_.
1574
1620
  t = @property.parent
1575
1621
  while t
1576
1622
  # If the parent is a dependency, than all childs are as well.
1577
- return true if t.isDependencyOf(@scenarioIdx, task, depth)
1623
+ return true if t.isDependencyOf(@scenarioIdx, task, depth, list)
1578
1624
  t = t.parent
1579
1625
  end
1580
1626
 
1581
-
1582
- @startsuccs.each do |dep|
1583
- unless dep[1]
1584
- # must be a start->start dependency
1585
- return true if dep[0].isDependencyOf(@scenarioIdx, task, depth)
1586
- end
1587
- end
1588
-
1589
1627
  return false if depth == 1
1590
1628
 
1591
- @endsuccs.each do |dep|
1592
- unless dep[1]
1629
+ @endsuccs.each do |ta, onEnd|
1630
+ unless onEnd
1593
1631
  # must be an end->start dependency
1594
- return true if dep[0].isDependencyOf(@scenarioIdx, task, depth - 1)
1632
+ return true if ta.isDependencyOf(@scenarioIdx, task, depth - 1, list)
1595
1633
  end
1596
1634
  end
1597
1635
 
@@ -1726,7 +1764,9 @@ class TaskJuggler
1726
1764
 
1727
1765
  def bookResources
1728
1766
  # First check if there is any resource at all for this slot.
1729
- return true unless @project.anyResourceAvailable?(@currentSlotIdx)
1767
+ return if !@project.anyResourceAvailable?(@currentSlotIdx) ||
1768
+ (@projectionMode && (@nowIdx > @currentSlotIdx))
1769
+
1730
1770
 
1731
1771
  # If the task has resource independent allocation limits we need to make
1732
1772
  # sure that none of them is already exceeded.
@@ -2290,27 +2330,74 @@ class TaskJuggler
2290
2330
  end
2291
2331
  end
2292
2332
 
2333
+ def activeTasks(query)
2334
+ return 0 unless TimeInterval.new(@start, @end).
2335
+ overlaps?(TimeInterval.new(query.start, query.end))
2336
+
2337
+ if @property.leaf?
2338
+ now = @project['now']
2339
+ return @start <= now && now < @end ? 1 : 0
2340
+ else
2341
+ cnt = 0
2342
+ @property.kids.each do |task|
2343
+ cnt += task.closedTasks(@scenarioIdx, query)
2344
+ end
2345
+ return cnt
2346
+ end
2347
+ end
2348
+
2349
+ def closedTasks(query)
2350
+ return 0 unless TimeInterval.new(@start, @end).
2351
+ overlaps?(TimeInterval.new(query.start, query.end))
2352
+
2353
+ if @property.leaf?
2354
+ return @end <= @project['now'] ? 1 : 0
2355
+ else
2356
+ cnt = 0
2357
+ @property.kids.each do |task|
2358
+ cnt += task.closedTasks(@scenarioIdx, query)
2359
+ end
2360
+ return cnt
2361
+ end
2362
+ end
2363
+
2364
+ def openTasks(query)
2365
+ return 0 unless TimeInterval.new(@start, @end).
2366
+ overlaps?(TimeInterval.new(query.start, query.end))
2367
+
2368
+ if @property.leaf?
2369
+ return @end > @project['now'] ? 1 : 0
2370
+ else
2371
+ cnt = 0
2372
+ @property.kids.each do |task|
2373
+ cnt += task.openTasks(@scenarioIdx, query)
2374
+ end
2375
+ return cnt
2376
+ end
2377
+ end
2378
+
2293
2379
  # Recursively compile a list of Task properties which depend on the
2294
2380
  # current task.
2295
- def inputs(list, includeChildren)
2296
- # Ignore tasks that we have already included in the list.
2297
- return if list.include?(@property)
2381
+ def inputs(foundInputs, includeChildren, checkedTasks = [])
2382
+ # Ignore tasks that we have already included in the checked tasks list.
2383
+ return if checkedTasks.include?(@property)
2384
+ checkedTasks << @property
2298
2385
 
2299
2386
  # A target must be a leaf function that has no direct or indirect
2300
2387
  # (through parent) following tasks. Only milestones are recognized as
2301
2388
  # targets.
2302
2389
  if @property.leaf? && !hasPredecessors && @milestone
2303
- list << @property
2390
+ foundInputs << @property
2304
2391
  return
2305
2392
  end
2306
2393
 
2307
2394
  @startpreds.each do |t, onEnd|
2308
- t.inputs(@scenarioIdx, list, false)
2395
+ t.inputs(@scenarioIdx, foundInputs, false, checkedTasks)
2309
2396
  end
2310
2397
 
2311
2398
  # Check for indirect predecessors.
2312
2399
  if @property.parent
2313
- @property.parent.inputs(@scenarioIdx, list, false)
2400
+ @property.parent.inputs(@scenarioIdx, foundInputs, false, checkedTasks)
2314
2401
  end
2315
2402
 
2316
2403
  # Also include targets of child tasks. The recursive iteration of child
@@ -2318,32 +2405,33 @@ class TaskJuggler
2318
2405
  # iterated.
2319
2406
  if includeChildren
2320
2407
  @property.kids.each do |child|
2321
- child.inputs(@scenarioIdx, list, true)
2408
+ child.inputs(@scenarioIdx, foundInputs, true, checkedTasks)
2322
2409
  end
2323
2410
  end
2324
2411
  end
2325
2412
 
2326
2413
  # Recursively compile a list of Task properties which depend on the
2327
2414
  # current task.
2328
- def targets(list, includeChildren)
2329
- # Ignore tasks that we have already included in the list.
2330
- return if list.include?(@property)
2415
+ def targets(foundTargets, includeChildren, checkedTasks = [])
2416
+ # Ignore tasks that we have already included in the checked tasks list.
2417
+ return if checkedTasks.include?(@property)
2418
+ checkedTasks << @property
2331
2419
 
2332
2420
  # A target must be a leaf function that has no direct or indirect
2333
2421
  # (through parent) following tasks. Only milestones are recognized as
2334
2422
  # targets.
2335
2423
  if @property.leaf? && !hasSuccessors && @milestone
2336
- list << @property
2424
+ foundTargets << @property
2337
2425
  return
2338
2426
  end
2339
2427
 
2340
2428
  @endsuccs.each do |t, onEnd|
2341
- t.targets(@scenarioIdx, list, false)
2429
+ t.targets(@scenarioIdx, foundTargets, false, checkedTasks)
2342
2430
  end
2343
2431
 
2344
2432
  # Check for indirect followers.
2345
2433
  if @property.parent
2346
- @property.parent.targets(@scenarioIdx, list, false)
2434
+ @property.parent.targets(@scenarioIdx, foundTargets, false, checkedTasks)
2347
2435
  end
2348
2436
 
2349
2437
  # Also include targets of child tasks. The recursive iteration of child
@@ -2351,7 +2439,7 @@ class TaskJuggler
2351
2439
  # iterated.
2352
2440
  if includeChildren
2353
2441
  @property.kids.each do |child|
2354
- child.targets(@scenarioIdx, list, true)
2442
+ child.targets(@scenarioIdx, foundTargets, true, checkedTasks)
2355
2443
  end
2356
2444
  end
2357
2445
  end
@@ -2416,8 +2504,8 @@ class TaskJuggler
2416
2504
 
2417
2505
  def generateDepencyListItem(query, task, dep, date)
2418
2506
  if query.listItem
2419
- rti = RichText.new(query.listItem, RTFHandlers.create(@project),
2420
- @project.messageHandler).generateIntermediateFormat
2507
+ rti = RichText.new(query.listItem, RTFHandlers.create(@project)).
2508
+ generateIntermediateFormat
2421
2509
  q = query.dup
2422
2510
  q.property = task
2423
2511
  q.setCustomData('dependency', { :string => dep })
@@ -2435,8 +2523,8 @@ class TaskJuggler
2435
2523
  date = task['start', @scenarioIdx].
2436
2524
  to_s(@property.project['timeFormat'])
2437
2525
  if query.listItem
2438
- rti = RichText.new(query.listItem, RTFHandlers.create(@project),
2439
- @project.messageHandler).generateIntermediateFormat
2526
+ rti = RichText.new(query.listItem, RTFHandlers.create(@project)).
2527
+ generateIntermediateFormat
2440
2528
  q = query.dup
2441
2529
  q.property = task
2442
2530
  q.setCustomData('date', { :string => date })
@@ -50,6 +50,8 @@ class TaskJuggler
50
50
  # with the name of the start rule.
51
51
  class TextParser
52
52
 
53
+ include MessageHandler
54
+
53
55
  # Utility class so that we can distinguish Array results from the Array
54
56
  # containing the results of a repeatable rule. We define some merging
55
57
  # method with a slightly different behaviour.
@@ -72,12 +74,10 @@ class TaskJuggler
72
74
  end
73
75
  end
74
76
 
75
- attr_reader :rules, :messageHandler
77
+ attr_reader :rules
76
78
 
77
79
  # Create a new TextParser object.
78
- def initialize(messageHandler)
79
- # The message handler will collect all error messages.
80
- @messageHandler = messageHandler
80
+ def initialize
81
81
  # This Hash will store the ruleset that the parser is operating on.
82
82
  @rules = { }
83
83
  # Array to hold the token types that the scanner can return.
@@ -201,7 +201,7 @@ class TaskJuggler
201
201
  result = parseFSM(@rules[ruleName])
202
202
  rescue TjException => msg
203
203
  if msg.message && !msg.message.empty?
204
- @messageHandler.critical('parse', msg.message)
204
+ critical('parse', msg.message)
205
205
  end
206
206
  return false
207
207
  end
@@ -224,7 +224,7 @@ class TaskJuggler
224
224
  # on to the TextScanner.
225
225
  @scanner.error(id, text, sfi, data)
226
226
  else
227
- @messageHandler.error(id, text, sfi, data)
227
+ error(id, text, sfi, data)
228
228
  end
229
229
  end
230
230
 
@@ -235,7 +235,7 @@ class TaskJuggler
235
235
  # warning on to the TextScanner.
236
236
  @scanner.warning(id, text, sfi, data)
237
237
  else
238
- @messageHandler.warning(id, text, sfi, data)
238
+ warning(id, text, sfi, data)
239
239
  end
240
240
  end
241
241
 
@@ -298,6 +298,7 @@ class TaskJuggler
298
298
  stackElement = @stack.last
299
299
  first = true
300
300
  transition.stateStack.each do |s|
301
+ checkForOldSyntax(s, token)
301
302
  if first && s.pattern == stackElement.state.pattern
302
303
  # The first state in the list may just be another state of the
303
304
  # current pattern. In this case, we already have the
@@ -318,16 +319,7 @@ class TaskJuggler
318
319
  # stores the result of the pattern and keeps the State that we
319
320
  # need to return to in case we jump to other patterns from this
320
321
  # pattern.
321
- if state.pattern.supportLevel == :deprecated
322
- warning('deprecated_keyword',
323
- "The keyword '#{token[1]}' has been deprecated! " +
324
- "See the reference manual for details.")
325
- end
326
- if state.pattern.supportLevel == :removed
327
- error('removed_keyword',
328
- "The keyword '#{token[1]}' is no longer supported! " +
329
- "See the reference manual for details.")
330
- end
322
+ checkForOldSyntax(state, token)
331
323
  @stack.push(TextParser::StackElement.new(state.pattern.function,
332
324
  state))
333
325
  end
@@ -441,6 +433,21 @@ class TaskJuggler
441
433
  end
442
434
  end
443
435
 
436
+ # Check if the current token matches a deprecated or removed syntax
437
+ # element.
438
+ def checkForOldSyntax(state, token)
439
+ if state.pattern.supportLevel == :deprecated
440
+ warning('deprecated_keyword',
441
+ "The keyword '#{token[1]}' has been deprecated! " +
442
+ "See the reference manual for details.")
443
+ end
444
+ if state.pattern.supportLevel == :removed
445
+ error('removed_keyword',
446
+ "The keyword '#{token[1]}' is no longer supported! " +
447
+ "See the reference manual for details.")
448
+ end
449
+ end
450
+
444
451
  # Convert the FSM stack state entries from State objects into [ rule,
445
452
  # pattern, index ] equivalents.
446
453
  def saveFsmStack