Commit 0cb218bb authored by Raphael Sofaer's avatar Raphael Sofaer

Delete statistic and data point models

parent a7f149e3
class StatisticsController < ApplicationController
before_filter :authenticate_user!
before_filter :redirect_unless_admin
def index
@statistics = Statistic.find(:all, :order => 'created_at DESC').paginate(:page => params[:page], :per_page => 15)
end
def show
@statistic = Statistic.where(:id => params[:id]).first
@distribution = @statistic.distribution_as_array
@google_chart_url = Gchart.line( :size => '700x400',
:title => "Posts on day",
:bg => 'efefef',
:legend => ['Posts'],
:data => @distribution,
:max_value => 1,
:axis_with_labels => ['x','y'],
:axis_labels => [(0..@distribution.length-1).to_a.map{|d| d%10==0 ? d : ''},
(0..10).to_a.map!{|int| int.to_f/10}]
)
end
def generate_single
stat = Statistic.generate()
redirect_to stat
end
def user_search
user = params[:user] || {}
user = user.delete_if {|key, value| value.blank? }
params[:user] = user
if user.keys.count == 0
@users = []
else
@users = User.where(params[:user]).all || []
end
render 'statistics/user_search'
end
def admin_inviter
Invitation.create_invitee(:identifier => params[:identifier])
flash[:notice] = "invitation sent to #{params[:identifier]}"
redirect_to 'statistics/user_search'
end
end
class DataPoint < ActiveRecord::Base
belongs_to :statistic
def self.users_with_posts_on_day(time, number)
sql = ActiveRecord::Base.connection()
value = sql.execute("SELECT COUNT(*) FROM (SELECT COUNT(*) AS post_sum, person_id FROM posts WHERE created_at >= '#{(time - 1.days).utc.to_datetime}' AND created_at <= '#{time.utc.to_datetime}' GROUP BY person_id) AS t1 WHERE t1.post_sum = #{number};").first[0]
self.new(:key => number.to_s, :value => value)
end
end
class Statistic < ActiveRecord::Base
has_many :data_points, :class_name => 'DataPoint'
def compute_average
users = 0
sum = 0
self.data_points.each do |d|
sum += d.key.to_i*d.value
users += d.value
end
self.average = sum.to_f/users
end
def distribution
@dist ||= lambda {
dist = {}
self.data_points.each do |d|
dist[d.key] = d.value.to_f/users_in_sample
end
dist
}.call
end
def distribution_as_array
dist = distribution
arr = []
(0..dist.size-1).each do |key|
arr << dist[key.to_s]
end
arr
end
def users_in_sample
@users ||= lambda {
users = self.data_points.map{|d| d.value}
users.inject do |total,curr|
total += curr
end
}.call
end
def generate_graph
# need to use google's graph API
end
def self.generate(time=Time.now, post_range=(0..50))
stat = Statistic.new(:time => time)
stat.save
post_range.each do |n|
data_point = DataPoint.users_with_posts_on_day(time,n)
data_point.statistic = stat
data_point.save
end
stat.compute_average
stat.save
stat
end
end
-# Copyright (c) 2010, Diaspora Inc. This file is
-# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file.
%h1 Statistics
%ul
- for statistic in @statistics
%li= link_to statistic.created_at, statistic
= will_paginate @statistics
-# Copyright (c) 2010, Diaspora Inc. This file is
-# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file.
%h3 Viewing statistic
%h2
= "Users in sample: #{@statistic.users_in_sample}"
= image_tag(@google_chart_url)
%br
= link_to 'all statistics', statistics_path
......@@ -14,8 +14,6 @@ Diaspora::Application.routes.draw do
match 'admins/user_search' => 'admins#user_search'
match 'admins/admin_inviter' => 'admins#admin_inviter'
match 'statistics/generate_single' => 'statistics#generate_single'
resources :statistics
match 'notifications/read_all' => 'notifications#read_all'
resources :notifications, :only => [:index, :update]
......@@ -39,7 +37,7 @@ Diaspora::Application.routes.draw do
devise_for :users, :controllers => {:registrations => "registrations",
:password => "devise/passwords",
:invitations => "invitations"} do
get 'invitations/resend/:id' => 'invitations#resend', :as => 'invitation_resend'
end
......
class DropStatistics < ActiveRecord::Migration
def self.up
drop_table :statistics
drop_table :data_points
end
def self.down
end
end
......@@ -10,7 +10,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20110228201109) do
ActiveRecord::Schema.define(:version => 20110301202619) do
create_table "aspect_memberships", :force => true do |t|
t.integer "aspect_id", :null => false
......@@ -70,16 +70,6 @@ ActiveRecord::Schema.define(:version => 20110228201109) do
add_index "contacts", ["user_id", "pending"], :name => "index_contacts_on_user_id_and_pending"
add_index "contacts", ["user_id", "person_id"], :name => "index_contacts_on_user_id_and_person_id", :unique => true
create_table "data_points", :force => true do |t|
t.string "key", :null => false
t.integer "value", :null => false
t.integer "statistic_id", :null => false
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "data_points", ["statistic_id"], :name => "index_data_points_on_statistic_id"
create_table "invitations", :force => true do |t|
t.text "message"
t.integer "sender_id", :null => false
......@@ -436,13 +426,6 @@ ActiveRecord::Schema.define(:version => 20110228201109) do
add_index "services", ["mongo_id"], :name => "index_services_on_mongo_id"
add_index "services", ["user_id"], :name => "index_services_on_user_id"
create_table "statistics", :force => true do |t|
t.integer "average"
t.datetime "time", :null => false
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "users", :force => true do |t|
t.string "username"
t.text "serialized_private_key"
......
......@@ -55,15 +55,6 @@ namespace :statistics do
puts "Users with 10 or more contacts: %i" % users_with_x_contacts(9)
end
task :model => :environment do
stat = Statistic.new(:type => "posts_per_day")
[0..15].each do |n|
stat.data_points << DataPoint.posts_per_day(n)
end
stat.compute_average
stat.save
end
task :splunk => :environment do
set_up_user_stats
puts "event=statistic, type=users, count=#{@users}, "+
......
require 'spec_helper'
describe StatisticsController do
render_views
before do
AppConfig[:admins] = ['alice']
sign_in :user, alice
end
before do
faker_stat = Statistic.generate
@stat = Statistic.new
5.times do |n|
bob.post(:status_message, :message => 'hi', :to => bob.aspects.first)
end
(0..10).each do |n|
@stat.data_points << DataPoint.users_with_posts_on_day(Time.now, n)
end
@stat.time = faker_stat.time
@stat.save
end
describe '#index' do
it 'returns all statistics' do
get :index
assigns[:statistics].should include @stat
end
end
describe '#show' do
it 'succeeds' do
get :show, :id => @stat.id
response.should be_success
end
end
describe ' sets a before filter to use #redirect_unless_admin' do
it 'redirects for non admins' do
AppConfig[:admins] = ['bob']
get :index
response.should be_redirect
end
it 'succeeds' do
get :index
response.should be_success
end
end
end
require 'spec_helper'
describe DataPoint do
before do
@time = Time.now
end
describe '.users_with_posts_on_day' do
it 'returns a DataPoint object' do
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_on_day(@time, 1)
point.value.should == 1
end
it 'returns a DataPoint with zero value' do
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_on_day(Time.now, 15)
point.key.should == 15.to_s
end
end
end
require 'spec_helper'
describe Statistic do
before do
@stat = Statistic.first
@time = Time.now
end
describe '#compute_average' do
it 'computes the average of all its DataPoints' do
@stat.compute_average.should == 16.to_f/3
end
end
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|
d.should == 1.to_f/3
end
end
it 'generates a distribution' do
values = @stat.distribution.map{|d| d[1]}
values.inject{ |sum, curr|
sum += curr
}.should == 1
end
end
describe '#distribution_as_array' do
it 'returns an array' do
@stat.distribution_as_array.class.should == Array
end
it 'returns in order' do
dist = @stat.distribution_as_array
[dist[1], dist[5], dist[10]].each do |d|
d.should == 1.to_f/3
end
end
end
describe '#users_in_sample' do
it 'returns a count' do
@stat.users_in_sample.should == 3
end
end
describe '#generate_graph' do
it 'outputs a binary string' do
pending "should use google graph API"
@stat.generate_graph.class.should == String
end
end
describe '.generate' do
before 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
......@@ -14,24 +14,6 @@ FixtureBuilder.configure do |fbuilder|
connect_users(bob, bob.aspects.first, alice, alice.aspects.first)
connect_users(bob, bob.aspects.first, eve, eve.aspects.first)
# Statistics
frodo = Factory(:user_with_aspect, :username => "frodo")
sam = Factory(:user_with_aspect, :username => "sam")
bilbo = Factory(:user_with_aspect, :username => "bilbo")
stat = Statistic.new
time = Time.now
1.times { frodo.post_at_time(time) }
5.times { sam.post_at_time(time) }
10.times { bilbo.post_at_time(time) }
(0..10).each do |n|
stat.data_points << DataPoint.users_with_posts_on_day(time, n)
end
stat.time = time
stat.save!
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment