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