taskjuggler 0.2.1 → 0.2.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 (443) hide show
  1. data/{tasks/missing.rake → .gemtest} +0 -0
  2. data/CHANGELOG +27 -0
  3. data/Rakefile +8 -9
  4. data/bin/tj3 +2 -1
  5. data/bin/tj3client +2 -1
  6. data/bin/tj3d +2 -1
  7. data/bin/tj3man +2 -1
  8. data/bin/tj3ss_receiver +2 -1
  9. data/bin/tj3ss_sender +2 -1
  10. data/bin/tj3ts_receiver +2 -1
  11. data/bin/tj3ts_sender +2 -1
  12. data/bin/tj3ts_summary +2 -1
  13. data/data/tjp.vim +425 -419
  14. data/examples/Fedora-20/f-20.tjp +2442 -0
  15. data/examples/Fedora-20/icons/fedoralogo.png +0 -0
  16. data/examples/Fedora-20/reports.tji +423 -0
  17. data/lib/header.tmpl +13 -0
  18. data/lib/taskjuggler/AppConfig.rb +5 -0
  19. data/lib/taskjuggler/Attributes.rb +22 -0
  20. data/lib/taskjuggler/Journal.rb +273 -10
  21. data/lib/taskjuggler/Log.rb +9 -8
  22. data/lib/taskjuggler/Project.rb +28 -60
  23. data/lib/taskjuggler/ProjectFileScanner.rb +2 -1
  24. data/lib/taskjuggler/PropertySet.rb +3 -0
  25. data/lib/taskjuggler/PropertyTreeNode.rb +4 -0
  26. data/lib/taskjuggler/Query.rb +2 -1
  27. data/lib/taskjuggler/Resource.rb +0 -103
  28. data/lib/taskjuggler/RichText/RTFQuery.rb +42 -4
  29. data/lib/taskjuggler/SheetHandlerBase.rb +0 -20
  30. data/lib/taskjuggler/SheetReceiver.rb +23 -21
  31. data/lib/taskjuggler/Task.rb +3 -5
  32. data/lib/taskjuggler/TaskJuggler.rb +4 -0
  33. data/lib/taskjuggler/TaskScenario.rb +81 -103
  34. data/lib/taskjuggler/TextParser/Scanner.rb +19 -18
  35. data/lib/taskjuggler/Tj3Config.rb +1 -1
  36. data/lib/taskjuggler/TjpSyntaxRules.rb +180 -45
  37. data/lib/taskjuggler/UTF8String.rb +30 -0
  38. data/lib/taskjuggler/apps/Tj3.rb +1 -1
  39. data/lib/taskjuggler/apps/Tj3Man.rb +54 -2
  40. data/lib/taskjuggler/reports/ICalReport.rb +4 -4
  41. data/lib/taskjuggler/reports/NikuReport.rb +6 -0
  42. data/lib/taskjuggler/reports/Report.rb +5 -5
  43. data/lib/taskjuggler/reports/ReportContext.rb +4 -2
  44. data/lib/taskjuggler/reports/ResourceListRE.rb +10 -1
  45. data/lib/taskjuggler/reports/StatusSheetReport.rb +3 -0
  46. data/lib/taskjuggler/reports/TableReport.rb +8 -3
  47. data/lib/taskjuggler/reports/TimeSheetReport.rb +3 -0
  48. data/lib/updateheader.sh +15 -0
  49. data/manual/Installation +11 -22
  50. data/manual/Software +17 -3
  51. data/manual/html/Day_To_Day_Juggling.html +359 -0
  52. data/manual/html/Getting_Started.html +62 -0
  53. data/manual/html/How_To_Contribute.html +88 -0
  54. data/manual/html/Installation.html +172 -0
  55. data/manual/html/Intro.html +74 -0
  56. data/manual/html/Reporting_Bugs.html +47 -0
  57. data/manual/html/Rich_Text_Attributes.html +174 -0
  58. data/manual/html/Software.html +147 -0
  59. data/manual/html/TaskJuggler_2x_Migration.html +71 -0
  60. data/manual/html/TaskJuggler_Internals.html +61 -0
  61. data/manual/html/The_TaskJuggler_Syntax.html +89 -0
  62. data/manual/html/Tutorial.html +498 -0
  63. data/manual/html/account.html +152 -0
  64. data/manual/html/account.task.html +68 -0
  65. data/manual/html/accountprefix.html +67 -0
  66. data/manual/html/active.html +66 -0
  67. data/manual/html/adopt.task.html +73 -0
  68. data/manual/html/alert level.html +66 -0
  69. data/manual/html/alert.html +66 -0
  70. data/manual/html/allocate.html +92 -0
  71. data/manual/html/alphabet.html +33 -0
  72. data/manual/html/alternative.html +77 -0
  73. data/manual/html/author.html +69 -0
  74. data/manual/html/balance.html +73 -0
  75. data/manual/html/booking.resource.html +122 -0
  76. data/manual/html/booking.task.html +120 -0
  77. data/manual/html/caption.html +96 -0
  78. data/manual/html/cellcolor.column.html +71 -0
  79. data/manual/html/celltext.column.html +68 -0
  80. data/manual/html/center.html +67 -0
  81. data/manual/html/charge.html +89 -0
  82. data/manual/html/chargeset.html +73 -0
  83. data/manual/html/columnid.html +358 -0
  84. data/manual/html/columns.html +73 -0
  85. data/manual/html/complete.html +80 -0
  86. data/manual/html/copyright.html +97 -0
  87. data/manual/html/credit.html +117 -0
  88. data/{benchmarks → manual/html}/css/tjmanual.css +0 -0
  89. data/{benchmarks → manual/html}/css/tjreport.css +0 -0
  90. data/manual/html/currency.html +120 -0
  91. data/manual/html/currencyformat.html +99 -0
  92. data/manual/html/dailymax.html +144 -0
  93. data/manual/html/dailymin.html +132 -0
  94. data/manual/html/dailyworkinghours.html +90 -0
  95. data/manual/html/date.extend.html +77 -0
  96. data/manual/html/date.html +100 -0
  97. data/manual/html/definitions.html +94 -0
  98. data/manual/html/depends.html +110 -0
  99. data/manual/html/details.html +69 -0
  100. data/manual/html/disabled.html +85 -0
  101. data/manual/html/duration.html +133 -0
  102. data/manual/html/efficiency.html +93 -0
  103. data/manual/html/effort.html +134 -0
  104. data/manual/html/email.html +68 -0
  105. data/manual/html/enabled.html +69 -0
  106. data/manual/html/end.column.html +67 -0
  107. data/manual/html/end.html +87 -0
  108. data/manual/html/end.limit.html +69 -0
  109. data/manual/html/end.report.html +99 -0
  110. data/manual/html/end.timesheet.html +94 -0
  111. data/manual/html/endcredit.html +110 -0
  112. data/manual/html/epilog.html +72 -0
  113. data/manual/html/export.html +197 -0
  114. data/manual/html/extend.html +87 -0
  115. data/manual/html/fail.html +69 -0
  116. data/manual/html/fdl.html +430 -0
  117. data/manual/html/flags.account.html +66 -0
  118. data/manual/html/flags.html +66 -0
  119. data/manual/html/flags.journalentry.html +66 -0
  120. data/manual/html/flags.report.html +66 -0
  121. data/manual/html/flags.resource.html +68 -0
  122. data/manual/html/flags.statussheet.html +66 -0
  123. data/manual/html/flags.task.html +68 -0
  124. data/manual/html/flags.timesheet.html +66 -0
  125. data/manual/html/fontcolor.column.html +71 -0
  126. data/manual/html/footer.html +72 -0
  127. data/manual/html/formats.html +80 -0
  128. data/manual/html/functions.html +78 -0
  129. data/manual/html/gapduration.html +93 -0
  130. data/manual/html/gaplength.html +93 -0
  131. data/manual/html/halign.center.html +66 -0
  132. data/manual/html/halign.column.html +67 -0
  133. data/manual/html/halign.left.html +66 -0
  134. data/manual/html/halign.right.html +66 -0
  135. data/manual/html/hasalert.html +71 -0
  136. data/manual/html/header.html +72 -0
  137. data/manual/html/headline.html +69 -0
  138. data/manual/html/hidejournalentry.html +69 -0
  139. data/manual/html/hidereport.html +67 -0
  140. data/manual/html/hideresource.html +73 -0
  141. data/manual/html/hidetask.html +73 -0
  142. data/manual/html/icalreport.html +137 -0
  143. data/manual/html/include.macro.html +70 -0
  144. data/manual/html/include.project.html +71 -0
  145. data/manual/html/include.properties.html +168 -0
  146. data/manual/html/index.html +18 -0
  147. data/manual/html/inherit.extend.html +68 -0
  148. data/manual/html/interval1.html +99 -0
  149. data/manual/html/interval2.html +98 -0
  150. data/manual/html/interval3.html +99 -0
  151. data/manual/html/interval4.html +100 -0
  152. data/manual/html/isactive.html +67 -0
  153. data/manual/html/ischildof.html +67 -0
  154. data/manual/html/isdependencyof.html +75 -0
  155. data/manual/html/isdutyof.html +71 -0
  156. data/manual/html/isfeatureof.html +71 -0
  157. data/manual/html/isleaf.html +66 -0
  158. data/manual/html/ismilestone.html +67 -0
  159. data/manual/html/isongoing.html +67 -0
  160. data/manual/html/isresource.html +66 -0
  161. data/manual/html/istask.html +66 -0
  162. data/manual/html/journalattributes.html +107 -0
  163. data/manual/html/journalentry.html +83 -0
  164. data/manual/html/journalmode.html +83 -0
  165. data/manual/html/left.html +66 -0
  166. data/manual/html/length.html +104 -0
  167. data/manual/html/limits.allocate.html +72 -0
  168. data/manual/html/limits.html +72 -0
  169. data/manual/html/limits.resource.html +80 -0
  170. data/manual/html/limits.task.html +113 -0
  171. data/manual/html/listitem.column.html +66 -0
  172. data/manual/html/listtype.column.html +79 -0
  173. data/manual/html/loadunit.html +99 -0
  174. data/manual/html/logicalexpression.html +110 -0
  175. data/manual/html/logicalflagexpression.html +82 -0
  176. data/manual/html/macro.html +103 -0
  177. data/manual/html/managers.html +109 -0
  178. data/manual/html/mandatory.html +66 -0
  179. data/manual/html/maxend.html +69 -0
  180. data/manual/html/maximum.html +99 -0
  181. data/manual/html/maxstart.html +69 -0
  182. data/manual/html/milestone.html +71 -0
  183. data/manual/html/minend.html +69 -0
  184. data/manual/html/minimum.html +99 -0
  185. data/manual/html/minstart.html +69 -0
  186. data/manual/html/monthlymax.html +99 -0
  187. data/manual/html/monthlymin.html +99 -0
  188. data/manual/html/navbar.html +513 -0
  189. data/manual/html/navigator.html +70 -0
  190. data/manual/html/newtask.html +83 -0
  191. data/manual/html/nikureport.html +216 -0
  192. data/manual/html/note.task.html +68 -0
  193. data/manual/html/now.html +67 -0
  194. data/manual/html/numberformat.html +85 -0
  195. data/manual/html/onend.html +68 -0
  196. data/manual/html/onstart.html +68 -0
  197. data/manual/html/opennodes.html +66 -0
  198. data/manual/html/overtime.booking.html +76 -0
  199. data/manual/html/period.column.html +67 -0
  200. data/manual/html/period.limit.html +69 -0
  201. data/manual/html/period.report.html +69 -0
  202. data/manual/html/period.task.html +69 -0
  203. data/manual/html/persistent.html +66 -0
  204. data/manual/html/precedes.html +86 -0
  205. data/manual/html/priority.html +114 -0
  206. data/manual/html/priority.timesheet.html +68 -0
  207. data/manual/html/project.html +88 -0
  208. data/manual/html/projectid.html +66 -0
  209. data/manual/html/projectid.task.html +68 -0
  210. data/manual/html/projectids.html +66 -0
  211. data/manual/html/projection.html +75 -0
  212. data/manual/html/prolog.html +72 -0
  213. data/manual/html/properties.html +64 -0
  214. data/manual/html/purge.html +69 -0
  215. data/manual/html/rate.html +66 -0
  216. data/manual/html/rate.resource.html +68 -0
  217. data/manual/html/reference.extend.html +77 -0
  218. data/manual/html/remaining.html +117 -0
  219. data/manual/html/replace.html +66 -0
  220. data/manual/html/report.html +333 -0
  221. data/manual/html/reportprefix.html +67 -0
  222. data/manual/html/resource.html +194 -0
  223. data/manual/html/resourceattributes.html +83 -0
  224. data/manual/html/resourceprefix.html +67 -0
  225. data/manual/html/resourcereport.html +69 -0
  226. data/manual/html/resourceroot.html +90 -0
  227. data/manual/html/resources.limit.html +82 -0
  228. data/manual/html/responsible.html +69 -0
  229. data/manual/html/richtext.extend.html +78 -0
  230. data/manual/html/right.html +66 -0
  231. data/manual/html/rollupresource.html +92 -0
  232. data/manual/html/rolluptask.html +69 -0
  233. data/manual/html/scale.column.html +87 -0
  234. data/manual/html/scenario.html +123 -0
  235. data/manual/html/scenario.ical.html +67 -0
  236. data/manual/html/scenarios.export.html +66 -0
  237. data/manual/html/scenarios.html +66 -0
  238. data/manual/html/scenariospecific.extend.html +68 -0
  239. data/manual/html/scheduled.html +68 -0
  240. data/manual/html/scheduling.html +74 -0
  241. data/manual/html/select.html +86 -0
  242. data/manual/html/selfcontained.html +66 -0
  243. data/manual/html/shift.html +128 -0
  244. data/manual/html/shift.resource.html +74 -0
  245. data/manual/html/shift.task.html +74 -0
  246. data/manual/html/shift.timesheet.html +70 -0
  247. data/manual/html/shifts.allocate.html +71 -0
  248. data/manual/html/shifts.resource.html +73 -0
  249. data/manual/html/shifts.task.html +73 -0
  250. data/manual/html/shorttimeformat.html +67 -0
  251. data/manual/html/sloppy.booking.html +77 -0
  252. data/manual/html/sloppy.projection.html +66 -0
  253. data/manual/html/sortjournalentries.html +81 -0
  254. data/manual/html/sortresources.html +73 -0
  255. data/manual/html/sorttasks.html +73 -0
  256. data/manual/html/start.column.html +67 -0
  257. data/manual/html/start.html +78 -0
  258. data/manual/html/start.limit.html +69 -0
  259. data/manual/html/start.report.html +69 -0
  260. data/manual/html/startcredit.html +68 -0
  261. data/manual/html/status.statussheet.html +73 -0
  262. data/manual/html/status.timesheet.html +91 -0
  263. data/manual/html/statussheet.html +124 -0
  264. data/manual/html/statussheetreport.html +125 -0
  265. data/manual/html/strict.projection.html +66 -0
  266. data/manual/html/summary.html +69 -0
  267. data/manual/html/supplement.html +108 -0
  268. data/manual/html/supplement.resource.html +195 -0
  269. data/manual/html/supplement.task.html +329 -0
  270. data/manual/html/tagfile.html +73 -0
  271. data/manual/html/task.html +320 -0
  272. data/manual/html/task.statussheet.html +74 -0
  273. data/manual/html/task.timesheet.html +89 -0
  274. data/manual/html/taskattributes.html +115 -0
  275. data/manual/html/taskprefix.html +67 -0
  276. data/manual/html/taskreport.html +69 -0
  277. data/manual/html/taskroot.html +103 -0
  278. data/manual/html/text.extend.html +77 -0
  279. data/manual/html/textreport.html +66 -0
  280. data/manual/html/timeformat.html +160 -0
  281. data/manual/html/timeoff.nikureport.html +71 -0
  282. data/manual/html/timesheet.html +129 -0
  283. data/manual/html/timesheetreport.html +107 -0
  284. data/manual/html/timezone.export.html +66 -0
  285. data/manual/html/timezone.html +72 -0
  286. data/manual/html/timezone.report.html +66 -0
  287. data/manual/html/timezone.shift.html +70 -0
  288. data/manual/html/timingresolution.html +71 -0
  289. data/manual/html/title.column.html +67 -0
  290. data/manual/html/title.html +68 -0
  291. data/manual/html/toc.html +1330 -0
  292. data/manual/html/tooltip.column.html +72 -0
  293. data/manual/html/trackingscenario.html +80 -0
  294. data/manual/html/treelevel.html +66 -0
  295. data/manual/html/vacation.html +71 -0
  296. data/manual/html/vacation.resource.html +73 -0
  297. data/manual/html/vacation.shift.html +71 -0
  298. data/manual/html/warn.html +69 -0
  299. data/manual/html/weeklymax.html +99 -0
  300. data/manual/html/weeklymin.html +99 -0
  301. data/manual/html/weekstartsmonday.html +66 -0
  302. data/manual/html/weekstartssunday.html +66 -0
  303. data/manual/html/width.column.html +66 -0
  304. data/manual/html/work.html +105 -0
  305. data/manual/html/workinghours.project.html +102 -0
  306. data/manual/html/workinghours.resource.html +79 -0
  307. data/manual/html/workinghours.shift.html +81 -0
  308. data/manual/html/yearlyworkingdays.html +70 -0
  309. data/spec/StatusSheets_spec.rb +0 -6
  310. data/spec/TimeSheets_spec.rb +0 -6
  311. data/spec/Tj3Daemon_spec.rb +2 -0
  312. data/spec/support/DaemonControl.rb +10 -0
  313. data/taskjuggler.gemspec +71 -0
  314. data/tasks/changelog.rake +2 -2
  315. data/tasks/gem.rake +50 -21
  316. data/tasks/manual.rake +1 -1
  317. data/tasks/rdoc.rake +5 -12
  318. data/tasks/spec.rake +1 -1
  319. data/tasks/test.rake +5 -8
  320. data/test/ReferenceGenerator.rb +91 -0
  321. data/test/TestSuite/CSV-Reports/refs/resourcereport.csv +4 -4
  322. data/test/TestSuite/ReportGenerator/Correct/Journal.tjp +21 -0
  323. data/test/TestSuite/ReportGenerator/Correct/JournalMode.tjp +124 -0
  324. data/test/TestSuite/ReportGenerator/Correct/refs/Alerts-1.csv +124 -124
  325. data/test/TestSuite/ReportGenerator/Correct/refs/Journal-1.csv +1 -7
  326. data/test/TestSuite/ReportGenerator/Correct/refs/Journal-2.csv +7 -3
  327. data/test/TestSuite/ReportGenerator/Correct/refs/JournalMode-1.csv +79 -0
  328. data/test/TestSuite/ReportGenerator/Correct/refs/JournalMode-2.csv +208 -0
  329. data/test/TjpGen.rb +152 -0
  330. metadata +1290 -741
  331. data/benchmarks/666tasks.tjp +0 -3183
  332. data/benchmarks/allocate.tjp +0 -30
  333. data/benchmarks/allocatedSlots.tjp +0 -1602
  334. data/benchmarks/booking.tjp +0 -76
  335. data/benchmarks/depends.tjp +0 -113
  336. data/benchmarks/gantt.tjp +0 -57
  337. data/benchmarks/htmltaskreport.tjp +0 -71
  338. data/benchmarks/icons/details.png +0 -0
  339. data/benchmarks/icons/flag-green.png +0 -0
  340. data/benchmarks/icons/flag-red.png +0 -0
  341. data/benchmarks/icons/flag-yellow.png +0 -0
  342. data/benchmarks/icons/resource.png +0 -0
  343. data/benchmarks/icons/resourcegroup.png +0 -0
  344. data/benchmarks/icons/task.png +0 -0
  345. data/benchmarks/icons/taskgroup.png +0 -0
  346. data/benchmarks/icons/trend-down.png +0 -0
  347. data/benchmarks/icons/trend-flat.png +0 -0
  348. data/benchmarks/icons/trend-up.png +0 -0
  349. data/benchmarks/runbench.rb +0 -30
  350. data/benchmarks/scripts/wz_tooltip.js +0 -1301
  351. data/gem_spec.rb +0 -37
  352. data/lib/exchangebug.rb +0 -42
  353. data/lib/ruby-signal-bug.rb +0 -55
  354. data/prj_cfg.rb +0 -50
  355. data/tasks/csts.rake +0 -72
  356. data/tasks/rcov.rake +0 -14
  357. data/tasks/rexml_fix.rb +0 -16
  358. data/tasks/rexml_fix_19.rb +0 -49
  359. data/tasks/show.rake +0 -21
  360. data/tasks/stats.rake +0 -25
  361. data/test/TestSuite/Export-Reports/refs/DST.tjp +0 -60
  362. data/test/TestSuite/Export-Reports/refs/ReleasePlan.tjp +0 -80
  363. data/test/TestSuite/Export-Reports/tp.tjp +0 -49
  364. data/test/TestSuite/HTML-Reports/Alerts.html +0 -424
  365. data/test/TestSuite/HTML-Reports/TimeSheet.html +0 -79
  366. data/test/TestSuite/HTML-Reports/css/tjmanual.css +0 -86
  367. data/test/TestSuite/HTML-Reports/css/tjreport.css +0 -413
  368. data/test/TestSuite/HTML-Reports/icons/details.png +0 -0
  369. data/test/TestSuite/HTML-Reports/icons/flag-green.png +0 -0
  370. data/test/TestSuite/HTML-Reports/icons/flag-red.png +0 -0
  371. data/test/TestSuite/HTML-Reports/icons/flag-yellow.png +0 -0
  372. data/test/TestSuite/HTML-Reports/icons/resource.png +0 -0
  373. data/test/TestSuite/HTML-Reports/icons/resourcegroup.png +0 -0
  374. data/test/TestSuite/HTML-Reports/icons/task.png +0 -0
  375. data/test/TestSuite/HTML-Reports/icons/taskgroup.png +0 -0
  376. data/test/TestSuite/HTML-Reports/icons/trend-down.png +0 -0
  377. data/test/TestSuite/HTML-Reports/icons/trend-flat.png +0 -0
  378. data/test/TestSuite/HTML-Reports/icons/trend-up.png +0 -0
  379. data/test/TestSuite/HTML-Reports/reference.html +0 -51
  380. data/test/TestSuite/HTML-Reports/scripts/wz_tooltip.js +0 -1301
  381. data/test/TestSuite/ReportGenerator/Correct/css/tjmanual.css +0 -86
  382. data/test/TestSuite/ReportGenerator/Correct/css/tjreport.css +0 -413
  383. data/test/TestSuite/ReportGenerator/Correct/icons/details.png +0 -0
  384. data/test/TestSuite/ReportGenerator/Correct/icons/flag-green.png +0 -0
  385. data/test/TestSuite/ReportGenerator/Correct/icons/flag-red.png +0 -0
  386. data/test/TestSuite/ReportGenerator/Correct/icons/flag-yellow.png +0 -0
  387. data/test/TestSuite/ReportGenerator/Correct/icons/resource.png +0 -0
  388. data/test/TestSuite/ReportGenerator/Correct/icons/resourcegroup.png +0 -0
  389. data/test/TestSuite/ReportGenerator/Correct/icons/task.png +0 -0
  390. data/test/TestSuite/ReportGenerator/Correct/icons/taskgroup.png +0 -0
  391. data/test/TestSuite/ReportGenerator/Correct/icons/trend-down.png +0 -0
  392. data/test/TestSuite/ReportGenerator/Correct/icons/trend-flat.png +0 -0
  393. data/test/TestSuite/ReportGenerator/Correct/icons/trend-up.png +0 -0
  394. data/test/TestSuite/ReportGenerator/Correct/opennodes.tjp +0 -26
  395. data/test/TestSuite/ReportGenerator/Correct/refs/opennodes-1.csv +0 -2
  396. data/test/TestSuite/ReportGenerator/Correct/scripts/wz_tooltip.js +0 -1301
  397. data/test/TestSuite/Scheduler/Correct/Allocate.html +0 -1075
  398. data/test/TestSuite/Scheduler/Correct/Duration.html +0 -610
  399. data/test/TestSuite/Scheduler/Correct/css/tjmanual.css +0 -85
  400. data/test/TestSuite/Scheduler/Correct/css/tjreport.css +0 -413
  401. data/test/TestSuite/Scheduler/Correct/icons/details.png +0 -0
  402. data/test/TestSuite/Scheduler/Correct/icons/flag-green.png +0 -0
  403. data/test/TestSuite/Scheduler/Correct/icons/flag-red.png +0 -0
  404. data/test/TestSuite/Scheduler/Correct/icons/flag-yellow.png +0 -0
  405. data/test/TestSuite/Scheduler/Correct/icons/resource.png +0 -0
  406. data/test/TestSuite/Scheduler/Correct/icons/resourcegroup.png +0 -0
  407. data/test/TestSuite/Scheduler/Correct/icons/task.png +0 -0
  408. data/test/TestSuite/Scheduler/Correct/icons/taskgroup.png +0 -0
  409. data/test/TestSuite/Scheduler/Correct/icons/trend-down.png +0 -0
  410. data/test/TestSuite/Scheduler/Correct/icons/trend-flat.png +0 -0
  411. data/test/TestSuite/Scheduler/Correct/icons/trend-up.png +0 -0
  412. data/test/TestSuite/Scheduler/Correct/scripts/wz_tooltip.js +0 -1301
  413. data/test/TestSuite/StatusSheetTemplates/project.tji +0 -35
  414. data/test/TestSuite/StatusSheetTemplates/project.tjp +0 -56
  415. data/test/TestSuite/StatusSheets/TimeSheets/2002-03-01/missing-reports +0 -2
  416. data/test/TestSuite/StatusSheets/TimeSheets/2002-03-01/resource1_2002-03-01.tji +0 -0
  417. data/test/TestSuite/StatusSheets/boss.tji +0 -45
  418. data/test/TestSuite/StatusSheets/boss_mail +0 -51
  419. data/test/TestSuite/StatusSheets/dev2_mail +0 -37
  420. data/test/TestSuite/StatusSheets/project.tjp +0 -275
  421. data/test/TestSuite/StatusSheets/run +0 -54
  422. data/test/TestSuite/Syntax/Correct/DST.tjp +0 -11
  423. data/test/TestSuite/Syntax/Correct/ReleasePlan.tjp +0 -32
  424. data/test/TestSuite/Syntax/Correct/css/tjmanual.css +0 -86
  425. data/test/TestSuite/Syntax/Correct/css/tjreport.css +0 -413
  426. data/test/TestSuite/Syntax/Correct/icons/details.png +0 -0
  427. data/test/TestSuite/Syntax/Correct/icons/flag-green.png +0 -0
  428. data/test/TestSuite/Syntax/Correct/icons/flag-red.png +0 -0
  429. data/test/TestSuite/Syntax/Correct/icons/flag-yellow.png +0 -0
  430. data/test/TestSuite/Syntax/Correct/icons/resource.png +0 -0
  431. data/test/TestSuite/Syntax/Correct/icons/resourcegroup.png +0 -0
  432. data/test/TestSuite/Syntax/Correct/icons/task.png +0 -0
  433. data/test/TestSuite/Syntax/Correct/icons/taskgroup.png +0 -0
  434. data/test/TestSuite/Syntax/Correct/icons/trend-down.png +0 -0
  435. data/test/TestSuite/Syntax/Correct/icons/trend-flat.png +0 -0
  436. data/test/TestSuite/Syntax/Correct/icons/trend-up.png +0 -0
  437. data/test/TestSuite/Syntax/Correct/scripts/wz_tooltip.js +0 -1301
  438. data/test/TestSuite/TimeSheets/dev2_mail1 +0 -84
  439. data/test/TestSuite/TimeSheets/dev2_mail2 +0 -87
  440. data/test/TestSuite/TimeSheets/project.tjp +0 -271
  441. data/test/TestSuite/TimeSheets/receiver.log.mod +0 -1056
  442. data/test/TestSuite/TimeSheets/run +0 -76
  443. data/test/TestSuite/TimeSheets/uu.txt +0 -29
