Class: Saga::Planning

Inherits:
Object
  • Object
show all
Defined in:
lib/saga/planning.rb

Constant Summary collapse

BLANK_ITERATION =
{ story_count: 0, estimate_total_in_hours: 0 }.freeze
FIRST_COLUMN_WIDTH =
14

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(document) ⇒ Planning

Returns a new instance of Planning.



5
6
7
8
9
10
11
# File 'lib/saga/planning.rb', line 5

def initialize(document)
  unless document
    raise ArgumentError, 'Please supply a document for planning.'
  end

  @document = document
end

Class Method Details

.estimate_to_hours(estimate) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/saga/planning.rb', line 87

def self.estimate_to_hours(estimate)
  case estimate[1]
  when :days
    estimate[0] * 8
  when :weeks
    estimate[0] * 40
  when :range
    0
  else
    estimate[0]
  end
end

.format_properties(iteration, properties) ⇒ Object



100
101
102
103
104
105
106
107
108
# File 'lib/saga/planning.rb', line 100

def self.format_properties(iteration, properties)
  label = if iteration
            iteration == -1 ? 'Unplanned' : "Iteration #{iteration}"
          else
            'Total'
          end
  story_column = format_stories_count(properties[:story_count])
  "#{label.ljust(FIRST_COLUMN_WIDTH)}: #{properties[:estimate_total_in_hours]} (#{story_column})"
end

.format_range_estimated(range_estimated) ⇒ Object



114
115
116
# File 'lib/saga/planning.rb', line 114

def self.format_range_estimated(range_estimated)
  "Range-estimate: #{format_stories_count(range_estimated)}"
end

.format_statusses(statusses) ⇒ Object



122
123
124
125
126
127
128
# File 'lib/saga/planning.rb', line 122

def self.format_statusses(statusses)
  parts = []
  statusses.each do |status, hours|
    parts << "#{status.capitalize.ljust(FIRST_COLUMN_WIDTH)}: #{hours}"
  end
  parts.join("\n")
end

.format_stories_count(count) ⇒ Object



118
119
120
# File 'lib/saga/planning.rb', line 118

def self.format_stories_count(count)
  count > 1 ? "#{count} stories" : 'one story'
end

.format_unestimated(unestimated) ⇒ Object



110
111
112
# File 'lib/saga/planning.rb', line 110

def self.format_unestimated(unestimated)
  "Unestimated   : #{format_stories_count(unestimated)}"
end

Instance Method Details

#iterationsObject



13
14
15
16
17
18
19
20
21
22
# File 'lib/saga/planning.rb', line 13

def iterations
  @document.stories_as_flat_list.each_with_object({}) do |story, properties|
    next unless story[:estimate]

    iteration = story[:iteration] || -1
    properties[iteration] ||= BLANK_ITERATION.dup
    properties[iteration][:story_count] += 1
    properties[iteration][:estimate_total_in_hours] += self.class.estimate_to_hours(story[:estimate])
  end
end

#range_estimatedObject



41
42
43
44
45
46
47
48
49
# File 'lib/saga/planning.rb', line 41

def range_estimated
  range_estimated = 0
  @document.stories_as_flat_list.each do |story|
    if story[:estimate] && story[:estimate][1] == :range
      range_estimated += 1
    end
  end
  range_estimated
end

#statussesObject



51
52
53
54
55
56
57
58
59
60
# File 'lib/saga/planning.rb', line 51

def statusses
  statusses = {}
  @document.stories_as_flat_list.each do |story|
    if story[:estimate] && story[:status]
      statusses[story[:status]] ||= 0
      statusses[story[:status]] += self.class.estimate_to_hours(story[:estimate])
    end
  end
  statusses
end

#to_sObject



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/saga/planning.rb', line 62

def to_s
  if @document.empty?
    'There are no stories yet.'
  else
    parts = iterations.keys.sort.map do |iteration|
      self.class.format_properties(iteration, iterations[iteration])
    end
    unless parts.empty?
      formatted_totals = self.class.format_properties(false, total)
      parts << '-' * formatted_totals.length
      parts << formatted_totals
    end
    if (unestimated > 0) || !statusses.empty?
      parts << ''
      parts << self.class.format_unestimated(unestimated) if unestimated > 0
      parts << self.class.format_range_estimated(range_estimated) if range_estimated > 0
      parts << self.class.format_statusses(statusses) unless statusses.empty?
    end
    parts.shift if parts[0] == ''
    parts.join("\n")
  end
end

#totalObject



24
25
26
27
28
29
30
31
# File 'lib/saga/planning.rb', line 24

def total
  total = BLANK_ITERATION.dup
  iterations.each do |_iteration, properties|
    total[:story_count] += properties[:story_count]
    total[:estimate_total_in_hours] += properties[:estimate_total_in_hours]
  end
  total
end

#unestimatedObject



33
34
35
36
37
38
39
# File 'lib/saga/planning.rb', line 33

def unestimated
  unestimated = 0
  @document.stories_as_flat_list.each do |story|
    unestimated += 1 unless story[:estimate]
  end
  unestimated
end