From 56831cec63b4ab255accc1feab2ad7f11205f215 Mon Sep 17 00:00:00 2001 From: zhitomirskiyi Date: Thu, 20 Jan 2011 19:48:34 -0800 Subject: [PATCH] stats WIP --- app/controllers/statistics_controller.rb | 10 +-- app/models/data_point.rb | 9 +-- app/models/statistic.rb | 14 +++- .../20110120181553_create_statistics.rb | 1 + db/schema.rb | 1 + spec/models/data_point_spec.rb | 17 +++-- spec/models/statistic_spec.rb | 75 ++++++++++++++++--- 7 files changed, 95 insertions(+), 32 deletions(-) diff --git a/app/controllers/statistics_controller.rb b/app/controllers/statistics_controller.rb index 9d4c1f930..06848a6ed 100644 --- a/app/controllers/statistics_controller.rb +++ b/app/controllers/statistics_controller.rb @@ -10,15 +10,7 @@ class StatisticsController < ApplicationController end def generate_single - stat = Statistic.new(:type => "posts_per_day") - (0..15).each do |n| - data_point = DataPoint.users_with_posts_today(n) - data_point.save - stat.data_points << data_point - end - stat.compute_average - stat.save! - stat + stat = Statistic.generate() redirect_to stat end diff --git a/app/models/data_point.rb b/app/models/data_point.rb index 9debe8526..a283e197e 100644 --- a/app/models/data_point.rb +++ b/app/models/data_point.rb @@ -1,12 +1,9 @@ class DataPoint < ActiveRecord::Base belongs_to :statistic - def self.users_with_posts_today(number) + def self.users_with_posts_on_day(time, number) sql = ActiveRecord::Base.connection() - value = sql.execute( - "SELECT COUNT(*) FROM (SELECT `people`.guid, COUNT(*) AS posts_sum FROM `people` LEFT JOIN `posts` ON `people`.id = `posts`.person_id AND `posts`.created_at > '#{(Time.now - 1.days).to_date}' GROUP BY `people`.guid) AS t1 WHERE t1.posts_sum = #{number};" - ).first[0] - - self.new(:key => number, :value => value) + value = sql.execute("SELECT COUNT(*) FROM (SELECT COUNT(*) AS post_sum, DATE(created_at) AS date, person_id FROM posts GROUP BY person_id, date HAVING date = '#{time.utc.to_date}') AS t1 WHERE t1.post_sum = #{number};").first[0] + self.new(:key => number.to_s, :value => value) end end diff --git a/app/models/statistic.rb b/app/models/statistic.rb index 34d07749c..8d55182df 100644 --- a/app/models/statistic.rb +++ b/app/models/statistic.rb @@ -5,7 +5,7 @@ class Statistic < ActiveRecord::Base users = 0 sum = 0 self.data_points.each do |d| - sum += d.key*d.value + sum += d.key.to_i*d.value users += d.value end self.average = sum.to_f/users @@ -50,4 +50,16 @@ class Statistic < ActiveRecord::Base g.labels = h g.to_blob end + + def self.generate(time=Time.now, post_range=(0..50)) + stat = Statistic.new(:type => "posts_per_day", :time => time) + post_range.each do |n| + data_point = DataPoint.users_with_posts_on_day(time,n) + data_point.save + stat.data_points << data_point + end + stat.compute_average + stat.save + stat + end end diff --git a/db/migrate/20110120181553_create_statistics.rb b/db/migrate/20110120181553_create_statistics.rb index 63eb758f6..bf0fe9910 100644 --- a/db/migrate/20110120181553_create_statistics.rb +++ b/db/migrate/20110120181553_create_statistics.rb @@ -3,6 +3,7 @@ class CreateStatistics < ActiveRecord::Migration create_table :statistics do |t| t.integer :average t.string :type + t.datetime :time t.timestamps end diff --git a/db/schema.rb b/db/schema.rb index 46d3e7f0c..1015ff443 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -420,6 +420,7 @@ ActiveRecord::Schema.define(:version => 20110120182100) do create_table "statistics", :force => true do |t| t.integer "average" t.string "type" + t.datetime "time" t.datetime "created_at" t.datetime "updated_at" end diff --git a/spec/models/data_point_spec.rb b/spec/models/data_point_spec.rb index d4b689ae5..3d14e27b5 100644 --- a/spec/models/data_point_spec.rb +++ b/spec/models/data_point_spec.rb @@ -1,8 +1,13 @@ require 'spec_helper' describe DataPoint do + + before do + @time = Time.now + end + context '.posts_per_day_last_week' do - before do + before(:all) do 1.times do |n| alice.post(:status_message, :message => 'hi', :to => alice.aspects.first) end @@ -17,22 +22,22 @@ describe DataPoint do end it 'returns a DataPoint object' do - DataPoint.users_with_posts_today(1).class.should == DataPoint + DataPoint.users_with_posts_on_day(@time, 1).class.should == DataPoint end it 'returns a DataPoint with non-zero value' do - point = DataPoint.users_with_posts_today(1) + point = DataPoint.users_with_posts_on_day(@time, 1) point.value.should == 1 end it 'returns a DataPoint with zero value' do - point = DataPoint.users_with_posts_today(15) + point = DataPoint.users_with_posts_on_day(@time, 15) point.value.should == 0 end it 'returns the correct descriptor' do - point = DataPoint.users_with_posts_today(15) - point.key.should == 15 + point = DataPoint.users_with_posts_on_day(Time.now, 15) + point.key.should == 15.to_s end end end diff --git a/spec/models/statistic_spec.rb b/spec/models/statistic_spec.rb index 293f4e7bd..a1190ff52 100644 --- a/spec/models/statistic_spec.rb +++ b/spec/models/statistic_spec.rb @@ -3,38 +3,45 @@ require 'spec_helper' describe Statistic do before(:all) do @stat = Statistic.new + @time = Time.now 1.times do |n| - alice.post(:status_message, :message => 'hi', :to => alice.aspects.first) + p = alice.post(:status_message, :message => 'hi', :to => alice.aspects.first) + p.created_at = @time + p.save end 5.times do |n| - bob.post(:status_message, :message => 'hi', :to => bob.aspects.first) + p = bob.post(:status_message, :message => 'hi', :to => bob.aspects.first) + p.created_at = @time + p.save end 10.times do |n| - eve.post(:status_message, :message => 'hi', :to => eve.aspects.first) + p = eve.post(:status_message, :message => 'hi', :to => eve.aspects.first) + p.created_at = @time + p.save end (0..10).each do |n| - @stat.data_points << DataPoint.users_with_posts_today(n) + @stat.data_points << DataPoint.users_with_posts_on_day(@time, n) end end - context '#compute_average' do + describe '#compute_average' do it 'computes the average of all its DataPoints' do @stat.compute_average.should == 16.to_f/3 end end - context '#distribution' do + describe '#distribution' do it 'generates a hash' do @stat.distribution.class.should == Hash end it 'correctly sets values' do dist = @stat.distribution - [dist[1], dist[5], dist[10]].each do |d| + [dist['1'], dist['5'], dist['10']].each do |d| d.should == 1.to_f/3 end end @@ -47,7 +54,7 @@ describe Statistic do end end - context '#distribution_as_array' do + describe '#distribution_as_array' do it 'returns an array' do @stat.distribution_as_array.class.should == Array end @@ -60,15 +67,63 @@ describe Statistic do end end - context '#users_in_sample' do + describe '#users_in_sample' do it 'returns a count' do @stat.users_in_sample.should == 3 end end - context '#generate_graph' do + describe '#generate_graph' do it 'outputs a binary string' do @stat.generate_graph.class.should == String end end + + describe '.generate' do + before(:all) do + @time = Time.now - 1.day + + 1.times do |n| + p = alice.post(:status_message, :message => 'hi', :to => alice.aspects.first) + p.created_at = @time + p.save + end + + 5.times do |n| + p = bob.post(:status_message, :message => 'hi', :to => alice.aspects.first) + p.created_at = @time + p.save + end + end + + it 'creates a Statistic with a default date and range' do + time = Time.now + Time.stub!(:now).and_return(time) + + stat = Statistic.generate + stat.data_points.count.should == 51 + stat.time.should == time + end + + context 'custom date' do + before do + @stat = Statistic.generate(@time) + end + + it 'creates a Statistic with a custom date' do + @stat.time.should == @time + end + + it 'returns only desired sampling' do + @stat.users_in_sample.should == 2 + end + end + + context 'custom range' do + it 'creates a Statistic with a custom range' do + stat = Statistic.generate(Time.now, (2..32)) + stat.data_points.count.should == 31 + end + end + end end