Class: Decision
- Inherits:
-
PersistentDocument
- Object
- BaseDocument
- PersistentDocument
- Decision
- Defined in:
- lib/almirah/doc_types/decision.rb
Instance Attribute Summary collapse
-
#current_status ⇒ Object
Returns the value of attribute current_status.
-
#html_rel_path ⇒ Object
Returns the value of attribute html_rel_path.
-
#owners ⇒ Object
Returns the value of attribute owners.
-
#path ⇒ Object
Returns the value of attribute path.
-
#record_type ⇒ Object
Returns the value of attribute record_type.
-
#root_prefix ⇒ Object
Returns the value of attribute root_prefix.
-
#scope_table ⇒ Object
Returns the value of attribute scope_table.
-
#sequence_number ⇒ Object
Returns the value of attribute sequence_number.
-
#specifications_path ⇒ Object
Returns the value of attribute specifications_path.
-
#start_date ⇒ Object
Returns the value of attribute start_date.
-
#target_date ⇒ Object
Returns the value of attribute target_date.
-
#target_release_version ⇒ Object
Returns the value of attribute target_release_version.
-
#wrong_links_hash ⇒ Object
Returns the value of attribute wrong_links_hash.
Attributes inherited from PersistentDocument
#controlled_items, #frontmatter, #headings, #items, #up_link_docs
Attributes inherited from BaseDocument
#dom, #headings, #id, #output_rel_path, #title
Instance Method Summary collapse
-
#actual_hours ⇒ Object
Total logged effort in hours across the # Effort table (ADR-196); 0 when the record has no Effort section.
-
#actual_hours_on(date) ⇒ Object
Logged hours dated on or before
date(ADR-196). -
#declared_dependencies? ⇒ Boolean
A record declares prerequisites when any of its rows carries a Depends On reference; the overview Kit column is empty otherwise.
- #effective_status_on(date) ⇒ Object
-
#effort_date_range(item) ⇒ Object
The [earliest, latest] dated # Effort entry crediting the Scope row whose Item matches
item(case-insensitive) — the real logged span the Gantt's tracking lane draws (ADR-213). - #extract_current_status ⇒ Object
-
#extract_owners ⇒ Object
The distinct, first-seen-ordered list of non-empty Owner cells in the Scope table.
-
#extract_scope_table ⇒ Object
The parsed Scope ScopeTable (ADR-194), or nil when the record has no Scope section.
- #extract_start_date ⇒ Object
- #extract_target_date ⇒ Object
- #extract_target_release_version ⇒ Object
-
#fully_kitted? ⇒ Boolean
Kitted when every one of its work items is (a record with no rows is kitted).
-
#in_progress_owner_tally ⇒ Object
One entry per Scope row whose row Status is In-Progress, yielding that row's owner.
-
#initialize(file_path) ⇒ Decision
constructor
A new instance of Decision.
-
#kit_started_violation? ⇒ Boolean
A started row blocked by an unsatisfied cross-record predecessor — the overview emphasises such a record, matching the console warning.
-
#row_actual_hours_on(item, date) ⇒ Object
Logged hours dated on or before
datefor the Scope row whose Item matchesitem(case-insensitive) — the per-chain-row actual the fever chart credits (ADR-196). -
#scope_work_items ⇒ Object
The Scope rows as WorkItem nodes (ADR-194); empty when there is no ScopeTable.
- #to_console ⇒ Object
- #to_html(nav_pane, output_file_path) ⇒ Object
Methods inherited from BaseDocument
#critical_chain_link, #decisions_link, #home_link, #index_link, #needs_chartjs?, #rel_to, #save_html_to_file
Constructor Details
#initialize(file_path) ⇒ Decision
Returns a new instance of Decision.
14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/almirah/doc_types/decision.rb', line 14 def initialize(file_path) super @path = file_path stem = File.basename(file_path, File.extname(file_path)) assign_id_parts(stem) @current_status = nil @start_date = nil @target_date = nil @target_release_version = nil @wrong_links_hash = {} @owners = [] end |
Instance Attribute Details
#current_status ⇒ Object
Returns the value of attribute current_status.
10 11 12 |
# File 'lib/almirah/doc_types/decision.rb', line 10 def current_status @current_status end |
#html_rel_path ⇒ Object
Returns the value of attribute html_rel_path.
10 11 12 |
# File 'lib/almirah/doc_types/decision.rb', line 10 def html_rel_path @html_rel_path end |
#owners ⇒ Object
Returns the value of attribute owners.
10 11 12 |
# File 'lib/almirah/doc_types/decision.rb', line 10 def owners @owners end |
#path ⇒ Object
Returns the value of attribute path.
10 11 12 |
# File 'lib/almirah/doc_types/decision.rb', line 10 def path @path end |
#record_type ⇒ Object
Returns the value of attribute record_type.
10 11 12 |
# File 'lib/almirah/doc_types/decision.rb', line 10 def record_type @record_type end |
#root_prefix ⇒ Object
Returns the value of attribute root_prefix.
10 11 12 |
# File 'lib/almirah/doc_types/decision.rb', line 10 def root_prefix @root_prefix end |
#scope_table ⇒ Object
Returns the value of attribute scope_table.
10 11 12 |
# File 'lib/almirah/doc_types/decision.rb', line 10 def scope_table @scope_table end |
#sequence_number ⇒ Object
Returns the value of attribute sequence_number.
10 11 12 |
# File 'lib/almirah/doc_types/decision.rb', line 10 def sequence_number @sequence_number end |
#specifications_path ⇒ Object
Returns the value of attribute specifications_path.
10 11 12 |
# File 'lib/almirah/doc_types/decision.rb', line 10 def specifications_path @specifications_path end |
#start_date ⇒ Object
Returns the value of attribute start_date.
10 11 12 |
# File 'lib/almirah/doc_types/decision.rb', line 10 def start_date @start_date end |
#target_date ⇒ Object
Returns the value of attribute target_date.
10 11 12 |
# File 'lib/almirah/doc_types/decision.rb', line 10 def target_date @target_date end |
#target_release_version ⇒ Object
Returns the value of attribute target_release_version.
10 11 12 |
# File 'lib/almirah/doc_types/decision.rb', line 10 def target_release_version @target_release_version end |
#wrong_links_hash ⇒ Object
Returns the value of attribute wrong_links_hash.
10 11 12 |
# File 'lib/almirah/doc_types/decision.rb', line 10 def wrong_links_hash @wrong_links_hash end |
Instance Method Details
#actual_hours ⇒ Object
Total logged effort in hours across the # Effort table (ADR-196); 0 when the record has no Effort section. Undated and unparseable entries still count toward the record total.
164 165 166 |
# File 'lib/almirah/doc_types/decision.rb', line 164 def actual_hours effort_entries.sum { |e| e[:hours] } end |
#actual_hours_on(date) ⇒ Object
Logged hours dated on or before date (ADR-196). Undated entries are
excluded since they cannot be placed on the timeline.
170 171 172 |
# File 'lib/almirah/doc_types/decision.rb', line 170 def actual_hours_on(date) effort_entries.sum { |e| e[:date] && e[:date] <= date ? e[:hours] : 0.0 } end |
#declared_dependencies? ⇒ Boolean
A record declares prerequisites when any of its rows carries a Depends On reference; the overview Kit column is empty otherwise.
101 102 103 |
# File 'lib/almirah/doc_types/decision.rb', line 101 def declared_dependencies? scope_work_items.any? { |wi| wi.depends_on_refs.any? } end |
#effective_status_on(date) ⇒ Object
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/almirah/doc_types/decision.rb', line 136 def effective_status_on(date) table = find_section_table('Status') return nil if table.nil? date_idx = column_index(table, 'Date') status_idx = column_index(table, 'Status') return nil if date_idx.nil? || status_idx.nil? best_idx = nil best_date = nil table.rows.each_with_index do |row, i| parsed = parse_dd_mm_yyyy(row[date_idx]) next if parsed.nil? || parsed > date if best_date.nil? || parsed > best_date || (parsed == best_date && i > best_idx) best_date = parsed best_idx = i end end return nil if best_idx.nil? status = table.rows[best_idx][status_idx].to_s.strip status.empty? ? nil : status end |
#effort_date_range(item) ⇒ Object
The [earliest, latest] dated # Effort entry crediting the Scope row whose Item
matches item (case-insensitive) — the real logged span the Gantt's tracking
lane draws (ADR-213). nil when the row has no dated effort. Undated entries are
excluded since they cannot be placed on the timeline.
190 191 192 193 194 195 196 |
# File 'lib/almirah/doc_types/decision.rb', line 190 def effort_date_range(item) key = item.to_s.strip.downcase return nil if key.empty? dates = effort_entries.filter_map { |e| e[:date] if e[:item] == key } dates.empty? ? nil : dates.minmax end |
#extract_current_status ⇒ Object
42 43 44 45 46 47 48 49 |
# File 'lib/almirah/doc_types/decision.rb', line 42 def extract_current_status status_table = find_section_table('Status') return if status_table.nil? status_table.is_decision_status_table = true marker_rows = status_table.rows.select { |row| row[0].to_s.strip == '*' } @current_status = marker_rows.length == 1 ? marker_rows[0][-1].to_s.strip : nil end |
#extract_owners ⇒ Object
The distinct, first-seen-ordered list of non-empty Owner cells in the Scope table. Empty when there is no Scope table, no Owner column, or no owner values. The Owner column is located by header text, not position.
73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/almirah/doc_types/decision.rb', line 73 def extract_owners @owners = [] table = find_section_table('Scope') return if table.nil? owner_idx = column_index(table, 'Owner') return if owner_idx.nil? table.cells.each do |row| owner = row[owner_idx].to_s.strip @owners << owner unless owner.empty? || @owners.include?(owner) end end |
#extract_scope_table ⇒ Object
The parsed Scope ScopeTable (ADR-194), or nil when the record has no Scope section. Memoised so the work-item network and the readers share one table.
89 90 91 92 |
# File 'lib/almirah/doc_types/decision.rb', line 89 def extract_scope_table table = find_section_table('Scope') @scope_table = table.is_a?(ScopeTable) ? table : nil end |
#extract_start_date ⇒ Object
51 52 53 54 |
# File 'lib/almirah/doc_types/decision.rb', line 51 def extract_start_date dates = collect_dates('Status', 'Date') + collect_dates('Scope', 'Start Date') @start_date = dates.min end |
#extract_target_date ⇒ Object
56 57 58 59 |
# File 'lib/almirah/doc_types/decision.rb', line 56 def extract_target_date dates = collect_dates('Status', 'Date') + collect_dates('Scope', 'Target Date') @target_date = dates.max end |
#extract_target_release_version ⇒ Object
61 62 63 64 65 66 67 68 |
# File 'lib/almirah/doc_types/decision.rb', line 61 def extract_target_release_version @target_release_version = lookup_cell( section_name: 'Software Versions', key_column: 'Software Version Category', value_column: 'Software Version ID', key: 'Target Release Version' ) end |
#fully_kitted? ⇒ Boolean
Kitted when every one of its work items is (a record with no rows is kitted).
106 107 108 |
# File 'lib/almirah/doc_types/decision.rb', line 106 def fully_kitted? scope_work_items.all?(&:fully_kitted?) end |
#in_progress_owner_tally ⇒ Object
One entry per Scope row whose row Status is In-Progress, yielding that row's owner. Rows without an owner, or not In-Progress, contribute nothing. The per-row Status is read directly and is independent of the record's lifecycle status. Owner and Status columns are located by header text, not position.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/almirah/doc_types/decision.rb', line 120 def in_progress_owner_tally table = find_section_table('Scope') return [] if table.nil? owner_idx = column_index(table, 'Owner') status_idx = column_index(table, 'Status') return [] if owner_idx.nil? || status_idx.nil? table.cells.filter_map do |row| owner = row[owner_idx].to_s.strip next if owner.empty? owner if row[status_idx].to_s.strip == 'In-Progress' end end |
#kit_started_violation? ⇒ Boolean
A started row blocked by an unsatisfied cross-record predecessor — the overview emphasises such a record, matching the console warning.
112 113 114 |
# File 'lib/almirah/doc_types/decision.rb', line 112 def kit_started_violation? scope_work_items.any?(&:cross_record_violation?) end |
#row_actual_hours_on(item, date) ⇒ Object
Logged hours dated on or before date for the Scope row whose Item matches
item (case-insensitive) — the per-chain-row actual the fever chart credits
(ADR-196). Entries with no Item credit no row and are excluded here.
177 178 179 180 181 182 183 184 |
# File 'lib/almirah/doc_types/decision.rb', line 177 def row_actual_hours_on(item, date) key = item.to_s.strip.downcase return 0.0 if key.empty? effort_entries.sum do |e| e[:item] == key && e[:date] && e[:date] <= date ? e[:hours] : 0.0 end end |
#scope_work_items ⇒ Object
The Scope rows as WorkItem nodes (ADR-194); empty when there is no ScopeTable.
95 96 97 |
# File 'lib/almirah/doc_types/decision.rb', line 95 def scope_work_items @scope_table ? @scope_table.work_items : [] end |
#to_console ⇒ Object
27 28 29 |
# File 'lib/almirah/doc_types/decision.rb', line 27 def to_console puts "\e[36mDecision: #{@id}\e[0m" end |
#to_html(nav_pane, output_file_path) ⇒ Object
31 32 33 34 35 36 37 38 39 40 |
# File 'lib/almirah/doc_types/decision.rb', line 31 def to_html(nav_pane, output_file_path) html_rows = [] html_rows.append('') @items.each do |item| html_rows.append item.to_html end save_html_to_file(html_rows, nav_pane, output_file_path) end |