further refactoring and more tests

This commit is contained in:
Reinier Balt 2011-12-09 17:17:42 +01:00
parent 2349bee535
commit b948cc48b2
7 changed files with 256 additions and 217 deletions

View file

@ -61,22 +61,22 @@ class StatsController < ApplicationController
# query is sorted, so use last todo to calculate number of months
@month_count = [difference_in_months(@today, @actions_created_last_months.last.created_at),
difference_in_months(@today, @actions_done_last_months.last.completed_at)].max + 1
difference_in_months(@today, @actions_done_last_months.last.completed_at)].max
# convert to array and fill in non-existing months
@actions_done_last_months_array = convert_to_array(convert_to_hash(@actions_done_last_months, :difference_in_months, :completed_at), @month_count)
@actions_created_last_months_array = convert_to_array(convert_to_hash(@actions_created_last_months, :difference_in_months, :created_at), @month_count)
@actions_done_last_months_array = convert_to_array(convert_to_hash(@actions_done_last_months, :difference_in_months, :completed_at), @month_count+1)
@actions_created_last_months_array = convert_to_array(convert_to_hash(@actions_created_last_months, :difference_in_months, :created_at), @month_count+1)
# find max for graph in both hashes
@max = [@actions_done_last_months_array.max, @actions_created_last_months_array.max].max
# find running avg
@actions_done_avg_last_months_array, @actions_created_avg_last_months_array =
find_running_avg_array(@actions_done_last_months_array, @actions_created_last_months_array, @month_count)
find_running_avg_array(@actions_done_last_months_array, @actions_created_last_months_array, @month_count+1)
# correct last two months since the data of last+1 and last+2 are not available for avg
correct_last_two_months(@actions_done_avg_last_months_array, @month_count-1)
correct_last_two_months(@actions_created_avg_last_months_array, @month_count-1)
correct_last_two_months(@actions_done_avg_last_months_array, @month_count)
correct_last_two_months(@actions_created_avg_last_months_array, @month_count)
# interpolate avg for this month.
percent_of_month = Time.zone.now.day.to_f / Time.zone.now.end_of_month.day.to_f
@ -91,14 +91,12 @@ class StatsController < ApplicationController
@actions_done_last30days = current_user.todos.completed_after(@cut_off_month).find(:all, { :select => "completed_at" })
@actions_created_last30days = current_user.todos.created_after(@cut_off_month).find(:all, { :select => "created_at" })
# convert to hash to be able to fill in non-existing days in
# @actions_done_last30days and count the total actions done in the past 30
# days to be able to calculate percentage
@actions_done_last30days_hash = convert_to_hash(@actions_done_last30days, :difference_in_days, :completed_at)
@actions_created_last30days_hash = convert_to_hash(@actions_created_last30days, :difference_in_days, :created_at)
# convert to array. 30+1 to have 30 complete days and one current day [0]
@actions_done_last30days_array = convert_to_array(convert_to_hash(@actions_done_last30days, :difference_in_days, :completed_at), 31)
@actions_created_last30days_array = convert_to_array(convert_to_hash(@actions_created_last30days, :difference_in_days, :created_at), 31)
# find max for graph in both hashes
@max = [find_max_in_hash(@actions_done_last30days_hash, 30), find_max_in_hash(@actions_created_last30days_hash, 30)].max
@max = [@actions_done_last30days_array.max, @actions_created_last30days_array.max].max
render :layout => false
end
@ -106,15 +104,19 @@ class StatsController < ApplicationController
def actions_completion_time_data
@actions_completion_time = current_user.todos.completed.find(:all, { :select => "completed_at, created_at", :order => "completed_at DESC" })
# convert to hash to be able to fill in non-existing days in
# @actions_completion_time also convert days to weeks (/7)
@actions_completion_time_hash = convert_to_week_hash(@actions_completion_time)
# convert to array and fill in non-existing weeks with 0
@max_weeks = difference_in_weeks(@today, @actions_completion_time.last.completed_at)
@max_actions = find_max_in_hash(@actions_completion_time_hash, @max_weeks)
@actions_completed_per_week_array = convert_to_array(convert_to_week_hash(@actions_completion_time), @max_weeks+1)
# stop the chart after 10 weeks
@cut_off = 10
@count = [10, @max_weeks].min
# convert to new array to hold max @cut_off elems + 1 for sum of actions after @cut_off
@actions_completion_time_array = cut_off_array(@actions_completed_per_week_array, @count)
@max_actions = @actions_completion_time_array.max
# get percentage done cummulative
@cumm_percent_done = convert_to_cummulative_array(@actions_completion_time_array, @actions_completion_time.count)
render :layout => false
end
@ -122,13 +124,20 @@ class StatsController < ApplicationController
def actions_running_time_data
@actions_running_time = current_user.todos.not_completed.find(:all, { :select => "created_at", :order => "created_at DESC" })
@actions_running_time_hash = convert_to_week_hash_today(@actions_running_time)
# convert to array and fill in non-existing weeks with 0
@max_weeks = difference_in_weeks(@today, @actions_running_time.last.created_at)
@max_actions = find_max_in_hash(@actions_running_time_hash, @max_weeks)
@actions_running_per_week_array = convert_to_array(convert_to_week_hash_today(@actions_running_time), @max_weeks+1)
# cut off chart at 52 weeks = one year
@cut_off=52
@count = [52, @max_weeks].min
# convert to new array to hold max @cut_off elems + 1 for sum of actions after @cut_off
@actions_running_time_array = cut_off_array(@actions_running_per_week_array, @count)
@max_actions = @actions_running_time_array.max
# get percentage done cummulative
@cumm_percent_done = convert_to_cummulative_array(@actions_running_time_array, @actions_running_time.count )
render :layout => false
end
@ -144,12 +153,18 @@ class StatsController < ApplicationController
@actions_running_time = current_user.todos.not_completed.not_hidden.not_deferred_or_blocked.find(
:all, :select => "todos.created_at", :order => "todos.created_at DESC")
@actions_running_time_hash = convert_to_week_hash_today(@actions_running_time)
@max_weeks = difference_in_weeks(@today, @actions_running_time.last.created_at)
@max_actions = find_max_in_hash(@actions_running_time_hash, @max_weeks)
@actions_running_per_week_array = convert_to_array(convert_to_week_hash_today(@actions_running_time), @max_weeks+1)
# cut off chart at 52 weeks = one year
@cut_off=52
@count = [52, @max_weeks].min
# convert to new array to hold max @cut_off elems + 1 for sum of actions after @cut_off
@actions_running_time_array = cut_off_array(@actions_running_per_week_array, @count)
@max_actions = @actions_running_time_array.max
# get percentage done cummulative
@cumm_percent_done = convert_to_cummulative_array(@actions_running_time_array, @actions_running_time.count )
render :layout => false
end
@ -162,29 +177,29 @@ class StatsController < ApplicationController
"SELECT c.name AS name, c.id as id, count(*) AS total "+
"FROM contexts c, todos t "+
"WHERE t.context_id=c.id "+
"AND c.user_id = #{current_user.id} " +
"GROUP BY c.name, c.id "+
"ORDER BY total DESC"
)
@sum = @all_actions_per_context.inject(0){|sum, apc| sum += apc['total'].to_i }
pie_cutoff=10
size = @all_actions_per_context.size()
size = pie_cutoff if size > pie_cutoff
@actions_per_context = Array.new(size)
0.upto size-1 do |i|
@actions_per_context[i] = @all_actions_per_context[i]
end
size = [@all_actions_per_context.size, pie_cutoff].min
# explicitely copy contents of hash to avoid ending up with two arrays pointing to same hashes
@actions_per_context = Array.new(size){|i| {
'name' => @all_actions_per_context[i][:name],
'total' => @all_actions_per_context[i][:total].to_i,
'id' => @all_actions_per_context[i][:id]
} }
if size==pie_cutoff
@actions_per_context[size-1]['name']=t('stats.other_actions_label')
@actions_per_context[size-1]['total']=0
@actions_per_context[size-1]['total']=@actions_per_context[size-1]['total']
@actions_per_context[size-1]['id']=-1
(size-1).upto @all_actions_per_context.size()-1 do |i|
@actions_per_context[size-1]['total']+=@all_actions_per_context[i]['total'].to_i
end
size.upto(@all_actions_per_context.size-1){ |i| @actions_per_context[size-1]['total']+=(@all_actions_per_context[i]['total'].to_i) }
end
@sum = @all_actions_per_context.inject(0){|sum, apc| sum += apc['total'].to_i }
@truncate_chars = 15
render :layout => false
@ -230,12 +245,12 @@ class StatsController < ApplicationController
@actions_creation_day = current_user.todos.find(:all, { :select => "created_at" })
@actions_completion_day = current_user.todos.completed.find(:all, { :select => "completed_at" })
# convert to hash to be able to fill in non-existing days
# convert to array and fill in non-existing days
@actions_creation_day_array = Array.new(7) { |i| 0}
@actions_creation_day.each { |t| @actions_creation_day_array[ t.created_at.wday ] += 1 }
@max = @actions_creation_day_array.max
# convert to hash to be able to fill in non-existing days
# convert to array and fill in non-existing days
@actions_completion_day_array = Array.new(7) { |i| 0}
@actions_completion_day.each { |t| @actions_completion_day_array[ t.completed_at.wday ] += 1 }
@max = @actions_completion_day_array.max
@ -652,7 +667,26 @@ class StatsController < ApplicationController
return hash
end
# returns a new array containing all elems of array up to cut_off and
# adds the sum of the rest of array to the last elem
def cut_off_array(array, cut_off)
# +1 to hold sum of rest
a = Array.new(cut_off+1){|i| array[i]||0}
# add rest of array to last elem
a[cut_off] += array.inject(:+) - a.inject(:+)
return a
end
def convert_to_cummulative_array(array, max)
# calculate fractions
a = Array.new(array.size){|i| array[i]*100.0/max}
# make cummulative
1.upto(array.size-1){ |i| a[i] += a[i-1] }
return a
end
# assumes date1 > date2
# this results in the number of months before the month of date1, not taking days into account, so diff of 31-12 and 1-1 is 1 month!
def difference_in_months(date1, date2)
return (date1.year - date2.year)*12 + (date1.month - date2.month)
end
@ -662,12 +696,13 @@ class StatsController < ApplicationController
return ((date1.at_midnight-date2.at_midnight)/@seconds_per_day).to_i
end
# assumes date1 > date2
def difference_in_weeks(date1, date2)
return difference_in_days(date1, date2) / 7
end
def three_month_avg(set, i)
return ( (set[i]||0) + (set[i+1]||0) + (set[i+2]||0) )/3.0
return ( (set[i]||0) + (set[i+1]||0) + (set[i+2]||0) ) / 3.0
end
def interpolate_avg(set, percent)
@ -678,25 +713,6 @@ class StatsController < ApplicationController
month_data[count] = month_data[count] * 3
month_data[count-1] = month_data[count-1] * 3 / 2 if count > 1
end
def find_max_in_hash(hash, upper_bound)
max = hash[0]
1.upto(upper_bound){ |i| max = [hash[i], max].max }
return max
end
def find_running_avg(done_hash, created_hash, upper_bound)
avg_done, avg_created = Hash.new("null"), Hash.new("null")
# find running avg for month i by calculating avg of month i and the two
# after them. Ignore current month [0] because you do not have full data for it
1.upto(upper_bound) do |i|
avg_done[i] = three_month_avg(done_hash, i)
avg_created[i] = three_month_avg(created_hash, i)
end
return avg_done, avg_created
end
def find_running_avg_array(done_array, created_array, upper_bound)
avg_done = Array.new(upper_bound){ |i| three_month_avg(done_array,i) }
@ -706,5 +722,4 @@ class StatsController < ApplicationController
return avg_done, avg_created
end
end