diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index b55ab963..1adffe69 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -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 \ No newline at end of file diff --git a/app/views/stats/actions_completion_time_data.html.erb b/app/views/stats/actions_completion_time_data.html.erb index 3bcf0a35..b38a464a 100755 --- a/app/views/stats/actions_completion_time_data.html.erb +++ b/app/views/stats/actions_completion_time_data.html.erb @@ -1,37 +1,23 @@ +<%- +time_labels = Array.new(@count){ |i| "#{i}-#{i+1}" } +time_labels[0] = "within 1" +time_labels[@count] = "#{@count}" +-%> &title=<%= t('stats.action_completion_time_title') %>,{font-size:16},& &y_legend=<%= t('stats.legend.actions') %>,10,0x8010A0& &y2_legend=<%= t('stats.legend.percentage') %>,10,0xFF0000& &x_legend=<%= t('stats.legend.running_time') %>,12,0x736AFF& &y_ticks=5,10,5& &filled_bar=50,0x9933CC,0x8010A0& -&values= -<% @count = @max_weeks > @cut_off ? @cut_off : @max_weeks -0.upto @count.to_i-1 do |i| -%> - <%= @actions_completion_time_hash[i] -%>, -<% end -%> -<% -@sum=0 -@count.upto @max_weeks do |i| - @sum += @actions_completion_time_hash[i] -end -%> -<%=@sum%>& +&values=<%= @actions_completion_time_array.join(",")%>& &line_2=2,0xFF0000& -&values_2= -<% total=0 -@count = @max_weeks > @cut_off ? @cut_off : @max_weeks -0.upto @count-1 do |i| - total += @actions_completion_time_hash[i]*100.0/@actions_completion_time.count -%> - <%= total -%>, -<% end -%> -<%= total+@sum*100.0/@actions_completion_time.count%>& -&x_labels=within 1, -<% 1.upto @count-1 do |i| -%> - <%= i %>-<%= i+1 %>, -<% end -%> -> <%= @count %>& +&values_2=<%= @cumm_percent_done.join(",")%>& +&x_labels=<%= time_labels.join(",")%>& &y_min=0& -<% # add one to @max for people who have no actions completed yet. -# OpenFlashChart cannot handle y_max=0 -%> +<% +# add one to @max for people who have no actions completed yet. +# OpenFlashChart cannot handle y_max=0 +-%> &y_max=<%=1+@max_actions+@max_actions/10-%>& &show_y2=true& &y2_lines=2& diff --git a/app/views/stats/actions_done_last30days_data.html.erb b/app/views/stats/actions_done_last30days_data.html.erb index 03bf323c..28e2903c 100755 --- a/app/views/stats/actions_done_last30days_data.html.erb +++ b/app/views/stats/actions_done_last30days_data.html.erb @@ -1,3 +1,8 @@ +<%- +created_count_array = Array.new(30){ |i| @actions_created_last30days.count/30.0 } +done_count_array = Array.new(30){ |i| @actions_done_last30days.count/30.0 } +time_labels = Array.new(30){ |i| (Time.zone.now-i.days).strftime("%a %d-%m") } +-%> &title=<%= t('stats.actions_30days_title') %>,{font-size:16},& &y_legend=<%= t('stats.legend.number_of_actions') %>,12,0x736AFF& &x_legend=<%= t('stats.legend.number_of_days') %>,12,0x736AFF& @@ -6,37 +11,15 @@ &filled_bar_2=50,0x0066CC,0x0066CC,<%= t('stats.labels.completed') %>,9& &line_3=3,0x00FF00, <%= t('stats.labels.avg_created') %>, 9& &line_4=3,0xFF0000, <%= t('stats.labels.avg_completed') %>, 9& -&values= -<% 0.upto 29 do |i| -%> -<%= @actions_created_last30days_hash[i]%>, -<% end -%><%= @actions_created_last30days_hash[30]%>& -&values_2= -<% 0.upto 29 do |i| -%> -<%= @actions_done_last30days_hash[i]%>, -<% end -%><%= @actions_done_last30days_hash[30]%>& -&values_3= -<%0.upto 29 do |i| -%> -<%=@actions_created_last30days.count/30.0-%>, -<%end-%> -<%=@actions_created_last30days.count/30.0-%>& -&values_4= -<%0.upto 29 do |i| -%> -<%=@actions_done_last30days.count/30.0-%>, -<%end-%> -<%=@actions_done_last30days.count/30.0-%>& -&x_labels= -<%0.upto 29 do |i| - seconds = i * 24 * 60 * 60 - delta = Time.now-seconds --%> -<%= delta.strftime("%a %d-%m") -%>, -<% end - seconds = 29*25*60*60 - delta = Time.now-seconds-%> -<%= delta.strftime("%a %d-%m") -%>& +&values=<%= @actions_created_last30days_array.join(",")%>& +&values_2=<%= @actions_done_last30days_array.join(",")%>& +&values_3=<%= created_count_array.join(",")%>& +&values_4=<%= done_count_array.join(",")%>& +&x_labels=<%= time_labels.join(",")%>& &y_min=0& <% # max + 10% for some extra space at the top # add one to @max for people who have no actions completed yet. - # OpenFlashChart cannot handle y_max=0 -%> + # OpenFlashChart cannot handle y_max=0 +-%> &y_max=<%=@max+@max/10+1 -%>& &x_label_style=9,,2,3& \ No newline at end of file diff --git a/app/views/stats/actions_done_lastyears_data.html.erb b/app/views/stats/actions_done_lastyears_data.html.erb index d71c825d..03cfa025 100644 --- a/app/views/stats/actions_done_lastyears_data.html.erb +++ b/app/views/stats/actions_done_lastyears_data.html.erb @@ -1,9 +1,9 @@ <%- -created_count_array = Array.new(@month_count){ |i| @actions_created_last_months.count/@month_count } -done_count_array = Array.new(@month_count){ |i| @actions_done_last_months.count/@month_count } -month_names = Array.new(@month_count){ |i| Date::MONTHNAMES[ (Time.now.mon - i -1 ) % 12 + 1 ]+ " " + (Time.now - i.months).year.to_s} +created_count_array = Array.new(@month_count+1){ |i| @actions_created_last_months.count/@month_count } +done_count_array = Array.new(@month_count+1){ |i| @actions_done_last_months.count/@month_count } +month_names = Array.new(@month_count+1){ |i| Date::MONTHNAMES[ (Time.now.mon - i -1 ) % 12 + 1 ]+ " " + (Time.now - i.months).year.to_s} -%> -&title=<%= t('stats.actions_last_year') %>,{font-size:16},& +&title=<%= t('stats.actions_last_year') %>,{font-size:16},& &y_legend=<%= t('stats.actions_last_year_legend.number_of_actions') %>,12,0x736AFF& &x_legend=<%= t('stats.actions_last_year_legend.months_ago') %>,12,0x736AFF& &y_ticks=5,10,5& diff --git a/app/views/stats/actions_running_time_data.html.erb b/app/views/stats/actions_running_time_data.html.erb index 923a0420..6578a1cf 100755 --- a/app/views/stats/actions_running_time_data.html.erb +++ b/app/views/stats/actions_running_time_data.html.erb @@ -1,39 +1,27 @@ -&title=<%= t('stats.running_time_all') %>,{font-size:16},& -&y_legend=<%= t('stats.running_time_all_legend.actions') %>",10,0x736AFF& +<%- +url_labels = Array.new(@count){ |i| url_for(:controller => 'stats', :action => 'show_selected_actions_from_chart', :index => i, :id=> "art") } +url_labels[@count]=url_for(:controller => 'stats', :action => 'show_selected_actions_from_chart', :index => @count, :id=> "art_end") + +time_labels = Array.new(@count){ |i| "#{i}-#{i+1}" } +time_labels[0] = "< 1" +time_labels[@count] = "#{@count}" +-%> +&title=<%= t('stats.running_time_all') %>,{font-size:16},& +&y_legend=<%= t('stats.running_time_all_legend.actions') %>,10,0x736AFF& &y2_legend=<%= t('stats.running_time_all_legend.percentage') %>,10,0xFF0000& -&x_legend=<%= t('stats.running_time_all_legend.running_time') %>,11,0x736AFF& +&x_legend=<%= t('stats.running_time_all_legend.running_time') %>,11,0x736AFF& &y_ticks=5,10,5& &filled_bar=50,0x9933CC,0x8010A0& -&values= -<% @count = @max_weeks > @cut_off ? @cut_off : @max_weeks - 0.upto @count.to_i-1 do |i| -%> -<%= @actions_running_time_hash[i] -%>, -<% end -%> -<% - @sum=0 - @count.upto(@max_weeks.to_i) {|i| @sum += @actions_running_time_hash[i]} -%> -<%=@sum%>& -&links=<% -0.upto(@count-1) { |i| %><%= url_for :controller => 'stats', :action => 'show_selected_actions_from_chart', :index => i, :id=> "art" %>, <% } -%><%= url_for :controller => 'stats', :action => 'show_selected_actions_from_chart', :index => @count, :id=> "art_end" %>& +&values=<%= @actions_running_time_array.join(",") -%>& +&links=<%= url_labels.join(",") %>& &line_2=2,0xFF0000& -&values_2= -<% total=0 - @count = @max_weeks > @cut_off ? @cut_off : @max_weeks - 0.upto @count.to_i-1 do |i| - total += @actions_running_time_hash[i] -%> - <%= total*100.0/@actions_running_time.count -%>, -<% end -%> -<%= (total+@sum)*100.0/@actions_running_time.count%>& -&x_labels=< 1, -<% 1.upto @count-1 do |i| -%> -<%= i %>-<%= i+1 %>, -<% end -%> -><%=@count-%>& +&values_2=<%= @cumm_percent_done.join(",") %>& +&x_labels=<%= time_labels.join(",") %> & &y_min=0& -<% @max_actions = [@sum,@max_actions].max -%> -<% # add one to @max for people who have no actions completed yet. - # OpenFlashChart cannot handle y_max=0 -%> +<% + # add one to @max for people who have no actions completed yet. + # OpenFlashChart cannot handle y_max=0 +-%> &y_max=<%=1+@max_actions+@max_actions/10-%>& &x_label_style=9,,2,2& &show_y2=true& diff --git a/app/views/stats/actions_visible_running_time_data.html.erb b/app/views/stats/actions_visible_running_time_data.html.erb index 9219e11c..cd913eb4 100755 --- a/app/views/stats/actions_visible_running_time_data.html.erb +++ b/app/views/stats/actions_visible_running_time_data.html.erb @@ -1,37 +1,27 @@ -&title=<%= t('stats.current_running_time_of_incomplete_visible_actions') %>,{font-size:16},& -&y_legend=<%= t('stats.running_time_legend.actions') %>,10,0x736AFF& +<%- +url_labels = Array.new(@count){ |i| url_for(:controller => 'stats', :action => 'show_selected_actions_from_chart', :index => i, :id=> "avrt") } +url_labels[@count]=url_for(:controller => 'stats', :action => 'show_selected_actions_from_chart', :index => @count, :id=> "avrt_end") + +time_labels = Array.new(@count){ |i| "#{i}-#{i+1}" } +time_labels[0] = "< 1" +time_labels[@count] = "#{@count}" +-%> +&title=<%= t('stats.current_running_time_of_incomplete_visible_actions') %>,{font-size:16},& +&y_legend=<%= t('stats.running_time_legend.actions') %>,10,0x736AFF& &y2_legend=<%= t('stats.running_time_legend.percentage') %>,10,0xFF0000& -&x_legend=<%= t('stats.running_time_legend.weeks') %>,11,0x736AFF& +&x_legend=<%= t('stats.running_time_legend.weeks') %>,11,0x736AFF& &y_ticks=5,10,5& &filled_bar=50,0x9933CC,0x8010A0& -&values= -<% @count = @max_weeks > @cut_off ? @cut_off : @max_weeks -0.upto(@count-1) { |i| -%><%= @actions_running_time_hash[i] -%>,<% } %> -<% -@sum=0 -@count.upto(@max_weeks.to_i) { |i| @sum += @actions_running_time_hash[i] } -%> -<%=@sum%>& -&links=<% -0.upto(@count-1) { |i| %><%= url_for :controller => 'stats', :action => 'show_selected_actions_from_chart', :index => i, :id=> "avrt" %>, <% } -%><%= url_for :controller => 'stats', :action => 'show_selected_actions_from_chart', :index => @count, :id=> "avrt_end" %>& +&values=<%= @actions_running_time_array.join(",") -%>& +&links=<%= url_labels.join(",") %>& &line_2=2,0xFF0000& -&values_2= -<% total=0 -@count = @max_weeks > @cut_off ? @cut_off : @max_weeks -0.upto @count-1 do |i| - total += @actions_running_time_hash[i] -%> - <%= total*100.0/@actions_running_time.count -%>, -<% end -%> -<%= (total+@sum)*100.0/@actions_running_time.count%>& -&x_labels=< 1, -<% 1.upto @count-1 do |i| -%> - <%= i %>-<%= i+1 %>, -<% end -%> -><%=@count-%>& +&values_2=<%= @cumm_percent_done.join(",") -%>& +&x_labels=<%= time_labels.join(",")%>& &y_min=0& -<% @max_actions = @sum > @max_actions ? @sum : @max_actions -%> -<% # add one to @max for people who have no actions completed yet. -# OpenFlashChart cannot handle y_max=0 -%> +<% + # add one to @max for people who have no actions completed yet. + # OpenFlashChart cannot handle y_max=0 +-%> &y_max=<%=1+@max_actions+@max_actions/10-%>& &x_label_style=9,,2,2& &show_y2=true& diff --git a/test/functional/stats_controller_test.rb b/test/functional/stats_controller_test.rb index 88ff2e27..035a48f5 100755 --- a/test/functional/stats_controller_test.rb +++ b/test/functional/stats_controller_test.rb @@ -26,17 +26,18 @@ class StatsControllerTest < ActionController::TestCase def test_get_charts login_as(:admin_user) - %w{ actions_done_last30days_data - actions_done_last12months_data - actions_completion_time_data - actions_visible_running_time_data - actions_running_time_data - actions_day_of_week_all_data - actions_day_of_week_30days_data - actions_time_of_day_all_data - actions_time_of_day_30days_data - context_total_actions_data - context_running_actions_data + %w{ + actions_done_last30days_data + actions_done_last12months_data + actions_completion_time_data + actions_visible_running_time_data + actions_running_time_data + actions_day_of_week_all_data + actions_day_of_week_30days_data + actions_time_of_day_all_data + actions_time_of_day_30days_data + context_total_actions_data + context_running_actions_data }.each do |action| get action assert_response :success @@ -113,28 +114,51 @@ class StatsControllerTest < ActionController::TestCase # And they should be totalled in a hash assert_equal 2, assigns['actions_created_last12months_array'][0], "there should be two todos in current month" - assert_equal 1, assigns['actions_created_last12months_array'][1], "there should be one todo in previous month" - assert_equal 1, assigns['actions_created_last12months_array'][2], "there should be one todo in two month ago" + + # these test use relative dates. It will go wrong when the data is [1-8] of the month :-( + # FIXME: make testdata not relative of today to avoid crossing end_of_month + too_early = Time.zone.now.day <= 8 ? 1 : 0 + + assert_equal 1-too_early, assigns['actions_created_last12months_array'][1], "there should be one todo in previous month" + assert_equal 1+too_early, assigns['actions_created_last12months_array'][2], "there should be one todo in two month ago" assert_equal 1, assigns['actions_created_last12months_array'][3], "there should be one todo in three month ago" assert_equal 2, assigns['actions_created_last12months_array'][4], "there should be two todos (1 created & 1 done) in four month ago" - assert_equal 1, assigns['actions_done_last12months_array'][2], "there should be one completed todo in last three months" - assert_equal 1, assigns['actions_done_last12months_array'][4], "there should be one completed todo in last four months" + assert_equal 1, assigns['actions_done_last12months_array'][1], "there should be one completed todo one-two months ago" + assert_equal 1, assigns['actions_done_last12months_array'][2], "there should be one completed todo two-three months ago" + assert_equal 1, assigns['actions_done_last12months_array'][4], "there should be one completed todo four-five months ago" # And they should be averaged over three months - assert_equal 1/3.0, assigns['actions_done_avg_last12months_array'][1], "fourth month should be excluded" + assert_equal 2/3.0, assigns['actions_done_avg_last12months_array'][1], "fourth month should be excluded" assert_equal 2/3.0, assigns['actions_done_avg_last12months_array'][2], "fourth month should be included" - assert_equal 1.0, assigns['actions_created_avg_last12months_array'][1], "one every month" - assert_equal 4/3.0, assigns['actions_created_avg_last12months_array'][2], "two in fourth month" + assert_equal 3/3.0, assigns['actions_created_avg_last12months_array'][1], "one every month" + assert_equal (4+too_early)/3.0, assigns['actions_created_avg_last12months_array'][2], "two in fourth month" # And the current month should be interpolated fraction = Time.zone.now.day.to_f / Time.zone.now.end_of_month.day.to_f assert_equal (2*fraction+2)/3.0, assigns['interpolated_actions_created_this_month'], "two this month and one in the last two months" - assert_equal 1/3.0, assigns['interpolated_actions_done_this_month'], "none this month and one in the last two months" + assert_equal 2/3.0, assigns['interpolated_actions_done_this_month'], "none this month and one two the last two months" # And totals should be calculated - assert_equal 2, assigns['max'], "max of created or completed todos" + assert_equal 2, assigns['max'], "max of created or completed todos in one month" + end + + def test_actions_done_last30days_data + login_as(:admin_user) + @current_user = User.find(users(:admin_user).id) + @current_user.todos.delete_all + + given_todos_for_stats + + # When I get the chart data + get :actions_done_last30days_data + assert_response :success + + # only tests relevant differences with actions_done_last_12months_data + + assert_equal 31, assigns['actions_done_last30days_array'].size, "30 complete days plus 1 for the current day" + assert_equal 2, assigns['max'], "two actions created on one day is max" end def test_actions_done_lastyears_data @@ -151,11 +175,11 @@ class StatsControllerTest < ActionController::TestCase # only tests difference with actions_done_last_12months_data # Then the count of months should be calculated - assert_equal 24, assigns['month_count'] + assert_equal 27, assigns['month_count'], "two years and three months of last todo" # And the last two months are corrected - assert_equal 0.5, assigns['actions_done_avg_last_months_hash'][23] - assert_equal 1.0, assigns['actions_done_avg_last_months_hash'][24] + assert_equal 2/3.0, assigns['actions_done_avg_last_months_array'][23] + assert_equal 2/3.0, assigns['actions_done_avg_last_months_array'][24] end def test_actions_completion_time_data @@ -170,8 +194,11 @@ class StatsControllerTest < ActionController::TestCase assert_response :success # do not test stuff already implicitly tested in other tests - - assert_equal 104, assigns['max_weeks'], "two years is 104 weeks" + assert_equal 104, assigns['max_weeks'], "two years is 104 weeks (for completed_at)" + assert_equal 3, assigns['max_actions'], "3 completed within one week" + assert_equal 11, assigns['actions_completion_time_array'].size, "there should be 10 weeks of data + 1 for the rest" + assert_equal 1, assigns['actions_completion_time_array'][10], "there is one completed todo after the 10 weeks cut_off" + assert_equal 100.0, assigns['cumm_percent_done'][10], "cummulative percentage should add up to 100%" end def test_actions_running_time_data @@ -186,8 +213,11 @@ class StatsControllerTest < ActionController::TestCase assert_response :success # do not test stuff already implicitly tested in other tests - - assert_equal 17, assigns['max_weeks'], "there are action in the first 17 weeks of this year" + assert_equal 17, assigns['max_weeks'], "there are actions in the first 17 weeks of this year" + assert_equal 2, assigns['max_actions'], "2 actions running long together" + assert_equal 18, assigns['actions_running_time_array'].size, "there should be 17 weeks ( < cut_off) of data + 1 for the rest" + assert_equal 1, assigns['actions_running_time_array'][17], "there is one running todos in week 17 and zero after 17 weeks ( < cut off; ) " + assert_equal 100.0, assigns['cumm_percent_done'][17], "cummulative percentage should add up to 100%" end def test_actions_visible_running_time_data @@ -196,22 +226,51 @@ class StatsControllerTest < ActionController::TestCase @current_user.todos.delete_all given_todos_for_stats + # Given todo1 is deferred (i.e. not visible) + @todo_today1.show_from = Time.zone.now + 1.week + @todo_today1.save # When I get the chart data get :actions_visible_running_time_data + assert_response :success + + # do not test stuff already implicitly tested in other tests + assert_equal 17, assigns['max_weeks'], "there are actions in the first 17 weeks of this year" + assert_equal 1, assigns['max_actions'], "1 action running long; 1 is deferred" + assert_equal 1, assigns['actions_running_time_array'][0], "there is one running todos and one deferred todo created in week 1" + assert_equal 18, assigns['actions_running_time_array'].size, "there should be 17 weeks ( < cut_off) of data + 1 for the rest" + assert_equal 1, assigns['actions_running_time_array'][17], "there is one running todos in week 17 and zero after 17 weeks ( < cut off; ) " + assert_equal 100.0, assigns['cumm_percent_done'][17], "cummulative percentage should add up to 100%" + end + + def test_context_total_actions_data login_as(:admin_user) @current_user = User.find(users(:admin_user).id) @current_user.todos.delete_all given_todos_for_stats - + # When I get the chart data - get :actions_running_time_data + get :context_total_actions_data assert_response :success - - # do not test stuff already implicitly tested in other tests - - assert_equal 17, assigns['max_weeks'], "there are action in the first 17 weeks of this year" + + assert_equal 9, assigns['sum'], "Nine todos in 1 context" + assert_equal 1, assigns['actions_per_context'].size + + # Given 10 more todos in 10 different contexts + 1.upto(10) do |i| + context = @current_user.contexts.create!(:name => "context #{i}") + @current_user.todos.create!(:description => "created today with new context #{i}", :context => context) + end + + # When I get the chart data + get :context_total_actions_data + assert_response :success + + assert_equal 19, assigns['sum'], "added 10 todos" + assert_equal 10, assigns['actions_per_context'].size, "pie slices limited to max 10" + assert_equal 2, assigns['actions_per_context'][9]['total'], "pie slices limited to max 10; last pie contains sum of rest" + assert_equal "(others)", assigns['actions_per_context'][9]['name'], "pie slices limited to max 10; last slice contains label for others" end private @@ -221,17 +280,18 @@ class StatsControllerTest < ActionController::TestCase @todo_today1 = @current_user.todos.create!(:description => "created today1", :context => contexts(:office)) @todo_today2 = @current_user.todos.create!(:description => "created today2", :context => contexts(:office)) # And a todo created a month ago - @todo_month1 = create_todo_in_past(1.month+1.day) + @todo_month1 = create_completed_todo_in_past(1.month+1.weeks+1.day, 1.month+1.day) # And a todo created two months ago - @todo_month2 = create_completed_todo_in_past(2.months+1.day, 2.months+2.days) + @todo_month2 = create_completed_todo_in_past(2.months+2.days, 2.months+1.day) # And a todo created three months ago @todo_month3 = create_todo_in_past(3.months+1.day) # And a todo created four months ago @todo_month4 = create_todo_in_past(4.months+1.day) # And a todo created four months ago - @todo_month5 = create_completed_todo_in_past(4.months+1.day, 4.months+2.days) + @todo_month5 = create_completed_todo_in_past(4.months+2.days, 4.months+1.day) # And a todo created over a year ago - @todo_year = create_completed_todo_in_past(2.years+1.day, 2.years+2.day) + @todo_year1 = create_completed_todo_in_past(2.years+2.days, 2.years+1.day) + @todo_year2 = create_completed_todo_in_past(2.years+3.months, 2.years+1.day) end def create_todo_in_past(creation_time_in_past) @@ -250,4 +310,21 @@ class StatsControllerTest < ActionController::TestCase return todo end + # assumes date1 > date2 + def difference_in_days(date1, date2) + return ((date1.at_midnight-date2.at_midnight)/(60*60*24)).to_i + end + + # assumes date1 > date2 + def difference_in_weeks(date1, date2) + return difference_in_days(date1, date2) / 7 + end + + # assumes date1 > date2 + def difference_in_months(date1, date2) + diff = (date1.year - date2.year)*12 + (date1.month - date2.month) + return diff-1 if date1.day - date2.day < 0 # correct for incomplete months + return diff + end + end