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.
- data/{tasks/missing.rake → .gemtest} +0 -0
- data/CHANGELOG +27 -0
- data/Rakefile +8 -9
- data/bin/tj3 +2 -1
- data/bin/tj3client +2 -1
- data/bin/tj3d +2 -1
- data/bin/tj3man +2 -1
- data/bin/tj3ss_receiver +2 -1
- data/bin/tj3ss_sender +2 -1
- data/bin/tj3ts_receiver +2 -1
- data/bin/tj3ts_sender +2 -1
- data/bin/tj3ts_summary +2 -1
- data/data/tjp.vim +425 -419
- data/examples/Fedora-20/f-20.tjp +2442 -0
- data/examples/Fedora-20/icons/fedoralogo.png +0 -0
- data/examples/Fedora-20/reports.tji +423 -0
- data/lib/header.tmpl +13 -0
- data/lib/taskjuggler/AppConfig.rb +5 -0
- data/lib/taskjuggler/Attributes.rb +22 -0
- data/lib/taskjuggler/Journal.rb +273 -10
- data/lib/taskjuggler/Log.rb +9 -8
- data/lib/taskjuggler/Project.rb +28 -60
- data/lib/taskjuggler/ProjectFileScanner.rb +2 -1
- data/lib/taskjuggler/PropertySet.rb +3 -0
- data/lib/taskjuggler/PropertyTreeNode.rb +4 -0
- data/lib/taskjuggler/Query.rb +2 -1
- data/lib/taskjuggler/Resource.rb +0 -103
- data/lib/taskjuggler/RichText/RTFQuery.rb +42 -4
- data/lib/taskjuggler/SheetHandlerBase.rb +0 -20
- data/lib/taskjuggler/SheetReceiver.rb +23 -21
- data/lib/taskjuggler/Task.rb +3 -5
- data/lib/taskjuggler/TaskJuggler.rb +4 -0
- data/lib/taskjuggler/TaskScenario.rb +81 -103
- data/lib/taskjuggler/TextParser/Scanner.rb +19 -18
- data/lib/taskjuggler/Tj3Config.rb +1 -1
- data/lib/taskjuggler/TjpSyntaxRules.rb +180 -45
- data/lib/taskjuggler/UTF8String.rb +30 -0
- data/lib/taskjuggler/apps/Tj3.rb +1 -1
- data/lib/taskjuggler/apps/Tj3Man.rb +54 -2
- data/lib/taskjuggler/reports/ICalReport.rb +4 -4
- data/lib/taskjuggler/reports/NikuReport.rb +6 -0
- data/lib/taskjuggler/reports/Report.rb +5 -5
- data/lib/taskjuggler/reports/ReportContext.rb +4 -2
- data/lib/taskjuggler/reports/ResourceListRE.rb +10 -1
- data/lib/taskjuggler/reports/StatusSheetReport.rb +3 -0
- data/lib/taskjuggler/reports/TableReport.rb +8 -3
- data/lib/taskjuggler/reports/TimeSheetReport.rb +3 -0
- data/lib/updateheader.sh +15 -0
- data/manual/Installation +11 -22
- data/manual/Software +17 -3
- data/manual/html/Day_To_Day_Juggling.html +359 -0
- data/manual/html/Getting_Started.html +62 -0
- data/manual/html/How_To_Contribute.html +88 -0
- data/manual/html/Installation.html +172 -0
- data/manual/html/Intro.html +74 -0
- data/manual/html/Reporting_Bugs.html +47 -0
- data/manual/html/Rich_Text_Attributes.html +174 -0
- data/manual/html/Software.html +147 -0
- data/manual/html/TaskJuggler_2x_Migration.html +71 -0
- data/manual/html/TaskJuggler_Internals.html +61 -0
- data/manual/html/The_TaskJuggler_Syntax.html +89 -0
- data/manual/html/Tutorial.html +498 -0
- data/manual/html/account.html +152 -0
- data/manual/html/account.task.html +68 -0
- data/manual/html/accountprefix.html +67 -0
- data/manual/html/active.html +66 -0
- data/manual/html/adopt.task.html +73 -0
- data/manual/html/alert level.html +66 -0
- data/manual/html/alert.html +66 -0
- data/manual/html/allocate.html +92 -0
- data/manual/html/alphabet.html +33 -0
- data/manual/html/alternative.html +77 -0
- data/manual/html/author.html +69 -0
- data/manual/html/balance.html +73 -0
- data/manual/html/booking.resource.html +122 -0
- data/manual/html/booking.task.html +120 -0
- data/manual/html/caption.html +96 -0
- data/manual/html/cellcolor.column.html +71 -0
- data/manual/html/celltext.column.html +68 -0
- data/manual/html/center.html +67 -0
- data/manual/html/charge.html +89 -0
- data/manual/html/chargeset.html +73 -0
- data/manual/html/columnid.html +358 -0
- data/manual/html/columns.html +73 -0
- data/manual/html/complete.html +80 -0
- data/manual/html/copyright.html +97 -0
- data/manual/html/credit.html +117 -0
- data/{benchmarks → manual/html}/css/tjmanual.css +0 -0
- data/{benchmarks → manual/html}/css/tjreport.css +0 -0
- data/manual/html/currency.html +120 -0
- data/manual/html/currencyformat.html +99 -0
- data/manual/html/dailymax.html +144 -0
- data/manual/html/dailymin.html +132 -0
- data/manual/html/dailyworkinghours.html +90 -0
- data/manual/html/date.extend.html +77 -0
- data/manual/html/date.html +100 -0
- data/manual/html/definitions.html +94 -0
- data/manual/html/depends.html +110 -0
- data/manual/html/details.html +69 -0
- data/manual/html/disabled.html +85 -0
- data/manual/html/duration.html +133 -0
- data/manual/html/efficiency.html +93 -0
- data/manual/html/effort.html +134 -0
- data/manual/html/email.html +68 -0
- data/manual/html/enabled.html +69 -0
- data/manual/html/end.column.html +67 -0
- data/manual/html/end.html +87 -0
- data/manual/html/end.limit.html +69 -0
- data/manual/html/end.report.html +99 -0
- data/manual/html/end.timesheet.html +94 -0
- data/manual/html/endcredit.html +110 -0
- data/manual/html/epilog.html +72 -0
- data/manual/html/export.html +197 -0
- data/manual/html/extend.html +87 -0
- data/manual/html/fail.html +69 -0
- data/manual/html/fdl.html +430 -0
- data/manual/html/flags.account.html +66 -0
- data/manual/html/flags.html +66 -0
- data/manual/html/flags.journalentry.html +66 -0
- data/manual/html/flags.report.html +66 -0
- data/manual/html/flags.resource.html +68 -0
- data/manual/html/flags.statussheet.html +66 -0
- data/manual/html/flags.task.html +68 -0
- data/manual/html/flags.timesheet.html +66 -0
- data/manual/html/fontcolor.column.html +71 -0
- data/manual/html/footer.html +72 -0
- data/manual/html/formats.html +80 -0
- data/manual/html/functions.html +78 -0
- data/manual/html/gapduration.html +93 -0
- data/manual/html/gaplength.html +93 -0
- data/manual/html/halign.center.html +66 -0
- data/manual/html/halign.column.html +67 -0
- data/manual/html/halign.left.html +66 -0
- data/manual/html/halign.right.html +66 -0
- data/manual/html/hasalert.html +71 -0
- data/manual/html/header.html +72 -0
- data/manual/html/headline.html +69 -0
- data/manual/html/hidejournalentry.html +69 -0
- data/manual/html/hidereport.html +67 -0
- data/manual/html/hideresource.html +73 -0
- data/manual/html/hidetask.html +73 -0
- data/manual/html/icalreport.html +137 -0
- data/manual/html/include.macro.html +70 -0
- data/manual/html/include.project.html +71 -0
- data/manual/html/include.properties.html +168 -0
- data/manual/html/index.html +18 -0
- data/manual/html/inherit.extend.html +68 -0
- data/manual/html/interval1.html +99 -0
- data/manual/html/interval2.html +98 -0
- data/manual/html/interval3.html +99 -0
- data/manual/html/interval4.html +100 -0
- data/manual/html/isactive.html +67 -0
- data/manual/html/ischildof.html +67 -0
- data/manual/html/isdependencyof.html +75 -0
- data/manual/html/isdutyof.html +71 -0
- data/manual/html/isfeatureof.html +71 -0
- data/manual/html/isleaf.html +66 -0
- data/manual/html/ismilestone.html +67 -0
- data/manual/html/isongoing.html +67 -0
- data/manual/html/isresource.html +66 -0
- data/manual/html/istask.html +66 -0
- data/manual/html/journalattributes.html +107 -0
- data/manual/html/journalentry.html +83 -0
- data/manual/html/journalmode.html +83 -0
- data/manual/html/left.html +66 -0
- data/manual/html/length.html +104 -0
- data/manual/html/limits.allocate.html +72 -0
- data/manual/html/limits.html +72 -0
- data/manual/html/limits.resource.html +80 -0
- data/manual/html/limits.task.html +113 -0
- data/manual/html/listitem.column.html +66 -0
- data/manual/html/listtype.column.html +79 -0
- data/manual/html/loadunit.html +99 -0
- data/manual/html/logicalexpression.html +110 -0
- data/manual/html/logicalflagexpression.html +82 -0
- data/manual/html/macro.html +103 -0
- data/manual/html/managers.html +109 -0
- data/manual/html/mandatory.html +66 -0
- data/manual/html/maxend.html +69 -0
- data/manual/html/maximum.html +99 -0
- data/manual/html/maxstart.html +69 -0
- data/manual/html/milestone.html +71 -0
- data/manual/html/minend.html +69 -0
- data/manual/html/minimum.html +99 -0
- data/manual/html/minstart.html +69 -0
- data/manual/html/monthlymax.html +99 -0
- data/manual/html/monthlymin.html +99 -0
- data/manual/html/navbar.html +513 -0
- data/manual/html/navigator.html +70 -0
- data/manual/html/newtask.html +83 -0
- data/manual/html/nikureport.html +216 -0
- data/manual/html/note.task.html +68 -0
- data/manual/html/now.html +67 -0
- data/manual/html/numberformat.html +85 -0
- data/manual/html/onend.html +68 -0
- data/manual/html/onstart.html +68 -0
- data/manual/html/opennodes.html +66 -0
- data/manual/html/overtime.booking.html +76 -0
- data/manual/html/period.column.html +67 -0
- data/manual/html/period.limit.html +69 -0
- data/manual/html/period.report.html +69 -0
- data/manual/html/period.task.html +69 -0
- data/manual/html/persistent.html +66 -0
- data/manual/html/precedes.html +86 -0
- data/manual/html/priority.html +114 -0
- data/manual/html/priority.timesheet.html +68 -0
- data/manual/html/project.html +88 -0
- data/manual/html/projectid.html +66 -0
- data/manual/html/projectid.task.html +68 -0
- data/manual/html/projectids.html +66 -0
- data/manual/html/projection.html +75 -0
- data/manual/html/prolog.html +72 -0
- data/manual/html/properties.html +64 -0
- data/manual/html/purge.html +69 -0
- data/manual/html/rate.html +66 -0
- data/manual/html/rate.resource.html +68 -0
- data/manual/html/reference.extend.html +77 -0
- data/manual/html/remaining.html +117 -0
- data/manual/html/replace.html +66 -0
- data/manual/html/report.html +333 -0
- data/manual/html/reportprefix.html +67 -0
- data/manual/html/resource.html +194 -0
- data/manual/html/resourceattributes.html +83 -0
- data/manual/html/resourceprefix.html +67 -0
- data/manual/html/resourcereport.html +69 -0
- data/manual/html/resourceroot.html +90 -0
- data/manual/html/resources.limit.html +82 -0
- data/manual/html/responsible.html +69 -0
- data/manual/html/richtext.extend.html +78 -0
- data/manual/html/right.html +66 -0
- data/manual/html/rollupresource.html +92 -0
- data/manual/html/rolluptask.html +69 -0
- data/manual/html/scale.column.html +87 -0
- data/manual/html/scenario.html +123 -0
- data/manual/html/scenario.ical.html +67 -0
- data/manual/html/scenarios.export.html +66 -0
- data/manual/html/scenarios.html +66 -0
- data/manual/html/scenariospecific.extend.html +68 -0
- data/manual/html/scheduled.html +68 -0
- data/manual/html/scheduling.html +74 -0
- data/manual/html/select.html +86 -0
- data/manual/html/selfcontained.html +66 -0
- data/manual/html/shift.html +128 -0
- data/manual/html/shift.resource.html +74 -0
- data/manual/html/shift.task.html +74 -0
- data/manual/html/shift.timesheet.html +70 -0
- data/manual/html/shifts.allocate.html +71 -0
- data/manual/html/shifts.resource.html +73 -0
- data/manual/html/shifts.task.html +73 -0
- data/manual/html/shorttimeformat.html +67 -0
- data/manual/html/sloppy.booking.html +77 -0
- data/manual/html/sloppy.projection.html +66 -0
- data/manual/html/sortjournalentries.html +81 -0
- data/manual/html/sortresources.html +73 -0
- data/manual/html/sorttasks.html +73 -0
- data/manual/html/start.column.html +67 -0
- data/manual/html/start.html +78 -0
- data/manual/html/start.limit.html +69 -0
- data/manual/html/start.report.html +69 -0
- data/manual/html/startcredit.html +68 -0
- data/manual/html/status.statussheet.html +73 -0
- data/manual/html/status.timesheet.html +91 -0
- data/manual/html/statussheet.html +124 -0
- data/manual/html/statussheetreport.html +125 -0
- data/manual/html/strict.projection.html +66 -0
- data/manual/html/summary.html +69 -0
- data/manual/html/supplement.html +108 -0
- data/manual/html/supplement.resource.html +195 -0
- data/manual/html/supplement.task.html +329 -0
- data/manual/html/tagfile.html +73 -0
- data/manual/html/task.html +320 -0
- data/manual/html/task.statussheet.html +74 -0
- data/manual/html/task.timesheet.html +89 -0
- data/manual/html/taskattributes.html +115 -0
- data/manual/html/taskprefix.html +67 -0
- data/manual/html/taskreport.html +69 -0
- data/manual/html/taskroot.html +103 -0
- data/manual/html/text.extend.html +77 -0
- data/manual/html/textreport.html +66 -0
- data/manual/html/timeformat.html +160 -0
- data/manual/html/timeoff.nikureport.html +71 -0
- data/manual/html/timesheet.html +129 -0
- data/manual/html/timesheetreport.html +107 -0
- data/manual/html/timezone.export.html +66 -0
- data/manual/html/timezone.html +72 -0
- data/manual/html/timezone.report.html +66 -0
- data/manual/html/timezone.shift.html +70 -0
- data/manual/html/timingresolution.html +71 -0
- data/manual/html/title.column.html +67 -0
- data/manual/html/title.html +68 -0
- data/manual/html/toc.html +1330 -0
- data/manual/html/tooltip.column.html +72 -0
- data/manual/html/trackingscenario.html +80 -0
- data/manual/html/treelevel.html +66 -0
- data/manual/html/vacation.html +71 -0
- data/manual/html/vacation.resource.html +73 -0
- data/manual/html/vacation.shift.html +71 -0
- data/manual/html/warn.html +69 -0
- data/manual/html/weeklymax.html +99 -0
- data/manual/html/weeklymin.html +99 -0
- data/manual/html/weekstartsmonday.html +66 -0
- data/manual/html/weekstartssunday.html +66 -0
- data/manual/html/width.column.html +66 -0
- data/manual/html/work.html +105 -0
- data/manual/html/workinghours.project.html +102 -0
- data/manual/html/workinghours.resource.html +79 -0
- data/manual/html/workinghours.shift.html +81 -0
- data/manual/html/yearlyworkingdays.html +70 -0
- data/spec/StatusSheets_spec.rb +0 -6
- data/spec/TimeSheets_spec.rb +0 -6
- data/spec/Tj3Daemon_spec.rb +2 -0
- data/spec/support/DaemonControl.rb +10 -0
- data/taskjuggler.gemspec +71 -0
- data/tasks/changelog.rake +2 -2
- data/tasks/gem.rake +50 -21
- data/tasks/manual.rake +1 -1
- data/tasks/rdoc.rake +5 -12
- data/tasks/spec.rake +1 -1
- data/tasks/test.rake +5 -8
- data/test/ReferenceGenerator.rb +91 -0
- data/test/TestSuite/CSV-Reports/refs/resourcereport.csv +4 -4
- data/test/TestSuite/ReportGenerator/Correct/Journal.tjp +21 -0
- data/test/TestSuite/ReportGenerator/Correct/JournalMode.tjp +124 -0
- data/test/TestSuite/ReportGenerator/Correct/refs/Alerts-1.csv +124 -124
- data/test/TestSuite/ReportGenerator/Correct/refs/Journal-1.csv +1 -7
- data/test/TestSuite/ReportGenerator/Correct/refs/Journal-2.csv +7 -3
- data/test/TestSuite/ReportGenerator/Correct/refs/JournalMode-1.csv +79 -0
- data/test/TestSuite/ReportGenerator/Correct/refs/JournalMode-2.csv +208 -0
- data/test/TjpGen.rb +152 -0
- metadata +1290 -741
- data/benchmarks/666tasks.tjp +0 -3183
- data/benchmarks/allocate.tjp +0 -30
- data/benchmarks/allocatedSlots.tjp +0 -1602
- data/benchmarks/booking.tjp +0 -76
- data/benchmarks/depends.tjp +0 -113
- data/benchmarks/gantt.tjp +0 -57
- data/benchmarks/htmltaskreport.tjp +0 -71
- data/benchmarks/icons/details.png +0 -0
- data/benchmarks/icons/flag-green.png +0 -0
- data/benchmarks/icons/flag-red.png +0 -0
- data/benchmarks/icons/flag-yellow.png +0 -0
- data/benchmarks/icons/resource.png +0 -0
- data/benchmarks/icons/resourcegroup.png +0 -0
- data/benchmarks/icons/task.png +0 -0
- data/benchmarks/icons/taskgroup.png +0 -0
- data/benchmarks/icons/trend-down.png +0 -0
- data/benchmarks/icons/trend-flat.png +0 -0
- data/benchmarks/icons/trend-up.png +0 -0
- data/benchmarks/runbench.rb +0 -30
- data/benchmarks/scripts/wz_tooltip.js +0 -1301
- data/gem_spec.rb +0 -37
- data/lib/exchangebug.rb +0 -42
- data/lib/ruby-signal-bug.rb +0 -55
- data/prj_cfg.rb +0 -50
- data/tasks/csts.rake +0 -72
- data/tasks/rcov.rake +0 -14
- data/tasks/rexml_fix.rb +0 -16
- data/tasks/rexml_fix_19.rb +0 -49
- data/tasks/show.rake +0 -21
- data/tasks/stats.rake +0 -25
- data/test/TestSuite/Export-Reports/refs/DST.tjp +0 -60
- data/test/TestSuite/Export-Reports/refs/ReleasePlan.tjp +0 -80
- data/test/TestSuite/Export-Reports/tp.tjp +0 -49
- data/test/TestSuite/HTML-Reports/Alerts.html +0 -424
- data/test/TestSuite/HTML-Reports/TimeSheet.html +0 -79
- data/test/TestSuite/HTML-Reports/css/tjmanual.css +0 -86
- data/test/TestSuite/HTML-Reports/css/tjreport.css +0 -413
- data/test/TestSuite/HTML-Reports/icons/details.png +0 -0
- data/test/TestSuite/HTML-Reports/icons/flag-green.png +0 -0
- data/test/TestSuite/HTML-Reports/icons/flag-red.png +0 -0
- data/test/TestSuite/HTML-Reports/icons/flag-yellow.png +0 -0
- data/test/TestSuite/HTML-Reports/icons/resource.png +0 -0
- data/test/TestSuite/HTML-Reports/icons/resourcegroup.png +0 -0
- data/test/TestSuite/HTML-Reports/icons/task.png +0 -0
- data/test/TestSuite/HTML-Reports/icons/taskgroup.png +0 -0
- data/test/TestSuite/HTML-Reports/icons/trend-down.png +0 -0
- data/test/TestSuite/HTML-Reports/icons/trend-flat.png +0 -0
- data/test/TestSuite/HTML-Reports/icons/trend-up.png +0 -0
- data/test/TestSuite/HTML-Reports/reference.html +0 -51
- data/test/TestSuite/HTML-Reports/scripts/wz_tooltip.js +0 -1301
- data/test/TestSuite/ReportGenerator/Correct/css/tjmanual.css +0 -86
- data/test/TestSuite/ReportGenerator/Correct/css/tjreport.css +0 -413
- data/test/TestSuite/ReportGenerator/Correct/icons/details.png +0 -0
- data/test/TestSuite/ReportGenerator/Correct/icons/flag-green.png +0 -0
- data/test/TestSuite/ReportGenerator/Correct/icons/flag-red.png +0 -0
- data/test/TestSuite/ReportGenerator/Correct/icons/flag-yellow.png +0 -0
- data/test/TestSuite/ReportGenerator/Correct/icons/resource.png +0 -0
- data/test/TestSuite/ReportGenerator/Correct/icons/resourcegroup.png +0 -0
- data/test/TestSuite/ReportGenerator/Correct/icons/task.png +0 -0
- data/test/TestSuite/ReportGenerator/Correct/icons/taskgroup.png +0 -0
- data/test/TestSuite/ReportGenerator/Correct/icons/trend-down.png +0 -0
- data/test/TestSuite/ReportGenerator/Correct/icons/trend-flat.png +0 -0
- data/test/TestSuite/ReportGenerator/Correct/icons/trend-up.png +0 -0
- data/test/TestSuite/ReportGenerator/Correct/opennodes.tjp +0 -26
- data/test/TestSuite/ReportGenerator/Correct/refs/opennodes-1.csv +0 -2
- data/test/TestSuite/ReportGenerator/Correct/scripts/wz_tooltip.js +0 -1301
- data/test/TestSuite/Scheduler/Correct/Allocate.html +0 -1075
- data/test/TestSuite/Scheduler/Correct/Duration.html +0 -610
- data/test/TestSuite/Scheduler/Correct/css/tjmanual.css +0 -85
- data/test/TestSuite/Scheduler/Correct/css/tjreport.css +0 -413
- data/test/TestSuite/Scheduler/Correct/icons/details.png +0 -0
- data/test/TestSuite/Scheduler/Correct/icons/flag-green.png +0 -0
- data/test/TestSuite/Scheduler/Correct/icons/flag-red.png +0 -0
- data/test/TestSuite/Scheduler/Correct/icons/flag-yellow.png +0 -0
- data/test/TestSuite/Scheduler/Correct/icons/resource.png +0 -0
- data/test/TestSuite/Scheduler/Correct/icons/resourcegroup.png +0 -0
- data/test/TestSuite/Scheduler/Correct/icons/task.png +0 -0
- data/test/TestSuite/Scheduler/Correct/icons/taskgroup.png +0 -0
- data/test/TestSuite/Scheduler/Correct/icons/trend-down.png +0 -0
- data/test/TestSuite/Scheduler/Correct/icons/trend-flat.png +0 -0
- data/test/TestSuite/Scheduler/Correct/icons/trend-up.png +0 -0
- data/test/TestSuite/Scheduler/Correct/scripts/wz_tooltip.js +0 -1301
- data/test/TestSuite/StatusSheetTemplates/project.tji +0 -35
- data/test/TestSuite/StatusSheetTemplates/project.tjp +0 -56
- data/test/TestSuite/StatusSheets/TimeSheets/2002-03-01/missing-reports +0 -2
- data/test/TestSuite/StatusSheets/TimeSheets/2002-03-01/resource1_2002-03-01.tji +0 -0
- data/test/TestSuite/StatusSheets/boss.tji +0 -45
- data/test/TestSuite/StatusSheets/boss_mail +0 -51
- data/test/TestSuite/StatusSheets/dev2_mail +0 -37
- data/test/TestSuite/StatusSheets/project.tjp +0 -275
- data/test/TestSuite/StatusSheets/run +0 -54
- data/test/TestSuite/Syntax/Correct/DST.tjp +0 -11
- data/test/TestSuite/Syntax/Correct/ReleasePlan.tjp +0 -32
- data/test/TestSuite/Syntax/Correct/css/tjmanual.css +0 -86
- data/test/TestSuite/Syntax/Correct/css/tjreport.css +0 -413
- data/test/TestSuite/Syntax/Correct/icons/details.png +0 -0
- data/test/TestSuite/Syntax/Correct/icons/flag-green.png +0 -0
- data/test/TestSuite/Syntax/Correct/icons/flag-red.png +0 -0
- data/test/TestSuite/Syntax/Correct/icons/flag-yellow.png +0 -0
- data/test/TestSuite/Syntax/Correct/icons/resource.png +0 -0
- data/test/TestSuite/Syntax/Correct/icons/resourcegroup.png +0 -0
- data/test/TestSuite/Syntax/Correct/icons/task.png +0 -0
- data/test/TestSuite/Syntax/Correct/icons/taskgroup.png +0 -0
- data/test/TestSuite/Syntax/Correct/icons/trend-down.png +0 -0
- data/test/TestSuite/Syntax/Correct/icons/trend-flat.png +0 -0
- data/test/TestSuite/Syntax/Correct/icons/trend-up.png +0 -0
- data/test/TestSuite/Syntax/Correct/scripts/wz_tooltip.js +0 -1301
- data/test/TestSuite/TimeSheets/dev2_mail1 +0 -84
- data/test/TestSuite/TimeSheets/dev2_mail2 +0 -87
- data/test/TestSuite/TimeSheets/project.tjp +0 -271
- data/test/TestSuite/TimeSheets/receiver.log.mod +0 -1056
- data/test/TestSuite/TimeSheets/run +0 -76
- 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
|
-
|
|
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.
|
data/lib/taskjuggler/Query.rb
CHANGED
|
@@ -38,7 +38,8 @@ class TaskJuggler
|
|
|
38
38
|
attributeId scenario scenarioIdx
|
|
39
39
|
loadUnit numberFormat currencyFormat timeFormat
|
|
40
40
|
listItem listType hideJournalEntry
|
|
41
|
-
|
|
41
|
+
journalMode journalAttributes sortJournalEntries
|
|
42
|
+
costAccount revenueAccount selfContained )
|
|
42
43
|
@@ps.each do |p|
|
|
43
44
|
attr_accessor p.to_sym
|
|
44
45
|
end
|
data/lib/taskjuggler/Resource.rb
CHANGED
|
@@ -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(
|
|
74
|
-
|
|
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.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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 =
|
|
154
|
-
|
|
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)
|
data/lib/taskjuggler/Task.rb
CHANGED
|
@@ -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.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
1748
|
-
|
|
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
|
|
1755
|
-
|
|
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
|
|
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
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
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
|
|
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
|