Method: TaskJuggler::TaskScenario#postScheduleCheck
- Defined in:
- lib/taskjuggler/TaskScenario.rb
#postScheduleCheck ⇒ Object
This function is not essential but does perform a large number of consistency checks. It should be called after the scheduling run has been finished.
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 |
# File 'lib/taskjuggler/TaskScenario.rb', line 434 def postScheduleCheck @errors = 0 @property.children.each do |task| @errors += 1 unless task.postScheduleCheck(@scenarioIdx) end # There is no point to check the parent if the child(s) have errors. return false if @errors > 0 # Same for runaway tasks. They have already been reported. if @isRunAway error('sched_runaway', "Some tasks did not fit into the project time " + "frame.") end # Make sure the task is marked complete unless @scheduled error('not_scheduled', "Task #{@property.fullId} has not been marked as scheduled.") end # If the task has a follower or predecessor that is a runaway this task # is also incomplete. (@startsuccs + @endsuccs).each do |task, onEnd| return false if task.isRunAway(@scenarioIdx) end (@startpreds + @endpreds).each do |task, onEnd| return false if task.isRunAway(@scenarioIdx) end # Check if the start time is ok if @start.nil? error('task_start_undef', "Task #{@property.fullId} has undefined start time") end if @start < @project['start'] || @start > @project['end'] error('task_start_range', "The start time (#{@start}) of task #{@property.fullId} " + "is outside the project interval (#{@project['start']} - " + "#{@project['end']})") end if !@minstart.nil? && @start < @minstart warning('minstart', "The start time (#{@start}) of task #{@property.fullId} " + "is too early. Must be after #{@minstart}.") end if !@maxstart.nil? && @start > @maxstart warning('maxstart', "The start time (#{@start}) of task #{@property.fullId} " + "is too late. Must be before #{@maxstart}.") end # Check if the end time is ok error('task_end_undef', "Task #{@property.fullId} has undefined end time") if @end.nil? if @end < @project['start'] || @end > @project['end'] error('task_end_range', "The end time (#{@end}) of task #{@property.fullId} " + "is outside the project interval (#{@project['start']} - " + "#{@project['end']})") end if !@minend.nil? && @end < @minend warning('minend', "The end time (#{@end}) of task #{@property.fullId} " + "is too early. Must be after #{@minend}.") end if !@maxend.nil? && @end > @maxend warning('maxend', "The end time (#{@end}) of task #{@property.fullId} " + "is too late. Must be before #{@maxend}.") end # Make sure the start is before the end if @start > @end error('start_after_end', "The start time (#{@start}) of task #{@property.fullId} " + "is after the end time (#{@end}).") end # Check that tasks fits into parent task. unless (parent = @property.parent).nil? || parent['start', @scenarioIdx].nil? || parent['end', @scenarioIdx].nil? if @start < parent['start', @scenarioIdx] error('task_start_in_parent', "The start date (#{@start}) of task #{@property.fullId} " + "is before the start date (#{parent['start', @scenarioIdx]}) " + "of the enclosing task.") end if @end > parent['end', @scenarioIdx] error('task_end_in_parent', "The end date (#{@end}) of task #{@property.fullId} " + "is after the end date (#{parent['end', @scenarioIdx]}) " + "of the enclosing task.") end end # Check that all preceding tasks start/end before this task. @depends.each do |dependency| task = dependency.task limit = task[dependency.onEnd ? 'end' : 'start', @scenarioIdx] next if limit.nil? if @start < limit || (dependency.gapDuration > 0 && limit + dependency.gapDuration > @start) || (dependency.gapLength > 0 && calcLength(limit, @start) < dependency.gapLength) error('task_pred_before', "Task #{@property.fullId} (#{@start}) must start " + (dependency.gapDuration > 0 ? "#{dependency.gapDuration / (60 * 60 * 24)} days " : (dependency.gapLength > 0 ? "#{@project.slotsToDays(dependency.gapLength)} " + "working days " : '')) + "after " + "#{dependency.onEnd ? 'end' : 'start'} (#{limit}) of task " + "#{task.fullId}. This condition could not be met.") end end # Check that all following tasks end before this task @precedes.each do |dependency| task = dependency.task limit = task[dependency.onEnd ? 'end' : 'start', @scenarioIdx] next if limit.nil? if limit < @end || (dependency.gapDuration > 0 && limit - dependency.gapDuration < @end) || (dependency.gapLength > 0 && calcLength(@end, limit) < dependency.gapLength) error('task_succ_after', "Task #{@property.fullId} (#{@end}) must end " + (dependency.gapDuration > 0 ? "#{dependency.gapDuration / (60 * 60 * 24)} days " : (dependency.gapLength > 0 ? "#{@project.slotsToDays(dependency.gapLength)} " + "working days " : '')) + "before " + "#{dependency.onEnd ? 'end' : 'start'} (#{limit}) of task " + "#{task.fullId}. This condition could not be met.") end end if @milestone && @start != @end error('milestone_times_equal', "Milestone #{@property.fullId} must have identical start and " + "end date.") end if @property.leaf? && @effort == 0 && !@milestone && !@allocate.empty? && @assignedresources.empty? # The user used an 'allocate' for the task, but did not specify any # 'effort'. Actual allocations will only happen when resources are # available by chance. If there are no assigned resources, we generate # a warning as this is probably not what the user intended. warning('allocate_no_assigned', "Task #{@property.id} has resource allocation requested, but " + "did not get any resources assigned. Either use 'effort' " + "to ensure allocations or use a higher 'priority'.") end thieves = [] @competitors.each do |t| thieves << t if t['priority', @scenarioIdx] < @priority end unless thieves.empty? warning('priority_inversion', "Due to a mix of ALAP and ASAP scheduled tasks or a " + "dependency on a lower priority tasks the following " + "task#{thieves.length > 1 ? 's' : ''} stole resources from " + "#{@property.fullId} despite having a lower priority:") thieves.each do |t| info('priority_inversion_info', "Task #{t.fullId}", t.sourceFileInfo) end end @errors == 0 end |