Added the fantastic statistics work contributed by lrbalt! This is a work in progress. It's not rendering correctly for me in Firefox but is OK in Safari and there is at least one other minor error. Contribute bug reports and fixes to ticket #406.

git-svn-id: http://www.rousette.org.uk/svn/tracks-repos/trunk@587 a4c988fc-2ded-0310-b66e-134b36920a42
This commit is contained in:
lukemelia 2007-09-13 03:21:37 +00:00
parent 4f3762a64c
commit 8c26ea7cb5
26 changed files with 1013 additions and 0 deletions

View file

@ -0,0 +1,516 @@
class StatsController < ApplicationController
def index
@page_title = 'TRACKS::Statistics'
@projects = @user.projects
@contexts = @user.contexts
@actions = @user.todos
@tags = @user.tags
@unique_tags = @tags.find(:all, {:group=>"tag_id"})
@hidden_contexts = @contexts.select{ |c| c.hide? }
@first_action = @actions.find(:first, :order => "created_at asc")
# default chart dimensions
@chart_width=450
@chart_height=250
@pie_width=@chart_width
@pie_height=325
get_stats_actions
get_stats_contexts
get_stats_projects
get_stats_tags
render :layout => 'standard'
end
def actions_done_last12months_data
@actions = @user.todos
@actions_done_last12months = @actions.count(
:all, {
:group => "period_diff(extract(year_month from now()), extract(year_month from completed_at))",
:conditions => "period_diff(extract(year_month from now()), extract(year_month from completed_at)) <= 12 and not completed_at is null"
})
@actions_created_last12months = @actions.count(:all, {
:group => "period_diff(extract(year_month from now()), extract(year_month from created_at))",
:conditions => "period_diff(extract(year_month from now()), extract(year_month from created_at)) <= 12"
})
# find max count for graph
@max=0
# convert to hash to be able to fill in non-existing days in @actions_done_last12months
@sum_actions_done_last12months=0
@actions_done_last12months_hash = Hash.new(0)
@actions_done_last12months.each do |month, count|
@actions_done_last12months_hash[month] = count
@sum_actions_done_last12months+= count.to_i
if count.to_i > @max
@max = count.to_i
end
end
@sum_actions_created_last12months=0
@actions_created_last12months_hash = Hash.new(0)
@actions_created_last12months.each do |month, count|
@actions_created_last12months_hash[month] = count
@sum_actions_created_last12months+= count.to_i
if count.to_i > @max
@max = count.to_i
end
end
render :layout => false
end
def actions_done_last30days_data
@actions = @user.todos
# get count of actions done in the past 30 days. Results in a array of arrays
@actions_done_last30days = @actions.count(:all, {
:group => "datediff(now(), completed_at)",
:conditions => "datediff(now(), completed_at) <= 30 and not completed_at is null"
})
@actions_created_last30days = @actions.count(:all, {
:group => "datediff(now(), created_at)",
:conditions => "datediff(now(), created_at) <= 30"
})
@max=0
# convert to hash to be albe to fill in non-existing days in @actions_done_last30days
@sum_actions_done_last30days=0
@actions_done_last30days_hash = Hash.new(0)
@actions_done_last30days.each do |day, count|
@actions_done_last30days_hash[day] = count
@sum_actions_done_last30days+= count.to_i
if count.to_i > @max
@max = count.to_i
end
end
@sum_actions_created_last30days=0
# convert to hash to be albe to fill in non-existing days in @actions_done_last30days
@actions_created_last30days_hash = Hash.new(0)
@actions_created_last30days.each do |day, count|
@actions_created_last30days_hash[day] = count
@sum_actions_created_last30days+= count.to_i
if count.to_i > @max
@max = count.to_i
end
end
render :layout => false
end
def actions_completion_time_data
@actions = @user.todos
@actions_completion_time = @actions.count(:all, {
:group => "datediff(completed_at, created_at)",
:conditions => "not completed_at is null", :order => "datediff(completed_at, created_at) ASC"
})
# convert to hash to be able to fill in non-existing days in @actions_completion_time
# also convert days to weeks (/7)
@max_days=0
@max_actions=0
@actions_completion_time_hash = Hash.new(0)
@actions_completion_time.each do |days, total|
# RAILS_DEFAULT_LOGGER.error("\n" + total.to_s + " - " + days + "\n")
@actions_completion_time_hash[days.to_i/7] = @actions_completion_time_hash[days.to_i/7] + total
if days.to_i > @max_days
@max_days=days.to_i
end
if @actions_completion_time_hash[days.to_i/7] > @max_actions
@max_actions = @actions_completion_time_hash[days.to_i/7]
end
end
@cut_off = 10
render :layout => false
end
def actions_running_time_data
@actions = @user.todos
@actions_running_time = @actions.count(:all, {
:group => "datediff(now(), created_at)",
:conditions => "completed_at is null", :order => "datediff(now(), created_at) ASC"
})
# convert to hash to be able to fill in non-existing days in @actions_running_time
# also convert days to weeks (/7)
@max_days=0
@max_actions=0
@actions_running_time_hash = Hash.new(0)
@actions_running_time.each do |days, total|
# RAILS_DEFAULT_LOGGER.error("\n" + total.to_s + " - " + days + "\n")
@actions_running_time_hash[days.to_i/7] = @actions_running_time_hash[days.to_i/7] + total
if days.to_i > @max_days
@max_days=days.to_i
end
if @actions_running_time_hash[days.to_i/7] > @max_actions
@max_actions = @actions_running_time_hash[days.to_i/7]
end
end
# cut off chart at 52 weeks = one year
@cut_off=52
render :layout => false
end
def actions_visible_running_time_data
@actions = @user.todos
@actions_running_time = @actions.count(:all, {
:group => "datediff(now(), created_at)",
:conditions => "completed_at is null", :order => "datediff(now(), created_at) ASC"
})
@actions_running_time = @actions.find_by_sql(
"SELECT datediff(now(), t.created_at) as days, count(*) as total "+
"FROM todos t LEFT OUTER JOIN projects p ON t.project_id = p.id LEFT OUTER JOIN contexts c ON t.context_id = c.id "+
"WHERE t.user_id="+@user.id.to_s+" "+
"AND t.completed_at is null " +
"AND NOT (p.state='hidden' OR c.hide=1) " +
"GROUP BY days ORDER BY days DESC"
)
# convert to hash to be able to fill in non-existing days in @actions_running_time
# also convert days to weeks (/7)
@max_days=0
@max_actions=0
@actions_running_time_hash = Hash.new(0)
@actions_running_time.each do |a|
# RAILS_DEFAULT_LOGGER.error("\n" + total.to_s + " - " + days + "\n")
@actions_running_time_hash[a.days.to_i/7] += a.total.to_i
if a.days.to_i > @max_days
@max_days=a.days.to_i
end
if @actions_running_time_hash[a.days.to_i/7] > @max_actions
@max_actions = @actions_running_time_hash[a.days.to_i/7]
end
end
# cut off chart at 52 weeks = one year
@cut_off=52
render :layout => false
end
def context_total_actions_data
@contexts = @user.contexts
# SELECT c.name, c.hide, count(*) as totaal
# FROM contexts c, todos t
# where t.context_id=c.id group by c.id order by totaal desc;
# get total action count per context
@actions_per_context = @contexts.find_by_sql(
"SELECT c.name as name, count(*) as total "+
"FROM contexts c, todos t "+
"WHERE t.context_id=c.id "+
"AND t.user_id="+@user.id.to_s+" "+
"GROUP BY c.id ORDER BY total DESC"
)
@sum=0
0.upto @actions_per_context.size()-1 do |i|
@sum += @actions_per_context[i]['total'].to_i
end
render :layout => false
end
def context_running_actions_data
@contexts = @user.contexts
# SELECT c.name, c.hide, count(*) as totaal
# FROM contexts c, todos t
# where t.context_id=c.id group by c.id order by totaal desc;
# get uncompleted action count per visible context
@actions_per_context = @contexts.find_by_sql(
"SELECT c.name as name, count(*) as total "+
"FROM contexts c, todos t "+
"WHERE t.context_id=c.id AND t.completed_at IS NULL AND NOT c.hide "+
"AND t.user_id="+@user.id.to_s+" "+
"GROUP BY c.id ORDER BY total DESC"
)
@sum=0
0.upto @actions_per_context.size()-1 do |i|
@sum += @actions_per_context[i]['total'].to_i
end
render :layout => false
end
def actions_day_of_week_all_data
@actions = @user.todos
@actions_creation_day = @actions.count(:all, {:group => "dayofweek(created_at)" })
@actions_completion_day = @actions.count(:all, {:group => "dayofweek(completed_at)", :conditions => "not completed_at is null" })
# convert to hash to be able to fill in non-existing days
@max=0
@actions_creation_day_array = Array.new(7) { |i| 0}
@actions_creation_day.each do |dayofweek, total|
# dayofweek: sunday=1..saterday=7
@max = total.to_i > @max ? total.to_i : @max
@actions_creation_day_array[dayofweek.to_i-1]=total.to_i
end
# convert to hash to be able to fill in non-existing days
@actions_completion_day_array = Array.new(7) { |i| 0}
@actions_completion_day.each do |dayofweek, total|
# dayofweek: sunday=1..saterday=7
@max = total.to_i > @max ? total.to_i : @max
@actions_completion_day_array[dayofweek.to_i-1]=total.to_i
end
render :layout => false
end
def actions_day_of_week_30days_data
@actions = @user.todos
@actions_creation_day = @actions.count(
:all, {
:group => "dayofweek(created_at)",
:conditions => "datediff(now(), created_at) <= 30"
})
@actions_completion_day = @actions.count(
:all, {:group => "dayofweek(completed_at)",
:conditions => "not completed_at is null and datediff(now(), created_at) <= 30"
})
# convert to hash to be able to fill in non-existing days
@max=0
@actions_creation_day_array = Array.new(7) { |i| 0}
@actions_creation_day.each do |dayofweek, total|
# dayofweek: sunday=1..saterday=7
@max = total.to_i > @max ? total.to_i : @max
@actions_creation_day_array[dayofweek.to_i-1]=total.to_i
end
# convert to hash to be able to fill in non-existing days
@actions_completion_day_array = Array.new(7) { |i| 0}
@actions_completion_day.each do |dayofweek, total|
# dayofweek: sunday=1..saterday=7
@max = total.to_i > @max ? total.to_i : @max
@actions_completion_day_array[dayofweek.to_i-1]=total.to_i
end
render :layout => false
end
def actions_time_of_day_all_data
@actions = @user.todos
@actions_creation_hour = @actions.count(:all, {:group => "hour(convert_tz(created_at, @@session.time_zone, '+2:00'))" })
@actions_completion_hour = @actions.count(:all, {:group => "hour(convert_tz(created_at, @@session.time_zone, '+2:00'))", :conditions => "not completed_at is null" })
# convert to hash to be able to fill in non-existing days
@max=0
@actions_creation_hour_array = Array.new(24) { |i| 0}
@actions_creation_hour.each do |hour, total|
@max = total.to_i > @max ? total.to_i : @max
@actions_creation_hour_array[hour.to_i]=total.to_i
end
# convert to hash to be able to fill in non-existing days
@actions_completion_hour_array = Array.new(24) { |i| 0}
@actions_completion_hour.each do |hour, total|
@max = total.to_i > @max ? total.to_i : @max
@actions_completion_hour_array[hour.to_i]=total.to_i
end
render :layout => false
end
def actions_time_of_day_30days_data
@actions = @user.todos
# TODO: find out how to find current timezone
@actions_creation_hour = @actions.count(
:all, {
:group => "hour(convert_tz(created_at, @@session.time_zone, '+2:00'))",
:conditions => "datediff(now(), created_at) <= 30"
})
# TODO: find out how to find current timezone
@actions_completion_hour = @actions.count(
:all, {:group => "hour(convert_tz(completed_at, @@session.time_zone, '+2:00'))",
:conditions => "not completed_at is null and datediff(now(), completed_at) <= 30"
})
# convert to hash to be able to fill in non-existing days
@max=0
@actions_creation_hour_array = Array.new(24) { |i| 0}
@actions_creation_hour.each do |hour, total|
@max = total.to_i > @max ? total.to_i : @max
@actions_creation_hour_array[hour.to_i]=total.to_i
end
# convert to hash to be able to fill in non-existing days
@actions_completion_hour_array = Array.new(24) { |i| 0}
@actions_completion_hour.each do |hour, total|
@max = total.to_i > @max ? total.to_i : @max
@actions_completion_hour_array[hour.to_i]=total.to_i
end
render :layout => false
end
private
def get_stats_actions
# time to complete
@actions_avg_ttc = @actions.average("datediff(completed_at, created_at)", {:conditions => "not completed_at is null"} )
@actions_max_ttc = @actions.maximum("datediff(completed_at, created_at)", {:conditions => "not completed_at is null"} )
@actions_min_ttc = @actions.minimum("datediff(completed_at, created_at)", {:conditions => "not completed_at is null"} )
@actions_min_ttc_sec = @actions.minimum("timediff(completed_at, created_at)", {:conditions => "not completed_at is null"} )
# get count of actions created and actions done in the past 30 days. Results in a array of arrays
@actions_done_last30days = @actions.count(:all, {
:group => "datediff(now(), completed_at)",
:conditions => "datediff(now(), completed_at) <= 30"
})
@actions_created_last30days = @actions.count(:all, {
:group => "datediff(now(), created_at)",
:conditions => "datediff(now(), created_at) <= 30"
})
@sum_actions_done_last30days=0
# convert to hash to be albe to fill in non-existing days in @actions_done_last30days
@actions_done_last30days_hash = Hash.new(0)
@actions_done_last30days.each do |day, count|
@actions_done_last30days_hash[day] = count
@sum_actions_done_last30days+= count.to_i
end
@sum_actions_created_last30days=0
# convert to hash to be albe to fill in non-existing days in @actions_done_last30days
@actions_created_last30days_hash = Hash.new(0)
@actions_created_last30days.each do |day, count|
@actions_created_last30days_hash[day] = count
@sum_actions_created_last30days+= count.to_i
end
# get count of actions done in the past 12 months. Results in a array of arrays
@actions_done_last12months = @actions.count(:all, {
:group => "period_diff(extract(year_month from now()), extract(year_month from completed_at))",
:conditions => "period_diff(extract(year_month from now()), extract(year_month from completed_at)) <= 12 and not completed_at is null"
})
@actions_created_last12months = @actions.count(:all, {
:group => "period_diff(extract(year_month from now()), extract(year_month from created_at))",
:conditions => "period_diff(extract(year_month from now()), extract(year_month from created_at)) <= 12"
})
# convert to hash to be albe to fill in non-existing days in @actions_done_last12months
@sum_actions_done_last12months=0
@actions_done_last12months_hash = Hash.new(0)
@actions_done_last12months.each do |month, count|
@actions_done_last12months_hash[month] = count
@sum_actions_done_last12months+= count.to_i
end
@sum_actions_created_last12months=0
@actions_created_last12months_hash = Hash.new(0)
@actions_created_last12months.each do |month, count|
@actions_created_last12months_hash[month] = count
@sum_actions_created_last12months+= count.to_i
end
end
def get_stats_contexts
# get action count per context for TOP 5
@actions_per_context = @contexts.find_by_sql(
"SELECT c.name as name, count(*) as total "+
"FROM contexts c, todos t "+
"WHERE t.context_id=c.id "+
"AND t.user_id="+@user.id.to_s+" "+
"GROUP BY c.id ORDER BY total DESC " +
"LIMIT 5"
)
# get uncompleted action count per visible context for TOP 5
@running_actions_per_context = @contexts.find_by_sql(
"SELECT c.name as name, count(*) as total "+
"FROM contexts c, todos t "+
"WHERE t.context_id=c.id AND t.completed_at IS NULL AND NOT c.hide "+
"AND t.user_id="+@user.id.to_s+" "+
"GROUP BY c.id ORDER BY total DESC " +
"LIMIT 5"
)
end
def get_stats_projects
# get the first 10 projects and their action count (all actions)
@projects_and_actions = @projects.find_by_sql(
"SELECT p.name, count(*) as count "+
"FROM projects p, todos t "+
"WHERE p.id = t.project_id "+
"AND p.user_id="+@user.id.to_s+" "+
"GROUP BY p.id "+
"ORDER BY count DESC " +
"LIMIT 10"
)
# get the first 10 projects with their actions count of actions that
# have been created or completed the past 30 days
@projects_and_actions_last30days = @projects.find_by_sql(
"SELECT p.name, count(*) AS count "+
"FROM todos t, projects p "+
"WHERE t.project_id = p.id AND "+
" (datediff(now(), t.created_at) < 30 OR "+
" datediff(now(), t.completed_at) < 30) "+
"AND p.user_id="+@user.id.to_s+" "+
"GROUP BY p.id "+
"ORDER BY count DESC"
)
# get the first 10 projects and their running time (creation date versus now())
@projects_and_runtime = @projects.find_by_sql(
"SELECT name, datediff(now(),created_at) AS days "+
"FROM projects p "+
"WHERE state='active' "+
"AND p.user_id="+@user.id.to_s+" "+
"ORDER BY days DESC "+
"LIMIT 10"
)
end
def get_stats_tags
# todo: parameterize limit
query = "select tags.id, name, count(*) as count"
query << " from taggings, tags"
query << " where tags.id = tag_id"
query << " AND taggings.user_id="+@user.id.to_s+" "
query << " group by tag_id"
query << " order by count DESC, name"
query << " limit 100"
@tags_for_cloud = Tag.find_by_sql(query).sort_by { |tag| tag.name.downcase }
max, @tags_min = 0, 0
@tags_for_cloud.each { |t|
max = t.count.to_i if t.count.to_i > max
@tags_min = t.count.to_i if t.count.to_i < @tags_min
}
# 10 = number of levels
@tags_divisor = ((max - @tags_min) / 10) + 1
end
end