@@ -382,7 +382,8 @@ class TaskJuggler
382
382
  end
383
383
 
384
384
  unless scanner.eos?
385
- raise "Junk found at end of macro: #{scanner.post_match}"
385
+ error('junk_at_eom',
386
+ "Junk found at end of macro: #{scanner.post_match}")
386
387
  end
387
388
 
388
389
  # Expand the macro and inject it into the scanner.
@@ -266,6 +266,9 @@ class TaskJuggler
266
266
  @properties.length
267
267
  end
268
268
 
269
+ alias length items
270
+
271
+
269
272
  # Return true if the set is empty.
270
273
  def empty?
271
274
  @properties.empty?
@@ -545,6 +545,10 @@ class TaskJuggler
545
545
  end
546
546
  end
547
547
 
548
+ def query_journal(query)
549
+ @project['journal'].to_rti(query)
550
+ end
551
+
548
552
  def query_alert(query)
549
553
  journal = @project['journal']
550
554
  query.sortable = query.numerical = alert =
@@ -38,7 +38,8 @@ class TaskJuggler
38
38
  attributeId scenario scenarioIdx
39
39
  loadUnit numberFormat currencyFormat timeFormat
40
40
  listItem listType hideJournalEntry
41
- costAccount revenueAccount selfContained)
41
+ journalMode journalAttributes sortJournalEntries
42
+ costAccount revenueAccount selfContained )
42
43
  @@ps.each do |p|
