taskjuggler 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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