This module contains the rule definition for the TJP syntax. Every rule is put in a function who’s name must start with rule_. The functions are not necessary but make the file more readable and receptable to syntax folding.
# File lib/TjpSyntaxRules.rb, line 21 21: def rule_account 22: pattern(%( !accountHeader !accountBody ), lambda { 23: @property = @property.parent 24: }) 25: doc('account', Declares an account. Accounts can be used to calculate costs of tasks or thewhole project. Account declaration may be nested, but only leaf accounts maybe used to track turnover. When the cost of a task is split over multipleaccounts they all must have the same top-level group account. Top-levelaccounts can be used for profit/loss calculations. The sub-account structureof a top-level account should be organized accordingly.Accounts have a global name space. All IDs must be unique within the accounts of the project. 26: ) 27: example('Account', '1') 28: end
# File lib/TjpSyntaxRules.rb, line 39 39: def rule_accountAttributes 40: repeatable 41: optional 42: pattern(%( !account)) 43: pattern(%( !accountScenarioAttributes )) 44: pattern(%( !scenarioIdCol !accountScenarioAttributes ), lambda { 45: @scenarioIdx = 0 46: }) 47: # Other attributes will be added automatically. 48: end
# File lib/TjpSyntaxRules.rb, line 50 50: def rule_accountBody 51: optionsRule('accountAttributes') 52: end
# File lib/TjpSyntaxRules.rb, line 54 54: def rule_accountHeader 55: pattern(%( _account !optionalID $STRING ), lambda { 56: if @property.nil? && !@accountprefix.empty? 57: @property = @project.accout(@accountprefix) 58: end 59: if @val[1] && @project.account(@val[1]) 60: error('account_exists', "Account #{@val[1]} has already been defined.", 61: @sourceFileInfo[1], @property) 62: end 63: @property = Account.new(@project, @val[1], @val[2], @property) 64: @property.sourceFileInfo = @sourceFileInfo[0] 65: @property.inheritAttributes 66: @scenarioIdx = 0 67: }) 68: arg(2, 'name', 'A name or short description of the account') 69: end
# File lib/TjpSyntaxRules.rb, line 71 71: def rule_accountId 72: pattern(%( $ID ), lambda { 73: id = @val[0] 74: id = @accountprefix + '.' + id unless @accountprefix.empty? 75: # In case we have a nested supplement, we need to prepend the parent ID. 76: id = @property.fullId + '.' + id if @property && @property.is_a?(Account) 77: if (account = @project.account(id)).nil? 78: error('unknown_account', "Unknown account #{id}", @sourceFileInfo[0]) 79: end 80: account 81: }) 82: end
# File lib/TjpSyntaxRules.rb, line 84 84: def rule_accountScenarioAttributes 85: pattern(%( _credit !valDate $STRING !number ), lambda { 86: #@property['credit', @scenarioIdx] += 87: # AccountCredit.new(@val[1], @val[2], @val[3]) 88: }) 89: doc('credit', Book the specified amount to the account at the specified date. 90: ) 91: example('Account', '1') 92: arg(2, 'description', 'Short description of the transaction') 93: arg(3, 'amount', 'Amount to be booked.') 94: 95: pattern(%( !flags )) 96: doc('flags.account', Attach a set of flags. The flags can be used in logical expressions to filterproperties from the reports. 97: ) 98: 99: # Other attributes will be added automatically. 100: end
# File lib/TjpSyntaxRules.rb, line 107 107: def rule_alertLevel 108: pattern(%( $ID ), lambda { 109: level = @project.alertLevelIndex(@val[0]) 110: unless level 111: error('bad_alert', "Unknown alert level #{@val[1]}. Must be " + 112: 'green, yellow or red', @sourceFileInfo[0]) 113: end 114: level 115: }) 116: doc('alert level', Specify the alert level for this entry. Supported values are green, yellow andred. The default value is green. This attribute is inteded to be used forstatus reporting. When used for a journal entry that is associated with aproperty, the value can be reported in the alert column. When multiple entrieshave been specified for the property, the entry with the date closest to thereport end date will be used. Container properties will inherit the highestalert level of all its sub properties unless it has an own journal entry datedcloser to the report end than all of its sub properties. 117: ) 118: end
# File lib/TjpSyntaxRules.rb, line 129 129: def rule_allocate 130: pattern(%( _allocate !allocations ), lambda { 131: checkContainer('allocate') 132: # Don't use << operator here so the 'provided' flag gets set properly. 133: begin 134: @property['allocate', @scenarioIdx] = 135: @property['allocate', @scenarioIdx] + @val[1] 136: rescue AttributeOverwrite 137: # Adding multiple allocates for a task is a pretty common idiom. 138: end 139: }) 140: doc('allocate', Specify which resources should be allocated to the task. Theattributes provide numerous ways to control which resource is used and whenexactly it will be assigned to the task. Shifts and limits can be used torestrict the allocation to certain time intervals or to limit them to acertain maximum per time period. The purge statement can be used to removeinherited allocations or flags. 141: ) 142: example('Allocate-1', '1') 143: end
# File lib/TjpSyntaxRules.rb, line 152 152: def rule_allocation 153: pattern(%( !allocationHeader !allocationBody ), lambda { 154: @val[0] 155: }) 156: end
# File lib/TjpSyntaxRules.rb, line 158 158: def rule_allocationAttributes 159: optional 160: repeatable 161: 162: pattern(%( _alternative !resourceId !moreAlternatives ), lambda { 163: ([ @val[1] ] + (@val[2] ? @val[2] : [])).each do |candidate| 164: @allocate.addCandidate(candidate) 165: end 166: }) 167: doc('alternative', Specify which resources should be allocated to the task. The optionalattributes provide numerous ways to control which resource is used and whenexactly it will be assigned to the task. Shifts and limits can be used torestrict the allocation to certain time intervals or to limit them to acertain maximum per time period. 168: ) 169: example('Alternative', '1') 170: 171: pattern(%( !limits ), lambda { 172: limits = @property['limits', @scenarioIdx] = @val[0] 173: @allocate.candidates.each do |resource| 174: limits.limits.each do |l| 175: l.resource = resource if resource.leaf? 176: end 177: end 178: }) 179: doc('limits.allocate', 'This keyword is deprecated. Don\t use it anymore!') 180: 181: pattern(%( _select !allocationSelectionMode ), lambda { 182: @allocate.setSelectionMode(@val[1]) 183: }) 184: doc('select', The select functions controls which resource is picked from an allocation andit's alternatives. The selection is re-evaluated each time the resource usedin the previous time slot becomes unavailable.Even for non-persistent allocations a change in the resource selection onlyhappens if the resource used in the previous (or next for ASAP tasks) timeslot has become unavailable. 185: ) 186: 187: pattern(%( _persistent ), lambda { 188: @allocate.persistent = true 189: }) 190: doc('persistent', Specifies that once a resource is picked from the list of alternatives thisresource is used for the whole task. This is useful when several alternativeresources have been specified. Normally the selected resource can change aftereach break. A break is an interval of at least one timeslot where no resourceswere available. 191: ) 192: 193: pattern(%( _mandatory ), lambda { 194: @allocate.mandatory = true 195: }) 196: doc('mandatory', Makes a resource allocation mandatory. This means, that for each time slotonly then resources are allocated when all mandatory resources are available.So either all mandatory resources can be allocated for the time slot, or noresource will be allocated. 197: ) 198: pattern(%( _shift !allocationShiftAssignment )) 199: doc('shifts.allocate', Limits the allocations of resources during the specified interval to thespecified shift. Multiple shifts can be defined, but shift intervals may notoverlap. Allocation shifts are an additional restriction to the[[shifts.task|task shifts]] and [[shifts.resource|resource shifts]] or[[workinghours.resource|resource working hours]]. Allocations will only bemade for time slots that are specified as duty time in all relevant shifts.The restriction to the shift is only active during the specified timeinterval. Outside of this interval, no restrictions apply. 200: ) 201: end
# File lib/TjpSyntaxRules.rb, line 237 237: def rule_allocationBody 238: optionsRule('allocationAttributes') 239: end
# File lib/TjpSyntaxRules.rb, line 241 241: def rule_allocationHeader 242: pattern(%( !resourceId ), lambda { 243: @allocate = Allocation.new([ @val[0] ]) 244: }) 245: end
# File lib/TjpSyntaxRules.rb, line 251 251: def rule_allocationSelectionMode 252: singlePattern('_maxloaded') 253: descr('Pick the available resource that has been used the most so far.') 254: 255: singlePattern('_minloaded') 256: descr('Pick the available resource that has been used the least so far.') 257: 258: singlePattern('_minallocated') 259: descr(Pick the resource that has the smallest allocation factor. Theallocation factor is calculated from the various allocations of the resourceacross the tasks. This is the default setting.) 260: ) 261: 262: singlePattern('_order') 263: descr('Pick the first available resource from the list.') 264: 265: singlePattern('_random') 266: descr('Pick a random resource from the list.') 267: end
# File lib/TjpSyntaxRules.rb, line 273 273: def rule_allocationShiftAssignment 274: pattern(%( !shiftId !intervalsOptional ), lambda { 275: # Make sure we have a ShiftAssignment for the allocation. 276: if @allocate.shifts.nil? 277: @allocate.shifts = ShiftAssignments.new 278: @allocate.shifts.project = @project 279: end 280: 281: if @val[1].nil? 282: intervals = [ Interval.new(@project['start'], @project['end']) ] 283: else 284: intervals = @val[1] 285: end 286: intervals.each do |interval| 287: if !@allocate.shifts. 288: addAssignment(ShiftAssignment.new(@val[0].scenario(@scenarioIdx), 289: interval)) 290: error('shift_assignment_overlap', 291: 'Shifts may not overlap each other.', @sourceFileInfo[0]) 292: end 293: end 294: }) 295: end
# File lib/TjpSyntaxRules.rb, line 247 247: def rule_allocations 248: listRule('moreAllocations', '!allocation') 249: end
# File lib/TjpSyntaxRules.rb, line 297 297: def rule_argument 298: singlePattern('$ABSOLUTE_ID') 299: singlePattern('!date') 300: singlePattern('$ID') 301: singlePattern('$INTEGER') 302: singlePattern('$FLOAT') 303: end
# File lib/TjpSyntaxRules.rb, line 305 305: def rule_argumentList 306: optional 307: pattern(%( _( !argumentListBody _) ), lambda { 308: @val[1].nil? ? [] : @val[1] 309: }) 310: end
# File lib/TjpSyntaxRules.rb, line 312 312: def rule_argumentListBody 313: optional 314: pattern(%( !argument !moreArguments ), lambda { 315: [ @val[0] ] + (@val[1].nil? ? [] : @val[1]) 316: }) 317: end
# File lib/TjpSyntaxRules.rb, line 330 330: def rule_balance 331: pattern(%( _balance !accountId !accountId ), lambda { 332: if @val[1].parent 333: error('cost_acct_no_top', 334: "The cost account #{@val[1].fullId} is not a top-level account.", 335: @sourceFileInfo[1]) 336: end 337: if @val[2].parent 338: error('rev_acct_no_top', 339: "The revenue account #{@val[2].fullId} is not a top-level " + 340: "account.", @sourceFileInfo[2]) 341: end 342: if @val[1] == @val[2] 343: error('cost_rev_same', 344: 'The cost and revenue accounts may not be the same.', 345: @sourceFileInfo[1]) 346: end 347: [ @val[1], @val[2] ] 348: }) 349: doc('balance', During report generation, TaskJuggler can consider some accounts to be revenue accounts, while other can be considered cost accounts. By using the balance attribute, two top-level accounts can be designated for a profit-loss-analysis. This analysis includes all sub accounts of these two top-level accounts. 350: ) 351: arg(1, 'cost account', The top-level account that is used for all cost related charges. 352: ) 353: arg(2, 'revenue account', The top-level account that is used for all revenue related charges. 354: ) 355: end
# File lib/TjpSyntaxRules.rb, line 363 363: def rule_bookingAttributes 364: optional 365: repeatable 366: 367: pattern(%( _overtime $INTEGER ), lambda { 368: if @val[1] < 0 || @val[1] > 2 369: error('overtime_range', 370: "Overtime value #{@val[1]} out of range (0 - 2).", 371: @sourceFileInfo[1], @property) 372: end 373: @booking.overtime = @val[1] 374: }) 375: doc('overtime.booking', This attribute enables bookings during off-hours and vacations. It implicitlysets the [[sloppy.booking|sloppy]] attribute accordingly. 376: ) 377: arg(1, 'value', * '''0''': You can only book available working time. (Default)* '''1''': You can book off-hours as well.* '''2''': You can book working time, off-hours and vacation time. 378: ) 379: 380: pattern(%( _sloppy $INTEGER ), lambda { 381: if @val[1] < 0 || @val[1] > 2 382: error('sloppy_range', 383: "Sloppyness value #{@val[1]} out of range (0 - 2).", 384: @sourceFileInfo[1], @property) 385: end 386: @booking.sloppy = @val[1] 387: }) 388: doc('sloppy.booking', Controls how strict TaskJuggler checks booking intervals for conflicts withworking periods and vacations. This attribute only affects the check forconflicts. No assignments will be made unless the [[overtime.booking|overtime]] attribute is set accordingly. 389: ) 390: arg(1, 'sloppyness', * '''0''': Period may not contain any off-duty hours, vacation or other taskassignments. (default)* '''1''': Period may contain off-duty hours, but no vacation time or othertask assignments.* '''2''': Period may contain off-duty hours and vacation time, but no othertask assignments. 391: ) 392: end
# File lib/TjpSyntaxRules.rb, line 417 417: def rule_bookingBody 418: optionsRule('bookingAttributes') 419: end
# File lib/TjpSyntaxRules.rb, line 421 421: def rule_calendarDuration 422: pattern(%( !number !durationUnit ), lambda { 423: convFactors = [ 60.0, # minutes 424: 60.0 * 60, # hours 425: 60.0 * 60 * 24, # days 426: 60.0 * 60 * 24 * 7, # weeks 427: 60.0 * 60 * 24 * 30.4167, # months 428: 60.0 * 60 * 24 * 365 # years 429: ] 430: ((@val[0] * convFactors[@val[1]]) / @project['scheduleGranularity']).to_i 431: }) 432: arg(0, 'value', 'A floating point or integer number') 433: end
# File lib/TjpSyntaxRules.rb, line 474 474: def rule_chargeMode 475: singlePattern('_onstart') 476: descr('Charge the amount on starting the task.') 477: 478: singlePattern('_onend') 479: descr('Charge the amount on finishing the task.') 480: 481: singlePattern('_perhour') 482: descr('Charge the amount for every hour the task lasts.') 483: 484: singlePattern('_perday') 485: descr('Charge the amount for every day the task lasts.') 486: 487: singlePattern('_perweek') 488: descr('Charge the amount for every week the task lasts.') 489: end
# File lib/TjpSyntaxRules.rb, line 491 491: def rule_chargeSetItem 492: pattern(%( !accountId !optionalPercent ), lambda { 493: [ @val[0], @val[1] ] 494: }) 495: arg(0, 'account', 'The ID of a previously defined leaf account.') 496: arg(1, 'share', 'A percentage between 0 and 100%') 497: end
# File lib/TjpSyntaxRules.rb, line 435 435: def rule_chargeset 436: pattern(%( _chargeset !chargeSetItem !moreChargeSetItems ), lambda { 437: checkContainer('chargeset') 438: items = [ @val[1] ] 439: items += @val[2] if @val[2] 440: chargeSet = ChargeSet.new 441: begin 442: items.each do |item| 443: chargeSet.addAccount(item[0], item[1]) 444: end 445: chargeSet.complete 446: rescue TjException 447: error('chargeset', $!.message, @sourceFileInfo[0], @property) 448: end 449: masterAccounts = [] 450: @property['chargeset', @scenarioIdx].each do |set| 451: masterAccounts << set.master 452: end 453: if masterAccounts.include?(chargeSet.master) 454: error('chargeset_master', 455: "All charge sets for this task must have different top-level " + 456: "accounts.", @sourceFileInfo[0], @property) 457: end 458: @property['chargeset', @scenarioIdx] = 459: @property['chargeset', @scenarioIdx] + [ chargeSet ] 460: }) 461: doc('chargeset', A chargeset defines how the turnover associated with the task will be chargedto one or more accounts. A task may have any number of charge sets, but eachchargeset must deal with a different top-level account. A charge set consistsof one or more accounts. Each account must be a leaf account. The account IDmay be followed by a percentage value that determines the share for thisaccount. The total percentage of all accounts must be exactly 100%. If someaccounts don't have a percentage specification, the remainder to 100% isdistributed evenly to them. 462: ) 463: end
# File lib/TjpSyntaxRules.rb, line 499 499: def rule_chartScale 500: singlePattern('_hour') 501: descr('Set chart resolution to 1 hour.') 502: 503: singlePattern('_day') 504: descr('Set chart resolution to 1 day.') 505: 506: singlePattern('_week') 507: descr('Set chart resolution to 1 week.') 508: 509: singlePattern('_month') 510: descr('Set chart resolution to 1 month.') 511: 512: singlePattern('_quarter') 513: descr('Set chart resolution to 1 quarter.') 514: 515: singlePattern('_year') 516: descr('Set chart resolution to 1 year.') 517: end
# File lib/TjpSyntaxRules.rb, line 519 519: def rule_color 520: pattern(%( $STRING ), lambda { 521: col = @val[0] 522: unless /#[0-9A-Fa-f]{3}/ =~ col || /#[0-9A-Fa-f]{3}/ =~ col 523: error('bad_color', 524: "Color values must be specified as '#RGB' or '#RRGGBB' values", 525: @sourceFileInfo[0]) 526: end 527: col 528: }) 529: arg(0, 'color', The RGB color values of the color. The following formats are supported: #RGBand #RRGGBB. Where R, G, B are hexadecimal values. See[http://en.wikipedia.org/wiki/Web_colors Wikipedia] for more details. 530: ) 531: end
# File lib/TjpSyntaxRules.rb, line 537 537: def rule_columnBody 538: optionsRule('columnOptions') 539: end
# File lib/TjpSyntaxRules.rb, line 541 541: def rule_columnDef 542: pattern(%( !columnId !columnBody ), lambda { 543: @val[0] 544: }) 545: end
# File lib/TjpSyntaxRules.rb, line 547 547: def rule_columnId 548: pattern(%( !reportableAttributes ), lambda { 549: title = TableReport.defaultColumnTitle(@val[0]) || 550: @project.attributeName(@val[0]) 551: @column = TableColumnDefinition.new(@val[0], title) 552: }) 553: doc('columnid', This is a comprehensive list of all pre-defined [[columns]]. In addition tothe listed IDs all user defined attributes can be used as column IDs. 554: ) 555: end
# File lib/TjpSyntaxRules.rb, line 560 560: def rule_columnOptions 561: optional 562: repeatable 563: 564: pattern(%( _celltext !logicalExpression $STRING ), lambda { 565: @column.cellText.addPattern( 566: CellSettingPattern.new(newRichText(@val[2], @sourceFileInfo[2]), 567: @val[1])) 568: }) 569: doc('celltext.column', Specifies an alternative content that is used for the cells of the column.Usually such a text contains a query function. Otherwise all cells of thecolumn will have the same fixed value. The logical expression specifies forwhich cells the text should be used. If multiple celltext patterns areprovided for a column, the first matching one is taken for each cell. 570: ) 571: arg(1, 'text', 572: 'Alterntive cell text specified as [[Rich_Text_Attributes|Rich Text]]') 573: 574: pattern(%( _cellcolor !logicalExpression !color ), lambda { 575: @column.cellColor.addPattern( 576: CellSettingPattern.new(@val[2], @val[1])) 577: }) 578: doc('cellcolor.column', Specifies an alternative background color for the cells of this column. Thelogical expression specifies for which cells the color should be used. Ifmultiple cellcolor patterns are provided for a column, the firstmatching one is used for each cell. 579: ) 580: 581: pattern(%( _end !date ), lambda { 582: @column.end = @val[1] 583: }) 584: doc('end.column', Normally, columns with calculated values take the specified report period intoaccount when calculating their values. With this attribute, the user canspecify an end date for the period that should be used when calculating thevalues of this column. It does not have an impact on column with timeinvariant values. 585: ) 586: 587: pattern(%( _fontcolor !logicalExpression !color ), lambda { 588: @column.fontColor.addPattern( 589: CellSettingPattern.new(@val[2], @val[1])) 590: }) 591: doc('fontcolor.column', Specifies an alternative font color for the cells of this column. Thelogical expression specifies for which cells the color should be used. Ifmultiple fontcolor patterns are provided for a column, the firstmatching one is used for each cell. 592: ) 593: 594: pattern(%( _halign !logicalExpression !hAlignment ), lambda { 595: @column.hAlign.addPattern( 596: CellSettingPattern.new(@val[2], @val[1])) 597: }) 598: doc('halign.column', Specifies the horizontal alignment of the cell content. The logical expressionspecifies for which cells the alignment setting should be used. If multiplehalign patterns are provided for a column, the first matching one is used foreach cell. 599: ) 600: 601: pattern(%( _listmode $INTEGER ), lambda { 602: @column.listMode = @val[1] 603: }) 604: also(%( listtype.column )) 605: doc('listmode.column', Specifies how the list items look like. The result of this setting depends onthe actual column. Please refer to the [columnid|documentation for thespecific column] to learn more about the effect that this setting has. 606: ) 607: 608: pattern(%( _listtype !listType ), lambda { 609: @column.listType = @val[1] 610: }) 611: also(%( listmode.column )) 612: doc('listtype.column', Specifies what type of list should be used. This attribute only affectscolumns that contain a list of items. 613: ) 614: 615: pattern(%( _period !interval ), lambda { 616: @column.start = @val[1].start 617: @column.end = @val[1].end 618: }) 619: doc('period.column', This property is a shortcut for setting the [[start.column|start]] and[[end.column|end]] property at the same time. 620: ) 621: 622: pattern(%( _scale !chartScale ), lambda { 623: @column.scale = @val[1] 624: }) 625: doc('scale.column', Specifies the scale that should be used for a chart column. This value is ignored for all other columns. 626: ) 627: 628: pattern(%( _start !date ), lambda { 629: @column.start = @val[1] 630: }) 631: doc('start.column', Normally, columns with calculated values take the specified report period intoaccount when calculating their values. With this attribute, the user canspecify a start date for the period that should be used when calculating thevalues of this column. It does not have an impact on column with timeinvariant values. 632: ) 633: 634: pattern(%( _title $STRING ), lambda { 635: @column.title = @val[1] 636: }) 637: doc('title.column', Specifies an alternative title for a report column. 638: ) 639: arg(1, 'text', 'The new column title.') 640: 641: pattern(%( _tooltip !logicalExpression $STRING ), lambda { 642: @column.tooltip.addPattern( 643: CellSettingPattern.new(newRichText(@val[2], @sourceFileInfo[2]), 644: @val[1])) 645: }) 646: doc('tooltip.column', Specifies an alternative content for the tooltip. This will replace theoriginal content of the tooltip that would be available for columns with textthat does not fit the column with. The logical expression specifies for whichcells the text should be used. If multiple tooltip patterns are provided for acolumn, the first matching one is taken for each cell. 647: ) 648: arg(2, 'text', The content of the tooltip. The text is interpreted as [[Rich_Text_Attributes|Rich Text]]. 649: ) 650: 651: pattern(%( _width !number ), lambda { 652: @column.width = @val[1] 653: }) 654: doc('width.column', Specifies the width of the column in screen pixels. If the content of thecolumn does not fit into this width, it will be cut off. In some cases ascrollbar is added or a tooltip window with the complete content is shown whenthe mouse is moved over the column. The latter is only supported ininteractive output formats. 655: ) 656: end
# File lib/TjpSyntaxRules.rb, line 720 720: def rule_date 721: pattern(%( !dateCalcedOrNot ), lambda { 722: resolution = @project.nil? ? Project.maxScheduleGranularity : 723: @project['scheduleGranularity'] 724: if @val[0] % resolution != 0 725: error('misaligned_date', 726: "The date must be aligned to the timing resolution (" + 727: "#{resolution / 60} min) of the project.", 728: @sourceFileInfo[0]) 729: end 730: @val[0] 731: }) 732: doc('date', A DATE is an ISO-compliant date in the format''''<nowiki>YYYY-MM-DD[-hh:mm[:ss]][-TIMEZONE]</nowiki>''''. Hour, minutes,seconds, and the ''''TIMEZONE'''' are optional. If not specified, the valuesare set to 0. ''''TIMEZONE'''' must be an offset to GMT or UTC, specified as''''+HHMM'''' or ''''-HHMM''''. Dates must always be aligned with the[[timingresolution]].TaskJuggler also supports simple date calculations. You can add or substract agiven interval from a fixed date. %{2009-11-01 + 8m}This will result in an actual date of around 2009-07-01. Keep in mind that due to the varying lengths of months TaskJuggler cannot add exactly 8 calendar months. The date calculation functionality makes most sense when used with macros. %{${now} - 2w}This is result in a date 2 weeks earlier than the current (or specified) date.See [[duration]] for a complete list of supported time intervals. Don't forgetto put at least one space character after the date to prevent TaskJuggler frominterpreting the interval as an hour. 733: ) 734: end
# File lib/TjpSyntaxRules.rb, line 757 757: def rule_dateCalcedOrNot 758: singlePattern('$DATE') 759: pattern(%( _% _{ $DATE !plusOrMinus !intervalDuration _} ), lambda { 760: @val[2] + ((@val[3] == '+' ? 1 : 1) * @val[4]) 761: }) 762: end
# File lib/TjpSyntaxRules.rb, line 764 764: def rule_declareFlagList 765: listRule('moreDeclareFlagList', '$ID') 766: end
# File lib/TjpSyntaxRules.rb, line 768 768: def rule_details 769: pattern(%( _details $STRING ), lambda { 770: return if @val[1].empty? 771: 772: rtTokenSetMore = 773: [ :LINEBREAK, :SPACE, :WORD, :BOLD, :ITALIC, :CODE, :BOLDITALIC, 774: :PRE, :HREF, :HREFEND, :REF, :REFEND, :HLINE, :TITLE2, :TITLE3, 775: :TITLE4, :TITLE2END, :TITLE3END, :TITLE4END, 776: :BULLET1, :BULLET2, :BULLET3, :BULLET4, :NUMBER1, :NUMBER2, :NUMBER3, 777: :NUMBER4 ] 778: if @val[1] == "Some more details\n" 779: error('ts_default_details', 780: "'Some more details' is not a valid value", 781: @sourceFileInfo[1]) 782: end 783: @journalEntry.details = newRichText(@val[1], @sourceFileInfo[1], 784: rtTokenSetMore) 785: }) 786: doc('details', This is a continuation of the [[summary]] of the journal or status entry. Itcan be several paragraphs long. 787: ) 788: arg(1, 'text', The text will be interpreted as [[Rich_Text_Attributes|Rich Text]]. Only asubset of the markup is supported for this attribute. You can use wordformatting, paragraphs, hyperlinks, lists, section and subsectionheaders. 789: ) 790: end
# File lib/TjpSyntaxRules.rb, line 800 800: def rule_durationUnit 801: pattern(%( _min ), lambda { 0 }) 802: descr('minutes') 803: 804: pattern(%( _h ), lambda { 1 }) 805: descr('hours') 806: 807: pattern(%( _d ), lambda { 2 }) 808: descr('days') 809: 810: pattern(%( _w ), lambda { 3 }) 811: descr('weeks') 812: 813: pattern(%( _m ), lambda { 4 }) 814: descr('months') 815: 816: pattern(%( _y ), lambda { 5 }) 817: descr('years') 818: end
# File lib/TjpSyntaxRules.rb, line 820 820: def rule_durationUnitOrPercent 821: pattern(%( _% ), lambda { 1 }) 822: descr('percentage of reported period') 823: 824: pattern(%( _min ), lambda { 0 }) 825: descr('minutes') 826: 827: pattern(%( _h ), lambda { 1 }) 828: descr('hours') 829: 830: pattern(%( _d ), lambda { 2 }) 831: descr('days') 832: end
# File lib/TjpSyntaxRules.rb, line 834 834: def rule_export 835: pattern(%( !exportHeader !exportBody ), lambda { 836: @property = nil 837: }) 838: doc('export', The export report looks like a regular TaskJuggler file with the providedinput data complemented by the results of the scheduling process. The contentof the report can be controlled with the [[definitions]] attribute. In casethe file contains the project header, a ''''.tjp'''' extension is added to thefile name. Otherwise, a ''''.tji'''' extension is used.The [[resourceattributes]] and [[taskattributes]] attributes provide even morecontrol over the content of the file.The export report can be used to share certain tasks or milestones with otherprojects or to save past resource allocations as immutable part for futurescheduling runs. When an export report is included the project IDs of theincluded tasks must be declared first with the project id property. 839: ) 840: example('Export') 841: end
# File lib/TjpSyntaxRules.rb, line 868 868: def rule_exportAttributes 869: optional 870: repeatable 871: 872: pattern(%( _definitions !exportDefinitions ), lambda { 873: @property.set('definitions', @val[1]) 874: }) 875: doc('definitions', This attributes controls what definitions will be contained in the report. Ifthe list includes ''project'', the generated file will have a ''''.tjp''''extension. Otherwise it will have a ''''.tji'''' extension.By default, the report contains everything and the generated files has a ''''.tjp'''' extension. 876: ) 877: allOrNothingListRule('exportDefinitions', 878: { 'flags' => 'Include flag definitions', 879: 'project' => 'Include project header', 880: 'projecids' => 'Include project IDs', 881: 'tasks' => 'Include task definitions', 882: 'resources' => 'Include resource definitions' }) 883: pattern(%( !hideresource )) 884: pattern(%( !hidetask )) 885: pattern(%( !reportEnd )) 886: pattern(%( !reportPeriod )) 887: pattern(%( !reportStart )) 888: 889: pattern(%( _resourceattributes !exportableResourceAttributes ), lambda { 890: @property.set('resourceAttributes', @val[1]) 891: }) 892: doc('resourceattributes', Define a list of resource attributes that should be included in the report. 893: ) 894: allOrNothingListRule('exportableResourceAttributes', 895: { 'vacation' => 'Include vacations', 896: 'workinghours' => 'Include working hours' }) 897: 898: pattern(%( _taskattributes !exportableTaskAttributes ), lambda { 899: @property.set('taskAttributes', @val[1]) 900: }) 901: doc('taskattributes', Define a list of task attributes that should be included in the report. 902: ) 903: allOrNothingListRule('exportableTaskAttributes', 904: { 'booking' => 'Include bookings', 905: 'complete' => 'Include completion values', 906: 'depends' => 'Include dependencies', 907: 'flags' => 'Include flags', 908: 'maxend' => 'Include maximum end dates', 909: 'maxstart' => 'Include maximum start dates', 910: 'minend' => 'Include minimum end dates', 911: 'minstart' => 'Include minimum start dates', 912: 'note' => 'Include notes', 913: 'priority' => 'Include priorities', 914: 'responsible' => 'Include responsible resource' }) 915: end
# File lib/TjpSyntaxRules.rb, line 927 927: def rule_exportBody 928: optionsRule('exportAttributes') 929: end
# File lib/TjpSyntaxRules.rb, line 857 857: def rule_exportHeader 858: pattern(%( _export !optionalID $STRING ), lambda { 859: newReport(@val[1], @val[2], :export, sourceFileInfo) 860: }) 861: arg(1, 'file name', The name of the report file to generate. It must end with a .tjp or .tjiextension, or use . to use the standard output channel. 862: ) 863: end
# File lib/TjpSyntaxRules.rb, line 931 931: def rule_extendAttributes 932: optional 933: repeatable 934: 935: pattern(%( _date !extendId $STRING !extendOptionsBody ), lambda { 936: # Extend the propertySet definition and parser rules 937: if extendPropertySetDefinition(DateAttribute, nil) 938: @ruleToExtendWithScenario.addPattern(TextParser::Pattern.new( 939: [ '_' + @val[1], '!date' ], lambda { 940: @property[@val[0], @scenarioIdx] = @val[1] 941: })) 942: else 943: @ruleToExtend.addPattern(TextParser::Pattern.new( 944: [ '_' + @val[1], '!date' ], lambda { 945: @property.set(@val[0], @val[1]) 946: })) 947: end 948: }) 949: doc('date.extend', Extend the property with a new attribute of type date. 950: ) 951: arg(2, 'name', 'The name of the new attribute. It is used as header ' + 952: 'in report columns and the like.') 953: 954: pattern(%( _reference !extendId $STRING !extendOptionsBody ), lambda { 955: # Extend the propertySet definition and parser rules 956: if extendPropertySetDefinition(ReferenceAttribute, nil) 957: @ruleToExtendWithScenario.addPattern(TextParser::Pattern.new( 958: [ '_' + @val[1], '$STRING', '!referenceBody' ], lambda { 959: @property[@val[0], @scenarioIdx] = [ @val[1], @val[2] ] 960: })) 961: else 962: @ruleToExtend.addPattern(TextParser::Pattern.new( 963: [ '_' + @val[1], '$STRING', '!referenceBody' ], lambda { 964: @property.set(@val[0], [ @val[1], @val[2] ]) 965: })) 966: end 967: }) 968: doc('reference.extend', Extend the property with a new attribute of type reference. A reference is aURL and an optional text that will be shown instead of the URL if needed. 969: ) 970: arg(2, 'name', 'The name of the new attribute. It is used as header ' + 971: 'in report columns and the like.') 972: 973: pattern(%( _text !extendId $STRING !extendOptionsBody ), lambda { 974: # Extend the propertySet definition and parser rules 975: if extendPropertySetDefinition(StringAttribute, nil) 976: @ruleToExtendWithScenario.addPattern(TextParser::Pattern.new( 977: [ '_' + @val[1], '$STRING' ], lambda { 978: @property[@val[0], @scenarioIdx] = @val[1] 979: })) 980: else 981: @ruleToExtend.addPattern(TextParser::Pattern.new( 982: [ '_' + @val[1], '$STRING' ], lambda { 983: @property.set(@val[0], @val[1]) 984: })) 985: end 986: }) 987: doc('text.extend', Extend the property with a new attribute of type text. A text is a charactersequence enclosed in single or double quotes. 988: ) 989: arg(2, 'name', 'The name of the new attribute. It is used as header ' + 990: 'in report columns and the like.') 991: 992: end
# File lib/TjpSyntaxRules.rb, line 1002 1002: def rule_extendBody 1003: optionsRule('extendAttributes') 1004: end
# File lib/TjpSyntaxRules.rb, line 1006 1006: def rule_extendId 1007: pattern(%( $ID ), lambda { 1008: unless (AA..ZZ) === @val[0][0] 1009: error('extend_id_cap', 1010: "User defined attributes IDs must start with a capital letter", 1011: @sourceFileInfo[0]) 1012: end 1013: @val[0] 1014: }) 1015: arg(0, 'id', 'The ID of the new attribute. It can be used like the ' + 1016: 'built-in IDs.') 1017: end
# File lib/TjpSyntaxRules.rb, line 1019 1019: def rule_extendOptions 1020: optional 1021: repeatable 1022: 1023: singlePattern('_inherit') 1024: doc('inherit.extend', If the this attribute is used, the property extension will be inherited bychild properties from their parent property. 1025: ) 1026: 1027: singlePattern('_scenariospecific') 1028: doc('scenariospecific.extend', If this attribute is used, the property extension is scenario specific. Adifferent value can be set for each scenario. 1029: ) 1030: end
# File lib/TjpSyntaxRules.rb, line 1038 1038: def rule_extendOptionsBody 1039: optionsRule('extendOptions') 1040: end
# File lib/TjpSyntaxRules.rb, line 1042 1042: def rule_extendProperty 1043: pattern(%( !extendPropertyId ), lambda { 1044: case @val[0] 1045: when 'task' 1046: @ruleToExtend = @rules[:taskAttributes] 1047: @ruleToExtendWithScenario = @rules[:taskScenarioAttributes] 1048: @propertySet = @project.tasks 1049: when 'resource' 1050: @ruleToExtend = @rules[:resourceAttributes] 1051: @ruleToExtendWithScenario = @rules[:resourceScenarioAttributes] 1052: @propertySet = @project.resources 1053: end 1054: }) 1055: end
# File lib/TjpSyntaxRules.rb, line 1057 1057: def rule_extendPropertyId 1058: singlePattern('_task') 1059: singlePattern('_resource') 1060: end
# File lib/TjpSyntaxRules.rb, line 1062 1062: def rule_fail 1063: pattern(%( _fail !logicalExpression ), lambda { 1064: begin 1065: @property['fail', @scenarioIdx] = 1066: @property['fail', @scenarioIdx] + [ @val[1] ] 1067: rescue AttributeOverwrite 1068: end 1069: }) 1070: doc('fail', The fail attribute adds a logical expression to the property. The conditiondescribed by the logical expression is checked after the scheduling and anerror is raised if the condition evaluates to true. This attribute isprimarily intended for testing purposes. 1071: ) 1072: end
# File lib/TjpSyntaxRules.rb, line 1079 1079: def rule_flag 1080: pattern(%( $ID ), lambda { 1081: unless @project['flags'].include?(@val[0]) 1082: error('undecl_flag', "Undeclared flag '#{@val[0]}'", 1083: @sourceFileInfo[0]) 1084: end 1085: @val[0] 1086: }) 1087: end
# File lib/TjpSyntaxRules.rb, line 1100 1100: def rule_flagList 1101: listRule('moreFlagList', '!flag') 1102: end
# File lib/TjpSyntaxRules.rb, line 1089 1089: def rule_flags 1090: pattern(%( _flags !flagList ), lambda { 1091: @val[1].each do |flag| 1092: unless @property['flags', @scenarioIdx].include?(flag) 1093: @property['flags', @scenarioIdx] = 1094: @property['flags', @scenarioIdx] + @val[1] 1095: end 1096: end 1097: }) 1098: end
# File lib/TjpSyntaxRules.rb, line 1104 1104: def rule_formats 1105: pattern(%( _formats !outputFormats ), lambda { 1106: @property.set('formats', @val[1]) 1107: }) 1108: doc('formats', This attribute defines for which output formats the report should begenerated. By default, this list is empty. Unless a formats attribute wasadded to a report definition, no output will be generated for this report.As reports are composable, a report may include other report definitions. Aformat definition is only needed for the outermost report that includes theothers. 1109: ) 1110: end
# File lib/TjpSyntaxRules.rb, line 1165 1165: def rule_functionPatterns 1166: # This rule is not used by the parser. It's only for the documentation. 1167: pattern(%( _hasalert _( $INTEGER _, !date _) )) 1168: doc('hasalert', Will evaluate to true if the current property has a current alert message within the report time frame and with at least the provided alert level. 1169: ) 1170: arg(2, 'Level', 'The minimum required alert level to be considered.') 1171: 1172: pattern(%( _isactive _( $ID _) )) 1173: doc('isactive', Will evaluate to true for tasks and resources if they have bookings inthe scenario during the report time frame. 1174: ) 1175: arg(2, 'ID', 'A scenario ID') 1176: 1177: pattern(%( _isdependencyof _( $ID _, $ID _, $INTEGER _) )) 1178: doc('isdependencyof', Will evaluate to true for tasks that depend on the specified task inthe specified scenario and are no more than distance tasks away. Ifdistance is 0, all dependencies are considered independent of theirdistance. 1179: ) 1180: arg(2, 'Task ID', 'The ID of a defined task') 1181: arg(4, 'Scenario ID', 'A scenario ID') 1182: arg(6, 'Distance', 'The maximum task distance to be considered') 1183: 1184: pattern(%( _isdutyof _( $ID _, $ID _) )) 1185: doc('isdutyof', Will evaluate to true for tasks that have the specified resourceassigned to it in the specified scenario. 1186: ) 1187: arg(2, 'Resource ID', 'The ID of a defined resource') 1188: arg(4, 'Scenario ID', 'A scenario ID') 1189: 1190: pattern(%( _isfeatureof _( $ID _, $ID _) )) 1191: doc('isfeatureof', If the provided task or any of its sub-tasks depend on this task or any of itssub-tasks, we call this task a feature of the provided task. 1192: ) 1193: arg(2, 'Task ID', 'The ID of a defined task') 1194: arg(4, 'Scenario ID', 'A scenario ID') 1195: 1196: pattern(['_isleaf', '_(', '_)' ]) 1197: doc('isleaf', 'The result is true if the property is not a container.') 1198: 1199: pattern(%( _isongoing _( $ID _) )) 1200: doc('isongoing', Will evaluate to true for tasks that overlap with the report period in givenscenario. 1201: ) 1202: arg(2, 'ID', 'A scenario ID') 1203: 1204: pattern(['_isresource', '_(', '_)' ]) 1205: doc('isresource', 'The result is true if the property is a resource.') 1206: 1207: pattern(['_istask', '_(', '_)' ]) 1208: doc('istask', 'The result is true if the property is a task.') 1209: 1210: pattern(%( _treelevel _( _) )) 1211: doc('treelevel', Returns the nesting level of a property in the property tree.Top level properties have a level of 1, their children 2 and so on. 1212: ) 1213: end
# File lib/TjpSyntaxRules.rb, line 1120 1120: def rule_functions 1121: # This rule is not used by the parser. It's only for the documentation. 1122: pattern(%( !functionsBody )) 1123: doc('functions', The following functions are supported in logical expressions. These functionsare evaluated in logical conditions such as hidetask or rollupresource. Forthe evaluation, implicit and explicit parameters are used.All functions may operate on the current property and the scope property. Thescope property is the enclosing property in reports with nested properties.Imagine e. g a task report with nested resources. When the function is calledfor a task line, the task is the property and we don't have a scope property.When the function is called for a resource line, the resource is the propertyand the enclosing task is the scope property.These number of arguments that are passed in brackets to the function dependson the specific function. See the reference for details on each function.All functions can be suffixed with an underscore character. In that case, thefunction is operating on the scope property as if it were the property. Theoriginal property is ignored in that case. In our task report example fromabove, calling a function with an appended dash would mean that a taskline would be evaluated for the enclosing resource.In the example below you can see how this can be used. To generate a taskreport that lists all assigned leaf resources for leaf task lines only we usethe expression hideresource ~(isleaf() & isleaf_())The tilde in front of the bracketed expression means not that expression. Inother words: show resources that are leaf resources and show them for leaftasks only. The regular form isleaf() (without the appended underscore)operates on the resource. The isleaf_() variant operates on theenclosing task. 1124: ) 1125: example('LogicalFunction', '1') 1126: end
# File lib/TjpSyntaxRules.rb, line 1160 1160: def rule_functionsBody 1161: # This rule is not used by the parser. It's only for the documentation. 1162: optionsRule('functionPatterns') 1163: end
# File lib/TjpSyntaxRules.rb, line 1237 1237: def rule_hAlignment 1238: pattern(%( _center ), lambda { 1239: :center 1240: }) 1241: doc('halign.center', 'Center the cell content') 1242: 1243: pattern(%( _left ), lambda { 1244: :left 1245: }) 1246: doc('halign.left', 'Left align the cell content') 1247: 1248: pattern(%( _right ), lambda { 1249: :right 1250: }) 1251: doc('halign.right', 'Right align the cell content') 1252: end
# File lib/TjpSyntaxRules.rb, line 1254 1254: def rule_headline 1255: pattern(%( _headline $STRING ), lambda { 1256: @property.set('headline', newRichText(@val[1], @sourceFileInfo[1])) 1257: }) 1258: doc('headline', Specifies the headline for a report. 1259: ) 1260: arg(1, 'text', The text used for the headline. It is interpreted as[[Rich_Text_Attributes|Rich Text]]. 1261: ) 1262: end
# File lib/TjpSyntaxRules.rb, line 1269 1269: def rule_hideresource 1270: pattern(%( _hideresource !logicalExpression ), lambda { 1271: @property.set('hideResource', @val[1]) 1272: }) 1273: doc('hideresource', Do not include resources that match the specified logical expression. If thereport is sorted in tree mode (default) then enclosing resources are listedeven if the expression matches the resource. 1274: ) 1275: also(%( sortresources )) 1276: end
# File lib/TjpSyntaxRules.rb, line 1282 1282: def rule_hidetask 1283: pattern(%( _hidetask !logicalExpression ), lambda { 1284: @property.set('hideTask', @val[1]) 1285: }) 1286: doc('hidetask', Do not include tasks that match the specified logical expression. If thereport is sorted in tree mode (default) then enclosing tasks are listed evenif the expression matches the task. 1287: ) 1288: also(%( sorttasks )) 1289: end
# File lib/TjpSyntaxRules.rb, line 1295 1295: def rule_idOrAbsoluteId 1296: singlePattern('$ID') 1297: singlePattern('$ABSOLUTE_ID') 1298: end
# File lib/TjpSyntaxRules.rb, line 1300 1300: def rule_includeAttributes 1301: optionsRule('includeAttributesBody') 1302: end
# File lib/TjpSyntaxRules.rb, line 1304 1304: def rule_includeAttributesBody 1305: optional 1306: repeatable 1307: 1308: pattern(%( _accountprefix !taskId ), lambda { 1309: @accountprefix = @val[1].fullId 1310: }) 1311: doc('accountprefix', This attribute can be used to insert the accounts of the included file assub-account of the account specified by ID. The parent account must already bedefined. 1312: ) 1313: arg(1, 'account ID', 'The absolute ID of an already defined account') 1314: 1315: pattern(%( _reportprefix !taskId ), lambda { 1316: @reportprefix = @val[1].fullId 1317: }) 1318: doc('reportprefix', This attribute can be used to insert the reports of the included file assub-report of the report specified by ID. The parent report must alreadybe defined. 1319: ) 1320: arg(1, 'report ID', 'The absolute ID of an already defined report.') 1321: 1322: pattern(%( _resourceprefix !resourceId ), lambda { 1323: @resourceprefix = @val[1].fullId 1324: }) 1325: doc('resourceprefix', This attribute can be used to insert the resources of the included file assub-resource of the resource specified by ID. The parent resource must alreadybe defined. 1326: ) 1327: arg(1, 'resource ID', 'The ID of an already defined resource') 1328: 1329: pattern(%( _taskprefix !taskId ), lambda { 1330: @taskprefix = @val[1].fullId 1331: }) 1332: doc('taskprefix', This attribute can be used to insert the tasks of the included file assub-task of the task specified by ID. The parent task must already be defined. 1333: ) 1334: arg(1, 'task ID', 'The absolute ID of an already defined task.') 1335: end
# File lib/TjpSyntaxRules.rb, line 1352 1352: def rule_includeFile 1353: pattern(%( !includeFileName ), lambda { 1354: unless @project 1355: error('include_before_project', 1356: "You must declare the project header before you include other " + 1357: "files.") 1358: end 1359: @project.inputFiles << @scanner.include(@val[0], @sourceFileInfo[0]) do 1360: popFileStack 1361: end 1362: }) 1363: end
# File lib/TjpSyntaxRules.rb, line 1365 1365: def rule_includeFileName 1366: pattern(%( $STRING ), lambda { 1367: unless @val[0][4, 4] == '.tji' 1368: error('bad_include_suffix', "Included files must have a '.tji'" + 1369: "extension: '#{@val[0]}'", 1370: @sourceFileInfo[0]) 1371: end 1372: pushFileStack 1373: @val[0] 1374: }) 1375: arg(0, 'filename', Name of the file to include. This must have a ''''.tji'''' extension. The namemay have an absolute or relative path. You need to use ''''/'''' characters toseparate directories. 1376: ) 1377: end
# File lib/TjpSyntaxRules.rb, line 1383 1383: def rule_includeProperties 1384: pattern(%( !includeFileName !includeAttributes ), lambda { 1385: @project.inputFiles << @scanner.include(@val[0], @sourceFileInfo[0]) do 1386: popFileStack 1387: end 1388: }) 1389: end
# File lib/TjpSyntaxRules.rb, line 1423 1423: def rule_interval 1424: pattern(%( !date !intervalEnd ), lambda { 1425: mode = @val[1][0] 1426: endSpec = @val[1][1] 1427: if mode == 0 1428: unless @val[0] < endSpec 1429: error('start_before_end', "The end date (#{endSpec}) must be after " + 1430: "the start date (#{@val[0]}).", @sourceFileInfo[0]) 1431: end 1432: Interval.new(@val[0], endSpec) 1433: else 1434: Interval.new(@val[0], @val[0] + endSpec) 1435: end 1436: }) 1437: doc('interval2', There are two ways to specify a date interval. The first is the mostobvious. A date interval consists of a start and end DATE. Watch out for enddates without a time specification! Date specifications are 0 extended. Anend date without a time is expanded to midnight that day. So the day of theend date is not included in the interval! The start and end dates must be separated by a hyphen character.In the second form specifies the start date and an interval duration. Theduration must be prefixed by a plus character. 1438: ) 1439: end
# File lib/TjpSyntaxRules.rb, line 1450 1450: def rule_intervalDuration 1451: pattern(%( !number !durationUnit ), lambda { 1452: convFactors = [ 60, # minutes 1453: 60 * 60, # hours 1454: 60 * 60 * 24, # days 1455: 60 * 60 * 24 * 7, # weeks 1456: 60 * 60 * 24 * 30.4167, # months 1457: 60 * 60 * 24 * 365 # years 1458: ] 1459: if @val[0] == 0.0 1460: error('zero_duration', "The interval duration may not be 0.", 1461: @sourceFileInfo[1]) 1462: end 1463: duration = @val[0] * convFactors[@val[1]] 1464: resolution = @project.nil? ? 60 * 60 : @project['scheduleGranularity'] 1465: # Make sure the interval aligns with the timing resolution. 1466: (duration / resolution).to_i * resolution 1467: }) 1468: arg(0, 'duration', 'The duration of the interval. May not be 0.') 1469: end
# File lib/TjpSyntaxRules.rb, line 1471 1471: def rule_intervalEnd 1472: pattern([ '_-', '!date' ], lambda { 1473: [ 0, @val[1] ] 1474: }) 1475: 1476: pattern(%( _+ !intervalDuration ), lambda { 1477: [ 1, @val[1] ] 1478: }) 1479: end
# File lib/TjpSyntaxRules.rb, line 1481 1481: def rule_intervalOptionalEnd 1482: optional 1483: pattern([ '_-', '!date' ], lambda { 1484: [ 0, @val[1] ] 1485: }) 1486: 1487: pattern(%( _+ !intervalDuration ), lambda { 1488: [ 1, @val[1] ] 1489: }) 1490: end
# File lib/TjpSyntaxRules.rb, line 1391 1391: def rule_intervalOrDate 1392: pattern(%( !date !intervalOptionalEnd ), lambda { 1393: if @val[1] 1394: mode = @val[1][0] 1395: endSpec = @val[1][1] 1396: if mode == 0 1397: unless @val[0] < endSpec 1398: error('start_before_end', "The end date (#{endSpec}) must be " + 1399: "after the start date (#{@val[0]}).", @sourceFileInfo[0]) 1400: end 1401: Interval.new(@val[0], endSpec) 1402: else 1403: Interval.new(@val[0], @val[0] + endSpec) 1404: end 1405: else 1406: Interval.new(@val[0], @val[0].sameTimeNextDay) 1407: end 1408: }) 1409: doc('interval3', There are three ways to specify a date interval. The first is the mostobvious. A date interval consists of a start and end DATE. Watch out for enddates without a time specification! Date specifications are 0 extended. Anend date without a time is expanded to midnight that day. So the day of theend date is not included in the interval! The start and end dates must be separated by a hyphen character.In the second form, the end date is omitted. A 24 hour interval is assumed.The third form specifies the start date and an interval duration. The duration must be prefixed by a plus character. 1410: ) 1411: end
# File lib/TjpSyntaxRules.rb, line 1492 1492: def rule_intervals 1493: listRule('moreIntervals', '!intervalOrDate') 1494: end
# File lib/TjpSyntaxRules.rb, line 1496 1496: def rule_intervalsOptional 1497: optional 1498: singlePattern('!intervals') 1499: end
# File lib/TjpSyntaxRules.rb, line 1501 1501: def rule_journalEntry 1502: pattern(%( !journalEntryHeader !journalEntryBody ), lambda { 1503: @val[0] 1504: }) 1505: doc('journalentry', This attribute adds an entry to the journal of the project. A journal can beused to record events, decisions or news that happened at a particular momentduring the project. Depending on the context, a journal entry may or may notbe associated with a specific property or author.A journal entry can consists of up to three parts. The headline is mandatoryand should be only 5 to 10 words long. The introduction is optional and shouldbe only one or two sentences long. All other details should be put into thethird part.Depending on the context, journal entries are listed with headlines only, asheadlines plus introduction or in full. 1506: ) 1507: end
# File lib/TjpSyntaxRules.rb, line 1522 1522: def rule_journalEntryAttributes 1523: optional 1524: repeatable 1525: 1526: pattern(%( _alert $ID ), lambda { 1527: level = @project.alertLevelIndex(@val[1]) 1528: unless level 1529: error('bad_alert', "Unknown alert level #{@val[1]}. Must be " + 1530: 'green, yellow or red', @sourceFileInfo[0]) 1531: end 1532: @journalEntry.alertLevel = level 1533: }) 1534: doc('alert', Specify the alert level for this entry. Supported values are green, yellow andred. The default value is green. This attribute is inteded to be used forstatus reporting. When used for a journal entry that is associated with aproperty, the value can be reported in the alert column. When multiple entrieshave been specified for the property, the entry with the date closest to thereport end date will be used. Container properties will inherit the highestalert level of all its sub properties unless it has an own journal entry datedcloser to the report end than all of its sub properties. 1535: ) 1536: 1537: pattern(%( !author )) 1538: 1539: pattern(%( !summary )) 1540: 1541: pattern(%( !details )) 1542: end
# File lib/TjpSyntaxRules.rb, line 1553 1553: def rule_journalEntryBody 1554: optionsRule('journalEntryAttributes') 1555: end
# File lib/TjpSyntaxRules.rb, line 1557 1557: def rule_journalEntryHeader 1558: pattern(%( _journalentry !valDate $STRING ), lambda { 1559: @journalEntry = JournalEntry.new(@project['journal'], @val[1], @val[2], 1560: @property, @sourceFileInfo[0]) 1561: }) 1562: arg(2, 'headline', The headline of the journal entry. It will be interpreted as[[Rich_Text_Attributes|Rich Text]]. 1563: ) 1564: end
# File lib/TjpSyntaxRules.rb, line 1568 1568: def rule_leafResourceId 1569: pattern(%( !resourceId ), lambda { 1570: resource = @val[0] 1571: unless resource.leaf? 1572: error('leaf_resource_id_expected', 1573: "#{resource.id} is not a leaf resource.", @sourceFileInfo[0]) 1574: end 1575: resource 1576: }) 1577: arg(0, 'resource', 'The ID of a leaf resource') 1578: end
# File lib/TjpSyntaxRules.rb, line 1580 1580: def rule_limitAttributes 1581: optionsRule('limitAttributesBody') 1582: end
# File lib/TjpSyntaxRules.rb, line 1584 1584: def rule_limitAttributesBody 1585: optional 1586: repeatable 1587: 1588: pattern(%( _end !valDate ), lambda { 1589: @limitInterval.end = @val[1] 1590: }) 1591: doc('end.limit', The end date of the limit interval. It must be within the project time frame. 1592: ) 1593: 1594: pattern(%( _period !valInterval ), lambda { 1595: @limitInterval = @val[1] 1596: }) 1597: doc('period.limit', This property is a shortcut for setting the start and end dates of the limitinterval. Both dates must be within the project time frame. 1598: ) 1599: 1600: pattern(%( _resources !resourceLeafList ), lambda { 1601: @limitResources = @val[1] 1602: }) 1603: doc('resources.limit', When [[limits]] are used in a [[task]] context, the limits can be restrictedto a list of resources that are allocated to the task. In that case eachlisted resource will not be allocated more than the specified upper limit.Lower limits have no impact on the scheduler but do generate a warning whennot met. All specified resources must be leaf resources. 1604: ) 1605: example('Limits-1', '5') 1606: 1607: pattern(%( _start !valDate ), lambda { 1608: @limitInterval.start = @val[1] 1609: }) 1610: doc('start.limit', The start date of the limit interval. It must be within the project time frame. 1611: ) 1612: end
# File lib/TjpSyntaxRules.rb, line 1627 1627: def rule_limitValue 1628: pattern([ '!workingDuration' ], lambda { 1629: @limitInterval = Interval.new(@project['start'], @project['end']) 1630: @limitResources = [] 1631: @val[0] 1632: }) 1633: end
# File lib/TjpSyntaxRules.rb, line 1635 1635: def rule_limits 1636: pattern(%( !limitsHeader !limitsBody ), lambda { 1637: @val[0] 1638: }) 1639: end
# File lib/TjpSyntaxRules.rb, line 1641 1641: def rule_limitsAttributes 1642: optional 1643: repeatable 1644: 1645: pattern(%( _dailymax !limitValue !limitAttributes), lambda { 1646: setLimit(@val[0], @val[1], @limitInterval) 1647: }) 1648: doc('dailymax', Set a maximum limit for each calendar day. 1649: ) 1650: example('Limits-1', '1') 1651: 1652: pattern(%( _dailymin !limitValue !limitAttributes), lambda { 1653: setLimit(@val[0], @val[1], @limitInterval) 1654: }) 1655: doc('dailymin', Minimum required effort for any calendar day. This value cannot be guaranteed bythe scheduler. It is only checked after the schedule is complete. In case theminium required amount has not been reached, a warning will be generated. 1656: ) 1657: example('Limits-1', '4') 1658: 1659: pattern(%( _maximum !limitValue !limitAttributes), lambda { 1660: setLimit(@val[0], @val[1], @limitInterval) 1661: }) 1662: doc('maximum', Set a maximum limit for the specified period. You must ensure that the overalleffort can be achieved! 1663: ) 1664: 1665: pattern(%( _minimum !limitValue !limitAttributes), lambda { 1666: setLimit(@val[0], @val[1], @limitInterval) 1667: }) 1668: doc('minimum', Set a minim limit for each calendar month. This will only result in a warningif not met. 1669: ) 1670: 1671: pattern(%( _monthlymax !limitValue !limitAttributes), lambda { 1672: setLimit(@val[0], @val[1], @limitInterval) 1673: }) 1674: doc('monthlymax', Set a maximum limit for each calendar month. 1675: ) 1676: 1677: pattern(%( _monthlymin !limitValue !limitAttributes), lambda { 1678: setLimit(@val[0], @val[1], @limitInterval) 1679: }) 1680: doc('monthlymin', Minimum required effort for any calendar month. This value cannot beguaranteed by the scheduler. It is only checked after the schedule iscomplete. In case the minium required amount has not been reached, a warningwill be generated. 1681: ) 1682: 1683: pattern(%( _weeklymax !limitValue !limitAttributes), lambda { 1684: setLimit(@val[0], @val[1], @limitInterval) 1685: }) 1686: doc('weeklymax', Set a maximum limit for each calendar week. 1687: ) 1688: 1689: pattern(%( _weeklymin !limitValue !limitAttributes), lambda { 1690: setLimit(@val[0], @val[1], @limitInterval) 1691: }) 1692: doc('weeklymin', Minimum required effort for any calendar week. This value cannot be guaranteed bythe scheduler. It is only checked after the schedule is complete. In case theminium required amount has not been reached, a warning will be generated. 1693: ) 1694: end
# File lib/TjpSyntaxRules.rb, line 1721 1721: def rule_limitsBody 1722: optionsRule('limitsAttributes') 1723: end
# File lib/TjpSyntaxRules.rb, line 1725 1725: def rule_limitsHeader 1726: pattern(%( _limits ), lambda { 1727: @limits = Limits.new 1728: @limits.setProject(@project) 1729: @limits 1730: }) 1731: end
# File lib/TjpSyntaxRules.rb, line 1733 1733: def rule_listOfDays 1734: pattern(%( !weekDayInterval !moreListOfDays), lambda { 1735: weekDays = Array.new(7, false) 1736: ([ @val[0] ] + (@val[1] ? @val[1] : [])).each do |dayList| 1737: 7.times { |i| weekDays[i] = true if dayList[i] } 1738: end 1739: weekDays 1740: }) 1741: end
# File lib/TjpSyntaxRules.rb, line 1743 1743: def rule_listOfTimes 1744: pattern(%( _off ), lambda { 1745: [ ] 1746: }) 1747: pattern(%( !timeInterval !moreTimeIntervals ), lambda { 1748: [ @val[0] ] + (@val[1].nil? ? [] : @val[1]) 1749: }) 1750: end
# File lib/TjpSyntaxRules.rb, line 1752 1752: def rule_listType 1753: pattern([ '_bullets' ], lambda { :bullets }) 1754: descr('List items as bullet list') 1755: 1756: pattern([ '_comma' ], lambda { :comma }) 1757: descr('List items as comma separated list') 1758: 1759: pattern([ '_numbered' ], lambda { :numbered }) 1760: descr('List items as numbered list') 1761: end
# File lib/TjpSyntaxRules.rb, line 1763 1763: def rule_loadunit 1764: pattern([ '_days' ], lambda { :days }) 1765: descr('Display all load and duration values as days.') 1766: 1767: pattern([ '_hours' ], lambda { :hours }) 1768: descr('Display all load and duration values as hours.') 1769: 1770: pattern([ '_longauto'] , lambda { :longauto }) 1771: descr(Automatically select the unit that produces the shortest and most readablevalue. The unit name will not be abbreviated. 1772: ) 1773: 1774: pattern([ '_minutes' ], lambda { :minutes }) 1775: descr('Display all load and duration values as minutes.') 1776: 1777: pattern([ '_months' ], lambda { :months }) 1778: descr('Display all load and duration values as monts.') 1779: 1780: pattern([ '_shortauto' ], lambda { :shortauto }) 1781: descr(Automatically select the unit that produces the shortest and most readablevalue. The unit name will be abbreviated. 1782: ) 1783: 1784: pattern([ '_weeks' ], lambda { :weeks }) 1785: descr('Display all load and duration values as weeks.') 1786: 1787: pattern([ '_years' ], lambda { :years }) 1788: descr('Display all load and duration values as years.') 1789: end
# File lib/TjpSyntaxRules.rb, line 1797 1797: def rule_logicalExpression 1798: pattern(%( !operation ), lambda { 1799: LogicalExpression.new(@val[0], sourceFileInfo) 1800: }) 1801: doc('logicalexpression', A logical expression is a combination of operands and mathematical operations.The final result of a logical expression is always true or false. Logicalexpressions are used the reduce the properties in a report to a certain subsetor to select alternatives for the cell content of a table. When used withattributes like [[hidetask]] or [[hideresource]] the logical expressionevaluates to true for a certain property, this property is hidden or rolled-upin the report.Operands can be previously declared flags, built-in [[functions]], propertyattributes (specified as scenario.attribute) or another logical expression.When you combine logical operations to a more complex expression, theoperators are evaluated from left to right. '''a | b & c''' is identical to'''(a | b) & c'''. It's highly recommended that you always use brackets tocontrol the evaluation sequence. Currently, TaskJuggler does not support theconcept of operator precedence or right-left associativity. This may change inthe future.An operand can also be just a number. 0 evaluates to false, all other numbersto true. 1802: ) 1803: also(%( functions )) 1804: end
# File lib/TjpSyntaxRules.rb, line 1826 1826: def rule_macro 1827: pattern(%( _macro $ID $MACRO ), lambda { 1828: if @scanner.macroDefined?(@val[1]) 1829: warning('marco_redefinition', "Redefining macro #{@val[1]}") 1830: end 1831: @scanner.addMacro(Macro.new(@val[1], @val[2], @sourceFileInfo[0])) 1832: }) 1833: doc('macro', Defines a text fragment that can later be inserted by using the specified ID.To insert the text fragment anywhere in the text you need to write ${ID}.Thebody is not optional. It must be enclosed in square brackets. Macros can bedeclared like this: macro FOO [ This text ]If later ''''${FOO}'''' is found in the project file, it is expanded to''''This text''''.Macros may have arguments. Arguments are accessed with special macros withnumbers as names. The number specifies the index of the argument. macro FOO [ This ${1} text ]will expand to ''''This stupid text'''' if called as ''''${FOO "stupid"}''''.Macros may call other macros. All macro arguments must be enclosed by doublequotes. In case the argument contains a double quote, it must be escaped by aslash (''''/'''').User defined macro IDs must have at least one uppercase letter as alllowercase letter IDs are reserved for built-in macros.To terminate the macro definition, the ''''<nowiki>]</nowiki>'''' must be thelast character in the line. If there are any other characters trailing it(even spaces or comments) the ''''<nowiki>]</nowiki>'''' will not beconsidered the end of the macro definition.In macro calls the macro names can be prefixed by a question mark. In thiscase the macro will expand to nothing if the macro is not defined. Otherwisethe undefined macro would be flagged with an error message.The macro call ${?foo}will expand to nothing if foo is undefined. 1834: ) 1835: example('Macro-1') 1836: end
# File lib/TjpSyntaxRules.rb, line 1882 1882: def rule_moreAlternatives 1883: commaListRule('!resourceId') 1884: end
# File lib/TjpSyntaxRules.rb, line 1886 1886: def rule_moreArguments 1887: commaListRule('!argument') 1888: end
# File lib/TjpSyntaxRules.rb, line 1876 1876: def rule_moreBangs 1877: optional 1878: repeatable 1879: singlePattern('_!') 1880: end
# File lib/TjpSyntaxRules.rb, line 1890 1890: def rule_moreChargeSetItems 1891: commaListRule('!chargeSetItem') 1892: end
# File lib/TjpSyntaxRules.rb, line 1894 1894: def rule_moreColumnDef 1895: commaListRule('!columnDef') 1896: end
# File lib/TjpSyntaxRules.rb, line 1898 1898: def rule_moreDepTasks 1899: commaListRule('!taskDep') 1900: end
# File lib/TjpSyntaxRules.rb, line 1902 1902: def rule_moreLeafResources 1903: commaListRule('!resourceLeafList') 1904: end
# File lib/TjpSyntaxRules.rb, line 1906 1906: def rule_moreListOfDays 1907: commaListRule('!weekDayInterval') 1908: end
# File lib/TjpSyntaxRules.rb, line 1910 1910: def rule_moreOutputFormats 1911: commaListRule('!outputFormat') 1912: end
# File lib/TjpSyntaxRules.rb, line 1918 1918: def rule_morePredTasks 1919: commaListRule('!taskPredList') 1920: end
# File lib/TjpSyntaxRules.rb, line 1914 1914: def rule_moreProjectIDs 1915: commaListRule('$ID') 1916: end
# File lib/TjpSyntaxRules.rb, line 1922 1922: def rule_moreSortCriteria 1923: commaListRule('!sortNonTree') 1924: end
# File lib/TjpSyntaxRules.rb, line 1926 1926: def rule_moreTimeIntervals 1927: commaListRule('!timeInterval') 1928: end
# File lib/TjpSyntaxRules.rb, line 2011 2011: def rule_nikuReport 2012: pattern(%( !nikuReportHeader !nikuReportBody ), lambda { 2013: @property = nil 2014: }) 2015: doc('nikureport', This report generates an XML file to be imported into the enterprise resourcemanagement software Clarity(R) from Computer Associates(R). The files containsallocation curves for the specified resources. All tasks with identical userdefined attributes ''''ClarityPID'''' and ''''ClarityPNAME'''' are bundledinto a Clarity project. The resulting XML file can be imported into Claritywith the xog-in tool. 2016: ) 2017: example('Niku') 2018: end
# File lib/TjpSyntaxRules.rb, line 1970 1970: def rule_nikuReportAttributes 1971: optional 1972: repeatable 1973: 1974: pattern(%( !formats )) 1975: pattern(%( !headline )) 1976: pattern(%( !hideresource )) 1977: pattern(%( !hidetask )) 1978: pattern(%( !reportEnd )) 1979: pattern(%( !reportPeriod )) 1980: pattern(%( !reportStart )) 1981: pattern(%( !reportTitle )) 1982: pattern(%( _timeoff $STRING $STRING ), lambda { 1983: @property.set('timeOffId', @val[1]) 1984: @property.set('timeOffName', @val[2]) 1985: }) 1986: doc('timeoff.nikureport', Set the Clarity project ID and name that the vacation time will be reported to. 1987: ) 1988: arg(1, 'ID', 'The Clarity project ID') 1989: arg(2, 'Name', 'The Clarity project name') 1990: end
# File lib/TjpSyntaxRules.rb, line 1994 1994: def rule_nikuReportBody 1995: pattern(%( _{ !nikuReportAttributes _} ), lambda { 1996: 1997: }) 1998: end
# File lib/TjpSyntaxRules.rb, line 2000 2000: def rule_nikuReportHeader 2001: pattern(%( _nikureport !optionalID $STRING ), lambda { 2002: newReport(@val[1], @val[2], :niku, sourceFileInfo) 2003: }) 2004: arg(1, 'file name', The name of the time sheet report file to generate. It must end with a .tjiextension, or use . to use the standard output channel. 2005: ) 2006: end
# File lib/TjpSyntaxRules.rb, line 2027 2027: def rule_nodeId 2028: pattern(%( !idOrAbsoluteId !subNodeId ), lambda { 2029: case @property.typeSpec 2030: when :taskreport 2031: if (p1 = @project.task(@val[0])).nil? 2032: error('unknown_main_node', 2033: "Unknown task ID #{@val[0]}", @sourceFileInfo[0]) 2034: end 2035: if @val[1] 2036: if (p2 = @project.resource(@val[1])).nil? 2037: error('unknown_sub_node', 2038: "Unknown resource ID #{@val[0]}", @sourceFileInfo[0]) 2039: end 2040: return [ p2, p1 ] 2041: end 2042: return [ p1, nil ] 2043: when :resourcereport 2044: if (p1 = @project.task(@val[0])).nil? 2045: error('unknown_main_node', 2046: "Unknown task ID #{@val[0]}", @sourceFileInfo[0]) 2047: end 2048: if @val[1] 2049: if (p2 = @project.resource(@val[1])).nil? 2050: error('unknown_sub_node', 2051: "Unknown resource ID #{@val[0]}", @sourceFileInfo[0]) 2052: end 2053: return [ p2, p1 ] 2054: end 2055: return [ p1, nil ] 2056: end 2057: 2058: raise "Node list is not supported for this report type: " + 2059: "#{@property.typeSpec}" 2060: }) 2061: end
# File lib/TjpSyntaxRules.rb, line 2063 2063: def rule_nodeIdList 2064: listRule('moreNodeIdList', '!nodeId') 2065: pattern([ '_-' ], lambda { 2066: [] 2067: }) 2068: end
# File lib/TjpSyntaxRules.rb, line 2070 2070: def rule_number 2071: singlePattern('$INTEGER') 2072: singlePattern('$FLOAT') 2073: end
# File lib/TjpSyntaxRules.rb, line 2075 2075: def rule_operand 2076: pattern(%( _( !operation _) ), lambda { 2077: @val[1] 2078: }) 2079: pattern(%( _~ !operand ), lambda { 2080: operation = LogicalOperation.new(@val[1]) 2081: operation.operator = '~' 2082: operation 2083: }) 2084: 2085: pattern(%( $ABSOLUTE_ID ), lambda { 2086: if @val[0].count('.') > 1 2087: error('operand_attribute', 2088: 'Attributes must be specified as <scenarioID>.<attribute>', 2089: @sourceFileInfo[0]) 2090: end 2091: scenario, attribute = @val[0].split('.') 2092: if (scenarioIdx = @project.scenarioIdx(scenario)).nil? 2093: error('operand_unkn_scen', "Unknown scenario ID #{scenario}", 2094: @sourceFileInfo[0]) 2095: end 2096: LogicalAttribute.new(attribute, scenarioIdx) 2097: }) 2098: pattern(%( !date ), lambda { 2099: LogicalOperation.new(@val[0]) 2100: }) 2101: pattern(%( $ID !argumentList ), lambda { 2102: if @val[1].nil? 2103: unless @project['flags'].include?(@val[0]) 2104: error('operand_unkn_flag', "Undeclared flag '#{@val[0]}'", 2105: @sourceFileInfo[0]) 2106: end 2107: LogicalFlag.new(@val[0]) 2108: else 2109: func = LogicalFunction.new(@val[0]) 2110: res = func.setArgumentsAndCheck(@val[1]) 2111: unless res.nil? 2112: error(*res) 2113: end 2114: func 2115: end 2116: }) 2117: pattern(%( $INTEGER ), lambda { 2118: LogicalOperation.new(@val[0]) 2119: }) 2120: pattern(%( $FLOAT ), lambda { 2121: LogicalOperation.new(@val[0]) 2122: }) 2123: pattern(%( $STRING ), lambda { 2124: LogicalOperation.new(@val[0]) 2125: }) 2126: end
# File lib/TjpSyntaxRules.rb, line 2128 2128: def rule_operation 2129: pattern(%( !operand !operationChain ), lambda { 2130: operation = LogicalOperation.new(@val[0]) 2131: if @val[1] 2132: # Further operators/operands create an operation tree. 2133: @val[1].each do |ops| 2134: operation = LogicalOperation.new(operation) 2135: operation.operator = ops[0] 2136: operation.operand2 = ops[1] 2137: end 2138: end 2139: operation 2140: }) 2141: arg(0, 'operand', An operand can consist of a date, a text string, a [[functions|function]], aproperty attribute or a numerical value. It can also be the name of a declaredflag. Use the ''''scenario_id.attribute'''' notation to use an attribute of thecurrently evaluated property. The scenario ID always has to be specified, alsofor non-scenario specific attributes. This is necessary to distinguish themfrom flags.An operand can be a negated operand by prefixing a ~ charater or it can beanother logical expression enclosed in braces. 2142: ) 2143: end
# File lib/TjpSyntaxRules.rb, line 2155 2155: def rule_operationChain 2156: optional 2157: repeatable 2158: pattern(%( !operatorAndOperand), lambda { 2159: @val[0] 2160: }) 2161: end
# File lib/TjpSyntaxRules.rb, line 2173 2173: def rule_operator 2174: singlePattern('_|') 2175: descr('The \or\ operator') 2176: 2177: singlePattern('_&') 2178: descr('The \and\ operator') 2179: 2180: singlePattern('_>') 2181: descr('The \greater than\ operator') 2182: 2183: singlePattern('_<') 2184: descr('The \smaller than\ operator') 2185: 2186: singlePattern('_=') 2187: descr('The \equal\ operator') 2188: 2189: singlePattern('_>=') 2190: descr('The \greater-or-equal\ operator') 2191: 2192: singlePattern('_<=') 2193: descr('The \smaller-or-equal\ operator') 2194: 2195: singlePattern('_!=') 2196: descr('The \not-equal\ operator') 2197: end
# File lib/TjpSyntaxRules.rb, line 2163 2163: def rule_operatorAndOperand 2164: pattern(%( !operator !operand), lambda{ 2165: [ @val[0], @val[1] ] 2166: }) 2167: arg(1, 'operand', An operand can consist of a date, a text string or a numerical value. It can also be the name of a declared flag. Finally, an operand can be a negated operand by prefixing a ~ charater or it can be another operation enclosed in braces. 2168: ) 2169: end
# File lib/TjpSyntaxRules.rb, line 2199 2199: def rule_optionalID 2200: optional 2201: pattern(%( $ID ), lambda { 2202: @val[0] 2203: }) 2204: arg(0, 'id', An optional ID. If you ever want to reference this property, you must specifyyour own unique ID. If no ID is specified one will be automatically generated.These IDs may become visible in reports, but may change at any time. You maynever rely on automatically generated IDs. 2205: ) 2206: end
# File lib/TjpSyntaxRules.rb, line 2213 2213: def rule_optionalPercent 2214: optional 2215: pattern(%( !number _% ), lambda { 2216: @val[0] / 100.0 2217: }) 2218: end
# File lib/TjpSyntaxRules.rb, line 2220 2220: def rule_optionalVersion 2221: optional 2222: pattern(%( $STRING ), lambda { 2223: @val[0] 2224: }) 2225: arg(0, 'version', An optional version ID. This can be something simple as "4.2" or an ID tag ofa revision control system. If not specified, it defaults to "1.0". 2226: ) 2227: end
# File lib/TjpSyntaxRules.rb, line 2232 2232: def rule_outputFormat 2233: pattern(%( _csv ), lambda { 2234: :csv 2235: }) 2236: descr(The report lists the resources and their respective values ascolon-separated-value (CSV) format. Due to the very simple nature of the CSVformat, only a small subset of features will be supported for CSV output.Including tasks or listing multiple scenarios will result in very difficult toread reports. 2237: ) 2238: 2239: pattern(%( _html ), lambda { 2240: :html 2241: }) 2242: descr('Generate a web page (HTML file)') 2243: 2244: pattern(%( _niku ), lambda { 2245: :niku 2246: }) 2247: descr('Generate a XOG XML file to be used with Clarity.') 2248: end
# File lib/TjpSyntaxRules.rb, line 2256 2256: def rule_outputFormats 2257: pattern(%( !outputFormat !moreOutputFormats ), lambda { 2258: [ @val[0] ] + (@val[1].nil? ? [] : @val[1]) 2259: }) 2260: end
# File lib/TjpSyntaxRules.rb, line 2262 2262: def rule_plusOrMinus 2263: singlePattern('_+') 2264: singlePattern('_-') 2265: end
# File lib/TjpSyntaxRules.rb, line 2267 2267: def rule_project 2268: pattern(%( !projectProlog !projectDeclaration !properties . ), lambda { 2269: @val[1] 2270: }) 2271: end
# File lib/TjpSyntaxRules.rb, line 2273 2273: def rule_projectBody 2274: optionsRule('projectBodyAttributes') 2275: end
# File lib/TjpSyntaxRules.rb, line 2277 2277: def rule_projectBodyAttributes 2278: repeatable 2279: optional 2280: 2281: pattern(%( _currencyformat $STRING $STRING $STRING $STRING $INTEGER ), 2282: lambda { 2283: @project['currencyFormat'] = RealFormat.new(@val.slice(1, 5)) 2284: }) 2285: doc('currencyformat', 2286: 'These values specify the default format used for all currency ' + 2287: 'values.') 2288: example('Currencyformat') 2289: arg(1, 'negativeprefix', 'Prefix for negative numbers') 2290: arg(2, 'negativesuffix', 'Suffix for negative numbers') 2291: arg(3, 'thousandsep', 'Separator used for every 3rd digit') 2292: arg(4, 'fractionsep', 'Separator used to separate the fraction digits') 2293: arg(5, 'fractiondigits', 'Number of fraction digits to show') 2294: 2295: pattern(%( _currency $STRING ), lambda { 2296: @project['currency'] = @val[1] 2297: }) 2298: doc('currency', 'The default currency unit.') 2299: example('Account') 2300: arg(1, 'symbol', 'Currency symbol') 2301: 2302: pattern(%( _dailyworkinghours !number ), lambda { 2303: @project['dailyworkinghours'] = @val[1] 2304: }) 2305: doc('dailyworkinghours', Set the average number of working hours per day. This is used asthe base to convert working hours into working days. This affectsfor example the length task attribute. The default value is 8 hoursand should work for most Western countries. The value you specify should matchthe settings you specified as your default [[workinghours.project|workinghours]]. 2306: ) 2307: example('Project') 2308: arg(1, 'hours', 'Average number of working hours per working day') 2309: 2310: pattern(%( _extend !extendProperty !extendBody ), lambda { 2311: updateParserTables 2312: }) 2313: doc('extend', Often it is desirable to collect more information in the project file than isnecessary for task scheduling and resource allocation. To add such informationto tasks, resources or accounts the user can extend these properties withuser-defined attributes. The new attributes can be of various types such astext, date or reference to capture various types of data. Optionally the usercan specify if the attribute value should be inherited from the enclosingproperty. 2314: ) 2315: example('CustomAttributes') 2316: 2317: pattern(%( !projectBodyInclude )) 2318: 2319: pattern(%( !journalEntry )) 2320: 2321: pattern(%( _now !date ), lambda { 2322: @project['now'] = @val[1] 2323: @scanner.addMacro(Macro.new('now', @val[1].to_s, 2324: @sourceFileInfo[0])) 2325: @scanner.addMacro(Macro.new('today', @val[1].to_s(@project['timeFormat']), 2326: @sourceFileInfo[0])) 2327: }) 2328: doc('now', Specify the date that TaskJuggler uses for calculation as currentdate. If no value is specified, the current value of the systemclock is used. 2329: ) 2330: arg(1, 'date', 'Alternative date to be used as current date for all ' + 2331: 'computations') 2332: 2333: pattern(%( _numberformat $STRING $STRING $STRING $STRING $INTEGER ), 2334: lambda { 2335: @project['numberFormat'] = RealFormat.new(@val.slice(1, 5)) 2336: }) 2337: doc('numberformat', 2338: 'These values specify the default format used for all numerical ' + 2339: 'real values.') 2340: arg(1, 'negativeprefix', 'Prefix for negative numbers') 2341: arg(2, 'negativesuffix', 'Suffix for negative numbers') 2342: arg(3, 'thousandsep', 'Separator used for every 3rd digit') 2343: arg(4, 'fractionsep', 'Separator used to separate the fraction digits') 2344: arg(5, 'fractiondigits', 'Number of fraction digits to show') 2345: 2346: pattern(%( !scenario )) 2347: pattern(%( _shorttimeformat $STRING ), lambda { 2348: @project['shortTimeFormat'] = @val[1] 2349: }) 2350: doc('shorttimeformat', 2351: 'Specifies time format for time short specifications. This is normal' + 2352: 'just the hour and minutes.') 2353: arg(1, 'format', 'strftime like format string') 2354: 2355: pattern(%( !timeformat ), lambda { 2356: @project['timeFormat'] = @val[0] 2357: }) 2358: 2359: pattern(%( !timezone ), lambda { 2360: @project['timezone'] = @val[1] 2361: }) 2362: 2363: pattern(%( _timingresolution $INTEGER _min ), lambda { 2364: goodValues = [ 5, 10, 15, 20, 30, 60 ] 2365: unless goodValues.include?(@val[1]) 2366: error('bad_timing_res', 2367: "Timing resolution must be one of #{goodValues.join(', ')} min.", 2368: @sourceFileInfo[1]) 2369: end 2370: if @val[1] > (Project.maxScheduleGranularity / 60) 2371: error('too_large_timing_res', 2372: 'The maximum allowed timing resolution for the timezone is ' + 2373: "#{Project.maxScheduleGranularity / 60} minutes.", 2374: @sourceFileInfo[1]) 2375: end 2376: @project['scheduleGranularity'] = @val[1] * 60 2377: }) 2378: doc('timingresolution', Sets the minimum timing resolution. The smaller the value, the longer thescheduling process lasts and the more memory the application needs. Thedefault and maximum value is 1 hour. The smallest value is 5 min.This value is a pretty fundamental setting of TaskJuggler. It has a severeimpact on memory usage and scheduling performance. You should set this valueto the minimum required resolution. Make sure that all values that you specifyare aligned with the resolution.Changing the timing resolution will reset the [[workinghours.project|workinghours]] to the default times. It's recommended that this is the very firstoption in the project header section.Do not use this option after you've set the time zone! 2379: ) 2380: 2381: pattern(%( _weekstartsmonday ), lambda { 2382: @project['weekStartsMonday'] = true 2383: }) 2384: doc('weekstartsmonday', 2385: 'Specify that you want to base all week calculation on weeks ' + 2386: 'starting on Monday. This is common in many European countries.') 2387: 2388: pattern(%( _weekstartssunday ), lambda { 2389: @project['weekStartsMonday'] = false 2390: }) 2391: doc('weekstartssunday', 2392: 'Specify that you want to base all week calculation on weeks ' + 2393: 'starting on Sunday. This is common in the United States of America.') 2394: 2395: pattern(%( !workinghoursProject )) 2396: pattern(%( _yearlyworkingdays !number ), lambda { 2397: @project['yearlyworkingdays'] = @val[1] 2398: }) 2399: doc('yearlyworkingdays', Specifies the number of average working days per year. This should correlateto the specified workinghours and vacation. It affects the conversion ofworking hours, working days, working weeks, working months and working yearsinto each other.When public holidays and vacations are disregarded, this value should be equalto the number of working days per week times 52.1428 (the average number ofweeks per year). E. g. for a culture with 5 working days it is 260.714 (thedefault), for 6 working days it is 312.8568 and for 7 working days it is365. 2400: ) 2401: arg(1, 'days', 'Number of average working days for a year') 2402: end
# File lib/TjpSyntaxRules.rb, line 2528 2528: def rule_projectBodyInclude 2529: pattern(%( _include !includeFile !projectBodyAttributes . )) 2530: lastSyntaxToken(1) 2531: doc('include.project', Includes the specified file name as if its contents would be writteninstead of the include property. The only exception is the includestatement itself. When the included files contains other includestatements or report definitions, the filenames are relative to filewhere they are defined in.The included files may only contain content that may be present in a projectheader section.If the include statement is the last statement in the file it must have the option block. The option block can be empty, but the curly braces must be present. 2532: ) 2533: end
# File lib/TjpSyntaxRules.rb, line 2448 2448: def rule_projectDeclaration 2449: pattern(%( !projectHeader !projectBody ), lambda { 2450: @val[0] 2451: }) 2452: doc('project', The project property is mandatory and should be the first propertyin a project file. It is used to capture basic attributes such asthe project id, name and the expected time frame. 2453: ) 2454: end
# File lib/TjpSyntaxRules.rb, line 2460 2460: def rule_projectHeader 2461: pattern(%( _project !optionalID $STRING !optionalVersion !interval ), lambda { 2462: @project = Project.new(@val[1], @val[2], @val[3], @messageHandler) 2463: @project['start'] = @val[4].start 2464: @project['end'] = @val[4].end 2465: @projectId = @val[1] 2466: setGlobalMacros 2467: @property = nil 2468: @reportCounter = 0 2469: @project 2470: }) 2471: arg(2, 'name', 'The name of the project') 2472: end
# File lib/TjpSyntaxRules.rb, line 2474 2474: def rule_projectIDs 2475: pattern(%( $ID !moreProjectIDs ), lambda { 2476: [ @val[0] ] + (@val[1].nil? ? [] : @val[1]) 2477: }) 2478: end
# File lib/TjpSyntaxRules.rb, line 2505 2505: def rule_projectProlog 2506: optional 2507: repeatable 2508: pattern(%( !prologInclude )) 2509: pattern(%( !macro )) 2510: end
# File lib/TjpSyntaxRules.rb, line 2512 2512: def rule_projectProperties 2513: # This rule is not defining actual syntax. It's only used for the 2514: # documentation. 2515: pattern(%( !projectPropertiesBody )) 2516: doc('properties', The project properties. Every project must consists of at least one task. The other properties are optional. To save the scheduled data at least one output generating property should be used. 2517: ) 2518: end
# File lib/TjpSyntaxRules.rb, line 2522 2522: def rule_projectPropertiesBody 2523: # This rule is not defining actual syntax. It's only used for the 2524: # documentation. 2525: optionsRule('properties') 2526: end
# File lib/TjpSyntaxRules.rb, line 2480 2480: def rule_projection 2481: optionsRule('projectionAttributes') 2482: end
# File lib/TjpSyntaxRules.rb, line 2484 2484: def rule_projectionAttributes 2485: optional 2486: repeatable 2487: pattern(%( _sloppy ), lambda { 2488: @property.set('strict', false) 2489: }) 2490: doc('sloppy.projection', In sloppy mode tasks with no bookings will be filled from the original start. 2491: ) 2492: 2493: pattern(%( _strict ), lambda { 2494: @property.set('strict', true) 2495: }) 2496: doc('strict.projection', In strict mode all tasks will be filled starting with the current date. Nobookings will be added prior to the current date. 2497: ) 2498: end
# File lib/TjpSyntaxRules.rb, line 2546 2546: def rule_prologInclude 2547: pattern(%( _include !includeFile !projectProlog . )) 2548: lastSyntaxToken(1) 2549: doc('include.macro', Includes the specified file name as if its contents would be writteninstead of the include property. The only exception is the includestatement itself. When the included files contains other includestatements or report definitions, the filenames are relative to filewhere they are defined in.The included file may only contain macro definitions. 2550: ) 2551: end
# File lib/TjpSyntaxRules.rb, line 2561 2561: def rule_properties 2562: pattern(%( !propertiesBody )) 2563: end
# File lib/TjpSyntaxRules.rb, line 2565 2565: def rule_propertiesBody 2566: repeatable 2567: optional 2568: 2569: pattern(%( !account )) 2570: 2571: pattern(%( _copyright $STRING ), lambda { 2572: @project['copyright'] = @val[1] 2573: }) 2574: doc('copyright', Set a copyright notice for the project file and its content. This copyright notice will be added to all reports that can support it. 2575: ) 2576: example('Caption', '2') 2577: 2578: pattern(%( !balance ), lambda { 2579: @project['costAccount'] = @val[0][0] 2580: @project['revenueAccount'] = @val[0][1] 2581: }) 2582: 2583: pattern(%( !export )) 2584: 2585: pattern(%( _flags !declareFlagList ), lambda { 2586: unless @project['flags'].include?(@val[1]) 2587: @project['flags'] += @val[1] 2588: end 2589: }) 2590: doc('flags', Declare one or more flag for later use. Flags can be used to mark tasks, resources or other properties to filter them in reports. 2591: ) 2592: 2593: pattern(%( !propertiesInclude )) 2594: 2595: pattern(%( !limits ), lambda { 2596: @project['limits'] = @val[0] 2597: }) 2598: doc('limits', Set per-interval allocation limits for the following resource definitions.The limits can be overwritten in each resource definition and the globallimits can be changed later. 2599: ) 2600: 2601: pattern(%( !macro )) 2602: 2603: pattern(%( !nikuReport )) 2604: 2605: pattern(%( !navigator )) 2606: 2607: pattern(%( _projectid $ID ), lambda { 2608: @project['projectids'] << @val[1] 2609: @project['projectids'].uniq! 2610: @project['projectid'] = @projectId = @val[1] 2611: }) 2612: doc('projectid', This declares a new project id and activates it. All subsequenttask definitions will inherit this ID. The tasks of a project can havedifferent IDs. This is particularly helpful if the project is merged fromseveral sub projects that each have their own ID. 2613: ) 2614: 2615: pattern(%( _projectids !projectIDs ), lambda { 2616: @project['projectids'] += @val[1] 2617: @project['projectids'].uniq! 2618: }) 2619: doc('projectids', Declares a list of project IDs. When an include file that was generated from another project brings different project IDs, these need to be declared first. 2620: ) 2621: 2622: pattern(%( _rate !number ), lambda { 2623: @project['rate'] = @val[1].to_f 2624: }) 2625: doc('rate', Set the default rate for all subsequently defined resources. The rate describes the daily cost of a resource. 2626: ) 2627: 2628: pattern(%( !report )) 2629: pattern(%( !resource )) 2630: pattern(%( !shift )) 2631: pattern(%( !statusSheet )) 2632: pattern(%( !statusSheetReport )) 2633: 2634: pattern(%( _supplement !supplement )) 2635: doc('supplement', The supplement keyword provides a mechanism to add more attributes to alreadydefined accounts, tasks or resources. The additional attributes must obey thesame rules as in regular task or resource definitions and must be enclosed bycurly braces.This construct is primarily meant for situations where the information about atask or resource is split over several files. E. g. the vacation dates for theresources may be in a separate file that was generated by some other tool. 2636: ) 2637: example('Supplement') 2638: 2639: pattern(%( !task )) 2640: pattern(%( !timeSheet )) 2641: pattern(%( !timeSheetReport )) 2642: pattern(%( _vacation !vacationName !intervals ), lambda { 2643: begin 2644: @project['vacations'] = @project['vacations'] + @val[2] 2645: rescue AttributeOverwrite 2646: end 2647: }) 2648: doc('vacation', Specify a global vacation period for all subsequently defined resources. Avacation can also be used to block out the time before a resource joined orafter it left. For employees changing their work schedule from full-time topart-time, or vice versa, please refer to the 'Shift' property. 2649: ) 2650: arg(1, 'name', 'Name or purpose of the vacation') 2651: 2652: pattern(%( _trackingscenario !scenarioId ), lambda { 2653: @project['trackingScenarioIdx'] = @val[1] 2654: }) 2655: doc('trackingscenario', Specifies which scenario should be used for time sheet reports. By default,the top-level scenario will be used. 2656: ) 2657: example('TimeSheet1', '2') 2658: end
# File lib/TjpSyntaxRules.rb, line 2694 2694: def rule_propertiesFile 2695: pattern(%( !propertiesBody . )) 2696: end
# File lib/TjpSyntaxRules.rb, line 2698 2698: def rule_propertiesInclude 2699: pattern(%( _include !includeProperties !properties . ), lambda { 2700: }) 2701: doc('include.properties', Includes the specified file name as if its contents would be writteninstead of the include property. The only exception is the includestatement itself. When the included files contains other includestatements or report definitions, the filenames are relative to filewhere they are defined in. include commands can be used in the projectheader, at global scope or between property declarations of tasks,resources, and accounts.For technical reasons you have to supply the optional pair of curlybrackets if the include is followed immediately by a macro call thatis defined within the included file. 2702: ) 2703: end
# File lib/TjpSyntaxRules.rb, line 2717 2717: def rule_purge 2718: pattern(%( _purge $ID ), lambda { 2719: if (attributeDefinition = @property.attributeDefinition(@val[1])).nil? 2720: error('purge_unknown_id', 2721: "#{@val[1]} is not a known attribute for this property", 2722: @sourceFileInfo[1]) 2723: end 2724: if attributeDefinition.scenarioSpecific 2725: attr = @property[@val[1], 0] 2726: else 2727: attr = @propert.get(@val[1]) 2728: end 2729: unless attr.is_a?(Array) 2730: error('purge_no_list', 2731: "#{@val[1]} is not a list attribute. Only those can be purged.", 2732: @sourceFileInfo[1]) 2733: end 2734: @property.getAttr(@val[1], @scenarioIdx).reset 2735: }) 2736: doc('purge', List attributes, like regular attributes, can inherit their values from theenclosing property. By defining more values for such a list attribute, the newvalues will be appended to the existing ones. The purge statement clears sucha list atribute. A subsequent definition for the attribute within the propertywill then add their values to an empty list. 2737: ) 2738: arg(1, 'attribute', 'Any name of a list attribute') 2739: end
# File lib/TjpSyntaxRules.rb, line 2747 2747: def rule_referenceAttributes 2748: optional 2749: repeatable 2750: pattern(%( _label $STRING ), lambda { 2751: @val[1] 2752: }) 2753: end
# File lib/TjpSyntaxRules.rb, line 2755 2755: def rule_referenceBody 2756: optionsRule('referenceAttributes') 2757: end
# File lib/TjpSyntaxRules.rb, line 2759 2759: def rule_relativeId 2760: pattern(%( _! !moreBangs !idOrAbsoluteId ), lambda { 2761: str = '!' 2762: if @val[1] 2763: @val[1].each { |bang| str += bang } 2764: end 2765: str += @val[2] 2766: str 2767: }) 2768: end
# File lib/TjpSyntaxRules.rb, line 2770 2770: def rule_report 2771: pattern(%( !reportHeader !reportBody ), lambda { 2772: @property = @property.parent 2773: }) 2774: doc('report', Reports are used to store and vizualize the results of a scheduled project.The content, the output format and the appearance of a report can be adjustedwith report attributes. Reports can be nested to create structured documenttrees. As with other properties, the resource attributes can be inherited fromthe enclosing report or the project.By default, report definitions do not generate any files. With more complexprojects, most report definitions will be used to describe elements ofcomposed reports. If you want to generate a file from this report, you mustspecify the list of [[formats]] that you want to generate. The report namewill then be used as a base name to create the file. The suffix will beappended based on the generated format.Reports have a local name space. All IDs must be unique within the reportsthat belong to the same enclosing report. To reference a report for inclusioninto another report, you need to specify the full report ID. This is composedof the report ID, prefixed by a dot-separated list of all parent report IDs. 2775: ) 2776: also(%( resourcereport taskreport textreport )) 2777: end
# File lib/TjpSyntaxRules.rb, line 3174 3174: def rule_reportAttributes 3175: optional 3176: repeatable 3177: 3178: pattern(%( !balance ), lambda { 3179: @property.set('costAccount', @val[0][0]) 3180: @property.set('revenueAccount', @val[0][1]) 3181: }) 3182: 3183: pattern(%( _caption $STRING ), lambda { 3184: @property.set('caption', newRichText(@val[1], @sourceFileInfo[1])) 3185: }) 3186: doc('caption', The caption will be embedded in the footer of the table or data segment. Thetext will be interpreted as [[Rich_Text_Attributes|Rich Text]]. 3187: ) 3188: arg(1, 'text', 'The caption text.') 3189: example('Caption', '1') 3190: 3191: pattern(%( _center $STRING ), lambda { 3192: @property.set('center', newRichText(@val[1], @sourceFileInfo[1])) 3193: }) 3194: doc('center', This attribute defines the center section of the [[textreport]]. The text willbe interpreted as [[Rich_Text_Attributes|Rich Text]]. 3195: ) 3196: arg(1, 'text', 'The text') 3197: 3198: pattern(%( _columns !columnDef !moreColumnDef ), lambda { 3199: columns = [ @val[1] ] 3200: columns += @val[2] if @val[2] 3201: @property.set('columns', columns) 3202: }) 3203: doc('columns', Specifies which columns shall be included in a report. Some columns showvalues that are constant over the course of the project. Other columns showcalculated values that depend on the time period that was chosen for thereport. 3204: ) 3205: 3206: pattern(%( !reportEnd )) 3207: 3208: pattern(%( _epilog $STRING ), lambda { 3209: @property.set('epilog', newRichText(@val[1], @sourceFileInfo[1])) 3210: }) 3211: doc('epilog', Define a text section that is printed right after the actual report data. Thetext will be interpreted as [[Rich_Text_Attributes|Rich Text]]. 3212: ) 3213: also(%( footer header prolog )) 3214: 3215: pattern(%( !flags )) 3216: doc('flags.report', Attach a set of flags. The flags can be used in logical expressions to filterproperties from the reports. 3217: ) 3218: 3219: pattern(%( _footer $STRING ), lambda { 3220: @property.set('footer', newRichText(@val[1], @sourceFileInfo[1])) 3221: }) 3222: doc('footer', Define a text section that is put at the bottom of the report. Thetext will be interpreted as [[Rich_Text_Attributes|Rich Text]]. 3223: ) 3224: also(%( epilog header prolog )) 3225: 3226: pattern(%( !formats )) 3227: 3228: pattern(%( _header $STRING ), lambda { 3229: @property.set('header', newRichText(@val[1], @sourceFileInfo[1])) 3230: }) 3231: doc('header', Define a text section that is put at the top of the report. Thetext will be interpreted as [[Rich_Text_Attributes|Rich Text]]. 3232: ) 3233: also(%( epilog footer prolog )) 3234: 3235: pattern(%( !headline )) 3236: pattern(%( !hideresource )) 3237: 3238: pattern(%( !hidetask )) 3239: 3240: pattern(%( _left $STRING ), lambda { 3241: @property.set('left', newRichText(@val[1], @sourceFileInfo[1])) 3242: }) 3243: doc('left', This attribute defines the left margin section of the [[textreport]]. The textwill be interpreted as [[Rich_Text_Attributes|Rich Text]]. The margin will notspan the [[header]] or [[footer]] sections. 3244: ) 3245: 3246: pattern(%( _loadunit !loadunit ), lambda { 3247: @property.set('loadUnit', @val[1]) 3248: }) 3249: doc('loadunit', Determines what unit should be used to display all load values in this report. 3250: ) 3251: 3252: pattern(%( !reportPeriod )) 3253: 3254: pattern(%( _prolog $STRING ), lambda { 3255: @property.set('prolog', newRichText(@val[1], @sourceFileInfo[1])) 3256: }) 3257: doc('prolog', Define a text section that is printed right before the actual report data. Thetext will be interpreted as [[Rich_Text_Attributes|Rich Text]]. 3258: ) 3259: also(%( epilog footer header )) 3260: 3261: pattern(%( _opennodes !nodeIdList ), lambda { 3262: @property.set('openNodes', @val[1]) 3263: }) 3264: doc('opennodes', 'For internal use only!') 3265: 3266: pattern(%( !report )) 3267: 3268: pattern(%( _right $STRING ), lambda { 3269: @property.set('right', newRichText(@val[1], @sourceFileInfo[1])) 3270: }) 3271: doc('right', This attribute defines the right margin section of the [[textreport]]. The textwill be interpreted as [[Rich_Text_Attributes|Rich Text]]. The margin will notspan the [[header]] or [[footer]] sections. 3272: ) 3273: 3274: pattern(%( _rollupresource !logicalExpression ), lambda { 3275: @property.set('rollupResource', @val[1]) 3276: }) 3277: doc('rollupresource', Do not show sub-resources of resources that match the specified logicalexpression. 3278: ) 3279: example('RollupResource') 3280: 3281: pattern(%( _rolluptask !logicalExpression ), lambda { 3282: @property.set('rollupTask', @val[1]) 3283: }) 3284: doc('rolluptask', Do not show sub-tasks of tasks that match the specified logical expression. 3285: ) 3286: 3287: pattern(%( _scenarios !scenarioIdList ), lambda { 3288: # Don't include disabled scenarios in the report 3289: @val[1].delete_if { |sc| !@project.scenario(sc).get('enabled') } 3290: @property.set('scenarios', @val[1]) 3291: }) 3292: doc('scenarios', List of scenarios that should be included in the report. 3293: ) 3294: 3295: pattern(%( _selfcontained !yesNo ), lambda { 3296: @property.set('selfcontained', @val[1]) 3297: }) 3298: doc('selfcontained', Try to generate selfcontained output files when the format supports this. E.g. for HTML reports, the style sheet will be included and no icons will beused. 3299: ) 3300: 3301: pattern(%( !sortResources )) 3302: pattern(%( !sortTasks )) 3303: 3304: pattern(%( !reportStart )) 3305: 3306: pattern(%( _resourceroot !resourceId), lambda { 3307: @property.set('resourceRoot', @val[1]) 3308: }) 3309: doc('resourceroot', Only resources below the specified root-level resources are exported. Theexported resources will have the ID of the root-level resource stripped fromtheir ID, so that the sub-resourcess of the root-level resource becometop-level resources in the report file. 3310: ) 3311: example('ResourceRoot') 3312: 3313: pattern(%( _taskroot !taskId), lambda { 3314: @property.set('taskRoot', @val[1]) 3315: }) 3316: doc('taskroot', Only tasks below the specified root-level tasks are exported. The exportedtasks will have the ID of the root-level task stripped from their ID, so thatthe sub-tasks of the root-level task become top-level tasks in the reportfile. 3317: ) 3318: example('TaskRoot') 3319: 3320: pattern(%( !timeformat ), lambda { 3321: @property.set('timeFormat', @val[0]) 3322: }) 3323: 3324: pattern(%( !reportTitle )) 3325: end
# File lib/TjpSyntaxRules.rb, line 3451 3451: def rule_reportBody 3452: optionsRule('reportAttributes') 3453: end
# File lib/TjpSyntaxRules.rb, line 3384 3384: def rule_reportEnd 3385: pattern(%( _end !date ), lambda { 3386: if @val[1] < @property.get('start') 3387: error('report_end', 3388: "End date must be before start date #{@property.get('start')}", 3389: @sourceFileInfo[1]) 3390: end 3391: @property.set('end', @val[1]) 3392: }) 3393: doc('end.report', Specifies the end date of the report. In task reports only tasks that startbefore this end date are listed. 3394: ) 3395: example('Export', '2') 3396: end
# File lib/TjpSyntaxRules.rb, line 3455 3455: def rule_reportHeader 3456: pattern(%( !reportType !optionalID $STRING ), lambda { 3457: if @property.nil? && !@reportprefix.empty? 3458: @property = @project.report(@reportprefix) 3459: end 3460: if @val[1] 3461: id = (@property ? @property.fullId + '.' : '') + @val[1] 3462: if @project.report(id) 3463: error('report_exists', "report #{id} has already been defined.", 3464: @sourceFileInfo[1], @property) 3465: end 3466: end 3467: @property = Report.new(@project, @val[1], @val[2], @property) 3468: @property.sourceFileInfo = @sourceFileInfo[0] 3469: @property.inheritAttributes 3470: case @val[0] 3471: when 'taskreport' 3472: @property.typeSpec = :taskreport 3473: unless @property.modified?('columns') 3474: # Set the default columns for this report. 3475: %( wbs name start end effort chart ).each do |col| 3476: @property.get('columns') << 3477: TableColumnDefinition.new(col, columnTitle(col)) 3478: end 3479: end 3480: # Show all tasks, sorted by tree, start-up, seqno-up. 3481: unless @property.modified?('hideTask') 3482: @property.set('hideTask', 3483: LogicalExpression.new(LogicalOperation.new(0))) 3484: end 3485: unless @property.modified?('softTask') 3486: @property.set('sortTasks', 3487: [ [ 'tree', true, 1 ], 3488: [ 'start', true, 0 ], 3489: [ 'seqno', true, 1 ] ]) 3490: end 3491: # Show no resources, but set sorting to id-up. 3492: unless @property.modified?('hideResource') 3493: @property.set('hideResource', 3494: LogicalExpression.new(LogicalOperation.new(1))) 3495: end 3496: unless @property.modified?('sortResources') 3497: @property.set('sortResources', [ [ 'id', true, 1 ] ]) 3498: end 3499: when 'resourcereport' 3500: @property.typeSpec = :resourcereport 3501: if @property.modified?('columns') 3502: # Set the default columns for this report. 3503: %( no name ).each do |col| 3504: @property.get('columns') << 3505: TableColumnDefinition.new(col, columnTitle(col)) 3506: end 3507: end 3508: # Show all resources, sorted by tree and id-up. 3509: unless @property.modified?('hideResource') 3510: @property.set('hideResource', 3511: LogicalExpression.new(LogicalOperation.new(0))) 3512: end 3513: unless @property.modified?('sortResources') 3514: @property.set('sortResources', [ [ 'tree', true, 1 ], 3515: [ 'id', true, 1 ] ]) 3516: end 3517: # Hide all resources, but set sorting to tree, start-up, seqno-up. 3518: unless @property.modified?('hideTask') 3519: @property.set('hideTask', 3520: LogicalExpression.new(LogicalOperation.new(1))) 3521: end 3522: unless @property.modified?('sortTasks') 3523: @property.set('sortTasks', 3524: [ [ 'tree', true, 1 ], 3525: [ 'start', true, 0 ], 3526: [ 'seqno', true, 1 ] ]) 3527: end 3528: when 'textreport' 3529: @property.typeSpec = :textreport 3530: else 3531: raise "Unsupported report type #{@val[0]}" 3532: end 3533: }) 3534: arg(2, 'name', The name of the report. This will be the base name for generated output files.The suffix will depend on the specified [[formats]].It will also be used innavigation bars. 3535: ) 3536: end
# File lib/TjpSyntaxRules.rb, line 3400 3400: def rule_reportId 3401: pattern(%( !reportIdUnverifd ), lambda { 3402: id = @val[0] 3403: if @property && @property.is_a?(Report) 3404: id = @property.fullId + '.' + id 3405: else 3406: id = @reportprefix + '.' + id unless @reportprefix.empty? 3407: end 3408: # In case we have a nested supplement, we need to prepend the parent ID. 3409: if (report = @project.report(id)).nil? 3410: error('report_id_expected', "#{id} is not a defined report.", 3411: @sourceFileInfo[0]) 3412: end 3413: report 3414: }) 3415: arg(0, 'report', 'The ID of a defined report') 3416: end
# File lib/TjpSyntaxRules.rb, line 3418 3418: def rule_reportIdUnverifd 3419: singlePattern('$ABSOLUTE_ID') 3420: singlePattern('$ID') 3421: end
# File lib/TjpSyntaxRules.rb, line 3423 3423: def rule_reportPeriod 3424: pattern(%( _period !interval ), lambda { 3425: @property.set('start', @val[1].start) 3426: @property.set('end', @val[1].end) 3427: }) 3428: doc('period.report', This property is a shortcut for setting the start and end property at thesame time. 3429: ) 3430: end
# File lib/TjpSyntaxRules.rb, line 3435 3435: def rule_reportStart 3436: pattern(%( _start !date ), lambda { 3437: if @val[1] > @property.get('end') 3438: error('report_start', 3439: "Start date must be before end date #{@property.get('end')}", 3440: @sourceFileInfo[1]) 3441: end 3442: @property.set('start', @val[1]) 3443: }) 3444: doc('start.report', Specifies the start date of the report. In task reports only tasks that endafter this end date are listed. 3445: ) 3446: end
# File lib/TjpSyntaxRules.rb, line 3542 3542: def rule_reportTitle 3543: pattern(%( _title $STRING ), lambda { 3544: @property.set('title', @val[1]) 3545: }) 3546: doc('title', The title of the report will be used in external references to the report. Itwill not show up in the reports directly. It's used e. g. by [[navigator]]. 3547: ) 3548: end
# File lib/TjpSyntaxRules.rb, line 3553 3553: def rule_reportType 3554: singlePattern('_resourcereport') 3555: doc('resourcereport', The report lists resources and their respective values in a table. The taskthat are the resources are allocated to can be listed as well. To reduce thelist of included resources, you can use the [[hideresource]],[[rollupresource]] or [[resourceroot]] attributes. The order of the task canbe controlled with [[sortresources]]. If the first sorting criteria is treesorting, the parent resources will always be included to form the tree.Tree sorting is the default. You need to change it if you do not want certainparent resources to be included in the report.The tasks that the resources are allocated to can be included as well. Use the[[hidetask]] attribute for this. See [[report]] for a complete list ofattributes and the full syntax for this keyword. 3556: ) 3557: singlePattern('_taskreport') 3558: doc('taskreport', The report lists tasks and their respective values in a table. To reduce thelist of included tasks, you can use the [[hidetask]], [[rolluptask]] or[[taskroot]] attributes. The order of the task can be controlled with[[sorttasks]]. If the first sorting criteria is tree sorting, the parent taskswill always be included to form the tree. Tree sorting is the default. Youneed to change it if you do not want certain parent tasks to be included inthe report.The resources that are allocated to each task can be listed as well. Use the[[hideresource]] attribute for this. See [[report]] for a complete list ofattributes and the full syntax for this keyword. 3559: ) 3560: singlePattern('_textreport') 3561: doc('textreport', This report consists of 5 RichText sections, a header, a center section with aleft and right margin and a footer. The sections may contain the output ofother defined reports. See [[report]] for further details. 3562: ) 3563: end
# File lib/TjpSyntaxRules.rb, line 2798 2798: def rule_reportableAttributes 2799: singlePattern('_alert') 2800: descr(The alert level of the property that was reported with the date closest to theend date of the report. Container properties that don't have their own alertlevel reported with a date equal or newer than the alert levels of all theirsub properties will get the highest alert level of their direct subproperties. 2801: ) 2802: 2803: singlePattern('_alertmessages') 2804: descr(The headlines, the summary and the details of the message from the journalentries that caused the current alert level to be larger than the defaul levelfor this task or any of its sub tasks. 2805: ) 2806: 2807: singlePattern('_alertsummaries') 2808: descr(The headlines and the summary message from the journal entries that caused thecurrent alert level to be larger than the default for this task or any of itssub tasks. 2809: ) 2810: 2811: singlePattern('_alerttrend') 2812: descr(Shows how the alert level at the end of the report period compares to thealert level at the begining of the report period. Possible values are up, downor flat. 2813: ) 2814: 2815: singlePattern('_chart') 2816: descr(A Gantt chart. This column type requires all lines to have the same fixedheight. This does not work well with rich text columns in some browsers. Someshow a scrollbar for the compressed table cells, others don't. It isrecommended, that you don't use rich text columns in conjuction with the chartcolumn. 2817: ) 2818: 2819: singlePattern('_complete') 2820: descr('The completion degree of a task') 2821: 2822: pattern([ '_completed' ], lambda { 2823: 'complete' 2824: }) 2825: descr('Deprecated alias for complete') 2826: 2827: singlePattern('_criticalness') 2828: descr('A measure for how much effort the resource is allocated for, or' + 2829: 'how strained the allocated resources of a task are') 2830: 2831: singlePattern('_cost') 2832: descr(The cost of the task or resource. The use of this column requires that a costaccount has been set for the report using the [[balance]] attribute. 2833: ) 2834: 2835: singlePattern('_daily') 2836: descr('A group of columns with one column for each day') 2837: 2838: singlePattern('_directreports') 2839: descr(The resources that have this resource assigned as manager.The list can be customized by the [listmode.column listmode] attribute. Thefollowing modes are supported:# ID# Name ''(This is the default)''# Name (ID)# ID: Name 2840: ) 2841: 2842: singlePattern('_duration') 2843: descr('The duration of a task') 2844: 2845: singlePattern('_duties') 2846: descr('List of tasks that the resource is allocated to') 2847: 2848: singlePattern('_efficiency') 2849: descr('Measure for how efficient a resource can perform tasks') 2850: 2851: singlePattern('_effort') 2852: descr('The allocated effort during the reporting period') 2853: 2854: singlePattern('_effortdone') 2855: descr('The already completed effort as of now') 2856: 2857: singlePattern('_effortleft') 2858: descr('The remaining allocated effort as of now') 2859: 2860: singlePattern('_email') 2861: descr('The email address of a resource') 2862: 2863: singlePattern('_end') 2864: descr('The end date of a task') 2865: 2866: singlePattern('_flags') 2867: descr('List of attached flags') 2868: 2869: singlePattern('_followers') 2870: descr(A list of tasks that depend on the current task. The list contains the names,the IDs, the date and the type of dependency. For the type the followingsymbols are used for <nowiki><dep></nowiki>.* '''<nowiki>]->[</nowiki>''': End-to-Start dependency* '''<nowiki>[->[</nowiki>''': Start-to-Start dependency* '''<nowiki>]->]</nowiki>''': End-to-End dependency* '''<nowiki>[->]</nowiki>''': Start-to-End dependencyThe list can be customized by the [listmode.column listmode] attribute. Thefollowing modes are supported:# ID <nowiki><dep></nowiki> Date# Name <nowiki><dep></nowiki> Date# Name (ID) <nowiki><dep></nowiki> Date# ID: Name <nowiki><dep></nowiki> Date# ID <nowiki><dep></nowiki># Name <nowiki><dep></nowiki># Name (ID) <nowiki><dep></nowiki># ID: Name <nowiki><dep></nowiki># ID# Name# Name (ID)# ID: Name 2871: ) 2872: 2873: singlePattern('_freetime') 2874: descr(The amount of unallocated work time of a resource during the reporting period. 2875: ) 2876: 2877: singlePattern('_freework') 2878: descr(The amount of unallocated work capacity of a resource during the reportingperiod. This is the product of unallocated work time times the efficiency ofthe resource. 2879: ) 2880: 2881: singlePattern('_fte') 2882: descr('The Full-Time-Equivalent of a resource or group') 2883: 2884: singlePattern('_headcount') 2885: descr('The headcount number of the resource or group') 2886: 2887: pattern([ '_hierarchindex' ], lambda { 2888: 'wbs' 2889: }) 2890: descr('Deprecated alias for wbs') 2891: 2892: singlePattern('_hourly') 2893: descr('A group of columns with one column for each hour') 2894: 2895: singlePattern('_id') 2896: descr('The id of the item') 2897: 2898: singlePattern('_index') 2899: descr('The index of the item based on the nesting hierachy') 2900: 2901: singlePattern('_journal') 2902: descr(The journal entries for the task or resource for the reported interval. 2903: ) 2904: 2905: singlePattern('_journal_sub') 2906: descr(The journal entries for the task or resource and all its subtasks or resourcesfor the reported interval. 2907: ) 2908: 2909: singlePattern('_journalmessages') 2910: descr(The headlines, the summary and the details of the message from the journalentries that caused the current alert level for this task. 2911: ) 2912: 2913: singlePattern('_journalsummaries') 2914: descr(The headlines and the summary message from the journal entries that caused thecurrent alert level for this task. 2915: ) 2916: 2917: singlePattern('_line') 2918: descr('The line number in the report') 2919: 2920: singlePattern('_managers') 2921: descr(A list of managers that the resource reports to.The list can be customized by the [listmode.column listmode] attribute. Thefollowing modes are supported:# ID# Name ''(This is the default)''# Name (ID)# ID: Name 2922: ) 2923: 2924: singlePattern('_maxend') 2925: descr('The latest allowed end of a task') 2926: 2927: singlePattern('_maxstart') 2928: descr('The lastest allowed start of a task') 2929: 2930: singlePattern('_minend') 2931: descr('The earliest allowed end of a task') 2932: 2933: singlePattern('_minstart') 2934: descr('The earliest allowed start of a task') 2935: 2936: singlePattern('_monthly') 2937: descr('A group of columns with one column for each month') 2938: 2939: singlePattern('_no') 2940: descr('The object line number in the report (Cannot be used for sorting!)') 2941: 2942: singlePattern('_name') 2943: descr('The name or description of the item') 2944: 2945: singlePattern('_note') 2946: descr('The note attached to a task') 2947: 2948: singlePattern('_pathcriticalness') 2949: descr('The criticalness of the task with respect to all the paths that ' + 2950: 'it is a part of.') 2951: 2952: singlePattern('_precursors') 2953: descr(A list of tasks the current task depends on. The list contains the names, theIDs, the date and the type of dependency. For the type the following symbolsare used* '''<nowiki>]->[</nowiki>''': End-to-Start dependency* '''<nowiki>[->[</nowiki>''': Start-to-Start dependency* '''<nowiki>]->]</nowiki>''': End-to-End dependency* '''<nowiki>[->]</nowiki>''': Start-to-End dependencyThe list can be customized by the [listmode.column listmode] attribute. Thefollowing modes are supported:# ID <nowiki><dep></nowiki> Date# Name <nowiki><dep></nowiki> Date# Name (ID) <nowiki><dep></nowiki> Date# ID: Name <nowiki><dep></nowiki> Date# ID <nowiki><dep></nowiki># Name <nowiki><dep></nowiki># Name (ID) <nowiki><dep></nowiki># ID: Name <nowiki><dep></nowiki># ID# Name# Name (ID)# ID: Name 2954: ) 2955: 2956: singlePattern('_priority') 2957: descr('The priority of a task') 2958: 2959: singlePattern('_quarterly') 2960: descr('A group of columns with one column for each quarter') 2961: 2962: singlePattern('_rate') 2963: descr('The daily cost of a resource.') 2964: 2965: singlePattern('_reports') 2966: descr(All resources that have this resource assigned as a direct or indirect manager.The list can be customized by the [listmode.column listmode] attribute. Thefollowing modes are supported:# ID# Name ''(This is the default)''# Name (ID)# ID: Name 2967: ) 2968: 2969: singlePattern('_resources') 2970: descr(A list of resources that are assigned to the task in the report time frame.The list can be customized by the [listmode.column listmode] attribute. Thefollowing modes are supported:# ID# Name ''(This is the default)''# Name (ID)# ID: Name 2971: ) 2972: 2973: singlePattern('_responsible') 2974: descr(The responsible people for this task.The list can be customized by the [listmode.column listmode] attribute. Thefollowing modes are supported:# ID# Name ''(This is the default)''# Name (ID)# ID: Name 2975: ) 2976: 2977: singlePattern('_revenue') 2978: descr(The revenue of the task or resource. The use of this column requires that arevenue account has been set for the report using the [[balance]] attribute. 2979: ) 2980: 2981: singlePattern('_scenario') 2982: descr('The name of the scenario') 2983: 2984: singlePattern('_seqno') 2985: descr('The index of the item based on the declaration order') 2986: 2987: singlePattern('_start') 2988: descr('The start date of the task') 2989: 2990: singlePattern('_status') 2991: descr(The status of a task. It is determined based on the current date or the datespecified by [[now]]. 2992: ) 2993: 2994: singlePattern('_targets') 2995: descr(A list of milestones that depend on the current task. For container tasks itwill also include the targets of the child tasks.The list can be customized by the [listmode.column listmode] attribute. Thefollowing modes are supported:# ID# Name# Name (ID)# ID: Name# ID (Date)# Name (Date) ''(This is the default)''# Name (ID) Date# ID: Name Date 2996: ) 2997: 2998: singlePattern('_wbs') 2999: descr('The hierarchical or work breakdown structure index') 3000: 3001: singlePattern('_weekly') 3002: descr('A group of columns with one column for each week') 3003: 3004: singlePattern('_yearly') 3005: descr('A group of columns with one column for each year') 3006: 3007: end
# File lib/TjpSyntaxRules.rb, line 3594 3594: def rule_resource 3595: pattern(%( !resourceHeader !resourceBody ), lambda { 3596: @property = @property.parent 3597: }) 3598: doc('resource', Tasks that have an effort specification need to have at least one resourceassigned to do the work. Use this property to define resources or groups ofresources.Resources have a global name space. All IDs must be unique within the resourcesof the project. 3599: ) 3600: end
# File lib/TjpSyntaxRules.rb, line 3609 3609: def rule_resourceAttributes 3610: repeatable 3611: optional 3612: pattern(%( _email $STRING ), lambda { 3613: @property.set('email', @val[1]) 3614: }) 3615: doc('email', 3616: 'The email address of the resource.') 3617: 3618: pattern(%( !journalEntry )) 3619: pattern(%( !purge )) 3620: pattern(%( !resource )) 3621: pattern(%( !resourceScenarioAttributes )) 3622: pattern(%( !scenarioIdCol !resourceScenarioAttributes ), lambda { 3623: @scenarioIdx = 0 3624: }) 3625: 3626: pattern(%( _supplement !resourceId !resourceBody ), lambda { 3627: @property = @property.parent 3628: }) 3629: doc('supplement.resource', The supplement keyword provides a mechanism to add more attributes to alreadydefined resources. The additional attributes must obey the same rules as inregular resource definitions and must be enclosed by curly braces.This construct is primarily meant for situations where the information about aresource is split over several files. E. g. the vacation dates for theresources may be in a separate file that was generated by some other tool. 3630: ) 3631: example('Supplement', 'resource') 3632: 3633: # Other attributes will be added automatically. 3634: end
# File lib/TjpSyntaxRules.rb, line 3644 3644: def rule_resourceBody 3645: optionsRule('resourceAttributes') 3646: end
# File lib/TjpSyntaxRules.rb, line 3648 3648: def rule_resourceBooking 3649: pattern(%( !resourceBookingHeader !bookingBody ), lambda { 3650: @val[0].task.addBooking(@scenarioIdx, @val[0]) 3651: }) 3652: end
# File lib/TjpSyntaxRules.rb, line 3654 3654: def rule_resourceBookingHeader 3655: pattern(%( !taskId !valIntervals ), lambda { 3656: checkBooking(@val[0], @property) 3657: @booking = Booking.new(@property, @val[0], @val[1]) 3658: @booking.sourceFileInfo = @sourceFileInfo[0] 3659: @booking 3660: }) 3661: arg(0, 'id', 'Absolute ID of a defined task') 3662: end
# File lib/TjpSyntaxRules.rb, line 3676 3676: def rule_resourceHeader 3677: pattern(%( _resource !optionalID $STRING ), lambda { 3678: if @property.nil? && !@resourceprefix.empty? 3679: @property = @project.resource(@resourceprefix) 3680: end 3681: if @val[1] && @project.resource(@val[1]) 3682: error('resource_exists', 3683: "Resource #{@val[1]} has already been defined.", 3684: @sourceFileInfo[1], @property) 3685: end 3686: @property = Resource.new(@project, @val[1], @val[2], @property) 3687: @property.sourceFileInfo = @sourceFileInfo[0] 3688: @property.inheritAttributes 3689: @scenarioIdx = 0 3690: }) 3691: # arg(1, 'id', <<'EOT' 3692: #The ID of the resource. Resources have a global name space. The ID must be 3693: #unique within the whole project. 3694: #EOT 3695: # ) 3696: arg(2, 'name', 'The name of the resource') 3697: end
# File lib/TjpSyntaxRules.rb, line 3664 3664: def rule_resourceId 3665: pattern(%( $ID ), lambda { 3666: id = (@resourceprefix.empty? ? '' : @resourceprefix + '.') + @val[0] 3667: if (resource = @project.resource(id)).nil? 3668: error('resource_id_expected', "#{id} is not a defined resource.", 3669: @sourceFileInfo[0]) 3670: end 3671: resource 3672: }) 3673: arg(0, 'resource', 'The ID of a defined resource') 3674: end
# File lib/TjpSyntaxRules.rb, line 3699 3699: def rule_resourceLeafList 3700: pattern(%( !leafResourceId !moreLeafResources ), lambda { 3701: [ @val[0] ] + (@val[1].nil? ? [] : @val[1]) 3702: }) 3703: end
# File lib/TjpSyntaxRules.rb, line 3705 3705: def rule_resourceList 3706: listRule('moreResources', '!resourceId') 3707: end
# File lib/TjpSyntaxRules.rb, line 3709 3709: def rule_resourceScenarioAttributes 3710: pattern(%( _efficiency !number ), lambda { 3711: @property['efficiency', @scenarioIdx] = @val[1] 3712: }) 3713: doc('efficiency', The efficiency of a resource can be used for two purposes. First you can useit as a crude way to model a team. A team of 5 people should have anefficiency of 5.0. Keep in mind that you cannot track the members of the teamindividually if you use this feature. They always act as a group.The other use is to model performance variations between your resources. Again, this is a fairly crude mechanism and should be used with care. A resource that isn't every good at some task might be pretty good at another. This can't be taken into account as the resource efficiency can only set globally for all tasks.All resources that do not contribute effort to the task, should have anefficiency of 0.0. A typical example would be a conference room. It's necessary for a meeting, but it does not contribute any work. 3714: ) 3715: example('Efficiency') 3716: pattern(%( !flags )) 3717: doc('flags.resource', Attach a set of flags. The flags can be used in logical expressions to filterproperties from the reports. 3718: ) 3719: 3720: pattern(%( _booking !resourceBooking )) 3721: doc('booking', The booking attribute can be used to report completed work. This can be partof the necessary effort or the whole effort. When the scenario is scheduled in[[projection]] mode, TaskJuggler assumes that only the work reported withbookings has been done up to now. It then schedules a plan for the stillmissing effort. All task with bookings must be scheduled in ''''asap'''' mode.This attribute is also used within export reports to describe the details of ascheduled project.The sloppy attribute can be used when you want to skip non-working time orother allocations automatically. If it's not given, all bookings must onlycover working time for the resource.The booking attributes is designed to capture the exact amount of completedwork. This attribute is not really intended to specify completed effort byhand. Usually, booking statements are generated by [[export]] reports. The[[sloppy.booking|sloppy]] and [[overtime.booking|overtime]] attributes areonly kludge for users who want to write them manually. 3722: ) 3723: also(%( scheduling )) 3724: example('Booking') 3725: 3726: pattern(%( !fail )) 3727: 3728: pattern(%( !limits ), lambda { 3729: @property['limits', @scenarioIdx] = @val[0] 3730: }) 3731: doc('limits.resource', Set per-interval usage limits for the resource. 3732: ) 3733: example('Limits-1', '6') 3734: 3735: pattern(%( _managers !resourceList ), lambda { 3736: @property['managers', @scenarioIdx] = 3737: @property['managers', @scenarioIdx] + @val[1] 3738: }) 3739: doc('managers', Defines one or more resources to be the manager who is responsible for thisresource. Managers must be leaf resources. This attribute does not impact thescheduling. It can only be used for documentation purposes.You must only specify direct managers here. Do not list higher level managershere. If necessary, use the [[purge]] attribute to clearinherited managers. For most use cases, there should be only one manager. ButTaskJuggler is not limited to just one manager. Dotted reporting lines can becaptured as well as long as the managers are not reporting to each other. 3740: ) 3741: also(%( statussheet )) 3742: example('Manager') 3743: 3744: 3745: pattern(%( _rate !number ), lambda { 3746: @property['rate', @scenarioIdx] = @val[1] 3747: }) 3748: doc('rate.resource', The rate specifies the daily cost of the resource. 3749: ) 3750: 3751: pattern(%( _shift !shiftAssignments )) 3752: doc('shift.resource', This keyword has been deprecated. Please use [[shifts.resource|shifts(resource)]] instead. 3753: ) 3754: 3755: pattern(%( _shifts !shiftAssignments )) 3756: doc('shifts.resource', Limits the working time of a resource to a defined shift during the specifiedinterval. Multiple shifts can be defined, but shift intervals may not overlap.In case a shift is defined for a certain interval, the shift working hoursreplace the standard resource working hours for this interval. 3757: ) 3758: 3759: pattern(%( _vacation !vacationName !intervals ), lambda { 3760: begin 3761: @property['vacations', @scenarioIdx] = 3762: @property['vacations', @scenarioIdx ] + @val[2] 3763: rescue AttributeOverwrite 3764: end 3765: }) 3766: doc('vacation.resource', Specify a vacation period for the resource. It can also be used to block outthe time before a resource joined or after it left. For employees changingtheir work schedule from full-time to part-time, or vice versa, please referto the 'Shift' property. 3767: ) 3768: 3769: pattern(%( !warn )) 3770: 3771: pattern(%( !workinghoursResource )) 3772: # Other attributes will be added automatically. 3773: end
# File lib/TjpSyntaxRules.rb, line 3834 3834: def rule_scenario 3835: pattern(%( !scenarioHeader !scenarioBody ), lambda { 3836: @property = @property.parent 3837: }) 3838: doc('scenario', Defines a new project scenario. By default, the project has only one scenariocalled ''''plan''''. To do plan vs. actual comparisons or to do awhat-if-analysis, you can define a set of scenarios. There can only be onetop-level scenario. Additional scenarios are either derived from thistop-level scenario or other scenarios.Each nested scenario is a variation of the enclosing scenario. All scenariosshare the same set of properties (task, resources, etc.) but the attributesthat are listed as scenario specific may differ between the variousscenarios. A nested scenario uses all attributes from the enclosing scenariounless the user has specified a different value for this attribute.By default, the scheduler assigns resources to task beginning with the projectstart date. If the scenario is switched to projection mode, no assignmentswill be made prior to the current date or the date specified by [[now]]. Inthis case, TaskJuggler assumes, that all assignements prior to thecurrent date have been provided by [[booking]] statements. 3839: ) 3840: end
# File lib/TjpSyntaxRules.rb, line 3860 3860: def rule_scenarioAttributes 3861: optional 3862: repeatable 3863: 3864: pattern(%( _disabled ), lambda { 3865: @property.set('enabled', false) 3866: }) 3867: doc('disabled', Disable the scenario for scheduling. The default for the top-levelscenario is to be enabled. 3868: ) 3869: example('Scenario') 3870: pattern(%( _enabled ), lambda { 3871: @property.set('enabled', true) 3872: }) 3873: doc('enabled', Enable the scenario for scheduling. This is the default for the top-levelscenario. 3874: ) 3875: 3876: pattern(%( _minslackrate !number ), lambda { 3877: @property.set('minslackrate', @val[1] / 100.0) 3878: }) 3879: doc('minslackrate', Specifies the minimum percentage of slack a task path must have before it ismarked as critical. A path is any list of explicitely or implicitely connectedtasks measured from first task to last task. The slack is the time betweenstart of the first task and end of the last task that is not covered by anytask of the path.Larger values in combination with a project that uses lots of inheriteddependencies and long dependency pathes can result in very long schedulingtimes. The more slack you require, the more pathes have to be searched tillthe end. For larger projects an increase of 5% can turn a 10 second schedulingrun into a 1 hour or more scheduling run. If you need larger slack ratevalues, avoid the use of inherited dependencies.The default value is 0% which turns off the critical path detector. 3880: ) 3881: 3882: pattern(%( _projection !projection ), lambda { 3883: @property.set('projection', true) 3884: }) 3885: doc('projection', Enables the projection mode for the scenario. All tasks will be scheduledtaking the manual bookings into account. The tasks will be extended byscheduling new bookings starting with the current date until the specifiedeffort, length or duration has been reached. 3886: ) 3887: 3888: pattern(%( !scenario )) 3889: end
# File lib/TjpSyntaxRules.rb, line 3917 3917: def rule_scenarioBody 3918: optionsRule('scenarioAttributes') 3919: end
# File lib/TjpSyntaxRules.rb, line 3921 3921: def rule_scenarioHeader 3922: 3923: pattern(%( _scenario $ID $STRING ), lambda { 3924: # If this is the top-level scenario, we must delete the default scenario 3925: # first. 3926: @project.scenarios.clearProperties if @property.nil? 3927: if @project.scenario(@val[1]) 3928: error('scenario_exists', 3929: "Scenario #{@val[1]} has already been defined.", 3930: @sourceFileInfo[1]) 3931: end 3932: @property = Scenario.new(@project, @val[1], @val[2], @property) 3933: @property.inheritAttributes 3934: }) 3935: arg(1, 'id', 'The ID of the scenario') 3936: arg(2, 'name', 'The name of the scenario') 3937: end
# File lib/TjpSyntaxRules.rb, line 3939 3939: def rule_scenarioId 3940: pattern(%( $ID ), lambda { 3941: if (@scenarioIdx = @project.scenarioIdx(@val[0])).nil? 3942: error('unknown_scenario_id', "Unknown scenario: #{@val[0]}", 3943: @sourceFileInfo[0]) 3944: end 3945: @scenarioIdx 3946: }) 3947: arg(0, 'scenario', 'ID of a defined scenario') 3948: end
# File lib/TjpSyntaxRules.rb, line 3950 3950: def rule_scenarioIdCol 3951: pattern(%( $ID_WITH_COLON ), lambda { 3952: if (@scenarioIdx = @project.scenarioIdx(@val[0])).nil? 3953: error('unknown_scenario_id', "Unknown scenario: @val[0]", 3954: @sourceFileInfo[0]) 3955: end 3956: }) 3957: end
# File lib/TjpSyntaxRules.rb, line 3959 3959: def rule_scenarioIdList 3960: listRule('moreScnarioIdList', '!scenarioIdx') 3961: end
# File lib/TjpSyntaxRules.rb, line 3963 3963: def rule_scenarioIdx 3964: pattern(%( $ID ), lambda { 3965: if (scenarioIdx = @project.scenarioIdx(@val[0])).nil? 3966: error('unknown_scenario_idx', "Unknown scenario #{@val[0]}", 3967: @sourceFileInfo[0]) 3968: end 3969: scenarioIdx 3970: }) 3971: end
# File lib/TjpSyntaxRules.rb, line 3973 3973: def rule_schedulingDirection 3974: singlePattern('_alap') 3975: singlePattern('_asap') 3976: end
# File lib/TjpSyntaxRules.rb, line 3978 3978: def rule_shift 3979: pattern(%( !shiftHeader !shiftBody ), lambda { 3980: @property = @property.parent 3981: }) 3982: doc('shift', A shift combines several workhours related settings in a reusable entity.Besides the weekly working hours it can also hold information such asvacations and a time zone.Shifts have a global name space. All IDs must be unique within the shifts ofthe project. 3983: ) 3984: also(%( shifts.task shifts.resource )) 3985: end
# File lib/TjpSyntaxRules.rb, line 3994 3994: def rule_shiftAssignment 3995: pattern(%( !shiftId !intervalsOptional ), lambda { 3996: # Make sure we have a ShiftAssignment for the property. 3997: sa = @property['shifts', @scenarioIdx] || ShiftAssignments.new 3998: sa.project = @project 3999: 4000: if @val[1].nil? 4001: intervals = [ Interval.new(@project['start'], @project['end']) ] 4002: else 4003: intervals = @val[1] 4004: end 4005: intervals.each do |interval| 4006: if !sa.addAssignment(ShiftAssignment.new(@val[0].scenario(@scenarioIdx), 4007: interval)) 4008: error('shift_assignment_overlap', 4009: 'Shifts may not overlap each other.', 4010: @sourceFileInfo[0], @property) 4011: end 4012: end 4013: # Set same value again to set the 'provided' state for the attribute. 4014: begin 4015: @property['shifts', @scenarioIdx] = sa 4016: rescue AttributeOverwrite 4017: # Multiple shift assignments are a common idiom, so don't warn about 4018: # them. 4019: end 4020: }) 4021: end
# File lib/TjpSyntaxRules.rb, line 4023 4023: def rule_shiftAssignments 4024: listRule('moreShiftAssignments', '!shiftAssignment') 4025: end
# File lib/TjpSyntaxRules.rb, line 4027 4027: def rule_shiftAttributes 4028: optional 4029: repeatable 4030: 4031: pattern(%( !shift )) 4032: pattern(%( !shiftScenarioAttributes )) 4033: pattern(%( !scenarioIdCol !shiftScenarioAttributes ), lambda { 4034: @scenarioIdx = 0 4035: }) 4036: end
# File lib/TjpSyntaxRules.rb, line 4038 4038: def rule_shiftBody 4039: optionsRule('shiftAttributes') 4040: end
# File lib/TjpSyntaxRules.rb, line 4042 4042: def rule_shiftHeader 4043: pattern(%( _shift !optionalID $STRING ), lambda { 4044: if @val[1] && @project.shift(@val[1]) 4045: error('shift_exists', "Shift #{@val[1]} has already been defined.", 4046: @sourceFileInfo[1]) 4047: end 4048: @property = Shift.new(@project, @val[1], @val[2], @property) 4049: @property.sourceFileInfo = @sourceFileInfo[0] 4050: @property.inheritAttributes 4051: @scenarioIdx = 0 4052: }) 4053: arg(2, 'name', 'The name of the shift') 4054: end
# File lib/TjpSyntaxRules.rb, line 4056 4056: def rule_shiftId 4057: pattern(%( $ID ), lambda { 4058: if (shift = @project.shift(@val[0])).nil? 4059: error('shift_id_expected', "#{@val[0]} is not a defined shift.", 4060: @sourceFileInfo[0]) 4061: end 4062: shift 4063: }) 4064: arg(0, 'shift', 'The ID of a defined shift') 4065: end
# File lib/TjpSyntaxRules.rb, line 4067 4067: def rule_shiftScenarioAttributes 4068: pattern(%( _replace ), lambda { 4069: @property['replace', @scenarioIdx] = true 4070: }) 4071: doc('replace', Use this attribute if the vacation definition for the shift should replace the vacation settings of a resource. This is only effective for shifts that are assigned to resources directly. It is not effective for shifts that are assigned to tasks or allocations. 4072: ) 4073: 4074: pattern(%( _timezone !validTimeZone ), lambda { 4075: @property['timezone', @scenarioIdx] = @val[1] 4076: }) 4077: doc('timezone.shift', Sets the time zone of the shift. The working hours of the shift are assumed tobe within the specified time zone. The time zone does not effect the vactioninterval. The latter is assumed to be within the project time zone.TaskJuggler stores all dates internally as UTC. Since all events must alignwith the [[timingresolution|timing resolution]] for time zones you may have tochange the timing resolution appropriately. The time zone difference comparedto UTC must be a multiple of the used timing resolution. 4078: ) 4079: arg(1, 'zone', Time zone to use. E. g. 'Europe/Berlin' or 'America/Denver'. Don't use the 3letter acronyms. See[http://en.wikipedia.org/wiki/List_of_zoneinfo_time_zones Wikipedia] forpossible values. 4080: ) 4081: 4082: pattern(%( _vacation !vacationName !intervalsOptional ), lambda { 4083: @property['vacations', @scenarioIdx] = 4084: @property['vacations', @scenarioIdx ] + @val[2] 4085: }) 4086: doc('vacation.shift', Specify a vacation period associated with this shift. 4087: ) 4088: 4089: pattern(%( !workinghoursShift )) 4090: end
# File lib/TjpSyntaxRules.rb, line 4110 4110: def rule_sortCriteria 4111: pattern([ "!sortCriterium", "!moreSortCriteria" ], lambda { 4112: [ @val[0] ] + (@val[1].nil? ? [] : @val[1]) 4113: }) 4114: end
# File lib/TjpSyntaxRules.rb, line 4116 4116: def rule_sortCriterium 4117: pattern(%( !sortTree ), lambda { 4118: @val[0] 4119: }) 4120: pattern(%( !sortNonTree ), lambda { 4121: @val[0] 4122: }) 4123: end
# File lib/TjpSyntaxRules.rb, line 4125 4125: def rule_sortNonTree 4126: pattern(%( $ABSOLUTE_ID ), lambda { 4127: args = @val[0].split('.') 4128: case args.length 4129: when 2 4130: # <attribute>.<up|down> 4131: scenario = 1 4132: direction = args[1] == 'up' 4133: attribute = args[0] 4134: when 3 4135: # <scenario>.<attribute>.<up|down> 4136: if (scenario = @project.scenarioIdx(args[0])).nil? 4137: error('sort_unknown_scen', 4138: "Unknown scenario #{args[0]} in sorting criterium", 4139: @sourceFileInfo[0]) 4140: end 4141: attribute = args[1] 4142: if args[2] != 'up' && args[2] != 'down' 4143: error('sort_direction', "Sorting direction must be 'up' or 'down'", 4144: @sourceFileInfo[0]) 4145: end 4146: direction = args[2] == 'up' 4147: else 4148: error('sorting_crit_exptd1', 4149: "Sorting criterium expected (e.g. tree, start.up or " + 4150: "plan.end.down).", @sourceFileInfo[0]) 4151: end 4152: if attribute == 'wbs' 4153: error('sorting_wbs', 4154: "Sorting by wbs is not supported. Please use 'tree' " + 4155: '(without appended .up or .down) instead.', 4156: @sourceFileInfo[0]) 4157: end 4158: [ attribute, direction, scenario ] 4159: }) 4160: arg(0, 'criteria', The sorting criteria must consist of a property attribute ID. See [[columnid]]for a complete list of available attributes. The ID must be suffixed by '.up'or '.down' to determine the sorting direction. Optionally the ID may beprefixed with a scenario ID and a dot to determine the scenario that should beused for sorting. So, possible values are 'plan.start.up' or 'priority.down'. 4161: ) 4162: end
# File lib/TjpSyntaxRules.rb, line 4170 4170: def rule_sortResources 4171: pattern(%( _sortresources !sortCriteria ), lambda { 4172: @property.set('sortResources', @val[1]) 4173: }) 4174: doc('sortresources', Determines how the resources are sorted in the report. Multiple criteria can bespecified as a comma separated list. If one criteria is not sufficient to sorta group of resources, the next criteria will be used to sort the resources inthis group. 4175: ) 4176: end
# File lib/TjpSyntaxRules.rb, line 4183 4183: def rule_sortTasks 4184: pattern(%( _sorttasks !sortCriteria ), lambda { 4185: @property.set('sortTasks', @val[1]) 4186: }) 4187: doc('sorttasks', Determines how the tasks are sorted in the report. Multiple criteria can bespecified as comma separated list. If one criteria is not sufficient to sort agroup of tasks, the next criteria will be used to sort the tasks withinthis group. 4188: ) 4189: end
# File lib/TjpSyntaxRules.rb, line 4196 4196: def rule_sortTree 4197: pattern(%( $ID ), lambda { 4198: if @val[0] != 'tree' 4199: error('sorting_crit_exptd2', 4200: "Sorting criterium expected (e.g. tree, start.up or " + 4201: "plan.end.down).", @sourceFileInfo[0]) 4202: end 4203: [ 'tree', true, 1 ] 4204: }) 4205: arg(0, 'tree', 4206: 'Use \tree\ as first criteria to keep the breakdown structure.') 4207: end
# File lib/TjpSyntaxRules.rb, line 4237 4237: def rule_ssReportAttributes 4238: optional 4239: repeatable 4240: 4241: pattern(%( !hideresource )) 4242: pattern(%( !hidetask )) 4243: pattern(%( !reportEnd )) 4244: pattern(%( !reportPeriod )) 4245: pattern(%( !reportStart )) 4246: pattern(%( !sortResources )) 4247: pattern(%( !sortTasks )) 4248: end
# File lib/TjpSyntaxRules.rb, line 4250 4250: def rule_ssReportBody 4251: optionsRule('ssReportAttributes') 4252: end
# File lib/TjpSyntaxRules.rb, line 4208 4208: def rule_ssReportHeader 4209: pattern(%( _statussheetreport !optionalID $STRING ), lambda { 4210: if (fileName = @val[2]) != '.' 4211: if @project.reports[fileName] 4212: error('report_redefinition', 4213: "A report with the name '#{fileName}' has already been " + 4214: "defined.", @sourceFileInfo[2]) 4215: end 4216: else 4217: fileName = "statusSheet#{@project.reports.length + 1}" 4218: end 4219: report = newReport(@val[1], fileName, :statusSheet, sourceFileInfo) 4220: report.set('scenarios', [ 0 ]) 4221: # Show all tasks, sorted by id-up. 4222: report.set('hideTask', LogicalExpression.new(LogicalOperation.new(0))) 4223: report.set('sortTasks', [ [ 'id', true, 1 ] ]) 4224: # Show all resources, sorted by seqno-up. 4225: report.set('hideResource', LogicalExpression.new(LogicalOperation.new(0))) 4226: report.set('sortResources', [ [ 'seqno', true, 1 ] ]) 4227: report.set('loadUnit', :hours) 4228: report.set('definitions', []) 4229: }) 4230: arg(1, 'file name', The name of the status sheet report file to generate. It must end with a .tjiextension, or use . to use the standard output channel. 4231: ) 4232: end
# File lib/TjpSyntaxRules.rb, line 4279 4279: def rule_ssStatus 4280: pattern(%( !ssStatusHeader !ssStatusBody )) 4281: doc('status.statussheet', The status attribute can be used to describe the current status of the task orresource. The content of the status messages is added to the project journal. 4282: ) 4283: end
# File lib/TjpSyntaxRules.rb, line 4254 4254: def rule_ssStatusAttributes 4255: optional 4256: repeatable 4257: 4258: pattern(%( !author )) 4259: pattern(%( !details )) 4260: pattern(%( !summary )) 4261: end
# File lib/TjpSyntaxRules.rb, line 4263 4263: def rule_ssStatusBody 4264: optional 4265: pattern(%( _{ !ssStatusAttributes _} )) 4266: end
# File lib/TjpSyntaxRules.rb, line 4268 4268: def rule_ssStatusHeader 4269: pattern(%( _status !alertLevel $STRING ), lambda { 4270: @journalEntry = JournalEntry.new(@project['journal'], @sheetEnd, 4271: @val[2], @property, 4272: @sourceFileInfo[0]) 4273: @journalEntry.alertLevel = @val[1] 4274: @journalEntry.author = @sheetAuthor 4275: 4276: }) 4277: end
# File lib/TjpSyntaxRules.rb, line 4288 4288: def rule_statusSheet 4289: pattern(%( !statusSheetHeader !statusSheetBody ), lambda { 4290: [ @sheetAuthor, @sheetStart, @sheetEnd ] 4291: }) 4292: doc('statussheet', A status sheet can be used to capture the status of various tasks outside ofthe regular task tree definition. It is intended for use by managers thatdon't directly work with the full project plan, but need to report the currentstatus of each task or task-tree that they are responsible for. 4293: ) 4294: example('StatusSheet') 4295: end
# File lib/TjpSyntaxRules.rb, line 4302 4302: def rule_statusSheetAttributes 4303: optional 4304: repeatable 4305: 4306: pattern(%( !statusSheetTask )) 4307: end
# File lib/TjpSyntaxRules.rb, line 4309 4309: def rule_statusSheetBody 4310: optionsRule('statusSheetAttributes') 4311: end
# File lib/TjpSyntaxRules.rb, line 4313 4313: def rule_statusSheetFile 4314: pattern(%( !statusSheet . ), lambda { 4315: @val[0] 4316: }) 4317: lastSyntaxToken(1) 4318: end
# File lib/TjpSyntaxRules.rb, line 4321 4321: def rule_statusSheetHeader 4322: pattern(%( _statussheet !resourceId !valIntervalOrDate ), lambda { 4323: @sheetAuthor = @val[1] 4324: @sheetStart = @val[2].start 4325: @sheetEnd = @val[2].end 4326: }) 4327: arg(1, 'reporter', The ID of a defined resource. This identifies the status reporter. Unless thestatus entries provide a different author, the sheet author will be used asstatus entry author. 4328: ) 4329: end
# File lib/TjpSyntaxRules.rb, line 4335 4335: def rule_statusSheetReport 4336: pattern(%( !ssReportHeader !ssReportBody ), lambda { 4337: @property = nil 4338: }) 4339: doc('statussheetreport', A status sheet report is a template for a status sheet. It collects all thestatus information of the top-level task that a resource is responsible for.This report is typically used by managers or team leads to review the timesheet status information and destill it down to a summary that can beforwarded to the next person in the reporting chain. 4340: ) 4341: end
# File lib/TjpSyntaxRules.rb, line 4349 4349: def rule_statusSheetTask 4350: pattern(%( !statusSheetTaskHeader !statusSheetTaskBody), lambda { 4351: @property = @propertyStack.pop 4352: }) 4353: doc('task.statussheet', Opens the task with the specified ID to add a status report. Child task can beopened inside this context by specifying their relative ID to this parent. 4354: ) 4355: end
# File lib/TjpSyntaxRules.rb, line 4360 4360: def rule_statusSheetTaskAttributes 4361: optional 4362: repeatable 4363: pattern(%( !ssStatus )) 4364: pattern(%( !statusSheetTask ), lambda { 4365: }) 4366: end
# File lib/TjpSyntaxRules.rb, line 4368 4368: def rule_statusSheetTaskBody 4369: optionsRule('statusSheetTaskAttributes') 4370: end
# File lib/TjpSyntaxRules.rb, line 4372 4372: def rule_statusSheetTaskHeader 4373: pattern(%( _task !taskId ), lambda { 4374: if @property 4375: @propertyStack.push(@property) 4376: else 4377: @propertyStack = [] 4378: end 4379: @property = @val[1] 4380: }) 4381: end
# File lib/TjpSyntaxRules.rb, line 4383 4383: def rule_subNodeId 4384: optional 4385: pattern(%( _: !idOrAbsoluteId ), lambda { 4386: @val[1] 4387: }) 4388: end
# File lib/TjpSyntaxRules.rb, line 4390 4390: def rule_summary 4391: pattern(%( _summary $STRING ), lambda { 4392: return if @val[1].empty? 4393: 4394: if @val[1].length > 480 4395: error('ts_summary_too_long', 4396: "The summary text must be 480 characters long or shorter. " + 4397: "This text has #{@val[1].length} characters.", 4398: @sourceFileInfo[1]) 4399: end 4400: if @val[1] == "A summary text\n" 4401: error('ts_default_summary', 4402: "'A summary text' is not a valid summary", 4403: @sourceFileInfo[1]) 4404: end 4405: rtTokenSetIntro = 4406: [ :LINEBREAK, :SPACE, :WORD, :BOLD, :ITALIC, :CODE, :BOLDITALIC, 4407: :HREF, :HREFEND ] 4408: @journalEntry.summary = newRichText(@val[1], @sourceFileInfo[1], 4409: rtTokenSetIntro) 4410: }) 4411: doc('summary', This is the introductory part of the journal or status entry. It shouldonly summarize the full entry but should contain more details than theheadline. The text including formatting characters must be 240 characters longor less. 4412: ) 4413: arg(1, 'text', The text will be interpreted as [[Rich_Text_Attributes|Rich Text]]. Only asmall subset of the markup is supported for this attribute. You can use wordformatting, hyperlinks and paragraphs. 4414: ) 4415: end
# File lib/TjpSyntaxRules.rb, line 4426 4426: def rule_supplement 4427: pattern(%( !supplementAccount !accountBody ), lambda { 4428: @property = nil 4429: }) 4430: pattern(%( !supplementReport !reportBody ), lambda { 4431: @property = nil 4432: }) 4433: pattern(%( !supplementResource !resourceBody ), lambda { 4434: @property = nil 4435: }) 4436: pattern(%( !supplementTask !taskBody ), lambda { 4437: @property = nil 4438: }) 4439: end
# File lib/TjpSyntaxRules.rb, line 4441 4441: def rule_supplementAccount 4442: pattern(%( _account !accountId ), lambda { 4443: @property = @val[1] 4444: }) 4445: arg(1, 'account ID', 'The ID of an already defined account.') 4446: end
# File lib/TjpSyntaxRules.rb, line 4448 4448: def rule_supplementReport 4449: pattern(%( _report !reportId ), lambda { 4450: @property = @val[1] 4451: }) 4452: arg(1, 'report ID', 'The ID of an already defined report.') 4453: end
# File lib/TjpSyntaxRules.rb, line 4455 4455: def rule_supplementResource 4456: pattern(%( _resource !resourceId ), lambda { 4457: @property = @val[1] 4458: }) 4459: arg(1, 'resource ID', 'The ID of an already defined resource.') 4460: end
# File lib/TjpSyntaxRules.rb, line 4462 4462: def rule_supplementTask 4463: pattern(%( _task !taskId ), lambda { 4464: @property = @val[1] 4465: }) 4466: arg(1, 'task ID', 'The ID of an already defined task.') 4467: end
# File lib/TjpSyntaxRules.rb, line 4469 4469: def rule_task 4470: pattern(%( !taskHeader !taskBody ), lambda { 4471: @property = @property.parent 4472: }) 4473: doc('task', Tasks are the central elements of a project plan. Use a task to specify thevarious steps and phases of the project. Depending on the attributes of thattask, a task can be a container task, a milestone or a regular leaf task. Thelatter may have resources assigned. By specifying dependencies the user canforce a certain sequence of tasks.Tasks have a local name space. All IDs must be unique within the tasksthat belong to the same enclosing task. 4474: ) 4475: end
# File lib/TjpSyntaxRules.rb, line 4486 4486: def rule_taskAttributes 4487: repeatable 4488: optional 4489: 4490: pattern(%( !journalEntry )) 4491: 4492: pattern(%( _note $STRING ), lambda { 4493: @property.set('note', newRichText(@val[1], @sourceFileInfo[1])) 4494: }) 4495: doc('note.task', Attach a note to the task. This is usually a more detailed specification ofwhat the task is about. 4496: ) 4497: 4498: pattern(%( !purge )) 4499: 4500: pattern(%( _supplement !supplementTask !taskBody ), lambda { 4501: @property = @property.parent 4502: }) 4503: doc('supplement.task', The supplement keyword provides a mechanism to add more attributes to alreadydefined tasks. The additional attributes must obey the same rules as inregular task definitions and must be enclosed by curly braces.This construct is primarily meant for situations where the information about atask is split over several files. E. g. the vacation dates for theresources may be in a separate file that was generated by some other tool. 4504: ) 4505: example('Supplement', 'task') 4506: 4507: pattern(%( !task )) 4508: pattern(%( !taskScenarioAttributes )) 4509: pattern(%( !scenarioIdCol !taskScenarioAttributes ), lambda { 4510: @scenarioIdx = 0 4511: }) 4512: # Other attributes will be added automatically. 4513: end
# File lib/TjpSyntaxRules.rb, line 4526 4526: def rule_taskBody 4527: optionsRule('taskAttributes') 4528: end
# File lib/TjpSyntaxRules.rb, line 4530 4530: def rule_taskBooking 4531: pattern(%( !taskBookingHeader !bookingBody ), lambda { 4532: @val[0].task.addBooking(@scenarioIdx, @val[0]) 4533: }) 4534: end
# File lib/TjpSyntaxRules.rb, line 4536 4536: def rule_taskBookingHeader 4537: pattern(%( !resourceId !valIntervals ), lambda { 4538: checkBooking(@property, @val[0]) 4539: @booking = Booking.new(@val[0], @property, @val[1]) 4540: @booking.sourceFileInfo = @sourceFileInfo[0] 4541: @booking 4542: }) 4543: end
# File lib/TjpSyntaxRules.rb, line 4545 4545: def rule_taskDep 4546: pattern(%( !taskDepHeader !taskDepBody ), lambda { 4547: @val[0] 4548: }) 4549: end
# File lib/TjpSyntaxRules.rb, line 4551 4551: def rule_taskDepAttributes 4552: optional 4553: repeatable 4554: 4555: pattern(%( _gapduration !intervalDuration ), lambda { 4556: @taskDependency.gapDuration = @val[1] 4557: }) 4558: doc('gapduration', Specifies the minimum required gap between the end of a preceding task and thestart of this task, or the start of a following task and the end of this task.This is calendar time, not working time. 7d means one week. 4559: ) 4560: 4561: pattern(%( _gaplength !workingDuration ), lambda { 4562: @taskDependency.gapLength = @val[1] 4563: }) 4564: doc('gaplength', Specifies the minimum required gap between the end of a preceding task and thestart of this task, or the start of a following task and the end of this task.This is working time, not calendar time. 7d means 7 working days, not oneweek. Whether a day is considered a working day or not depends on the definedworking hours and global vacations. 4565: ) 4566: 4567: pattern(%( _onend ), lambda { 4568: @taskDependency.onEnd = true 4569: }) 4570: doc('onend', The target of the dependency is the end of the task. 4571: ) 4572: 4573: pattern(%( _onstart ), lambda { 4574: @taskDependency.onEnd = false 4575: }) 4576: doc('onstart', The target of the dependency is the start of the task. 4577: ) 4578: end
# File lib/TjpSyntaxRules.rb, line 4594 4594: def rule_taskDepBody 4595: optionsRule('taskDepAttributes') 4596: end
# File lib/TjpSyntaxRules.rb, line 4598 4598: def rule_taskDepHeader 4599: pattern(%( !taskDepId ), lambda { 4600: @taskDependency = TaskDependency.new(@val[0], true) 4601: }) 4602: end
# File lib/TjpSyntaxRules.rb, line 4604 4604: def rule_taskDepId 4605: singlePattern('$ABSOLUTE_ID') 4606: arg(0, 'ABSOLUTE ID', A reference using the full qualified ID of a task. The IDs of all enclosingparent tasks must be prepended to the task ID and separated with a dot, e.g.''''proj.plan.doc''''. 4607: ) 4608: 4609: singlePattern('$ID') 4610: arg(0, 'ID', 'Just the ID of the task without and parent IDs.') 4611: 4612: pattern(%( !relativeId ), lambda { 4613: task = @property 4614: id = @val[0] 4615: while task && id[0] == !! 4616: id = id.slice(1, id.length) 4617: task = task.parent 4618: end 4619: error('too_many_bangs', 4620: "Too many '!' for relative task in this context.", 4621: @sourceFileInfo[0], @property) if id[0] == !! 4622: if task 4623: task.fullId + '.' + id 4624: else 4625: id 4626: end 4627: }) 4628: arg(0, 'RELATIVE ID', A relative task ID always starts with one or more exclamation marks and isfollowed by a task ID. Each exclamation mark lifts the scope where the ID islooked for to the enclosing task. The ID may contain some of the parent IDsseparated by dots, e. g. ''''!!plan.doc''''. 4629: ) 4630: end
# File lib/TjpSyntaxRules.rb, line 4641 4641: def rule_taskDepList 4642: pattern(%( !taskDep !moreDepTasks ), lambda { 4643: [ @val[0] ] + (@val[1].nil? ? [] : @val[1]) 4644: }) 4645: end
# File lib/TjpSyntaxRules.rb, line 4647 4647: def rule_taskHeader 4648: pattern(%( _task !optionalID $STRING ), lambda { 4649: if @property.nil? && !@taskprefix.empty? 4650: @property = @project.task(@taskprefix) 4651: end 4652: if @val[1] 4653: id = (@property ? @property.fullId + '.' : '') + @val[1] 4654: if @project.task(id) 4655: error('task_exists', "Task #{id} has already been defined.", 4656: @sourceFileInfo[0]) 4657: end 4658: end 4659: @property = Task.new(@project, @val[1], @val[2], @property) 4660: @property['projectid', 0] = @projectId 4661: @property.sourceFileInfo = @sourceFileInfo[0] 4662: @property.inheritAttributes 4663: @scenarioIdx = 0 4664: }) 4665: arg(2, 'name', 'The name of the task') 4666: end
# File lib/TjpSyntaxRules.rb, line 4668 4668: def rule_taskId 4669: pattern(%( !taskIdUnverifd ), lambda { 4670: id = @val[0] 4671: if @property && @property.is_a?(Task) 4672: # In case we have a nested supplement, we need to prepend the parent ID. 4673: id = @property.fullId + '.' + id 4674: else 4675: id = @taskprefix + '.' + id unless @taskprefix.empty? 4676: end 4677: if (task = @project.task(id)).nil? 4678: error('unknown_task', "Unknown task #{id}", @sourceFileInfo[0]) 4679: end 4680: task 4681: }) 4682: end
# File lib/TjpSyntaxRules.rb, line 4684 4684: def rule_taskIdUnverifd 4685: singlePattern('$ABSOLUTE_ID') 4686: singlePattern('$ID') 4687: end
# File lib/TjpSyntaxRules.rb, line 4689 4689: def rule_taskPeriod 4690: pattern(%( _period !valInterval), lambda { 4691: @property['start', @scenarioIdx] = @val[1].start 4692: @property['end', @scenarioIdx] = @val[1].end 4693: }) 4694: doc('period.task', This property is a shortcut for setting the start and end property at the sametime. In contrast to using these, it does not change the scheduling direction. 4695: ) 4696: end
# File lib/TjpSyntaxRules.rb, line 4701 4701: def rule_taskPred 4702: pattern(%( !taskPredHeader !taskDepBody ), lambda { 4703: @val[0] 4704: }) 4705: end
# File lib/TjpSyntaxRules.rb, line 4707 4707: def rule_taskPredHeader 4708: pattern(%( !taskDepId ), lambda { 4709: @taskDependency = TaskDependency.new(@val[0], false) 4710: }) 4711: end
# File lib/TjpSyntaxRules.rb, line 4713 4713: def rule_taskPredList 4714: pattern(%( !taskPred !morePredTasks ), lambda { 4715: [ @val[0] ] + (@val[1].nil? ? [] : @val[1]) 4716: }) 4717: end
# File lib/TjpSyntaxRules.rb, line 4719 4719: def rule_taskScenarioAttributes 4720: 4721: pattern(%( _account $ID ), lambda { 4722: # TODO 4723: }) 4724: doc('account.task', This property has been deprecated. Use [[charge]] instead. 4725: ) 4726: 4727: pattern(%( !allocate )) 4728: 4729: pattern(%( _booking !taskBooking )) 4730: doc('booking.task', Bookings can be used to report already completed work by specifying the exacttime intervals a certain resource has worked on this task. 4731: ) 4732: 4733: pattern(%( _charge !number !chargeMode ), lambda { 4734: checkContainer('charge') 4735: 4736: if @property['chargeset', @scenarioIdx].empty? 4737: error('task_without_chargeset', 4738: 'The task does not have a chargeset defined.', 4739: @sourceFileInfo[0], @property) 4740: end 4741: case @val[2] 4742: when 'onstart' 4743: mode = :onStart 4744: amount = @val[1] 4745: when 'onend' 4746: mode = :onEnd 4747: amount = @val[1] 4748: when 'perhour' 4749: mode = :perDiem 4750: amount = @val[1] * 24 4751: when 'perday' 4752: mode = :perDiem 4753: amount = @val[1] 4754: when 'perweek' 4755: mode = :perDiem 4756: amount = @val[1] / 7.0 4757: end 4758: @property['charge', @scenarioIdx] = 4759: @property['charge', @scenarioIdx] + 4760: [ Charge.new(amount, mode, @property, @scenarioIdx) ] 4761: }) 4762: doc('charge', Specify a one-time or per-period charge to a certain account. The charge canoccur at the start of the task, at the end of it, or continuously over theduration of the task. The accounts to be charged are determined by the[[chargeset]] setting of the task. 4763: ) 4764: arg(1, 'amount', 'The amount to charge') 4765: 4766: pattern(%( !chargeset )) 4767: 4768: pattern(%( _complete !number), lambda { 4769: if @val[1] < 0.0 || @val[1] > 100.0 4770: error('task_complete', "Complete value must be between 0 and 100", 4771: @sourceFileInfo[1], @property) 4772: end 4773: @property['complete', @scenarioIdx] = @val[1] 4774: }) 4775: doc('complete', Specifies what percentage of the task is already completed. This can be usefulfor project tracking. Reports with calendar elements may show the completedpart of the task in a different color. The completion percentage has no impacton the scheduler. It's meant for documentation purposes only.Tasks may not have subtasks if this attribute is used. 4776: ) 4777: example('Complete', '1') 4778: 4779: arg(1, 'percent', 'The percent value. It must be between 0 and 100.') 4780: 4781: pattern(%( _depends !taskDepList ), lambda { 4782: checkContainer('depends') 4783: @property['depends', @scenarioIdx] = 4784: @property['depends', @scenarioIdx] + @val[1] 4785: begin 4786: @property['forward', @scenarioIdx] = true 4787: rescue AttributeOverwrite 4788: end 4789: }) 4790: doc('depends', Specifies that the task cannot start before the specified tasks have beenfinished.By using the 'depends' attribute, the scheduling policy is automatically setto asap. If both depends and precedes are used, the last policy counts. 4791: ) 4792: example('Depends1') 4793: pattern(%( _duration !calendarDuration ), lambda { 4794: checkContainer('duration') 4795: @property['duration', @scenarioIdx] = @val[1] 4796: @property['effort', @scenarioIdx] = 0 4797: @property['length', @scenarioIdx] = 0 4798: }) 4799: doc('duration', Specifies the time the task should last. This is calendar time, not workingtime. 7d means one week. If resources are specified they are allocated whenavailable. Availability of resources has no impact on the duration of thetask. It will always be the specified duration.Tasks may not have subtasks if this attribute is used. Setting this attributewill reset the [[effort]] and [[length]] attributes. 4800: ) 4801: example('Durations') 4802: also(%( effort length )) 4803: 4804: pattern(%( _effort !workingDuration ), lambda { 4805: checkContainer('effort') 4806: if @val[1] <= 0.0 4807: error('effort_zero', "Effort value must be larger than 0", 4808: @sourceFileInfo[1], @property) 4809: end 4810: @property['effort', @scenarioIdx] = @val[1] 4811: @property['duration', @scenarioIdx] = 0 4812: @property['length', @scenarioIdx] = 0 4813: }) 4814: doc('effort', Specifies the effort needed to complete the task. An effort of 4d can be donewith 2 full-time resources in 2 days. The task will not finish before theresources have contributed the specified effort. So the duration of the taskwill depend on the availability of the resources.WARNING: In almost all real world projects effort is not the product of timeand resources. This is only true if the task can be partitioned without addingany overhead. For more information about this read ''The Mythical Man-Month'' byFrederick P. Brooks, Jr.Tasks may not have subtasks if this attribute is used. Setting this attributewill reset the [[duration]] and [[length]] attributes. 4815: ) 4816: example('Durations') 4817: also(%( duration length )) 4818: 4819: pattern(%( _end !valDate ), lambda { 4820: @property['end', @scenarioIdx] = @val[1] 4821: begin 4822: @property['forward', @scenarioIdx] = false 4823: rescue AttributeOverwrite 4824: end 4825: }) 4826: doc('end', The end date of the task. When specified for the top-level (default) scenariothis attributes also implicitly sets the scheduling policy of the tasks toalap.If no end date is given for a task and the end is not specified by adependency on another task, or by a start date plus a duration, the end datewill be inherited from the enclosing tasks or the project end date. 4827: ) 4828: example('Export', '1') 4829: pattern(%( _endcredit !number ), lambda { 4830: @property['charge', @scenarioIdx] = 4831: @property['charge', @scenarioIdx] + 4832: [ Charge.new(@val[1], :onEnd, @property, @scenarioIdx) ] 4833: }) 4834: doc('endcredit', Specifies an amount that is credited to the accounts specified by the[[chargeset]] attributes at the moment the tasks ends. This attribute has beendeprecated and should no longer be used. Use [[charge]] instead. 4835: ) 4836: example('Account', '1') 4837: pattern(%( !flags )) 4838: doc('flags.task', Attach a set of flags. The flags can be used in logical expressions to filterproperties from the reports. 4839: ) 4840: 4841: pattern(%( !fail )) 4842: 4843: pattern(%( _length !workingDuration ), lambda { 4844: checkContainer('length') 4845: @property['length', @scenarioIdx] = @val[1] 4846: @property['duration', @scenarioIdx] = 0 4847: @property['effort', @scenarioIdx] = 0 4848: }) 4849: doc('length', Specifies the time the task occupies the resources. This is working time, notcalendar time. 7d means 7 working days, not one week. Whether a day isconsidered a working day or not depends on the defined working hours andglobal vacations. A task with a length specification may have resourceallocations. Resources are allocated when they are available. The availabilityhas no impact on the duration of the task. A day where none of the specifiedresources is available is still considered a working day, if there is noglobal vacation or global working time defined.Tasks may not have subtasks if this attribute is used. Setting this attributewill reset the [[duration]] and [[effort]] attributes. 4850: ) 4851: also(%( duration effort )) 4852: 4853: pattern(%( !limits ), lambda { 4854: checkContainer('limits') 4855: @property['limits', @scenarioIdx] = @val[0] 4856: }) 4857: doc('limits.task', Set per-interval allocation limits for the task. This setting affects all allocations for this task. 4858: ) 4859: example('Limits-1', '2') 4860: 4861: pattern(%( _maxend !valDate ), lambda { 4862: @property['maxend', @scenarioIdx] = @val[1] 4863: }) 4864: doc('maxend', Specifies the maximum wanted end time of the task. The value is not usedduring scheduling, but is checked after all tasks have been scheduled. If theend of the task is later than the specified value, then an error is reported. 4865: ) 4866: 4867: pattern(%( _maxstart !valDate ), lambda { 4868: @property['maxstart', @scenarioIdx] = @val[1] 4869: }) 4870: doc('maxstart', Specifies the maximum wanted start time of the task. The value is not usedduring scheduling, but is checked after all tasks have been scheduled. If thestart of the task is later than the specified value, then an error isreported. 4871: ) 4872: 4873: pattern(%( _milestone ), lambda { 4874: checkContainer('limits') 4875: @property['milestone', @scenarioIdx] = true 4876: }) 4877: doc('milestone', Turns the task into a special task that has no duration. You may not specify aduration, length, effort or subtasks for a milestone task.A task that only has a start or an end specification and no durationspecification, inherited start or end dates, no dependencies or sub tasks,will be recognized as milestone automatically. 4878: ) 4879: 4880: pattern(%( _minend !valDate ), lambda { 4881: @property['minend', @scenarioIdx] = @val[1] 4882: }) 4883: doc('minend', Specifies the minimum wanted end time of the task. The value is not usedduring scheduling, but is checked after all tasks have been scheduled. If theend of the task is earlier than the specified value, then an error isreported. 4884: ) 4885: 4886: pattern(%( _minstart !valDate ), lambda { 4887: @property['minstart', @scenarioIdx] = @val[1] 4888: }) 4889: doc('minstart', Specifies the minimum wanted start time of the task. The value is not usedduring scheduling, but is checked after all tasks have been scheduled. If thestart of the task is earlier than the specified value, then an error isreported. 4890: ) 4891: 4892: pattern(%( _startcredit !number ), lambda { 4893: @property['charge', @scenarioIdx] = 4894: @property['charge', @scenarioIdx] + 4895: [ Charge.new(@val[1], :onStart, @property, @scenarioIdx) ] 4896: }) 4897: doc('startcredit', Specifies an amount that is credited to the account specified by the[[chargeset]] attributes at the moment the tasks starts. This attribute hasbeen deprecated and should no longer be used. Use [[charge]] instead. 4898: ) 4899: pattern(%( !taskPeriod )) 4900: 4901: pattern(%( _precedes !taskPredList ), lambda { 4902: checkContainer('precedes') 4903: @property['precedes', @scenarioIdx] = 4904: @property['precedes', @scenarioIdx] + @val[1] 4905: begin 4906: @property['forward', @scenarioIdx] = false 4907: rescue AttributeOverwrite 4908: end 4909: }) 4910: doc('precedes', Specifies that the tasks with the specified IDs cannot start before the taskhas been finished. If multiple IDs are specified, they must be separated bycommas. IDs must be either global or relative. A relative ID starts with anumber of '!'. Each '!' moves the scope to the parent task. Global IDs do notcontain '!', but have IDs separated by dots.By using the 'precedes' attribute, the scheduling policy is automatically setto alap. If both depends and precedes are used within a task, the last policycounts. 4911: ) 4912: 4913: pattern(%( _priority $INTEGER ), lambda { 4914: if @val[1] < 0 || @val[1] > 1000 4915: error('task_priority', "Priority must have a value between 0 and 1000", 4916: @sourceFileInfo[1], @property) 4917: end 4918: @property['priority', @scenarioIdx] = @val[1] 4919: }) 4920: doc('priority', Specifies the priority of the task. A task with higher priority is morelikely to get the requested resources. The default priority value of all tasksis 500. Don't confuse the priority of a tasks with the importance or urgencyof a task. It only increases the chances that the tasks gets the requestedresources. It does not mean that the task happens earlier, though that isusually the effect you will see. It also does not have any effect on tasksthat don't have any resources assigned (e.g. milestones).For milestones it will raise or lower the chances that task leading up themilestone will get their resources over task with equal priority that competefor the same resources.This attribute is inherited by subtasks if specified prior to the definitionof the subtask. 4921: ) 4922: arg(1, 'value', 'Priority value (1 - 1000)') 4923: 4924: pattern(%( _projectid $ID ), lambda { 4925: unless @project['projectids'].include?(@val[1]) 4926: error('unknown_projectid', "Unknown project ID #{@val[1]}", 4927: @sourceFileInfo[1]) 4928: end 4929: begin 4930: @property['projectid', @scenarioIdx] = @val[1] 4931: rescue AttributeOverwrite 4932: # This attribute always overwrites the implicitely provided ID. 4933: end 4934: }) 4935: doc('projectid.task', In larger projects it may be desireable to work with different project IDs forparts of the project. This attribute assignes a new project ID to this task anall subsequently defined sub tasks. The project ID needs to be declared first using [[projectid]] or [[projectids]]. 4936: ) 4937: 4938: pattern(%( _responsible !resourceList ), lambda { 4939: @property['responsible', @scenarioIdx] = 4940: @property['responsible', @scenarioIdx] + @val[1] 4941: }) 4942: doc('responsible', The ID of the resource that is responsible for this task. This value is fordocumentation purposes only. It's not used by the scheduler. 4943: ) 4944: 4945: pattern(%( _scheduled ), lambda { 4946: if (@property['milestone', @scenarioIdx] && 4947: @property['start', @scenarioIdx].nil? && 4948: @property['end', @scenarioIdx].nil?) || 4949: (!@property['milestone', @scenarioIdx] && 4950: (@property['start', @scenarioIdx].nil? || 4951: @property['end', @scenarioIdx].nil?)) 4952: error('not_scheduled', 4953: "Task #{@property.fullId} is marked as scheduled but does not " + 4954: 'have a fixed start and end date.', 4955: @sourceFileInfo[0], @property) 4956: end 4957: @property['scheduled', @scenarioIdx] = true 4958: }) 4959: doc('scheduled', This is mostly for internal use. It specifies that the task can be ignored forscheduling in the scenario. 4960: ) 4961: 4962: pattern(%( _scheduling !schedulingDirection ), lambda { 4963: if @val[1] == 'alap' 4964: begin 4965: @property['forward', @scenarioIdx] = false 4966: rescue AttributeOverwrite 4967: end 4968: elsif @val[1] == 'asap' 4969: begin 4970: @property['forward', @scenarioIdx] = true 4971: rescue AttributeOverwrite 4972: end 4973: end 4974: }) 4975: doc('scheduling', Specifies the scheduling policy for the task. A task can be scheduled fromstart to end (As Soon As Possible, asap) or from end to start (As Late AsPossible, alap).A task can be scheduled from start to end (ASAP mode) when it has a hard(start) or soft (depends) criteria for the start time. A task can be scheduledfrom end to start (ALAP mode) when it has a hard (end) or soft (precedes)criteria for the end time.Some task attributes set the scheduling policy implicitly. This attribute canbe used to explicitly set the scheduling policy of the task to a certaindirection. To avoid it being overwritten again by an implicit attribute thisattribute should always be the last attribute of the task.A random mixture of ASAP and ALAP tasks can have unexpected side effects onthe scheduling of the project. It increases significantly the schedulingcomplexity and results in much longer scheduling times. Especially in projectswith many hundreds of tasks the scheduling time of a project with a mixture ofASAP and ALAP times can be 2 to 10 times longer. When the projects containschains of ALAP and ASAP tasks the tasks further down the dependency chain willbe served much later than other non-chained task even when they have a muchhigher priority. This can result in situations where high priority tasks donot get their resources even though the parallel competing tasks have a muchlower priority.As a general rule, try to avoid ALAP tasks whenever possible. Have a closeeye on tasks that have been switched implicitly to ALAP mode because theend attribute comes after the start attribute. 4976: ) 4977: 4978: pattern(%( _shift !shiftAssignments ), lambda { 4979: checkContainer('shift') 4980: }) 4981: doc('shift.task', This keyword has been deprecated. Please use [[shifts.task|shifts(task)]] instead. 4982: ) 4983: 4984: pattern(%( _shifts !shiftAssignments ), lambda { 4985: checkContainer('shifts') 4986: }) 4987: doc('shifts.task', Limits the working time for this task during the during the specified intervalto the working hours of the given shift. Multiple shifts can be defined, butshift intervals may not overlap. This is an additional working timerestriction ontop of the working hours of the allocated resources. It does notreplace the resource working hour restrictions. For a resource to be assignedto a time slot, both the respective task shift as well as the resource workinghours must declare the time slot as duty slot. 4988: ) 4989: 4990: pattern(%( _start !valDate), lambda { 4991: @property['start', @scenarioIdx] = @val[1] 4992: begin 4993: @property['forward', @scenarioIdx] = true 4994: rescue AttributeOverwrite 4995: end 4996: }) 4997: doc('start', The start date of the task. When specified for the top-level (default)scenario this attribute also implicitly sets the scheduling policy of the taskto asap.If no start date is given for a task and the start is not specified by adependency on another task, or by an end date plus a duration, the start datewill be inherited from the enclosing tasks or the project start date. 4998: ) 4999: also(%( end period.task maxstart minstart scheduling )) 5000: 5001: pattern(%( !warn )) 5002: 5003: # Other attributes will be added automatically. 5004: end
# File lib/TjpSyntaxRules.rb, line 5333 5333: def rule_timeInterval 5334: pattern([ '$TIME', '_-', '$TIME' ], lambda { 5335: if @val[0] >= @val[2] 5336: error('time_interval', 5337: "End time of interval must be larger than start time", 5338: @sourceFileInfo[0]) 5339: end 5340: [ @val[0], @val[2] ] 5341: }) 5342: end
# File lib/TjpSyntaxRules.rb, line 5344 5344: def rule_timeSheet 5345: pattern(%( !timeSheetHeader !timeSheetBody ), lambda { 5346: @timeSheet 5347: }) 5348: doc('timesheet', A time sheet record can be used to capture the current status of the tasksassigned to a specific resource and the achieved progress for a given periodof time. The status is assumed to be for the end of this time period. Theremust be a separate time sheet record for each resource per period. Differentresources can use different reporting periods and reports for the sameresource may have different reporting periods as long as they don't overlap.For the time after the last time sheet, TaskJuggler will project the resultbased on the plan data. For periods without a time sheet record prior to thelast record for this resource, TaskJuggler assumes that no work has been done.The work is booked for the scenario specified by [[trackingscenario]].The intended use for time sheets is to have all resources report a time sheetevery day, week or month. All time sheets can be added to the project plan.The status information is always used to determin the current status of theproject. The [[work]], [[remaining]] and [[end.timesheet|end]] attributes areignored if there are also [[booking|bookings]] for the resource in the timesheet period. The non-ignored attributes of the time sheetswill be converted into [[booking]] statements internally. These bookings canthen be [[export|exported]] into a file which can then be added to the projectagain. This way, you can use time sheets to incrementally record progress ofyour project. There is a possibility that time sheets conflict with other datain the plan. In case TaskJuggler cannot automatically resolve them, theseconflicts have to be manually resolved by either changing the plan or the timesheet.The status messages are interpreted as [[journalentry|journal entries]]. Thealert level will be evaluated and the current state of the project can be putinto a dashboard using the ''''alert'''' and ''''alertmessage'''' [[columnid|columns]].Currently, the provided effort values and dates are not yet used toautomatically update the plan data. This feature will be added in futureversions. 5349: ) 5350: example('TimeSheet1', '1') 5351: end
# File lib/TjpSyntaxRules.rb, line 5387 5387: def rule_timeSheetAttributes 5388: optional 5389: repeatable 5390: 5391: pattern(%( !tsNewTaskHeader !tsTaskBody ), lambda { 5392: @property = nil 5393: @timeSheetRecord = nil 5394: }) 5395: doc('newtask', The keyword can be used add a new task to the project. If the task ID requiresfurther parent task that don't exist yet, these tasks will be created as well.If the task exists already, an error is generated. The new task can be usedimmediately to report progress and status against it. 5396: ) 5397: example('TimeSheet1', '3') 5398: 5399: pattern(%( _shift !shiftId ), lambda { 5400: #TODO 5401: }) 5402: doc('shift.timesheet', Specifies an alternative [[shift]] for the time sheet period. This shift willoverride any existing working hour definitions for the resource. It will notoverride already declared [[vacation|vacations]] though.The primary use of this feature is to let the resources report different totalwork time for the report period. 5403: ) 5404: 5405: pattern(%( !tsStatus )) 5406: 5407: pattern(%( !tsTaskHeader !tsTaskBody ), lambda { 5408: @property = nil 5409: @timeSheetRecord = nil 5410: }) 5411: doc('task.timesheet', Specifies an existing task that progress and status should be reportedagainst. 5412: ) 5413: example('TimeSheet1', '4') 5414: end
# File lib/TjpSyntaxRules.rb, line 5438 5438: def rule_timeSheetBody 5439: pattern(%( _{ !timeSheetAttributes _} ), lambda { 5440: 5441: }) 5442: end
# File lib/TjpSyntaxRules.rb, line 5431 5431: def rule_timeSheetFile 5432: pattern(%( !timeSheet . ), lambda { 5433: @val[0] 5434: }) 5435: lastSyntaxToken(1) 5436: end
# File lib/TjpSyntaxRules.rb, line 5444 5444: def rule_timeSheetHeader 5445: pattern(%( _timesheet !resourceId !valIntervalOrDate ), lambda { 5446: @sheetAuthor = @val[1] 5447: @property = nil 5448: unless @sheetAuthor.leaf? 5449: error('ts_group_author', 5450: 'A resource group cannot file a time sheet', 5451: @sourceFileInfo[1]) 5452: end 5453: # Currently time sheets are hardcoded for scenario 0. 5454: @timeSheet = TimeSheet.new(@sheetAuthor, @val[2], 5455: @project['trackingScenarioIdx']) 5456: @timeSheet.sourceFileInfo = @sourceFileInfo[0] 5457: @project.timeSheets << @timeSheet 5458: }) 5459: end
# File lib/TjpSyntaxRules.rb, line 5461 5461: def rule_timeSheetReport 5462: pattern(%( !tsReportHeader !tsReportBody ), lambda { 5463: @property = nil 5464: }) 5465: doc('timesheetreport', For projects that flow mostly according to plan, TaskJuggler already knowsmuch of the information that should be contained in the time sheets. With thisproperty, you can generate a report that contains drafts of the time sheetsfor one or more resources. The time sheet drafts will be for thespecified report period. 5466: ) 5467: end
# File lib/TjpSyntaxRules.rb, line 5191 5191: def rule_timeformat 5192: pattern(%( _timeformat $STRING ), lambda { 5193: @val[1] 5194: }) 5195: doc('timeformat', Determines how time specifications in reports look like. 5196: ) 5197: arg(1, 'format', Ordinary characters placed in the format string are copied withoutconversion. Conversion specifiers are introduced by a `%' character, and arereplaced in s as follows:* ''''%a'''' The abbreviated weekday name according to the current locale.* ''''%A'''' The full weekday name according to the current locale.* ''''%b'''' The abbreviated month name according to the current locale.* ''''%B'''' The full month name according to the current locale.* ''''%c'''' The preferred date and time representation for the current locale.* ''''%C'''' The century number (year/100) as a 2-digit integer. (SU)* ''''%d'''' The day of the month as a decimal number (range 01 to 31).* ''''%e'''' Like ''''%d'''', the day of the month as a decimal number, but aleading zero is replaced by a space. (SU)* ''''%E'''' Modifier: use alternative format, see below. (SU)* ''''%F'''' Equivalent to ''''%Y-%m-%d'''' (the ISO 8601 date format). (C99)* ''''%G'''' The ISO 8601 year with century as a decimal number. The 4-digityear corresponding to the ISO week number (see %V). This has the same formatand value as ''''%y'''', except that if the ISO week number belongs to theprevious or next year, that year is used instead. (TZ)* ''''%g'''' Like %G, but without century, i.e., with a 2-digit year (00-99).(TZ)* ''''%h'''' Equivalent to ''''%b''''. (SU)* ''''%H'''' The hour as a decimal number using a 24-hour clock (range 00 to23).* ''''%I'''' The hour as a decimal number using a 12-hour clock (range 01 to12).* ''''%j'''' The day of the year as a decimal number (range 001 to 366).* ''''%k'''' The hour (24-hour clock) as a decimal number (range 0 to 23);single digits are preceded by a blank. (See also ''''%H''''.) (TZ)* ''''%l'''' The hour (12-hour clock) as a decimal number (range 1 to 12);single digits are preceded by a blank. (See also ''''%I''''.) (TZ)* ''''%m'''' The month as a decimal number (range 01 to 12).* ''''%M'''' The minute as a decimal number (range 00 to 59).* ''''%n'''' A newline character. (SU)* ''''%O'''' Modifier: use alternative format, see below. (SU)* ''''%p'''' Either 'AM' or 'PM' according to the given time value, or thecorresponding strings for the current locale. Noon is treated as `pm' andmidnight as 'am'.* ''''%P'''' Like %p but in lowercase: 'am' or 'pm' or ''''%a''''corresponding string for the current locale. (GNU)* ''''%r'''' The time in a.m. or p.m. notation. In the POSIX locale this isequivalent to ''''%I:%M:%S %p''''. (SU)* ''''%R'''' The time in 24-hour notation (%H:%M). (SU) For a versionincluding the seconds, see ''''%T'''' below.* ''''%s'''' The number of seconds since the Epoch, i.e., since 1970-01-0100:00:00 UTC. (TZ)* ''''%S'''' The second as a decimal number (range 00 to 61).* ''''%t'''' A tab character. (SU)* ''''%T'''' The time in 24-hour notation (%H:%M:%S). (SU)* ''''%u'''' The day of the week as a decimal, range 1 to 7, Monday being 1.See also ''''%w''''. (SU)* ''''%U'''' The week number of the current year as a decimal number, range00 to 53, starting with the first Sunday as the first day of week 01. See also''''%V'''' and ''''%W''''.* ''''%V'''' The ISO 8601:1988 week number of the current year as a decimalnumber, range 01 to 53, where week 1 is the first week that has at least 4days in the current year, and with Monday as the first day of the week. Seealso ''''%U'''' and ''''%W''''. %(SU)* ''''%w'''' The day of the week as a decimal, range 0 to 6, Sunday being 0. See also ''''%u''''.* ''''%W'''' The week number of the current %year as a decimal number, range00 to 53, starting with the first Monday as the first day of week 01.* ''''%x'''' The preferred date representation for the current locale withoutthe time.* ''''%X'''' The preferred time representation for the current locale withoutthe date.* ''''%y'''' The year as a decimal number without a century (range 00 to 99).* ''''%Y'''' The year as a decimal number including the century.* ''''%z'''' The time zone as hour offset from GMT. Required to emitRFC822-conformant dates (using ''''%a, %d %%b %Y %H:%M:%S %%z''''). (GNU)* ''''%Z'''' The time zone or name or abbreviation.* ''''%+'''' The date and time in date(1) format. (TZ)* ''''%%'''' A literal ''''%'''' character.Some conversion specifiers can be modified by preceding them by the E or Omodifier to indicate that an alternative format should be used. If thealternative format or specification does not exist for the current locale, thebehavior will be as if the unmodified conversion specification were used.(SU) The Single Unix Specification mentions %Ec, %EC, %Ex, %%EX, %Ry, %EY,%Od, %Oe, %OH, %OI, %Om, %OM, %OS, %Ou, %OU, %OV, %Ow, %OW, %Oy, where theeffect of the O modifier is to use alternative numeric symbols (say, Romannumerals), and that of the E modifier is to use a locale-dependent alternativerepresentation.This documentation of the timeformat attribute has been taken from the man pageof the GNU strftime function. 5198: ) 5199: 5200: end
# File lib/TjpSyntaxRules.rb, line 5475 5475: def rule_timezone 5476: pattern(%( _timezone !validTimeZone ), lambda{ 5477: ENV['TZ'] = @project['timezone'] = @val[1] 5478: }) 5479: doc('timezone', Sets the default time zone of the project. All times that have no timezones specified will be assumed to be in this time zone. The value must be astring just like those used for the TZ environment variable. MostLinux systems have a command line utility called tzselect to lookuppossible values.The project start and end time are not affected by this setting. Youhave to explicitly state the time zone for those dates or the system defaultsare assumed. Using the TZ environment variable is the recommended way tospecify the time zone for your project.In case the specified time zone is not hour-aligned with UTC, the[[timingresolution]] will automatically be decreased accordingly. Do notchange the timingresolution after you've set the time zone!Changing the time zone will reset the [[workinghours.project|working hours]]to the default times. It's recommended that you declare your working hoursafter the time zone. 5480: ) 5481: arg(1, 'zone', Time zone to use. E. g. 'Europe/Berlin' or 'America/Denver'. Don't use the 3letter acronyms. See[http://en.wikipedia.org/wiki/List_of_zoneinfo_time_zones Wikipedia] forpossible values. 5482: ) 5483: end
# File lib/TjpSyntaxRules.rb, line 5509 5509: def rule_tsNewTaskHeader 5510: pattern(%( _newtask !taskIdUnverifd $STRING ), lambda { 5511: @timeSheetRecord = TimeSheetRecord.new(@timeSheet, @val[1]) 5512: @timeSheetRecord.name = @val[2] 5513: @timeSheetRecord.sourceFileInfo = @sourceFileInfo[0] 5514: }) 5515: arg(1, 'task', 'ID of the new task') 5516: end
# File lib/TjpSyntaxRules.rb, line 5537 5537: def rule_tsReportAttributes 5538: optional 5539: repeatable 5540: 5541: pattern(%( !hideresource )) 5542: pattern(%( !reportEnd )) 5543: pattern(%( !reportPeriod )) 5544: pattern(%( !reportStart )) 5545: end
# File lib/TjpSyntaxRules.rb, line 5547 5547: def rule_tsReportBody 5548: optionsRule('tsReportAttributes') 5549: end
# File lib/TjpSyntaxRules.rb, line 5517 5517: def rule_tsReportHeader 5518: pattern(%( _timesheetreport !optionalID $STRING ), lambda { 5519: report = newReport(@val[1], @val[2], :timeSheet, sourceFileInfo) 5520: report.set('scenarios', [ 0 ]) 5521: # Show all tasks, sorted by seqno-up. 5522: report.set('hideTask', LogicalExpression.new(LogicalOperation.new(0))) 5523: report.set('sortTasks', [ [ 'seqno', true, 1 ] ]) 5524: # Show all resources, sorted by seqno-up. 5525: report.set('hideResource', LogicalExpression.new(LogicalOperation.new(0))) 5526: report.set('sortResources', [ [ 'seqno', true, 1 ] ]) 5527: report.set('loadUnit', :hours) 5528: report.set('definitions', []) 5529: }) 5530: arg(1, 'file name', The name of the time sheet report file to generate. It must end with a .tjiextension, or use . to use the standard output channel. 5531: ) 5532: end
# File lib/TjpSyntaxRules.rb, line 5588 5588: def rule_tsStatus 5589: pattern(%( !tsStatusHeader !tsStatusBody )) 5590: doc('status.timesheet', The status attribute can be used to describe the current status of the task orresource. The content of the status messages is added to the project journal. 5591: ) 5592: arg(2, 'headline', A short headline for the status. Must be 60 characters or shorter. 5593: ) 5594: example('TimeSheet1', '4') 5595: end
# File lib/TjpSyntaxRules.rb, line 5551 5551: def rule_tsStatusAttributes 5552: optional 5553: repeatable 5554: 5555: pattern(%( !details )) 5556: pattern(%( !summary )) 5557: end
# File lib/TjpSyntaxRules.rb, line 5559 5559: def rule_tsStatusBody 5560: optional 5561: pattern(%( _{ !tsStatusAttributes _} )) 5562: end
# File lib/TjpSyntaxRules.rb, line 5564 5564: def rule_tsStatusHeader 5565: pattern(%( _status !alertLevel $STRING ), lambda { 5566: if @val[2].length > 120 5567: error('ts_headline_too_long', 5568: "The headline must be 120 or less characters long. This one " + 5569: "has #{@val[2].length} characters.", @sourceFileInfo[2]) 5570: end 5571: if @val[2] == 'Your headline here!' 5572: error('ts_no_headline', 5573: "'Your headline here!' is not a valid headline", 5574: @sourceFileInfo[2]) 5575: end 5576: @journalEntry = JournalEntry.new(@project['journal'], 5577: @timeSheet.interval.end, 5578: @val[2], 5579: @property || @timeSheet.resource, 5580: @sourceFileInfo[0]) 5581: @journalEntry.alertLevel = @val[1] 5582: @journalEntry.timeSheetRecord = @timeSheetRecord 5583: @journalEntry.author = @sheetAuthor 5584: @timeSheetRecord.status = @journalEntry if @timeSheetRecord 5585: }) 5586: end
# File lib/TjpSyntaxRules.rb, line 5602 5602: def rule_tsTaskAttributes 5603: optional 5604: repeatable 5605: 5606: pattern(%( _end !valDate ), lambda { 5607: if @val[1] < @timeSheet.interval.start 5608: error('ts_end_too_early', 5609: "The expected task end date must be after the start date of " + 5610: "this time sheet report.", @sourceFileInfo[1]) 5611: end 5612: @timeSheetRecord.expectedEnd = @val[1] 5613: }) 5614: doc('end.timesheet', The expected end date for the task. This can only be used for duration basedtask. For effort based task [[remaining]] has to be used. 5615: ) 5616: example('TimeSheet1', '5') 5617: 5618: pattern(%( _priority $INTEGER ), lambda { 5619: priority = @val[1] 5620: if priority < 1 || priority > 1000 5621: error('ts_bad_priority', 5622: "Priority value #{priority} must be between 1 and 1000.", 5623: @sourceFileInfo[1]) 5624: end 5625: @timeSheetRecord.priority = priority 5626: }) 5627: doc('priority.timesheet', The priority is a value between 1 and 1000. It is used to determine thesequence of task when converting [[work]] to [[booking|bookings]]. Tasks thatneed to finish earlier in the period should have a high priority, tasks thatend later in the period should have a low priority. For tasks that don't getfinished in the reported period the priority should be set to 1. 5628: ) 5629: 5630: pattern(%( _remaining !workingDuration ), lambda { 5631: @timeSheetRecord.remaining = @val[1] 5632: }) 5633: doc('remaining', The remaining effort for the task. This value is ignored if there are[[booking|bookings]] for the resource that overlap with the time sheet period.If there are no bookings, the value is compared with the [[effort]]specification of the task. If there a mismatch between the accumulated effortspecified with bookings, [[work]] and [[remaining]] on one side and thespecified [[effort]] on the other, a warning is generated.This attribute can only be used with tasks that are effort based. Durationbased tasks need to have an [[end.timesheet|end]] attribute. 5634: ) 5635: example('TimeSheet1', '6') 5636: 5637: pattern(%( !tsStatus )) 5638: 5639: pattern(%( _work !workingDurationPercent ), lambda { 5640: @timeSheetRecord.work = @val[1] 5641: }) 5642: doc('work', The amount of time that the resource has spend with the task during thereported period. This value is ignored when there are [[booking|bookings]] forthe resource overlapping with the time sheet period. If there are no bookings,TaskJuggler will try to convert the work specification into bookingsinternally before the actual scheduling is started.Every task listed in the time sheet needs to have a work attribute. The totalaccumulated work time that is reported must match exactly the total workinghours for the resource for that period.If a resource has no vacation during the week that is reported and it has aregular 40 hour work week, exactly 40 hours total or 5 working days have to bereported. 5643: ) 5644: example('TimeSheet1', '4') 5645: end
# File lib/TjpSyntaxRules.rb, line 5680 5680: def rule_tsTaskBody 5681: pattern(%( _{ !tsTaskAttributes _} )) 5682: end
# File lib/TjpSyntaxRules.rb, line 5684 5684: def rule_tsTaskHeader 5685: pattern(%( _task !taskId ), lambda { 5686: @property = @val[1] 5687: unless @property.leaf? 5688: error('ts_task_not_leaf', 5689: 'You cannot specify a task that has sub tasks here.', 5690: @sourceFileInfo[1], @property) 5691: end 5692: 5693: @timeSheetRecord = TimeSheetRecord.new(@timeSheet, @property) 5694: @timeSheetRecord.sourceFileInfo = @sourceFileInfo[0] 5695: }) 5696: arg(1, 'task', 'ID of an already existing task') 5697: end
# File lib/TjpSyntaxRules.rb, line 5699 5699: def rule_vacationName 5700: optional 5701: pattern(%( $STRING )) # We just throw the name away 5702: arg(0, 'name', 'An optional name for the vacation') 5703: end
# File lib/TjpSyntaxRules.rb, line 5705 5705: def rule_valDate 5706: pattern(%( !date ), lambda { 5707: if @val[0] < @project['start'] || @val[0] > @project['end'] 5708: error('date_in_range', "Date must be within the project time frame " + 5709: "#{@project['start']} - #{@project['end']}", 5710: @sourceFileInfo[0]) 5711: end 5712: @val[0] 5713: }) 5714: end
# File lib/TjpSyntaxRules.rb, line 5764 5764: def rule_valInterval 5765: pattern(%( !date !intervalEnd ), lambda { 5766: mode = @val[1][0] 5767: endSpec = @val[1][1] 5768: if mode == 0 5769: unless @val[0] < endSpec 5770: error('start_before_end', "The end date (#{endSpec}) must be after " + 5771: "the start date (#{@val[0]}).", @sourceFileInfo[1]) 5772: end 5773: iv = Interval.new(@val[0], endSpec) 5774: else 5775: iv = Interval.new(@val[0], @val[0] + endSpec) 5776: end 5777: checkInterval(iv) 5778: iv 5779: }) 5780: doc('interval1', There are two ways to specify a date interval. The start and end date must lie within the specified project period.The first is the most obvious. A date interval consists of a start and endDATE. Watch out for end dates without a time specification! Datespecifications are 0 extended. An end date without a time is expanded tomidnight that day. So the day of the end date is not included in the interval!The start and end dates must be separated by a hyphen character.In the second form specifies the start date and an interval duration. Theduration must be prefixed by a plus character. 5781: ) 5782: end
# File lib/TjpSyntaxRules.rb, line 5726 5726: def rule_valIntervalOrDate 5727: pattern(%( !date !intervalOptionalEnd ), lambda { 5728: if @val[1] 5729: mode = @val[1][0] 5730: endSpec = @val[1][1] 5731: if mode == 0 5732: unless @val[0] < endSpec 5733: error('start_before_end', "The end date (#{endSpec}) must be " + 5734: "after the start date (#{@val[0]}).", 5735: @sourceFileInfo[1]) 5736: end 5737: iv = Interval.new(@val[0], endSpec) 5738: else 5739: iv = Interval.new(@val[0], @val[0] + endSpec) 5740: end 5741: else 5742: iv = Interval.new(@val[0], @val[0].sameTimeNextDay) 5743: end 5744: checkInterval(iv) 5745: iv 5746: }) 5747: doc('interval4', There are three ways to specify a date interval. The first is the mostobvious. A date interval consists of a start and end DATE. Watch out for enddates without a time specification! Date specifications are 0 extended. Anend date without a time is expanded to midnight that day. So the day of theend date is not included in the interval! The start and end dates must be separated by a hyphen character.In the second form, the end date is omitted. A 24 hour interval is assumed.The third form specifies the start date and an interval duration. The duration must be prefixed by a plus character.The start and end date of the interval must be within the specified projecttime frame. 5748: ) 5749: end
# File lib/TjpSyntaxRules.rb, line 5795 5795: def rule_valIntervals 5796: listRule('moreValIntervals', '!valIntervalOrDate') 5797: end
# File lib/TjpSyntaxRules.rb, line 5716 5716: def rule_validTimeZone 5717: pattern(%( $STRING ), lambda { 5718: unless TjTime.checkTimeZone(@val[0]) 5719: error('bad_time_zone', "#{@val[0]} is not a known time zone", 5720: @sourceFileInfo[0]) 5721: end 5722: @val[0] 5723: }) 5724: end
# File lib/TjpSyntaxRules.rb, line 5799 5799: def rule_warn 5800: pattern(%( _warn !logicalExpression ), lambda { 5801: begin 5802: @property['warn', @scenarioIdx] = 5803: @property['warn', @scenarioIdx] + [ @val[1] ] 5804: rescue AttributeOverwrite 5805: end 5806: }) 5807: doc('warn', The warn attribute adds a logical expression to the property. The conditiondescribed by the logical expression is checked after the scheduling and anwarning is generated if the condition evaluates to true. This attribute isprimarily intended for testing purposes. 5808: ) 5809: end
# File lib/TjpSyntaxRules.rb, line 5827 5827: def rule_weekDayInterval 5828: pattern(%( !weekday !weekDayIntervalEnd ), lambda { 5829: weekdays = Array.new(7, false) 5830: if @val[1].nil? 5831: weekdays[@val[0]] = true 5832: else 5833: d = @val[0] 5834: loop do 5835: weekdays[d] = true 5836: break if d == @val[1] 5837: d = (d + 1) % 7 5838: end 5839: end 5840: 5841: weekdays 5842: }) 5843: arg(0, 'weekday', 'Weekday (sun - sat)') 5844: end
# File lib/TjpSyntaxRules.rb, line 5846 5846: def rule_weekDayIntervalEnd 5847: optional 5848: pattern([ '_-', '!weekday' ], lambda { 5849: @val[1] 5850: }) 5851: arg(1, 'end weekday', 5852: 'Weekday (sun - sat). It is included in the interval.') 5853: end
# File lib/TjpSyntaxRules.rb, line 5817 5817: def rule_weekday 5818: pattern(%( _sun ), lambda { 0 }) 5819: pattern(%( _mon ), lambda { 1 }) 5820: pattern(%( _tue ), lambda { 2 }) 5821: pattern(%( _wed ), lambda { 3 }) 5822: pattern(%( _thu ), lambda { 4 }) 5823: pattern(%( _fri ), lambda { 5 }) 5824: pattern(%( _sat ), lambda { 6 }) 5825: end
# File lib/TjpSyntaxRules.rb, line 5855 5855: def rule_workingDuration 5856: pattern(%( !number !durationUnit ), lambda { 5857: convFactors = [ 60, # minutes 5858: 60 * 60, # hours 5859: 60 * 60 * @project['dailyworkinghours'], # days 5860: 60 * 60 * @project['dailyworkinghours'] * 5861: (@project['yearlyworkingdays'] / 52.1429), # weeks 5862: 60 * 60 * @project['dailyworkinghours'] * 5863: (@project['yearlyworkingdays'] / 12), # months 5864: 60 * 60 * @project['dailyworkinghours'] * 5865: @project['yearlyworkingdays'] # years 5866: ] 5867: # The result will always be in number of time slots. 5868: (@val[0] * convFactors[@val[1]] / 5869: @project['scheduleGranularity']).round.to_i 5870: }) 5871: arg(0, 'value', 'A floating point or integer number') 5872: end
# File lib/TjpSyntaxRules.rb, line 5874 5874: def rule_workingDurationPercent 5875: pattern(%( !number !durationUnitOrPercent ), lambda { 5876: if @val[1] >= 0 5877: # Absolute value in minutes, hours or days. 5878: convFactors = [ 60, # minutes 5879: 60 * 60, # hours 5880: 60 * 60 * @project['dailyworkinghours'] # days 5881: ] 5882: # The result will always be in number of time slots. 5883: (@val[0] * convFactors[@val[1]] / 5884: @project['scheduleGranularity']).round.to_i 5885: else 5886: # Percentage values are always returned as Float in the rage of 0.0 to 5887: # 1.0. 5888: if @val[0] < 0.0 || @val[0] > 100.0 5889: error('illegal_percentage', 5890: "Percentage values must be between 0 and 100%.", 5891: @sourceFileInfo[1]) 5892: end 5893: @val[0] / 100.0 5894: end 5895: }) 5896: arg(0, 'value', 'A floating point or integer number') 5897: end
# File lib/TjpSyntaxRules.rb, line 5899 5899: def rule_workinghours 5900: pattern(%( _workinghours !listOfDays !listOfTimes), lambda { 5901: if @property.nil? 5902: # We are changing global working hours. 5903: wh = @project['workinghours'] 5904: else 5905: unless (wh = @property['workinghours', @scenarioIdx]) 5906: # The property does not have it's own WorkingHours yet. 5907: wh = WorkingHours.new(@project['workinghours']) 5908: @property['workinghours', @scenarioIdx] = wh 5909: end 5910: end 5911: wh.timezone = @property.nil? ? @project['timezone'] : 5912: @property['timezone', @scenarioIdx] 5913: 7.times { |i| wh.setWorkingHours(i, @val[2]) if @val[1][i] } 5914: }) 5915: end
# File lib/TjpSyntaxRules.rb, line 5917 5917: def rule_workinghoursProject 5918: pattern(%( !workinghours )) 5919: doc('workinghours.project', Set the default working hours for all subsequent resource definitions. Thestandard working hours are 9:00am - 12:00am, 1:00pm - 18:00pm, Monday toFriday. The working hours specification limits the availability of resourcesto certain time slots of week days.These default working hours can be replaced with other working hours forindividual resources. 5920: ) 5921: also(%( dailyworkinghours workinghours.resource workinghours.shift )) 5922: example('Project') 5923: end
# File lib/TjpSyntaxRules.rb, line 5933 5933: def rule_workinghoursResource 5934: pattern(%( !workinghours )) 5935: doc('workinghours.resource', Set the working hours for a specific resource. The working hours specificationlimits the availability of resources to certain time slots of week days. 5936: ) 5937: also(%( workinghours.project workinghours.shift )) 5938: end
# File lib/TjpSyntaxRules.rb, line 5943 5943: def rule_workinghoursShift 5944: pattern(%( !workinghours )) 5945: doc('workinghours.shift', Set the working hours for the shift. The working hours specification limitsthe availability of resources or the activity on a task to certain timeslots of week days.The shift working hours will replace the default or resource working hours forthe specified time frame when assigning the shift to a resource.In case the shift is used for a task, resources are only assigned during theworking hours of this shift and during the working hours of the allocatedresource. Allocations only happen when both the task shift and the resourcework hours allow work to happen. 5946: ) 5947: also(%( workinghours.project workinghours.resource )) 5948: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.