43
44
  attr_accessor p.to_sym
44
45
  end
@@ -41,115 +41,12 @@ class TaskJuggler
41
41
  @data[scenarioIdx].method(func).call(*args)
42
42
  end
43
43
 
44
- def query_journal(query)
45
- journalText(query, true)
46
- end
47
-
48
44
  def query_dashboard(query)
49
45
  dashboard(query)
50
46
  end
51
47
 
52
48
  private
53
49
 
54
- # Create a blog-style list of all alert messages that match the Query.
55
- def journalText(query, longVersion)
56
- # The components of the message are either UTF-8 text or RichText. For
57
- # the RichText components, we use the originally provided markup since
58
- # we compose the result as RichText markup first.
59
- rText = ''
60
- list = @project['journal'].entriesByResource(self, query.start, query.end,
61
- query.hideJournalEntry)
62
- # Sort all entries in buckets by their alert level.
63
- numberOfLevels = project['alertLevels'].length
64
- listByLevel = []
65
- numberOfLevels.times { |i| listByLevel[i] = [] }
66
- list.each do |entry|
67
- listByLevel[entry.alertLevel] << entry
68
- end
69
- (numberOfLevels - 1).downto(0) do |level|
70
- levelList = listByLevel[level]
71
- levelRecord = @project['alertLevels'][level]
72
- if query.selfContained
73
- alertName = "<nowiki>[</nowiki><fcol:#{levelRecord[0]}>" +
74
- "#{levelRecord[1]}</fcol><nowiki>]</nowiki>"
75
- else
76
- alertName = "[[File:icons/flag-#{levelRecord[0]}.png|" +
77
- "alt=[#{levelRecord[1]}]|text-bottom]]"
78
- end
79
- levelList.each do |entry|
80
- tsRecord = entry.timeSheetRecord
81
-
82
- if entry.property.is_a?(Task)
83
- rText += "=== #{alertName} <nowiki>#{entry.property.name}" +
84
- "</nowiki> (ID: #{entry.property.fullId}) ===\n\n"
85
- unless entry.flags.empty?
86
- rText += "'''Flags:''' #{entry.flags.join(', ')}\n\n"
87
- end
88
- if tsRecord
89
- rText += "'''Work:''' #{tsRecord.actualWorkPercent.to_i}% "
90
- if tsRecord.actualWorkPercent != tsRecord.planWorkPercent
91
- rText += "(#{tsRecord.planWorkPercent.to_i}%) "
92
- end
93
- if tsRecord.remaining
94
- rText += "'''Remaining:''' #{tsRecord.actualRemaining}d "
95
- if tsRecord.actualRemaining != tsRecord.planRemaining
96
- rText += "(#{tsRecord.planRemaining}d) "
97
- end
98
- else
99
- rText += "'''End:''' " +
100
- "#{tsRecord.actualEnd.to_s(query.timeFormat)} "
101
- if tsRecord.actualEnd != tsRecord.planEnd
102
- rText += "(#{tsRecord.planEnd.to_s(query.timeFormat)}) "
103
- end
104
- end
105
- rText += "\n\n"
106
- end
107
- elsif !(tsRecord = entry.timeSheetRecord).nil? &&
108
- entry.timeSheetRecord.task.is_a?(String)
109
- rText += "== #{alertName} <nowiki>[New Task] #{tsRecord.name} " +
110
- "</nowiki> "+
111
- "(ID: #{tsRecord.task}) ==\n\n"
112
- if tsRecord
113
- rText += "'''Work:''' #{tsRecord.actualWorkPercent}% "
114
- if tsRecord.remaining
115
- rText += "'''Remaining:''' #{tsRecord.actualRemaining}d "
116
- else
117
- rText += "'''End:''' " +
118
- "#{tsRecord.actualEnd.to_s(query.timeFormat)} "
119
- end
120
- rText += "\n\n"
121
- end
122
- else
123
- rText += "== #{alertName} Personal Notes ==\n\n"
124
- end
125
- unless entry.headline.empty?
126
- rText += "'''<nowiki>#{entry.headline}</nowiki>'''\n\n"
127
- end
128
- if entry.summary
129
- rText += entry.summary.richText.inputText + "\n\n"
130
- end
131
- if longVersion && entry.details
132
- rText += entry.details.richText.inputText + "\n\n"
133
- end
134
- end
135
- end
136
-
137
- # Now convert the RichText markup String into RichTextIntermediate
138
- # format.
139
- unless (rti = RichText.new(rText, RTFHandlers.create(@project),
140
- @project.messageHandler).
141
- generateIntermediateFormat)
142
- @project.messageHandler.warning(
143
- 'res_journal_text', 'Syntax error in journal text')
144
- return nil
145
- end
146
- # No section numbers, please!
147
- rti.sectionNumbers = false
148
- # We use a special class to allow CSS formating.
149
- rti.cssClass = 'tj_journal'
150
- query.rti = rti
151
- end
152
-
153
50
  # Create a dashboard-like list of all task that have a current alert
