Commit 94247db42f5e230f84031f2dd3d294b305889148

Authored by Luke Baker
1 parent 2372de54

retab spacing Question

Showing 1 changed file with 211 additions and 211 deletions   Show diff stats
app/models/question.rb
@@ -36,7 +36,7 @@ class Question < ActiveRecord::Base @@ -36,7 +36,7 @@ class Question < ActiveRecord::Base
36 def create_choices_from_ideas 36 def create_choices_from_ideas
37 if ideas && ideas.any? 37 if ideas && ideas.any?
38 ideas.each do |idea| 38 ideas.each do |idea|
39 - choices.create!(:creator => self.creator, :active => true, :data => idea.squish.strip) 39 + choices.create!(:creator => self.creator, :active => true, :data => idea.squish.strip)
40 end 40 end
41 end 41 end
42 end 42 end
@@ -48,27 +48,27 @@ class Question < ActiveRecord::Base @@ -48,27 +48,27 @@ class Question < ActiveRecord::Base
48 def choose_prompt(options = {}) 48 def choose_prompt(options = {})
49 49
50 # if there is one or fewer active choices, we won't be able to find a prompt 50 # if there is one or fewer active choices, we won't be able to find a prompt
51 - if self.choices.size - self.inactive_choices_count <= 1  
52 - raise RuntimeError, "More than one choice needs to be active"  
53 - end  
54 -  
55 - if self.uses_catchup? || options[:algorithm] == "catchup"  
56 - logger.info("Question #{self.id} is using catchup algorithm!")  
57 - next_prompt = self.pop_prompt_queue  
58 - if next_prompt.nil?  
59 - logger.info("DEBUG Catchup prompt cache miss! Nothing in prompt_queue")  
60 - next_prompt = self.catchup_choose_prompt  
61 - record_prompt_cache_miss  
62 - else  
63 - record_prompt_cache_hit  
64 - end  
65 - self.send_later :add_prompt_to_queue  
66 - return next_prompt  
67 - else  
68 - #Standard choose prompt at random 51 + if self.choices.size - self.inactive_choices_count <= 1
  52 + raise RuntimeError, "More than one choice needs to be active"
  53 + end
  54 +
  55 + if self.uses_catchup? || options[:algorithm] == "catchup"
  56 + logger.info("Question #{self.id} is using catchup algorithm!")
  57 + next_prompt = self.pop_prompt_queue
  58 + if next_prompt.nil?
  59 + logger.info("DEBUG Catchup prompt cache miss! Nothing in prompt_queue")
  60 + next_prompt = self.catchup_choose_prompt
  61 + record_prompt_cache_miss
  62 + else
  63 + record_prompt_cache_hit
  64 + end
  65 + self.send_later :add_prompt_to_queue
  66 + return next_prompt
  67 + else
  68 + #Standard choose prompt at random
69 next_prompt = self.picked_prompt 69 next_prompt = self.picked_prompt
70 - return next_prompt  
71 - end 70 + return next_prompt
  71 + end
72 72
73 end 73 end
74 74
@@ -92,16 +92,16 @@ class Question &lt; ActiveRecord::Base @@ -92,16 +92,16 @@ class Question &lt; ActiveRecord::Base
92 prompt = nil 92 prompt = nil
93 93
94 until prompt && prompt.active? 94 until prompt && prompt.active?
95 - target = rand  
96 - left_choice_id = right_choice_id = nil  
97 -  
98 - weighted.each do |item, weight|  
99 - if target <= weight  
100 - left_choice_id, right_choice_id = item.split(", ")  
101 - break  
102 - end  
103 - target -= weight  
104 - end 95 + target = rand
  96 + left_choice_id = right_choice_id = nil
  97 +
  98 + weighted.each do |item, weight|
  99 + if target <= weight
  100 + left_choice_id, right_choice_id = item.split(", ")
  101 + break
  102 + end
  103 + target -= weight
  104 + end
