Class: WorkItemScheduler

Inherits:
Object
  • Object
show all
Defined in:
lib/almirah/project/work_item_scheduler.rb

Overview

Lays the WorkItem network (ADR-194) on an abstract day axis for the overview swimlane Gantt (ADR-198). It performs a deterministic forward pass over the dependency edges and then levels each owner's lane so two work items of the same owner never overlap.

Durations are a constant placeholder (3 days) while no per-row estimates exist; duration_for is the single hook ADR-195 overrides to feed real estimates without changing the scheduling logic.

Days are 1-based. A work item starting on day s with duration d occupies the inclusive day span s .. s + d - 1; its finish (the next free day, returned in the ends map) is s + d, the earliest a successor or the same owner's next item may start.

Direct Known Subclasses

ChainScheduler

Constant Summary collapse

DEFAULT_DURATION =

Placeholder duration for every work item until ADR-195 supplies estimates.

3

Instance Method Summary collapse

Constructor Details

#initialize(work_items, duration: DEFAULT_DURATION) ⇒ WorkItemScheduler

Returns a new instance of WorkItemScheduler.



22
23
24
25
26
# File 'lib/almirah/project/work_item_scheduler.rb', line 22

def initialize(work_items, duration: DEFAULT_DURATION)
  @items = work_items
  @duration = duration
  @item_set = work_items.to_set
end

Instance Method Details

#critical_chainObject

The critical chain: the row with the latest finish, traced back through its binding predecessors (the dependency and resource hand-offs that set each row's start), returned in start order. Empty when nothing is scheduled.



49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/almirah/project/work_item_scheduler.rb', line 49

def critical_chain
  schedule unless @starts
  return [] if @ends.empty?

  max_end = @ends.values.max
  node = @items.select { |wi| @ends[wi] == max_end }.min_by { |wi| [wi.record_id, wi.step] }
  chain = []
  while node
    chain.unshift(node)
    node = @binding[node]
  end
  chain
end

#day_countObject

The number of day columns the chart needs: the latest finish minus one (finishes are the exclusive next-free day). Zero when there are no items.



36
37
38
39
# File 'lib/almirah/project/work_item_scheduler.rb', line 36

def day_count
  schedule unless @ends
  @ends.empty? ? 0 : (@ends.values.max - 1)
end

#duration_for(_work_item) ⇒ Object



63
64
65
# File 'lib/almirah/project/work_item_scheduler.rb', line 63

def duration_for(_work_item)
  @duration
end

#makespanObject

The schedule length in working days (the latest finish, day 1 being the start).



42
43
44
# File 'lib/almirah/project/work_item_scheduler.rb', line 42

def makespan
  day_count
end

#start_daysObject

{ work_item => start_day }, day index 1-based. Empty when there are no items.



29
30
31
32
# File 'lib/almirah/project/work_item_scheduler.rb', line 29

def start_days
  schedule unless @starts
  @starts
end