Commit fdaeaf26a8982de60a59f0979ebd28a693cfc222

Authored by Dhruv Kapadia
1 parent 06ee1c72

Adding density model(1), rake task to calculate density(2)

(1) We calculate the density of votes over time to see if the catchup
algorithm is having an effect. For each question, there are four types
of prompts (seed vs seed, seed vs nonseed, nonseed vs seed, and nonseed
vs nonseed). Over time, the density of all types of prompts should
converge. This model will allow us to track over time

(2)Rake task will be run every night via a cron job. Simply calculates
and saves the four density records for each question in the db.
app/controllers/densities_controller.rb 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +class DensitiesController < InheritedResources::Base
  2 + respond_to :xml, :json
  3 + before_filter :authenticate
  4 +
  5 + def index
  6 + if params[:question_id]
  7 + logger.info(" Got a question id")
  8 + @densities = Density.find(:all, :conditions => {:question_id => params[:question_id] }, :order => :created_at )
  9 + end
  10 + index!
  11 + end
  12 +
  13 +
  14 +end
... ...
app/models/density.rb 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +class Density < ActiveRecord::Base
  2 + belongs_to :question
  3 +end
... ...
app/models/question.rb
... ... @@ -17,7 +17,9 @@ class Question &lt; ActiveRecord::Base
17 17 end
18 18 end
19 19 has_many :votes
20   -
  20 + has_many :densities
  21 +
  22 + #comment out to run bt import script!
21 23 after_save :ensure_at_least_two_choices
22 24 attr_accessor :ideas
23 25  
... ... @@ -146,4 +148,66 @@ class Question &lt; ActiveRecord::Base
146 148 end
147 149 end
148 150  
  151 + def density
  152 + # slow code, only to be run by cron job once at night
  153 + the_prompts = prompts.find(:all, :include => ['left_choice', 'right_choice'])
  154 +
  155 + seed_seed_sum = 0
  156 + seed_seed_total = 0
  157 +
  158 + seed_nonseed_sum= 0
  159 + seed_nonseed_total= 0
  160 +
  161 + nonseed_seed_sum= 0
  162 + nonseed_seed_total= 0
  163 +
  164 + nonseed_nonseed_sum= 0
  165 + nonseed_nonseed_total= 0
  166 +
  167 + the_prompts.each do |p|
  168 + if p.left_choice.user_created == false && p.right_choice.user_created == false
  169 + seed_seed_sum += p.votes.size
  170 + seed_seed_total +=1
  171 + elsif p.left_choice.user_created == false && p.right_choice.user_created == true
  172 + seed_nonseed_sum += p.votes.size
  173 + seed_nonseed_total +=1
  174 + elsif p.left_choice.user_created == true && p.right_choice.user_created == false
  175 + nonseed_seed_sum += p.votes.size
  176 + nonseed_seed_total +=1
  177 + elsif p.left_choice.user_created == true && p.right_choice.user_created == true
  178 + nonseed_nonseed_sum += p.votes.size
  179 + nonseed_nonseed_total +=1
  180 + end
  181 + end
  182 +
  183 + densities = {}
  184 + densities[:seed_seed] = seed_seed_sum.to_f / seed_seed_total.to_f
  185 + densities[:seed_nonseed] = seed_nonseed_sum.to_f / seed_nonseed_total.to_f
  186 + densities[:nonseed_seed] = nonseed_seed_sum.to_f / nonseed_seed_total.to_f
  187 + densities[:nonseed_nonseed] = nonseed_nonseed_sum.to_f / nonseed_nonseed_total.to_f
  188 +
  189 + puts "Seed_seed sum: #{seed_seed_sum}, seed_seed total num: #{seed_seed_total}"
  190 + puts "Seed_nonseed sum: #{seed_nonseed_sum}, seed_nonseed total num: #{seed_nonseed_total}"
  191 + puts "Nonseed_seed sum: #{nonseed_seed_sum}, nonseed_seed total num: #{nonseed_seed_total}"
  192 + puts "Nonseed_nonseed sum: #{nonseed_nonseed_sum}, nonseed_nonseed total num: #{nonseed_nonseed_total}"
  193 +
  194 +
  195 + densities
  196 + end
  197 +
  198 + def save_densities!
  199 +
  200 + d_hash = density
  201 +
  202 + d_hash.each do |type, average|
  203 + d = Density.new
  204 + d.question_id = self.id
  205 + d.prompt_type = type.to_s
  206 + d.value = average.nan? ? nil : average
  207 + d.save!
  208 + end
  209 + end
  210 +
  211 +
  212 +
149 213 end
... ...
config/routes.rb
1 1 ActionController::Routing::Routes.draw do |map|
2 2 #map.resources :clicks
  3 + map.resources :densities
3 4 map.resources :visitors, :collection => {:votes_by_session_ids => :post}
4 5 map.resources :questions, :member => { :object_info_totals_by_date => :get,
5 6 :num_votes_by_visitor_id => :get,
... ...
db/migrate/20100331161516_create_densities.rb 0 → 100644
... ... @@ -0,0 +1,15 @@
  1 +class CreateDensities < ActiveRecord::Migration
  2 + def self.up
  3 + create_table :densities do |table|
  4 + table.integer :question_id
  5 + table.float :value
  6 + table.string :type, :default => ""
  7 + table.timestamps
  8 + end
  9 +
  10 + end
  11 +
  12 + def self.down
  13 + drop_table :densities
  14 + end
  15 +end
... ...
db/migrate/20100331180328_rename_density_type_column.rb 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +class RenameDensityTypeColumn < ActiveRecord::Migration
  2 + def self.up
  3 + rename_column :densities, :type, :prompt_type
  4 + end
  5 +
  6 + def self.down
  7 + rename_column :denisities, :prompt_type, :type
  8 + end
  9 +end
... ...
lib/tasks/test_api.rake
... ... @@ -106,6 +106,13 @@ namespace :test_api do
106 106 end
107 107 end
108 108  
  109 +
  110 + desc "Generate density information for each question - should be run nightly"
  111 + task(:generate_density_information => :environment) do
  112 + Question.find(:all).each do |q|
  113 + q.save_densities!
  114 + end
  115 + end
109 116  
110 117 desc "Description here"
111 118 task(:question_vote_consistency => :environment) do
... ...
test/factories/density.rb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +Factory.define :density do |density|
  2 + density.question_id
  3 + density.value
  4 + density.type { 'string' }
  5 +end
... ...
test/unit/density_test.rb 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +require 'test_helper'
  2 +
  3 +class DensityTest < ActiveSupport::TestCase
  4 + should "be valid with factory" do
  5 + assert_valid Factory.build(:density)
  6 + end
  7 +end
... ...