105 prompt = prompts.find_or_create_by_left_choice_id_and_right_choice_id(left_choice_id, right_choice_id, :include => [{ :left_choice => :item }, { :right_choice => :item }]) 105 prompt = prompts.find_or_create_by_left_choice_id_and_right_choice_id(left_choice_id, right_choice_id, :include => [{ :left_choice => :item }, { :right_choice => :item }])
106 end 106 end
107 # check if prompt has two active choices here, maybe we can set this on the prompt level too? 107 # check if prompt has two active choices here, maybe we can set this on the prompt level too?
@@ -116,24 +116,24 @@ class Question &lt; ActiveRecord::Base @@ -116,24 +116,24 @@ class Question &lt; ActiveRecord::Base
116 sum = 0.0 116 sum = 0.0
117 117
118 prompts.find_each(:select => 'votes_count, left_choice_id, right_choice_id') do |p| 118 prompts.find_each(:select => 'votes_count, left_choice_id, right_choice_id') do |p|
119 - value = [(1.0/ (p.votes.size + 1).to_f).to_f, throttle_min].min 119 + value = [(1.0/ (p.votes.size + 1).to_f).to_f, throttle_min].min
120 weights["#{p.left_choice_id}, #{p.right_choice_id}"] = value 120 weights["#{p.left_choice_id}, #{p.right_choice_id}"] = value
121 - sum += value 121 + sum += value
122 end 122 end
123 123
124 # This will not run once all prompts have been generated, 124 # This will not run once all prompts have been generated,
125 - # but it prevents us from having to pregenerate all possible prompts 125 + # but it prevents us from having to pregenerate all possible prompts
126 if weights.size < choices.size ** 2 - choices.size 126 if weights.size < choices.size ** 2 - choices.size
127 choices.each do |l| 127 choices.each do |l|
128 - choices.each do |r|  
129 - if l.id == r.id  
130 - next  
131 - end  
132 - if !weights.has_key?("#{l.id}, #{r.id}") 128 + choices.each do |r|
  129 + if l.id == r.id
  130 + next
  131 + end
  132 + if !weights.has_key?("#{l.id}, #{r.id}")
133 weights["#{l.id}, #{r.id}"] = throttle_min 133 weights["#{l.id}, #{r.id}"] = throttle_min
134 - sum+=throttle_min  
135 - end  
136 - end 134 + sum+=throttle_min
  135 + end
  136 + end
137 end 137 end
138 end 138 end
139 139
@@ -160,37 +160,37 @@ class Question &lt; ActiveRecord::Base @@ -160,37 +160,37 @@ class Question &lt; ActiveRecord::Base
160 @prompt = choose_prompt(:algorithm => params[:algorithm]) 160 @prompt = choose_prompt(:algorithm => params[:algorithm])
161 @appearance = current_user.record_appearance(visitor, @prompt) 161 @appearance = current_user.record_appearance(visitor, @prompt)
162 else 162 else
163 - #only display a new prompt and new appearance if the old prompt has not been voted on  
164 - @appearance = last_appearance 163 + #only display a new prompt and new appearance if the old prompt has not been voted on
  164 + @appearance = last_appearance
165 @prompt= @appearance.prompt 165 @prompt= @appearance.prompt
166 end 166 end
167 167
168 if params[:future_prompts] 168 if params[:future_prompts]
169 - num_future = params[:future_prompts][:number].to_i rescue 1  
170 - num_future.times do |number|  
171 - offset = number + 1 169 + num_future = params[:future_prompts][:number].to_i rescue 1
  170 + num_future.times do |number|
  171 + offset = number + 1
172 last_appearance = get_first_unanswered_appearance(visitor, offset) 172 last_appearance = get_first_unanswered_appearance(visitor, offset)
173 if last_appearance.nil? 173 if last_appearance.nil?
174 @future_prompt = choose_prompt(:algorithm => params[:algorithm]) 174 @future_prompt = choose_prompt(:algorithm => params[:algorithm])
175 @future_appearance = current_user.record_appearance(visitor, @future_prompt) 175 @future_appearance = current_user.record_appearance(visitor, @future_prompt)
176 - else  
177 - @future_appearance = last_appearance 176 + else
  177 + @future_appearance = last_appearance
178 @future_prompt= @future_appearance.prompt 178 @future_prompt= @future_appearance.prompt
179 - end  
180 - 179 + end
  180 +
181 result.merge!({"future_appearance_id_#{offset}".to_sym => @future_appearance.lookup}) 181 result.merge!({"future_appearance_id_#{offset}".to_sym => @future_appearance.lookup})
182 result.merge!({"future_prompt_id_#{offset}".to_sym => @future_prompt.id}) 182 result.merge!({"future_prompt_id_#{offset}".to_sym => @future_prompt.id})
183 183
184 - ["left", "right"].each do |side|  
185 - ["text", "id"].each do |param|  
186 - choice = (side == "left") ? @future_prompt.left_choice : @future_prompt.right_choice  
187 - param_val = (param == "text") ? choice.data : choice.id 184 + ["left", "right"].each do |side|
  185 + ["text", "id"].each do |param|
  186 + choice = (side == "left") ? @future_prompt.left_choice : @future_prompt.right_choice
  187 + param_val = (param == "text") ? choice.data : choice.id
