taskjuggler 0.0.5 → 0.0.6
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/CHANGELOG +2086 -0
- data/benchmarks/666tasks.tjp +3183 -0
- data/benchmarks/booking.tjp +14 -10
- data/doc/AppConfig.html +95 -73
- data/doc/Arguments.html +22 -2
- data/doc/CHANGELOG.html +2587 -0
- data/doc/COPYING.html +21 -1
- data/doc/Object.html +161 -122
- data/doc/README.html +21 -1
- data/doc/RuntimeConfig.html +26 -6
- data/doc/String.html +38 -18
- data/doc/StringIO.html +579 -0
- data/doc/TaskJuggler.html +251 -143
- data/doc/TaskJuggler/Account.html +26 -6
- data/doc/TaskJuggler/AccountAttribute.html +28 -8
- data/doc/TaskJuggler/AccountScenario.html +24 -4
- data/doc/TaskJuggler/Allocation.html +30 -10
- data/doc/TaskJuggler/AllocationAttribute.html +28 -8
- data/doc/TaskJuggler/AttributeBase.html +46 -26
- data/doc/TaskJuggler/AttributeDefinition.html +22 -2
- data/doc/TaskJuggler/BatchProcessor.html +40 -20
- data/doc/TaskJuggler/Booking.html +26 -6
- data/doc/TaskJuggler/BookingListAttribute.html +28 -8
- data/doc/TaskJuggler/BooleanAttribute.html +28 -8
- data/doc/TaskJuggler/CSVFile.html +308 -146
- data/doc/TaskJuggler/CellSettingPattern.html +22 -2
- data/doc/TaskJuggler/CellSettingPatternList.html +26 -6
- data/doc/TaskJuggler/Charge.html +26 -6
- data/doc/TaskJuggler/ChargeListAttribute.html +26 -6
- data/doc/TaskJuggler/ChargeSet.html +33 -13
- data/doc/TaskJuggler/ChargeSetListAttribute.html +28 -8
- data/doc/TaskJuggler/ColumnListAttribute.html +26 -6
- data/doc/TaskJuggler/ColumnTable.html +24 -4
- data/doc/TaskJuggler/Daemon.html +26 -6
- data/doc/TaskJuggler/DateAttribute.html +26 -6
- data/doc/TaskJuggler/DefinitionListAttribute.html +22 -2
- data/doc/TaskJuggler/DependencyListAttribute.html +28 -8
- data/doc/TaskJuggler/DurationAttribute.html +28 -8
- data/doc/TaskJuggler/FixnumAttribute.html +24 -4
- data/doc/TaskJuggler/FlagListAttribute.html +28 -8
- data/doc/TaskJuggler/FloatAttribute.html +26 -6
- data/doc/TaskJuggler/FormatListAttribute.html +24 -4
- data/doc/TaskJuggler/GanttChart.html +147 -126
- data/doc/TaskJuggler/GanttContainer.html +34 -14
- data/doc/TaskJuggler/GanttHeader.html +28 -8
- data/doc/TaskJuggler/GanttHeaderScaleItem.html +24 -4
- data/doc/TaskJuggler/GanttLine.html +38 -18
- data/doc/TaskJuggler/GanttLoadStack.html +26 -6
- data/doc/TaskJuggler/GanttMilestone.html +34 -14
- data/doc/TaskJuggler/GanttRouter.html +50 -30
- data/doc/TaskJuggler/GanttTaskBar.html +34 -14
- data/doc/TaskJuggler/HTMLDocument.html +26 -6
- data/doc/TaskJuggler/HTMLGraphics.html +30 -10
- data/doc/TaskJuggler/Interval.html +40 -22
- data/doc/TaskJuggler/IntervalListAttribute.html +28 -8
- data/doc/TaskJuggler/JobInfo.html +24 -4
- data/doc/TaskJuggler/Journal.html +226 -147
- data/doc/TaskJuggler/JournalEntry.html +22 -2
- data/doc/TaskJuggler/JournalEntryList.html +129 -112
- data/doc/TaskJuggler/KeywordArray.html +26 -6
- data/doc/TaskJuggler/KeywordDocumentation.html +46 -26
- data/doc/TaskJuggler/Limits.html +152 -123
- data/doc/TaskJuggler/Limits/Limit.html +149 -70
- data/doc/TaskJuggler/LimitsAttribute.html +36 -51
- data/doc/TaskJuggler/ListAttributeBase.html +24 -4
- data/doc/TaskJuggler/Log.html +50 -32
- data/doc/TaskJuggler/LogFile.html +37 -17
- data/doc/TaskJuggler/LogicalAttribute.html +53 -33
- data/doc/TaskJuggler/LogicalExpression.html +26 -6
- data/doc/TaskJuggler/LogicalExpressionAttribute.html +32 -12
- data/doc/TaskJuggler/LogicalFlag.html +42 -22
- data/doc/TaskJuggler/LogicalFunction.html +204 -140
- data/doc/TaskJuggler/LogicalOperation.html +135 -111
- data/doc/TaskJuggler/Macro.html +22 -2
- data/doc/TaskJuggler/MacroParser.html +32 -12
- data/doc/TaskJuggler/MacroTable.html +32 -12
- data/doc/TaskJuggler/ManagerResponsibilities.html +24 -4
- data/doc/TaskJuggler/ManagerStatusRecord.html +24 -4
- data/doc/TaskJuggler/Message.html +24 -4
- data/doc/TaskJuggler/MessageHandler.html +24 -4
- data/doc/TaskJuggler/Navigator.html +104 -71
- data/doc/TaskJuggler/NavigatorElement.html +32 -12
- data/doc/TaskJuggler/NikuProject.html +22 -2
- data/doc/TaskJuggler/NikuReport.html +310 -228
- data/doc/TaskJuggler/NikuResource.html +22 -2
- data/doc/TaskJuggler/NodeListAttribute.html +615 -0
- data/doc/TaskJuggler/OnShiftCache.html +32 -12
- data/doc/TaskJuggler/ProcessIntercom.html +205 -78
- data/doc/TaskJuggler/ProcessIntercomIface.html +26 -6
- data/doc/TaskJuggler/Project.html +708 -660
- data/doc/TaskJuggler/ProjectBroker.html +506 -304
- data/doc/TaskJuggler/ProjectBrokerIface.html +61 -41
- data/doc/TaskJuggler/ProjectFileParser.html +429 -373
- data/doc/TaskJuggler/ProjectFileScanner.html +1790 -0
- data/doc/TaskJuggler/ProjectRecord.html +80 -60
- data/doc/TaskJuggler/ProjectServer.html +312 -237
- data/doc/TaskJuggler/ProjectServerIface.html +101 -43
- data/doc/TaskJuggler/PropertyAttribute.html +32 -12
- data/doc/TaskJuggler/PropertyList.html +166 -145
- data/doc/TaskJuggler/PropertySet.html +254 -224
- data/doc/TaskJuggler/PropertyTreeNode.html +670 -536
- data/doc/TaskJuggler/Query.html +169 -148
- data/doc/TaskJuggler/RTFHandlers.html +622 -0
- data/doc/TaskJuggler/RTFNavigator.html +28 -8
- data/doc/TaskJuggler/RTFQuery.html +40 -20
- data/doc/TaskJuggler/RTFReport.html +62 -25
- data/doc/TaskJuggler/RTFReportLink.html +765 -0
- data/doc/TaskJuggler/RealFormat.html +26 -6
- data/doc/TaskJuggler/RealFormatAttribute.html +26 -6
- data/doc/TaskJuggler/ReferenceAttribute.html +59 -39
- data/doc/TaskJuggler/Report.html +402 -251
- data/doc/TaskJuggler/ReportBase.html +162 -137
- data/doc/TaskJuggler/ReportContext.html +112 -29
- data/doc/TaskJuggler/ReportServer.html +89 -64
- data/doc/TaskJuggler/ReportServerIface.html +75 -55
- data/doc/TaskJuggler/ReportServerRecord.html +54 -31
- data/doc/TaskJuggler/ReportServlet.html +980 -0
- data/doc/TaskJuggler/ReportTable.html +41 -21
- data/doc/TaskJuggler/ReportTableCell.html +214 -170
- data/doc/TaskJuggler/ReportTableColumn.html +30 -10
- data/doc/TaskJuggler/ReportTableLegend.html +36 -16
- data/doc/TaskJuggler/ReportTableLine.html +32 -12
- data/doc/TaskJuggler/Resource.html +99 -87
- data/doc/TaskJuggler/ResourceListAttribute.html +59 -39
- data/doc/TaskJuggler/ResourceListRE.html +47 -26
- data/doc/TaskJuggler/ResourceScenario.html +403 -437
- data/doc/TaskJuggler/RichText.html +26 -6
- data/doc/TaskJuggler/RichTextAttribute.html +50 -30
- data/doc/TaskJuggler/RichTextDocument.html +37 -17
- data/doc/TaskJuggler/RichTextElement.html +475 -413
- data/doc/TaskJuggler/RichTextException.html +22 -2
- data/doc/TaskJuggler/RichTextFunctionExample.html +28 -8
- data/doc/TaskJuggler/RichTextFunctionHandler.html +24 -4
- data/doc/TaskJuggler/RichTextImage.html +22 -2
- data/doc/TaskJuggler/RichTextIntermediate.html +38 -18
- data/doc/TaskJuggler/RichTextParser.html +56 -34
- data/doc/TaskJuggler/RichTextScanner.html +82 -61
- data/doc/TaskJuggler/RichTextSnip.html +34 -14
- data/doc/TaskJuggler/RichTextSyntaxRules.html +507 -353
- data/doc/TaskJuggler/Scenario.html +22 -2
- data/doc/TaskJuggler/ScenarioData.html +30 -46
- data/doc/TaskJuggler/ScenarioListAttribute.html +38 -18
- data/doc/TaskJuggler/Scoreboard.html +42 -22
- data/doc/TaskJuggler/SheetHandlerBase.html +40 -20
- data/doc/TaskJuggler/SheetReceiver.html +333 -295
- data/doc/TaskJuggler/SheetSender.html +253 -230
- data/doc/TaskJuggler/Shift.html +26 -6
- data/doc/TaskJuggler/ShiftAssignment.html +89 -73
- data/doc/TaskJuggler/ShiftAssignments.html +226 -234
- data/doc/TaskJuggler/ShiftAssignmentsAttribute.html +39 -54
- data/doc/TaskJuggler/ShiftScenario.html +28 -8
- data/doc/TaskJuggler/SortListAttribute.html +34 -14
- data/doc/TaskJuggler/SourceFileInfo.html +24 -4
- data/doc/TaskJuggler/StatusSheetReceiver.html +24 -3
- data/doc/TaskJuggler/StatusSheetReport.html +168 -153
- data/doc/TaskJuggler/StatusSheetSender.html +24 -3
- data/doc/TaskJuggler/StringAttribute.html +38 -18
- data/doc/TaskJuggler/SymbolAttribute.html +32 -12
- data/doc/TaskJuggler/SyntaxReference.html +40 -20
- data/doc/TaskJuggler/TOCEntry.html +26 -6
- data/doc/TaskJuggler/TSResourceRecord.html +22 -2
- data/doc/TaskJuggler/TSTaskRecord.html +22 -2
- data/doc/TaskJuggler/TableColumnDefinition.html +59 -22
- data/doc/TaskJuggler/TableOfContents.html +26 -6
- data/doc/TaskJuggler/TableReport.html +937 -904
- data/doc/TaskJuggler/Task.html +55 -36
- data/doc/TaskJuggler/TaskDependency.html +24 -4
- data/doc/TaskJuggler/TaskListAttribute.html +50 -30
- data/doc/TaskJuggler/TaskListRE.html +27 -7
- data/doc/TaskJuggler/TaskScenario.html +1273 -1153
- data/doc/TaskJuggler/TextFormatter.html +28 -8
- data/doc/TaskJuggler/TextParser.html +585 -338
- data/doc/TaskJuggler/TextParser/Pattern.html +54 -34
- data/doc/TaskJuggler/TextParser/Rule.html +95 -73
- data/doc/TaskJuggler/TextParser/StackElement.html +39 -17
- data/doc/TaskJuggler/TextParser/TextParserResultArray.html +24 -4
- data/doc/TaskJuggler/TextParser/TokenDoc.html +22 -2
- data/doc/TaskJuggler/TextReport.html +28 -8
- data/doc/TaskJuggler/TextScanner.html +400 -1404
- data/doc/TaskJuggler/TextScanner/BufferStreamHandle.html +28 -240
- data/doc/TaskJuggler/TextScanner/FileStreamHandle.html +37 -184
- data/doc/TaskJuggler/TextScanner/MacroStackEntry.html +682 -0
- data/doc/TaskJuggler/TextScanner/StreamHandle.html +342 -67
- data/doc/TaskJuggler/TimeSheet.html +48 -28
- data/doc/TaskJuggler/TimeSheetReceiver.html +24 -3
- data/doc/TaskJuggler/TimeSheetRecord.html +47 -27
- data/doc/TaskJuggler/TimeSheetReport.html +154 -133
- data/doc/TaskJuggler/TimeSheetSender.html +24 -3
- data/doc/TaskJuggler/TimeSheetSummary.html +137 -91
- data/doc/TaskJuggler/TimeSheets.html +26 -6
- data/doc/TaskJuggler/Tj3AppBase.html +85 -58
- data/doc/TaskJuggler/Tj3Client.html +292 -238
- data/doc/TaskJuggler/Tj3Daemon.html +159 -74
- data/doc/TaskJuggler/Tj3SheetAppBase.html +26 -6
- data/doc/TaskJuggler/Tj3SsReceiver.html +26 -6
- data/doc/TaskJuggler/Tj3SsSender.html +53 -26
- data/doc/TaskJuggler/Tj3TsReceiver.html +28 -7
- data/doc/TaskJuggler/Tj3TsSender.html +26 -6
- data/doc/TaskJuggler/Tj3TsSummary.html +26 -6
- data/doc/TaskJuggler/TjException.html +22 -2
- data/doc/TaskJuggler/TjTime.html +216 -160
- data/doc/TaskJuggler/TjpExample.html +34 -14
- data/doc/TaskJuggler/TjpExportRE.html +403 -407
- data/doc/TaskJuggler/TjpSyntaxRules.html +4805 -4408
- data/doc/TaskJuggler/URLParameter.html +649 -0
- data/doc/TaskJuggler/UserManual.html +42 -22
- data/doc/TaskJuggler/WebServer.html +702 -0
- data/doc/TaskJuggler/WorkingHours.html +38 -18
- data/doc/TaskJuggler/WorkingHoursAttribute.html +61 -41
- data/doc/TaskJuggler/XMLBlob.html +24 -4
- data/doc/TaskJuggler/XMLComment.html +24 -4
- data/doc/TaskJuggler/XMLDocument.html +30 -10
- data/doc/TaskJuggler/XMLElement.html +34 -14
- data/doc/TaskJuggler/XMLNamedText.html +22 -2
- data/doc/TaskJuggler/XMLText.html +24 -4
- data/doc/index.html +1841 -1666
- data/doc/lib/AccountScenario_rb.html +1 -1
- data/doc/lib/Account_rb.html +1 -1
- data/doc/lib/Allocation_rb.html +1 -1
- data/doc/lib/AppConfig_rb.html +2 -2
- data/doc/lib/AttributeBase_rb.html +1 -1
- data/doc/lib/AttributeDefinition_rb.html +1 -1
- data/doc/lib/Attributes_rb.html +2 -2
- data/doc/lib/BatchProcessor_rb.html +1 -1
- data/doc/lib/Booking_rb.html +1 -1
- data/doc/lib/ChargeSet_rb.html +1 -1
- data/doc/lib/Charge_rb.html +1 -1
- data/doc/lib/HTMLDocument_rb.html +1 -1
- data/doc/lib/Interval_rb.html +1 -1
- data/doc/lib/Journal_rb.html +2 -2
- data/doc/lib/KeywordArray_rb.html +1 -1
- data/doc/lib/KeywordDocumentation_rb.html +1 -1
- data/doc/lib/Limits_rb.html +2 -2
- data/doc/lib/LogFile_rb.html +2 -2
- data/doc/lib/Log_rb.html +1 -1
- data/doc/lib/LogicalExpression_rb.html +1 -1
- data/doc/lib/LogicalFunction_rb.html +2 -2
- data/doc/lib/LogicalOperation_rb.html +2 -2
- data/doc/lib/MacroParser_rb.html +1 -1
- data/doc/lib/MacroTable_rb.html +1 -1
- data/doc/lib/MessageHandler_rb.html +1 -1
- data/doc/lib/Message_rb.html +1 -1
- data/doc/lib/ProjectFileParser_rb.html +4 -8
- data/doc/lib/ProjectFileScanner_rb.html +67 -0
- data/doc/lib/Project_rb.html +2 -2
- data/doc/lib/PropertyList_rb.html +2 -2
- data/doc/lib/PropertySet_rb.html +2 -2
- data/doc/lib/PropertyTreeNode_rb.html +2 -2
- data/doc/lib/Query_rb.html +2 -2
- data/doc/lib/RTFHandlers_rb.html +73 -0
- data/doc/lib/RTFNavigator_rb.html +1 -1
- data/doc/lib/RTFQuery_rb.html +1 -1
- data/doc/lib/RTFReportLink_rb.html +71 -0
- data/doc/lib/RTFReport_rb.html +2 -2
- data/doc/lib/RealFormat_rb.html +1 -1
- data/doc/lib/ResourceScenario_rb.html +2 -2
- data/doc/lib/Resource_rb.html +2 -2
- data/doc/lib/RichTextDocument_rb.html +1 -1
- data/doc/lib/RichTextElement_rb.html +2 -2
- data/doc/lib/RichTextFunctionExample_rb.html +1 -1
- data/doc/lib/RichTextFunctionHandler_rb.html +1 -1
- data/doc/lib/RichTextParser_rb.html +2 -2
- data/doc/lib/RichTextScanner_rb.html +2 -2
- data/doc/lib/RichTextSnip_rb.html +1 -1
- data/doc/lib/RichTextSyntaxRules_rb.html +2 -2
- data/doc/lib/RichText_rb.html +1 -1
- data/doc/lib/RuntimeConfig_rb.html +1 -1
- data/doc/lib/ScenarioData_rb.html +2 -2
- data/doc/lib/Scenario_rb.html +1 -1
- data/doc/lib/Scoreboard_rb.html +1 -1
- data/doc/lib/SheetHandlerBase_rb.html +1 -1
- data/doc/lib/SheetReceiver_rb.html +2 -2
- data/doc/lib/SheetSender_rb.html +4 -2
- data/doc/lib/ShiftAssignments_rb.html +4 -2
- data/doc/lib/ShiftScenario_rb.html +1 -1
- data/doc/lib/Shift_rb.html +1 -1
- data/doc/lib/SourceFileInfo_rb.html +1 -1
- data/doc/lib/StatusSheetReceiver_rb.html +2 -2
- data/doc/lib/StatusSheetSender_rb.html +2 -2
- data/doc/lib/SyntaxReference_rb.html +1 -1
- data/doc/lib/TOCEntry_rb.html +1 -1
- data/doc/lib/TableColumnDefinition_rb.html +2 -2
- data/doc/lib/TableOfContents_rb.html +1 -1
- data/doc/lib/TaskDependency_rb.html +1 -1
- data/doc/lib/TaskJuggler_rb.html +2 -2
- data/doc/lib/TaskScenario_rb.html +2 -2
- data/doc/lib/Task_rb.html +2 -2
- data/doc/lib/TextFormatter_rb.html +1 -1
- data/doc/lib/TextParser/Pattern_rb.html +1 -1
- data/doc/lib/TextParser/Rule_rb.html +2 -2
- data/doc/lib/TextParser/StackElement_rb.html +2 -2
- data/doc/lib/TextParser/TokenDoc_rb.html +1 -1
- data/doc/lib/TextParser_rb.html +2 -2
- data/doc/lib/TextScanner_rb.html +6 -2
- data/doc/lib/TimeSheetReceiver_rb.html +2 -2
- data/doc/lib/TimeSheetSender_rb.html +2 -2
- data/doc/lib/TimeSheetSummary_rb.html +2 -2
- data/doc/lib/TimeSheets_rb.html +2 -2
- data/doc/lib/Tj3AppBase_rb.html +2 -2
- data/doc/lib/Tj3Config_rb.html +2 -2
- data/doc/lib/Tj3SheetAppBase_rb.html +2 -2
- data/doc/lib/TjException_rb.html +1 -1
- data/doc/lib/TjTime_rb.html +2 -2
- data/doc/lib/TjpExample_rb.html +1 -1
- data/doc/lib/TjpSyntaxRules_rb.html +2 -2
- data/doc/lib/URLParameter_rb.html +67 -0
- data/doc/lib/UTF8String_rb.html +1 -1
- data/doc/lib/UserManual_rb.html +1 -1
- data/doc/lib/WorkingHours_rb.html +1 -1
- data/doc/lib/XMLDocument_rb.html +2 -2
- data/doc/lib/XMLElement_rb.html +1 -1
- data/doc/lib/daemon/Daemon_rb.html +1 -1
- data/doc/lib/daemon/ProcessIntercom_rb.html +2 -2
- data/doc/lib/daemon/ProjectBroker_rb.html +4 -2
- data/doc/lib/daemon/ProjectServer_rb.html +2 -2
- data/doc/lib/daemon/ReportServer_rb.html +2 -2
- data/doc/lib/daemon/WebServer_rb.html +75 -0
- data/doc/lib/deep_copy_rb.html +2 -2
- data/doc/lib/reports/CSVFile_rb.html +2 -2
- data/doc/lib/reports/ColumnTable_rb.html +1 -1
- data/doc/lib/reports/GanttChart_rb.html +2 -2
- data/doc/lib/reports/GanttContainer_rb.html +1 -1
- data/doc/lib/reports/GanttHeaderScaleItem_rb.html +1 -1
- data/doc/lib/reports/GanttHeader_rb.html +1 -1
- data/doc/lib/reports/GanttLine_rb.html +1 -1
- data/doc/lib/reports/GanttLoadStack_rb.html +1 -1
- data/doc/lib/reports/GanttMilestone_rb.html +1 -1
- data/doc/lib/reports/GanttRouter_rb.html +1 -1
- data/doc/lib/reports/GanttTaskBar_rb.html +1 -1
- data/doc/lib/reports/HTMLGraphics_rb.html +1 -1
- data/doc/lib/reports/Navigator_rb.html +2 -2
- data/doc/lib/reports/NikuReport_rb.html +2 -2
- data/doc/lib/reports/ReportBase_rb.html +2 -2
- data/doc/lib/reports/ReportContext_rb.html +2 -2
- data/doc/lib/reports/ReportTableCell_rb.html +2 -2
- data/doc/lib/reports/ReportTableColumn_rb.html +1 -1
- data/doc/lib/reports/ReportTableLegend_rb.html +1 -1
- data/doc/lib/reports/ReportTableLine_rb.html +1 -1
- data/doc/lib/reports/ReportTable_rb.html +2 -2
- data/doc/lib/reports/Report_rb.html +2 -2
- data/doc/lib/reports/ResourceListRE_rb.html +2 -2
- data/doc/lib/reports/StatusSheetReport_rb.html +2 -2
- data/doc/lib/reports/TableReport_rb.html +2 -2
- data/doc/lib/reports/TaskListRE_rb.html +2 -2
- data/doc/lib/reports/TextReport_rb.html +1 -1
- data/doc/lib/reports/TimeSheetReport_rb.html +2 -2
- data/doc/lib/reports/TjpExportRE_rb.html +2 -2
- data/doc/lib/ruby-signal-bug_rb.html +1 -1
- data/doc/lib/taskjuggler3_rb.html +2 -2
- data/doc/lib/tj3client_rb.html +2 -2
- data/doc/lib/tj3d_rb.html +2 -2
- data/doc/lib/tj3man_rb.html +1 -1
- data/doc/lib/tj3ss_receiver_rb.html +1 -1
- data/doc/lib/tj3ss_sender_rb.html +2 -2
- data/doc/lib/tj3ts_receiver_rb.html +2 -2
- data/doc/lib/tj3ts_sender_rb.html +1 -1
- data/doc/lib/tj3ts_summary_rb.html +1 -1
- data/doc/rdoc.css +9 -4
- data/examples/tutorial.tjp +17 -15
- data/gem_spec.rb +3 -0
- data/lib/AppConfig.rb +3 -1
- data/lib/Attributes.rb +10 -8
- data/lib/Journal.rb +55 -20
- data/lib/Limits.rb +72 -46
- data/lib/LogFile.rb +3 -3
- data/lib/LogicalFunction.rb +19 -6
- data/lib/LogicalOperation.rb +5 -1
- data/lib/Project.rb +37 -9
- data/lib/ProjectFileParser.rb +25 -22
- data/lib/ProjectFileScanner.rb +365 -0
- data/lib/PropertyList.rb +2 -1
- data/lib/PropertySet.rb +14 -4
- data/lib/PropertyTreeNode.rb +42 -29
- data/lib/Query.rb +3 -1
- data/lib/RTFHandlers.rb +35 -0
- data/lib/RTFReport.rb +23 -6
- data/lib/RTFReportLink.rb +72 -0
- data/lib/Resource.rb +8 -16
- data/lib/ResourceScenario.rb +1 -22
- data/lib/RichTextElement.rb +42 -0
- data/lib/RichTextParser.rb +6 -4
- data/lib/RichTextScanner.rb +5 -5
- data/lib/RichTextSyntaxRules.rb +48 -10
- data/lib/ScenarioData.rb +5 -3
- data/lib/SheetReceiver.rb +24 -6
- data/lib/SheetSender.rb +17 -13
- data/lib/ShiftAssignments.rb +56 -52
- data/lib/StatusSheetReceiver.rb +1 -0
- data/lib/StatusSheetSender.rb +1 -0
- data/lib/TableColumnDefinition.rb +4 -2
- data/lib/Task.rb +8 -9
- data/lib/TaskJuggler.rb +21 -11
- data/lib/TaskScenario.rb +61 -26
- data/lib/TextParser.rb +268 -106
- data/lib/TextParser/Rule.rb +4 -2
- data/lib/TextParser/StackElement.rb +6 -4
- data/lib/TextScanner.rb +283 -700
- data/lib/TimeSheetReceiver.rb +1 -0
- data/lib/TimeSheetSender.rb +1 -0
- data/lib/TimeSheetSummary.rb +51 -26
- data/lib/TimeSheets.rb +1 -1
- data/lib/Tj3AppBase.rb +8 -1
- data/lib/Tj3Config.rb +1 -1
- data/lib/TjTime.rb +5 -0
- data/lib/TjpSyntaxRules.rb +360 -144
- data/lib/URLParameter.rb +30 -0
- data/lib/XMLDocument.rb +2 -2
- data/lib/daemon/ProcessIntercom.rb +50 -9
- data/lib/daemon/ProjectBroker.rb +63 -10
- data/lib/daemon/ProjectServer.rb +47 -16
- data/lib/daemon/ReportServer.rb +9 -4
- data/lib/daemon/WebServer.rb +204 -0
- data/lib/deep_copy.rb +4 -1
- data/lib/reports/CSVFile.rb +150 -66
- data/lib/reports/GanttChart.rb +2 -1
- data/lib/reports/Navigator.rb +18 -5
- data/lib/reports/NikuReport.rb +32 -2
- data/lib/reports/Report.rb +65 -37
- data/lib/reports/ReportBase.rb +14 -9
- data/lib/reports/ReportContext.rb +19 -4
- data/lib/reports/ReportTable.rb +2 -2
- data/lib/reports/ReportTableCell.rb +54 -30
- data/lib/reports/ResourceListRE.rb +4 -3
- data/lib/reports/StatusSheetReport.rb +8 -13
- data/lib/reports/TableReport.rb +47 -32
- data/lib/reports/TaskListRE.rb +3 -3
- data/lib/reports/TimeSheetReport.rb +14 -5
- data/lib/reports/TjpExportRE.rb +14 -19
- data/lib/taskjuggler3.rb +15 -0
- data/lib/tj3client.rb +9 -7
- data/lib/tj3d.rb +38 -10
- data/lib/tj3ss_sender.rb +7 -0
- data/lib/tj3ts_receiver.rb +1 -0
- data/manual/Day_To_Day_Juggling +1 -1
- data/manual/Rich_Text_Attributes +8 -0
- data/manual/TaskJuggler_2x_Migration +7 -0
- data/manual/The_TaskJuggler_Syntax +20 -6
- data/prj_cfg.rb +3 -2
- data/tasks/changelog.rake +36 -0
- data/tasks/csts.rake +2 -3
- data/tasks/gem.rake +10 -0
- data/tasks/missing.rake +0 -17
- data/test/TestSuite/ReportGenerator/Correct/Journal.html +63 -0
- data/test/TestSuite/ReportGenerator/Correct/Journal.tjp +14 -0
- data/test/TestSuite/{HTML-Reports/LogicalFunctions.tjp → ReportGenerator/Correct/LogicalFunctions1.tjp} +2 -2
- data/test/TestSuite/ReportGenerator/Correct/LogicalFunctions2.csv +3 -0
- data/test/TestSuite/ReportGenerator/Correct/LogicalFunctions2.tjp +19 -0
- data/test/TestSuite/ReportGenerator/Correct/css/tjmanual.css +66 -0
- data/test/TestSuite/ReportGenerator/Correct/css/tjreport.css +407 -0
- 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.csv +2 -0
- data/test/TestSuite/ReportGenerator/Correct/opennodes.tjp +26 -0
- data/test/TestSuite/ReportGenerator/Correct/refs/Journal-1.csv +6 -0
- data/test/TestSuite/ReportGenerator/Correct/refs/LogicalFunctions1-1.csv +7 -0
- data/test/TestSuite/ReportGenerator/Correct/refs/LogicalFunctions2-1.csv +2 -0
- data/test/TestSuite/ReportGenerator/Correct/refs/opennodes-1.csv +2 -0
- data/test/TestSuite/ReportGenerator/Correct/scripts/wz_tooltip.js +1301 -0
- data/test/TestSuite/ReportGenerator/Errors/rtp_report_recursion.tjp +20 -0
- data/test/TestSuite/Scheduler/Correct/Container.html +349 -0
- data/test/TestSuite/Scheduler/Correct/Limits.tjp +11 -4
- data/test/TestSuite/Scheduler/Correct/Shift2.html +464 -150
- data/test/TestSuite/Scheduler/Correct/TimeSheet2.html +108 -0
- data/test/TestSuite/Scheduler/Correct/TimeSheet2.tjp +7 -0
- data/test/TestSuite/Scheduler/Correct/css/tjmanual.css +14 -0
- data/test/TestSuite/Scheduler/Correct/css/tjreport.css +233 -21
- data/test/TestSuite/Scheduler/Correct/scripts/wz_tooltip.js +20 -20
- data/test/TestSuite/StatusSheetTemplates/project.tji +35 -0
- data/test/TestSuite/StatusSheetTemplates/project.tjp +56 -0
- data/test/TestSuite/StatusSheets/run +3 -2
- data/test/TestSuite/Syntax/Correct/Include.tjp +1 -1
- data/test/TestSuite/Syntax/Correct/Macro-1.tjp +1 -1
- data/test/TestSuite/Syntax/Correct/Macro-2.tjp +6 -0
- data/test/TestSuite/Syntax/Correct/Macro-3.tjp +14 -0
- data/test/TestSuite/Syntax/Correct/ResourcePrefix.html +32 -0
- data/test/TestSuite/Syntax/Correct/css/tjmanual.css +66 -0
- data/test/TestSuite/Syntax/Correct/css/tjreport.css +407 -0
- 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/include/dir1/file2.tji +3 -0
- data/test/TestSuite/Syntax/Correct/include/dir1/file5.tji +2 -0
- data/test/TestSuite/Syntax/Correct/include/dir3/all.tji +3 -0
- data/test/TestSuite/Syntax/Correct/include/dir3/file1.tji +2 -0
- data/test/TestSuite/Syntax/Correct/include/dir3/file2.tji +1 -0
- data/test/TestSuite/Syntax/Correct/scripts/wz_tooltip.js +1301 -0
- data/test/TestSuite/Syntax/Correct/tutorial.tjp +13 -13
- data/test/TestSuite/Syntax/Errors/empty.tjp +1 -1
- data/test/TestSuite/Syntax/Errors/include_recursion.tjp +1 -0
- data/test/TestSuite/Syntax/Errors/macro_stack_overflow.tjp +2 -1
- data/test/TestSuite/Syntax/Errors/{eof_in_istring1.tjp → no_token_match1.tjp} +2 -2
- data/test/TestSuite/Syntax/Errors/{eof_in_istring2.tjp → no_token_match2.tjp} +2 -2
- data/test/TestSuite/Syntax/Errors/{eof_in_istring3.tjp → no_token_match3.tjp} +1 -1
- data/test/TestSuite/Syntax/Errors/{eof_in_istring4.tjp → no_token_match4.tjp} +1 -1
- data/test/TestSuite/Syntax/Errors/{eof_in_istring5.tjp → no_token_match5.tjp} +1 -1
- data/test/TestSuite/Syntax/Errors/not_scheduled.tjp +13 -0
- data/test/TestSuite/Syntax/Errors/unsupported_token.tjp +1 -1
- data/test/TestSuite/TimeSheets/run +5 -5
- data/test/test_CSVFile.rb +75 -0
- data/test/test_Limits.rb +63 -5
- data/test/test_ProjectFileScanner.rb +163 -0
- data/test/test_ReportGenerator.rb +81 -0
- data/test/test_RichText.rb +21 -3
- data/test/test_Scheduler.rb +1 -1
- data/test/test_ShiftAssignments.rb +4 -4
- data/test/test_Syntax.rb +1 -1
- data/test/test_URLParameter.rb +30 -0
- metadata +126 -32
- data/test/TestSuite/Scheduler/Errors/not_scheduled.tjp +0 -8
- data/test/TestSuite/Syntax/Errors/bad_comment.tjp +0 -7
- data/test/TestSuite/TimeSheets/TimeSheetTemplates/2002-03-01/boss_2002-03-01.tji +0 -36
- data/test/TestSuite/TimeSheets/TimeSheetTemplates/2002-03-01/dev1_2002-03-01.tji +0 -48
- data/test/TestSuite/TimeSheets/TimeSheetTemplates/2002-03-01/dev2_2002-03-01.tji +0 -67
- data/test/TestSuite/TimeSheets/TimeSheetTemplates/2002-03-01/dev3_2002-03-01.tji +0 -67
- data/test/TestSuite/TimeSheets/TimeSheetTemplates/2002-03-01/doc_2002-03-01.tji +0 -48
- data/test/TestSuite/TimeSheets/TimeSheetTemplates/2002-03-01/resources.yml +0 -31
- data/test/TestSuite/TimeSheets/TimeSheetTemplates/2002-03-01/test_2002-03-01.tji +0 -36
- data/test/TestSuite/TimeSheets/TimeSheetTemplates/acceptable_intervals +0 -1
- data/test/TestSuite/TimeSheets/TimeSheets/2002-03-01/all.tji +0 -1
- data/test/TestSuite/TimeSheets/TimeSheets/2002-03-01/dev2_2002-03-01.tji +0 -54
- data/test/TestSuite/TimeSheets/TimeSheets/all.tji +0 -2
- data/test/TestSuite/TimeSheets/receiver.log +0 -102
- data/test/TestSuite/TimeSheets/sender.log +0 -794
- data/test/TestSuite/TimeSheets/summary.log +0 -884
- data/test/TestSuite/TimeSheets/timesheets.log +0 -45
- data/test/TestSuite/TimeSheets/tj3d.log +0 -292
- data/test/test_TextScanner.rb +0 -95
data/lib/TimeSheetReceiver.rb
CHANGED
|
@@ -34,6 +34,7 @@ class TaskJuggler
|
|
|
34
34
|
@sheetHeader = /^[ ]*timesheet\s([a-z][a-z0-9_]*)\s[0-9\-:+]*\s-\s([0-9]*-[0-9]*-[0-9]*)/
|
|
35
35
|
# Regular expression to extract the sheet signature (time period).
|
|
36
36
|
@signatureFilter = /^[ ]*timesheet\s[a-z][a-z0-9_]*\s([0-9:\-+]*\s-\s[0-9:\-+]*)/
|
|
37
|
+
@emailSubject = "Report from %s for %s"
|
|
37
38
|
end
|
|
38
39
|
|
|
39
40
|
end
|
data/lib/TimeSheetSender.rb
CHANGED
data/lib/TimeSheetSummary.rb
CHANGED
|
@@ -27,7 +27,7 @@ class TaskJuggler
|
|
|
27
27
|
super('tj3ts_summary', 'summary')
|
|
28
28
|
|
|
29
29
|
# This is a LogicalExpression string that controls what resources should
|
|
30
|
-
# not be
|
|
30
|
+
# not be considered in the summary.
|
|
31
31
|
@hideResource = '0'
|
|
32
32
|
# The base directory of the time sheet templates.
|
|
33
33
|
@templateDir = 'TimeSheetTemplates'
|
|
@@ -44,22 +44,23 @@ class TaskJuggler
|
|
|
44
44
|
@resourceIntro = " Weekly Report from %s\n\n"
|
|
45
45
|
@resourceSheetSubject = "Weekly report %s"
|
|
46
46
|
@summarySubject = "Weekly staff reports %s"
|
|
47
|
-
@reminderSubject = "Your
|
|
47
|
+
@reminderSubject = "Your time sheet for the period ending %s is overdue!"
|
|
48
48
|
@reminderText = <<'EOT'
|
|
49
|
-
The deadline for your
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
report.
|
|
49
|
+
The deadline for your time sheet submission has passed but we haven't received
|
|
50
|
+
it yet. Please submit your time sheet immediately so the content can still be
|
|
51
|
+
included in the management reports. Please send a copy of your submission
|
|
52
|
+
notification email to your manager. If possible, your manager will still try
|
|
53
|
+
to include your report data in his/her report.
|
|
55
54
|
|
|
56
|
-
Please be aware that post deadline submissions must be processed
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
Please be aware that post deadline submissions must be processed manually and
|
|
56
|
+
create an additional load for your manager and/or project manager. Please try
|
|
57
|
+
to submit in time in the future.
|
|
59
58
|
|
|
60
59
|
Thanks for your cooperation!
|
|
61
60
|
|
|
62
61
|
EOT
|
|
62
|
+
@defaulterHeader = "The following %d person(s) have not yet submitted " +
|
|
63
|
+
"their time sheets:\n\n"
|
|
63
64
|
end
|
|
64
65
|
|
|
65
66
|
def sendSummary(resourceIds)
|
|
@@ -77,37 +78,61 @@ EOT
|
|
|
77
78
|
sheetFile = "#{@sheetDir}/#{@date}/#{resourceId}_#{@date}.tji"
|
|
78
79
|
if File.exist?(templateFile)
|
|
79
80
|
if File.exists?(sheetFile)
|
|
80
|
-
#
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
81
|
+
# If there are no recipients specified, we don't need to compile
|
|
82
|
+
# the summary.
|
|
83
|
+
unless @digestRecipients.empty? && @sheetRecipients.empty?
|
|
84
|
+
# Resource has submitted a time sheet
|
|
85
|
+
sheet = getResourceJournal(sheetFile)
|
|
86
|
+
summary += sprintf(@resourceIntro, resourceName)
|
|
87
|
+
summary += sheet + "\n#{'-' * 74}\n\n"
|
|
88
|
+
info("Adding report from #{resourceName} to summary")
|
|
89
|
+
|
|
90
|
+
@sheetRecipients.each do |to|
|
|
91
|
+
sendEmail(to, sprintf(@resourceSheetSubject, @date), sheet,
|
|
92
|
+
nil, "#{resourceName} <#{resourceEmail}>")
|
|
93
|
+
end
|
|
89
94
|
end
|
|
90
95
|
else
|
|
91
96
|
defaulterList << resource
|
|
92
97
|
# Resource did not submit a time sheet
|
|
93
|
-
summary += "\n Report from #{resourceName} is missing\n\n"
|
|
94
98
|
info("Report from #{resourceId} is missing")
|
|
95
99
|
end
|
|
96
|
-
summary += "\n#{'-' * 74}\n\n"
|
|
97
100
|
end
|
|
98
101
|
end
|
|
99
102
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
unless defaulterList.empty?
|
|
104
|
+
# Prepend the defaulter list to the summary.
|
|
105
|
+
text = sprintf(@defaulterHeader, defaulterList.length)
|
|
103
106
|
defaulterList.each do |resource|
|
|
104
|
-
|
|
107
|
+
text += " * #{resource[1]}\n"
|
|
108
|
+
end
|
|
109
|
+
text += "\n#{'-' * 74}\n\n"
|
|
110
|
+
summary = text + summary
|
|
111
|
+
|
|
112
|
+
# Create a file with the IDs of the resources who's reports are
|
|
113
|
+
# missing.
|
|
114
|
+
missingFile = "#{@sheetDir}/#{@date}/missing-reports"
|
|
115
|
+
begin
|
|
116
|
+
File.open(missingFile, 'w') do |f|
|
|
117
|
+
defaulterList.each { |resource| f.puts resource[0] }
|
|
118
|
+
end
|
|
119
|
+
rescue
|
|
120
|
+
error("Cannot write file with missing reports (#missingFile): #{$!}")
|
|
105
121
|
end
|
|
106
122
|
end
|
|
107
123
|
|
|
124
|
+
# Send out the summary text to the list of digest recipients.
|
|
108
125
|
@digestRecipients.each do |to|
|
|
109
126
|
sendEmail(to, sprintf(@summarySubject, @date), summary)
|
|
110
127
|
end
|
|
128
|
+
|
|
129
|
+
# If there is a reminder text defined, resend the template to those
|
|
130
|
+
# individuals that have not yet submitted their report yet.
|
|
131
|
+
if @reminderText && !@reminderText.empty?
|
|
132
|
+
defaulterList.each do |resource|
|
|
133
|
+
sendReminder(resource[0], resource[1], resource[2])
|
|
134
|
+
end
|
|
135
|
+
end
|
|
111
136
|
end
|
|
112
137
|
|
|
113
138
|
private
|
data/lib/TimeSheets.rb
CHANGED
|
@@ -212,7 +212,7 @@ class TaskJuggler
|
|
|
212
212
|
resource = @timeSheet.resource
|
|
213
213
|
project = resource.project
|
|
214
214
|
scenarioIdx = @timeSheet.scenarioIdx
|
|
215
|
-
startIdx = project.dateToIdx(project['now'])
|
|
215
|
+
startIdx = project.dateToIdx(project['now'], true)
|
|
216
216
|
endIdx = project.dateToIdx(@task['end', scenarioIdx])
|
|
217
217
|
remainingWork = @task.getEffectiveWork(scenarioIdx, startIdx, endIdx,
|
|
218
218
|
resource)
|
data/lib/Tj3AppBase.rb
CHANGED
|
@@ -55,6 +55,9 @@ class TaskJuggler
|
|
|
55
55
|
format("Don't show program and progress information")) do
|
|
56
56
|
@silent = true
|
|
57
57
|
end
|
|
58
|
+
@opts.on('--debug', format('Enable Ruby debug mode')) do
|
|
59
|
+
$DEBUG = true
|
|
60
|
+
end
|
|
58
61
|
|
|
59
62
|
yield
|
|
60
63
|
|
|
@@ -81,13 +84,17 @@ class TaskJuggler
|
|
|
81
84
|
|
|
82
85
|
def main
|
|
83
86
|
# Install signal handler to exit gracefully on CTRL-C.
|
|
84
|
-
Kernel.trap('INT') do
|
|
87
|
+
intHandler = Kernel.trap('INT') do
|
|
85
88
|
puts "\nAborting on user request!"
|
|
86
89
|
exit 1
|
|
87
90
|
end
|
|
88
91
|
|
|
89
92
|
args = processArguments(ARGV)
|
|
90
93
|
|
|
94
|
+
# If DEBUG mode has been enabled, we restore the INT trap handler again
|
|
95
|
+
# to get Ruby backtrackes.
|
|
96
|
+
Kernel.trap('INT', intHandler) if $DEBUG
|
|
97
|
+
|
|
91
98
|
unless @silent
|
|
92
99
|
puts "#{AppConfig.softwareName} v#{AppConfig.version} - " +
|
|
93
100
|
"#{AppConfig.packageInfo}\n\n" +
|
data/lib/Tj3Config.rb
CHANGED
data/lib/TjTime.rb
CHANGED
data/lib/TjpSyntaxRules.rb
CHANGED
|
@@ -56,10 +56,11 @@ EOT
|
|
|
56
56
|
@property = @project.accout(@accountprefix)
|
|
57
57
|
end
|
|
58
58
|
if @val[1] && @project.account(@val[1])
|
|
59
|
-
error('account_exists', "Account #{@val[1]} has already been defined."
|
|
59
|
+
error('account_exists', "Account #{@val[1]} has already been defined.",
|
|
60
|
+
@property, @sourceFileInfo[1])
|
|
60
61
|
end
|
|
61
62
|
@property = Account.new(@project, @val[1], @val[2], @property)
|
|
62
|
-
@property.sourceFileInfo = @
|
|
63
|
+
@property.sourceFileInfo = @sourceFileInfo[0]
|
|
63
64
|
@property.inheritAttributes
|
|
64
65
|
@scenarioIdx = 0
|
|
65
66
|
})
|
|
@@ -73,7 +74,8 @@ EOT
|
|
|
73
74
|
# In case we have a nested supplement, we need to prepend the parent ID.
|
|
74
75
|
id = @property.fullId + '.' + id if @property && @property.is_a?(Account)
|
|
75
76
|
if (account = @project.account(id)).nil?
|
|
76
|
-
error('unknown_account', "Unknown account #{id}"
|
|
77
|
+
error('unknown_account', "Unknown account #{id}", nil,
|
|
78
|
+
@sourceFileInfo[0])
|
|
77
79
|
end
|
|
78
80
|
account
|
|
79
81
|
})
|
|
@@ -107,7 +109,7 @@ EOT
|
|
|
107
109
|
level = @project.alertLevelIndex(@val[0])
|
|
108
110
|
unless level
|
|
109
111
|
error('bad_alert', "Unknown alert level #{@val[1]}. Must be " +
|
|
110
|
-
'green, yellow or red')
|
|
112
|
+
'green, yellow or red', nil, @sourceFileInfo[0])
|
|
111
113
|
end
|
|
112
114
|
level
|
|
113
115
|
})
|
|
@@ -171,7 +173,7 @@ EOT
|
|
|
171
173
|
pattern(%w( !limits ), lambda {
|
|
172
174
|
limits = @property['limits', @scenarioIdx] = @val[0]
|
|
173
175
|
@allocate.candidates.each do |resource|
|
|
174
|
-
limits.limits.
|
|
176
|
+
limits.limits.each do |l|
|
|
175
177
|
l.resource = resource if resource.leaf?
|
|
176
178
|
end
|
|
177
179
|
end
|
|
@@ -257,7 +259,7 @@ EOT
|
|
|
257
259
|
# Make sure we have a ShiftAssignment for the allocation.
|
|
258
260
|
if @allocate.shift.nil?
|
|
259
261
|
@allocate.shift = ShiftAssignments.new
|
|
260
|
-
@allocate.shift.
|
|
262
|
+
@allocate.shift.project = @project
|
|
261
263
|
end
|
|
262
264
|
|
|
263
265
|
if @val[1].nil?
|
|
@@ -270,7 +272,7 @@ EOT
|
|
|
270
272
|
addAssignment(ShiftAssignment.new(@val[0].scenario(@scenarioIdx),
|
|
271
273
|
interval))
|
|
272
274
|
error('shift_assignment_overlap',
|
|
273
|
-
'Shifts may not overlap each other.')
|
|
275
|
+
'Shifts may not overlap each other.', nil, @sourceFileInfo[0])
|
|
274
276
|
end
|
|
275
277
|
end
|
|
276
278
|
})
|
|
@@ -313,16 +315,18 @@ EOT
|
|
|
313
315
|
pattern(%w( _balance !accountId !accountId ), lambda {
|
|
314
316
|
if @val[1].parent
|
|
315
317
|
error('cost_acct_no_top',
|
|
316
|
-
"The cost account #{@val[1].fullId} is not a top-level account."
|
|
318
|
+
"The cost account #{@val[1].fullId} is not a top-level account.",
|
|
319
|
+
nil, @sourceFileInfo[1])
|
|
317
320
|
end
|
|
318
321
|
if @val[2].parent
|
|
319
322
|
error('rev_acct_no_top',
|
|
320
323
|
"The revenue account #{@val[2].fullId} is not a top-level " +
|
|
321
|
-
"account.")
|
|
324
|
+
"account.", nil, @sourceFileInfo[2])
|
|
322
325
|
end
|
|
323
326
|
if @val[1] == @val[2]
|
|
324
327
|
error('cost_rev_same',
|
|
325
|
-
'The cost and revenue accounts may not be the same.'
|
|
328
|
+
'The cost and revenue accounts may not be the same.', nil,
|
|
329
|
+
@sourceFileInfo[1])
|
|
326
330
|
end
|
|
327
331
|
[ @val[1], @val[2] ]
|
|
328
332
|
})
|
|
@@ -347,7 +351,8 @@ EOT
|
|
|
347
351
|
pattern(%w( _overtime $INTEGER ), lambda {
|
|
348
352
|
if @val[1] < 0 || @val[1] > 2
|
|
349
353
|
error('overtime_range',
|
|
350
|
-
"Overtime value #{@val[1]} out of range (0 - 2).", @property
|
|
354
|
+
"Overtime value #{@val[1]} out of range (0 - 2).", @property,
|
|
355
|
+
@sourceFileInfo[1])
|
|
351
356
|
end
|
|
352
357
|
@booking.overtime = @val[1]
|
|
353
358
|
})
|
|
@@ -368,7 +373,8 @@ EOT
|
|
|
368
373
|
pattern(%w( _sloppy $INTEGER ), lambda {
|
|
369
374
|
if @val[1] < 0 || @val[1] > 2
|
|
370
375
|
error('sloppy_range',
|
|
371
|
-
"Sloppyness value #{@val[1]} out of range (0 - 2).", @property
|
|
376
|
+
"Sloppyness value #{@val[1]} out of range (0 - 2).", @property,
|
|
377
|
+
@sourceFileInfo[1])
|
|
372
378
|
end
|
|
373
379
|
@booking.sloppy = @val[1]
|
|
374
380
|
})
|
|
@@ -422,7 +428,7 @@ EOT
|
|
|
422
428
|
end
|
|
423
429
|
chargeSet.complete
|
|
424
430
|
rescue TjException
|
|
425
|
-
error('chargeset', $!.message)
|
|
431
|
+
error('chargeset', $!.message, @property, @sourceFileInfo[0])
|
|
426
432
|
end
|
|
427
433
|
masterAccounts = []
|
|
428
434
|
@property['chargeset', @scenarioIdx].each do |set|
|
|
@@ -431,7 +437,7 @@ EOT
|
|
|
431
437
|
if masterAccounts.include?(chargeSet.master)
|
|
432
438
|
error('chargeset_master',
|
|
433
439
|
"All charge sets for this task must have different top-level " +
|
|
434
|
-
"accounts.")
|
|
440
|
+
"accounts.", @property, @sourceFileInfo[0])
|
|
435
441
|
end
|
|
436
442
|
@property['chargeset', @scenarioIdx] =
|
|
437
443
|
@property['chargeset', @scenarioIdx] + [ chargeSet ]
|
|
@@ -499,7 +505,8 @@ EOT
|
|
|
499
505
|
col = @val[0]
|
|
500
506
|
unless /#[0-9A-Fa-f]{3}/ =~ col || /#[0-9A-Fa-f]{3}/ =~ col
|
|
501
507
|
error('bad_color',
|
|
502
|
-
"Color values must be specified as '#RGB' or '#RRGGBB' values"
|
|
508
|
+
"Color values must be specified as '#RGB' or '#RRGGBB' values",
|
|
509
|
+
nil, @sourceFileInfo[0])
|
|
503
510
|
end
|
|
504
511
|
col
|
|
505
512
|
})
|
|
@@ -586,6 +593,18 @@ Specifies an alternative font color for the cells of this column. The
|
|
|
586
593
|
logical expression specifies for which cells the color should be used. If
|
|
587
594
|
multiple fontcolor patterns are provided for a column, the first
|
|
588
595
|
matching one is used for each cell.
|
|
596
|
+
EOT
|
|
597
|
+
)
|
|
598
|
+
|
|
599
|
+
pattern(%w( _halign !logicalExpression !hAlignment ), lambda {
|
|
600
|
+
@column.hAlign.addPattern(
|
|
601
|
+
CellSettingPattern.new(@val[2], @val[1]))
|
|
602
|
+
})
|
|
603
|
+
doc('halign.column', <<'EOT'
|
|
604
|
+
Specifies the horizontal alignment of the cell content. The logical expression
|
|
605
|
+
specifies for which cells the alignment setting should be used. If multiple
|
|
606
|
+
halign patterns are provided for a column, the first matching one is used for
|
|
607
|
+
each cell.
|
|
589
608
|
EOT
|
|
590
609
|
)
|
|
591
610
|
|
|
@@ -666,7 +685,8 @@ EOT
|
|
|
666
685
|
if @val[0] % resolution != 0
|
|
667
686
|
error('misaligned_date',
|
|
668
687
|
"The date must be aligned to the timing resolution (" +
|
|
669
|
-
"#{resolution / 60} min) of the project."
|
|
688
|
+
"#{resolution / 60} min) of the project.", nil,
|
|
689
|
+
@sourceFileInfo[0])
|
|
670
690
|
end
|
|
671
691
|
@val[0]
|
|
672
692
|
})
|
|
@@ -712,11 +732,12 @@ EOT
|
|
|
712
732
|
|
|
713
733
|
rtTokenSetMore =
|
|
714
734
|
%w( LINEBREAK SPACE WORD BOLD ITALIC CODE BOLDITALIC PRE HREF HREFEND
|
|
715
|
-
REF REFEND HLINE TITLE2 TITLE3 TITLE2END TITLE3END
|
|
716
|
-
BULLET3 NUMBER1 NUMBER2 NUMBER3 )
|
|
735
|
+
REF REFEND HLINE TITLE2 TITLE3 TITLE4 TITLE2END TITLE3END TITLE4END
|
|
736
|
+
BULLET1 BULLET2 BULLET3 BULLET4 NUMBER1 NUMBER2 NUMBER3 NUMBER4 )
|
|
717
737
|
if @val[1] == "Some more details\n"
|
|
718
738
|
error('ts_default_details',
|
|
719
|
-
"'Some more details' is not a valid value"
|
|
739
|
+
"'Some more details' is not a valid value", nil,
|
|
740
|
+
@sourceFileInfo[1])
|
|
720
741
|
end
|
|
721
742
|
@journalEntry.details = newRichText(@val[1], rtTokenSetMore)
|
|
722
743
|
})
|
|
@@ -773,23 +794,19 @@ EOT
|
|
|
773
794
|
@property = nil
|
|
774
795
|
})
|
|
775
796
|
doc('export', <<'EOT'
|
|
776
|
-
The export report looks like a regular TaskJuggler file
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
If specified the resource usage for the tasks is reported as well. But only
|
|
786
|
-
those allocations are listed that belong to tasks listed in the same export
|
|
787
|
-
report.
|
|
797
|
+
The export report looks like a regular TaskJuggler file with the provided
|
|
798
|
+
input data complemented by the results of the scheduling process. The content
|
|
799
|
+
of the report can be controlled with the [[definitions]] attribute. In case
|
|
800
|
+
the file contains the project header, a ''''.tjp'''' extension is added to the
|
|
801
|
+
file name. Otherwise, a ''''.tji'''' extension is used.
|
|
802
|
+
|
|
803
|
+
The [[resourceattributes]] and [[taskattributes]] attributes provide even more
|
|
804
|
+
control over the content of the file.
|
|
788
805
|
|
|
789
806
|
The export report can be used to share certain tasks or milestones with other
|
|
790
807
|
projects or to save past resource allocations as immutable part for future
|
|
791
808
|
scheduling runs. When an export report is included the project IDs of the
|
|
792
|
-
included tasks must be declared first with the project id property
|
|
809
|
+
included tasks must be declared first with the project id property.
|
|
793
810
|
EOT
|
|
794
811
|
)
|
|
795
812
|
example('Export')
|
|
@@ -817,6 +834,8 @@ EOT
|
|
|
817
834
|
This attributes controls what definitions will be contained in the report. If
|
|
818
835
|
the list includes ''project'', the generated file will have a ''''.tjp''''
|
|
819
836
|
extension. Otherwise it will have a ''''.tji'''' extension.
|
|
837
|
+
|
|
838
|
+
By default, the report contains everything and the generated files has a ''''.tjp'''' extension.
|
|
820
839
|
EOT
|
|
821
840
|
)
|
|
822
841
|
allOrNothingListRule('exportDefinitions',
|
|
@@ -946,7 +965,8 @@ EOT
|
|
|
946
965
|
pattern(%w( $ID ), lambda {
|
|
947
966
|
unless (?A..?Z) === @val[0][0]
|
|
948
967
|
error('extend_id_cap',
|
|
949
|
-
"User defined attributes IDs must start with a capital letter"
|
|
968
|
+
"User defined attributes IDs must start with a capital letter",
|
|
969
|
+
nil, @sourceFileInfo[0])
|
|
950
970
|
end
|
|
951
971
|
@val[0]
|
|
952
972
|
})
|
|
@@ -1005,7 +1025,7 @@ EOT
|
|
|
1005
1025
|
The fail attribute adds a logical expression to the property. The condition
|
|
1006
1026
|
described by the logical expression is checked after the scheduling and an
|
|
1007
1027
|
error is raised if the condition evaluates to true. This attribute is
|
|
1008
|
-
primarily intended for testing
|
|
1028
|
+
primarily intended for testing purposes.
|
|
1009
1029
|
EOT
|
|
1010
1030
|
)
|
|
1011
1031
|
end
|
|
@@ -1013,7 +1033,8 @@ EOT
|
|
|
1013
1033
|
def rule_flag
|
|
1014
1034
|
pattern(%w( $ID ), lambda {
|
|
1015
1035
|
unless @project['flags'].include?(@val[0])
|
|
1016
|
-
error('undecl_flag', "Undeclared flag '#{@val[0]}'"
|
|
1036
|
+
error('undecl_flag', "Undeclared flag '#{@val[0]}'", nil,
|
|
1037
|
+
@sourceFileInfo[0])
|
|
1017
1038
|
end
|
|
1018
1039
|
@val[0]
|
|
1019
1040
|
})
|
|
@@ -1133,6 +1154,15 @@ EOT
|
|
|
1133
1154
|
arg(2, 'Resource ID', 'The ID of a defined resource')
|
|
1134
1155
|
arg(4, 'Scenario ID', 'A scenario ID')
|
|
1135
1156
|
|
|
1157
|
+
pattern(%w( _isfeatureof _( $ID _, $ID _) ))
|
|
1158
|
+
doc('isfeatureof', <<'EOT'
|
|
1159
|
+
If the provided task or any of its sub-tasks depend on this task or any of its
|
|
1160
|
+
sub-tasks, we call this task a feature of the provided task.
|
|
1161
|
+
EOT
|
|
1162
|
+
)
|
|
1163
|
+
arg(2, 'Task ID', 'The ID of a defined task')
|
|
1164
|
+
arg(4, 'Scenario ID', 'A scenario ID')
|
|
1165
|
+
|
|
1136
1166
|
pattern(['_isleaf', '_(', '_)' ])
|
|
1137
1167
|
doc('isleaf', 'The result is true if the property is not a container.')
|
|
1138
1168
|
|
|
@@ -1158,6 +1188,23 @@ EOT
|
|
|
1158
1188
|
)
|
|
1159
1189
|
end
|
|
1160
1190
|
|
|
1191
|
+
def rule_hAlignment
|
|
1192
|
+
pattern(%w( _center ), lambda {
|
|
1193
|
+
:center
|
|
1194
|
+
})
|
|
1195
|
+
doc('halign.center', 'Center the cell content')
|
|
1196
|
+
|
|
1197
|
+
pattern(%w( _left ), lambda {
|
|
1198
|
+
:left
|
|
1199
|
+
})
|
|
1200
|
+
doc('halign.left', 'Left align the cell content')
|
|
1201
|
+
|
|
1202
|
+
pattern(%w( _right ), lambda {
|
|
1203
|
+
:right
|
|
1204
|
+
})
|
|
1205
|
+
doc('halign.right', 'Right align the cell content')
|
|
1206
|
+
end
|
|
1207
|
+
|
|
1161
1208
|
def rule_headline
|
|
1162
1209
|
pattern(%w( _headline $STRING ), lambda {
|
|
1163
1210
|
@property.set('headline', newRichText(@val[1]))
|
|
@@ -1183,6 +1230,7 @@ report is sorted in tree mode (default) then enclosing resources are listed
|
|
|
1183
1230
|
even if the expression matches the resource.
|
|
1184
1231
|
EOT
|
|
1185
1232
|
)
|
|
1233
|
+
also(%w( sortresources ))
|
|
1186
1234
|
end
|
|
1187
1235
|
|
|
1188
1236
|
def rule_hidetask
|
|
@@ -1195,6 +1243,7 @@ report is sorted in tree mode (default) then enclosing tasks are listed even
|
|
|
1195
1243
|
if the expression matches the task.
|
|
1196
1244
|
EOT
|
|
1197
1245
|
)
|
|
1246
|
+
also(%w( sorttasks ))
|
|
1198
1247
|
end
|
|
1199
1248
|
|
|
1200
1249
|
def rule_idOrAbsoluteId
|
|
@@ -1256,7 +1305,7 @@ EOT
|
|
|
1256
1305
|
|
|
1257
1306
|
def rule_includeFile
|
|
1258
1307
|
pattern(%w( !includeFileName ), lambda {
|
|
1259
|
-
@scanner.include(@val[0])
|
|
1308
|
+
@scanner.include(@val[0], @sourceFileInfo[0])
|
|
1260
1309
|
})
|
|
1261
1310
|
end
|
|
1262
1311
|
|
|
@@ -1264,7 +1313,8 @@ EOT
|
|
|
1264
1313
|
pattern(%w( $STRING ), lambda {
|
|
1265
1314
|
unless @val[0][-4, 4] == '.tji'
|
|
1266
1315
|
error('bad_include_suffix', "Included files must have a '.tji'" +
|
|
1267
|
-
"extension: '#{@val[0]}'"
|
|
1316
|
+
"extension: '#{@val[0]}'",
|
|
1317
|
+
nil, @sourceFileInfo[0])
|
|
1268
1318
|
end
|
|
1269
1319
|
@val[0]
|
|
1270
1320
|
})
|
|
@@ -1279,7 +1329,7 @@ EOT
|
|
|
1279
1329
|
def rule_includeProperties
|
|
1280
1330
|
pattern(%w( !includeFileName !includeAttributes ), lambda {
|
|
1281
1331
|
pushFileStack
|
|
1282
|
-
@scanner.include(@val[0])
|
|
1332
|
+
@scanner.include(@val[0], @sourceFileInfo[0])
|
|
1283
1333
|
})
|
|
1284
1334
|
end
|
|
1285
1335
|
|
|
@@ -1291,7 +1341,7 @@ EOT
|
|
|
1291
1341
|
if mode == 0
|
|
1292
1342
|
unless @val[0] < endSpec
|
|
1293
1343
|
error('start_before_end', "The end date (#{endSpec}) must be " +
|
|
1294
|
-
"after the start date (#{@val[0]}).")
|
|
1344
|
+
"after the start date (#{@val[0]}).", nil, @sourceFileInfo[0])
|
|
1295
1345
|
end
|
|
1296
1346
|
Interval.new(@val[0], endSpec)
|
|
1297
1347
|
else
|
|
@@ -1322,7 +1372,7 @@ EOT
|
|
|
1322
1372
|
if mode == 0
|
|
1323
1373
|
unless @val[0] < endSpec
|
|
1324
1374
|
error('start_before_end', "The end date (#{endSpec}) must be after " +
|
|
1325
|
-
"the start date (#{@val[0]}).")
|
|
1375
|
+
"the start date (#{@val[0]}).", nil, @sourceFileInfo[0])
|
|
1326
1376
|
end
|
|
1327
1377
|
Interval.new(@val[0], endSpec)
|
|
1328
1378
|
else
|
|
@@ -1352,7 +1402,8 @@ EOT
|
|
|
1352
1402
|
60 * 60 * 24 * 365 # years
|
|
1353
1403
|
]
|
|
1354
1404
|
if @val[0] == 0.0
|
|
1355
|
-
error('zero_duration', "The interval duration may not be 0."
|
|
1405
|
+
error('zero_duration', "The interval duration may not be 0.", nil,
|
|
1406
|
+
@sourceFileInfo[1])
|
|
1356
1407
|
end
|
|
1357
1408
|
duration = @val[0] * convFactors[@val[1]]
|
|
1358
1409
|
resolution = @project.nil? ? 60 * 60 : @project['scheduleGranularity']
|
|
@@ -1363,7 +1414,7 @@ EOT
|
|
|
1363
1414
|
end
|
|
1364
1415
|
|
|
1365
1416
|
def rule_intervalEnd
|
|
1366
|
-
pattern([ '_
|
|
1417
|
+
pattern([ '_-', '!date' ], lambda {
|
|
1367
1418
|
[ 0, @val[1] ]
|
|
1368
1419
|
})
|
|
1369
1420
|
|
|
@@ -1374,7 +1425,7 @@ EOT
|
|
|
1374
1425
|
|
|
1375
1426
|
def rule_intervalOptionalEnd
|
|
1376
1427
|
optional
|
|
1377
|
-
pattern([ '_
|
|
1428
|
+
pattern([ '_-', '!date' ], lambda {
|
|
1378
1429
|
[ 0, @val[1] ]
|
|
1379
1430
|
})
|
|
1380
1431
|
|
|
@@ -1421,7 +1472,7 @@ EOT
|
|
|
1421
1472
|
level = @project.alertLevelIndex(@val[1])
|
|
1422
1473
|
unless level
|
|
1423
1474
|
error('bad_alert', "Unknown alert level #{@val[1]}. Must be " +
|
|
1424
|
-
'green, yellow or red')
|
|
1475
|
+
'green, yellow or red', nil, @sourceFileInfo[0])
|
|
1425
1476
|
end
|
|
1426
1477
|
@journalEntry.alertLevel = level
|
|
1427
1478
|
})
|
|
@@ -1451,7 +1502,7 @@ EOT
|
|
|
1451
1502
|
def rule_journalEntryHeader
|
|
1452
1503
|
pattern(%w( _journalentry !valDate $STRING ), lambda {
|
|
1453
1504
|
@journalEntry = JournalEntry.new(@project['journal'], @val[1], @val[2],
|
|
1454
|
-
@property, @
|
|
1505
|
+
@property, @sourceFileInfo[0])
|
|
1455
1506
|
})
|
|
1456
1507
|
arg(2, 'headline', <<'EOT'
|
|
1457
1508
|
The headline of the journal entry. It will be interpreted as
|
|
@@ -1464,7 +1515,7 @@ EOT
|
|
|
1464
1515
|
resource = @val[0]
|
|
1465
1516
|
unless resource.leaf?
|
|
1466
1517
|
error('leaf_resource_id_expected',
|
|
1467
|
-
"#{resource.id} is not a leaf resource.")
|
|
1518
|
+
"#{resource.id} is not a leaf resource.", nil, @sourceFileInfo[0])
|
|
1468
1519
|
end
|
|
1469
1520
|
resource
|
|
1470
1521
|
})
|
|
@@ -1711,7 +1762,7 @@ EOT
|
|
|
1711
1762
|
if @scanner.macroDefined?(@val[1])
|
|
1712
1763
|
warning('marco_redefinition', "Redefining macro #{@val[1]}")
|
|
1713
1764
|
end
|
|
1714
|
-
@scanner.addMacro(Macro.new(@val[1], @val[2], @
|
|
1765
|
+
@scanner.addMacro(Macro.new(@val[1], @val[2], @sourceFileInfo[0]))
|
|
1715
1766
|
})
|
|
1716
1767
|
doc('macro', <<'EOT'
|
|
1717
1768
|
Defines a text fragment that can later be inserted by using the specified ID.
|
|
@@ -1730,14 +1781,17 @@ numbers as names. The number specifies the index of the argument.
|
|
|
1730
1781
|
macro FOO [ This ${1} text ]
|
|
1731
1782
|
|
|
1732
1783
|
will expand to ''''This stupid text'''' if called as ''''${FOO "stupid"}''''.
|
|
1733
|
-
Macros may call other macros.
|
|
1784
|
+
Macros may call other macros. All macro arguments must be enclosed by double
|
|
1785
|
+
quotes. In case the argument contains a double quote, it must be escaped by a
|
|
1786
|
+
slash (''''/'''').
|
|
1734
1787
|
|
|
1735
1788
|
User defined macro IDs must have at least one uppercase letter as all
|
|
1736
1789
|
lowercase letter IDs are reserved for built-in macros.
|
|
1737
1790
|
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
''''<nowiki>
|
|
1791
|
+
To terminate the macro definition, the ''''<nowiki>]</nowiki>'''' must be the
|
|
1792
|
+
last character in the line. If there are any other characters trailing it
|
|
1793
|
+
(even spaces or comments) the ''''<nowiki>]</nowiki>'''' will not be
|
|
1794
|
+
considered the end of the macro definition.
|
|
1741
1795
|
|
|
1742
1796
|
In macro calls the macro names can be prefixed by a question mark. In this
|
|
1743
1797
|
case the macro will expand to nothing if the macro is not defined. Otherwise
|
|
@@ -1840,7 +1894,8 @@ EOT
|
|
|
1840
1894
|
pattern(%w( _navigator $ID ), lambda {
|
|
1841
1895
|
if @project['navigators'][@val[1]]
|
|
1842
1896
|
error('navigator_exists',
|
|
1843
|
-
"The navigator #{@val[1]} has already been defined."
|
|
1897
|
+
"The navigator #{@val[1]} has already been defined.", nil,
|
|
1898
|
+
@sourceFileInfo[0])
|
|
1844
1899
|
end
|
|
1845
1900
|
@navigator = Navigator.new(@val[1], @project)
|
|
1846
1901
|
})
|
|
@@ -1893,6 +1948,49 @@ EOT
|
|
|
1893
1948
|
example('Niku')
|
|
1894
1949
|
end
|
|
1895
1950
|
|
|
1951
|
+
def rule_nodeId
|
|
1952
|
+
pattern(%w( !idOrAbsoluteId !subNodeId ), lambda {
|
|
1953
|
+
case @property.typeSpec
|
|
1954
|
+
when :taskreport
|
|
1955
|
+
if (p1 = @project.task(@val[0])).nil?
|
|
1956
|
+
error('unknown_main_node',
|
|
1957
|
+
"Unknown task ID #{@val[0]}", nil, @sourceFileInfo[0])
|
|
1958
|
+
end
|
|
1959
|
+
if @val[1]
|
|
1960
|
+
if (p2 = @project.resource(@val[1])).nil?
|
|
1961
|
+
error('unknown_sub_node',
|
|
1962
|
+
"Unknown resource ID #{@val[0]}", nil, @sourceFileInfo[0])
|
|
1963
|
+
end
|
|
1964
|
+
return [ p2, p1 ]
|
|
1965
|
+
end
|
|
1966
|
+
return [ p1, nil ]
|
|
1967
|
+
when :resourcereport
|
|
1968
|
+
if (p1 = @project.task(@val[0])).nil?
|
|
1969
|
+
error('unknown_main_node',
|
|
1970
|
+
"Unknown task ID #{@val[0]}", nil, @sourceFileInfo[0])
|
|
1971
|
+
end
|
|
1972
|
+
if @val[1]
|
|
1973
|
+
if (p2 = @project.resource(@val[1])).nil?
|
|
1974
|
+
error('unknown_sub_node',
|
|
1975
|
+
"Unknown resource ID #{@val[0]}", nil, @sourceFileInfo[0])
|
|
1976
|
+
end
|
|
1977
|
+
return [ p2, p1 ]
|
|
1978
|
+
end
|
|
1979
|
+
return [ p1, nil ]
|
|
1980
|
+
end
|
|
1981
|
+
|
|
1982
|
+
raise "Node list is not supported for this report type: " +
|
|
1983
|
+
"#{@property.typeSpec}"
|
|
1984
|
+
})
|
|
1985
|
+
end
|
|
1986
|
+
|
|
1987
|
+
def rule_nodeIdList
|
|
1988
|
+
listRule('moreNodeIdList', '!nodeId')
|
|
1989
|
+
pattern([ '_-' ], lambda {
|
|
1990
|
+
[]
|
|
1991
|
+
})
|
|
1992
|
+
end
|
|
1993
|
+
|
|
1896
1994
|
def rule_number
|
|
1897
1995
|
singlePattern('$INTEGER')
|
|
1898
1996
|
singlePattern('$FLOAT')
|
|
@@ -1911,12 +2009,13 @@ EOT
|
|
|
1911
2009
|
pattern(%w( $ABSOLUTE_ID ), lambda {
|
|
1912
2010
|
if @val[0].count('.') > 1
|
|
1913
2011
|
error('operand_attribute',
|
|
1914
|
-
'Attributes must be specified as <scenarioID>.<attribute>'
|
|
2012
|
+
'Attributes must be specified as <scenarioID>.<attribute>', nil,
|
|
2013
|
+
@sourceFileInfo[0])
|
|
1915
2014
|
end
|
|
1916
2015
|
scenario, attribute = @val[0].split('.')
|
|
1917
2016
|
if (scenarioIdx = @project.scenarioIdx(scenario)).nil?
|
|
1918
|
-
error('operand_unkn_scen',
|
|
1919
|
-
|
|
2017
|
+
error('operand_unkn_scen', "Unknown scenario ID #{scenario}", nil,
|
|
2018
|
+
@sourceFileInfo[0])
|
|
1920
2019
|
end
|
|
1921
2020
|
LogicalAttribute.new(attribute, scenarioIdx)
|
|
1922
2021
|
})
|
|
@@ -1926,7 +2025,8 @@ EOT
|
|
|
1926
2025
|
pattern(%w( $ID !argumentList ), lambda {
|
|
1927
2026
|
if @val[1].nil?
|
|
1928
2027
|
unless @project['flags'].include?(@val[0])
|
|
1929
|
-
error('operand_unkn_flag', "Undeclared flag '#{@val[0]}'"
|
|
2028
|
+
error('operand_unkn_flag', "Undeclared flag '#{@val[0]}'",
|
|
2029
|
+
nil, @sourceFileInfo[0])
|
|
1930
2030
|
end
|
|
1931
2031
|
LogicalFlag.new(@val[0])
|
|
1932
2032
|
else
|
|
@@ -1966,10 +2066,10 @@ EOT
|
|
|
1966
2066
|
arg(0, 'operand', <<'EOT'
|
|
1967
2067
|
An operand can consist of a date, a text string, a [[functions|function]], a
|
|
1968
2068
|
property attribute or a numerical value. It can also be the name of a declared
|
|
1969
|
-
flag. Use the
|
|
1970
|
-
evaluated property. The scenario ID always has to be specified, also
|
|
1971
|
-
non-scenario specific attributes. This is necessary to distinguish them
|
|
1972
|
-
flags.
|
|
2069
|
+
flag. Use the ''''scenario_id.attribute'''' notation to use an attribute of the
|
|
2070
|
+
currently evaluated property. The scenario ID always has to be specified, also
|
|
2071
|
+
for non-scenario specific attributes. This is necessary to distinguish them
|
|
2072
|
+
from flags.
|
|
1973
2073
|
|
|
1974
2074
|
An operand can be a negated operand by prefixing a ~ charater or it can be
|
|
1975
2075
|
another logical expression enclosed in braces.
|
|
@@ -2087,11 +2187,11 @@ EOT
|
|
|
2087
2187
|
|
|
2088
2188
|
def rule_plusOrMinus
|
|
2089
2189
|
singlePattern('_+')
|
|
2090
|
-
singlePattern('_
|
|
2190
|
+
singlePattern('_-')
|
|
2091
2191
|
end
|
|
2092
2192
|
|
|
2093
2193
|
def rule_project
|
|
2094
|
-
pattern(%w( !projectProlog !projectDeclaration !properties ), lambda {
|
|
2194
|
+
pattern(%w( !projectProlog !projectDeclaration !properties . ), lambda {
|
|
2095
2195
|
@val[1]
|
|
2096
2196
|
})
|
|
2097
2197
|
end
|
|
@@ -2132,8 +2232,9 @@ EOT
|
|
|
2132
2232
|
Set the average number of working hours per day. This is used as
|
|
2133
2233
|
the base to convert working hours into working days. This affects
|
|
2134
2234
|
for example the length task attribute. The default value is 8 hours
|
|
2135
|
-
and should work for most Western countries. The value you specify
|
|
2136
|
-
|
|
2235
|
+
and should work for most Western countries. The value you specify should match
|
|
2236
|
+
the settings you specified as your default [[workinghours.project|working
|
|
2237
|
+
hours]].
|
|
2137
2238
|
EOT
|
|
2138
2239
|
)
|
|
2139
2240
|
example('Project')
|
|
@@ -2161,9 +2262,9 @@ EOT
|
|
|
2161
2262
|
pattern(%w( _now !date ), lambda {
|
|
2162
2263
|
@project['now'] = @val[1]
|
|
2163
2264
|
@scanner.addMacro(Macro.new('now', @val[1].to_s,
|
|
2164
|
-
@
|
|
2265
|
+
@sourceFileInfo[0]))
|
|
2165
2266
|
@scanner.addMacro(Macro.new('today', @val[1].to_s(@project['timeFormat']),
|
|
2166
|
-
@
|
|
2267
|
+
@sourceFileInfo[0]))
|
|
2167
2268
|
})
|
|
2168
2269
|
doc('now', <<'EOT'
|
|
2169
2270
|
Specify the date that TaskJuggler uses for calculation as current
|
|
@@ -2208,12 +2309,14 @@ EOT
|
|
|
2208
2309
|
goodValues = [ 5, 10, 15, 20, 30, 60 ]
|
|
2209
2310
|
unless goodValues.include?(@val[1])
|
|
2210
2311
|
error('bad_timing_res',
|
|
2211
|
-
"Timing resolution must be one of #{goodValues.join(', ')} min."
|
|
2312
|
+
"Timing resolution must be one of #{goodValues.join(', ')} min.",
|
|
2313
|
+
nil, @sourceFileInfo[1])
|
|
2212
2314
|
end
|
|
2213
2315
|
if @val[1] > (Project.maxScheduleGranularity / 60)
|
|
2214
2316
|
error('too_large_timing_res',
|
|
2215
2317
|
'The maximum allowed timing resolution for the timezone is ' +
|
|
2216
|
-
"#{Project.maxScheduleGranularity / 60} minutes."
|
|
2318
|
+
"#{Project.maxScheduleGranularity / 60} minutes.", nil,
|
|
2319
|
+
@sourceFileInfo[1])
|
|
2217
2320
|
end
|
|
2218
2321
|
@project['scheduleGranularity'] = @val[1] * 60
|
|
2219
2322
|
})
|
|
@@ -2283,6 +2386,7 @@ EOT
|
|
|
2283
2386
|
@messageHandler)
|
|
2284
2387
|
@project['start'] = @val[4].start
|
|
2285
2388
|
@project['end'] = @val[4].end
|
|
2389
|
+
@projectId = @val[1]
|
|
2286
2390
|
setGlobalMacros
|
|
2287
2391
|
@property = nil
|
|
2288
2392
|
@reportCounter = 0
|
|
@@ -2381,10 +2485,12 @@ EOT
|
|
|
2381
2485
|
|
|
2382
2486
|
def rule_properties
|
|
2383
2487
|
pattern(%w( !propertiesBody . ))
|
|
2488
|
+
lastSyntaxToken(1)
|
|
2384
2489
|
end
|
|
2385
2490
|
|
|
2386
2491
|
def rule_propertiesBody
|
|
2387
2492
|
repeatable
|
|
2493
|
+
optional
|
|
2388
2494
|
|
|
2389
2495
|
pattern(%w( !account ))
|
|
2390
2496
|
|
|
@@ -2435,7 +2541,7 @@ EOT
|
|
|
2435
2541
|
pattern(%w( _projectid $ID ), lambda {
|
|
2436
2542
|
@project['projectids'] << @val[1]
|
|
2437
2543
|
@project['projectids'].uniq!
|
|
2438
|
-
@project['projectid'] = @val[1]
|
|
2544
|
+
@project['projectid'] = @projectId = @val[1]
|
|
2439
2545
|
})
|
|
2440
2546
|
doc('projectid', <<'EOT'
|
|
2441
2547
|
This declares a new project id and activates it. All subsequent
|
|
@@ -2511,7 +2617,6 @@ EOT
|
|
|
2511
2617
|
pattern(%w( _include !includeProperties !properties ), lambda {
|
|
2512
2618
|
popFileStack
|
|
2513
2619
|
})
|
|
2514
|
-
lastSyntaxToken(1)
|
|
2515
2620
|
doc('include.properties', <<'EOT'
|
|
2516
2621
|
Includes the specified file name as if its contents would be written
|
|
2517
2622
|
instead of the include property. The only exception is the include
|
|
@@ -2532,7 +2637,8 @@ EOT
|
|
|
2532
2637
|
pattern(%w( _purge $ID ), lambda {
|
|
2533
2638
|
if (attributeDefinition = @property.attributeDefinition(@val[1])).nil?
|
|
2534
2639
|
error('purge_unknown_id',
|
|
2535
|
-
"#{@val[1]} is not a known attribute for this property"
|
|
2640
|
+
"#{@val[1]} is not a known attribute for this property", nil,
|
|
2641
|
+
@sourceFileInfo[1])
|
|
2536
2642
|
end
|
|
2537
2643
|
if attributeDefinition.scenarioSpecific
|
|
2538
2644
|
attr = @property[@val[1], 0]
|
|
@@ -2541,7 +2647,8 @@ EOT
|
|
|
2541
2647
|
end
|
|
2542
2648
|
unless attr.is_a?(Array)
|
|
2543
2649
|
error('purge_no_list',
|
|
2544
|
-
"#{@val[1]} is not a list attribute. Only those can be purged."
|
|
2650
|
+
"#{@val[1]} is not a list attribute. Only those can be purged.",
|
|
2651
|
+
nil, @sourceFileInfo[1])
|
|
2545
2652
|
end
|
|
2546
2653
|
if attributeDefinition.scenarioSpecific
|
|
2547
2654
|
@property[@val[1], @scenarioIdx] = attributeDefinition.default.dup
|
|
@@ -2620,17 +2727,19 @@ properties.
|
|
|
2620
2727
|
EOT
|
|
2621
2728
|
)
|
|
2622
2729
|
|
|
2623
|
-
singlePattern('
|
|
2730
|
+
singlePattern('_alertmessages')
|
|
2624
2731
|
descr(<<'EOT'
|
|
2625
2732
|
The headlines, the summary and the details of the message from the journal
|
|
2626
|
-
entries that caused the current alert level
|
|
2733
|
+
entries that caused the current alert level to be larger than the defaul level
|
|
2734
|
+
for this task or any of its sub tasks.
|
|
2627
2735
|
EOT
|
|
2628
2736
|
)
|
|
2629
2737
|
|
|
2630
|
-
singlePattern('
|
|
2738
|
+
singlePattern('_alertsummaries')
|
|
2631
2739
|
descr(<<'EOT'
|
|
2632
2740
|
The headlines and the summary message from the journal entries that caused the
|
|
2633
|
-
current alert level for this task
|
|
2741
|
+
current alert level to be larger than the default for this task or any of its
|
|
2742
|
+
sub tasks.
|
|
2634
2743
|
EOT
|
|
2635
2744
|
)
|
|
2636
2745
|
|
|
@@ -2754,6 +2863,20 @@ EOT
|
|
|
2754
2863
|
singlePattern('_journal')
|
|
2755
2864
|
descr(<<'EOT'
|
|
2756
2865
|
The journal entries for the task or resource for the reported interval.
|
|
2866
|
+
EOT
|
|
2867
|
+
)
|
|
2868
|
+
|
|
2869
|
+
singlePattern('_journalmessages')
|
|
2870
|
+
descr(<<'EOT'
|
|
2871
|
+
The headlines, the summary and the details of the message from the journal
|
|
2872
|
+
entries that caused the current alert level for this task.
|
|
2873
|
+
EOT
|
|
2874
|
+
)
|
|
2875
|
+
|
|
2876
|
+
singlePattern('_journalsummaries')
|
|
2877
|
+
descr(<<'EOT'
|
|
2878
|
+
The headlines and the summary message from the journal entries that caused the
|
|
2879
|
+
current alert level for this task.
|
|
2757
2880
|
EOT
|
|
2758
2881
|
)
|
|
2759
2882
|
|
|
@@ -2788,7 +2911,7 @@ EOT
|
|
|
2788
2911
|
descr('The criticalness of the task with respect to all the paths that ' +
|
|
2789
2912
|
'it is a part of.')
|
|
2790
2913
|
|
|
2791
|
-
singlePattern('
|
|
2914
|
+
singlePattern('_precursors')
|
|
2792
2915
|
descr(<<EOT
|
|
2793
2916
|
A list of tasks the current task depends on. The list contains the names, the
|
|
2794
2917
|
IDs, the date and the type of dependency. For the type the following symbols
|
|
@@ -2979,6 +3102,11 @@ EOT
|
|
|
2979
3102
|
)
|
|
2980
3103
|
also(%w( epilog footer header ))
|
|
2981
3104
|
|
|
3105
|
+
pattern(%w( _opennodes !nodeIdList ), lambda {
|
|
3106
|
+
@property.set('openNodes', @val[1])
|
|
3107
|
+
})
|
|
3108
|
+
doc('opennods', 'For internal use only!')
|
|
3109
|
+
|
|
2982
3110
|
pattern(%w( !report ))
|
|
2983
3111
|
|
|
2984
3112
|
pattern(%w( _right $STRING ), lambda {
|
|
@@ -3046,7 +3174,8 @@ EOT
|
|
|
3046
3174
|
pattern(%w( _end !date ), lambda {
|
|
3047
3175
|
if @val[1] < @property.get('start')
|
|
3048
3176
|
error('report_end',
|
|
3049
|
-
"End date must be before start date #{@property.get('start')}"
|
|
3177
|
+
"End date must be before start date #{@property.get('start')}",
|
|
3178
|
+
nil, @sourceFileInfo[1])
|
|
3050
3179
|
end
|
|
3051
3180
|
@property.set('end', @val[1])
|
|
3052
3181
|
})
|
|
@@ -3067,7 +3196,8 @@ EOT
|
|
|
3067
3196
|
end
|
|
3068
3197
|
# In case we have a nested supplement, we need to prepend the parent ID.
|
|
3069
3198
|
if (report = @project.report(id)).nil?
|
|
3070
|
-
error('report_id_expected', "#{id} is not a defined report."
|
|
3199
|
+
error('report_id_expected', "#{id} is not a defined report.", nil,
|
|
3200
|
+
@sourceFileInfo[0])
|
|
3071
3201
|
end
|
|
3072
3202
|
report
|
|
3073
3203
|
})
|
|
@@ -3095,7 +3225,8 @@ EOT
|
|
|
3095
3225
|
pattern(%w( _start !date ), lambda {
|
|
3096
3226
|
if @val[1] > @property.get('end')
|
|
3097
3227
|
error('report_start',
|
|
3098
|
-
"Start date must be before end date #{@property.get('end')}"
|
|
3228
|
+
"Start date must be before end date #{@property.get('end')}",
|
|
3229
|
+
nil, @sourceFileInfo[1])
|
|
3099
3230
|
end
|
|
3100
3231
|
@property.set('start', @val[1])
|
|
3101
3232
|
})
|
|
@@ -3118,11 +3249,12 @@ EOT
|
|
|
3118
3249
|
if @val[1]
|
|
3119
3250
|
id = (@property ? @property.fullId + '.' : '') + @val[1]
|
|
3120
3251
|
if @project.report(id)
|
|
3121
|
-
error('report_exists', "report #{id} has already been defined."
|
|
3252
|
+
error('report_exists', "report #{id} has already been defined.",
|
|
3253
|
+
@property, @sourceFileInfo[1])
|
|
3122
3254
|
end
|
|
3123
3255
|
end
|
|
3124
3256
|
@property = Report.new(@project, @val[1], @val[2], @property)
|
|
3125
|
-
@property.sourceFileInfo = @
|
|
3257
|
+
@property.sourceFileInfo = @sourceFileInfo[0]
|
|
3126
3258
|
@property.inheritAttributes
|
|
3127
3259
|
case @val[0]
|
|
3128
3260
|
when 'taskreport'
|
|
@@ -3303,7 +3435,7 @@ EOT
|
|
|
3303
3435
|
pattern(%w( !taskId !valIntervals ), lambda {
|
|
3304
3436
|
checkBooking(@val[0], @property)
|
|
3305
3437
|
@booking = Booking.new(@property, @val[0], @val[1])
|
|
3306
|
-
@booking.sourceFileInfo = @
|
|
3438
|
+
@booking.sourceFileInfo = @sourceFileInfo[0]
|
|
3307
3439
|
@booking
|
|
3308
3440
|
})
|
|
3309
3441
|
arg(0, 'id', 'Absolute ID of a defined task')
|
|
@@ -3313,7 +3445,8 @@ EOT
|
|
|
3313
3445
|
pattern(%w( $ID ), lambda {
|
|
3314
3446
|
id = (@resourceprefix.empty? ? '' : @resourceprefix + '.') + @val[0]
|
|
3315
3447
|
if (resource = @project.resource(id)).nil?
|
|
3316
|
-
error('resource_id_expected', "#{id} is not a defined resource."
|
|
3448
|
+
error('resource_id_expected', "#{id} is not a defined resource.",
|
|
3449
|
+
nil, @sourceFileInfo[0])
|
|
3317
3450
|
end
|
|
3318
3451
|
resource
|
|
3319
3452
|
})
|
|
@@ -3326,10 +3459,12 @@ EOT
|
|
|
3326
3459
|
@property = @project.resource(@resourceprefix)
|
|
3327
3460
|
end
|
|
3328
3461
|
if @val[1] && @project.resource(@val[1])
|
|
3329
|
-
error('resource_exists',
|
|
3462
|
+
error('resource_exists',
|
|
3463
|
+
"Resource #{@val[1]} has already been defined.", @property,
|
|
3464
|
+
@sourceFileInfo[1])
|
|
3330
3465
|
end
|
|
3331
3466
|
@property = Resource.new(@project, @val[1], @val[2], @property)
|
|
3332
|
-
@property.sourceFileInfo = @
|
|
3467
|
+
@property.sourceFileInfo = @sourceFileInfo[0]
|
|
3333
3468
|
@property.inheritAttributes
|
|
3334
3469
|
@scenarioIdx = 0
|
|
3335
3470
|
})
|
|
@@ -3443,8 +3578,8 @@ EOT
|
|
|
3443
3578
|
doc('shifts.resource', <<'EOT'
|
|
3444
3579
|
Limits the working time of a resource to a defined shift during the specified
|
|
3445
3580
|
interval. Multiple shifts can be defined, but shift intervals may not overlap.
|
|
3446
|
-
|
|
3447
|
-
hours
|
|
3581
|
+
In case a shift is defined for a certain interval, the shift working hours
|
|
3582
|
+
replace the standard resource working hours for this interval.
|
|
3448
3583
|
EOT
|
|
3449
3584
|
)
|
|
3450
3585
|
|
|
@@ -3555,7 +3690,9 @@ EOT
|
|
|
3555
3690
|
# first.
|
|
3556
3691
|
@project.scenarios.clearProperties if @property.nil?
|
|
3557
3692
|
if @project.scenario(@val[1])
|
|
3558
|
-
error('scenario_exists',
|
|
3693
|
+
error('scenario_exists',
|
|
3694
|
+
"Scenario #{@val[1]} has already been defined.", nil,
|
|
3695
|
+
@sourceFileInfo[1])
|
|
3559
3696
|
end
|
|
3560
3697
|
@property = Scenario.new(@project, @val[1], @val[2], @property)
|
|
3561
3698
|
@property.inheritAttributes
|
|
@@ -3567,7 +3704,8 @@ EOT
|
|
|
3567
3704
|
def rule_scenarioId
|
|
3568
3705
|
pattern(%w( $ID ), lambda {
|
|
3569
3706
|
if (@scenarioIdx = @project.scenarioIdx(@val[0])).nil?
|
|
3570
|
-
error('unknown_scenario_id', "Unknown scenario: #{@val[0]}"
|
|
3707
|
+
error('unknown_scenario_id', "Unknown scenario: #{@val[0]}", nil,
|
|
3708
|
+
@sourceFileInfo[0])
|
|
3571
3709
|
end
|
|
3572
3710
|
@scenarioIdx
|
|
3573
3711
|
})
|
|
@@ -3577,7 +3715,8 @@ EOT
|
|
|
3577
3715
|
def rule_scenarioIdCol
|
|
3578
3716
|
pattern(%w( $ID_WITH_COLON ), lambda {
|
|
3579
3717
|
if (@scenarioIdx = @project.scenarioIdx(@val[0])).nil?
|
|
3580
|
-
error('unknown_scenario_id', "Unknown scenario: @val[0]"
|
|
3718
|
+
error('unknown_scenario_id', "Unknown scenario: @val[0]", nil,
|
|
3719
|
+
@sourceFileInfo[0])
|
|
3581
3720
|
end
|
|
3582
3721
|
})
|
|
3583
3722
|
end
|
|
@@ -3589,7 +3728,8 @@ EOT
|
|
|
3589
3728
|
def rule_scenarioIdx
|
|
3590
3729
|
pattern(%w( $ID ), lambda {
|
|
3591
3730
|
if (scenarioIdx = @project.scenarioIdx(@val[0])).nil?
|
|
3592
|
-
error('unknown_scenario_idx', "Unknown scenario #{@val[0]}"
|
|
3731
|
+
error('unknown_scenario_idx', "Unknown scenario #{@val[0]}", nil,
|
|
3732
|
+
@sourceFileInfo[0])
|
|
3593
3733
|
end
|
|
3594
3734
|
scenarioIdx
|
|
3595
3735
|
})
|
|
@@ -3613,6 +3753,7 @@ Shifts have a global name space. All IDs must be unique within the shifts of
|
|
|
3613
3753
|
the project.
|
|
3614
3754
|
EOT
|
|
3615
3755
|
)
|
|
3756
|
+
also(%w( shifts.task shifts.resource ))
|
|
3616
3757
|
end
|
|
3617
3758
|
|
|
3618
3759
|
def rule_shiftAssignment
|
|
@@ -3620,7 +3761,7 @@ EOT
|
|
|
3620
3761
|
# Make sure we have a ShiftAssignment for the property.
|
|
3621
3762
|
if @property['shifts', @scenarioIdx].nil?
|
|
3622
3763
|
@property['shifts', @scenarioIdx] = ShiftAssignments.new
|
|
3623
|
-
@property['shifts', @scenarioIdx].
|
|
3764
|
+
@property['shifts', @scenarioIdx].project = @project
|
|
3624
3765
|
end
|
|
3625
3766
|
|
|
3626
3767
|
if @val[1].nil?
|
|
@@ -3633,7 +3774,8 @@ EOT
|
|
|
3633
3774
|
addAssignment(ShiftAssignment.new(@val[0].scenario(@scenarioIdx),
|
|
3634
3775
|
interval))
|
|
3635
3776
|
error('shift_assignment_overlap',
|
|
3636
|
-
'Shifts may not overlap each other.'
|
|
3777
|
+
'Shifts may not overlap each other.', @property,
|
|
3778
|
+
@sourceFileInfo[0])
|
|
3637
3779
|
end
|
|
3638
3780
|
end
|
|
3639
3781
|
# Set same value again to set the 'provided' state for the attribute.
|
|
@@ -3663,10 +3805,11 @@ EOT
|
|
|
3663
3805
|
def rule_shiftHeader
|
|
3664
3806
|
pattern(%w( _shift !optionalID $STRING ), lambda {
|
|
3665
3807
|
if @val[1] && @project.shift(@val[1])
|
|
3666
|
-
error('shift_exists', "Shift #{@val[1]} has already been defined."
|
|
3808
|
+
error('shift_exists', "Shift #{@val[1]} has already been defined.",
|
|
3809
|
+
nil, @sourceFileInfo[1])
|
|
3667
3810
|
end
|
|
3668
3811
|
@property = Shift.new(@project, @val[1], @val[2], @property)
|
|
3669
|
-
@property.sourceFileInfo = @
|
|
3812
|
+
@property.sourceFileInfo = @sourceFileInfo[0]
|
|
3670
3813
|
@property.inheritAttributes
|
|
3671
3814
|
@scenarioIdx = 0
|
|
3672
3815
|
})
|
|
@@ -3676,7 +3819,8 @@ EOT
|
|
|
3676
3819
|
def rule_shiftId
|
|
3677
3820
|
pattern(%w( $ID ), lambda {
|
|
3678
3821
|
if (shift = @project.shift(@val[0])).nil?
|
|
3679
|
-
error('shift_id_expected', "#{@val[0]} is not a defined shift."
|
|
3822
|
+
error('shift_id_expected', "#{@val[0]} is not a defined shift.", nil,
|
|
3823
|
+
@sourceFileInfo[0])
|
|
3680
3824
|
end
|
|
3681
3825
|
shift
|
|
3682
3826
|
})
|
|
@@ -3746,33 +3890,38 @@ EOT
|
|
|
3746
3890
|
args = @val[0].split('.')
|
|
3747
3891
|
case args.length
|
|
3748
3892
|
when 2
|
|
3893
|
+
# <attribute>.<up|down>
|
|
3749
3894
|
scenario = -1
|
|
3750
3895
|
direction = args[1] == 'up'
|
|
3751
3896
|
attribute = args[0]
|
|
3752
3897
|
when 3
|
|
3898
|
+
# <scenario>.<attribute>.<up|down>
|
|
3753
3899
|
if (scenario = @project.scenarioIdx(args[0])).nil?
|
|
3754
3900
|
error('sort_unknown_scen',
|
|
3755
|
-
"Unknown scenario #{args[0]} in sorting criterium"
|
|
3901
|
+
"Unknown scenario #{args[0]} in sorting criterium", nil,
|
|
3902
|
+
@sourceFileInfo[0])
|
|
3756
3903
|
end
|
|
3757
3904
|
attribute = args[1]
|
|
3758
3905
|
if args[2] != 'up' && args[2] != 'down'
|
|
3759
|
-
error('sort_direction', "Sorting direction must be 'up' or 'down'"
|
|
3906
|
+
error('sort_direction', "Sorting direction must be 'up' or 'down'",
|
|
3907
|
+
nil, @sourceFileInfo[0])
|
|
3760
3908
|
end
|
|
3761
3909
|
direction = args[2] == 'up'
|
|
3762
3910
|
else
|
|
3763
3911
|
error('sorting_crit_exptd1',
|
|
3764
3912
|
"Sorting criterium expected (e.g. tree, start.up or " +
|
|
3765
|
-
"plan.end.down).")
|
|
3913
|
+
"plan.end.down).", nil, @sourceFileInfo[0])
|
|
3766
3914
|
end
|
|
3767
3915
|
if attribute == 'wbs'
|
|
3768
3916
|
error('sorting_wbs',
|
|
3769
3917
|
"Sorting by wbs is not supported. Please use 'tree' " +
|
|
3770
|
-
'(without appended .up or .down) instead.'
|
|
3918
|
+
'(without appended .up or .down) instead.', nil,
|
|
3919
|
+
@sourceFileInfo[0])
|
|
3771
3920
|
end
|
|
3772
3921
|
[ attribute, direction, scenario ]
|
|
3773
3922
|
})
|
|
3774
3923
|
arg(0, 'criteria', <<'EOT'
|
|
3775
|
-
The
|
|
3924
|
+
The sorting criteria must consist of a property attribute ID. See [[columnid]]
|
|
3776
3925
|
for a complete list of available attributes. The ID must be suffixed by '.up'
|
|
3777
3926
|
or '.down' to determine the sorting direction. Optionally the ID may be
|
|
3778
3927
|
prefixed with a scenario ID and a dot to determine the scenario that should be
|
|
@@ -3812,7 +3961,7 @@ EOT
|
|
|
3812
3961
|
if @val[0] != 'tree'
|
|
3813
3962
|
error('sorting_crit_exptd2',
|
|
3814
3963
|
"Sorting criterium expected (e.g. tree, start.up or " +
|
|
3815
|
-
"plan.end.down).")
|
|
3964
|
+
"plan.end.down).", nil, @sourceFileInfo[0])
|
|
3816
3965
|
end
|
|
3817
3966
|
[ 'tree', true, -1 ]
|
|
3818
3967
|
})
|
|
@@ -3825,7 +3974,7 @@ EOT
|
|
|
3825
3974
|
if @project.reports[fileName]
|
|
3826
3975
|
error('report_redefinition',
|
|
3827
3976
|
"A report with the name '#{fileName}' has already been " +
|
|
3828
|
-
"defined.")
|
|
3977
|
+
"defined.", nil, @sourceFileInfo[2])
|
|
3829
3978
|
end
|
|
3830
3979
|
else
|
|
3831
3980
|
fileName = "statusSheet#{@project.reports.length + 1}"
|
|
@@ -3883,7 +4032,7 @@ EOT
|
|
|
3883
4032
|
pattern(%w( _status !alertLevel $STRING ), lambda {
|
|
3884
4033
|
@journalEntry = JournalEntry.new(@project['journal'], @sheetEnd,
|
|
3885
4034
|
@val[2], @property,
|
|
3886
|
-
@
|
|
4035
|
+
@sourceFileInfo[0])
|
|
3887
4036
|
@journalEntry.alertLevel = @val[1]
|
|
3888
4037
|
@journalEntry.author = @sheetAuthor
|
|
3889
4038
|
|
|
@@ -3924,6 +4073,14 @@ EOT
|
|
|
3924
4073
|
optionsRule('statusSheetAttributes')
|
|
3925
4074
|
end
|
|
3926
4075
|
|
|
4076
|
+
def rule_statusSheetFile
|
|
4077
|
+
pattern(%w( !statusSheet . ), lambda {
|
|
4078
|
+
@val[0]
|
|
4079
|
+
})
|
|
4080
|
+
lastSyntaxToken(1)
|
|
4081
|
+
end
|
|
4082
|
+
|
|
4083
|
+
|
|
3927
4084
|
def rule_statusSheetHeader
|
|
3928
4085
|
pattern(%w( _statussheet !resourceId !valIntervalOrDate ), lambda {
|
|
3929
4086
|
@sheetAuthor = @val[1]
|
|
@@ -3985,6 +4142,14 @@ EOT
|
|
|
3985
4142
|
@property = @val[1]
|
|
3986
4143
|
})
|
|
3987
4144
|
end
|
|
4145
|
+
|
|
4146
|
+
def rule_subNodeId
|
|
4147
|
+
optional
|
|
4148
|
+
pattern(%w( _: !idOrAbsoluteId ), lambda {
|
|
4149
|
+
@val[1]
|
|
4150
|
+
})
|
|
4151
|
+
end
|
|
4152
|
+
|
|
3988
4153
|
def rule_summary
|
|
3989
4154
|
pattern(%w( _summary $STRING ), lambda {
|
|
3990
4155
|
return if @val[1].empty?
|
|
@@ -3992,11 +4157,13 @@ EOT
|
|
|
3992
4157
|
if @val[1].length > 480
|
|
3993
4158
|
error('ts_summary_too_long',
|
|
3994
4159
|
"The summary text must be 480 characters long or shorter. " +
|
|
3995
|
-
"This text has #{@val[1].length} characters."
|
|
4160
|
+
"This text has #{@val[1].length} characters.",
|
|
4161
|
+
nil, @sourceFileInfo[1])
|
|
3996
4162
|
end
|
|
3997
4163
|
if @val[1] == "A summary text\n"
|
|
3998
4164
|
error('ts_default_summary',
|
|
3999
|
-
"'A summary text' is not a valid summary"
|
|
4165
|
+
"'A summary text' is not a valid summary", nil,
|
|
4166
|
+
@sourceFileInfo[1])
|
|
4000
4167
|
end
|
|
4001
4168
|
rtTokenSetIntro =
|
|
4002
4169
|
%w( LINEBREAK SPACE WORD BOLD ITALIC CODE BOLDITALIC HREF HREFEND )
|
|
@@ -4130,7 +4297,7 @@ EOT
|
|
|
4130
4297
|
pattern(%w( !resourceId !valIntervals ), lambda {
|
|
4131
4298
|
checkBooking(@property, @val[0])
|
|
4132
4299
|
@booking = Booking.new(@val[0], @property, @val[1])
|
|
4133
|
-
@booking.sourceFileInfo = @
|
|
4300
|
+
@booking.sourceFileInfo = @sourceFileInfo[0]
|
|
4134
4301
|
@booking
|
|
4135
4302
|
})
|
|
4136
4303
|
end
|
|
@@ -4215,7 +4382,7 @@ EOT
|
|
|
4215
4382
|
end
|
|
4216
4383
|
error('too_many_bangs',
|
|
4217
4384
|
"Too many '!' for relative task in this context.",
|
|
4218
|
-
@property) if id[0] == ?!
|
|
4385
|
+
@property, @sourceFileInfo[0]) if id[0] == ?!
|
|
4219
4386
|
if task
|
|
4220
4387
|
task.fullId + '.' + id
|
|
4221
4388
|
else
|
|
@@ -4245,11 +4412,13 @@ EOT
|
|
|
4245
4412
|
if @val[1]
|
|
4246
4413
|
id = (@property ? @property.fullId + '.' : '') + @val[1]
|
|
4247
4414
|
if @project.task(id)
|
|
4248
|
-
error('task_exists', "Task #{id} has already been defined."
|
|
4415
|
+
error('task_exists', "Task #{id} has already been defined.", nil,
|
|
4416
|
+
@sourceFileInfo[1])
|
|
4249
4417
|
end
|
|
4250
4418
|
end
|
|
4251
4419
|
@property = Task.new(@project, @val[1], @val[2], @property)
|
|
4252
|
-
@property
|
|
4420
|
+
@property['projectid', 0] = @projectId
|
|
4421
|
+
@property.sourceFileInfo = @sourceFileInfo[0]
|
|
4253
4422
|
@property.inheritAttributes
|
|
4254
4423
|
@scenarioIdx = 0
|
|
4255
4424
|
})
|
|
@@ -4266,7 +4435,7 @@ EOT
|
|
|
4266
4435
|
id = @taskprefix + '.' + id unless @taskprefix.empty?
|
|
4267
4436
|
end
|
|
4268
4437
|
if (task = @project.task(id)).nil?
|
|
4269
|
-
error('unknown_task', "Unknown task #{id}")
|
|
4438
|
+
error('unknown_task', "Unknown task #{id}", nil, @sourceFileInfo[0])
|
|
4270
4439
|
end
|
|
4271
4440
|
task
|
|
4272
4441
|
})
|
|
@@ -4331,7 +4500,8 @@ EOT
|
|
|
4331
4500
|
|
|
4332
4501
|
if @property['chargeset', @scenarioIdx].empty?
|
|
4333
4502
|
error('task_without_chargeset',
|
|
4334
|
-
'The task does not have a chargeset defined.'
|
|
4503
|
+
'The task does not have a chargeset defined.', @property,
|
|
4504
|
+
@sourceFileInfo[0])
|
|
4335
4505
|
end
|
|
4336
4506
|
case @val[2]
|
|
4337
4507
|
when 'onstart'
|
|
@@ -4368,7 +4538,7 @@ EOT
|
|
|
4368
4538
|
pattern(%w( _complete !number), lambda {
|
|
4369
4539
|
if @val[1] < 0.0 || @val[1] > 100.0
|
|
4370
4540
|
error('task_complete', "Complete value must be between 0 and 100",
|
|
4371
|
-
@property)
|
|
4541
|
+
@property, @sourceFileInfo[1])
|
|
4372
4542
|
end
|
|
4373
4543
|
@property['complete', @scenarioIdx] = @val[1]
|
|
4374
4544
|
})
|
|
@@ -4418,7 +4588,8 @@ EOT
|
|
|
4418
4588
|
pattern(%w( _effort !workingDuration ), lambda {
|
|
4419
4589
|
checkContainer('effort')
|
|
4420
4590
|
if @val[1] <= 0.0
|
|
4421
|
-
error('effort_zero', "Effort value must be larger than 0", @property
|
|
4591
|
+
error('effort_zero', "Effort value must be larger than 0", @property,
|
|
4592
|
+
@sourceFileInfo[1])
|
|
4422
4593
|
end
|
|
4423
4594
|
@property['effort', @scenarioIdx] = @val[1]
|
|
4424
4595
|
})
|
|
@@ -4595,7 +4766,7 @@ EOT
|
|
|
4595
4766
|
pattern(%w( _priority $INTEGER ), lambda {
|
|
4596
4767
|
if @val[1] < 0 || @val[1] > 1000
|
|
4597
4768
|
error('task_priority', "Priority must have a value between 0 and 1000",
|
|
4598
|
-
@property)
|
|
4769
|
+
@property, @sourceFileInfo[1])
|
|
4599
4770
|
end
|
|
4600
4771
|
@property['priority', @scenarioIdx] = @val[1]
|
|
4601
4772
|
})
|
|
@@ -4620,7 +4791,8 @@ EOT
|
|
|
4620
4791
|
|
|
4621
4792
|
pattern(%w( _projectid $ID ), lambda {
|
|
4622
4793
|
unless @project['projectids'].include?(@val[1])
|
|
4623
|
-
error('unknown_projectid', "Unknown project ID #{@val[1]}"
|
|
4794
|
+
error('unknown_projectid', "Unknown project ID #{@val[1]}", nil,
|
|
4795
|
+
@sourceFileInfo[1])
|
|
4624
4796
|
end
|
|
4625
4797
|
@property['projectid', @scenarioIdx] = @val[1]
|
|
4626
4798
|
})
|
|
@@ -4642,6 +4814,17 @@ EOT
|
|
|
4642
4814
|
)
|
|
4643
4815
|
|
|
4644
4816
|
pattern(%w( _scheduled ), lambda {
|
|
4817
|
+
if (@property['milestone', @scenarioIdx] &&
|
|
4818
|
+
@property['start', @scenarioIdx].nil? &&
|
|
4819
|
+
@property['end', @scenarioIdx].nil?) ||
|
|
4820
|
+
(!@property['milestone', @scenarioIdx] &&
|
|
4821
|
+
(@property['start', @scenarioIdx].nil? ||
|
|
4822
|
+
@property['end', @scenarioIdx].nil?))
|
|
4823
|
+
error('not_scheduled',
|
|
4824
|
+
"Task #{@property.fullId} is marked as scheduled but does not " +
|
|
4825
|
+
'have a fixed start and end date.', @property,
|
|
4826
|
+
@sourceFileInfo[0])
|
|
4827
|
+
end
|
|
4645
4828
|
@property['scheduled', @scenarioIdx] = true
|
|
4646
4829
|
})
|
|
4647
4830
|
doc('scheduled', <<'EOT'
|
|
@@ -4875,10 +5058,11 @@ EOT
|
|
|
4875
5058
|
end
|
|
4876
5059
|
|
|
4877
5060
|
def rule_timeInterval
|
|
4878
|
-
pattern([ '$TIME', '_
|
|
5061
|
+
pattern([ '$TIME', '_-', '$TIME' ], lambda {
|
|
4879
5062
|
if @val[0] >= @val[2]
|
|
4880
5063
|
error('time_interval',
|
|
4881
|
-
"End time of interval must be larger than start time"
|
|
5064
|
+
"End time of interval must be larger than start time", nil,
|
|
5065
|
+
@sourceFileInfo[0])
|
|
4882
5066
|
end
|
|
4883
5067
|
[ @val[0], @val[2] ]
|
|
4884
5068
|
})
|
|
@@ -4931,7 +5115,10 @@ EOT
|
|
|
4931
5115
|
optional
|
|
4932
5116
|
repeatable
|
|
4933
5117
|
|
|
4934
|
-
pattern(%w( !tsNewTaskHeader !tsTaskBody )
|
|
5118
|
+
pattern(%w( !tsNewTaskHeader !tsTaskBody ), lambda {
|
|
5119
|
+
@property = nil
|
|
5120
|
+
@timeSheetRecord = nil
|
|
5121
|
+
})
|
|
4935
5122
|
doc('newtask', <<'EOT'
|
|
4936
5123
|
The keyword can be used add a new task to the project. If the task ID requires
|
|
4937
5124
|
further parent task that don't exist yet, these tasks will be created as well.
|
|
@@ -4942,7 +5129,7 @@ EOT
|
|
|
4942
5129
|
example('TimeSheet1', '3')
|
|
4943
5130
|
|
|
4944
5131
|
pattern(%w( _shift !shiftId ), lambda {
|
|
4945
|
-
|
|
5132
|
+
#TODO
|
|
4946
5133
|
})
|
|
4947
5134
|
doc('shift.timesheet', <<'EOT'
|
|
4948
5135
|
Specifies an alternative [[shift]] for the time sheet period. This shift will
|
|
@@ -4968,6 +5155,13 @@ EOT
|
|
|
4968
5155
|
example('TimeSheet1', '4')
|
|
4969
5156
|
end
|
|
4970
5157
|
|
|
5158
|
+
def rule_timeSheetFile
|
|
5159
|
+
pattern(%w( !timeSheet . ), lambda {
|
|
5160
|
+
@val[0]
|
|
5161
|
+
})
|
|
5162
|
+
lastSyntaxToken(1)
|
|
5163
|
+
end
|
|
5164
|
+
|
|
4971
5165
|
def rule_timeSheetBody
|
|
4972
5166
|
pattern(%w( _{ !timeSheetAttributes _} ), lambda {
|
|
4973
5167
|
|
|
@@ -4976,16 +5170,17 @@ EOT
|
|
|
4976
5170
|
|
|
4977
5171
|
def rule_timeSheetHeader
|
|
4978
5172
|
pattern(%w( _timesheet !resourceId !valIntervalOrDate ), lambda {
|
|
4979
|
-
sheetAuthor = @val[1]
|
|
5173
|
+
@sheetAuthor = @val[1]
|
|
4980
5174
|
@property = nil
|
|
4981
|
-
unless sheetAuthor.leaf?
|
|
5175
|
+
unless @sheetAuthor.leaf?
|
|
4982
5176
|
error('ts_group_author',
|
|
4983
|
-
'A resource group cannot file a time sheet'
|
|
5177
|
+
'A resource group cannot file a time sheet', nil,
|
|
5178
|
+
@sourceFileInfo[1])
|
|
4984
5179
|
end
|
|
4985
5180
|
# Currently time sheets are hardcoded for scenario 0.
|
|
4986
|
-
@timeSheet = TimeSheet.new(sheetAuthor, @val[2],
|
|
5181
|
+
@timeSheet = TimeSheet.new(@sheetAuthor, @val[2],
|
|
4987
5182
|
@project['trackingScenarioIdx'])
|
|
4988
|
-
@timeSheet.sourceFileInfo = @
|
|
5183
|
+
@timeSheet.sourceFileInfo = @sourceFileInfo[0]
|
|
4989
5184
|
@project.timeSheets << @timeSheet
|
|
4990
5185
|
})
|
|
4991
5186
|
end
|
|
@@ -5039,7 +5234,7 @@ EOT
|
|
|
5039
5234
|
pattern(%w( _newtask !taskIdUnverifd $STRING ), lambda {
|
|
5040
5235
|
@timeSheetRecord = TimeSheetRecord.new(@timeSheet, @val[1])
|
|
5041
5236
|
@timeSheetRecord.name = @val[2]
|
|
5042
|
-
@timeSheetRecord.sourceFileInfo = @
|
|
5237
|
+
@timeSheetRecord.sourceFileInfo = @sourceFileInfo[0]
|
|
5043
5238
|
})
|
|
5044
5239
|
arg(1, 'task', 'ID of the new task')
|
|
5045
5240
|
end
|
|
@@ -5095,20 +5290,21 @@ EOT
|
|
|
5095
5290
|
if @val[2].length > 120
|
|
5096
5291
|
error('ts_headline_too_long',
|
|
5097
5292
|
"The headline must be 120 or less characters long. This one " +
|
|
5098
|
-
"has #{@val[2].length} characters.")
|
|
5293
|
+
"has #{@val[2].length} characters.", nil, @sourceFileInfo[2])
|
|
5099
5294
|
end
|
|
5100
5295
|
if @val[2] == 'Your headline here!'
|
|
5101
5296
|
error('ts_no_headline',
|
|
5102
|
-
"'Your headline here!' is not a valid headline"
|
|
5297
|
+
"'Your headline here!' is not a valid headline", nil,
|
|
5298
|
+
@sourceFileInfo[2])
|
|
5103
5299
|
end
|
|
5104
5300
|
@journalEntry = JournalEntry.new(@project['journal'],
|
|
5105
5301
|
@timeSheet.interval.end,
|
|
5106
5302
|
@val[2],
|
|
5107
5303
|
@property || @timeSheet.resource,
|
|
5108
|
-
@
|
|
5304
|
+
@sourceFileInfo[0])
|
|
5109
5305
|
@journalEntry.alertLevel = @val[1]
|
|
5110
5306
|
@journalEntry.timeSheetRecord = @timeSheetRecord
|
|
5111
|
-
@journalEntry.author = @
|
|
5307
|
+
@journalEntry.author = @sheetAuthor
|
|
5112
5308
|
@timeSheetRecord.status = @journalEntry if @timeSheetRecord
|
|
5113
5309
|
})
|
|
5114
5310
|
end
|
|
@@ -5135,7 +5331,7 @@ EOT
|
|
|
5135
5331
|
if @val[1] < @timeSheet.interval.start
|
|
5136
5332
|
error('ts_end_too_early',
|
|
5137
5333
|
"The expected task end date must be after the start date of " +
|
|
5138
|
-
"this time sheet report.")
|
|
5334
|
+
"this time sheet report.", nil, @sourceFileInfo[1])
|
|
5139
5335
|
end
|
|
5140
5336
|
@timeSheetRecord.expectedEnd = @val[1]
|
|
5141
5337
|
})
|
|
@@ -5150,7 +5346,8 @@ EOT
|
|
|
5150
5346
|
priority = @val[1]
|
|
5151
5347
|
if priority < 1 || priority > 1000
|
|
5152
5348
|
error('ts_bad_priority',
|
|
5153
|
-
"Priority value #{priority} must be between 1 and 1000."
|
|
5349
|
+
"Priority value #{priority} must be between 1 and 1000.", nil,
|
|
5350
|
+
@sourceFileInfo[1])
|
|
5154
5351
|
end
|
|
5155
5352
|
@timeSheetRecord.priority = priority
|
|
5156
5353
|
})
|
|
@@ -5213,14 +5410,15 @@ EOT
|
|
|
5213
5410
|
@property = @val[1]
|
|
5214
5411
|
unless @property.leaf?
|
|
5215
5412
|
error('ts_task_not_leaf',
|
|
5216
|
-
'You cannot specify a task that has sub tasks here.'
|
|
5413
|
+
'You cannot specify a task that has sub tasks here.',
|
|
5414
|
+
@property, @sourceFileInfo[1])
|
|
5217
5415
|
end
|
|
5218
5416
|
scenarioIdx = @timeSheet.scenarioIdx
|
|
5219
5417
|
taskStart = @property['start', scenarioIdx] || @project['start']
|
|
5220
5418
|
taskEnd = @property['end', scenarioIdx] || @project['end']
|
|
5221
5419
|
|
|
5222
5420
|
@timeSheetRecord = TimeSheetRecord.new(@timeSheet, @property)
|
|
5223
|
-
@timeSheetRecord.sourceFileInfo = @
|
|
5421
|
+
@timeSheetRecord.sourceFileInfo = @sourceFileInfo[0]
|
|
5224
5422
|
})
|
|
5225
5423
|
arg(1, 'task', 'ID of an already existing task')
|
|
5226
5424
|
end
|
|
@@ -5235,7 +5433,8 @@ EOT
|
|
|
5235
5433
|
pattern(%w( !date ), lambda {
|
|
5236
5434
|
if @val[0] < @project['start'] || @val[0] > @project['end']
|
|
5237
5435
|
error('date_in_range', "Date must be within the project time frame " +
|
|
5238
|
-
"#{@project['start']}
|
|
5436
|
+
"#{@project['start']} - #{@project['end']}", nil,
|
|
5437
|
+
@sourceFileInfo[0])
|
|
5239
5438
|
end
|
|
5240
5439
|
@val[0]
|
|
5241
5440
|
})
|
|
@@ -5244,7 +5443,8 @@ EOT
|
|
|
5244
5443
|
def rule_validTimeZone
|
|
5245
5444
|
pattern(%w( $STRING ), lambda {
|
|
5246
5445
|
unless TjTime.checkTimeZone(@val[0])
|
|
5247
|
-
error('bad_time_zone', "#{@val[0]} is not a known time zone"
|
|
5446
|
+
error('bad_time_zone', "#{@val[0]} is not a known time zone", nil,
|
|
5447
|
+
@sourceFileInfo[0])
|
|
5248
5448
|
end
|
|
5249
5449
|
@val[0]
|
|
5250
5450
|
})
|
|
@@ -5258,7 +5458,8 @@ EOT
|
|
|
5258
5458
|
if mode == 0
|
|
5259
5459
|
unless @val[0] < endSpec
|
|
5260
5460
|
error('start_before_end', "The end date (#{endSpec}) must be " +
|
|
5261
|
-
"after the start date (#{@val[0]})."
|
|
5461
|
+
"after the start date (#{@val[0]}).", nil,
|
|
5462
|
+
@sourceFileInfo[1])
|
|
5262
5463
|
end
|
|
5263
5464
|
iv = Interval.new(@val[0], endSpec)
|
|
5264
5465
|
else
|
|
@@ -5294,7 +5495,7 @@ EOT
|
|
|
5294
5495
|
if mode == 0
|
|
5295
5496
|
unless @val[0] < endSpec
|
|
5296
5497
|
error('start_before_end', "The end date (#{endSpec}) must be after " +
|
|
5297
|
-
"the start date (#{@val[0]}).")
|
|
5498
|
+
"the start date (#{@val[0]}).", nil, @sourceFileInfo[1])
|
|
5298
5499
|
end
|
|
5299
5500
|
iv = Interval.new(@val[0], endSpec)
|
|
5300
5501
|
else
|
|
@@ -5330,7 +5531,7 @@ EOT
|
|
|
5330
5531
|
The warn attribute adds a logical expression to the property. The condition
|
|
5331
5532
|
described by the logical expression is checked after the scheduling and an
|
|
5332
5533
|
warning is generated if the condition evaluates to true. This attribute is
|
|
5333
|
-
primarily intended for testing
|
|
5534
|
+
primarily intended for testing purposes.
|
|
5334
5535
|
EOT
|
|
5335
5536
|
)
|
|
5336
5537
|
end
|
|
@@ -5367,7 +5568,7 @@ EOT
|
|
|
5367
5568
|
|
|
5368
5569
|
def rule_weekDayIntervalEnd
|
|
5369
5570
|
optional
|
|
5370
|
-
pattern([ '_
|
|
5571
|
+
pattern([ '_-', '!weekday' ], lambda {
|
|
5371
5572
|
@val[1]
|
|
5372
5573
|
})
|
|
5373
5574
|
arg(1, 'end weekday',
|
|
@@ -5409,7 +5610,8 @@ EOT
|
|
|
5409
5610
|
# 1.0.
|
|
5410
5611
|
if @val[0] < 0.0 || @val[0] > 100.0
|
|
5411
5612
|
error('illegal_percentage',
|
|
5412
|
-
"Percentage values must be between 0 and 100%."
|
|
5613
|
+
"Percentage values must be between 0 and 100%.", nil,
|
|
5614
|
+
@sourceFileInfo[1])
|
|
5413
5615
|
end
|
|
5414
5616
|
@val[0] / 100.0
|
|
5415
5617
|
end
|
|
@@ -5441,8 +5643,12 @@ EOT
|
|
|
5441
5643
|
Set the default working hours for all subsequent resource definitions.
|
|
5442
5644
|
The working hours specification limits the availability of resources to
|
|
5443
5645
|
certain time slots of week days.
|
|
5646
|
+
|
|
5647
|
+
These default working hours can be replaced with other working hours for
|
|
5648
|
+
individual resources.
|
|
5444
5649
|
EOT
|
|
5445
5650
|
)
|
|
5651
|
+
also(%w( dailyworkinghours workinghours.resource workinghours.shift ))
|
|
5446
5652
|
end
|
|
5447
5653
|
|
|
5448
5654
|
def rule_workinghoursResource
|
|
@@ -5452,16 +5658,26 @@ Set the working hours for a specific resource. The working hours specification
|
|
|
5452
5658
|
limits the availability of resources to certain time slots of week days.
|
|
5453
5659
|
EOT
|
|
5454
5660
|
)
|
|
5661
|
+
also(%w( workinghours.project workinghours.shift ))
|
|
5455
5662
|
end
|
|
5456
5663
|
|
|
5457
5664
|
def rule_workinghoursShift
|
|
5458
5665
|
pattern(%w( !workinghours ))
|
|
5459
5666
|
doc('workinghours.shift', <<'EOT'
|
|
5460
|
-
Set the
|
|
5461
|
-
|
|
5667
|
+
Set the working hours for the shift. The working hours specification limits
|
|
5668
|
+
the availability of resources or the activity on a task to certain time
|
|
5462
5669
|
slots of week days.
|
|
5670
|
+
|
|
5671
|
+
The shift working hours will replace the default or resource working hours for
|
|
5672
|
+
the specified time frame when assigning the shift to a resource.
|
|
5673
|
+
|
|
5674
|
+
In case the shift is used for a task, resources are only assigned during the
|
|
5675
|
+
working hours of this shift and during the working hours of the allocated
|
|
5676
|
+
resource. Allocations only happen when both the task shift and the resource
|
|
5677
|
+
work hours allow work to happen.
|
|
5463
5678
|
EOT
|
|
5464
5679
|
)
|
|
5680
|
+
also(%w( workinghours.project workinghours.resource ))
|
|
5465
5681
|
end
|
|
5466
5682
|
|
|
5467
5683
|
def rule_yesNo
|