Commit fd5da22491e6b145ad7b45649becd39fc995dd50

Authored by Luke Baker
1 parent beb3b15f

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  
... ...