188 188
189 result.merge!({"future_#{side}_choice_#{param}_#{offset}".to_sym => param_val}) 189 result.merge!({"future_#{side}_choice_#{param}_#{offset}".to_sym => param_val})
190 - end  
191 - end  
192 -  
193 - end 190 + end
  191 + end
  192 +
  193 + end
194 194
195 end 195 end
196 196
@@ -219,7 +219,7 @@ class Question &lt; ActiveRecord::Base @@ -219,7 +219,7 @@ class Question &lt; ActiveRecord::Base
219 if votes_by_visitors.size > 0 219 if votes_by_visitors.size > 0
220 average = votes_by_visitors.inject(0){|total, (k,v)| total = total + v}.to_f / votes_by_visitors.size.to_f 220 average = votes_by_visitors.inject(0){|total, (k,v)| total = total + v}.to_f / votes_by_visitors.size.to_f
221 else 221 else
222 - average = 0.0 222 + average = 0.0
223 end 223 end
224 224
225 result.merge!(:average_votes => average.round) # round to 2 decimals 225 result.merge!(:average_votes => average.round) # round to 2 decimals
@@ -232,22 +232,22 @@ class Question &lt; ActiveRecord::Base @@ -232,22 +232,22 @@ class Question &lt; ActiveRecord::Base
232 #passing precomputed sum saves us a traversal through the array 232 #passing precomputed sum saves us a traversal through the array
233 def normalize!(weighted, sum=nil) 233 def normalize!(weighted, sum=nil)
234 if weighted.instance_of?(Hash) 234 if weighted.instance_of?(Hash)
235 - if sum.nil?  
236 - sum = weighted.inject(0) do |sum, item_and_weight|  
237 - sum += item_and_weight[1]  
238 - end  
239 - sum = sum.to_f  
240 - end  
241 - weighted.each do |item, weight|  
242 - weighted[item] = weight/sum  
243 - weighted[item] = 0.0 unless weighted[item].finite?  
244 - end 235 + if sum.nil?
  236 + sum = weighted.inject(0) do |sum, item_and_weight|
  237 + sum += item_and_weight[1]
  238 + end
  239 + sum = sum.to_f
  240 + end
  241 + weighted.each do |item, weight|
  242 + weighted[item] = weight/sum
  243 + weighted[item] = 0.0 unless weighted[item].finite?
  244 + end
245 elsif weighted.instance_of?(Array) 245 elsif weighted.instance_of?(Array)
246 - sum = weighted.inject(0) {|sum, item| sum += item} if sum.nil?  
247 - weighted.each_with_index do |item, i|  
248 - weighted[i] = item/sum  
249 - weighted[i] = 0.0 unless weighted[i].finite?  
250 - end 246 + sum = weighted.inject(0) {|sum, item| sum += item} if sum.nil?
  247 + weighted.each_with_index do |item, i|
  248 + weighted[i] = item/sum
  249 + weighted[i] = 0.0 unless weighted[i].finite?
  250 + end
251 251
252 end 252 end
253 end 253 end
@@ -266,8 +266,8 @@ class Question &lt; ActiveRecord::Base @@ -266,8 +266,8 @@ class Question &lt; ActiveRecord::Base
266 266
267 # Initial probabilities chosen at random 267 # Initial probabilities chosen at random
268 the_choices.size.times do 268 the_choices.size.times do
269 - probs << rand  
270 - prev_probs << rand 269 + probs << rand
  270 + prev_probs << rand
271 end 271 end
272 272
273 t=0 273 t=0
@@ -287,13 +287,13 @@ class Question &lt; ActiveRecord::Base @@ -287,13 +287,13 @@ class Question &lt; ActiveRecord::Base
287 287
288 denominator = 0.0 288 denominator = 0.0
289 the_choices.each_with_index do |c, index| 289 the_choices.each_with_index do |c, index|
290 - if(index == s)  
291 - next  
292 - end 290 + if(index == s)
  291 + next
  292 + end
