diff --git a/app/models/question.rb b/app/models/question.rb index 78453c6..a35215c 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -80,26 +80,29 @@ class Question < ActiveRecord::Base end # adapted from ruby cookbook(2006): section 5-11 - def catchup_choose_prompt + def catchup_choose_prompt(num=1000) weighted = catchup_prompts_weights # Rand returns a number from 0 - 1, so weighted needs to be normalized - prompt = nil - - until prompt && prompt.active? - target = rand - left_choice_id = right_choice_id = nil - - weighted.each do |item, weight| - if target <= weight - left_choice_id, right_choice_id = item.split(", ") - break + generated_prompts = [] + + num.times do + prompt = nil + until prompt && prompt.active? + target = rand + left_choice_id = right_choice_id = nil + + weighted.each do |item, weight| + if target <= weight + left_choice_id, right_choice_id = item.split(", ") + break + end + target -= weight end - target -= weight + 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 }]) end - 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 }]) + generated_prompts.push prompt end - # check if prompt has two active choices here, maybe we can set this on the prompt level too? - prompt + generated_prompts end @@ -472,9 +475,18 @@ class Question < ActiveRecord::Base end def add_prompt_to_queue - prompt = self.catchup_choose_prompt - $redis.rpush(self.pq_key, prompt.id) - prompt + num_prompts = 1000 + # if less than 90% full, regenerate prompts + if $redis.llen(self.pq_key) < num_prompts * 0.9 + prompts = self.catchup_choose_prompt(num_prompts) + # clear list + $redis.ltrim(self.pq_key, 0, 0) + $redis.lpop(self.pq_key) + prompts.each do |prompt| + $redis.rpush(self.pq_key, prompt.id) + end + return prompts + end end def pop_prompt_queue diff --git a/lib/tasks/test_api.rake b/lib/tasks/test_api.rake index fbbf043..399b244 100644 --- a/lib/tasks/test_api.rake +++ b/lib/tasks/test_api.rake @@ -39,7 +39,7 @@ namespace :test_api do 1000.times do |n| puts "#{n} votes completed" if n % 100 == 0 question = Question.find(214) # test question change as needed - @prompt = question.catchup_choose_prompt + @prompt = question.catchup_choose_prompt(1).first @appearance = current_user.record_appearance(current_user.default_visitor, @prompt) direction = (rand(2) == 0) ? "left" : "right" diff --git a/spec/models/question_spec.rb b/spec/models/question_spec.rb index fc0c168..8eb2fe7 100644 --- a/spec/models/question_spec.rb +++ b/spec/models/question_spec.rb @@ -55,7 +55,7 @@ describe Question do end it "should choose an active prompt using catchup algorithm" do - prompt = @question.catchup_choose_prompt + prompt = @question.catchup_choose_prompt(1).first prompt.active?.should == true end @@ -242,7 +242,7 @@ describe Question do # Sanity check @catchup_q.choices.size.should == 100 - prompt = @catchup_q.catchup_choose_prompt + prompt = @catchup_q.catchup_choose_prompt(1).first prompt.active?.should == true end @@ -282,36 +282,10 @@ describe Question do prompt.should_not == nil prompt.active?.should == true end - it "should return prompts from the queue in FIFO order" do - @catchup_q.clear_prompt_queue - @catchup_q.pop_prompt_queue.should == nil - - prompt1 = @catchup_q.add_prompt_to_queue - prompt2 = @catchup_q.add_prompt_to_queue - prompt3 = @catchup_q.add_prompt_to_queue - - prompt_1 = @catchup_q.pop_prompt_queue - prompt_2 = @catchup_q.pop_prompt_queue - prompt_3 = @catchup_q.pop_prompt_queue - - - prompt_1.should == prompt1 - prompt_2.should == prompt2 - prompt_3.should == prompt3 - - # there is a small probability that the catchup algorithm - # choose two prompts that are indeed equal - prompt_1.should_not == prompt_2 - prompt_1.should_not == prompt_3 - prompt_2.should_not == prompt_3 - - - @catchup_q.pop_prompt_queue.should == nil - end it "should not return prompts from queue that are deactivated" do @catchup_q.clear_prompt_queue @catchup_q.pop_prompt_queue.should == nil - prompt1 = @catchup_q.add_prompt_to_queue + prompt1 = @catchup_q.add_prompt_to_queue.first prompt = Prompt.find(prompt1) prompt.left_choice.deactivate! -- libgit2 0.21.2