View file

@ -0,0 +1,2 @@
module StatsHelper
end

View file

@ -55,6 +55,7 @@ window.onload=function(){
<li><%= navigation_link("Admin", users_path, {:accesskey => "a", :title => "Add or delete users"} ) %></li>
<% end -%>
<li><%= navigation_link(image_tag("feed-icon.png", :size => "16X16", :border => 0), {:controller => "feedlist", :action => "index"}, :title => "See a list of available feeds" ) %></li>
<li><%= navigation_link(image_tag("stats.gif", :size => "16X16", :border => 0), {:controller => "stats", :action => "index"}, :title => "See your statistics" ) %></li>
</ul>
</div>

View file

@ -0,0 +1,29 @@
<p>Of all your completed actions, the average time to complete is <%= @actions_avg_ttc %> days.
The Max-/minimum days to complete is <%= @actions_max_ttc%>/<%= @actions_min_ttc %>.
The minimum time to complete is <%= @actions_min_ttc_sec %></p>
<p>In the last 30 days you created on average <%=@sum_actions_created_last30days/30%> actions
and completed on average <%=@sum_actions_done_last30days/30%> actions per day.
In the last 12 months you created on average <%=@sum_actions_created_last12months/12 %> actions
and completed on average <%=@sum_actions_done_last12months/12%> actions per month.
<p><br/>
<%= render :partial => 'chart', :locals => {:width => @chart_width, :height => @chart_height, :data => '/stats/actions_done_last30days_data'} -%>
&nbsp;
<%= render :partial => 'chart', :locals => {:width => @chart_width, :height => @chart_height, :data => '/stats/actions_done_last12months_data'} -%>
<p><br/>
<%= render :partial => 'chart', :locals => {:width => @chart_width, :height => @chart_height, :data => '/stats/actions_completion_time_data'} -%>
<p><br/>
<%= render :partial => 'chart', :locals => {:width => @chart_width, :height => @chart_height, :data => '/stats/actions_visible_running_time_data'} -%>
&nbsp;
<%= render :partial => 'chart', :locals => {:width => @chart_width, :height => @chart_height, :data => '/stats/actions_running_time_data'} -%>
<p><br/>
<%= render :partial => 'chart', :locals => {:width => @chart_width, :height => @chart_height, :data => '/stats/actions_day_of_week_all_data'} -%>
&nbsp;
<%= render :partial => 'chart', :locals => {:width => @chart_width, :height => @chart_height, :data => '/stats/actions_day_of_week_30days_data'} -%>
<p><br/>
<%= render :partial => 'chart', :locals => {:width => @chart_width, :height => @chart_height, :data => '/stats/actions_time_of_day_all_data'} -%>
&nbsp;
<%= render :partial => 'chart', :locals => {:width => @chart_width, :height => @chart_height, :data => '/stats/actions_time_of_day_30days_data'} -%>

View file

@ -0,0 +1,5 @@
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" width="<%=width-%>" height="<%=height-%>" id="graph-2" align="middle">
<param name="allowScriptAccess" value="sameDomain" />
<param name="movie" value="/open-flash-chart.swf?width=<%=width-%>&height=<%=height-%>&data=<%=data-%>" /><param name="quality" value="high" /><param name="bgcolor" value="#FFFFFF" />
<embed src="/open-flash-chart.swf?width=<%=width-%>&height=<%=height-%>&data=<%=data-%>" quality="high" bgcolor="#FFFFFF" width="<%=width-%>" height="<%=height-%>" name="open-flash-chart" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>

View file

@ -0,0 +1,30 @@
<p><br/>
<%= render :partial => 'chart', :locals => {:width => @pie_width, :height => @pie_height, :data => '/stats/context_total_actions_data'} -%>
&nbsp;
<%= render :partial => 'chart', :locals => {:width => @pie_width, :height => @pie_height, :data => '/stats/context_running_actions_data'} -%>
<br/><p><b>Top 5 Contexts</b><br>
<%
1.upto 5 do |i|
%><%=i-%> -
<%= i <= @actions_per_context.size ? @actions_per_context[i-1]['name'] : "n/a"%>
(
<%= i <= @actions_per_context.size ? @actions_per_context[i-1]['total'] : "n/a"%>
)
<br/><%
end
-%>
</p>
<br/><p><b>Top 5 Visible Contexts with uncomplete actions</b><br>
<%
1.upto 5 do |i|
%><%=i-%> -
<%= i <= @running_actions_per_context.size ? @running_actions_per_context[i-1]['name'] : "n/a"-%>
(
<%= i <= @running_actions_per_context.size ? @running_actions_per_context[i-1]['total'] : "n/a"-%>
)
<br/><%
end
-%>
</p>

View file

@ -0,0 +1,42 @@
<br/>
<p><b>Top 10 projects</b><br/>
<% i=0
@projects_and_actions.each do |p|
i+=1 -%>
<%= i -%> - <%= p.name %> (<%=p.count %> actions) <br/>
<% end
if i < 10
i.upto 10 do |j| %>
<%= i -%> - n/a (n/a) <br/>
<% end
end
%>
<br/>
<p><b>Top 10 project in past 30 days</b><br/>
<% i=0
@projects_and_actions_last30days.each do |p|
i+=1 -%>
<%= i -%> - <%= p.name %> (<%=p.count %> actions) <br/>
<% end
if i < 10
i.upto 10 do |j| %>
<%= i -%> - n/a (n/a) <br/>
<% end
end
%>
<br/>
<p><b>Top 10 longest running projects</b><br/>
<% i=0
@projects_and_runtime.each do |p|
i+=1 -%>
<%= i -%> - <%= p.name %> (<%=p.days %> days) <br/>
<% end
if i < 10
i.upto 10 do |j| %>
<%= i -%> - n/a (n/a) <br/>
<% end
end
%>
<br/>

View file

@ -0,0 +1,15 @@
<br/>
<P><B>Tag Cloud</b></p>
<p>
<% if @tags_for_cloud.size < 1
%> no tags available <%
else
@tags_for_cloud.each do |t| %>
<%= link_to t.name,
{:controller => "todos", :action => "tag", :id => t.name},
{:style => "font-size: " + (9 + 2*(t.count.to_i-@tags_min)/@tags_divisor).to_s + "pt",
:title => t.count+" actions"}
-%> <%
end
end-%>
</p>

View file

@ -0,0 +1,13 @@
<p>You have <%= @projects.count%> projects.
Of those <%= @projects.count(:conditions => "state = 'active'")%> are active projects,
<%= @projects.count(:conditions => "state = 'hidden'")%> hidden projects and
<%= @projects.count(:conditions => "state = 'completed'")%> completed projects</p>
<p>You have <%= @contexts.count%> contexts.
Of those <%= @contexts.count(:conditions => "hide = 'false'")%> are visible contexts and
<%= @contexts.count(:conditions => "hide = 'true'") %> are hidden contexts
<p>You have <%= @actions.reject{ |t| t.completed? }.length %> uncompleted actions of which
<%= @actions.select{ |t| t.deferred? }.length %> are deferred actions.
<p>Since your first action on <%= format_date(@first_action.created_at) %> you have a total of <%= @actions.count %> actions. <%= @actions.select { |t| t.completed? }.length %> of these are completed.
<p>You have <%= @tags.count-%> tags placed on actions. Of those tags, <%= @unique_tags.size -%> are unique.

View file

@ -0,0 +1,26 @@
&title=Completion time (all completed actions),{font-size:16},&
&y_legend=Actions,12,0x736AFF&
&x_legend=Running time of an action (weeks),12,0x736AFF&
&y_ticks=5,10,5&
&filled_bar=50,0x9933CC,0x8010A0&
&values=
<% @count = @max_days > @cut_off*7 ? @cut_off : @max_days/7
0.upto @count-1 do |i| -%>
<%= @actions_completion_time_hash[i] -%>,
<% end -%>
<%
@sum=0
@count.upto @max_days/7 do |i|
@sum += @actions_completion_time_hash[i]
end -%>
<%=@sum%>&
&x_labels=within 1,
<% 1.upto @count-1 do |i| -%>
<%= i %>-<%= i+1 %>,
<% end -%>
> <%= @count %>&
&y_min=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,1&

View file

@ -0,0 +1,23 @@
&title=Day of week (past 30 days),{font-size:16},&
&y_legend=Number of actions,12,0x736AFF&
&x_legend=Day of week,12,0x736AFF&
&y_ticks=5,10,5&
&filled_bar=50,0x9933CC,0x8010A0,Created,8&
&filled_bar_2=50,0x0066CC,0x0066CC,Completed,8&
&values=<%
0.upto 5 do |i| -%>
<%=@actions_creation_day_array[i] -%>,
<% end -%><%=@actions_creation_day_array[6]%>&
&values_2=<%
0.upto 5 do |i| -%>
<%=@actions_completion_day_array[i] -%>,
<% end -%><%=@actions_completion_day_array[6]%>&
&x_labels= <%
0.upto 5 do |i| -%>
<%=Date::DAYNAMES[i] -%>,
<% end -%><%=Date::DAYNAMES[6]%>&
&y_min=0&
<% # add one to @max for people who have no actions completed yet.
# OpenFlashChart cannot handle y_max=0 -%>
&y_max=<%=@max+1 -%>&
&x_label_style=9,,2,1&

View file

@ -0,0 +1,23 @@
&title=Day of week (all actions),{font-size:16},&
&y_legend=Number of actions,12,0x736AFF&
&x_legend=Day of week,12,0x736AFF&
&y_ticks=5,10,5&
&filled_bar=50,0x9933CC,0x8010A0,Created,8&
&filled_bar_2=50,0x0066CC,0x0066CC,Completed,8&
&values=<%
0.upto 5 do |i| -%>
<%=@actions_creation_day_array[i] -%>,
<% end -%><%=@actions_creation_day_array[6]%>&
&values_2=<%
0.upto 5 do |i| -%>
<%=@actions_completion_day_array[i] -%>,
<% end -%><%=@actions_completion_day_array[6]%>&
&x_labels= <%
0.upto 5 do |i| -%>
<%=Date::DAYNAMES[i] -%>,
<% end -%><%=Date::DAYNAMES[6]%>&
&y_min=0&
<% # add one to @max for people who have no actions completed yet.
# OpenFlashChart cannot handle y_max=0 -%>
&y_max=<%=@max+1 -%>&
&x_label_style=9,,2,1&

View file

@ -0,0 +1,27 @@
&title=Actions in the last 12 months,{font-size:16},&
&y_legend=Number of actions,12,0x736AFF&
&x_legend=Months ago,12,0x736AFF&
&y_ticks=5,10,5&
&filled_bar=50,0x9933CC,0x8010A0,Completed,9&
&filled_bar_2=50,0x0066CC,0x0066CC,Created,9&
&line_3=3,0xFF0000, Avg completed, 9&
&line_4=3,0x00FF00, Avg created, 9&
&values=
<% 0.upto 11 do |i| -%>
<%= @actions_done_last12months_hash[i.to_s]%>,
<% end -%><%= @actions_done_last12months_hash["12"]%>&
&values_2=
<% 0.upto 11 do |i| -%>
<%= @actions_created_last12months_hash[i.to_s]%>,
<% end -%><%= @actions_created_last12months_hash["12"]%>&
&values_3=<%0.upto 11 do |i| -%><%=@sum_actions_done_last12months/12-%>,<%end-%><%=@sum_actions_done_last12months/12-%>&
&values_4=<%0.upto 11 do |i| -%><%=@sum_actions_created_last12months/12-%>,<%end-%><%=@sum_actions_created_last12months/12-%>&
&x_labels=<%0.upto 11 do |i| -%>
<%= Date::MONTHNAMES[ (Time.now.mon - i -1 ) % 12 + 1 ] -%>,
<% end -%>
<%= Date::MONTHNAMES[(Time.now.mon - 12 -1 ) % 12 + 1] -%>&
&y_min=0&
<% # add one to @max for people who have no actions completed yet.
# OpenFlashChart cannot handle y_max=0 -%>
&y_max=<%=@max+@max/10+1-%>&
&x_label_style=9,,2,&

View file

@ -0,0 +1,18 @@
&title=Actions completed in the last 12 months,16,&
&y_legend=Number of actions,12,0x736AFF&
&x_legend=Months ago,12,0x736AFF&
&y_ticks=5,10,5&
&filled_bar=50,0x9933CC,0x8010A0&
&line_2=3,0xFF0000&
&values=
<% 0.upto 11 do |i| -%>
<%= @actions_done_last12months_hash[i.to_s]%>,
<% end -%><%= @actions_done_last12months_hash["12"]%>&
&values_2=<%0.upto 11 do |i| -%><%=@sum_actions_done_last12months/12-%>,<%end-%><%=@sum_actions_done_last12months/12-%>&
&x_labels=<%0.upto 11 do |i| -%>
<%= Date::MONTHNAMES[ (Time.now.mon - i -1 ) % 12 + 1 ] -%>,
<% end -%>
<%= Date::MONTHNAMES[(Time.now.mon - 12 -1 ) % 12 + 1] -%>&
&y_min=0&
&y_max=<%=@max-%>&
&x_label_style=9,,2,&

View file

@ -0,0 +1,42 @@
&title=Actions in the last 30 days,{font-size:16},&
&y_legend=Number of actions,12,0x736AFF&
&x_legend=Number of days ago,12,0x736AFF&
&y_ticks=5,10,5&
&filled_bar=50,0x9933CC,0x8010A0,Completed,9&
&filled_bar_2=50,0x0066CC,0x0066CC,Created,9&
&line_3=3,0xFF0000, Avg completed, 9&
&line_4=3,0x00FF00, Avg created, 9&
&values=
<% 0.upto 29 do |i| -%>
<%= @actions_done_last30days_hash[i.to_s]%>,
<% end -%><%= @actions_done_last30days_hash["30"]%>&
&values_2=
<% 0.upto 29 do |i| -%>
<%= @actions_created_last30days_hash[i.to_s]%>,
<% end -%><%= @actions_created_last30days_hash["30"]%>&
&values_3=
<%0.upto 29 do |i| -%>
<%=@sum_actions_done_last30days/30-%>,
<%end-%>
<%=@sum_actions_done_last30days/30-%>&
&values_4=
<%0.upto 29 do |i| -%>
<%=@sum_actions_created_last30days/30-%>,
<%end-%>
<%=@sum_actions_created_last30days/30-%>&
&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") -%>&
&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 -%>
&y_max=<%=@max+@max/10+1 -%>&
&x_label_style=9,,2,3&

View file

@ -0,0 +1,28 @@
&title=Actions completed in the last 30 days,16,&
&y_legend=Number of actions,12,0x736AFF&
&x_legend=Number of days ago,12,0x736AFF&
&y_ticks=5,10,5&
&filled_bar=50,0x9933CC,0x8010A0&
&line_2=3,0xFF0000&
&values=
<% 0.upto 29 do |i| -%>
<%= @actions_done_last30days_hash[i.to_s]%>,
<% end -%><%= @actions_done_last30days_hash["30"]%>&
&values_2=
<%0.upto 29 do |i| -%>
<%=@sum_actions_done_last30days/30-%>,
<%end-%>
<%=@sum_actions_done_last30days/30-%>&
&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") -%>&
&y_min=0&
&y_max=<%=@max -%>&
&x_label_style=9,,2,3&

View file

@ -0,0 +1,27 @@
&title=Current running time of all uncompleted actions,{font-size:16},&
&y_legend=Actions,12,0x736AFF&
&x_legend=Running time of an action (weeks),12,0x736AFF&
&y_ticks=5,10,5&
&filled_bar=50,0x9933CC,0x8010A0&
&values=
<% @count = @max_days > @cut_off*7 ? @cut_off : @max_days/7
0.upto @count-1 do |i| -%>
<%= @actions_running_time_hash[i] -%>,
<% end -%>
<%
@sum=0
@count.upto @max_days/7 do |i|
@sum += @actions_running_time_hash[i]
end -%>
<%=@sum%>&
&x_labels=< 1,
<% 1.upto @count-1 do |i| -%>
<%= i %>-<%= i+1 %>,
<% end -%>
><%=@count-%>&
&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 -%>
&y_max=<%=1+@max_actions+@max_actions/10-%>&
&x_label_style=9,,2,2&

View file

@ -0,0 +1,23 @@
&title=Time of day (last 30 days),{font-size:16},&
&y_legend=Number of actions,12,0x736AFF&
&x_legend=Time of Day,12,0x736AFF&
&y_ticks=5,10,5&
&filled_bar=50,0x9933CC,0x8010A0,Created,8&
&filled_bar_2=50,0x0066CC,0x0066CC,Completed,8&
&values=<%
0.upto 22 do |i| -%>
<%=@actions_creation_hour_array[i] -%>,
<% end -%><%=@actions_creation_hour_array[23]%>&
&values_2=<%
0.upto 22 do |i| -%>
<%=@actions_completion_hour_array[i] -%>,
<% end -%><%=@actions_completion_hour_array[23]%>&
&x_labels= <%
0.upto 22 do |i| -%>
<%=i-%>,
<% end -%>23&
&y_min=0&
<% # add one to @max for people who have no actions completed yet.
# OpenFlashChart cannot handle y_max=0 -%>
&y_max=<%=@max+1 -%>&
&x_label_style=9,,1,1&

View file

@ -0,0 +1,23 @@
&title=Time of day (all actions),{font-size:16},&
&y_legend=Number of actions,12,0x736AFF&
&x_legend=Time of Day,12,0x736AFF&
&y_ticks=5,10,5&
&filled_bar=50,0x9933CC,0x8010A0,Created,8&
&filled_bar_2=50,0x0066CC,0x0066CC,Completed,8&
&values=<%
0.upto 22 do |i| -%>
<%=@actions_creation_hour_array[i] -%>,
<% end -%><%=@actions_creation_hour_array[23]%>&
&values_2=<%
0.upto 22 do |i| -%>
<%=@actions_completion_hour_array[i] -%>,
<% end -%><%=@actions_completion_hour_array[23]%>&
&x_labels= <%
0.upto 22 do |i| -%>
<%=i-%>,
<% end -%>23&
&y_min=0&
<% # add one to @max for people who have no actions completed yet.
# OpenFlashChart cannot handle y_max=0 -%>
&y_max=<%=@max+1 -%>&
&x_label_style=9,,1,1&

View file

@ -0,0 +1,27 @@
&title=Current running time of uncompleted visible actions,{font-size:16},&
&y_legend=Actions,12,0x736AFF&
&x_legend=Running time of an action (weeks),12,0x736AFF&
&y_ticks=5,10,5&
&filled_bar=50,0x9933CC,0x8010A0&
&values=
<% @count = @max_days > @cut_off*7 ? @cut_off : @max_days/7
0.upto @count-1 do |i| -%>
<%= @actions_running_time_hash[i] -%>,
<% end -%>
<%
@sum=0
@count.upto @max_days/7 do |i|
@sum += @actions_running_time_hash[i]
end -%>
<%=@sum%>&
&x_labels=< 1,
<% 1.upto @count-1 do |i| -%>
<%= i %>-<%= i+1 %>,
<% end -%>
><%=@count-%>&
&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 -%>
&y_max=<%=1+@max_actions+@max_actions/10-%>&
&x_label_style=9,,2,2&

View file

@ -0,0 +1,16 @@
&title=Spread of running actions for visible contexts,{font-size:16}&
&pie=60,#505050,#000000,true,1&
&x_axis_steps=1& &y_ticks=5,10,5& &line=3,#87421F& &y_min=0& &y_max=20&
&values=<%
0.upto @actions_per_context.size()-2 do | i |
%><%=@actions_per_context[i]['total'].to_i*100/@sum%>,<%
end
-%><%=@actions_per_context[@actions_per_context.size()-1]['total'].to_i*100/@sum%>&
&pie_labels=<%
0.upto @actions_per_context.size()-2 do | i |
%><%=@actions_per_context[i]['name']%>,<%
end
-%><%=@actions_per_context[@actions_per_context.size()-1]['name']%>&
&colours=#d01f3c,#356aa0,#C79810,#c61fd0,#1fc6d0,#1fd076,#72d01f,#c6d01f,#d0941f&
&tool_tip=#x_label#: #val#%25&
&x_label_style=9,,2,1&

View file

@ -0,0 +1,16 @@
&title=Spread of actions for all context,{font-size:16}&
&pie=70,#505050,#000000,true,1&
&x_axis_steps=1& &y_ticks=5,10,5& &line=3,#87421F& &y_min=0& &y_max=20&
&values=<%
0.upto @actions_per_context.size()-2 do | i |
%><%=@actions_per_context[i]['total'].to_i*100/@sum%>,<%
end
-%><%=@actions_per_context[@actions_per_context.size()-1]['total'].to_i*100/@sum%>&
&pie_labels=<%
0.upto @actions_per_context.size()-2 do | i |
%><%=@actions_per_context[i]['name']%>,<%
end
-%><%=@actions_per_context[@actions_per_context.size()-1]['name']%>&
&colours=#d01f3c,#356aa0,#C79810,#c61fd0,#1fc6d0,#1fd076,#72d01f,#c6d01f,#d0941f&
&tool_tip=#x_label#: #val#%25&
&x_label_style=9,,2,1&

View file

@ -0,0 +1,23 @@
<h2>Totals</h2>
<%= render :partial => 'totals' -%>
<br/><br/>
<h2>Actions</h2>
<%= render :partial => 'actions' -%>
<br/><br/>
<h2>Contexts</h2>
<%= render :partial => 'contexts' -%>
<br/><br/>
<h2>Projects</h2>
<%= render :partial => 'projects' -%>
<h2>Tags</h2>
<%= render :partial => 'tags' -%>

BIN
tracks/public/images/stats.gif Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 B

Binary file not shown.

View file

@ -0,0 +1,18 @@
require File.dirname(__FILE__) + '/../test_helper'
require 'stats_controller'
# Re-raise errors caught by the controller.
class StatsController; def rescue_action(e) raise e end; end
class StatsControllerTest < Test::Unit::TestCase
def setup
@controller = StatsController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
end
# Replace this with your real tests.
def test_truth
assert true
end
end