293 293
294 - wins_and_losses = the_prompts["#{choice.id}, #{c.id}"].votes.size + the_prompts["#{c.id}, #{choice.id}"].votes.size 294 + wins_and_losses = the_prompts["#{choice.id}, #{c.id}"].votes.size + the_prompts["#{c.id}, #{choice.id}"].votes.size
295 295
296 - denominator+= (wins_and_losses).to_f / (prev_probs[s] + prev_probs[index]) 296 + denominator+= (wins_and_losses).to_f / (prev_probs[s] + prev_probs[index])
297 end 297 end
298 probs[s] = numerator / denominator 298 probs[s] = numerator / denominator
299 # avoid divide by zero NaN 299 # avoid divide by zero NaN
@@ -303,25 +303,25 @@ class Question &lt; ActiveRecord::Base @@ -303,25 +303,25 @@ class Question &lt; ActiveRecord::Base
303 303
304 difference = 0 304 difference = 0
305 probs.each_with_index do |curr, index| 305 probs.each_with_index do |curr, index|
306 - difference += (curr - prev_probs[index]).abs 306 + difference += (curr - prev_probs[index]).abs
307 end 307 end
308 puts difference 308 puts difference
309 end 309 end
310 310
311 probs_hash = {} 311 probs_hash = {}
312 probs.each_with_index do |item, index| 312 probs.each_with_index do |item, index|
313 - probs_hash[the_choices[index].id] = item 313 + probs_hash[the_choices[index].id] = item
314 end 314 end
315 probs_hash 315 probs_hash
316 end 316 end
317 317
318 318
319 def all_bt_scores 319 def all_bt_scores
320 - btprobs = bradley_terry_probs  
321 - btprobs.each do |key, value|  
322 - c = Choice.find(key)  
323 - puts "#{c.id}: #{c.votes.size} #{c.compute_bt_score(btprobs)}"  
324 - end 320 + btprobs = bradley_terry_probs
  321 + btprobs.each do |key, value|
  322 + c = Choice.find(key)
  323 + puts "#{c.id}: #{c.votes.size} #{c.compute_bt_score(btprobs)}"
  324 + end
325 325
326 end 326 end
327 327
@@ -388,36 +388,36 @@ class Question &lt; ActiveRecord::Base @@ -388,36 +388,36 @@ class Question &lt; ActiveRecord::Base
388 388
389 is_user_created = {} 389 is_user_created = {}
390 self.choices.each do |c| 390 self.choices.each do |c|
391 - is_user_created[c.id] = c.user_created 391 + is_user_created[c.id] = c.user_created
392 end 392 end
393 393
394 394
395 #the_prompts = prompts.find(:all, :include => ['left_choice', 'right_choice']) 395 #the_prompts = prompts.find(:all, :include => ['left_choice', 'right_choice'])
396 prompts.find_each do |p| 396 prompts.find_each do |p|
397 397
398 - num_appearances = num_appearances_by_prompt[p.id]  
399 -  
400 - if num_appearances.nil?  
401 - num_appearances = 0  
402 - end  
403 -  
404 - left_user_created = is_user_created[p.left_choice_id]  
405 - right_user_created = is_user_created[p.right_choice_id]  
406 -  
407 -  
408 - if left_user_created == false && right_user_created == false  
409 - seed_seed_sum += num_appearances  
410 - seed_seed_total +=1  
411 - elsif left_user_created == false && right_user_created == true  
412 - seed_nonseed_sum += num_appearances  
413 - seed_nonseed_total +=1  
414 - elsif left_user_created == true && right_user_created == false  
415 - nonseed_seed_sum += num_appearances  
416 - nonseed_seed_total +=1  
417 - elsif left_user_created == true && right_user_created == true  
418 - nonseed_nonseed_sum += num_appearances  
419 - nonseed_nonseed_total +=1  
420 - end 398 + num_appearances = num_appearances_by_prompt[p.id]
  399 +
  400 + if num_appearances.nil?
  401 + num_appearances = 0
  402 + end
  403 +
  404 + left_user_created = is_user_created[p.left_choice_id]
  405 + right_user_created = is_user_created[p.right_choice_id]
  406 +
  407 +
  408 + if left_user_created == false && right_user_created == false
  409 + seed_seed_sum += num_appearances
  410 + seed_seed_total +=1
  411 + elsif left_user_created == false && right_user_created == true
  412 + seed_nonseed_sum += num_appearances
  413 + seed_nonseed_total +=1
  414 + elsif left_user_created == true && right_user_created == false
  415 + nonseed_seed_sum += num_appearances
  416 + nonseed_seed_total +=1
  417 + elsif left_user_created == true && right_user_created == true
  418 + nonseed_nonseed_sum += num_appearances
  419 + nonseed_nonseed_total +=1
  420 + end
