Commit 8716cedc034f94a2771478b1e49a3c269af636d6

Authored by Luke Baker
1 parent 3bd8a171

update spacing in test_api.rake

Showing 1 changed file with 447 additions and 445 deletions   Show diff stats
lib/tasks/test_api.rake
... ... @@ -5,120 +5,120 @@ namespace :test_api do
5 5 desc "Don't run unless you know what you are doing"
6 6 task(:generate_lots_of_votes => :environment) do
7 7 if Rails.env.production?
8   - print "You probably don't want to run this in production as it will falsify a bunch of random votes"
  8 + print "You probably don't want to run this in production as it will falsify a bunch of random votes"
9 9 end
10 10  
11 11  
12 12 current_user = User.first
13 13 1000.times do |n|
14   - puts "#{n} votes completed" if n % 100 == 0
  14 + puts "#{n} votes completed" if n % 100 == 0
15 15 question = Question.find(214) # test question change as needed
16   - @prompt = question.catchup_choose_prompt
  16 + @prompt = question.catchup_choose_prompt
17 17 @appearance = current_user.record_appearance(current_user.default_visitor, @prompt)
18 18  
19   - direction = (rand(2) == 0) ? "left" : "right"
20   - current_user.record_vote(:prompt => @prompt, :direction => direction, :appearance_lookup => @appearance.lookup)
  19 + direction = (rand(2) == 0) ? "left" : "right"
  20 + current_user.record_vote(:prompt => @prompt, :direction => direction, :appearance_lookup => @appearance.lookup)
21 21 end
22 22  
23 23 end
24 24  
25 25 desc "Generate appearances for any votes that have no current appearance, should only need to be run once"
26 26 task(:generate_appearances_for_existing_votes => :environment) do
27   - votes = Vote.all
  27 + votes = Vote.all
28 28  
29   - count = 0
30   - votes.each do |v|
31   - if v.appearance.nil?
32   - print "."
33   - 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)
34   - v.appearance = a
35   - v.save
  29 + count = 0
  30 + votes.each do |v|
  31 + if v.appearance.nil?
  32 + print "."
  33 + 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)
  34 + v.appearance = a
  35 + v.save
36 36  
37   - count += 1
38   - end
39   - end
  37 + count += 1
  38 + end
  39 + end
40 40  
41   - print count
  41 + print count
