Class: FeverChart

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

Overview

The buffer-consumption fever chart for one decision group (ADR-196): given the group's CriticalChain plan, the effort logged on its records, and the working- hours-per-day conversion, it produces the (completion%, consumption%) point and the historical trail the Critical Chain page plots.

It tracks only chain rows with a positive focused estimate (a zero-estimate row carries no schedule weight). Per-row actual effort is read from the owning Decision's append-only # Effort log via row_actual_hours_on, converted to days; the chart never consults the record lifecycle status.

It reads the plan's baseline chain and buffer (completed rows included, issue-207), not the remaining-work chain: a chain row that overran and then was marked Done has consumed real buffer that must stay accounted, and the consumption denominator must not shrink as rows finish. The live point still credits a Done row in full via its per-row Status (ADR-196); historical trail points reconstruct even a completed row's progress and overrun from its dated

Effort log, which a per-row Status (no dated history) could not.

Instance Method Summary collapse

Constructor Details

#initialize(plan, record_lookup, hours_per_day: 8) ⇒ FeverChart

record_lookup maps an upcased record id (e.g. "ADR-196") to its Decision.



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

def initialize(plan, record_lookup, hours_per_day: 8)
  @rows = plan.baseline_chain.select { |wi| wi.focused_estimate.positive? }
  @buffer = plan.baseline_buffer
  @record_lookup = record_lookup
  @hours_per_day = hours_per_day.to_f
end

Instance Method Details

#consumed_days(date) ⇒ Object

The baseline buffer days these overruns have consumed as of date -- the numerator behind the consumption percentage (its denominator is the baseline buffer). Lets the Critical Chain page report "X of Y baseline days".



55
56
57
# File 'lib/almirah/project/fever_chart.rb', line 55

def consumed_days(date)
  @rows.sum { |wi| [actual_days(wi, date) - wi.focused_estimate, 0].max }
end

#live_point(date) ⇒ Object

The live fever point [completion%, consumption%] as of date: a Done row credits full completion regardless of logged effort, matching the bounded per-row Status (ADR-193); other rows credit logged effort only.



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

def live_point(date)
  [completion(date, live: true), consumption(date)]
end

#plottable?Boolean

True when there is anything to plot (at least one positive-estimate chain row).

Returns:

  • (Boolean)


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

def plottable?
  @rows.any?
end

#point_on(date) ⇒ Object

A historical point [completion%, consumption%] as of date, from logged effort only (the per-row Status has no dated history to replay).



43
44
45
# File 'lib/almirah/project/fever_chart.rb', line 43

def point_on(date)
  [completion(date, live: false), consumption(date)]
end

#trail(dates) ⇒ Object

One historical point per date (recent Fridays), in the given order.



48
49
50
# File 'lib/almirah/project/fever_chart.rb', line 48

def trail(dates)
  dates.map { |d| point_on(d) }
end