421 end 421 end
422 422
423 densities = {} 423 densities = {}
@@ -437,175 +437,175 @@ class Question &lt; ActiveRecord::Base @@ -437,175 +437,175 @@ class Question &lt; ActiveRecord::Base
437 437
438 def save_densities! 438 def save_densities!
439 439
440 - d_hash = density 440 + d_hash = density
441 441
442 - d_hash.each do |type, average|  
443 - d = Density.new  
444 - d.question_id = self.id  
445 - d.prompt_type = type.to_s  
446 - d.value = average.nan? ? nil : average  
447 - d.save!  
448 - end 442 + d_hash.each do |type, average|
  443 + d = Density.new
  444 + d.question_id = self.id
  445 + d.prompt_type = type.to_s
  446 + d.value = average.nan? ? nil : average
  447 + d.save!
  448 + end
449 end 449 end
450 450
451 def pq_key 451 def pq_key
452 - @pq_key ||= "#{self.id}_prompt_queue" 452 + @pq_key ||= "#{self.id}_prompt_queue"
453 end 453 end
454 454
455 def clear_prompt_queue 455 def clear_prompt_queue
456 - $redis.del(self.pq_key) 456 + $redis.del(self.pq_key)
457 end 457 end
458 458
459 def add_prompt_to_queue 459 def add_prompt_to_queue
460 - prompt = self.catchup_choose_prompt  
461 - $redis.rpush(self.pq_key, prompt.id)  
462 - prompt 460 + prompt = self.catchup_choose_prompt
  461 + $redis.rpush(self.pq_key, prompt.id)
  462 + prompt
463 end 463 end
464 464
465 def pop_prompt_queue 465 def pop_prompt_queue
466 - begin  
467 - prompt_id = $redis.lpop(self.pq_key)  
468 - prompt = prompt_id.nil? ? nil : Prompt.find(prompt_id.to_i) 466 + begin
  467 + prompt_id = $redis.lpop(self.pq_key)
  468 + prompt = prompt_id.nil? ? nil : Prompt.find(prompt_id.to_i)
469 end until (prompt.nil? || prompt.active?) 469 end until (prompt.nil? || prompt.active?)
470 prompt 470 prompt
471 end 471 end
472 472
473 def record_prompt_cache_miss 473 def record_prompt_cache_miss
474 - $redis.incr(self.pq_key + "_" + Time.now.to_date.to_s + "_"+ "misses") 474 + $redis.incr(self.pq_key + "_" + Time.now.to_date.to_s + "_"+ "misses")
475 end 475 end
476 476
477 def record_prompt_cache_hit 477 def record_prompt_cache_hit
478 - $redis.incr(self.pq_key + "_" + Time.now.to_date.to_s + "_"+ "hits") 478 + $redis.incr(self.pq_key + "_" + Time.now.to_date.to_s + "_"+ "hits")
479 end 479 end
480 480
481 def get_prompt_cache_misses(date) 481 def get_prompt_cache_misses(date)
482 - $redis.get(self.pq_key + "_" + date.to_s + "_"+ "misses") 482 + $redis.get(self.pq_key + "_" + date.to_s + "_"+ "misses")
483 end 483 end
484 def get_prompt_cache_hits(date) 484 def get_prompt_cache_hits(date)
485 - $redis.get(self.pq_key + "_" + date.to_s + "_"+ "hits") 485 + $redis.get(self.pq_key + "_" + date.to_s + "_"+ "hits")
486 end 486 end
487 487
488 def reset_cache_tracking_keys(date) 488 def reset_cache_tracking_keys(date)
489 - $redis.del(self.pq_key + "_" + date.to_s + "_"+ "misses")  
490 - $redis.del(self.pq_key + "_" + date.to_s + "_"+ "hits") 489 + $redis.del(self.pq_key + "_" + date.to_s + "_"+ "misses")
  490 + $redis.del(self.pq_key + "_" + date.to_s + "_"+ "hits")
491 end 491 end
492 492
493 493
494 def expire_prompt_cache_tracking_keys(date, expire_time = 24*60*60 * 3) # default expires in three days 494 def expire_prompt_cache_tracking_keys(date, expire_time = 24*60*60 * 3) # default expires in three days
495 - $redis.expire(self.pq_key + "_" + date.to_s + "_"+ "hits", expire_time)  
496 - $redis.expire(self.pq_key + "_" + date.to_s + "_"+ "misses", expire_time) 495 + $redis.expire(self.pq_key + "_" + date.to_s + "_"+ "hits", expire_time)
  496 + $redis.expire(self.pq_key + "_" + date.to_s + "_"+ "misses", expire_time)