154
51
  # status.
155
52
  def dashboard(query)
@@ -69,9 +69,12 @@ class TaskJuggler
69
69
  raise "No Query has been registered for this RichText yet!"
70
70
  end
71
71
 
72
+ query = @query.dup
73
+
72
74
  # Check the user provided arguments. Only the following list is allowed.
73
- validArgs = %w( family property scopeproperty attribute scenario
74
- start end loadunit numberformat timeformat currencyformat )
75
+ validArgs = %w( attribute currencyformat end family journalattributes
76
+ journalmode loadunit numberformat property scenario
77
+ scopeproperty start timeformat )
75
78
  expandedArgs = {}
76
79
  args.each do |arg, value|
77
80
  unless validArgs.include?(arg)
@@ -91,8 +94,6 @@ class TaskJuggler
91
94
  "provide a family type as well.")
92
95
  end
93
96
 
94
- query = @query.dup
95
-
96
97
  # Every provided query parameter will overwrite the corresponding value
97
98
  # in the Query that was provided by the ReportContext. The name of the
98
99
  # arguments don't always exactly match the Query variables Let's start
@@ -115,11 +116,14 @@ class TaskJuggler
115
116
  if expandedArgs['currencyformat']
116
117
  query.currencyFormat = expandedArgs['currencyformat']