42 42 end
43 43  
44 44  
45 45 desc "Generate past density information"
46 46 task(:generate_past_densities => :environment) do
47   - #this is not elegant, but should only be run once, so quick and dirty wins
48   -
49   - start_date = Vote.find(:all, :conditions => 'loser_choice_id IS NOT NULL', :order => :created_at, :limit => 1).first.created_at.to_date
50   - start_date.upto(Date.today) do |the_date|
51   - questions = Question.find(:all, :conditions => ['created_at < ?', the_date])
52   -
53   - print the_date.to_s
54   - questions.each do |q|
55   - puts q.id
56   - relevant_choices = q.choices.find(:all, :conditions => ['created_at < ?', the_date])
57   -
58   - seed_choices = 0
59   -
60   - if relevant_choices == 0
61   - next
62   - #this question had not been created yet
63   - end
64   -
65   - relevant_choices.each do |c|
66   - if !c.user_created
67   - seed_choices+=1
68   - end
69   -
70   - end
71   -
72   - nonseed_choices = relevant_choices.size - seed_choices
73   -
74   - seed_seed_total = seed_choices **2 - seed_choices
75   - nonseed_nonseed_total = nonseed_choices **2 - nonseed_choices
76   - seed_nonseed_total = seed_choices * nonseed_choices
77   - nonseed_seed_total = seed_choices * nonseed_choices
78   -
79   - seed_seed_sum = 0
80   - seed_nonseed_sum= 0
81   - nonseed_seed_sum= 0
82   - nonseed_nonseed_sum= 0
83   -
84   - q.appearances.find_each(:conditions => ['prompt_id IS NOT NULL AND created_at < ?', the_date]) do |a|
85   -
86   - p = a.prompt
87   - if p.left_choice.user_created == false && p.right_choice.user_created == false
88   - seed_seed_sum += 1
89   - elsif p.left_choice.user_created == false && p.right_choice.user_created == true
90   - seed_nonseed_sum += 1
91   - elsif p.left_choice.user_created == true && p.right_choice.user_created == false
92   - nonseed_seed_sum += 1
93   - elsif p.left_choice.user_created == true && p.right_choice.user_created == true
94   - nonseed_nonseed_sum += 1
95   - end
96   - end
97   -
98   - densities = {}
99   - densities[:seed_seed] = seed_seed_sum.to_f / seed_seed_total.to_f
100   - densities[:seed_nonseed] = seed_nonseed_sum.to_f / seed_nonseed_total.to_f
101   - densities[:nonseed_seed] = nonseed_seed_sum.to_f / nonseed_seed_total.to_f
102   - densities[:nonseed_nonseed] = nonseed_nonseed_sum.to_f / nonseed_nonseed_total.to_f
103   -
104   - densities.each do |type, average|
105   - d = Density.new
106   - d.created_at = the_date
107   - d.question_id = q.id
108   - d.prompt_type = type.to_s
109   - d.value = average.nan? ? nil : average
110   - d.save!
111   - end
112   -
113   - puts "Seed_seed sum: #{seed_seed_sum}, seed_seed total num: #{seed_seed_total}"
114   - puts "Seed_nonseed sum: #{seed_nonseed_sum}, seed_nonseed total num: #{seed_nonseed_total}"
115   - puts "Nonseed_seed sum: #{nonseed_seed_sum}, nonseed_seed total num: #{nonseed_seed_total}"
116   - puts "Nonseed_nonseed sum: #{nonseed_nonseed_sum}, nonseed_nonseed total num: #{nonseed_nonseed_total}"
117   -
118   -
119   - end
120   -
121   - end
  47 + #this is not elegant, but should only be run once, so quick and dirty wins
  48 +
  49 + start_date = Vote.find(:all, :conditions => 'loser_choice_id IS NOT NULL', :order => :created_at, :limit => 1).first.created_at.to_date
  50 + start_date.upto(Date.today) do |the_date|
  51 + questions = Question.find(:all, :conditions => ['created_at < ?', the_date])
  52 +
  53 + print the_date.to_s
  54 + questions.each do |q|
  55 + puts q.id
  56 + relevant_choices = q.choices.find(:all, :conditions => ['created_at < ?', the_date])
  57 +
  58 + seed_choices = 0
  59 +
  60 + if relevant_choices == 0
  61 + next
  62 + #this question had not been created yet
  63 + end
  64 +
  65 + relevant_choices.each do |c|
  66 + if !c.user_created
  67 + seed_choices+=1
  68 + end
  69 +
  70 + end
  71 +
  72 + nonseed_choices = relevant_choices.size - seed_choices
  73 +
  74 + seed_seed_total = seed_choices **2 - seed_choices
  75 + nonseed_nonseed_total = nonseed_choices **2 - nonseed_choices
  76 + seed_nonseed_total = seed_choices * nonseed_choices
  77 + nonseed_seed_total = seed_choices * nonseed_choices
  78 +
  79 + seed_seed_sum = 0
  80 + seed_nonseed_sum= 0
  81 + nonseed_seed_sum= 0
  82 + nonseed_nonseed_sum= 0
  83 +
  84 + q.appearances.find_each(:conditions => ['prompt_id IS NOT NULL AND created_at < ?', the_date]) do |a|
  85 +
  86 + p = a.prompt
  87 + if p.left_choice.user_created == false && p.right_choice.user_created == false
  88 + seed_seed_sum += 1
  89 + elsif p.left_choice.user_created == false && p.right_choice.user_created == true
  90 + seed_nonseed_sum += 1
  91 + elsif p.left_choice.user_created == true && p.right_choice.user_created == false
  92 + nonseed_seed_sum += 1
  93 + elsif p.left_choice.user_created == true && p.right_choice.user_created == true
  94 + nonseed_nonseed_sum += 1
  95 + end
  96 + end
  97 +
  98 + densities = {}
  99 + densities[:seed_seed] = seed_seed_sum.to_f / seed_seed_total.to_f
  100 + densities[:seed_nonseed] = seed_nonseed_sum.to_f / seed_nonseed_total.to_f
  101 + densities[:nonseed_seed] = nonseed_seed_sum.to_f / nonseed_seed_total.to_f
  102 + densities[:nonseed_nonseed] = nonseed_nonseed_sum.to_f / nonseed_nonseed_total.to_f
  103 +
  104 + densities.each do |type, average|
  105 + d = Density.new
  106 + d.created_at = the_date
  107 + d.question_id = q.id
  108 + d.prompt_type = type.to_s
  109 + d.value = average.nan? ? nil : average
  110 + d.save!
  111 + end
  112 +
  113 + puts "Seed_seed sum: #{seed_seed_sum}, seed_seed total num: #{seed_seed_total}"
  114 + puts "Seed_nonseed sum: #{seed_nonseed_sum}, seed_nonseed total num: #{seed_nonseed_total}"
  115 + puts "Nonseed_seed sum: #{nonseed_seed_sum}, nonseed_seed total num: #{nonseed_seed_total}"
  116 + puts "Nonseed_nonseed sum: #{nonseed_nonseed_sum}, nonseed_nonseed total num: #{nonseed_nonseed_total}"
  117 +
  118 +
  119 + end
  120 +
  121 + end
122 122  
123 123 end
124 124  
... ... @@ -126,53 +126,53 @@ namespace :test_api do
126 126 desc "Should only need to be run once"
127 127 task(:generate_all_possible_prompts => :environment) do
128 128 Question.find(:all).each do |q|
129   - choices = q.choices
130   - if q.prompts.size > choices.size**2 - choices.size
131   - print "ERROR: #{q.id}\n"
132   - next
133   - elsif q.prompts.size == choices.size**2 - choices.size
134   - print "#{q.id} has enough prompts, skipping...\n"
135   - next
136   - else
137   - print "#{q.id} should add #{(choices.size ** 2 - choices.size) - q.prompts.size}\n"
138   -
139   - end
  129 + choices = q.choices
  130 + if q.prompts.size > choices.size**2 - choices.size
  131 + print "ERROR: #{q.id}\n"
  132 + next
  133 + elsif q.prompts.size == choices.size**2 - choices.size
  134 + print "#{q.id} has enough prompts, skipping...\n"
  135 + next
  136 + else
  137 + print "#{q.id} should add #{(choices.size ** 2 - choices.size) - q.prompts.size}\n"
  138 +
  139 + end
140 140 created_timestring = q.created_at.to_s(:db)
141   - updated_timestring = Time.now.to_s(:db) #isn't rails awesome?
142   - promptscount=0
  141 + updated_timestring = Time.now.to_s(:db) #isn't rails awesome?
  142 + promptscount=0
143 143 inserts = []
144   - the_prompts = Prompt.find(:all, :select => 'id, left_choice_id, right_choice_id', :conditions => {:question_id => q.id})
  144 + the_prompts = Prompt.find(:all, :select => 'id, left_choice_id, right_choice_id', :conditions => {:question_id => q.id})
145 145  
146   - the_prompts_hash = {}
147   - the_prompts.each do |p|
148   - the_prompts_hash["#{p.left_choice_id},#{p.right_choice_id}"] = 1
149   - end
  146 + the_prompts_hash = {}
  147 + the_prompts.each do |p|
  148 + the_prompts_hash["#{p.left_choice_id},#{p.right_choice_id}"] = 1
  149 + end
150 150  
151 151 choices.each do |l|
152   - choices.each do |r|
153   - if l.id == r.id
154   - next
155   - else
156   - #p = the_prompts.find{|o| o.left_choice_id == l.id && o.right_choice_id == r.id}
157   - keystring = "#{l.id},#{r.id}"
158   - p = the_prompts_hash[keystring]
159   - if p.nil?
160   - inserts.push("(NULL, #{q.id}, NULL, #{l.id}, '#{created_timestring}', '#{updated_timestring}', NULL, 0, #{r.id}, NULL, NULL)")
161   - promptscount+=1
162   - end
163   -
164   - end
165   -
166   - end
  152 + choices.each do |r|
  153 + if l.id == r.id
  154 + next
  155 + else
  156 + #p = the_prompts.find{|o| o.left_choice_id == l.id && o.right_choice_id == r.id}
  157 + keystring = "#{l.id},#{r.id}"
  158 + p = the_prompts_hash[keystring]
  159 + if p.nil?
  160 + inserts.push("(NULL, #{q.id}, NULL, #{l.id}, '#{created_timestring}', '#{updated_timestring}', NULL, 0, #{r.id}, NULL, NULL)")
  161 + promptscount+=1
  162 + end
  163 +
  164 + end
  165 +
  166 + end
167 167 end
168 168  
169   - print "Added #{promptscount} to #{q.id}\n"
170   - 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(', ')}"
171   - unless inserts.empty?
172   - ActiveRecord::Base.connection.execute(sql)
173   - end
  169 + print "Added #{promptscount} to #{q.id}\n"
  170 + 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(', ')}"
  171 + unless inserts.empty?
  172 + ActiveRecord::Base.connection.execute(sql)
  173 + end
174 174  
175   - Question.update_counters(q.id, :prompts_count => promptscount)
  175 + Question.update_counters(q.id, :prompts_count => promptscount)
176 176  
177 177  
178 178 end
... ... @@ -185,337 +185,339 @@ namespace :test_api do
185 185 desc "Dump votes of a question by left vs right id"
186 186 task(:make_csv => :environment) do
187 187  
188   - q = Question.find(214)
189   -
190   -
191   - the_prompts = q.prompts_hash_by_choice_ids
192   -
193   - #hash_of_choice_ids_from_left_to_right_to_votes
194   - the_hash = {}
195   - q.choices.each do |l|
196   - q.choices.each do |r|
197   - next if l.id == r.id
198   -
199   - if not the_hash.has_key?(l.id)
200   - the_hash[l.id] = {}
201   - the_hash[l.id][l.id] = 0
202   - end
203   -
204   - p = the_prompts["#{l.id}, #{r.id}"]
205   - if p.nil?
206   - the_hash[l.id][r.id] = 0
207   - else
208   - the_hash[l.id][r.id] = p.appearances.size
209   - end
210   - end
211   - end
212   -
213   - the_hash.sort.each do |xval, row|
214   - rowarray = []
215   - row.sort.each do |yval, cell|
216   - rowarray << cell
217   - end
218   - puts rowarray.join(", ")
219   - end
  188 + q = Question.find(214)
  189 +
  190 +
  191 + the_prompts = q.prompts_hash_by_choice_ids
  192 +
  193 + #hash_of_choice_ids_from_left_to_right_to_votes
  194 + the_hash = {}
  195 + q.choices.each do |l|
  196 + q.choices.each do |r|
  197 + next if l.id == r.id
  198 +
  199 + if not the_hash.has_key?(l.id)
  200 + the_hash[l.id] = {}
  201 + the_hash[l.id][l.id] = 0
  202 + end
  203 +
  204 + p = the_prompts["#{l.id}, #{r.id}"]
  205 + if p.nil?
  206 + the_hash[l.id][r.id] = 0
  207 + else
  208 + the_hash[l.id][r.id] = p.appearances.size
  209 + end
  210 + end
  211 + end
  212 +
  213 + the_hash.sort.each do |xval, row|
  214 + rowarray = []
  215 + row.sort.each do |yval, cell|
  216 + rowarray << cell
  217 + end
  218 + puts rowarray.join(", ")
  219 + end
220 220 end
221 221  
222 222  
223 223 desc "Generate density information for each question - should be run nightly"
224 224 task(:generate_density_information => :environment) do
225 225  
226   - # calculating densities is expensive, so only do it for questions with new data
227   - question_ids = Vote.count(:conditions => ['date(created_at) = ?', Date.yesterday], :group => 'question_id').keys()
  226 + # calculating densities is expensive, so only do it for questions with new data
  227 + question_ids = Vote.count(:conditions => ['date(created_at) = ?', Date.yesterday], :group => 'question_id').keys()
228 228  
229   - Question.find(:all, :conditions => {:id => question_ids}).each do |q|
230   - q.save_densities!
231   - end
  229 + Question.find(:all, :conditions => {:id => question_ids}).each do |q|
  230 + q.save_densities!
  231 + end
232 232  
233   - # we can just copy the previous night's data for remaining questions
234   -
235   - Question.find(:all, :conditions => ['id NOT IN (?)', question_ids]).each do |q|
236   - densities = q.densities.find(:all, :conditions => ['date(created_at) = ?', Date.yesterday])
  233 + # we can just copy the previous night's data for remaining questions
  234 +
  235 + Question.find(:all, :conditions => ['id NOT IN (?)', question_ids]).each do |q|
  236 + densities = q.densities.find(:all, :conditions => ['date(created_at) = ?', Date.yesterday])
237 237  
238 238  
239   - densities.each do |d|
240   - new_d = d.clone
241   - new_d.created_at = new_d.updated_at = Time.now
242   - new_d.save!
243   - end
  239 + densities.each do |d|
  240 + new_d = d.clone
  241 + new_d.created_at = new_d.updated_at = Time.now
  242 + new_d.save!
  243 + end
244 244  
245   - if densities.blank?
246   - #fallback in case there wasn't a successful run yesterday
247   - q.save_densities!
248   -
249   - end
  245 + if densities.blank?
  246 + #fallback in case there wasn't a successful run yesterday
  247 + q.save_densities!
  248 +
  249 + end
250 250  
251   - end
  251 + end
252 252 end
253 253  
254   - desc "Description here"
255   - task(:question_vote_consistency => :environment) do
256   - questions = Question.find(:all)
257   - errors = []
258   - successes = []
259   -
260   - questions.each do |question|
  254 + desc "Description here"
  255 + task(:question_vote_consistency => :environment) do
  256 + questions = Question.find(:all)
  257 + errors = []
  258 + successes = []
  259 +
  260 + questions.each do |question|
  261 +
  262 + message, error_occurred = check_basic_balanced_stats(question)
  263 + # hack for now, get around to doing this with block/yield to
  264 + # get rid of duplication
  265 + if error_occurred
  266 + errors << message
  267 + else
  268 + successes << message
  269 + end
261 270  
262   - message, error_occurred = check_basic_balanced_stats(question)
263   - #hack for now, get around to doing this with block /yield to get rid of duplication
264   - if error_occurred
265   - errors << message
266   - else
267   - successes << message
268   - end
269 271  
  272 + message, error_occurred = check_each_choice_appears_within_n_stddevs(question)
  273 + if error_occurred
  274 + errors << message
  275 + else
  276 + successes << message
  277 + end
270 278  
271   - message, error_occurred = check_each_choice_appears_within_n_stddevs(question)
272   - if error_occurred
273   - errors << message
274   - else
275   - successes << message
276   - end
277   -
278   - message, error_occurred = check_each_choice_equally_likely_to_appear_left_or_right(question)
279   - if error_occurred
280   - errors << message
281   - else
282   - successes << message
283   - end
284   -
285   -
286   -
287   - message, error_occurred = check_object_counter_cache_values_match_actual_values(question)
288   - if error_occurred
289   - errors << message
290   - else
291   - successes << message
292   - end
  279 + message, error_occurred = check_each_choice_equally_likely_to_appear_left_or_right(question)
  280 + if error_occurred
  281 + errors << message
  282 + else
  283 + successes << message
  284 + end
293 285  
294 286  
295   - #catchup specific
296   - if question.uses_catchup?
297   - message, error_occurred = check_prompt_cache_hit_rate(question)
298   - if error_occurred
299   - errors << message
300   - else
301   - successes << message
302   - end
303   - end
304   - end
305 287  
306   - message, error_occurred = ensure_all_votes_and_skips_have_unique_appearance
307   -
308   - if error_occurred
309   - errors << message
310   - else
311   - successes << message
312   - end
  288 + message, error_occurred = check_object_counter_cache_values_match_actual_values(question)
  289 + if error_occurred
  290 + errors << message
  291 + else
  292 + successes << message
  293 + end
313 294  
314   - message, error_occurred = response_time_tests
315 295  
316   - if error_occurred
317   - errors << message
318   - else
319   - successes << message
320   - end
  296 + #catchup specific
  297 + if question.uses_catchup?
  298 + message, error_occurred = check_prompt_cache_hit_rate(question)
  299 + if error_occurred
  300 + errors << message
  301 + else
  302 + successes << message
  303 + end
  304 + end
321 305  
322   - email_text = "Conducted the following tests on API data and found the following results\n" +
323   - "For each of the #{questions.length} questions in the database: \n"
324   - errors.each do |e|
325   - email_text += " Test FAILED: " + e + "\n"
326   - end
  306 + end
327 307  
328   - successes.uniq.each do |s|
329   - s.split("\n").each do |m| # some successes have several lines
330   - email_text += " Test Passed: " + m + "\n"
331   - end
332   - end
333   -
334   - puts email_text
  308 + message, error_occurred = ensure_all_votes_and_skips_have_unique_appearance
335 309  
336   - if errors.empty?
337   - CronMailer.deliver_info_message(CRON_EMAIL, "Test of API Vote Consistency passed", email_text)
338   - else
339   - CronMailer.deliver_info_message(CRON_EMAIL.to_a + ERRORS_EMAIL.to_a, "Error! Failure of API Vote Consistency " , email_text)
340   - end
  310 + if error_occurred
  311 + errors << message
  312 + else
  313 + successes << message
  314 + end
  315 +
  316 + message, error_occurred = response_time_tests
  317 +
  318 + if error_occurred
  319 + errors << message
  320 + else
  321 + successes << message
  322 + end
  323 +
  324 + email_text = "Conducted the following tests on API data and found the following results\n" + "For each of the #{questions.length} questions in the database: \n"
  325 + errors.each do |e|
  326 + email_text += " Test FAILED: " + e + "\n"
  327 + end
  328 +
  329 + successes.uniq.each do |s|
  330 + s.split("\n").each do |m| # some successes have several lines
  331 + email_text += " Test Passed: " + m + "\n"
  332 + end
  333 + end
  334 +
  335 + puts email_text
  336 +
  337 + if errors.empty?
  338 + CronMailer.deliver_info_message(CRON_EMAIL, "Test of API Vote Consistency passed", email_text)
  339 + else
  340 + CronMailer.deliver_info_message(CRON_EMAIL.to_a + ERRORS_EMAIL.to_a, "Error! Failure of API Vote Consistency " , email_text)
  341 + end
  342 +
  343 + end
341 344  
342   - end
343 345 def check_basic_balanced_stats(question)
344   - error_message = ""
345   - success_message = "2 x Total Wins = Total Votes\n" +
346   - "Total Votes (wins + losses) is Even\n" +
347   - "Total Votes (wins + losses) = 2 x the number of vote objects that belong to the question\n" +
348   - "Total generated prompts on left = Total generated prompts on right"
349   - total_wins =0
350   - total_votes =0
351   - total_generated_prompts_on_left = 0
352   - total_generated_prompts_on_right = 0
353   - total_scores_gte_fifty= 0
354   - total_scores_lte_fifty= 0
355   - error_bool = false
356   -
357   - question.choices.each do |choice|
358   -
359   - if choice.wins
360   - total_wins += choice.wins
361   - total_votes += choice.wins
362   - end
363   -
364   - if choice.losses
  346 + error_message = ""
  347 + success_message = "2 x Total Wins = Total Votes\n" +
  348 + "Total Votes (wins + losses) is Even\n" +
  349 + "Total Votes (wins + losses) = 2 x the number of vote objects that belong to the question\n" +
  350 + "Total generated prompts on left = Total generated prompts on right"
  351 + total_wins =0
  352 + total_votes =0
  353 + total_generated_prompts_on_left = 0
  354 + total_generated_prompts_on_right = 0
  355 + total_scores_gte_fifty= 0
  356 + total_scores_lte_fifty= 0
  357 + error_bool = false
  358 +
  359 + question.choices.each do |choice|
  360 +
  361 + if choice.wins
  362 + total_wins += choice.wins
  363 + total_votes += choice.wins
  364 + end
  365 +
  366 + if choice.losses
365 367 total_votes += choice.losses
366   - end
  368 + end
367 369  
368   - total_generated_prompts_on_left += choice.prompts_on_the_left.size
369   - total_generated_prompts_on_right += choice.prompts_on_the_right.size
  370 + total_generated_prompts_on_left += choice.prompts_on_the_left.size
  371 + total_generated_prompts_on_right += choice.prompts_on_the_right.size
370 372  
371   - cached_score = choice.score.to_f
372   - generated_score = choice.compute_score.to_f
  373 + cached_score = choice.score.to_f
  374 + generated_score = choice.compute_score.to_f
373 375  
374   - delta = 0.001
  376 + delta = 0.001
375 377  
376   - if (cached_score - generated_score).abs >= delta
377   - error_message += "Error! The cached_score is not equal to the calculated score for choice #{choice.id}\n"
  378 + if (cached_score - generated_score).abs >= delta
  379 + error_message += "Error! The cached_score is not equal to the calculated score for choice #{choice.id}\n"
378 380  
379   - print "This score is wrong! #{choice.id} , Question ID: #{question.id}, #{cached_score}, #{generated_score}, updated: #{choice.updated_at}\n"
  381 + print "This score is wrong! #{choice.id} , Question ID: #{question.id}, #{cached_score}, #{generated_score}, updated: #{choice.updated_at}\n"
380 382  
381 383  
382   - end
  384 + end
383 385  
384   - if cached_score == 0.0 || cached_score == 100.0 || cached_score.nil?
385   - error_message += "Error! The cached_score for choice #{choice.id} is exactly 0 or 100, the value: #{cached_score}"
386   - print "Either 0 or 100 This score is wrong! #{choice.id} , Question ID: #{question.id}, #{cached_score}, #{generated_score}, updated: #{choice.updated_at}\n"
387   - end
  386 + if cached_score == 0.0 || cached_score == 100.0 || cached_score.nil?
  387 + error_message += "Error! The cached_score for choice #{choice.id} is exactly 0 or 100, the value: #{cached_score}"
  388 + print "Either 0 or 100 This score is wrong! #{choice.id} , Question ID: #{question.id}, #{cached_score}, #{generated_score}, updated: #{choice.updated_at}\n"
  389 + end
388 390  
389 391  
390   - if cached_score >= 50
391   - total_scores_gte_fifty +=1
392   - end
393   - if cached_score <= 50
394   - total_scores_lte_fifty +=1
395   - end
  392 + if cached_score >= 50
  393 + total_scores_gte_fifty +=1
  394 + end
  395 + if cached_score <= 50
  396 + total_scores_lte_fifty +=1
  397 + end
396 398  
397   - if (choice.wins != choice.votes.count)
398   - error_message += "Error!: Cached choice wins != actual choice wins for choice #{choice.id}\n"
399   - error_bool= true
400   - end
401   -
402   - if (choice.losses != question.votes.count(:conditions => {:loser_choice_id => choice.id}))
403   - error_message += "Error!: Cached choice wins != actual choice wins for choice #{choice.id}\n"
404   - error_bool= true
405   - end
  399 + if (choice.wins != choice.votes.count)
  400 + error_message += "Error!: Cached choice wins != actual choice wins for choice #{choice.id}\n"
  401 + error_bool= true
  402 + end
  403 +
  404 + if (choice.losses != question.votes.count(:conditions => {:loser_choice_id => choice.id}))
  405 + error_message += "Error!: Cached choice wins != actual choice wins for choice #{choice.id}\n"
  406 + error_bool= true
  407 + end
406 408  
407 409 end
408   -
409   -
410   - if (2*total_wins != total_votes)
411   - error_message += "Error 1: 2 x Total Wins != Total votes"
412   - error_bool= true
413   - end
414   -
415   - if(total_votes % 2 != 0)
416   - error_message += "Error 2: Total votes is not Even!"
417   - error_bool= true
418   - end
419   -
420   - if(total_votes != 2* question.votes_count)
421   - error_message += "Error 3: Total votes != 2 x # vote objects"
422   - error_bool = true
423   - end
424   -
425   - if(total_generated_prompts_on_right != total_generated_prompts_on_right)
426   - error_message += "Error 4: Total generated prompts on left != Total generated prompts on right"
427   - error_bool = true
428   - end
429   -
430   - if(total_scores_lte_fifty == question.choices.size || total_scores_gte_fifty == question.choices.size) && (total_scores_lte_fifty != total_scores_gte_fifty)
431   - error_message += "Error: The scores of all choices are either all above 50, or all below 50. This is probably wrong"
432   - error_bool = true
433   - puts "Error score fifty: #{question.id}"
434   - end
435   -
436   - if error_bool
437   - error_message += "Question #{question.id}: 2*wins = #{2*total_wins}, total votes = #{total_votes}, vote_count = #{question.votes_count}\n"
438   - end
  410 +
  411 +
  412 + if (2*total_wins != total_votes)
  413 + error_message += "Error 1: 2 x Total Wins != Total votes"
  414 + error_bool= true
  415 + end
  416 +
  417 + if(total_votes % 2 != 0)
  418 + error_message += "Error 2: Total votes is not Even!"
  419 + error_bool= true
  420 + end
  421 +
  422 + if(total_votes != 2* question.votes_count)
  423 + error_message += "Error 3: Total votes != 2 x # vote objects"
  424 + error_bool = true
  425 + end
  426 +
  427 + if(total_generated_prompts_on_right != total_generated_prompts_on_right)
  428 + error_message += "Error 4: Total generated prompts on left != Total generated prompts on right"
  429 + error_bool = true
  430 + end
  431 +
  432 + if(total_scores_lte_fifty == question.choices.size || total_scores_gte_fifty == question.choices.size) && (total_scores_lte_fifty != total_scores_gte_fifty)
  433 + error_message += "Error: The scores of all choices are either all above 50, or all below 50. This is probably wrong"
  434 + error_bool = true
  435 + puts "Error score fifty: #{question.id}"
  436 + end
  437 +
  438 + if error_bool
  439 + error_message += "Question #{question.id}: 2*wins = #{2*total_wins}, total votes = #{total_votes}, vote_count = #{question.votes_count}\n"
  440 + end
439 441 return error_message.blank? ? [success_message, false] : [error_message, true]
440 442 end
441 443 def check_each_choice_appears_within_n_stddevs(question)
442   - error_message =""
443   - success_message = "Each choice has appeared n times, where n falls within 6 stddevs of the mean number of appearances for a question " +
444   - "(Note: this applies only to seed choices (not user submitted) and choices currently marked active)"
  444 + error_message =""
  445 + success_message = "Each choice has appeared n times, where n falls within 6 stddevs of the mean number of appearances for a question " +
  446 + "(Note: this applies only to seed choices (not user submitted) and choices currently marked active)"
445 447  
446   - wins_by_choice_id = question.votes.active.count(:group => :choice_id)
447   - losses_by_choice_id= question.votes.active.count(:conditions => "loser_choice_id IS NOT NULL", :group => :loser_choice_id)
  448 + wins_by_choice_id = question.votes.active.count(:group => :choice_id)
  449 + losses_by_choice_id= question.votes.active.count(:conditions => "loser_choice_id IS NOT NULL", :group => :loser_choice_id)
448 450  
449   - #Rails returns an ordered hash, which doesn't allow for blocks to change merging logic.
450   - #A little hack to create a normal hash
451   - wins_hash = {}
452   - wins_hash.merge!(wins_by_choice_id)
453   - losses_hash = {}
454   - losses_hash.merge!(losses_by_choice_id)
  451 + #Rails returns an ordered hash, which doesn't allow for blocks to change merging logic.
  452 + #A little hack to create a normal hash
  453 + wins_hash = {}
  454 + wins_hash.merge!(wins_by_choice_id)
  455 + losses_hash = {}
  456 + losses_hash.merge!(losses_by_choice_id)
455 457  
456 458  
457 459  
458   - appearances_by_choice_id = wins_hash.merge(losses_hash) do |key, oldval, newval| oldval + newval end
  460 + appearances_by_choice_id = wins_hash.merge(losses_hash) do |key, oldval, newval| oldval + newval end
459 461  
460   - sum = total_appearances = appearances_by_choice_id.values.inject(0) {|sum, x| sum +=x}
461   - mean = average_appearances = total_appearances.to_f / appearances_by_choice_id.size.to_f
  462 + sum = total_appearances = appearances_by_choice_id.values.inject(0) {|sum, x| sum +=x}
  463 + mean = average_appearances = total_appearances.to_f / appearances_by_choice_id.size.to_f
462 464  
463   - if sum > 0:
464   - stddev = Math.sqrt( appearances_by_choice_id.values.inject(0) { |sum, e| sum + (e - mean) ** 2 } / appearances_by_choice_id.size.to_f )
  465 + if sum > 0:
  466 + stddev = Math.sqrt( appearances_by_choice_id.values.inject(0) { |sum, e| sum + (e - mean) ** 2 } / appearances_by_choice_id.size.to_f )
465 467  
466 468 appearances_by_choice_id.each do |choice_id, n_i|
467   - if (n_i < (mean - 6*stddev)) || (n_i > mean + 6 *stddev)
468   - 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"
469   - end
470   - end
471   - end
  469 + if (n_i < (mean - 6*stddev)) || (n_i > mean + 6 *stddev)
  470 + 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"
  471 + end
  472 + end
  473 + end
472 474  
473 475 return error_message.blank? ? [success_message, false] : [error_message, true]
474 476 end
475 477 def check_each_choice_equally_likely_to_appear_left_or_right(question)
476   - error_message = ""
477   - success_message = "All choices have equal probability of appearing on left or right (within error params)"
478   - question.choices.each do |c|
479   - left_prompts_ids = c.prompts_on_the_left.ids_only
480   - right_prompts_ids = c.prompts_on_the_right.ids_only
481   -
482   - left_appearances = question.appearances.count(:conditions => {:prompt_id => left_prompts_ids})
483   - right_appearances = question.appearances.count(:conditions => {:prompt_id => right_prompts_ids})
484   -
485   - n = left_appearances + right_appearances
486   -
487   - if n == 0
488   - next
489   - end
490   - est_p = right_appearances.to_f / n.to_f
491   - z = (est_p - 0.5).abs / Math.sqrt((0.5 * 0.5) / n.to_f)
492   -
493   - if z > 6
494   - error_message += "Error: Choice ID #{c.id} seems to favor one side: Left Appearances #{left_appearances}, Right Appearances: #{right_appearances}, z = #{z}\n"
495   - end
496   - end
  478 + error_message = ""
  479 + success_message = "All choices have equal probability of appearing on left or right (within error params)"
  480 + question.choices.each do |c|
  481 + left_prompts_ids = c.prompts_on_the_left.ids_only
  482 + right_prompts_ids = c.prompts_on_the_right.ids_only
  483 +
  484 + left_appearances = question.appearances.count(:conditions => {:prompt_id => left_prompts_ids})
  485 + right_appearances = question.appearances.count(:conditions => {:prompt_id => right_prompts_ids})
  486 +
  487 + n = left_appearances + right_appearances
  488 +
  489 + if n == 0
  490 + next
  491 + end
  492 + est_p = right_appearances.to_f / n.to_f
  493 + z = (est_p - 0.5).abs / Math.sqrt((0.5 * 0.5) / n.to_f)
  494 +
  495 + if z > 6
  496 + error_message += "Error: Choice ID #{c.id} seems to favor one side: Left Appearances #{left_appearances}, Right Appearances: #{right_appearances}, z = #{z}\n"
  497 + end
  498 + end
497 499 return error_message.blank? ? [success_message, false] : [error_message, true]
498 500 end
499 501 def check_prompt_cache_hit_rate(question)
500   - error_message = ""
501   - success_message = "At least 90% of prompts on catchup algorithm questions were served from cache\n"
502   -
503   - misses = question.get_prompt_cache_misses(Date.yesterday).to_i
504   - hits = question.get_prompt_cache_hits(Date.yesterday).to_i
505   -
506   - question.expire_prompt_cache_tracking_keys(Date.yesterday)
507   -
508   - yesterday_appearances = question.appearances.count(:conditions => ['date(created_at) = ?', Date.yesterday])
509   -
510   - if misses + hits != yesterday_appearances
511   - error_message += "Error! Question #{question.id} isn't tracking prompt cache hits and misses accurately! Expected #{yesterday_appearances}, Actual: #{misses+hits}\n"
512   - end
513   -
514   - if yesterday_appearances > 5 # this test isn't worthwhile for small numbers of appearances
515   - miss_rate = misses.to_f / yesterday_appearances.to_f
516   - if miss_rate > 0.1
517   - 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"
518   - end
  502 + error_message = ""
  503 + success_message = "At least 90% of prompts on catchup algorithm questions were served from cache\n"
  504 +
  505 + misses = question.get_prompt_cache_misses(Date.yesterday).to_i
  506 + hits = question.get_prompt_cache_hits(Date.yesterday).to_i
  507 +
  508 + question.expire_prompt_cache_tracking_keys(Date.yesterday)
  509 +
  510 + yesterday_appearances = question.appearances.count(:conditions => ['date(created_at) = ?', Date.yesterday])
  511 +
  512 + if misses + hits != yesterday_appearances
  513 + error_message += "Error! Question #{question.id} isn't tracking prompt cache hits and misses accurately! Expected #{yesterday_appearances}, Actual: #{misses+hits}\n"
  514 + end
  515 +
  516 + if yesterday_appearances > 5 # this test isn't worthwhile for small numbers of appearances
  517 + miss_rate = misses.to_f / yesterday_appearances.to_f
  518 + if miss_rate > 0.1
  519 + 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"
  520 + end
519 521 end
520 522 return error_message.blank? ? [success_message, false] : [error_message, true]
521 523 end
... ... @@ -524,30 +526,30 @@ namespace :test_api do
524 526 error_message = ""
525 527 success_message = "All cached object values match actual values within database"
526 528 # Checks that counter_cache is working as expected
527   - cached_prompts_size = question.prompts.size
528   - actual_prompts_size = question.prompts.count
529   -
530   - if cached_prompts_size != actual_prompts_size
531   - error_message += "Error! Question #{question.id} has an inconsistent # of prompts! cached#: #{cached_prompts_size}, actual#: #{actual_prompts_size}\n"
532   - end
533   -
534   - cached_votes_size = question.votes.size
535   - actual_votes_size = question.votes.count
536   -
537   - if cached_votes_size != actual_votes_size
538   - error_message += "Error! Question #{question.id} has an inconsistent # of votes! cached#: #{cached_votes_size}, actual#: #{actual_votes_size}\n"
539   - end
540   -
541   - cached_choices_size = question.choices.size
542   - actual_choices_size = question.choices.count
543   -
544   - if cached_choices_size != actual_choices_size
545   - error_message+= "Error! Question #{question.id} has an inconsistent # of choices! cached#: #{cached_choices_size}, actual#: #{actual_choices_size}\n"
546   - end
547   -
548   - #if cached_prompts_size != question.choices.size **2 - question.choices.size
549   - # 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"
550   - #end
  529 + cached_prompts_size = question.prompts.size
  530 + actual_prompts_size = question.prompts.count
  531 +
  532 + if cached_prompts_size != actual_prompts_size
  533 + error_message += "Error! Question #{question.id} has an inconsistent # of prompts! cached#: #{cached_prompts_size}, actual#: #{actual_prompts_size}\n"
  534 + end
  535 +
  536 + cached_votes_size = question.votes.size
  537 + actual_votes_size = question.votes.count
  538 +
  539 + if cached_votes_size != actual_votes_size
  540 + error_message += "Error! Question #{question.id} has an inconsistent # of votes! cached#: #{cached_votes_size}, actual#: #{actual_votes_size}\n"
  541 + end
  542 +
  543 + cached_choices_size = question.choices.size
  544 + actual_choices_size = question.choices.count
  545 +
  546 + if cached_choices_size != actual_choices_size
  547 + error_message+= "Error! Question #{question.id} has an inconsistent # of choices! cached#: #{cached_choices_size}, actual#: #{actual_choices_size}\n"
  548 + end
  549 +
  550 + #if cached_prompts_size != question.choices.size **2 - question.choices.size
  551 + # 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"
  552 + #end
551 553 return error_message.blank? ? [success_message, false] : [error_message, true]
552 554 end
553 555  
... ... @@ -561,7 +563,7 @@ namespace :test_api do
561 563  
562 564 if (total_answered_appearances != total_votes+ total_skips)
563 565 difference = (total_votes+ total_skips) - total_answered_appearances
564   - error_message += "Error! There are #{difference} votes or skips without associated appearance objects."
  566 + error_message += "Error! There are #{difference} votes or skips without associated appearance objects."
565 567 end
566 568  
567 569 return error_message.blank? ? [success_message, false] : [error_message, true]
... ... @@ -575,32 +577,32 @@ namespace :test_api do
575 577  
576 578 Vote.find_each(:batch_size => 1000, :include => :appearance) do |v|
577 579  
578   - # Subtracting DateTime objects results in the difference in days
579   - server_response_time = v.created_at.to_f - v.appearance.created_at.to_f
580   - if server_response_time < 0
581   - 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"
  580 + # Subtracting DateTime objects results in the difference in days
  581 + server_response_time = v.created_at.to_f - v.appearance.created_at.to_f
  582 + if server_response_time < 0
  583 + 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"
582 584  
583   - error_message += the_error_msg
584   - print "Error!" + the_error_msg
585   - end
  585 + error_message += the_error_msg
  586 + print "Error!" + the_error_msg
  587 + end
586 588  
587   - if v.time_viewed && v.time_viewed/1000 > server_response_time
588   - 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"
  589 + if v.time_viewed && v.time_viewed/1000 > server_response_time
  590 + 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"
589 591  
590   - error_message += the_error_msg
591   - print the_error_msg
  592 + error_message += the_error_msg
  593 + print the_error_msg
592 594  
593 595 elsif v.time_viewed.nil?
594   - if v.created_at > recording_client_time_start_date && v.missing_response_time_exp != 'invalid'
595   - 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"
596   - error_message += the_error_msg
597   - print the_error_msg
598   - end
  596 + if v.created_at > recording_client_time_start_date && v.missing_response_time_exp != 'invalid'
  597 + 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"
  598 + error_message += the_error_msg
  599 + print the_error_msg
  600 + end
599 601  
600   - end
  602 + end
601 603  
602 604 end
603   -
  605 +
604 606 return error_message.blank? ? [success_message, false] : [error_message, true]
605 607 end
606 608 end
... ...