497 end 497 end
498 498
499 499
500 def export_and_delete(type, options={}) 500 def export_and_delete(type, options={})
501 - delete_at = options.delete(:delete_at)  
502 - filename = export(type, options) 501 + delete_at = options.delete(:delete_at)
  502 + filename = export(type, options)
503 503
504 - File.send_at(delete_at, :delete, filename)  
505 - filename 504 + File.send_at(delete_at, :delete, filename)
  505 + filename
506 end 506 end
507 507
508 def export(type, options = {}) 508 def export(type, options = {})
509 509
510 case type 510 case type
511 when 'votes' 511 when 'votes'
512 - outfile = "ideamarketplace_#{self.id}_votes.csv" 512 + outfile = "ideamarketplace_#{self.id}_votes.csv"
513 513
514 - headers = ['Vote ID', 'Session ID', 'Question ID','Winner ID', 'Winner Text', 'Loser ID', 'Loser Text',  
515 - 'Prompt ID', 'Left Choice ID', 'Right Choice ID', 'Created at', 'Updated at', 'Appearance ID',  
516 - 'Response Time (s)', 'Missing Response Time Explanation', 'Session Identifier'] 514 + headers = ['Vote ID', 'Session ID', 'Question ID','Winner ID', 'Winner Text', 'Loser ID', 'Loser Text',
  515 + 'Prompt ID', 'Left Choice ID', 'Right Choice ID', 'Created at', 'Updated at', 'Appearance ID',
  516 + 'Response Time (s)', 'Missing Response Time Explanation', 'Session Identifier']
517 517
518 when 'ideas' 518 when 'ideas'
519 - outfile = "ideamarketplace_#{self.id}_ideas.csv" 519 + outfile = "ideamarketplace_#{self.id}_ideas.csv"
520 headers = ['Ideamarketplace ID','Idea ID', 'Idea Text', 'Wins', 'Losses', 'Times involved in Cant Decide', 'Score', 520 headers = ['Ideamarketplace ID','Idea ID', 'Idea Text', 'Wins', 'Losses', 'Times involved in Cant Decide', 'Score',
521 - 'User Submitted', 'Session ID', 'Created at', 'Last Activity', 'Active',  
522 - 'Appearances on Left', 'Appearances on Right'] 521 + 'User Submitted', 'Session ID', 'Created at', 'Last Activity', 'Active',
  522 + 'Appearances on Left', 'Appearances on Right']
523 when 'non_votes' 523 when 'non_votes'
524 outfile = "ideamarketplace_#{self.id}_non_votes.csv" 524 outfile = "ideamarketplace_#{self.id}_non_votes.csv"
525 headers = ['Record Type', 'Record ID', 'Session ID', 'Question ID','Left Choice ID', 'Left Choice Text', 525 headers = ['Record Type', 'Record ID', 'Session ID', 'Question ID','Left Choice ID', 'Left Choice Text',
526 - 'Right Choice ID', 'Right Choice Text', 'Prompt ID', 'Appearance ID', 'Reason',  
527 - 'Created at', 'Updated at', 'Response Time (s)', 'Missing Response Time Explanation', 'Session Identifier'] 526 + 'Right Choice ID', 'Right Choice Text', 'Prompt ID', 'Appearance ID', 'Reason',
  527 + 'Created at', 'Updated at', 'Response Time (s)', 'Missing Response Time Explanation', 'Session Identifier']
528 else 528 else
529 - raise "Unsupported export type: #{type}" 529 + raise "Unsupported export type: #{type}"
530 end 530 end
531 531
532 filename = File.join(File.expand_path(Rails.root), "public", "system", "exports", 532 filename = File.join(File.expand_path(Rails.root), "public", "system", "exports",
533 - self.id.to_s, Digest::SHA1.hexdigest(outfile + rand(10000000).to_s) + "_" + outfile) 533 + self.id.to_s, Digest::SHA1.hexdigest(outfile + rand(10000000).to_s) + "_" + outfile)
534 534
535 FileUtils::mkdir_p(File.dirname(filename)) 535 FileUtils::mkdir_p(File.dirname(filename))
536 csv_data = FasterCSV.open(filename, "w") do |csv| 536 csv_data = FasterCSV.open(filename, "w") do |csv|
537 - csv << headers 537 + csv << headers
538 538
539 case type 539 case type
540 when 'votes' 540 when 'votes'
541 541
542 self.votes.find_each(:include => [:prompt, :choice, :loser_choice, :voter]) do |v| 542 self.votes.find_each(:include => [:prompt, :choice, :loser_choice, :voter]) do |v|
543 - prompt = v.prompt  
544 - # these may not exist  
545 - loser_data = v.loser_choice.nil? ? "" : "'#{v.loser_choice.data.strip}'"  
546 - left_id = v.prompt.nil? ? "" : v.prompt.left_choice_id  
547 - right_id = v.prompt.nil? ? "" : v.prompt.right_choice_id 543 + prompt = v.prompt
  544 + # these may not exist
  545 + loser_data = v.loser_choice.nil? ? "" : "'#{v.loser_choice.data.strip}'"
  546 + left_id = v.prompt.nil? ? "" : v.prompt.left_choice_id
  547 + right_id = v.prompt.nil? ? "" : v.prompt.right_choice_id
