Commit fd5da22491e6b145ad7b45649becd39fc995dd50
1 parent
beb3b15f
Exists in
master
and in
1 other branch
reindent test_api.rake
Showing
1 changed file
with
410 additions
and
410 deletions
Show diff stats
lib/tasks/test_api.rake
| ... | ... | @@ -8,8 +8,8 @@ namespace :test_api do |
| 8 | 8 | true_losses = question.votes.count(:conditions => {:loser_choice_id => choice.id}) |
| 9 | 9 | true_wins = choice.votes.count |
| 10 | 10 | Choice.update_counters choice.id, |
| 11 | - :losses => (true_losses - choice.losses), | |
| 12 | - :wins => (true_wins - choice.wins) | |
| 11 | + :losses => (true_losses - choice.losses), | |
| 12 | + :wins => (true_wins - choice.wins) | |
| 13 | 13 | choice.reload |
| 14 | 14 | choice.score = choice.compute_score |
| 15 | 15 | choice.save(false) |
| ... | ... | @@ -40,7 +40,7 @@ namespace :test_api do |
| 40 | 40 | end |
| 41 | 41 | end |
| 42 | 42 | |
| 43 | - task :all => [:question_vote_consistency,:generate_density_information] | |
| 43 | + task :all => [:question_vote_consistency,:generate_density_information] | |
| 44 | 44 | |
| 45 | 45 | desc "Ensure that all choices have 0 <= score <= 100" |
| 46 | 46 | task :verify_range_of_choices_scores => :environment do |
| ... | ... | @@ -73,255 +73,255 @@ namespace :test_api do |
| 73 | 73 | return error_message.blank? ? [success_message, false] : [error_message, true] |
| 74 | 74 | end |
| 75 | 75 | |
| 76 | - desc "Don't run unless you know what you are doing" | |
| 77 | - task(:generate_lots_of_votes => :environment) do | |
| 78 | - if Rails.env.production? | |
| 79 | - print "You probably don't want to run this in production as it will falsify a bunch of random votes" | |
| 80 | - end | |
| 81 | - | |
| 82 | - | |
| 83 | - current_user = User.first | |
| 84 | - 1000.times do |n| | |
| 85 | - puts "#{n} votes completed" if n % 100 == 0 | |
| 86 | - question = Question.find(214) # test question change as needed | |
| 87 | - @prompt = question.catchup_choose_prompt(1).first | |
| 88 | - @appearance = current_user.record_appearance(current_user.default_visitor, @prompt) | |
| 89 | - | |
| 90 | - direction = (rand(2) == 0) ? "left" : "right" | |
| 91 | - current_user.record_vote(:prompt => @prompt, :direction => direction, :appearance_lookup => @appearance.lookup) | |
| 92 | - end | |
| 76 | + desc "Don't run unless you know what you are doing" | |
| 77 | + task(:generate_lots_of_votes => :environment) do | |
| 78 | + if Rails.env.production? | |
| 79 | + print "You probably don't want to run this in production as it will falsify a bunch of random votes" | |
| 80 | + end | |
| 81 | + | |
| 93 | 82 | |
| 94 | - end | |
| 83 | + current_user = User.first | |
| 84 | + 1000.times do |n| | |
| 85 | + puts "#{n} votes completed" if n % 100 == 0 | |
| 86 | + question = Question.find(214) # test question change as needed | |
| 87 | + @prompt = question.catchup_choose_prompt(1).first | |
| 88 | + @appearance = current_user.record_appearance(current_user.default_visitor, @prompt) | |
| 95 | 89 | |
| 96 | - desc "Generate appearances for any votes that have no current appearance, should only need to be run once" | |
| 97 | - task(:generate_appearances_for_existing_votes => :environment) do | |
| 98 | - votes = Vote.all | |
| 90 | + direction = (rand(2) == 0) ? "left" : "right" | |
| 91 | + current_user.record_vote(:prompt => @prompt, :direction => direction, :appearance_lookup => @appearance.lookup) | |
| 92 | + end | |
| 99 | 93 | |
| 100 | - count = 0 | |
| 101 | - votes.each do |v| | |
| 102 | - if v.appearance.nil? | |
| 103 | - print "." | |
| 104 | - a = Appearance.create(:voter_id => v.voter_id, :site_id => v.site_id, :prompt_id => v.prompt_id, :question_id => v.question_id, :created_at => v.created_at, :updated_at => v.updated_at) | |
| 105 | - v.appearance = a | |
| 106 | - v.save | |
| 107 | - | |
| 108 | - count += 1 | |
| 109 | - end | |
| 110 | - end | |
| 111 | - | |
| 112 | - print count | |
| 113 | - end | |
| 114 | - | |
| 115 | - | |
| 116 | - desc "Generate past density information" | |
| 117 | - task(:generate_past_densities => :environment) do | |
| 118 | - #this is not elegant, but should only be run once, so quick and dirty wins | |
| 119 | - | |
| 120 | - start_date = Vote.find(:all, :conditions => 'loser_choice_id IS NOT NULL', :order => :created_at, :limit => 1).first.created_at.to_date | |
| 121 | - start_date.upto(Date.today) do |the_date| | |
| 122 | - questions = Question.find(:all, :conditions => ['created_at < ?', the_date]) | |
| 123 | - | |
| 124 | - print the_date.to_s | |
| 125 | - questions.each do |q| | |
| 126 | - puts q.id | |
| 127 | - relevant_choices = q.choices.find(:all, :conditions => ['created_at < ?', the_date]) | |
| 128 | - | |
| 129 | - seed_choices = 0 | |
| 130 | - | |
| 131 | - if relevant_choices == 0 | |
| 132 | - next | |
| 133 | - #this question had not been created yet | |
| 134 | - end | |
| 135 | - | |
| 136 | - relevant_choices.each do |c| | |
| 137 | - if !c.user_created | |
| 138 | - seed_choices+=1 | |
| 139 | - end | |
| 140 | - | |
| 141 | - end | |
| 142 | - | |
| 143 | - nonseed_choices = relevant_choices.size - seed_choices | |
| 144 | - | |
| 145 | - seed_seed_total = seed_choices **2 - seed_choices | |
| 146 | - nonseed_nonseed_total = nonseed_choices **2 - nonseed_choices | |
| 147 | - seed_nonseed_total = seed_choices * nonseed_choices | |
| 148 | - nonseed_seed_total = seed_choices * nonseed_choices | |
| 149 | - | |
| 150 | - seed_seed_sum = 0 | |
| 151 | - seed_nonseed_sum= 0 | |
| 152 | - nonseed_seed_sum= 0 | |
| 153 | - nonseed_nonseed_sum= 0 | |
| 154 | - | |
| 155 | - q.appearances.find_each(:conditions => ['prompt_id IS NOT NULL AND created_at < ?', the_date]) do |a| | |
| 156 | - | |
| 157 | - p = a.prompt | |
| 158 | - if p.left_choice.user_created == false && p.right_choice.user_created == false | |
| 159 | - seed_seed_sum += 1 | |
| 160 | - elsif p.left_choice.user_created == false && p.right_choice.user_created == true | |
| 161 | - seed_nonseed_sum += 1 | |
| 162 | - elsif p.left_choice.user_created == true && p.right_choice.user_created == false | |
| 163 | - nonseed_seed_sum += 1 | |
| 164 | - elsif p.left_choice.user_created == true && p.right_choice.user_created == true | |
| 165 | - nonseed_nonseed_sum += 1 | |
| 166 | - end | |
| 167 | - end | |
| 168 | - | |
| 169 | - densities = {} | |
| 170 | - densities[:seed_seed] = seed_seed_sum.to_f / seed_seed_total.to_f | |
| 171 | - densities[:seed_nonseed] = seed_nonseed_sum.to_f / seed_nonseed_total.to_f | |
| 172 | - densities[:nonseed_seed] = nonseed_seed_sum.to_f / nonseed_seed_total.to_f | |
| 173 | - densities[:nonseed_nonseed] = nonseed_nonseed_sum.to_f / nonseed_nonseed_total.to_f | |
| 174 | - | |
| 175 | - densities.each do |type, average| | |
| 176 | - d = Density.new | |
| 177 | - d.created_at = the_date | |
| 178 | - d.question_id = q.id | |
| 179 | - d.prompt_type = type.to_s | |
| 180 | - d.value = average.nan? ? nil : average | |
| 181 | - d.save! | |
| 182 | - end | |
| 183 | - | |
| 184 | - puts "Seed_seed sum: #{seed_seed_sum}, seed_seed total num: #{seed_seed_total}" | |
| 185 | - puts "Seed_nonseed sum: #{seed_nonseed_sum}, seed_nonseed total num: #{seed_nonseed_total}" | |
| 186 | - puts "Nonseed_seed sum: #{nonseed_seed_sum}, nonseed_seed total num: #{nonseed_seed_total}" | |
| 187 | - puts "Nonseed_nonseed sum: #{nonseed_nonseed_sum}, nonseed_nonseed total num: #{nonseed_nonseed_total}" | |
| 94 | + end | |
| 188 | 95 | |
| 96 | + desc "Generate appearances for any votes that have no current appearance, should only need to be run once" | |
| 97 | + task(:generate_appearances_for_existing_votes => :environment) do | |
| 98 | + votes = Vote.all | |
| 189 | 99 | |
| 190 | - end | |
| 100 | + count = 0 | |
| 101 | + votes.each do |v| | |
| 102 | + if v.appearance.nil? | |
| 103 | + print "." | |
| 104 | + a = Appearance.create(:voter_id => v.voter_id, :site_id => v.site_id, :prompt_id => v.prompt_id, :question_id => v.question_id, :created_at => v.created_at, :updated_at => v.updated_at) | |
| 105 | + v.appearance = a | |
| 106 | + v.save | |
| 191 | 107 | |
| 192 | - end | |
| 193 | - | |
| 194 | - end | |
| 195 | - | |
| 196 | - | |
| 197 | - desc "Should only need to be run once" | |
| 198 | - task(:generate_all_possible_prompts => :environment) do | |
| 199 | - Question.find(:all).each do |q| | |
| 200 | - choices = q.choices | |
| 201 | - if q.prompts.size > choices.size**2 - choices.size | |
| 202 | - print "ERROR: #{q.id}\n" | |
| 203 | - next | |
| 204 | - elsif q.prompts.size == choices.size**2 - choices.size | |
| 205 | - print "#{q.id} has enough prompts, skipping...\n" | |
| 206 | - next | |
| 207 | - else | |
| 208 | - print "#{q.id} should add #{(choices.size ** 2 - choices.size) - q.prompts.size}\n" | |
| 108 | + count += 1 | |
| 109 | + end | |
| 110 | + end | |
| 209 | 111 | |
| 112 | + print count | |
| 210 | 113 | end |
| 211 | - created_timestring = q.created_at.to_s(:db) | |
| 212 | - updated_timestring = Time.now.to_s(:db) #isn't rails awesome? | |
| 213 | - promptscount=0 | |
| 214 | - inserts = [] | |
| 215 | - the_prompts = Prompt.find(:all, :select => 'id, left_choice_id, right_choice_id', :conditions => {:question_id => q.id}) | |
| 216 | - | |
| 217 | - the_prompts_hash = {} | |
| 218 | - the_prompts.each do |p| | |
| 219 | - the_prompts_hash["#{p.left_choice_id},#{p.right_choice_id}"] = 1 | |
| 114 | + | |
| 115 | + | |
| 116 | + desc "Generate past density information" | |
| 117 | + task(:generate_past_densities => :environment) do | |
| 118 | + #this is not elegant, but should only be run once, so quick and dirty wins | |
| 119 | + | |
| 120 | + start_date = Vote.find(:all, :conditions => 'loser_choice_id IS NOT NULL', :order => :created_at, :limit => 1).first.created_at.to_date | |
| 121 | + start_date.upto(Date.today) do |the_date| | |
| 122 | + questions = Question.find(:all, :conditions => ['created_at < ?', the_date]) | |
| 123 | + | |
| 124 | + print the_date.to_s | |
| 125 | + questions.each do |q| | |
| 126 | + puts q.id | |
| 127 | + relevant_choices = q.choices.find(:all, :conditions => ['created_at < ?', the_date]) | |
| 128 | + | |
| 129 | + seed_choices = 0 | |
| 130 | + | |
| 131 | + if relevant_choices == 0 | |
| 132 | + next | |
| 133 | + #this question had not been created yet | |
| 134 | + end | |
| 135 | + | |
| 136 | + relevant_choices.each do |c| | |
| 137 | + if !c.user_created | |
| 138 | + seed_choices+=1 | |
| 139 | + end | |
| 140 | + | |
| 141 | + end | |
| 142 | + | |
| 143 | + nonseed_choices = relevant_choices.size - seed_choices | |
| 144 | + | |
| 145 | + seed_seed_total = seed_choices **2 - seed_choices | |
| 146 | + nonseed_nonseed_total = nonseed_choices **2 - nonseed_choices | |
| 147 | + seed_nonseed_total = seed_choices * nonseed_choices | |
| 148 | + nonseed_seed_total = seed_choices * nonseed_choices | |
| 149 | + | |
| 150 | + seed_seed_sum = 0 | |
| 151 | + seed_nonseed_sum= 0 | |
| 152 | + nonseed_seed_sum= 0 | |
| 153 | + nonseed_nonseed_sum= 0 | |
| 154 | + | |
| 155 | + q.appearances.find_each(:conditions => ['prompt_id IS NOT NULL AND created_at < ?', the_date]) do |a| | |
| 156 | + | |
| 157 | + p = a.prompt | |
| 158 | + if p.left_choice.user_created == false && p.right_choice.user_created == false | |
| 159 | + seed_seed_sum += 1 | |
| 160 | + elsif p.left_choice.user_created == false && p.right_choice.user_created == true | |
| 161 | + seed_nonseed_sum += 1 | |
| 162 | + elsif p.left_choice.user_created == true && p.right_choice.user_created == false | |
| 163 | + nonseed_seed_sum += 1 | |
| 164 | + elsif p.left_choice.user_created == true && p.right_choice.user_created == true | |
| 165 | + nonseed_nonseed_sum += 1 | |
| 166 | + end | |
| 167 | + end | |
| 168 | + | |
| 169 | + densities = {} | |
| 170 | + densities[:seed_seed] = seed_seed_sum.to_f / seed_seed_total.to_f | |
| 171 | + densities[:seed_nonseed] = seed_nonseed_sum.to_f / seed_nonseed_total.to_f | |
| 172 | + densities[:nonseed_seed] = nonseed_seed_sum.to_f / nonseed_seed_total.to_f | |
| 173 | + densities[:nonseed_nonseed] = nonseed_nonseed_sum.to_f / nonseed_nonseed_total.to_f | |
| 174 | + | |
| 175 | + densities.each do |type, average| | |
| 176 | + d = Density.new | |
| 177 | + d.created_at = the_date | |
| 178 | + d.question_id = q.id | |
| 179 | + d.prompt_type = type.to_s | |
| 180 | + d.value = average.nan? ? nil : average | |
| 181 | + d.save! | |
| 182 | + end | |
| 183 | + | |
| 184 | + puts "Seed_seed sum: #{seed_seed_sum}, seed_seed total num: #{seed_seed_total}" | |
| 185 | + puts "Seed_nonseed sum: #{seed_nonseed_sum}, seed_nonseed total num: #{seed_nonseed_total}" | |
| 186 | + puts "Nonseed_seed sum: #{nonseed_seed_sum}, nonseed_seed total num: #{nonseed_seed_total}" | |
| 187 | + puts "Nonseed_nonseed sum: #{nonseed_nonseed_sum}, nonseed_nonseed total num: #{nonseed_nonseed_total}" | |
| 188 | + | |
| 189 | + | |
| 190 | + end | |
| 191 | + | |
| 192 | + end | |
| 193 | + | |
| 220 | 194 | end |
| 221 | 195 | |
| 222 | - choices.each do |l| | |
| 223 | - choices.each do |r| | |
| 224 | - if l.id == r.id | |
| 225 | - next | |
| 226 | - else | |
| 227 | - #p = the_prompts.find{|o| o.left_choice_id == l.id && o.right_choice_id == r.id} | |
| 228 | - keystring = "#{l.id},#{r.id}" | |
| 229 | - p = the_prompts_hash[keystring] | |
| 230 | - if p.nil? | |
| 231 | - inserts.push("(NULL, #{q.id}, NULL, #{l.id}, '#{created_timestring}', '#{updated_timestring}', NULL, 0, #{r.id}, NULL, NULL)") | |
| 232 | - promptscount+=1 | |
| 196 | + | |
| 197 | + desc "Should only need to be run once" | |
| 198 | + task(:generate_all_possible_prompts => :environment) do | |
| 199 | + Question.find(:all).each do |q| | |
| 200 | + choices = q.choices | |
| 201 | + if q.prompts.size > choices.size**2 - choices.size | |
| 202 | + print "ERROR: #{q.id}\n" | |
| 203 | + next | |
| 204 | + elsif q.prompts.size == choices.size**2 - choices.size | |
| 205 | + print "#{q.id} has enough prompts, skipping...\n" | |
| 206 | + next | |
| 207 | + else | |
| 208 | + print "#{q.id} should add #{(choices.size ** 2 - choices.size) - q.prompts.size}\n" | |
| 209 | + | |
| 210 | + end | |
| 211 | + created_timestring = q.created_at.to_s(:db) | |
| 212 | + updated_timestring = Time.now.to_s(:db) #isn't rails awesome? | |
| 213 | + promptscount=0 | |
| 214 | + inserts = [] | |
| 215 | + the_prompts = Prompt.find(:all, :select => 'id, left_choice_id, right_choice_id', :conditions => {:question_id => q.id}) | |
| 216 | + | |
| 217 | + the_prompts_hash = {} | |
| 218 | + the_prompts.each do |p| | |
| 219 | + the_prompts_hash["#{p.left_choice_id},#{p.right_choice_id}"] = 1 | |
| 220 | + end | |
| 221 | + | |
| 222 | + choices.each do |l| | |
| 223 | + choices.each do |r| | |
| 224 | + if l.id == r.id | |
| 225 | + next | |
| 226 | + else | |
| 227 | + #p = the_prompts.find{|o| o.left_choice_id == l.id && o.right_choice_id == r.id} | |
| 228 | + keystring = "#{l.id},#{r.id}" | |
| 229 | + p = the_prompts_hash[keystring] | |
| 230 | + if p.nil? | |
| 231 | + inserts.push("(NULL, #{q.id}, NULL, #{l.id}, '#{created_timestring}', '#{updated_timestring}', NULL, 0, #{r.id}, NULL, NULL)") | |
| 232 | + promptscount+=1 | |
| 233 | + end | |
| 234 | + | |
| 235 | + end | |
| 236 | + | |
| 237 | + end | |
| 238 | + end | |
| 239 | + | |
| 240 | + print "Added #{promptscount} to #{q.id}\n" | |
| 241 | + sql = "INSERT INTO `prompts` (`algorithm_id`, `question_id`, `voter_id`, `left_choice_id`, `created_at`, `updated_at`, `tracking`, `votes_count`, `right_choice_id`, `active`, `randomkey`) VALUES #{inserts.join(', ')}" | |
| 242 | + unless inserts.empty? | |
| 243 | + ActiveRecord::Base.connection.execute(sql) | |
| 244 | + end | |
| 245 | + | |
| 246 | + Question.update_counters(q.id, :prompts_count => promptscount) | |
| 247 | + | |
| 248 | + | |
| 233 | 249 | end |
| 234 | 250 | |
| 235 | - end | |
| 236 | 251 | |
| 237 | - end | |
| 238 | - end | |
| 239 | 252 | |
| 240 | - print "Added #{promptscount} to #{q.id}\n" | |
| 241 | - sql = "INSERT INTO `prompts` (`algorithm_id`, `question_id`, `voter_id`, `left_choice_id`, `created_at`, `updated_at`, `tracking`, `votes_count`, `right_choice_id`, `active`, `randomkey`) VALUES #{inserts.join(', ')}" | |
| 242 | - unless inserts.empty? | |
| 243 | - ActiveRecord::Base.connection.execute(sql) | |
| 244 | 253 | end |
| 245 | 254 | |
| 246 | - Question.update_counters(q.id, :prompts_count => promptscount) | |
| 247 | - | |
| 248 | 255 | |
| 249 | - end | |
| 256 | + desc "Dump votes of a question by left vs right id" | |
| 257 | + task(:make_csv => :environment) do | |
| 250 | 258 | |
| 259 | + q = Question.find(214) | |
| 251 | 260 | |
| 252 | - | |
| 253 | - end | |
| 254 | 261 | |
| 262 | + the_prompts = q.prompts_hash_by_choice_ids | |
| 255 | 263 | |
| 256 | - desc "Dump votes of a question by left vs right id" | |
| 257 | - task(:make_csv => :environment) do | |
| 264 | + #hash_of_choice_ids_from_left_to_right_to_votes | |
| 265 | + the_hash = {} | |
| 266 | + q.choices.each do |l| | |
| 267 | + q.choices.each do |r| | |
| 268 | + next if l.id == r.id | |
| 258 | 269 | |
| 259 | - q = Question.find(214) | |
| 270 | + if not the_hash.has_key?(l.id) | |
| 271 | + the_hash[l.id] = {} | |
| 272 | + the_hash[l.id][l.id] = 0 | |
| 273 | + end | |
| 260 | 274 | |
| 275 | + p = the_prompts["#{l.id}, #{r.id}"] | |
| 276 | + if p.nil? | |
| 277 | + the_hash[l.id][r.id] = 0 | |
| 278 | + else | |
| 279 | + the_hash[l.id][r.id] = p.appearances.size | |
| 280 | + end | |
| 281 | + end | |
| 282 | + end | |
| 261 | 283 | |
| 262 | - the_prompts = q.prompts_hash_by_choice_ids | |
| 284 | + the_hash.sort.each do |xval, row| | |
| 285 | + rowarray = [] | |
| 286 | + row.sort.each do |yval, cell| | |
| 287 | + rowarray << cell | |
| 288 | + end | |
| 289 | + puts rowarray.join(", ") | |
| 290 | + end | |
| 291 | + end | |
| 263 | 292 | |
| 264 | - #hash_of_choice_ids_from_left_to_right_to_votes | |
| 265 | - the_hash = {} | |
| 266 | - q.choices.each do |l| | |
| 267 | - q.choices.each do |r| | |
| 268 | - next if l.id == r.id | |
| 269 | - | |
| 270 | - if not the_hash.has_key?(l.id) | |
| 271 | - the_hash[l.id] = {} | |
| 272 | - the_hash[l.id][l.id] = 0 | |
| 273 | - end | |
| 274 | 293 | |
| 275 | - p = the_prompts["#{l.id}, #{r.id}"] | |
| 276 | - if p.nil? | |
| 277 | - the_hash[l.id][r.id] = 0 | |
| 278 | - else | |
| 279 | - the_hash[l.id][r.id] = p.appearances.size | |
| 280 | - end | |
| 281 | - end | |
| 282 | - end | |
| 294 | + desc "Generate density information for each question - should be run nightly" | |
| 295 | + task(:generate_density_information => :environment) do | |
| 283 | 296 | |
| 284 | - the_hash.sort.each do |xval, row| | |
| 285 | - rowarray = [] | |
| 286 | - row.sort.each do |yval, cell| | |
| 287 | - rowarray << cell | |
| 288 | - end | |
| 289 | - puts rowarray.join(", ") | |
| 290 | - end | |
| 291 | - end | |
| 297 | + # calculating densities is expensive, so only do it for questions with new data | |
| 298 | + question_ids = Vote.count(:conditions => ['date(created_at) = ?', Date.yesterday], :group => 'question_id').keys() | |
| 292 | 299 | |
| 300 | + Question.find(:all, :conditions => {:id => question_ids}).each do |q| | |
| 301 | + q.save_densities! | |
| 302 | + end | |
| 293 | 303 | |
| 294 | - desc "Generate density information for each question - should be run nightly" | |
| 295 | - task(:generate_density_information => :environment) do | |
| 304 | + # we can just copy the previous night's data for remaining questions | |
| 296 | 305 | |
| 297 | - # calculating densities is expensive, so only do it for questions with new data | |
| 298 | - question_ids = Vote.count(:conditions => ['date(created_at) = ?', Date.yesterday], :group => 'question_id').keys() | |
| 306 | + Question.find(:all, :conditions => ['id NOT IN (?)', question_ids]).each do |q| | |
| 307 | + densities = q.densities.find(:all, :conditions => ['date(created_at) = ?', Date.yesterday]) | |
| 299 | 308 | |
| 300 | - Question.find(:all, :conditions => {:id => question_ids}).each do |q| | |
| 301 | - q.save_densities! | |
| 302 | - end | |
| 303 | 309 | |
| 304 | - # we can just copy the previous night's data for remaining questions | |
| 305 | - | |
| 306 | - Question.find(:all, :conditions => ['id NOT IN (?)', question_ids]).each do |q| | |
| 307 | - densities = q.densities.find(:all, :conditions => ['date(created_at) = ?', Date.yesterday]) | |
| 310 | + densities.each do |d| | |
| 311 | + new_d = d.clone | |
| 312 | + new_d.created_at = new_d.updated_at = Time.now | |
| 313 | + new_d.save! | |
| 314 | + end | |
| 308 | 315 | |
| 316 | + if densities.blank? | |
| 317 | + #fallback in case there wasn't a successful run yesterday | |
| 318 | + q.save_densities! | |
| 309 | 319 | |
| 310 | - densities.each do |d| | |
| 311 | - new_d = d.clone | |
| 312 | - new_d.created_at = new_d.updated_at = Time.now | |
| 313 | - new_d.save! | |
| 314 | - end | |
| 320 | + end | |
| 315 | 321 | |
| 316 | - if densities.blank? | |
| 317 | - #fallback in case there wasn't a successful run yesterday | |
| 318 | - q.save_densities! | |
| 319 | - | |
| 320 | - end | |
| 322 | + end | |
| 323 | + end | |
| 321 | 324 | |
| 322 | - end | |
| 323 | - end | |
| 324 | - | |
| 325 | 325 | desc "Description here" |
| 326 | 326 | task(:question_vote_consistency => :environment) do |
| 327 | 327 | questions = Question.find(:all) |
| ... | ... | @@ -384,7 +384,7 @@ namespace :test_api do |
| 384 | 384 | end |
| 385 | 385 | |
| 386 | 386 | message, error_occurred = ensure_all_votes_and_skips_have_unique_appearance |
| 387 | - | |
| 387 | + | |
| 388 | 388 | if error_occurred |
| 389 | 389 | errors << message |
| 390 | 390 | else |
| ... | ... | @@ -415,9 +415,9 @@ namespace :test_api do |
| 415 | 415 | email_text += " Test Passed: " + m + "\n" |
| 416 | 416 | end |
| 417 | 417 | end |
| 418 | - | |
| 418 | + | |
| 419 | 419 | puts email_text |
| 420 | - | |
| 420 | + | |
| 421 | 421 | if errors.empty? |
| 422 | 422 | CronMailer.deliver_info_message(CRON_EMAIL, "Test of API Vote Consistency passed", email_text) |
| 423 | 423 | else |
| ... | ... | @@ -426,34 +426,34 @@ namespace :test_api do |
| 426 | 426 | |
| 427 | 427 | end |
| 428 | 428 | |
| 429 | - def check_basic_balanced_stats(question) | |
| 430 | - error_message = "" | |
| 431 | - success_message = "2 x Total Wins = Total Votes\n" + | |
| 432 | - "Total Votes (wins + losses) is Even\n" + | |
| 433 | - "Total Votes (wins + losses) = 2 x the number of vote objects that belong to the question\n" + | |
| 434 | - "Total generated prompts on left = Total generated prompts on right" | |
| 435 | - total_wins =0 | |
| 436 | - total_votes =0 | |
| 437 | - total_generated_prompts_on_left = 0 | |
| 438 | - total_generated_prompts_on_right = 0 | |
| 439 | - total_scores_gte_fifty= 0 | |
| 440 | - total_scores_lte_fifty= 0 | |
| 441 | - error_bool = false | |
| 442 | - # votes before 2010-02-17 have null loser_choice_id therefore we | |
| 443 | - # want to ignore some tests for any question with votes before 2010-02-17 | |
| 444 | - question_has_votes_before_2010_02_17 = question.votes.count(:conditions => ["created_at < ?", '2010-02-17']) > 0 | |
| 445 | - | |
| 446 | - # reload question to make sure we have most recent data | |
| 447 | - question.reload | |
| 448 | - question.choices.each do |choice| | |
| 449 | - | |
| 429 | + def check_basic_balanced_stats(question) | |
| 430 | + error_message = "" | |
| 431 | + success_message = "2 x Total Wins = Total Votes\n" + | |
| 432 | + "Total Votes (wins + losses) is Even\n" + | |
| 433 | + "Total Votes (wins + losses) = 2 x the number of vote objects that belong to the question\n" + | |
| 434 | + "Total generated prompts on left = Total generated prompts on right" | |
| 435 | + total_wins =0 | |
| 436 | + total_votes =0 | |
| 437 | + total_generated_prompts_on_left = 0 | |
| 438 | + total_generated_prompts_on_right = 0 | |
| 439 | + total_scores_gte_fifty= 0 | |
| 440 | + total_scores_lte_fifty= 0 | |
| 441 | + error_bool = false | |
| 442 | + # votes before 2010-02-17 have null loser_choice_id therefore we | |
| 443 | + # want to ignore some tests for any question with votes before 2010-02-17 | |
| 444 | + question_has_votes_before_2010_02_17 = question.votes.count(:conditions => ["created_at < ?", '2010-02-17']) > 0 | |
| 445 | + | |
| 446 | + # reload question to make sure we have most recent data | |
| 447 | + question.reload | |
| 448 | + question.choices.each do |choice| | |
| 449 | + | |
| 450 | 450 | if choice.wins |
| 451 | 451 | total_wins += choice.wins |
| 452 | 452 | total_votes += choice.wins |
| 453 | 453 | end |
| 454 | 454 | |
| 455 | 455 | if choice.losses |
| 456 | - total_votes += choice.losses | |
| 456 | + total_votes += choice.losses | |
| 457 | 457 | end |
| 458 | 458 | |
| 459 | 459 | total_generated_prompts_on_left += choice.prompts_on_the_left.size |
| ... | ... | @@ -465,16 +465,16 @@ namespace :test_api do |
| 465 | 465 | delta = 0.001 |
| 466 | 466 | |
| 467 | 467 | if (cached_score - generated_score).abs >= delta |
| 468 | - error_message += "Error! The cached_score is not equal to the calculated score for choice #{choice.id}\n" | |
| 468 | + error_message += "Error! The cached_score is not equal to the calculated score for choice #{choice.id}\n" | |
| 469 | 469 | |
| 470 | - print "This score is wrong! #{choice.id} , Question ID: #{question.id}, #{cached_score}, #{generated_score}, updated: #{choice.updated_at}\n" | |
| 470 | + print "This score is wrong! #{choice.id} , Question ID: #{question.id}, #{cached_score}, #{generated_score}, updated: #{choice.updated_at}\n" | |
| 471 | 471 | |
| 472 | 472 | |
| 473 | 473 | end |
| 474 | 474 | |
| 475 | 475 | if cached_score == 0.0 || cached_score == 100.0 || cached_score.nil? |
| 476 | - error_message += "Error! The cached_score for choice #{choice.id} is exactly 0 or 100, the value: #{cached_score}" | |
| 477 | - print "Either 0 or 100 This score is wrong! #{choice.id} , Question ID: #{question.id}, #{cached_score}, #{generated_score}, updated: #{choice.updated_at}\n" | |
| 476 | + error_message += "Error! The cached_score for choice #{choice.id} is exactly 0 or 100, the value: #{cached_score}" | |
| 477 | + print "Either 0 or 100 This score is wrong! #{choice.id} , Question ID: #{question.id}, #{cached_score}, #{generated_score}, updated: #{choice.updated_at}\n" | |
| 478 | 478 | end |
| 479 | 479 | |
| 480 | 480 | unless question_has_votes_before_2010_02_17 |
| ... | ... | @@ -493,10 +493,10 @@ namespace :test_api do |
| 493 | 493 | end |
| 494 | 494 | |
| 495 | 495 | if (choice.wins != choice.votes.count) |
| 496 | - error_message += "Error!: Cached choice wins != actual choice wins for choice #{choice.id}\n" | |
| 497 | - error_bool= true | |
| 496 | + error_message += "Error!: Cached choice wins != actual choice wins for choice #{choice.id}\n" | |
| 497 | + error_bool= true | |
| 498 | 498 | end |
| 499 | - | |
| 499 | + | |
| 500 | 500 | # votes before 2010-02-17 have null loser_choice_id |
| 501 | 501 | # therefore we want to ignore this test for any question with votes |
| 502 | 502 | # prior to 2010-02-17 |
| ... | ... | @@ -507,156 +507,156 @@ namespace :test_api do |
| 507 | 507 | end |
| 508 | 508 | end |
| 509 | 509 | |
| 510 | - end | |
| 511 | - | |
| 512 | - | |
| 513 | - unless question_has_votes_before_2010_02_17 | |
| 514 | - if (2*total_wins != total_votes) | |
| 515 | - error_message += "Error 1: 2 x Total Wins != Total votes\n" | |
| 516 | - error_bool= true | |
| 517 | 510 | end |
| 518 | 511 | |
| 519 | - if(total_votes % 2 != 0) | |
| 520 | - error_message += "Error 2: Total votes is not Even!\n" | |
| 521 | - error_bool= true | |
| 512 | + | |
| 513 | + unless question_has_votes_before_2010_02_17 | |
| 514 | + if (2*total_wins != total_votes) | |
| 515 | + error_message += "Error 1: 2 x Total Wins != Total votes\n" | |
| 516 | + error_bool= true | |
| 517 | + end | |
| 518 | + | |
| 519 | + if(total_votes % 2 != 0) | |
| 520 | + error_message += "Error 2: Total votes is not Even!\n" | |
| 521 | + error_bool= true | |
| 522 | + end | |
| 523 | + | |
| 524 | + if(total_votes != 2* question.votes_count) | |
| 525 | + error_message += "Error 3: Total votes != 2 x # vote objects\n" | |
| 526 | + error_bool = true | |
| 527 | + end | |
| 522 | 528 | end |
| 523 | 529 | |
| 524 | - if(total_votes != 2* question.votes_count) | |
| 525 | - error_message += "Error 3: Total votes != 2 x # vote objects\n" | |
| 530 | + if(total_generated_prompts_on_right != total_generated_prompts_on_right) | |
| 531 | + error_message += "Error 4: Total generated prompts on left != Total generated prompts on right\n" | |
| 526 | 532 | error_bool = true |
| 527 | 533 | end |
| 528 | - end | |
| 529 | 534 | |
| 530 | - if(total_generated_prompts_on_right != total_generated_prompts_on_right) | |
| 531 | - error_message += "Error 4: Total generated prompts on left != Total generated prompts on right\n" | |
| 532 | - error_bool = true | |
| 533 | - end | |
| 535 | + unless question_has_votes_before_2010_02_17 | |
| 536 | + if(total_scores_lte_fifty == question.choices.size || total_scores_gte_fifty == question.choices.size) && (total_scores_lte_fifty != total_scores_gte_fifty) | |
| 537 | + error_message += "Error: The scores of all choices are either all above 50, or all below 50. This is probably wrong\n" | |
| 538 | + error_bool = true | |
| 539 | + puts "Error score fifty: #{question.id}" | |
| 540 | + end | |
| 541 | + end | |
| 534 | 542 | |
| 535 | - unless question_has_votes_before_2010_02_17 | |
| 536 | - if(total_scores_lte_fifty == question.choices.size || total_scores_gte_fifty == question.choices.size) && (total_scores_lte_fifty != total_scores_gte_fifty) | |
| 537 | - error_message += "Error: The scores of all choices are either all above 50, or all below 50. This is probably wrong\n" | |
| 538 | - error_bool = true | |
| 539 | - puts "Error score fifty: #{question.id}" | |
| 543 | + if error_bool | |
| 544 | + error_message += "Question #{question.id}: 2*wins = #{2*total_wins}, total votes = #{total_votes}, vote_count = #{question.votes_count}\n" | |
| 540 | 545 | end |
| 546 | + return error_message.blank? ? [success_message, false] : [error_message, true] | |
| 541 | 547 | end |
| 542 | - | |
| 543 | - if error_bool | |
| 544 | - error_message += "Question #{question.id}: 2*wins = #{2*total_wins}, total votes = #{total_votes}, vote_count = #{question.votes_count}\n" | |
| 545 | - end | |
| 546 | - return error_message.blank? ? [success_message, false] : [error_message, true] | |
| 547 | - end | |
| 548 | - def check_each_choice_appears_within_n_stddevs(question) | |
| 549 | - error_message ="" | |
| 550 | - success_message = "Each choice has appeared n times, where n falls within 6 stddevs of the mean number of appearances for a question " + | |
| 551 | - "(Note: this applies only to seed choices (not user submitted) and choices currently marked active)" | |
| 548 | + def check_each_choice_appears_within_n_stddevs(question) | |
| 549 | + error_message ="" | |
| 550 | + success_message = "Each choice has appeared n times, where n falls within 6 stddevs of the mean number of appearances for a question " + | |
| 551 | + "(Note: this applies only to seed choices (not user submitted) and choices currently marked active)" | |
| 552 | 552 | |
| 553 | - wins_by_choice_id = question.votes.active.count(:group => :choice_id) | |
| 554 | - losses_by_choice_id= question.votes.active.count(:conditions => "loser_choice_id IS NOT NULL", :group => :loser_choice_id) | |
| 553 | + wins_by_choice_id = question.votes.active.count(:group => :choice_id) | |
| 554 | + losses_by_choice_id= question.votes.active.count(:conditions => "loser_choice_id IS NOT NULL", :group => :loser_choice_id) | |
| 555 | 555 | |
| 556 | - #Rails returns an ordered hash, which doesn't allow for blocks to change merging logic. | |
| 557 | - #A little hack to create a normal hash | |
| 558 | - wins_hash = {} | |
| 559 | - wins_hash.merge!(wins_by_choice_id) | |
| 560 | - losses_hash = {} | |
| 561 | - losses_hash.merge!(losses_by_choice_id) | |
| 556 | + #Rails returns an ordered hash, which doesn't allow for blocks to change merging logic. | |
| 557 | + #A little hack to create a normal hash | |
| 558 | + wins_hash = {} | |
| 559 | + wins_hash.merge!(wins_by_choice_id) | |
| 560 | + losses_hash = {} | |
| 561 | + losses_hash.merge!(losses_by_choice_id) | |
| 562 | 562 | |
| 563 | 563 | |
| 564 | 564 | |
| 565 | - appearances_by_choice_id = wins_hash.merge(losses_hash) do |key, oldval, newval| oldval + newval end | |
| 565 | + appearances_by_choice_id = wins_hash.merge(losses_hash) do |key, oldval, newval| oldval + newval end | |
| 566 | 566 | |
| 567 | - sum = total_appearances = appearances_by_choice_id.values.inject(0) {|sum, x| sum +=x} | |
| 568 | - mean = average_appearances = total_appearances.to_f / appearances_by_choice_id.size.to_f | |
| 567 | + sum = total_appearances = appearances_by_choice_id.values.inject(0) {|sum, x| sum +=x} | |
| 568 | + mean = average_appearances = total_appearances.to_f / appearances_by_choice_id.size.to_f | |
| 569 | 569 | |
| 570 | - if sum > 0: | |
| 571 | - stddev = Math.sqrt( appearances_by_choice_id.values.inject(0) { |sum, e| sum + (e - mean) ** 2 } / appearances_by_choice_id.size.to_f ) | |
| 570 | + if sum > 0: | |
| 571 | + stddev = Math.sqrt( appearances_by_choice_id.values.inject(0) { |sum, e| sum + (e - mean) ** 2 } / appearances_by_choice_id.size.to_f ) | |
| 572 | 572 | |
| 573 | - appearances_by_choice_id.each do |choice_id, n_i| | |
| 574 | - if ((n_i < (mean - 6*stddev)) || (n_i > mean + 6 *stddev)) && Choice.find(choice_id).active? | |
| 575 | - error_message += "Choice #{choice_id} in Question ##{question.id} has an irregular number of appearances: #{n_i}, as compared to the mean: #{mean} and stddev #{stddev} for this question\n" | |
| 573 | + appearances_by_choice_id.each do |choice_id, n_i| | |
| 574 | + if ((n_i < (mean - 6*stddev)) || (n_i > mean + 6 *stddev)) && Choice.find(choice_id).active? | |
| 575 | + error_message += "Choice #{choice_id} in Question ##{question.id} has an irregular number of appearances: #{n_i}, as compared to the mean: #{mean} and stddev #{stddev} for this question\n" | |
| 576 | + end | |
| 577 | + end | |
| 576 | 578 | end |
| 577 | - end | |
| 578 | - end | |
| 579 | 579 | |
| 580 | - return error_message.blank? ? [success_message, false] : [error_message, true] | |
| 581 | - end | |
| 582 | - def check_each_choice_equally_likely_to_appear_left_or_right(question) | |
| 580 | + return error_message.blank? ? [success_message, false] : [error_message, true] | |
| 581 | + end | |
| 582 | + def check_each_choice_equally_likely_to_appear_left_or_right(question) | |
| 583 | 583 | error_message = "" |
| 584 | - success_message = "All choices have equal probability of appearing on left or right (within error params)" | |
| 585 | - question.choices.each do |c| | |
| 586 | - left_prompts_ids = c.prompts_on_the_left.ids_only | |
| 587 | - right_prompts_ids = c.prompts_on_the_right.ids_only | |
| 584 | + success_message = "All choices have equal probability of appearing on left or right (within error params)" | |
| 585 | + question.choices.each do |c| | |
| 586 | + left_prompts_ids = c.prompts_on_the_left.ids_only | |
| 587 | + right_prompts_ids = c.prompts_on_the_right.ids_only | |
| 588 | 588 | |
| 589 | - left_appearances = question.appearances.count(:conditions => {:prompt_id => left_prompts_ids}) | |
| 590 | - right_appearances = question.appearances.count(:conditions => {:prompt_id => right_prompts_ids}) | |
| 589 | + left_appearances = question.appearances.count(:conditions => {:prompt_id => left_prompts_ids}) | |
| 590 | + right_appearances = question.appearances.count(:conditions => {:prompt_id => right_prompts_ids}) | |
| 591 | 591 | |
| 592 | - n = left_appearances + right_appearances | |
| 592 | + n = left_appearances + right_appearances | |
| 593 | 593 | |
| 594 | - if n == 0 | |
| 594 | + if n == 0 | |
| 595 | 595 | next |
| 596 | - end | |
| 597 | - est_p = right_appearances.to_f / n.to_f | |
| 598 | - z = (est_p - 0.5).abs / Math.sqrt((0.5 * 0.5) / n.to_f) | |
| 596 | + end | |
| 597 | + est_p = right_appearances.to_f / n.to_f | |
| 598 | + z = (est_p - 0.5).abs / Math.sqrt((0.5 * 0.5) / n.to_f) | |
| 599 | 599 | |
| 600 | - if z > 6 | |
| 601 | - error_message += "Error: Choice ID #{c.id} seems to favor one side: Left Appearances #{left_appearances}, Right Appearances: #{right_appearances}, z = #{z}\n" | |
| 602 | - end | |
| 600 | + if z > 6 | |
| 601 | + error_message += "Error: Choice ID #{c.id} seems to favor one side: Left Appearances #{left_appearances}, Right Appearances: #{right_appearances}, z = #{z}\n" | |
| 602 | + end | |
| 603 | + end | |
| 604 | + return error_message.blank? ? [success_message, false] : [error_message, true] | |
| 603 | 605 | end |
| 604 | - return error_message.blank? ? [success_message, false] : [error_message, true] | |
| 605 | - end | |
| 606 | - def check_prompt_cache_hit_rate(question) | |
| 607 | - error_message = "" | |
| 608 | - success_message = "At least 90% of prompts on catchup algorithm questions were served from cache\n" | |
| 606 | + def check_prompt_cache_hit_rate(question) | |
| 607 | + error_message = "" | |
| 608 | + success_message = "At least 90% of prompts on catchup algorithm questions were served from cache\n" | |
| 609 | 609 | |
| 610 | - misses = question.get_prompt_cache_misses(Date.yesterday).to_i | |
| 611 | - hits = question.get_prompt_cache_hits(Date.yesterday).to_i | |
| 610 | + misses = question.get_prompt_cache_misses(Date.yesterday).to_i | |
| 611 | + hits = question.get_prompt_cache_hits(Date.yesterday).to_i | |
| 612 | 612 | |
| 613 | - question.expire_prompt_cache_tracking_keys(Date.yesterday) | |
| 614 | - | |
| 615 | - yesterday_appearances = question.appearances.count(:conditions => ['date(created_at) = ?', Date.yesterday]) | |
| 613 | + question.expire_prompt_cache_tracking_keys(Date.yesterday) | |
| 616 | 614 | |
| 617 | - if misses + hits != yesterday_appearances | |
| 618 | - error_message += "Error! Question #{question.id} isn't tracking prompt cache hits and misses accurately! Expected #{yesterday_appearances}, Actual: #{misses+hits}, Hits: #{hits}, Misses: #{misses}\n" | |
| 619 | - end | |
| 620 | - | |
| 621 | - if yesterday_appearances > 5 # this test isn't worthwhile for small numbers of appearances | |
| 622 | - miss_rate = misses.to_f / yesterday_appearances.to_f | |
| 623 | - if miss_rate > 0.1 | |
| 624 | - error_message += "Warning! Question #{question.id} has less than 90% of appearances taken from a pre-generated cache! Expected <#{0.1}, Actual: #{miss_rate}, total appearances yesterday: #{yesterday_appearances}\n" | |
| 615 | + yesterday_appearances = question.appearances.count(:conditions => ['date(created_at) = ?', Date.yesterday]) | |
| 616 | + | |
| 617 | + if misses + hits != yesterday_appearances | |
| 618 | + error_message += "Error! Question #{question.id} isn't tracking prompt cache hits and misses accurately! Expected #{yesterday_appearances}, Actual: #{misses+hits}, Hits: #{hits}, Misses: #{misses}\n" | |
| 625 | 619 | end |
| 626 | - end | |
| 627 | - return error_message.blank? ? [success_message, false] : [error_message, true] | |
| 628 | - end | |
| 629 | - | |
| 630 | - def check_object_counter_cache_values_match_actual_values(question) | |
| 631 | - error_message = "" | |
| 632 | - success_message = "All cached object values match actual values within database" | |
| 633 | - # Checks that counter_cache is working as expected | |
| 634 | - cached_prompts_size = question.prompts.size | |
| 635 | - actual_prompts_size = question.prompts.count | |
| 636 | - | |
| 637 | - if cached_prompts_size != actual_prompts_size | |
| 638 | - error_message += "Error! Question #{question.id} has an inconsistent # of prompts! cached#: #{cached_prompts_size}, actual#: #{actual_prompts_size}\n" | |
| 639 | - end | |
| 640 | - | |
| 641 | - cached_votes_size = question.votes.size | |
| 642 | - actual_votes_size = question.votes.count | |
| 643 | 620 | |
| 644 | - if cached_votes_size != actual_votes_size | |
| 645 | - error_message += "Error! Question #{question.id} has an inconsistent # of votes! cached#: #{cached_votes_size}, actual#: #{actual_votes_size}\n" | |
| 621 | + if yesterday_appearances > 5 # this test isn't worthwhile for small numbers of appearances | |
| 622 | + miss_rate = misses.to_f / yesterday_appearances.to_f | |
| 623 | + if miss_rate > 0.1 | |
| 624 | + error_message += "Warning! Question #{question.id} has less than 90% of appearances taken from a pre-generated cache! Expected <#{0.1}, Actual: #{miss_rate}, total appearances yesterday: #{yesterday_appearances}\n" | |
| 625 | + end | |
| 626 | + end | |
| 627 | + return error_message.blank? ? [success_message, false] : [error_message, true] | |
| 646 | 628 | end |
| 647 | - | |
| 648 | - cached_choices_size = question.choices.size | |
| 649 | - actual_choices_size = question.choices.count | |
| 650 | 629 | |
| 651 | - if cached_choices_size != actual_choices_size | |
| 652 | - error_message+= "Error! Question #{question.id} has an inconsistent # of choices! cached#: #{cached_choices_size}, actual#: #{actual_choices_size}\n" | |
| 653 | - end | |
| 630 | + def check_object_counter_cache_values_match_actual_values(question) | |
| 631 | + error_message = "" | |
| 632 | + success_message = "All cached object values match actual values within database" | |
| 633 | + # Checks that counter_cache is working as expected | |
| 634 | + cached_prompts_size = question.prompts.size | |
| 635 | + actual_prompts_size = question.prompts.count | |
| 654 | 636 | |
| 655 | - #if cached_prompts_size != question.choices.size **2 - question.choices.size | |
| 656 | - # error_message += "Error! Question #{question.id} has an incorrect number of prompts! Expected #{question.choices.size **2 - question.choices.size}, Actual: #{cached_prompts_size}\n" | |
| 657 | - #end | |
| 658 | - return error_message.blank? ? [success_message, false] : [error_message, true] | |
| 659 | - end | |
| 637 | + if cached_prompts_size != actual_prompts_size | |
| 638 | + error_message += "Error! Question #{question.id} has an inconsistent # of prompts! cached#: #{cached_prompts_size}, actual#: #{actual_prompts_size}\n" | |
| 639 | + end | |
| 640 | + | |
| 641 | + cached_votes_size = question.votes.size | |
| 642 | + actual_votes_size = question.votes.count | |
| 643 | + | |
| 644 | + if cached_votes_size != actual_votes_size | |
| 645 | + error_message += "Error! Question #{question.id} has an inconsistent # of votes! cached#: #{cached_votes_size}, actual#: #{actual_votes_size}\n" | |
| 646 | + end | |
| 647 | + | |
| 648 | + cached_choices_size = question.choices.size | |
| 649 | + actual_choices_size = question.choices.count | |
| 650 | + | |
| 651 | + if cached_choices_size != actual_choices_size | |
| 652 | + error_message+= "Error! Question #{question.id} has an inconsistent # of choices! cached#: #{cached_choices_size}, actual#: #{actual_choices_size}\n" | |
| 653 | + end | |
| 654 | + | |
| 655 | + #if cached_prompts_size != question.choices.size **2 - question.choices.size | |
| 656 | + # error_message += "Error! Question #{question.id} has an incorrect number of prompts! Expected #{question.choices.size **2 - question.choices.size}, Actual: #{cached_prompts_size}\n" | |
| 657 | + #end | |
| 658 | + return error_message.blank? ? [success_message, false] : [error_message, true] | |
| 659 | + end | |
| 660 | 660 | |
| 661 | 661 | desc "Ensure that a question has: answered_appearances == votes + skips" |
| 662 | 662 | task :answered_appearances_equals_votes_and_skips => :environment do |
| ... | ... | @@ -673,63 +673,63 @@ namespace :test_api do |
| 673 | 673 | if (total_answered_appearances != total_votes + total_skips) |
| 674 | 674 | error_message += "Question #{question.id}: answered_appearances = #{total_answered_appearances}, votes = #{total_votes}, skips = #{total_skips}" |
| 675 | 675 | end |
| 676 | - | |
| 676 | + | |
| 677 | 677 | |
| 678 | 678 | return error_message.blank? ? [success_message, false] : [error_message, true] |
| 679 | 679 | end |
| 680 | - | |
| 681 | - def ensure_all_votes_and_skips_have_unique_appearance | |
| 682 | - error_message = "" | |
| 683 | - success_message = "All vote and skip objects have an associated appearance object" | |
| 684 | 680 | |
| 685 | - total_answered_appearances = Appearance.count(:conditions => 'answerable_id IS NOT NULL') | |
| 686 | - total_votes = Vote.count | |
| 687 | - total_skips = Skip.count | |
| 681 | + def ensure_all_votes_and_skips_have_unique_appearance | |
| 682 | + error_message = "" | |
| 683 | + success_message = "All vote and skip objects have an associated appearance object" | |
| 688 | 684 | |
| 689 | - if (total_answered_appearances != total_votes+ total_skips) | |
| 690 | - difference = (total_votes+ total_skips) - total_answered_appearances | |
| 691 | - error_message += "Error! There are #{difference} votes or skips without associated appearance objects." | |
| 692 | - end | |
| 685 | + total_answered_appearances = Appearance.count(:conditions => 'answerable_id IS NOT NULL') | |
| 686 | + total_votes = Vote.count | |
| 687 | + total_skips = Skip.count | |
| 693 | 688 | |
| 694 | - return error_message.blank? ? [success_message, false] : [error_message, true] | |
| 695 | - end | |
| 689 | + if (total_answered_appearances != total_votes+ total_skips) | |
| 690 | + difference = (total_votes+ total_skips) - total_answered_appearances | |
| 691 | + error_message += "Error! There are #{difference} votes or skips without associated appearance objects." | |
| 692 | + end | |
| 696 | 693 | |
| 697 | - def response_time_tests | |
| 698 | - error_message = "" | |
| 699 | - success_message = "All Vote objects have an client response time < calculated server roundtrip time\n" | |
| 694 | + return error_message.blank? ? [success_message, false] : [error_message, true] | |
| 695 | + end | |
| 700 | 696 | |
| 701 | - recording_client_time_start_date = Vote.find(:all, :conditions => 'time_viewed IS NOT NULL', :order => 'created_at', :limit => 1).first.created_at | |
| 697 | + def response_time_tests | |
| 698 | + error_message = "" | |
| 699 | + success_message = "All Vote objects have an client response time < calculated server roundtrip time\n" | |
| 700 | + | |
| 701 | + recording_client_time_start_date = Vote.find(:all, :conditions => 'time_viewed IS NOT NULL', :order => 'created_at', :limit => 1).first.created_at | |
| 702 | 702 | |
| 703 | - Vote.find_each(:batch_size => 1000, :include => :appearance) do |v| | |
| 703 | + Vote.find_each(:batch_size => 1000, :include => :appearance) do |v| | |
| 704 | 704 | |
| 705 | 705 | next if v.nil? || v.appearance.nil? |
| 706 | - # Subtracting DateTime objects results in the difference in days | |
| 707 | - server_response_time = v.created_at.to_f - v.appearance.created_at.to_f | |
| 708 | - if server_response_time < 0 | |
| 709 | - the_error_msg = "Error! Vote #{v.id} was created before the appearance associated with it: Appearance id: #{v.appearance.id}, Vote creation time: #{v.created_at.to_s}, Appearance creation time: #{v.appearance.created_at.to_s}\n" | |
| 710 | - | |
| 711 | - error_message += the_error_msg | |
| 712 | - print "Error!" + the_error_msg | |
| 713 | - end | |
| 714 | - | |
| 715 | - if v.time_viewed && v.time_viewed/1000 > server_response_time | |
| 716 | - the_error_msg = "Warning! Vote #{v.id} with Appearance #{v.appearance.id}, has a longer client response time than is possible. Server roundtrip time is: #{v.created_at.to_f - v.appearance.created_at.to_f} seconds, but client side response time is: #{v.time_viewed.to_f / 1000.0} seconds\n" | |
| 717 | - | |
| 718 | - error_message += the_error_msg | |
| 719 | - print the_error_msg | |
| 720 | - | |
| 721 | - elsif v.time_viewed.nil? | |
| 722 | - if v.created_at > recording_client_time_start_date && v.missing_response_time_exp != 'invalid' | |
| 723 | - the_error_msg = "Error! Vote #{v.id} with Appearance #{v.appearance.id}, does not have a client response, even though it should! Vote creation time: #{v.created_at.to_s}, Appearance creation time: #{v.appearance.created_at.to_s}, Client side response time: #{v.time_viewed}\n" | |
| 724 | - error_message += the_error_msg | |
| 725 | - print the_error_msg | |
| 726 | - end | |
| 727 | - | |
| 728 | - end | |
| 729 | - | |
| 730 | - end | |
| 731 | - | |
| 732 | - return error_message.blank? ? [success_message, false] : [error_message, true] | |
| 733 | - end | |
| 706 | + # Subtracting DateTime objects results in the difference in days | |
| 707 | + server_response_time = v.created_at.to_f - v.appearance.created_at.to_f | |
| 708 | + if server_response_time < 0 | |
| 709 | + the_error_msg = "Error! Vote #{v.id} was created before the appearance associated with it: Appearance id: #{v.appearance.id}, Vote creation time: #{v.created_at.to_s}, Appearance creation time: #{v.appearance.created_at.to_s}\n" | |
| 710 | + | |
| 711 | + error_message += the_error_msg | |
| 712 | + print "Error!" + the_error_msg | |
| 713 | + end | |
| 714 | + | |
| 715 | + if v.time_viewed && v.time_viewed/1000 > server_response_time | |
| 716 | + the_error_msg = "Warning! Vote #{v.id} with Appearance #{v.appearance.id}, has a longer client response time than is possible. Server roundtrip time is: #{v.created_at.to_f - v.appearance.created_at.to_f} seconds, but client side response time is: #{v.time_viewed.to_f / 1000.0} seconds\n" | |
| 717 | + | |
| 718 | + error_message += the_error_msg | |
| 719 | + print the_error_msg | |
| 720 | + | |
| 721 | + elsif v.time_viewed.nil? | |
| 722 | + if v.created_at > recording_client_time_start_date && v.missing_response_time_exp != 'invalid' | |
| 723 | + the_error_msg = "Error! Vote #{v.id} with Appearance #{v.appearance.id}, does not have a client response, even though it should! Vote creation time: #{v.created_at.to_s}, Appearance creation time: #{v.appearance.created_at.to_s}, Client side response time: #{v.time_viewed}\n" | |
| 724 | + error_message += the_error_msg | |
| 725 | + print the_error_msg | |
| 726 | + end | |
| 727 | + | |
| 728 | + end | |
| 729 | + | |
| 730 | + end | |
| 731 | + | |
| 732 | + return error_message.blank? ? [success_message, false] : [error_message, true] | |
| 733 | + end | |
| 734 | 734 | end |
| 735 | 735 | ... | ... |