Class: ProjectConfiguration

Inherits:
Object
  • Object
show all
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

Instance Method Summary collapse

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.expand_path(path)
  @parameters = {}
  load_project_file
end

Instance Attribute Details

#parametersObject

Returns the value of attribute parameters.



9
10
11
# File 'lib/almirah/project_configuration.rb', line 9

def parameters
  @parameters
end

#project_root_directoryObject

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_ratioObject

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_inputsObject



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_datesObject

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_holidaysObject

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_dayObject

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_repositoriesObject



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_start_dateObject

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_limitObject



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_createdObject



109
110
111
112
113
114
115
116
# File 'lib/almirah/project_configuration.rb', line 109

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_fileObject



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.message}"
rescue Errno::ENOENT
  puts 'Project file not found: project.yml'
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.



128
129
130
131
132
133
134
135
136
137
138
# File 'lib/almirah/project_configuration.rb', line 128

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.



119
120
121
122
123
124
# File 'lib/almirah/project_configuration.rb', line 119

def planning_value(key)
  return nil unless @parameters.is_a?(Hash)

  planning = @parameters['planning']
  planning.is_a?(Hash) ? planning[key] : nil
end