Class: Burndown

Inherits:
Object
  • Object
show all
Defined in:
app/models/rb_sprint.rb

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (Burndown) initialize(sprint, direction)

A new instance of Burndown



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'app/models/rb_sprint.rb', line 4

def initialize(sprint, direction)
  @direction = direction
  @sprint_id = sprint.id
  @days = sprint.days(:all)

  stories = sprint.stories
  
  case Backlogs.platform
    when :redmine
      stories |= Journal.find(:all, :joins => :details,
                      :conditions => ["journalized_type = 'Issue'
                            and property = 'attr' and prop_key = 'fixed_version_id'
                            and (value = ? or old_value = ?)", sprint.id.to_s, sprint.id.to_s]).reject{|j| j.journalized.nil? }.collect{|j| j.journalized.becomes(RbStory) }
    when :chiliproject
      # chiliproject journals are not meant to be scanned, unfortunately. This will be slow.
      stories |= Journal.find(:all,
                              :conditions => ["type = 'Issue'"]).select{|j|
                              j.changes['fixed_version_id'].first == sprint.id || j.changes['fixed_version_id'].last == sprint.id}.collect{|j|
                              RbStory.find(j.journaled_id) }
  end

  baseline = [0] * (sprint.days(:active).size + 1)
  baseline += [nil] * (1 + (@days.size - baseline.size))

  series = Backlogs::MergedArray.new
  series.merge(:hours => baseline.dup)
  series.merge(:points => baseline.dup)
  series.merge(:points_resolved => baseline.dup)
  series.merge(:points_accepted => baseline.dup)

  stories.each { |story| series.add(story.burndown(sprint)) }

  series.merge(:to_resolve => series.collect{|r| r.points && r.points_resolved ? r.points - r.points_resolved : nil})
  series.merge(:to_accept => series.collect{|a| a.points && a.points_accepted ? a.points - a.points_accepted : nil})

  series.merge(:days_left => (0..@days.size).collect{|d| @days.size - d})

  @data = {}

  @data[:points_committed] = series.collect{|s| s.points }
  @data[:hours_remaining] = series.collect{|s| s.hours }
  @data[:points_accepted] = series.collect{|s| s.points_accepted }
  @data[:points_resolved] = series.collect{|s| s.points_resolved }
  @data[:points_to_resolve] = series.collect{|s| s.to_resolve }
  @data[:points_to_accept] = series.collect{|s| s.to_accept }

  @data[:ideal] = (0..@days.size).to_a.reverse

  @data[:points_required_burn_rate] = series.collect{|r| r.to_resolve ? Float(r.to_resolve) / (r.days_left == 0 ? 1 : r.days_left) : nil }
  @data[:hours_required_burn_rate] = series.collect{|r| r.hours ? Float(r.hours) / (r.days_left == 0 ? 1 : r.days_left) : nil }

  case direction
    when 'up'
      @data.delete(:points_to_resolve)
      @data.delete(:points_to_accept)
    when 'down'
      @data.delete(:points_resolved)
      @data.delete(:points_accepted)
    else
      raise "Unexpected burn direction #{direction.inspect}"
  end
end

Instance Attribute Details

- (Object) data (readonly)

Returns the value of attribute data



92
93
94
# File 'app/models/rb_sprint.rb', line 92

def data
  @data
end

- (Object) days (readonly)

Returns the value of attribute days



90
91
92
# File 'app/models/rb_sprint.rb', line 90

def days
  @days
end

- (Object) direction (readonly)

Returns the value of attribute direction



93
94
95
# File 'app/models/rb_sprint.rb', line 93

def direction
  @direction
end

- (Object) sprint_id (readonly)

Returns the value of attribute sprint_id



91
92
93
# File 'app/models/rb_sprint.rb', line 91

def sprint_id
  @sprint_id
end

Instance Method Details

- (Object) [](i)



67
68
69
70
71
# File 'app/models/rb_sprint.rb', line 67

def [](i)
  i = i.intern if i.is_a?(String)
  raise "No burn#{@direction} data series '#{i}', available: #{@data.keys.inspect}" unless @data[i]
  return @data[i]
end

- (Object) series(remove_empty = true)



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'app/models/rb_sprint.rb', line 73

def series(remove_empty = true)
  @series ||= {}
  return @series[remove_empty] if @series[remove_empty]

  @series[remove_empty] = @data.keys.collect{|k| k.to_s}.sort
  return @series[remove_empty] unless remove_empty

  # delete :points_committed if flatline
  @series[remove_empty].delete('points_committed') if @data[:points_committed].uniq.compact.size < 1

  # delete any series that is flat-line 0/nil
  @series[remove_empty].each {|k|
    @series[remove_empty].delete(k) if k != 'points_committed' && @data[k.intern].collect{|d| d.to_f }.uniq == [0.0]
  }
  return @series[remove_empty]
end