117
118
  end
119
+ query.project = @project
118
120
 
119
121
  # And now the slighly more complicated ones.
120
122
  setScenarioIdx(query, expandedArgs)
121
123
  setPropertyType(query, expandedArgs)
122
124
  setLoadUnit(query, expandedArgs)
125
+ setJournalMode(query, expandedArgs)
126
+ setJournalAttributes(query, expandedArgs)
123
127
 
124
128
  # Now that we have put together the query, we can process it and return
125
129
  # the query object for result extraction.
@@ -177,6 +181,40 @@ class TaskJuggler
177
181
  query.scenarioIdx = 0 unless query.scenarioIdx
178
182
  end
179
183
 
184
+ def setJournalMode(query, args)
185
+ if (mode = args['journalmode'])
186
+ validModes = %w( journal journal_sub status_up status_down alerts_down )
187
+ unless validModes.include?(mode)
188
+ error('rtfq_bad_journalmode',
189
+ "Unknown journalmode #{mode}. Must be one of " +
190
+ "#{validModes.join(', ')}.")
191
+ end
192
+ query.journalMode = mode.intern
193
+ elsif !query.journalMode
194
+ query.journalMode = :journal
195
+ end
196
+ end
197
+
198
+ def setJournalAttributes(query, args)
199
+ if (attrListStr = args['journalattributes'])
200
+ attrs = attrListStr.split(', ').map { |a| a.delete(' ') }
201
+ query.journalAttributes = []
202
+ validAttrs = %w( author date details flags headline property propertyid
203
+ summary timesheet )
204
+ attrs.each do |attr|
205
+ if validAttrs.include?(attr)
206
+ query.journalAttributes << attr
207
+ else
208
+ error('rtfq_bad_journalattr',
209
+ "Unknown journalattribute #{attr}. Must be one of " +
210
+ "#{validAttrs.join(', ')}.")
211
+ end
212
+ end
213
+ elsif !query.journalAttributes
214
+ query.journalAttributes = %w( date summary details )
215
+ end
216
+ end
217
+
180
218
  end
