Class: ProjectConfiguration
- Inherits:
-
Object
- Object
- ProjectConfiguration
- Defined in:
- lib/almirah/project_configuration.rb
Constant Summary collapse
- DEFAULT_WIP_LIMIT =
2- DEFAULT_BUFFER_RATIO =
0.5- DEFAULT_HOURS_PER_DAY =
8
Instance Attribute Summary collapse
-
#parameters ⇒ Object
Returns the value of attribute parameters.
-
#project_root_directory ⇒ Object
Returns the value of attribute project_root_directory.
Instance Method Summary collapse
-
#get_buffer_ratio ⇒ Object
The CCPM project-buffer ratio (ADR-195): a fraction in (0, 1] cutting the aggregated chain safety.
- #get_design_inputs ⇒ Object
-
#get_group_start_dates ⇒ Object
Per-group planning start dates (ADR-211): a map from a decision group's first-level folder name (under decisions/) to its start Date, read from planning.groups as DD-MM-YYYY entries.
-
#get_holidays ⇒ Object
The non-working holiday dates (ADR-205) from planning.holidays, each a DD-MM-YYYY entry; unparseable entries are dropped.
-
#get_hours_per_day ⇒ Object
Working hours per day (ADR-196): converts logged effort hours into the working-day unit the estimates use.
- #get_repositories ⇒ Object
-
#get_risk_columns(folder) ⇒ Object
The ordered register-column list for a risk registry folder (ADR-216), read from the risks: root — a list of { folder:, columns: } entries.
-
#get_risk_rpn_groups(folder) ⇒ Object
The named RPN groups of a risk registry folder (ADR-217), from the rpn: list of its risks: entry, in configured order: [{ name:, inputs: [..], acceptable:, unacceptable: }, ...].
-
#get_start_date ⇒ Object
The calendar anchor for working day 1 (ADR-205), a Date parsed from a DD-MM-YYYY planning.start_date.
- #get_wip_limit ⇒ Object
-
#initialize(path) ⇒ ProjectConfiguration
constructor
A new instance of ProjectConfiguration.
- #is_spec_db_shall_be_created ⇒ Object
- #load_project_file ⇒ Object
- #numeric_threshold(value) ⇒ Object
-
#parse_planning_date(value) ⇒ Object
Parse a planning date that may already be a Date (YAML ISO form) or a DD-MM-YYYY string; nil when neither.
-
#planning_value(key) ⇒ Object
A value under the planning: key, or nil when planning is absent.
-
#risk_entry(folder) ⇒ Object
The risks: entry configuring a registry folder, or nil when absent.
- #risk_rpn_group(raw) ⇒ Object
Constructor Details
#initialize(path) ⇒ ProjectConfiguration
Returns a new instance of ProjectConfiguration.
11 12 13 14 15 |
# File 'lib/almirah/project_configuration.rb', line 11 def initialize(path) @project_root_directory = File.(path) @parameters = {} load_project_file end |
Instance Attribute Details
#parameters ⇒ Object
Returns the value of attribute parameters.
9 10 11 |
# File 'lib/almirah/project_configuration.rb', line 9 def parameters @parameters end |
#project_root_directory ⇒ Object
Returns the value of attribute project_root_directory.
9 10 11 |
# File 'lib/almirah/project_configuration.rb', line 9 def project_root_directory @project_root_directory end |
Instance Method Details
#get_buffer_ratio ⇒ Object
The CCPM project-buffer ratio (ADR-195): a fraction in (0, 1] cutting the aggregated chain safety. Absent or out-of-range falls back to the 0.5 default.
51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/almirah/project_configuration.rb', line 51 def get_buffer_ratio return DEFAULT_BUFFER_RATIO unless @parameters.is_a?(Hash) planning = @parameters['planning'] return DEFAULT_BUFFER_RATIO unless planning.is_a?(Hash) value = planning['buffer_ratio'] return DEFAULT_BUFFER_RATIO unless value.is_a?(Numeric) && value.positive? && value <= 1 value end |
#get_design_inputs ⇒ Object
25 26 27 28 29 |
# File 'lib/almirah/project_configuration.rb', line 25 def get_design_inputs return @parameters['specifications']['input'] if (@parameters.key? 'specifications') and (@parameters['specifications'].key? 'input') [] end |
#get_group_start_dates ⇒ Object
Per-group planning start dates (ADR-211): a map from a decision group's first-level folder name (under decisions/) to its start Date, read from planning.groups as DD-MM-YYYY entries. Non-string or unparseable values are dropped; empty when unset. A group absent from the map sequences after the previous group rather than carrying a declared start.
76 77 78 79 80 81 82 83 84 |
# File 'lib/almirah/project_configuration.rb', line 76 def get_group_start_dates value = planning_value('groups') return {} unless value.is_a?(Hash) value.each_with_object({}) do |(name, raw), acc| date = parse_planning_date(raw) acc[name.to_s] = date if date end end |
#get_holidays ⇒ Object
The non-working holiday dates (ADR-205) from planning.holidays, each a DD-MM-YYYY entry; unparseable entries are dropped. Empty when unset.
88 89 90 91 92 93 |
# File 'lib/almirah/project_configuration.rb', line 88 def get_holidays value = planning_value('holidays') return [] unless value.is_a?(Array) value.filter_map { |entry| parse_planning_date(entry) } end |
#get_hours_per_day ⇒ Object
Working hours per day (ADR-196): converts logged effort hours into the working-day unit the estimates use. Absent or non-positive falls back to 8.
97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/almirah/project_configuration.rb', line 97 def get_hours_per_day return DEFAULT_HOURS_PER_DAY unless @parameters.is_a?(Hash) planning = @parameters['planning'] return DEFAULT_HOURS_PER_DAY unless planning.is_a?(Hash) value = planning['hours_per_day'] return DEFAULT_HOURS_PER_DAY unless value.is_a?(Numeric) && value.positive? value end |
#get_repositories ⇒ Object
31 32 33 34 35 |
# File 'lib/almirah/project_configuration.rb', line 31 def get_repositories return @parameters['repositories'] if @parameters.key? 'repositories' [] end |
#get_risk_columns(folder) ⇒ Object
The ordered register-column list for a risk registry folder (ADR-216), read from the risks: root — a list of { folder:, columns: } entries. nil when the registry carries no configuration; such a registry renders the implicit columns plus Status only.
113 114 115 116 117 118 |
# File 'lib/almirah/project_configuration.rb', line 113 def get_risk_columns(folder) entry = risk_entry(folder) return nil unless entry.is_a?(Hash) && entry['columns'].is_a?(Array) entry['columns'].map(&:to_s) end |
#get_risk_rpn_groups(folder) ⇒ Object
The named RPN groups of a risk registry folder (ADR-217), from the rpn: list of its risks: entry, in configured order: [{ name:, inputs: [..], acceptable:, unacceptable: }, ...]. Groups without a name or a non-empty inputs list are dropped; a threshold bound that is absent or not numeric is nil. Empty when the registry declares no groups.
125 126 127 128 129 130 |
# File 'lib/almirah/project_configuration.rb', line 125 def get_risk_rpn_groups(folder) entry = risk_entry(folder) return [] unless entry.is_a?(Hash) && entry['rpn'].is_a?(Array) entry['rpn'].filter_map { |raw| risk_rpn_group(raw) } end |
#get_start_date ⇒ Object
The calendar anchor for working day 1 (ADR-205), a Date parsed from a DD-MM-YYYY planning.start_date. Absent or unparseable falls back to today, so an unconfigured project still renders (a moving anchor).
66 67 68 69 |
# File 'lib/almirah/project_configuration.rb', line 66 def get_start_date date = parse_planning_date(planning_value('start_date')) date || Date.today end |
#get_wip_limit ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/almirah/project_configuration.rb', line 37 def get_wip_limit return DEFAULT_WIP_LIMIT unless @parameters.is_a?(Hash) planning = @parameters['planning'] return DEFAULT_WIP_LIMIT unless planning.is_a?(Hash) value = planning['wip_limit'] return DEFAULT_WIP_LIMIT unless value.is_a?(Integer) && value.positive? value end |
#is_spec_db_shall_be_created ⇒ Object
132 133 134 135 136 137 138 139 |
# File 'lib/almirah/project_configuration.rb', line 132 def is_spec_db_shall_be_created if @parameters.key? 'output' @parameters['output'].each do |p| return true if p == 'specifications_db' end end false end |
#load_project_file ⇒ Object
17 18 19 20 21 22 23 |
# File 'lib/almirah/project_configuration.rb', line 17 def load_project_file @parameters = YAML.load_file(@project_root_directory + '/project.yml') rescue Psych::SyntaxError => e puts "YAML syntax error: #{e.}" rescue Errno::ENOENT puts 'Project file not found: project.yml' end |
#numeric_threshold(value) ⇒ Object
164 165 166 |
# File 'lib/almirah/project_configuration.rb', line 164 def numeric_threshold(value) value.is_a?(Numeric) ? value : nil end |
#parse_planning_date(value) ⇒ Object
Parse a planning date that may already be a Date (YAML ISO form) or a DD-MM-YYYY string; nil when neither.
178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/almirah/project_configuration.rb', line 178 def parse_planning_date(value) return value if value.is_a?(Date) return nil unless value.is_a?(String) match = /\A(\d{2})-(\d{2})-(\d{4})\z/.match(value.strip) return nil unless match Date.new(match[3].to_i, match[2].to_i, match[1].to_i) rescue ArgumentError nil end |
#planning_value(key) ⇒ Object
A value under the planning: key, or nil when planning is absent.
169 170 171 172 173 174 |
# File 'lib/almirah/project_configuration.rb', line 169 def planning_value(key) return nil unless @parameters.is_a?(Hash) planning = @parameters['planning'] planning.is_a?(Hash) ? planning[key] : nil end |
#risk_entry(folder) ⇒ Object
The risks: entry configuring a registry folder, or nil when absent.
142 143 144 145 146 147 148 149 |
# File 'lib/almirah/project_configuration.rb', line 142 def risk_entry(folder) return nil unless @parameters.is_a?(Hash) entries = @parameters['risks'] return nil unless entries.is_a?(Array) entries.find { |e| e.is_a?(Hash) && e['folder'].to_s == folder } end |
#risk_rpn_group(raw) ⇒ Object
151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/almirah/project_configuration.rb', line 151 def risk_rpn_group(raw) return nil unless raw.is_a?(Hash) name = raw['name'].to_s inputs = raw['inputs'] return nil if name.empty? || !inputs.is_a?(Array) || inputs.empty? thresholds = raw['thresholds'].is_a?(Hash) ? raw['thresholds'] : {} { name: name, inputs: inputs.map(&:to_s), acceptable: numeric_threshold(thresholds['acceptable']), unacceptable: numeric_threshold(thresholds['unacceptable']) } end |