548 548
549 - time_viewed = v.time_viewed.nil? ? "NA": v.time_viewed.to_f / 1000.0 549 + time_viewed = v.time_viewed.nil? ? "NA": v.time_viewed.to_f / 1000.0
550 550
551 - csv << [ v.id, v.voter_id, v.question_id, v.choice_id, "'#{v.choice.data.strip}'", v.loser_choice_id, loser_data,  
552 - v.prompt_id, left_id, right_id, v.created_at, v.updated_at, v.appearance_id,  
553 - time_viewed, v.missing_response_time_exp , v.voter.identifier]  
554 - end 551 + csv << [ v.id, v.voter_id, v.question_id, v.choice_id, "'#{v.choice.data.strip}'", v.loser_choice_id, loser_data,
  552 + v.prompt_id, left_id, right_id, v.created_at, v.updated_at, v.appearance_id,
  553 + time_viewed, v.missing_response_time_exp , v.voter.identifier]
  554 + end
555 555
556 when 'ideas' 556 when 'ideas'
557 self.choices.each do |c| 557 self.choices.each do |c|
558 user_submitted = c.user_created ? "TRUE" : "FALSE" 558 user_submitted = c.user_created ? "TRUE" : "FALSE"
559 - left_prompts_ids = c.prompts_on_the_left.ids_only  
560 - right_prompts_ids = c.prompts_on_the_right.ids_only 559 + left_prompts_ids = c.prompts_on_the_left.ids_only
  560 + right_prompts_ids = c.prompts_on_the_right.ids_only
561 561
562 - left_appearances = self.appearances.count(:conditions => {:prompt_id => left_prompts_ids})  
563 - right_appearances = self.appearances.count(:conditions => {:prompt_id => right_prompts_ids}) 562 + left_appearances = self.appearances.count(:conditions => {:prompt_id => left_prompts_ids})
  563 + right_appearances = self.appearances.count(:conditions => {:prompt_id => right_prompts_ids})
564 564
565 - num_skips = self.skips.count(:conditions => {:prompt_id => left_prompts_ids + right_prompts_ids}) 565 + num_skips = self.skips.count(:conditions => {:prompt_id => left_prompts_ids + right_prompts_ids})
566 566
567 - csv << [c.question_id, c.id, "'#{c.data.strip}'", c.wins, c.losses, num_skips, c.score,  
568 - user_submitted , c.creator_id, c.created_at, c.updated_at, c.active,  
569 - left_appearances, right_appearances] 567 + csv << [c.question_id, c.id, "'#{c.data.strip}'", c.wins, c.losses, num_skips, c.score,
  568 + user_submitted , c.creator_id, c.created_at, c.updated_at, c.active,
  569 + left_appearances, right_appearances]
