backlog 0.5.8 → 0.5.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,7 @@
1
+ == 0.5.9 2007-08-06
2
+
3
+ * Aligned burn down graphs to even numbers
4
+
1
5
  == 0.5.8 2007-08-06
2
6
 
3
7
  * Fixed bug in daily_work_sheet
@@ -108,82 +108,11 @@ class PeriodsController < ApplicationController
108
108
 
109
109
  def send_burn_down_chart(size)
110
110
  period = Period.find(params[:id])
111
- g = Gruff::Line.new(size)
112
- g.theme_37signals
113
- g.title = l(:burn_down_chart) + " " + period.to_s
114
- g.font = '/usr/share/fonts/bitstream-vera/Vera.ttf'
115
- g.legend_font_size = 14
116
- g.hide_dots = true
117
- g.colors = %w{blue orange}
118
- if period.track_work?
119
- g.colors += %w{green}
120
- end
121
- if previous_period = period.higher_item
122
- g.colors += %w{grey grey}
123
- end
124
- if period.active?
125
- g.colors += %w{lightblue #d7a790}
126
- end
127
-
128
- recorded_dates = period.recorded_dates
129
- observed_todo_data = get_todo_data(recorded_dates, period)
130
- actual_todo_data = get_todo_data(recorded_dates, period, true)
131
- g.data("#{l :todo} (#{l :obs})", observed_todo_data)
132
- g.data("#{l :calc}", actual_todo_data)
133
- g.data(l(:done), get_work_data(recorded_dates, period)) if period.track_work?
134
- if previous_period = period.higher_item
135
- g.data("#{l :previous} #{l :obs}", get_todo_data(previous_period.dates, previous_period))
136
- g.data("#{l :calc}", get_todo_data(previous_period.dates, previous_period, true))
137
- end
138
-
139
- if period.active?
140
- g.data(l(:projection), projection_data(observed_todo_data, period))
141
- g.data(l(:projection), projection_data(actual_todo_data, period))
142
- end
143
-
144
- g.minimum_value = 0
145
-
146
- all_dates = period.dates
147
- labels = {0 => all_dates.first.to_s, all_dates.length-1 => all_dates.last.to_s}
148
- labels.merge({all_dates.index(Date.today) => Date.today.to_s}) if all_dates.index(Date.today) && (all_dates.index(Date.today) / all_dates.length) > 0.10
149
- g.labels = labels
150
-
151
- # g.draw_vertical_legend
152
-
153
- g.maximum_value = g.maximum_value.to_i
154
-
111
+ g = period.burn_down_graph(size)
155
112
  send_data(g.to_blob,
156
113
  :disposition => 'inline',
157
114
  :type => 'image/png',
158
115
  :filename => "burn_down_chart.png")
159
116
  end
160
117
 
161
- def get_todo_data(dates, period, actual=false)
162
- dates.map { |date| period.estimate_data(date, actual) }
163
- end
164
-
165
- def get_work_data(dates, period)
166
- dates.map { |date| period.work_data(date) }
167
- end
168
-
169
- def projection_data(observed_todo_data, period)
170
- if observed_todo_data.length <= 1
171
- velocity = 0
172
- else
173
- velocity = (observed_todo_data[-1] - observed_todo_data[0]).to_f / (observed_todo_data.length-1)
174
- end
175
- projection_data = period.dates.map do |date|
176
- if date < Date.today
177
- nil
178
- else
179
- if observed_todo_data.length == 1
180
- observed_todo_data[0]
181
- else
182
- value = observed_todo_data[0] + (date-period.start_on).to_f*velocity
183
- value >= 0 ? value : 0
184
- end
185
- end
186
- end
187
- end
188
-
189
118
  end
@@ -1,14 +1,16 @@
1
1
  class Period < ActiveRecord::Base
2
+ include Localization
3
+
2
4
  belongs_to :party
3
5
  acts_as_list :scope => :party, :order => :position
4
6
  has_many :tasks, :order => 'position, finished_at', :dependent => :destroy
5
7
  validates_associated :party
6
8
  validates_uniqueness_of :position, :scope => :party_id
7
-
9
+
8
10
  def validate
9
11
  errors.add "A period cannot end before it starts" unless end_on >= start_on
10
12
  end
11
-
13
+
12
14
  def self.find_active_or_future
13
15
  find(:all, :conditions => "end_on >= '#{Date.today.strftime '%Y-%m-%d'}'")
14
16
  end
@@ -16,11 +18,11 @@ class Period < ActiveRecord::Base
16
18
  def completed_tasks
17
19
  tasks.select {|task| task.completed?}
18
20
  end
19
-
21
+
20
22
  def open_tasks
21
23
  tasks.select {|task| task.active?}
22
24
  end
23
-
25
+
24
26
  def most_frequent_backlog
25
27
  all_backlogs = tasks.map {|t| t.backlog}.compact
26
28
  return nil if all_backlogs.empty?
@@ -35,7 +37,7 @@ class Period < ActiveRecord::Base
35
37
  def active?(check_tasks = false)
36
38
  start_on <= Date.today && (end_on >= Date.today || (check_tasks && tasks.select {|task| task.active?}.size > 0))
37
39
  end
38
-
40
+
39
41
  def future?
40
42
  start_on >= Date.today
41
43
  end
@@ -47,7 +49,7 @@ class Period < ActiveRecord::Base
47
49
  def passed?
48
50
  end_on < Date.today
49
51
  end
50
-
52
+
51
53
  def estimate_data(date, actual=false)
52
54
  total = BigDecimal('0')
53
55
  tasks.each do |task|
@@ -55,7 +57,7 @@ class Period < ActiveRecord::Base
55
57
  end
56
58
  total
57
59
  end
58
-
60
+
59
61
  def work_data(date)
60
62
  total = BigDecimal('0')
61
63
  tasks.each do |task|
@@ -63,7 +65,7 @@ class Period < ActiveRecord::Base
63
65
  end
64
66
  total
65
67
  end
66
-
68
+
67
69
  def required_speed
68
70
  todo = estimate_data(Date.today)
69
71
  remaining_days = end_on - Date.today
@@ -77,21 +79,21 @@ class Period < ActiveRecord::Base
77
79
  todo * (-remaining_days)
78
80
  end
79
81
  end
80
-
82
+
81
83
  def to_s
82
84
  name
83
85
  end
84
-
86
+
85
87
  def name
86
88
  "#{party.name}##{position}"
87
89
  end
88
-
90
+
89
91
  def dates
90
92
  all_dates = []
91
93
  start_on.upto(end_on) {|date| all_dates << date}
92
94
  return all_dates
93
95
  end
94
-
96
+
95
97
  def recorded_dates
96
98
  dates = []
97
99
  if start_on > Date.today
@@ -153,9 +155,84 @@ class Period < ActiveRecord::Base
153
155
  def invoice?
154
156
  not backlogs.find {|backlog| backlog.enable_invoicing?}.nil?
155
157
  end
156
-
158
+
157
159
  def backlogs
158
160
  tasks.map {|task| task.backlog}.uniq
159
161
  end
160
162
 
163
+ def burn_down_graph(size)
164
+ g = Gruff::Line.new(size)
165
+ g.theme_37signals
166
+ g.title = l(:burn_down_chart) + " " + name
167
+ g.font = '/usr/share/fonts/bitstream-vera/Vera.ttf'
168
+ g.legend_font_size = 14
169
+ g.hide_dots = true
170
+ g.colors = %w{blue orange}
171
+ if track_work?
172
+ g.colors += %w{green}
173
+ end
174
+ if previous_period = higher_item
175
+ g.colors += %w{grey grey}
176
+ end
177
+ if active?
178
+ g.colors += %w{lightblue #d7a790}
179
+ end
180
+
181
+ recorded_dates = self.recorded_dates
182
+ observed_todo_data = get_todo_data(recorded_dates)
183
+ actual_todo_data = get_todo_data(recorded_dates, true)
184
+ g.data("#{l :todo} (#{l :obs})", observed_todo_data)
185
+ g.data("#{l :calc}", actual_todo_data)
186
+ g.data(l(:done), get_work_data(recorded_dates)) if track_work?
187
+ if previous_period = higher_item
188
+ g.data("#{l :previous} #{l :obs}", previous_period.get_todo_data(previous_period.dates))
189
+ g.data("#{l :calc}", previous_period.get_todo_data(previous_period.dates, true))
190
+ end
191
+
192
+ if active?
193
+ g.data(l(:projection), projection_data(observed_todo_data))
194
+ g.data(l(:projection), projection_data(actual_todo_data))
195
+ end
196
+
197
+ g.minimum_value = 0
198
+
199
+ all_dates = dates
200
+ labels = {0 => all_dates.first.to_s, all_dates.length-1 => all_dates.last.to_s}
201
+ labels.merge({all_dates.index(Date.today) => Date.today.to_s}) if all_dates.index(Date.today) && (all_dates.index(Date.today) / all_dates.length) > 0.10
202
+ g.labels = labels
203
+
204
+ # g.draw_vertical_legend
205
+
206
+ g.maximum_value = (g.maximum_value.to_s[0..0].to_i + 1) * (10**Math::log10(g.maximum_value.to_i).to_i)
207
+ g
208
+ end
209
+
210
+ def get_todo_data(dates, actual=false)
211
+ dates.map { |date| estimate_data(date, actual) }
212
+ end
213
+
214
+ def get_work_data(dates)
215
+ dates.map { |date| work_data(date) }
216
+ end
217
+
218
+ def projection_data(observed_todo_data)
219
+ if observed_todo_data.length <= 1
220
+ velocity = 0
221
+ else
222
+ velocity = (observed_todo_data[-1] - observed_todo_data[0]).to_f / (observed_todo_data.length-1)
223
+ end
224
+ projection_data = dates.map do |date|
225
+ if date < Date.today
226
+ nil
227
+ else
228
+ if observed_todo_data.length == 1
229
+ observed_todo_data[0]
230
+ else
231
+ value = observed_todo_data[0] + (date-start_on).to_f*velocity
232
+ value >= 0 ? value : 0
233
+ end
234
+ end
235
+ end
236
+ end
237
+
161
238
  end
metadata CHANGED
@@ -3,7 +3,7 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: backlog
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.5.8
6
+ version: 0.5.9
7
7
  date: 2007-08-06 00:00:00 +02:00
8
8
  summary: Application to aid collecting, processing, organizing, reviewing and doing tasks.
9
9
  require_paths: