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 +8,8 @@ namespace :test_api do | ||
8 | true_losses = question.votes.count(:conditions => {:loser_choice_id => choice.id}) | 8 | true_losses = question.votes.count(:conditions => {:loser_choice_id => choice.id}) |
9 | true_wins = choice.votes.count | 9 | true_wins = choice.votes.count |
10 | Choice.update_counters choice.id, | 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 | choice.reload | 13 | choice.reload |
14 | choice.score = choice.compute_score | 14 | choice.score = choice.compute_score |
15 | choice.save(false) | 15 | choice.save(false) |
@@ -40,7 +40,7 @@ namespace :test_api do | @@ -40,7 +40,7 @@ namespace :test_api do | ||
40 | end | 40 | end |
41 | end | 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 | desc "Ensure that all choices have 0 <= score <= 100" | 45 | desc "Ensure that all choices have 0 <= score <= 100" |
46 | task :verify_range_of_choices_scores => :environment do | 46 | task :verify_range_of_choices_scores => :environment do |
@@ -73,255 +73,255 @@ namespace :test_api do | @@ -73,255 +73,255 @@ namespace :test_api do | ||
73 | return error_message.blank? ? [success_message, false] : [error_message, true] | 73 | return error_message.blank? ? [success_message, false] : [error_message, true] |
74 | end | 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 | end | 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 | end | 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 | end | 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 | end | 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 | desc "Description here" | 325 | desc "Description here" |
326 | task(:question_vote_consistency => :environment) do | 326 | task(:question_vote_consistency => :environment) do |
327 | questions = Question.find(:all) | 327 | questions = Question.find(:all) |
@@ -384,7 +384,7 @@ namespace :test_api do | @@ -384,7 +384,7 @@ namespace :test_api do | ||
384 | end | 384 | end |
385 | 385 | ||
386 | message, error_occurred = ensure_all_votes_and_skips_have_unique_appearance | 386 | message, error_occurred = ensure_all_votes_and_skips_have_unique_appearance |
387 | - | 387 | + |
388 | if error_occurred | 388 | if error_occurred |
389 | errors << message | 389 | errors << message |
390 | else | 390 | else |
@@ -415,9 +415,9 @@ namespace :test_api do | @@ -415,9 +415,9 @@ namespace :test_api do | ||
415 | email_text += " Test Passed: " + m + "\n" | 415 | email_text += " Test Passed: " + m + "\n" |
416 | end | 416 | end |
417 | end | 417 | end |
418 | - | 418 | + |
419 | puts email_text | 419 | puts email_text |
420 | - | 420 | + |
421 | if errors.empty? | 421 | if errors.empty? |
422 | CronMailer.deliver_info_message(CRON_EMAIL, "Test of API Vote Consistency passed", email_text) | 422 | CronMailer.deliver_info_message(CRON_EMAIL, "Test of API Vote Consistency passed", email_text) |
423 | else | 423 | else |
@@ -426,34 +426,34 @@ namespace :test_api do | @@ -426,34 +426,34 @@ namespace :test_api do | ||
426 | 426 | ||
427 | end | 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 | if choice.wins | 450 | if choice.wins |
451 | total_wins += choice.wins | 451 | total_wins += choice.wins |
452 | total_votes += choice.wins | 452 | total_votes += choice.wins |
453 | end | 453 | end |
454 | 454 | ||
455 | if choice.losses | 455 | if choice.losses |
456 | - total_votes += choice.losses | 456 | + total_votes += choice.losses |
457 | end | 457 | end |
458 | 458 | ||
459 | total_generated_prompts_on_left += choice.prompts_on_the_left.size | 459 | total_generated_prompts_on_left += choice.prompts_on_the_left.size |
@@ -465,16 +465,16 @@ namespace :test_api do | @@ -465,16 +465,16 @@ namespace :test_api do | ||
465 | delta = 0.001 | 465 | delta = 0.001 |
466 | 466 | ||
467 | if (cached_score - generated_score).abs >= delta | 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 | end | 473 | end |
474 | 474 | ||
475 | if cached_score == 0.0 || cached_score == 100.0 || cached_score.nil? | 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 | end | 478 | end |
479 | 479 | ||
480 | unless question_has_votes_before_2010_02_17 | 480 | unless question_has_votes_before_2010_02_17 |
@@ -493,10 +493,10 @@ namespace :test_api do | @@ -493,10 +493,10 @@ namespace :test_api do | ||
493 | end | 493 | end |
494 | 494 | ||
495 | if (choice.wins != choice.votes.count) | 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 | end | 498 | end |
499 | - | 499 | + |
500 | # votes before 2010-02-17 have null loser_choice_id | 500 | # votes before 2010-02-17 have null loser_choice_id |
501 | # therefore we want to ignore this test for any question with votes | 501 | # therefore we want to ignore this test for any question with votes |
502 | # prior to 2010-02-17 | 502 | # prior to 2010-02-17 |
@@ -507,156 +507,156 @@ namespace :test_api do | @@ -507,156 +507,156 @@ namespace :test_api do | ||
507 | end | 507 | end |
508 | end | 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 | end | 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 | end | 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 | error_bool = true | 532 | error_bool = true |
527 | end | 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 | end | 545 | end |
546 | + return error_message.blank? ? [success_message, false] : [error_message, true] | ||
541 | end | 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 | end | 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 | error_message = "" | 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 | next | 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 | end | 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 | end | 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 | end | 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 | desc "Ensure that a question has: answered_appearances == votes + skips" | 661 | desc "Ensure that a question has: answered_appearances == votes + skips" |
662 | task :answered_appearances_equals_votes_and_skips => :environment do | 662 | task :answered_appearances_equals_votes_and_skips => :environment do |
@@ -673,63 +673,63 @@ namespace :test_api do | @@ -673,63 +673,63 @@ namespace :test_api do | ||
673 | if (total_answered_appearances != total_votes + total_skips) | 673 | if (total_answered_appearances != total_votes + total_skips) |
674 | error_message += "Question #{question.id}: answered_appearances = #{total_answered_appearances}, votes = #{total_votes}, skips = #{total_skips}" | 674 | error_message += "Question #{question.id}: answered_appearances = #{total_answered_appearances}, votes = #{total_votes}, skips = #{total_skips}" |
675 | end | 675 | end |
676 | - | 676 | + |
677 | 677 | ||
678 | return error_message.blank? ? [success_message, false] : [error_message, true] | 678 | return error_message.blank? ? [success_message, false] : [error_message, true] |
679 | end | 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 | next if v.nil? || v.appearance.nil? | 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 | end | 734 | end |
735 | 735 |