181
219
 
182
220
  end
@@ -85,26 +85,6 @@ class TaskJuggler
85
85
  text
86
86
  end
87
87
 
88
- # Convert all CR+LF and CR line breaks into LF line breaks.
89
- def fixLineBreaks(text)
90
- out = ''
91
- cr = false
92
- text.each_utf8_char do |c|
93
- if c == "\r"
94
- # We don't know yet if it's a CR or CR+LF.
95
- cr = true
96
- else
97
- if cr
98
- # If we only found a CR. Replace it with a LF.
99
- out << "\n" if c != "\n"
100
- cr = false
101
- end
102
- out << c
103
- end
104
- end
105
- out
106
- end
107
-
108
88
  def setWorkingDir
109
89
  # Make sure the user has provided a properly setup config file.
110
90
  error('\'smtpServer\' not configured') unless @smtpServer
@@ -80,31 +80,27 @@ class TaskJuggler
80
80
 
81
81
  createDirectories
82
82
 
83
- # Read the RFC 822 compliant mail from STDIN.
84
- rawMail = $stdin.read
85
-
86
- # To get line-accurate error reports for encoding errors, we scan the
87
- # email for obvious ecoding errors and try to get a sender fallback
88
- # address. This will not find encoding problems inside encoded mime
89
- # parts.
90
- fromLine = nil
91
83
  begin
84
+ # Read the RFC 822 compliant mail from STDIN.
85
+ rawMail = $stdin.read
86
+ rawMail = rawMail.forceUTF8Encoding
87
+
88
+ mail = Mail.new(rawMail)
89
+ rescue
90
+ # In certain cases, Mail will fail to create the Mail object. Since we
91
+ # don't have the email sender yet, we have to try to extract it
92
+ # ourself.
93
+ fromLine = nil
92
94
  rawMail.each_line do |line|
93
95
  unless fromLine
94
- matches = line.encode('UTF-8', :invalid => :replace,
95
- :replace => '?').match('^From: .*')
96
- fromLine = matches[0] if matches
97
- end
98
- begin
99
- # Try the encoding. If it fails, we'll get an exception.
100
- line.encode!('UTF-8')
101
- rescue
102
- raise "Encoding error in line: #{line.encode('UTF-8', :invalid)}"
96
+ matches = line.match('^From: .*')
97
+ if matches
98
+ fromLine = matches[0]
99
+ break
100
+ end
103
101
  end
104
102
  end
105
103
 
106
- mail = Mail.new(rawMail)
107
- rescue
108
104
  # Try to extract the mail sender the dirty way so we can at least send
109
105
  # a response to the submitter.
110
106
  @submitter = fromLine[6..-1] if fromLine && fromLine.is_a?(String)
@@ -150,8 +146,14 @@ EOT
150
146
 
151
147
  # Isolate the actual syntax from _sheet_ and process it.
152
148
  def processSheet(sheet)
153
- @sheet = fixLineBreaks(sheet)
154
- @sheet = cutOut(@sheet) unless @sheetWasAttached
149
+ @sheet = @sheetWasAttached ? cutOut(sheet) : sheet
150
+
151
+ begin
152
+ @sheet = @sheet.forceUTF8Encoding
153
+ rescue
154
+ error($!)
155
+ end
156
+
155
157
  # A valid sheet must have the poper header line.
156
158
  if @sheetHeader.match(@sheet)
157
159
  checkSignature(@sheet)
@@ -32,10 +32,6 @@ class TaskJuggler
32
32
  @data[scenarioIdx].readyForScheduling?
33
33
  end
34
34
 
35
- def query_journal(query)
36
- journalText(query, true, false)
37
- end
38
-
39
35
  def query_journal_sub(query)
40
36
  journalText(query, true, true)
41
37
  end
@@ -55,7 +51,9 @@ class TaskJuggler
55
51
  list = @project['journal'].entriesByTask(self, query.start, query.end,
56
52
  query.hideJournalEntry)
57
53
  end
58
- list.reverse.each do |entry|
54
+ list.setSorting([ [ :alert, -1 ], [ :date, -1 ], [ :seqno, 1 ] ])
55
+ list.sort!
56
+ list.each do |entry|
59
57
  tsRecord = entry.timeSheetRecord
60
58
 
61
59
  if entry.property.is_a?(Task)
@@ -303,6 +303,10 @@ class TaskJuggler
303
303
  'scenarioIdx' => @project['trackingScenarioIdx'],
304
304
  'start' => ts.interval.start,
305
305
  'end' => ts.interval.end,
306
+ 'journalMode' => :journal,
307
+ 'journalAttributes' => %w( alert property headline flags
308
+ timesheet summary details ),
309
+ 'sortJournalEntries' => [ [ :seqno, 1 ] ],
306
310
  'timeFormat' => '%Y-%m-%d',
307
311
  'selfContained' => true }
308
312
  query = Query.new(queryAttrs)
@@ -29,7 +29,7 @@ class TaskJuggler
29
29
  %w( allocate assignedresources booking charge chargeset complete
30
30
  criticalness depends duration effort end forward length
31
31
  maxend maxstart minend minstart milestone pathcriticalness
32
- precedes scheduled shifts start status ).each do |attr|
32
+ precedes priority scheduled shifts start status ).each do |attr|
33
33
  @property[attr, @scenarioIdx]
34
34
  end
35
35
 
@@ -80,7 +80,7 @@ class TaskJuggler
80
80
  if @start && @end && @effort == 0 && @length == 0 && @duration == 0 &&
81
81
  @allocate.empty?
82
82
  @scheduled = true
83
- Log << "Task #{@property.fullId}: #{@start} -> #{@end}"
83
+ Log.msg { "Task #{@property.fullId}: #{period_to_s}" }
84
84
  end
85
85
 
86
86
  # Collect the limits of this task and all parent tasks into a single
@@ -153,19 +153,19 @@ class TaskJuggler
153
153
  def propagateInitialValues
154
154
  unless @startPropagated
155
155
  if @start
156
- propagateDate(@start, false)
156
+ propagateDate(@start, false, true)
157
157
  elsif @property.parent.nil? &&
158
158
  @property.canInheritDate?(@scenarioIdx, false)
159
- propagateDate(@project['start'], false)
159
+ propagateDate(@project['start'], false, true)
160
160
  end
