taskjuggler 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +119 -0
- data/benchmarks/allocatedSlots.tjp +1602 -0
- data/benchmarks/booking.tjp +40 -30
- data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/css/tjmanual.css +0 -0
- data/{test/TestSuite/Scheduler/Correct → benchmarks}/css/tjreport.css +1 -0
- data/benchmarks/gantt.tjp +57 -0
- data/benchmarks/htmltaskreport.tjp +26 -1
- data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/details.png +0 -0
- data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/flag-green.png +0 -0
- data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/flag-red.png +0 -0
- data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/flag-yellow.png +0 -0
- data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/resource.png +0 -0
- data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/resourcegroup.png +0 -0
- data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/task.png +0 -0
- data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/taskgroup.png +0 -0
- data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/trend-down.png +0 -0
- data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/trend-flat.png +0 -0
- data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/icons/trend-up.png +0 -0
- data/benchmarks/profile.clt +36082 -0
- data/benchmarks/profile.html +58182 -0
- data/benchmarks/runbench.rb +6 -0
- data/{test/TestSuite/ReportGenerator/Errors → benchmarks}/scripts/wz_tooltip.js +0 -0
- data/doc/AppConfig.html +85 -37
- data/doc/Arguments.html +11 -1
- data/doc/CHANGELOG.html +131 -2
- data/doc/COPYING.html +11 -1
- data/doc/Object.html +12 -3
- data/doc/README.html +11 -1
- data/doc/RuntimeConfig.html +11 -1
- data/doc/String.html +11 -1
- data/doc/StringIO.html +11 -1
- data/doc/TaskJuggler.html +250 -219
- data/doc/TaskJuggler/Account.html +11 -1
- data/doc/TaskJuggler/AccountAttribute.html +11 -1
- data/doc/TaskJuggler/AccountScenario.html +11 -1
- data/doc/TaskJuggler/Allocation.html +11 -1
- data/doc/TaskJuggler/AllocationAttribute.html +11 -1
- data/doc/TaskJuggler/AttributeBase.html +11 -1
- data/doc/TaskJuggler/AttributeDefinition.html +11 -1
- data/doc/TaskJuggler/BatchProcessor.html +11 -1
- data/doc/TaskJuggler/Booking.html +11 -1
- data/doc/TaskJuggler/BookingListAttribute.html +11 -1
- data/doc/TaskJuggler/BooleanAttribute.html +11 -1
- data/doc/TaskJuggler/CSVFile.html +12 -2
- data/doc/TaskJuggler/CellSettingPattern.html +11 -1
- data/doc/TaskJuggler/CellSettingPatternList.html +11 -1
- data/doc/TaskJuggler/Charge.html +11 -1
- data/doc/TaskJuggler/ChargeListAttribute.html +11 -1
- data/doc/TaskJuggler/ChargeSet.html +11 -1
- data/doc/TaskJuggler/ChargeSetListAttribute.html +11 -1
- data/doc/TaskJuggler/CollisionDetector.html +1063 -0
- data/doc/TaskJuggler/ColumnListAttribute.html +11 -1
- data/doc/TaskJuggler/ColumnTable.html +11 -1
- data/doc/TaskJuggler/Daemon.html +11 -1
- data/doc/TaskJuggler/{OnShiftCache.html → DataCache.html} +127 -139
- data/doc/TaskJuggler/DataCacheEntry.html +711 -0
- data/doc/TaskJuggler/DateAttribute.html +11 -1
- data/doc/TaskJuggler/DefinitionListAttribute.html +11 -1
- data/doc/TaskJuggler/DependencyListAttribute.html +11 -1
- data/doc/TaskJuggler/DurationAttribute.html +16 -5
- data/doc/TaskJuggler/FileList.html +11 -1
- data/doc/TaskJuggler/FileRecord.html +11 -1
- data/doc/TaskJuggler/FixnumAttribute.html +19 -9
- data/doc/TaskJuggler/FlagListAttribute.html +29 -19
- data/doc/TaskJuggler/FloatAttribute.html +23 -13
- data/doc/TaskJuggler/FormatListAttribute.html +19 -9
- data/doc/TaskJuggler/GanttChart.html +94 -133
- data/doc/TaskJuggler/GanttContainer.html +11 -1
- data/doc/TaskJuggler/GanttHeader.html +11 -1
- data/doc/TaskJuggler/GanttHeaderScaleItem.html +11 -1
- data/doc/TaskJuggler/GanttLine.html +11 -1
- data/doc/TaskJuggler/GanttLoadStack.html +11 -1
- data/doc/TaskJuggler/GanttMilestone.html +11 -1
- data/doc/TaskJuggler/GanttRouter.html +247 -596
- data/doc/TaskJuggler/GanttTaskBar.html +11 -1
- data/doc/TaskJuggler/HTMLDocument.html +11 -1
- data/doc/TaskJuggler/HTMLGraphics.html +11 -1
- data/doc/TaskJuggler/Interval.html +11 -1
- data/doc/TaskJuggler/IntervalListAttribute.html +33 -23
- data/doc/TaskJuggler/JobInfo.html +11 -1
- data/doc/TaskJuggler/Journal.html +11 -1
- data/doc/TaskJuggler/JournalEntry.html +11 -1
- data/doc/TaskJuggler/JournalEntryList.html +11 -1
- data/doc/TaskJuggler/KeywordArray.html +11 -1
- data/doc/TaskJuggler/KeywordDocumentation.html +16 -6
- data/doc/TaskJuggler/Limits.html +11 -1
- data/doc/TaskJuggler/Limits/Limit.html +11 -1
- data/doc/TaskJuggler/LimitsAttribute.html +24 -14
- data/doc/TaskJuggler/ListAttributeBase.html +11 -1
- data/doc/TaskJuggler/Log.html +11 -1
- data/doc/TaskJuggler/LogFile.html +11 -1
- data/doc/TaskJuggler/LogicalAttribute.html +11 -1
- data/doc/TaskJuggler/LogicalExpression.html +11 -1
- data/doc/TaskJuggler/LogicalExpressionAttribute.html +19 -9
- data/doc/TaskJuggler/LogicalFlag.html +11 -1
- data/doc/TaskJuggler/LogicalFunction.html +11 -1
- data/doc/TaskJuggler/LogicalOperation.html +11 -1
- data/doc/TaskJuggler/Macro.html +11 -1
- data/doc/TaskJuggler/MacroTable.html +11 -1
- data/doc/TaskJuggler/ManagerResponsibilities.html +11 -1
- data/doc/TaskJuggler/ManagerStatusRecord.html +11 -1
- data/doc/TaskJuggler/Message.html +11 -1
- data/doc/TaskJuggler/MessageHandler.html +11 -1
- data/doc/TaskJuggler/Navigator.html +12 -2
- data/doc/TaskJuggler/NavigatorElement.html +11 -1
- data/doc/TaskJuggler/NikuProject.html +11 -1
- data/doc/TaskJuggler/NikuReport.html +11 -1
- data/doc/TaskJuggler/NikuResource.html +11 -1
- data/doc/TaskJuggler/NodeListAttribute.html +17 -7
- data/doc/TaskJuggler/PlaceHolderCell.html +722 -0
- data/doc/TaskJuggler/ProcessIntercom.html +11 -1
- data/doc/TaskJuggler/ProcessIntercomIface.html +11 -1
- data/doc/TaskJuggler/Project.html +587 -500
- data/doc/TaskJuggler/ProjectBroker.html +11 -1
- data/doc/TaskJuggler/ProjectBrokerIface.html +11 -1
- data/doc/TaskJuggler/ProjectFileParser.html +205 -192
- data/doc/TaskJuggler/ProjectFileScanner.html +230 -207
- data/doc/TaskJuggler/ProjectRecord.html +11 -1
- data/doc/TaskJuggler/ProjectServer.html +11 -1
- data/doc/TaskJuggler/ProjectServerIface.html +11 -1
- data/doc/TaskJuggler/PropertyAttribute.html +19 -9
- data/doc/TaskJuggler/PropertyList.html +95 -83
- data/doc/TaskJuggler/PropertySet.html +11 -1
- data/doc/TaskJuggler/PropertyTreeNode.html +11 -1
- data/doc/TaskJuggler/Query.html +234 -232
- data/doc/TaskJuggler/RTFHandlers.html +11 -1
- data/doc/TaskJuggler/RTFNavigator.html +11 -1
- data/doc/TaskJuggler/RTFQuery.html +11 -1
- data/doc/TaskJuggler/RTFReport.html +11 -1
- data/doc/TaskJuggler/RTFReportLink.html +11 -1
- data/doc/TaskJuggler/RTFWithQuerySupport.html +11 -1
- data/doc/TaskJuggler/RealFormat.html +12 -2
- data/doc/TaskJuggler/RealFormatAttribute.html +15 -5
- data/doc/TaskJuggler/ReferenceAttribute.html +38 -28
- data/doc/TaskJuggler/Report.html +96 -113
- data/doc/TaskJuggler/ReportBase.html +161 -152
- data/doc/TaskJuggler/ReportContext.html +11 -1
- data/doc/TaskJuggler/ReportServer.html +59 -48
- data/doc/TaskJuggler/ReportServerIface.html +51 -41
- data/doc/TaskJuggler/ReportServerRecord.html +11 -1
- data/doc/TaskJuggler/ReportServlet.html +11 -1
- data/doc/TaskJuggler/ReportTable.html +46 -25
- data/doc/TaskJuggler/ReportTableCell.html +296 -275
- data/doc/TaskJuggler/ReportTableColumn.html +14 -4
- data/doc/TaskJuggler/ReportTableLegend.html +11 -1
- data/doc/TaskJuggler/ReportTableLine.html +19 -7
- data/doc/TaskJuggler/Resource.html +12 -2
- data/doc/TaskJuggler/ResourceListAttribute.html +40 -30
- data/doc/TaskJuggler/ResourceListRE.html +11 -1
- data/doc/TaskJuggler/ResourceScenario.html +708 -565
- data/doc/TaskJuggler/RichText.html +54 -36
- data/doc/TaskJuggler/RichTextAttribute.html +31 -21
- data/doc/TaskJuggler/RichTextDocument.html +11 -1
- data/doc/TaskJuggler/RichTextElement.html +11 -1
- data/doc/TaskJuggler/RichTextFunctionExample.html +11 -1
- data/doc/TaskJuggler/RichTextFunctionHandler.html +11 -1
- data/doc/TaskJuggler/RichTextImage.html +11 -1
- data/doc/TaskJuggler/RichTextIntermediate.html +81 -71
- data/doc/TaskJuggler/RichTextParser.html +88 -33
- data/doc/TaskJuggler/RichTextScanner.html +45 -35
- data/doc/TaskJuggler/RichTextSnip.html +11 -1
- data/doc/TaskJuggler/RichTextSyntaxRules.html +436 -389
- data/doc/TaskJuggler/Scenario.html +11 -1
- data/doc/TaskJuggler/ScenarioData.html +11 -1
- data/doc/TaskJuggler/ScenarioListAttribute.html +23 -13
- data/doc/TaskJuggler/Scoreboard.html +92 -73
- data/doc/TaskJuggler/SheetHandlerBase.html +11 -1
- data/doc/TaskJuggler/SheetReceiver.html +11 -1
- data/doc/TaskJuggler/SheetSender.html +11 -1
- data/doc/TaskJuggler/Shift.html +11 -1
- data/doc/TaskJuggler/ShiftAssignment.html +11 -1
- data/doc/TaskJuggler/ShiftAssignments.html +11 -1
- data/doc/TaskJuggler/ShiftAssignmentsAttribute.html +24 -14
- data/doc/TaskJuggler/ShiftScenario.html +11 -1
- data/doc/TaskJuggler/SimpleQueryExpander.html +11 -1
- data/doc/TaskJuggler/SortListAttribute.html +21 -11
- data/doc/TaskJuggler/SourceFileInfo.html +11 -1
- data/doc/TaskJuggler/StatusSheetReceiver.html +11 -1
- data/doc/TaskJuggler/StatusSheetReport.html +11 -1
- data/doc/TaskJuggler/StatusSheetSender.html +112 -11
- data/doc/TaskJuggler/StringAttribute.html +23 -13
- data/doc/TaskJuggler/SymbolAttribute.html +19 -9
- data/doc/TaskJuggler/SyntaxReference.html +80 -71
- data/doc/TaskJuggler/TOCEntry.html +11 -1
- data/doc/TaskJuggler/TSResourceRecord.html +11 -1
- data/doc/TaskJuggler/TSTaskRecord.html +11 -1
- data/doc/TaskJuggler/TableColumnDefinition.html +11 -1
- data/doc/TaskJuggler/TableOfContents.html +11 -1
- data/doc/TaskJuggler/TableReport.html +422 -411
- data/doc/TaskJuggler/Task.html +11 -1
- data/doc/TaskJuggler/TaskDependency.html +11 -1
- data/doc/TaskJuggler/TaskListAttribute.html +33 -23
- data/doc/TaskJuggler/TaskListRE.html +11 -1
- data/doc/TaskJuggler/TaskScenario.html +2007 -1919
- data/doc/TaskJuggler/TextFormatter.html +11 -1
- data/doc/TaskJuggler/TextParser.html +421 -612
- data/doc/TaskJuggler/TextParser/Pattern.html +410 -211
- data/doc/TaskJuggler/TextParser/Rule.html +224 -152
- data/doc/TaskJuggler/TextParser/StackElement.html +190 -28
- data/doc/TaskJuggler/TextParser/State.html +989 -0
- data/doc/TaskJuggler/TextParser/StateTransition.html +782 -0
- data/doc/TaskJuggler/TextParser/TextParserResultArray.html +25 -14
- data/doc/TaskJuggler/TextParser/TokenDoc.html +11 -1
- data/doc/TaskJuggler/TextReport.html +11 -1
- data/doc/TaskJuggler/TextScanner.html +285 -273
- data/doc/TaskJuggler/TextScanner/BufferStreamHandle.html +17 -7
- data/doc/TaskJuggler/TextScanner/FileStreamHandle.html +24 -14
- data/doc/TaskJuggler/TextScanner/MacroStackEntry.html +11 -1
- data/doc/TaskJuggler/TextScanner/StreamHandle.html +64 -52
- data/doc/TaskJuggler/TimeSheet.html +11 -1
- data/doc/TaskJuggler/TimeSheetReceiver.html +11 -1
- data/doc/TaskJuggler/TimeSheetRecord.html +11 -1
- data/doc/TaskJuggler/TimeSheetReport.html +11 -1
- data/doc/TaskJuggler/TimeSheetSender.html +11 -1
- data/doc/TaskJuggler/TimeSheetSummary.html +11 -1
- data/doc/TaskJuggler/TimeSheets.html +11 -1
- data/doc/TaskJuggler/Tj3AppBase.html +11 -1
- data/doc/TaskJuggler/Tj3Client.html +11 -1
- data/doc/TaskJuggler/Tj3Daemon.html +11 -1
- data/doc/TaskJuggler/Tj3SheetAppBase.html +11 -1
- data/doc/TaskJuggler/Tj3SsReceiver.html +11 -1
- data/doc/TaskJuggler/Tj3SsSender.html +11 -1
- data/doc/TaskJuggler/Tj3TsReceiver.html +11 -1
- data/doc/TaskJuggler/Tj3TsSender.html +11 -1
- data/doc/TaskJuggler/Tj3TsSummary.html +11 -1
- data/doc/TaskJuggler/TjException.html +11 -1
- data/doc/TaskJuggler/TjTime.html +474 -324
- data/doc/TaskJuggler/TjpExample.html +11 -1
- data/doc/TaskJuggler/TjpExportRE.html +11 -1
- data/doc/TaskJuggler/TjpSyntaxRules.html +3731 -3662
- data/doc/TaskJuggler/URLParameter.html +11 -1
- data/doc/TaskJuggler/UserManual.html +11 -1
- data/doc/TaskJuggler/VimSyntax.html +11 -1
- data/doc/TaskJuggler/WebServer.html +11 -1
- data/doc/TaskJuggler/WorkingHours.html +295 -221
- data/doc/TaskJuggler/WorkingHoursAttribute.html +11 -1
- data/doc/TaskJuggler/XMLBlob.html +11 -1
- data/doc/TaskJuggler/XMLComment.html +11 -1
- data/doc/TaskJuggler/XMLDocument.html +11 -1
- data/doc/TaskJuggler/XMLElement.html +11 -1
- data/doc/TaskJuggler/XMLNamedText.html +11 -1
- data/doc/TaskJuggler/XMLText.html +11 -1
- data/doc/index.html +694 -624
- data/doc/lib/AppConfig_rb.html +1 -1
- data/doc/lib/Attributes_rb.html +1 -1
- data/doc/lib/Booking_rb.html +1 -1
- data/doc/lib/DataCache_rb.html +69 -0
- data/doc/lib/KeywordDocumentation_rb.html +1 -1
- data/doc/lib/ProjectFileParser_rb.html +1 -1
- data/doc/lib/ProjectFileScanner_rb.html +1 -1
- data/doc/lib/Project_rb.html +1 -1
- data/doc/lib/PropertyList_rb.html +1 -1
- data/doc/lib/Query_rb.html +1 -1
- data/doc/lib/RealFormat_rb.html +1 -1
- data/doc/lib/ResourceScenario_rb.html +1 -1
- data/doc/lib/Resource_rb.html +1 -1
- data/doc/lib/RichTextParser_rb.html +1 -1
- data/doc/lib/RichTextScanner_rb.html +1 -1
- data/doc/lib/RichTextSyntaxRules_rb.html +1 -1
- data/doc/lib/RichText_rb.html +1 -1
- data/doc/lib/Scoreboard_rb.html +1 -1
- data/doc/lib/StatusSheetSender_rb.html +1 -1
- data/doc/lib/SyntaxReference_rb.html +1 -1
- data/doc/lib/TaskJuggler_rb.html +1 -1
- data/doc/lib/TaskScenario_rb.html +3 -1
- data/doc/lib/TextParser/Pattern_rb.html +3 -1
- data/doc/lib/TextParser/Rule_rb.html +3 -1
- data/doc/lib/TextParser/StackElement_rb.html +3 -1
- data/doc/lib/TextParser/State_rb.html +65 -0
- data/doc/lib/TextParser_rb.html +1 -1
- data/doc/lib/TextScanner_rb.html +1 -1
- data/doc/lib/Tj3Config_rb.html +1 -1
- data/doc/lib/TjTime_rb.html +1 -1
- data/doc/lib/TjpSyntaxRules_rb.html +1 -1
- data/doc/lib/WorkingHours_rb.html +3 -1
- data/doc/lib/daemon/ReportServer_rb.html +1 -1
- data/doc/lib/reports/CSVFile_rb.html +1 -1
- data/doc/lib/reports/CollisionDetector_rb.html +67 -0
- data/doc/lib/reports/GanttChart_rb.html +1 -1
- data/doc/lib/reports/GanttRouter_rb.html +3 -1
- data/doc/lib/reports/Navigator_rb.html +1 -1
- data/doc/lib/reports/ReportBase_rb.html +1 -1
- data/doc/lib/reports/ReportTableCell_rb.html +1 -1
- data/doc/lib/reports/ReportTableColumn_rb.html +1 -1
- data/doc/lib/reports/ReportTableLine_rb.html +1 -1
- data/doc/lib/reports/ReportTable_rb.html +1 -1
- data/doc/lib/reports/Report_rb.html +1 -1
- data/doc/lib/reports/TableReport_rb.html +1 -1
- data/doc/lib/taskjuggler3_rb.html +1 -1
- data/examples/tutorial.tjp +1 -2
- data/lib/AppConfig.rb +10 -4
- data/lib/Attributes.rb +4 -4
- data/lib/DataCache.rb +124 -0
- data/lib/KeywordDocumentation.rb +5 -5
- data/lib/Project.rb +54 -10
- data/lib/ProjectFileParser.rb +10 -9
- data/lib/ProjectFileScanner.rb +38 -25
- data/lib/PropertyList.rb +6 -4
- data/lib/Query.rb +0 -8
- data/lib/RealFormat.rb +1 -1
- data/lib/Resource.rb +1 -1
- data/lib/ResourceScenario.rb +96 -31
- data/lib/RichText.rb +17 -5
- data/lib/RichTextParser.rb +22 -9
- data/lib/RichTextScanner.rb +34 -34
- data/lib/RichTextSyntaxRules.rb +41 -36
- data/lib/Scoreboard.rb +16 -7
- data/lib/StatusSheetSender.rb +63 -0
- data/lib/SyntaxReference.rb +9 -10
- data/lib/TaskJuggler.rb +28 -4
- data/lib/TaskScenario.rb +66 -19
- data/lib/TextParser.rb +219 -384
- data/lib/TextParser/Pattern.rb +168 -49
- data/lib/TextParser/Rule.rb +33 -17
- data/lib/TextParser/StackElement.rb +42 -2
- data/lib/TextParser/State.rb +175 -0
- data/lib/TextScanner.rb +19 -15
- data/lib/Tj3Config.rb +1 -1
- data/lib/TjTime.rb +111 -3
- data/lib/TjpSyntaxRules.rb +122 -66
- data/lib/WorkingHours.rb +91 -186
- data/lib/daemon/ReportServer.rb +3 -2
- data/lib/reports/CSVFile.rb +1 -1
- data/lib/reports/CollisionDetector.rb +177 -0
- data/lib/reports/GanttChart.rb +25 -41
- data/lib/reports/GanttRouter.rb +104 -233
- data/lib/reports/Navigator.rb +1 -1
- data/lib/reports/Report.rb +9 -33
- data/lib/reports/ReportBase.rb +0 -1
- data/lib/reports/ReportTable.rb +19 -8
- data/lib/reports/ReportTableCell.rb +61 -25
- data/lib/reports/ReportTableColumn.rb +2 -2
- data/lib/reports/ReportTableLine.rb +4 -2
- data/lib/reports/TableReport.rb +1 -0
- data/lib/taskjuggler3.rb +0 -1
- data/manual/Installation +7 -3
- data/manual/Intro +12 -10
- data/manual/The_TaskJuggler_Syntax +4 -4
- data/test/TestSuite/CSV-Reports/celltext-Reference.csv +14 -14
- data/test/TestSuite/CSV-Reports/genrefs +1 -1
- data/test/TestSuite/CSV-Reports/resourcereport-Reference.csv +4 -4
- data/test/TestSuite/CSV-Reports/resourcereport_with_tasks-Reference.csv +22 -22
- data/test/TestSuite/CSV-Reports/sortByTree-Reference.csv +14 -14
- data/test/TestSuite/CSV-Reports/sortBy_duration.down-Reference.csv +14 -14
- data/test/TestSuite/CSV-Reports/sortBy_effort.up-Reference.csv +14 -14
- data/test/TestSuite/CSV-Reports/sortBy_plan.start.down-Reference.csv +14 -14
- data/test/TestSuite/CSV-Reports/taskreport-Reference.csv +14 -14
- data/test/TestSuite/CSV-Reports/taskreport_with_resources-Reference.csv +32 -24
- data/test/TestSuite/CSV-Reports/weekly-Reference.csv +13 -0
- data/test/TestSuite/CSV-Reports/weekly.tjp +9 -0
- data/test/TestSuite/HTML-Reports/css/tjreport.css +7 -2
- data/test/TestSuite/HTML-Reports/depArrows.html +839 -830
- data/test/TestSuite/HTML-Reports/depArrows.tjp +12 -12
- data/test/TestSuite/HTML-Reports/profile.html +37581 -0
- data/test/TestSuite/ReportGenerator/Errors/no_report_defined.tjp +7 -0
- data/test/TestSuite/ReportGenerator/Errors/rtp_report_recursion.tjp +1 -1
- data/test/TestSuite/StatusSheets/TimeSheets/2002-03-01/missing-reports +2 -0
- data/test/TestSuite/StatusSheets/run +2 -0
- data/test/TestSuite/Syntax/Correct/Booking.tjp +13 -5
- data/test/TestSuite/Syntax/Correct/ResourceRoot.tjp +21 -0
- data/test/TestSuite/Syntax/Correct/RollupResource.tjp +21 -0
- data/test/TestSuite/Syntax/Correct/TaskRoot.tjp +1 -1
- data/test/TestSuite/Syntax/Errors/empty.tjp +1 -1
- data/test/TestSuite/Syntax/Errors/include_before_project.tjp +2 -0
- data/test/TestSuite/Syntax/Errors/no_reduce.tjp +6 -0
- data/test/TestSuite/Syntax/Errors/unsupported_token.tjp +1 -1
- data/test/TestSuite/TimeSheets/run +1 -1
- data/test/test_CSV-Reports.rb +2 -4
- data/test/test_CollisionDetector.rb +85 -0
- data/test/test_Project.rb +2 -2
- data/test/test_ProjectFileScanner.rb +73 -31
- data/test/test_Query.rb +2 -2
- data/test/test_ReportGenerator.rb +1 -1
- data/test/test_RichText.rb +4 -4
- data/test/test_WorkingHours.rb +150 -11
- metadata +75 -67
- data/test/TestSuite/ReportGenerator/Errors/css/tjreport.css +0 -407
- data/test/TestSuite/ReportGenerator/Errors/rtp_report_recursion.html +0 -26
- data/test/TestSuite/Scheduler/Correct/Allocate.html +0 -3210
- data/test/TestSuite/Scheduler/Correct/Container.html +0 -349
- data/test/TestSuite/Scheduler/Correct/Limits.html +0 -4964
- data/test/TestSuite/Scheduler/Correct/Shift.html +0 -1719
- data/test/TestSuite/Scheduler/Correct/Shift2.html +0 -476
- data/test/TestSuite/Scheduler/Correct/css/tjmanual.css +0 -66
- 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/Scheduler/Errors/css/tjmanual.css +0 -66
- data/test/TestSuite/Scheduler/Errors/css/tjreport.css +0 -407
- data/test/TestSuite/Scheduler/Errors/icons/details.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/flag-green.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/flag-red.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/flag-yellow.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/resource.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/resourcegroup.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/task.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/taskgroup.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/trend-down.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/trend-flat.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/trend-up.png +0 -0
- data/test/TestSuite/Scheduler/Errors/scripts/wz_tooltip.js +0 -1301
- data/test/TestSuite/StatusSheets/resrep.tji +0 -7
- data/test/TestSuite/StatusSheets/tj3d.log +0 -312
- data/test/TestSuite/Syntax/Correct/Managers.html +0 -263
- data/test/TestSuite/TimeSheets/acceptable_intervals +0 -1
- data/test/TestSuite/TimeSheets/statussheets.log +0 -1
data/lib/Project.rb
CHANGED
@@ -78,7 +78,7 @@ class TaskJuggler
|
|
78
78
|
'flags' => [],
|
79
79
|
'journal' => Journal.new,
|
80
80
|
'limits' => nil,
|
81
|
-
'loadUnit' => :
|
81
|
+
'loadUnit' => :days,
|
82
82
|
'name' => name,
|
83
83
|
'navigators' => {},
|
84
84
|
'now' => TjTime.now.align(3600),
|
@@ -97,7 +97,7 @@ class TaskJuggler
|
|
97
97
|
'vacations' => [],
|
98
98
|
'version' => version || "1.0",
|
99
99
|
'weekStartsMonday' => true,
|
100
|
-
'workinghours' =>
|
100
|
+
'workinghours' => nil,
|
101
101
|
'yearlyworkingdays' => 260.714
|
102
102
|
}
|
103
103
|
|
@@ -430,6 +430,23 @@ class TaskJuggler
|
|
430
430
|
raise "Unknown project attribute #{name}"
|
431
431
|
end
|
432
432
|
@attributes[name] = value
|
433
|
+
|
434
|
+
# If the start, end or schedule granularity have been changed, we have
|
435
|
+
# to reset the working hours.
|
436
|
+
if %w(start end scheduleGranularity timezone timingresolution).
|
437
|
+
include?(name)
|
438
|
+
if @attributes['start'] && @attributes['end']
|
439
|
+
@attributes['workinghours'] =
|
440
|
+
WorkingHours.new(@attributes['scheduleGranularity'],
|
441
|
+
@attributes['start'], @attributes['end'])
|
442
|
+
# WorkingHours is using a copy-on-write scheme to prevent multiple
|
443
|
+
# copies of the same Scoreboard. All other WorkingHours objects are
|
444
|
+
# created as copies of this object. By calling
|
445
|
+
# WorkingHours::onShift? we make sure this instance has got a
|
446
|
+
# Scoreboard than gets reused by the other instances.
|
447
|
+
@attributes['workinghours'].onShift?(@attributes['start'])
|
448
|
+
end
|
449
|
+
end
|
433
450
|
end
|
434
451
|
|
435
452
|
# Return the number of defined scenarios for the project.
|
@@ -440,7 +457,7 @@ class TaskJuggler
|
|
440
457
|
# Try to match _levelName_ to a defined alert level name and return the
|
441
458
|
# index of it. If no level is found, nil is returned.
|
442
459
|
def alertLevelIndex(levelName)
|
443
|
-
|
460
|
+
@attributes['alertLevels'].length.times do |i|
|
444
461
|
if @attributes['alertLevels'][i][0] == levelName
|
445
462
|
return i
|
446
463
|
end
|
@@ -602,6 +619,24 @@ class TaskJuggler
|
|
602
619
|
true
|
603
620
|
end
|
604
621
|
|
622
|
+
# Make sure that we have a least one report defined that has an output
|
623
|
+
# format.
|
624
|
+
def checkReports
|
625
|
+
if @reports.empty?
|
626
|
+
@messageHandler.warning('no_report_defined',
|
627
|
+
"This project has no reports defined. " +
|
628
|
+
"No output data will be generated.")
|
629
|
+
end
|
630
|
+
|
631
|
+
@reports.each do |report|
|
632
|
+
return unless report.get('formats').empty?
|
633
|
+
end
|
634
|
+
|
635
|
+
@messageHandler.warning('all_formats_empty',
|
636
|
+
"None of the reports has a 'formats' attribute. " +
|
637
|
+
"No output data will be generated.")
|
638
|
+
end
|
639
|
+
|
605
640
|
# Call this function to generate the reports based on the scheduling result.
|
606
641
|
# This function may only be called after Project#schedule has been called.
|
607
642
|
def generateReports(maxCpuCores)
|
@@ -652,6 +687,12 @@ class TaskJuggler
|
|
652
687
|
error('unknown_report_id',
|
653
688
|
"Request to generate unknown report #{id}")
|
654
689
|
end
|
690
|
+
if report.get('formats').empty?
|
691
|
+
@messageHandler.error('formats_empty',
|
692
|
+
"The report #{report.fullId} has no 'formats' attribute. " +
|
693
|
+
"No output data will be generated.")
|
694
|
+
end
|
695
|
+
|
655
696
|
Log.startProgressMeter("Report #{report.name}")
|
656
697
|
@reportContexts.push(context = ReportContext.new(self, report))
|
657
698
|
|
@@ -834,7 +875,7 @@ class TaskJuggler
|
|
834
875
|
|
835
876
|
# Print the attribute values. It's used for debugging only.
|
836
877
|
def to_s
|
837
|
-
raise "STOP!"
|
878
|
+
#raise "STOP!"
|
838
879
|
str = ''
|
839
880
|
@attributes.each do |attribute, value|
|
840
881
|
if value
|
@@ -921,19 +962,22 @@ class TaskJuggler
|
|
921
962
|
|
922
963
|
def finishScenario(scIdx)
|
923
964
|
Log.startProgressMeter("Checking scenario #{scenario(scIdx).get('name')}")
|
924
|
-
total = @tasks.items
|
925
|
-
i = 0
|
926
965
|
@tasks.each do |task|
|
927
|
-
|
928
|
-
|
929
|
-
|
966
|
+
# Recursively traverse the top-level tasks to finish all tasks.
|
967
|
+
task.finishScheduling(scIdx) unless task.parent
|
968
|
+
end
|
969
|
+
|
970
|
+
@resources.each do |resource|
|
971
|
+
# Recursively traverse the top-level resources to finish them all.
|
972
|
+
resource.finishScheduling(scIdx) unless resource.parent
|
930
973
|
end
|
931
974
|
|
932
975
|
i = 0
|
976
|
+
total = @tasks.items
|
933
977
|
@tasks.each do |task|
|
934
978
|
task.postScheduleCheck(scIdx) if task.parent.nil?
|
935
979
|
i += 1
|
936
|
-
Log.progress(
|
980
|
+
Log.progress(i.to_f / total)
|
937
981
|
end
|
938
982
|
|
939
983
|
# This should be really fast so we don't log progess.
|
data/lib/ProjectFileParser.rb
CHANGED
@@ -39,10 +39,11 @@ class TaskJuggler
|
|
39
39
|
|
40
40
|
# Define the token types that the ProjectFileScanner may return for
|
41
41
|
# variable elements.
|
42
|
-
@variables =
|
43
|
-
|
42
|
+
@variables = [ :INTEGER, :FLOAT, :DATE, :TIME, :STRING, :LITERAL,
|
43
|
+
:ID, :ID_WITH_COLON, :ABSOLUTE_ID, :MACRO ]
|
44
44
|
|
45
45
|
initRules
|
46
|
+
updateParserTables
|
46
47
|
|
47
48
|
@project = nil
|
48
49
|
end
|
@@ -196,7 +197,7 @@ class TaskJuggler
|
|
196
197
|
# Add the new user-defined attribute as reportable attribute to the parser
|
197
198
|
# rule.
|
198
199
|
oldCurrentRule = @cr
|
199
|
-
@cr = @rules[
|
200
|
+
@cr = @rules[:reportableAttributes]
|
200
201
|
singlePattern('_' + @val[1])
|
201
202
|
descr(@val[2])
|
202
203
|
@cr = oldCurrentRule
|
@@ -209,11 +210,10 @@ class TaskJuggler
|
|
209
210
|
# data into a MessageHandler message that points to the correct location.
|
210
211
|
# This is necessary, because the RichText parser knows nothing about the
|
211
212
|
# actual input file. So we have to map the error location in the RichText
|
212
|
-
# input stream back to the position in the project file.
|
213
|
-
# To limit the supported set of
|
214
|
-
# by _tokenSet_.
|
215
|
-
def newRichText(text, tokenSet = nil)
|
216
|
-
sfi = sourceFileInfo
|
213
|
+
# input stream back to the position in the project file. _sfi_ is the
|
214
|
+
# SourceFileInfo of the input string. To limit the supported set of
|
215
|
+
# variable tokens, a subset can be provided by _tokenSet_.
|
216
|
+
def newRichText(text, sfi, tokenSet = nil)
|
217
217
|
rText = RichText.new(text, RTFHandlers.create(@project, sfi))
|
218
218
|
unless (rti = rText.generateIntermediateFormat( [ 0, 0, 0], tokenSet))
|
219
219
|
rText.messageHandler.messages.each do |msg|
|
@@ -357,7 +357,8 @@ class TaskJuggler
|
|
357
357
|
# token.
|
358
358
|
def descr(text)
|
359
359
|
if @cr.patterns[-1].length != 1 ||
|
360
|
-
(@cr.patterns[-1][0][0] !=
|
360
|
+
(@cr.patterns[-1][0][0] != :literal &&
|
361
|
+
@cr.patterns[-1][0][0] != :variable)
|
361
362
|
raise 'descr() may only be used for patterns with terminal tokens.'
|
362
363
|
end
|
363
364
|
arg(0, nil, text)
|
data/lib/ProjectFileScanner.rb
CHANGED
@@ -71,25 +71,25 @@ class TaskJuggler
|
|
71
71
|
[ nil, /.*\n/, :macroCall, method('midMacroCall') ],
|
72
72
|
|
73
73
|
# An ID with a colon suffix: foo:
|
74
|
-
[
|
74
|
+
[ :ID_WITH_COLON, /[a-zA-Z_]\w*:/, :tjp, method('chop') ],
|
75
75
|
|
76
76
|
# An absolute ID: a.b.c
|
77
|
-
[
|
77
|
+
[ :ABSOLUTE_ID, /[a-zA-Z_]\w*(\.[a-zA-Z_]\w*)+/ ],
|
78
78
|
|
79
79
|
# A normal ID: bar
|
80
|
-
[
|
80
|
+
[ :ID, /[a-zA-Z_]\w*/ ],
|
81
81
|
|
82
82
|
# A date
|
83
|
-
[
|
83
|
+
[ :DATE, /\d{4}-\d{1,2}-\d{1,2}(-\d{1,2}:\d{1,2}(:\d{1,2})?(-[-+]?\d{4})?)?/, :tjp, method('to_date') ],
|
84
84
|
|
85
85
|
# A time of day
|
86
|
-
[
|
86
|
+
[ :TIME, /\d{1,2}:\d{2}/, :tjp, method('to_time') ],
|
87
87
|
|
88
88
|
# A floating point number (e. g. 3.143)
|
89
|
-
[
|
89
|
+
[ :FLOAT, /\d*\.\d+/, :tjp, method('to_f') ],
|
90
90
|
|
91
91
|
# An integer number
|
92
|
-
[
|
92
|
+
[ :INTEGER, /\d+/, :tjp, method('to_i') ],
|
93
93
|
|
94
94
|
# Multi line string enclosed with double quotes. The string may
|
95
95
|
# contain double quotes prefixed by a backslash. The first rule
|
@@ -98,14 +98,14 @@ class TaskJuggler
|
|
98
98
|
# Any line not containing the start or end.
|
99
99
|
[ 'nil', /^(\\"|[^"])*\n/, :dqString, method('midStringDQ') ],
|
100
100
|
# The end of the string.
|
101
|
-
[
|
101
|
+
[ :STRING, /(\\"|[^"])*"/, :dqString, method('endStringDQ') ],
|
102
102
|
|
103
103
|
# Multi line string enclosed with single quotes.
|
104
104
|
[ 'nil', /'(\\'|[^'])*/, :tjp, method('startStringSQ') ],
|
105
105
|
# Any line not containing the start or end.
|
106
106
|
[ 'nil', /^(\\'|[^'])*\n/, :sqString, method('midStringSQ') ],
|
107
107
|
# The end of the string.
|
108
|
-
[
|
108
|
+
[ :STRING, /(\\'|[^'])*'/, :sqString, method('endStringSQ') ],
|
109
109
|
|
110
110
|
# Scizzors marked string -8<- ... ->8-: The opening mark must be the
|
111
111
|
# last thing in the line. The indentation of the first line after the
|
@@ -115,8 +115,8 @@ class TaskJuggler
|
|
115
115
|
# Since the first line can be the last line (empty string case), we
|
116
116
|
# need to detect the end in szrString1 and szrString mode. The
|
117
117
|
# patterns switch the scanner back to tjp mode.
|
118
|
-
[
|
119
|
-
[
|
118
|
+
[ :STRING, /\s*->8-/, :szrString1, method('endStringSZR') ],
|
119
|
+
[ :STRING, /\s*->8-/, :szrString, method('endStringSZR') ],
|
120
120
|
# This rule handles macros inside of sizzors strings.
|
121
121
|
[ nil, /.*?\$\{\s*([a-zA-Z_]\w*)(\s*"(\\"|[^"])*")*/,
|
122
122
|
[ :szrString, :szrString1 ], method('startMacroCall') ],
|
@@ -125,24 +125,24 @@ class TaskJuggler
|
|
125
125
|
[ 'nil', /.*\n/, :szrString, method('midStringSZR') ],
|
126
126
|
|
127
127
|
# Single line macro definition
|
128
|
-
[
|
128
|
+
[ :MACRO, /\[.*\]\n/, :tjp, method('chop2nl') ],
|
129
129
|
|
130
130
|
# Multi line macro definition: The pattern switches the scanner into
|
131
131
|
# macroDef mode.
|
132
132
|
[ nil, /\[.*\n/, :tjp, method('startMacroDef') ],
|
133
133
|
# The end of the macro is marked by a ']' that is immediately followed
|
134
134
|
# by a line break. It switches the scanner back to tjp mode.
|
135
|
-
[
|
135
|
+
[ :MACRO, /.*\]\n/, :macroDef, method('endMacroDef') ],
|
136
136
|
# Any line not containing the start or end.
|
137
137
|
[ nil, /.*\n/, :macroDef, method('midMacroDef') ],
|
138
138
|
|
139
139
|
# Some multi-char literals.
|
140
|
-
[
|
141
|
-
[
|
142
|
-
[
|
140
|
+
[ :LITERAL, /<=?/ ],
|
141
|
+
[ :LITERAL, />=?/ ],
|
142
|
+
[ :LITERAL, /!=?/ ],
|
143
143
|
|
144
144
|
# Everything else is returned as a single-char literal.
|
145
|
-
[
|
145
|
+
[ :LITERAL, /./ ]
|
146
146
|
]
|
147
147
|
|
148
148
|
super(masterFile, messageHandler, tokenPatterns, :tjp)
|
@@ -159,15 +159,28 @@ class TaskJuggler
|
|
159
159
|
end
|
160
160
|
|
161
161
|
def to_time(type, match)
|
162
|
-
h, m
|
162
|
+
h, m = match.split(':')
|
163
163
|
h = h.to_i
|
164
|
+
if h < 0 || h > 24
|
165
|
+
error('time_bad_hour', "Hour #{h} out of range (0 - 24)")
|
166
|
+
end
|
164
167
|
m = m.to_i
|
165
|
-
|
166
|
-
|
168
|
+
if m < 0 || h > 59
|
169
|
+
error('time_bad_minute', "Minute #{m} out of range (0 - 59)")
|
170
|
+
end
|
171
|
+
if h == 24 && m != 0
|
172
|
+
error('time_bad_time', "Time #{match} cannot be larger then 24:00")
|
173
|
+
end
|
174
|
+
|
175
|
+
[ type, (h * 60 + m) * 60 ]
|
167
176
|
end
|
168
177
|
|
169
178
|
def to_date(type, match)
|
170
|
-
|
179
|
+
begin
|
180
|
+
[ type, TjTime.new(match) ]
|
181
|
+
rescue TjException => msg
|
182
|
+
error('time_error', msg)
|
183
|
+
end
|
171
184
|
end
|
172
185
|
|
173
186
|
def newPos(type, match)
|
@@ -216,7 +229,7 @@ class TaskJuggler
|
|
216
229
|
self.mode = :tjp
|
217
230
|
# Remove the trailing " and remove the backslashes from escaped ".
|
218
231
|
@string += match[0..-2].gsub(/\\"/, '"')
|
219
|
-
[
|
232
|
+
[ :STRING, @string ]
|
220
233
|
end
|
221
234
|
|
222
235
|
def startStringSQ(type, match)
|
@@ -236,7 +249,7 @@ class TaskJuggler
|
|
236
249
|
self.mode = :tjp
|
237
250
|
# Remove the trailing ' and remove the backslashes from escaped '.
|
238
251
|
@string += match[0..-2].gsub(/\\'/, "'")
|
239
|
-
[
|
252
|
+
[ :STRING, @string ]
|
240
253
|
end
|
241
254
|
|
242
255
|
def startStringSZR(type, match)
|
@@ -274,7 +287,7 @@ class TaskJuggler
|
|
274
287
|
|
275
288
|
def endStringSZR(type, match)
|
276
289
|
self.mode = :tjp
|
277
|
-
[
|
290
|
+
[ :STRING, @string ]
|
278
291
|
end
|
279
292
|
|
280
293
|
def startMacroDef(type, match)
|
@@ -293,7 +306,7 @@ class TaskJuggler
|
|
293
306
|
self.mode = :tjp
|
294
307
|
# Remove "]\n"
|
295
308
|
@macroDef += match[0..-3]
|
296
|
-
[
|
309
|
+
[ :MACRO, @macroDef ]
|
297
310
|
end
|
298
311
|
|
299
312
|
def startMacroCall(type, match)
|
data/lib/PropertyList.rb
CHANGED
@@ -168,19 +168,21 @@ class TaskJuggler
|
|
168
168
|
def addSortingCriteria(criteria, up, scIdx)
|
169
169
|
unless @propertySet.knownAttribute?(criteria) ||
|
170
170
|
@propertySet.hasQuery?(criteria, scIdx)
|
171
|
-
raise
|
171
|
+
raise TjException.new,
|
172
|
+
"Unknown attribute #{criteria} used for sorting criterium"
|
172
173
|
end
|
173
174
|
if scIdx == -1
|
174
175
|
if @propertySet.scenarioSpecific?(criteria)
|
175
|
-
raise
|
176
|
+
raise TjException.new,
|
177
|
+
"Attribute #{criteria} is scenario specific." +
|
176
178
|
"You must specify a scenario id."
|
177
179
|
end
|
178
180
|
else
|
179
181
|
if @propertySet.project.scenario(scIdx).nil?
|
180
|
-
raise "Unknown scenario index #{scIdx} used."
|
182
|
+
raise TjException.new, "Unknown scenario index #{scIdx} used."
|
181
183
|
end
|
182
184
|
if !@propertySet.scenarioSpecific?(criteria)
|
183
|
-
raise "Attribute #{criteria} is not scenario specific"
|
185
|
+
raise TjException.new, "Attribute #{criteria} is not scenario specific"
|
184
186
|
end
|
185
187
|
end
|
186
188
|
@sortingCriteria.push(criteria)
|
data/lib/Query.rb
CHANGED
@@ -70,8 +70,6 @@ class TaskJuggler
|
|
70
70
|
if date.is_a?(TjTime)
|
71
71
|
@start = date
|
72
72
|
@startIdx = @project.dateToIdx(date, true)
|
73
|
-
#elsif date.is_a?(Fixnum)
|
74
|
-
# self.startIdx=(date)
|
75
73
|
else
|
76
74
|
raise "Unsupported type #{date.class}"
|
77
75
|
end
|
@@ -81,8 +79,6 @@ class TaskJuggler
|
|
81
79
|
if idx.is_a?(Fixnum)
|
82
80
|
@startIdx = idx
|
83
81
|
@start = @project.idxToDate(idx)
|
84
|
-
#elsif idx.is_a?(TjTime)
|
85
|
-
# self.start=(idx)
|
86
82
|
else
|
87
83
|
raise "Unsupported type #{idx.class}"
|
88
84
|
end
|
@@ -92,8 +88,6 @@ class TaskJuggler
|
|
92
88
|
if date.is_a?(TjTime)
|
93
89
|
@end = date
|
94
90
|
@endIdx = @project.dateToIdx(date, true)
|
95
|
-
#elsif date.is_a?(Fixnum)
|
96
|
-
# self.endIdx=(date)
|
97
91
|
else
|
98
92
|
raise "Unsupported type #{date.class}"
|
99
93
|
end
|
@@ -103,8 +97,6 @@ class TaskJuggler
|
|
103
97
|
if idx.is_a?(Fixnum)
|
104
98
|
@endIdx = idx
|
105
99
|
@end = @project.idxToDate(idx)
|
106
|
-
#elsif idx.is_a?(TjTime)
|
107
|
-
# self.end=(idx)
|
108
100
|
else
|
109
101
|
raise "Unsupported type #{idx.class}"
|
110
102
|
end
|
data/lib/RealFormat.rb
CHANGED
data/lib/Resource.rb
CHANGED
@@ -56,7 +56,7 @@ class TaskJuggler
|
|
56
56
|
# Sort all entries in buckets by their alert level.
|
57
57
|
numberOfLevels = project['alertLevels'].length
|
58
58
|
listByLevel = []
|
59
|
-
|
59
|
+
numberOfLevels.times { |i| listByLevel[i] = [] }
|
60
60
|
list.each do |entry|
|
61
61
|
listByLevel[entry.alertLevel] << entry
|
62
62
|
end
|
data/lib/ResourceScenario.rb
CHANGED
@@ -37,15 +37,23 @@ class TaskJuggler
|
|
37
37
|
# subset.
|
38
38
|
@scoreboard = nil
|
39
39
|
|
40
|
+
# The index of the earliest booked time slot.
|
40
41
|
@firstBookedSlot = nil
|
42
|
+
# Same but for each assigned resource.
|
43
|
+
@firstBookedSlots = {}
|
44
|
+
# The index of the last booked time Slot.
|
41
45
|
@lastBookedSlot = nil
|
46
|
+
# Same but for each assigned resource.
|
47
|
+
@lastBookedSlots = {}
|
48
|
+
|
49
|
+
@dCache = DataCache.instance
|
42
50
|
end
|
43
51
|
|
44
52
|
# This method must be called at the beginning of each scheduling run. It
|
45
53
|
# initializes variables used during the scheduling process.
|
46
54
|
def prepareScheduling
|
47
55
|
@property['effort', @scenarioIdx] = 0
|
48
|
-
initScoreboard
|
56
|
+
initScoreboard if @property.leaf?
|
49
57
|
|
50
58
|
setDirectReports
|
51
59
|
end
|
@@ -91,7 +99,6 @@ class TaskJuggler
|
|
91
99
|
end
|
92
100
|
end
|
93
101
|
|
94
|
-
|
95
102
|
def preScheduleCheck
|
96
103
|
a('managers').each do |manager|
|
97
104
|
unless manager.leaf?
|
@@ -106,6 +113,25 @@ class TaskJuggler
|
|
106
113
|
end
|
107
114
|
end
|
108
115
|
|
116
|
+
# This method does some housekeeping work after the scheduling is
|
117
|
+
# completed. It's meant to be called for top-level resources and then
|
118
|
+
# recursively descends into all child resources.
|
119
|
+
def finishScheduling
|
120
|
+
# Recursively descend into all child resources.
|
121
|
+
@property.children.each do |resource|
|
122
|
+
resource.finishScheduling(@scenarioIdx)
|
123
|
+
end
|
124
|
+
|
125
|
+
if (parent = @property.parent)
|
126
|
+
# Add the assigned task to the parent duties list.
|
127
|
+
a('duties').each do |task|
|
128
|
+
unless parent['duties', @scenarioIdx].include?(task)
|
129
|
+
parent['duties', @scenarioIdx] << task
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
109
135
|
def postScheduleCheck
|
110
136
|
if a('fail') || a('warn')
|
111
137
|
queryAttrs = { 'project' => @project,
|
@@ -158,6 +184,11 @@ class TaskJuggler
|
|
158
184
|
def book(sbIdx, task, force = false)
|
159
185
|
return false if !force && !available?(sbIdx)
|
160
186
|
|
187
|
+
# Make sure the task is in the list of duties.
|
188
|
+
unless a('duties').include?(task)
|
189
|
+
@property['duties', @scenarioIdx] << task
|
190
|
+
end
|
191
|
+
|
161
192
|
#puts "Booking resource #{@property.fullId} at " +
|
162
193
|
# "#{@scoreboard.idxToDate(sbIdx)}/#{sbIdx} for task #{task.fullId}\n"
|
163
194
|
@scoreboard[sbIdx] = task
|
@@ -170,17 +201,24 @@ class TaskJuggler
|
|
170
201
|
end
|
171
202
|
a('limits').inc(@scoreboard.idxToDate(sbIdx)) if a('limits')
|
172
203
|
|
173
|
-
#
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
204
|
+
# Scoreboard iterations are fairly expensive but they are very frequent
|
205
|
+
# operations in later processing. To limit the interations to the
|
206
|
+
# relevant intervals, we store the interval for all bookings and for
|
207
|
+
# each individual task.
|
178
208
|
if @firstBookedSlot.nil? || @firstBookedSlot > sbIdx
|
179
209
|
@firstBookedSlot = sbIdx
|
180
210
|
end
|
181
211
|
if @lastBookedSlot.nil? || @lastBookedSlot < sbIdx
|
182
212
|
@lastBookedSlot = sbIdx
|
183
213
|
end
|
214
|
+
if task
|
215
|
+
if @firstBookedSlots[task].nil? || @firstBookedSlots[task] > sbIdx
|
216
|
+
@firstBookedSlots[task] = sbIdx
|
217
|
+
end
|
218
|
+
if @lastBookedSlots[task].nil? || @lastBookedSlots[task] < sbIdx
|
219
|
+
@lastBookedSlots[task] = sbIdx
|
220
|
+
end
|
221
|
+
end
|
184
222
|
true
|
185
223
|
end
|
186
224
|
|
@@ -291,6 +329,16 @@ class TaskJuggler
|
|
291
329
|
# Returns the work of the resource (and its children) weighted by their
|
292
330
|
# efficiency.
|
293
331
|
def getEffectiveWork(startIdx, endIdx, task = nil)
|
332
|
+
# There can't be any effective work if the start is after the end or the
|
333
|
+
# todo list doesn't contain the specified task.
|
334
|
+
return 0.0 if startIdx >= endIdx || (task && !a('duties').include?(task))
|
335
|
+
|
336
|
+
# The unique key we use to address the result in the cache.
|
337
|
+
key = [ self, :ResourceScenarioEffectiveWork, startIdx, endIdx,
|
338
|
+
task ].hash
|
339
|
+
work = @dCache.load(key)
|
340
|
+
return work if work
|
341
|
+
|
294
342
|
# Convert the interval dates to indexes if needed.
|
295
343
|
startIdx = @project.dateToIdx(startIdx, true) if startIdx.is_a?(TjTime)
|
296
344
|
endIdx = @project.dateToIdx(endIdx, true) if endIdx.is_a?(TjTime)
|
@@ -307,7 +355,7 @@ class TaskJuggler
|
|
307
355
|
getAllocatedSlots(startIdx, endIdx, task) *
|
308
356
|
@project['scheduleGranularity']) * a('efficiency')
|
309
357
|
end
|
310
|
-
work
|
358
|
+
@dCache.store(work, key)
|
311
359
|
end
|
312
360
|
|
313
361
|
# Returns the allocated accumulated time of this resource and its children.
|
@@ -419,16 +467,13 @@ class TaskJuggler
|
|
419
467
|
# the period specified with the Interval _iv_. If task is not nil
|
420
468
|
# only allocations to this tasks are respected.
|
421
469
|
def allocated?(iv, task = nil)
|
422
|
-
|
470
|
+
return false if task && !a('duties').include?(task)
|
423
471
|
|
424
|
-
startIdx = @
|
425
|
-
endIdx = @
|
472
|
+
startIdx = @project.dateToIdx(iv.start, true)
|
473
|
+
endIdx = @project.dateToIdx(iv.end, true)
|
426
474
|
|
427
|
-
startIdx =
|
428
|
-
|
429
|
-
endIdx = @lastBookedSlot + 1 if @lastBookedSlot &&
|
430
|
-
endIdx < @lastBookedSlot + 1
|
431
|
-
return false if startIdx > endIdx
|
475
|
+
startIdx, endIdx = fitIndicies(startIdx, endIdx, task)
|
476
|
+
return false if startIdx >= endIdx
|
432
477
|
|
433
478
|
return allocatedSub(startIdx, endIdx, task)
|
434
479
|
end
|
@@ -461,8 +506,6 @@ class TaskJuggler
|
|
461
506
|
bookings[lastTask] = Booking.new(@property, lastTask, [])
|
462
507
|
end
|
463
508
|
|
464
|
-
# Make sure the index is correct even for the last task block.
|
465
|
-
idx += 1 if idx == endIdx
|
466
509
|
# Append the new interval to the Booking.
|
467
510
|
bookings[lastTask].intervals <<
|
468
511
|
Interval.new(@scoreboard.idxToDate(bookingStart),
|
@@ -494,18 +537,15 @@ class TaskJuggler
|
|
494
537
|
# Count the booked slots between the start and end index. If _task_ is not
|
495
538
|
# nil count only those slots that are assigned to this particular task.
|
496
539
|
def getAllocatedSlots(startIdx, endIdx, task)
|
497
|
-
#
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
endIdx > @lastBookedSlot + 1
|
540
|
+
# If there is no scoreboard, we don't have any allocations.
|
541
|
+
return 0 unless @scoreboard
|
542
|
+
|
543
|
+
startIdx, endIdx = fitIndicies(startIdx, endIdx, task)
|
544
|
+
return 0 if startIdx >= endIdx
|
503
545
|
|
504
|
-
initScoreboard if @scoreboard.nil?
|
505
546
|
bookedSlots = 0
|
506
|
-
|
507
|
-
if (task.nil? &&
|
508
|
-
(task && @scoreboard[idx] == task)
|
547
|
+
@scoreboard.each(startIdx, endIdx) do |slot|
|
548
|
+
if (task.nil? && slot.is_a?(Task)) || (task && slot == task)
|
509
549
|
bookedSlots += 1
|
510
550
|
end
|
511
551
|
end
|
@@ -515,7 +555,9 @@ class TaskJuggler
|
|
515
555
|
|
516
556
|
# Count the free slots between the start and end index.
|
517
557
|
def getFreeSlots(startIdx, endIdx)
|
518
|
-
|
558
|
+
return 0 if startIdx >= endIdx
|
559
|
+
|
560
|
+
initScoreboard unless @scoreboard
|
519
561
|
|
520
562
|
freeSlots = 0
|
521
563
|
startIdx.upto(endIdx - 1) do |idx|
|
@@ -528,7 +570,9 @@ class TaskJuggler
|
|
528
570
|
# Count the regular work time slots between the start and end index that
|
529
571
|
# have been blocked by a vacation.
|
530
572
|
def getVacationSlots(startIdx, endIdx)
|
531
|
-
|
573
|
+
return 0 if startIdx >= endIdx
|
574
|
+
|
575
|
+
initScoreboard unless @scoreboard
|
532
576
|
|
533
577
|
vacationSlots = 0
|
534
578
|
startIdx.upto(endIdx - 1) do |idx|
|
@@ -603,6 +647,24 @@ class TaskJuggler
|
|
603
647
|
end
|
604
648
|
end
|
605
649
|
|
650
|
+
# Limit the _startIdx_ and _endIdx_ to the actually assigned interval.
|
651
|
+
# If _task_ is provided, fit it for the bookings of this particular task.
|
652
|
+
def fitIndicies(startIdx, endIdx, task = nil)
|
653
|
+
if task
|
654
|
+
startIdx = @firstBookedSlots[task] if @firstBookedSlots[task] &&
|
655
|
+
startIdx < @firstBookedSlots[task]
|
656
|
+
endIdx = @lastBookedSlots[task] + 1 if @lastBookedSlots[task] &&
|
657
|
+
endIdx >
|
658
|
+
@lastBookedSlots[task] + 1
|
659
|
+
else
|
660
|
+
startIdx = @firstBookedSlot if @firstBookedSlot &&
|
661
|
+
startIdx < @firstBookedSlot
|
662
|
+
endIdx = @lastBookedSlot + 1 if @lastBookedSlot &&
|
663
|
+
endIdx > @lastBookedSlot + 1
|
664
|
+
end
|
665
|
+
[ startIdx, endIdx ]
|
666
|
+
end
|
667
|
+
|
606
668
|
def setReports_i(reports)
|
607
669
|
if reports.include?(@property)
|
608
670
|
# A manager must never show up in the list of his/her own reports.
|
@@ -638,7 +700,10 @@ class TaskJuggler
|
|
638
700
|
task)
|
639
701
|
end
|
640
702
|
else
|
641
|
-
return false unless a('duties').include?(task)
|
703
|
+
return false unless @scoreboard && a('duties').include?(task)
|
704
|
+
|
705
|
+
startIdx, endIdx = fitIndicies(startIdx, endIdx, task)
|
706
|
+
return false if startIdx >= endIdx
|
642
707
|
|
643
708
|
startIdx.upto(endIdx - 1) do |idx|
|
644
709
|
return true if @scoreboard[idx] == task
|