570 end 570 end
571 when 'non_votes' 571 when 'non_votes'
572 -  
573 - self.appearances.find_each(:include => [:skip, :vote, :voter]) do |a|  
574 - # we only display skips and orphaned appearances in this csv file  
575 - unless a.vote.nil?  
576 - next  
577 - end  
578 -  
579 - #If no skip and no vote, this is an orphaned appearance  
580 - if a.skip.nil?  
581 - prompt = a.prompt  
582 - csv << [ "Orphaned Appearance", a.id, a.voter_id, a.question_id, a.prompt.left_choice.id, a.prompt.left_choice.data.strip,  
583 - a.prompt.right_choice.id, a.prompt.right_choice.data.strip, a.prompt_id, 'N/A', 'N/A',  
584 - a.created_at, a.updated_at, 'N/A', '', a.voter.identifier]  
585 -  
586 - else  
587 -  
588 - #If this appearance belongs to a skip, show information on the skip instead  
589 - s = a.skip  
590 - time_viewed = s.time_viewed.nil? ? "NA": s.time_viewed.to_f / 1000.0  
591 - prompt = s.prompt  
592 - csv << [ "Skip", s.id, s.skipper_id, s.question_id, s.prompt.left_choice.id, s.prompt.left_choice.data.strip,  
593 - s.prompt.right_choice.id, s.prompt.right_choice.data.strip, s.prompt_id, s.appearance_id, s.skip_reason,  
594 - s.created_at, s.updated_at, time_viewed , s.missing_response_time_exp, s.skipper.identifier]  
595 - end  
596 - end 572 +
  573 + self.appearances.find_each(:include => [:skip, :vote, :voter]) do |a|
  574 + # we only display skips and orphaned appearances in this csv file
  575 + unless a.vote.nil?
  576 + next
  577 + end
  578 +
  579 + #If no skip and no vote, this is an orphaned appearance
  580 + if a.skip.nil?
  581 + prompt = a.prompt
  582 + csv << [ "Orphaned Appearance", a.id, a.voter_id, a.question_id, a.prompt.left_choice.id, a.prompt.left_choice.data.strip,
  583 + a.prompt.right_choice.id, a.prompt.right_choice.data.strip, a.prompt_id, 'N/A', 'N/A',
  584 + a.created_at, a.updated_at, 'N/A', '', a.voter.identifier]
  585 +
  586 + else
  587 +
  588 + #If this appearance belongs to a skip, show information on the skip instead
  589 + s = a.skip
  590 + time_viewed = s.time_viewed.nil? ? "NA": s.time_viewed.to_f / 1000.0
  591 + prompt = s.prompt
  592 + csv << [ "Skip", s.id, s.skipper_id, s.question_id, s.prompt.left_choice.id, s.prompt.left_choice.data.strip,
  593 + s.prompt.right_choice.id, s.prompt.right_choice.data.strip, s.prompt_id, s.appearance_id, s.skip_reason,
  594 + s.created_at, s.updated_at, time_viewed , s.missing_response_time_exp, s.skipper.identifier]
  595 + end
  596 + end
597 end 597 end
598 598
599 end 599 end
600 600
601 if options[:response_type] == 'redis' 601 if options[:response_type] == 'redis'
602 602
603 - if options[:redis_key].nil?  
604 - raise "No :redis_key specified"  
605 - end  
606 - #The client should use blpop to listen for a key  
607 - #The client is responsible for deleting the redis key (auto expiration results failure in testing)  
608 - $redis.lpush(options[:redis_key], filename) 603 + if options[:redis_key].nil?
  604 + raise "No :redis_key specified"
  605 + end
  606 + #The client should use blpop to listen for a key
  607 + #The client is responsible for deleting the redis key (auto expiration results failure in testing)
  608 + $redis.lpush(options[:redis_key], filename)
609 #TODO implement response_type == 'email' for use by customers of the API (not local) 609 #TODO implement response_type == 'email' for use by customers of the API (not local)
610 end 610 end
611 611
@@ -614,17 +614,17 @@ class Question &lt; ActiveRecord::Base @@ -614,17 +614,17 @@ class Question &lt; ActiveRecord::Base
614 614
615 def get_first_unanswered_appearance(visitor, offset=0) 615 def get_first_unanswered_appearance(visitor, offset=0)
616 last_appearance = visitor.appearances.find(:first, 616 last_appearance = visitor.appearances.find(:first,
617 - :conditions => {:question_id => self.id,  
618 - :answerable_id => nil  
619 - },  
620 - :order => 'id ASC',  
621 - :offset => offset) 617 + :conditions => {:question_id => self.id,
  618 + :answerable_id => nil
  619 + },
  620 + :order => 'id ASC',
  621 + :offset => offset)
622 if last_appearance && !last_appearance.prompt.active? 622 if last_appearance && !last_appearance.prompt.active?
623 - last_appearance.valid_record = false  
624 - last_appearance.validity_information = "Deactivated Prompt"  
625 - last_appearance.save 623 + last_appearance.valid_record = false
  624 + last_appearance.validity_information = "Deactivated Prompt"
  625 + last_appearance.save
626 626
627 - return get_first_unanswered_appearance(visitor) 627 + return get_first_unanswered_appearance(visitor)
628 end 628 end
629 last_appearance 629 last_appearance
630 end 630 end