161
161
  end
162
162
 
163
163
  unless @endPropagated
164
164
  if @end
165
- propagateDate(@end, true)
165
+ propagateDate(@end, true, true)
166
166
  elsif @property.parent.nil? &&
167
167
  @property.canInheritDate?(@scenarioIdx, true)
168
- propagateDate(@project['end'], true)
168
+ propagateDate(@project['end'], true, true)
169
169
  end
170
170
  end
171
171
  end
@@ -895,6 +895,8 @@ class TaskJuggler
895
895
  # Check if the task has already been scheduled e. g. by propagateDate().
896
896
  return true if @scheduled
897
897
 
898
+ logTag = "schedule_#{@property.id}"
899
+ Log.enter(logTag, "Scheduling task #{@property.id}")
898
900
  # Compute the date of the next slot this task wants to have scheduled.
899
901
  # This must either be the first slot ever or it must be directly
900
902
  # adjecent to the previous slot. If this task has not yet been scheduled
@@ -927,16 +929,21 @@ class TaskJuggler
927
929
  @currentSlotIdx += delta
928
930
  if @currentSlotIdx < lowerLimit || upperLimit < @currentSlotIdx
929
931
  markAsRunaway
932
+ Log.exit(logTag, "Scheduling of task #{@property.id} failed")
930
933
  return false
931
934
  end
932
935
  end
933
936
 
937
+ Log.exit(logTag, "Scheduling of task #{@property.id} completed")
934
938
  true
935
939
  end
936
940
 
937
941
  # Set a new start or end date and propagate the value to all other
938
942
  # task ends that have a direct dependency to this end of the task.
939
943
  def propagateDate(date, atEnd, ignoreEffort = false)
944
+ logTag = "propagateDate_#{@property.id}_#{atEnd ? 'end' : 'start'}"
945
+ Log.enter(logTag, "Propagating #{atEnd ? 'end' : 'start'} date " +
946
+ "to task #{@property.id}")
940
947
  thisEnd = atEnd ? 'end' : 'start'
941
948
  otherEnd = atEnd ? 'start' : 'end'
942
949
  #puts "Propagating #{thisEnd} date #{date} of #{@property.fullId} " +
@@ -954,7 +961,7 @@ class TaskJuggler
954
961
  # are only set in scheduleContainer().
955
962
  if @property.leaf?
956
963
  instance_variable_set(('@' + thisEnd).intern, date)
957
- Log << "Task #{@property.fullId}: #{@start} -> #{@end}"
964
+ Log.msg { "Task #{@property.fullId}: #{period_to_s}" }
958
965
  end
959
966
 
960
967
  if @milestone
@@ -963,12 +970,12 @@ class TaskJuggler
963
970
  if a(otherEnd).nil?
964
971
  propagateDate(a(thisEnd), !atEnd)
965
972
  end
966
- Log << "Milestone #{@property.fullId}: #{@start} -> #{@end}"
973
+ Log.msg { "Milestone #{@property.fullId}: #{period_to_s}" }
967
974
  elsif !@scheduled && @start && @end &&
968
975
  !(@length == 0 && @duration == 0 && @effort == 0 &&
969
976
  !@allocate.empty?)
970
977
  @scheduled = true
971
- Log << "Task #{@property.fullId} has been scheduled"
978
+ Log.msg { "Task #{@property.fullId} has been scheduled" }
972
979
  end
973
980
 
974
981
  # Propagate date to all dependent tasks. Don't do this for start
@@ -1010,9 +1017,11 @@ class TaskJuggler
1010
1017
  @property.parents.each do |parent|
1011
1018
  parent.scheduleContainer(@scenarioIdx)
1012
1019
  end
1020
+ Log.exit(logTag, "Finished propagation of " +
1021
+ "#{atEnd ? 'end' : 'start'} date " +
1022
+ "to task #{@property.id}")
1013
1023
  end
1014
1024
 
1015
-
1016
1025
  # This function determines if a task can inherit the start or end date
1017
1026
  # from a parent task or the project time frame. +atEnd+ specifies whether
1018
1027
  # the check should be done for the task end (true) or task start (false).
@@ -1034,13 +1043,15 @@ class TaskJuggler
1034
1043
  thisEnd, thatEnd = atEnd ? [ 'end', 'start' ] : [ 'start', 'end' ]
1035
1044
  # Return false if we already have a date for this end or if we have a
1036
1045
  # strong dependency for this end.
1037
- return false if a(thisEnd) || hasStrongDeps(atEnd)
1046
+ return false if instance_variable_get('@' + thisEnd) ||
1047
+ hasStrongDeps?(atEnd)
1038
1048
 
1039
1049
  # Containter task can inherit the date if they have no dependencies at
1040
1050
  # this end.
1041
1051
  return true if @property.container?
1042
1052
 
1043
- hasThatSpec = a(thatEnd) || hasStrongDeps(!atEnd)
1053
+ hasThatSpec = !instance_variable_get('@' + thatEnd).nil? ||
1054
+ hasStrongDeps?(!atEnd)
1044
1055
  hasDurationSpec = hasDurationSpec?
1045
1056
 
1046
1057
  # Check for tasks that have no start and end spec, no duration spec but
@@ -1054,8 +1065,8 @@ class TaskJuggler
1054
1065
  return hasThatSpec
1055
1066
  else
1056
1067
  # the scheduling direction is pointing towards this end
1057
- return a(thatEnd) && !hasDurationSpec &&
1058
- @booking.empty? #&& @allocate.empty?
1068
+ return !instance_variable_get('@' + thatEnd).nil? &&
1069
+ !hasDurationSpec && @booking.empty? #&& @allocate.empty?
1059
1070
  end
1060
1071
  end
1061
1072
 
@@ -1097,7 +1108,7 @@ class TaskJuggler
1097
1108
  raise "Start (#{@start}) and end (#{@end}) must be set"
1098
1109
  end
1099
1110
  @scheduled = true
1100
- Log << "Container task #{@property.fullId} completed: #{@start} -> #{@end}"
1111
+ Log.msg { "Container task #{@property.fullId} completed: #{period_to_s}" }
1101
1112
 
1102
1113
  # If we have modified the start or end date, we need to communicate this
1103
1114
  # new date to surrounding tasks.
@@ -1327,6 +1338,22 @@ class TaskJuggler
1327
1338
  query.assignList(list)
1328
1339
  end
1329
1340
 
1341
+ def query_maxend(query)
1342
+ queryDateLimit(query, @maxend)
1343
+ end
1344
+
1345
+ def query_minend(query)
1346
+ queryDateLimit(query, @minend)
1347
+ end
1348
+
1349
+ def query_maxstart(query)
1350
+ queryDateLimit(query, @maxstart)
1351
+ end
1352
+
1353
+ def query_minstart(query)
1354
+ queryDateLimit(query, @minstart)
1355
+ end
1356
+
1330
1357
  def query_precursors(query)
1331
1358
  list = []
1332
1359
 
@@ -1744,15 +1771,15 @@ class TaskJuggler
1744
1771
  if @effort > 0 && @assignedresources.empty?
1745
1772
  if @forward
1746
1773
  @start = @project.idxToDate(@currentSlotIdx)
1747
- Log << "Task #{@property.fullId} first assignment: " +
1748
- "#{@start} -> #{@end}"
1774
+ Log.msg { "Task #{@property.fullId} first assignment: " +
1775
+ "#{period_to_s}" }
1749
1776
  @startsuccs.each do |task, onEnd|
1750
1777
  task.propagateDate(@scenarioIdx, @start, false, true)
1751
1778
  end
1752
1779
  else
1753
1780
  @end = @project.idxToDate(@currentSlotIdx + 1)
1754
- Log << "Task #{@property.fullId} last assignment: " +
1755
- "#{@start} -> #{@end}"
1781
+ Log.msg { "Task #{@property.fullId} last assignment: " +
1782
+ "#{period_to_s}" }
1756
1783
  @endpreds.each do |task, onEnd|
1757
1784
  task.propagateDate(@scenarioIdx, @end, true, true)
1758
1785
  end
@@ -1843,8 +1870,7 @@ class TaskJuggler
1843
1870
  firstSlotDate = @project.idxToDate(firstSlotIdx)
1844
1871
  if @start.nil? || firstSlotDate > @start
1845
1872
  @start = firstSlotDate
1846
- Log << "Task #{@property.fullId} first booking: " +
1847
- "#{@start} -> #{@end}"
1873
+ Log.msg { "Task #{@property.fullId} first booking: #{period_to_s}" }
1848
1874
  end
1849
1875
  end
1850
1876
 
@@ -1965,82 +1991,18 @@ class TaskJuggler
1965
1991
  false
1966
1992
  end
1967
1993
 
1968
- def hasStrongDeps(atEnd)
1969
- # A dependency that could determine the date on this side of the
1970
- # dependency is a strong dependency. If the scheduling direction of the
1971
- # task on the other side leads away from the dependency point, then the
1972
- # dependency is weak. This date will influence the other date for weak
1973
- # dependencies. > means ASAP task, < means ALAP task.
1974
- #
1975
- #
1976
- # T2 depends on T1 start
1977
- #
1978
- # +--- SS -> S> : Weak
1979
- # |-+ SS -> S< : Weak
1980
- # +-|- SP -> S> : Strong
1981
- # | +--- SP -> S< : Strong
1982
- # +-|
1983
- # +---
1984
- #
1985
- #
1986
- # T2 depends on T1 end
1987
- # T1 precedes T2 start
1988
- #
1989
- # ---+ ES -> S> : Weak
1990
- # |-+ ES -> S< : Strong
1991
- # ---+ | SP -> E> : Strong
1992
- # | +--- SP -> E< : Weak
1993
- # +-|
1994
- # +---
1995
- #
1996
- #
1997
- # T1 precedes T2 end
1998
- #
1999
- # ---+ ES -> E> : Strong
2000
- # +-| ES -> E< : Strong
2001
- # -|-+ EP -> E> : Weak
2002
- # ---+ | EP -> E< : Weak
2003
- # |-+
2004
- # ---+
2005
- #
2006
- # All other combinations are illegal and should be caught earlier. So,
2007
- # illegal values can be considered don't care values.
2008
- #
2009
- # f/t S> S< E> E<
2010
- # SP S S S W Row 1
2011
- # SS W W x x Row 2
2012
- # EP x x W W Row 3
2013
- # ES W S S S Row 4
2014
- #
2015
- # If the other end of the dependency already has a date, it's a strong
2016
- # dependency no matter how it was set.
2017
- unless atEnd
2018
- # Row 1
2019
- @startpreds.each do |task, onEnd|
2020
- if (onEnd && (task['forward', @scenarioIdx] ||
2021
- task['end', @scenarioIdx])) || !onEnd
2022
- return true
2023
- end
2024
- end
2025
- # Row 2
2026
- @startsuccs.each do |task, onEnd|
2027
- return true if task[onEnd ? 'end' : 'start', @scenarioIdx]
2028
- end
1994
+ # Return true if the task has a 'strong' dependency at the start if
1995
+ # _atEnd_ is false or at the end. A 'strong' dependency is an outer
1996
+ # dependency. At the start a predecessor is strong, and the end a
1997
+ # successor. start successors or end predecessors are considered weak
1998
+ # dependencies since this task will always have to get the date first and
1999
+ # then pass it on to the inner dependencies.
2000
+ def hasStrongDeps?(atEnd)
2001
+ if atEnd
2002
+ return !@endsuccs.empty?
2029
2003
  else
2030
- # Row 3
2031
- @endpreds.each do |task, onEnd|
2032
- return true if task[onEnd ? 'end' : 'start', @scenarioIdx]
2033
- end
2034
- # Row 4
2035
- @endsuccs.each do |task, onEnd|
2036
- if (!onEnd && (!task['forward', @scenarioIdx] ||
2037
- task['start', @scenarioIdx])) || onEnd
2038
- return true
2039
- end
2040
- end
2004
+ return !@startpreds.empty?
2041
2005
  end
2042
-
2043
- false
2044
2006
  end
2045
2007
 
2046
2008
  def markAsRunaway
@@ -2150,7 +2112,7 @@ class TaskJuggler
2150
2112
 
2151
2113
  # Looks like it is ok to propagate the date.
2152
2114
  task.propagateDate(@scenarioIdx, nDate, atEnd)
2153
- # puts "Propagate #{atEnd ? 'end' : 'start'} to dep. #{task.fullId} done"
2115
+ #puts "Propagate #{atEnd ? 'end' : 'start'} to dep. #{task.fullId} done"
2154
2116
  end
2155
2117
 
2156
2118
  # This is a helper function for calcPathCriticalness(). It computes the
@@ -2202,7 +2164,13 @@ class TaskJuggler
2202
2164
  else
2203
2165
  # The task is in progress. Calculate the current completion
2204
2166
  # degree.
2205
- if !property.leaf?
2167
+ if @end <= @project['now']
2168
+ # The task has ended already. It's 100% complete.
2169
+ completion = 100.0
2170
+ elsif @project['now'] <= @start
2171
+ # The task has not started yet. Its' 0% complete.
2172
+ completion = 0.0
2173
+ elsif !property.leaf?
2206
2174
  # For container task the completion degree is the average of the
2207
2175
  # sub tasks.
2208
2176
  completion = 0.0
@@ -2211,12 +2179,6 @@ class TaskJuggler
2211
2179
  completion += comp
2212
2180
  end
2213
2181
  completion /= @property.children.length
2214
- elsif @end <= @project['now']
2215
- # The task has ended already. It's 100% complete.
2216
- completion = 100.0
2217
- elsif @project['now'] <= @start
2218
- # The task has not started yet. Its' 0% complete.
2219
- completion = 0.0
2220
2182
  elsif @effort > 0
2221
2183
  # Effort based leaf tasks. The completion degree is the percentage
2222
2184
  # of effort that has been done already.
@@ -2420,6 +2382,22 @@ class TaskJuggler
2420
2382
  @property['booking', @property.project.scenarioIdx(scenario)]
2421
2383
  end
2422
2384
 
2385
+ # Date limits may be nil and this is not an error. TjTime.to_s() would
2386
+ # report it as such if we don't use this wrapper method.
2387
+ def queryDateLimit(query, date)
2388
+ if date
2389
+ query.sortable = query.numerical = date
2390
+ query.string = date.to_s(query.timeFormat)
2391
+ else
2392
+ query.sortable = query.numerical = -1
2393
+ query.string = ''
2394
+ end
2395
+ end
2396
+
2397
+ def period_to_s
2398
+ "#{@start ? @start.to_s : '<?>'} -> #{@end ? @end.to_s : '<?>'}"
2399
+ end
2400
+
2423
2401
  end
2424
2402
 
2425
2403
  end