prune_db.rake 7.85 KB
namespace :prune_db do

  task :all => [:invalidate_votes_with_bad_response_times]

  desc "Fixes a mis-match between a vote's prompt_id and its appearance's prompt_id. Sets the appearance prompt_id to match the vote's prompt_id"
  task :fix_promptid_mismatch => :environment do
    bad_records = Vote.connection.select_all "
      SELECT
        votes.prompt_id, appearances.id appearance_id,
        appearances.prompt_id appearance_prompt_id
      FROM votes LEFT JOIN appearances
        ON (votes.id = appearances.answerable_id
            AND appearances.answerable_type = 'Vote')
      WHERE votes.prompt_id <> appearances.prompt_id"
    bad_records.each do |record|
      Appearance.update_all("prompt_id = #{record["prompt_id"]}", "id = #{record["appearance_id"]} AND prompt_id = #{record["appearance_prompt_id"]}")
    end
  end

  desc "Invalidates votes with bad response times"
  task :invalidate_votes_with_bad_response_times => :environment do
    badvotes = [] 
    #might want to optimize later to not start from the beginning each time
    STDOUT.sync = true
    Vote.find_each(:batch_size => 10000, :include => :appearance) do |v|
      next if v.nil? || v.appearance.nil?
      server_response_time = v.created_at.to_f - v.appearance.created_at.to_f
      if v.time_viewed && v.time_viewed/1000 > server_response_time 
        badvotes << v
        print "."
      end
    end
    puts "\n"

    if badvotes.any?

      badvotes.each do |v|
        v.time_viewed = nil
        v.missing_response_time_exp = "invalid"
        v.save!
      end
    else
      puts "Could not find any bad votes. Yay."
    end
  end

  task :associate_skips_with_appearances => :environment do
    skips_to_fix = Skip.find(:all, :conditions => {:appearance_id => nil})
    skips_to_fix.each do |skip|
      puts "Skip #{skip.id} : "
      possible_appearances = skip.skipper.appearances.find(:all, :conditions => {:prompt_id => skip.prompt_id})
      if possible_appearances.nil? || possible_appearances.empty?
        puts " I couldn't find any matches!"
        skip.delete
        next
      end
      if possible_appearances.size > 1
        puts " More than one possible appearance"
        possible_appearances.delete_if{|a| a.answered?}
        if possible_appearances.size > 1 || possible_appearances.size == 0
          puts"   And I couldn't narrow it down.... moving on"
          skip.delete
          next
        end
      end
      possible_appearance = possible_appearances.first
      if possible_appearance.answered?
        puts " This appearance has been answered already! Moving on" 
        skip.delete
      else
        puts " MATCH"
        skip.appearance_id = possible_appearance.id
        skip.save!
      end
    end
  end

  task(:move_vote_and_skip_ids_to_appearance => :environment) do
    #Vote.find_each do |v|
    #    @appearance = Appearance.find(v.appearance_id)
    #	  @appearance.answerable = v
    #	  @appearance.save
    #	  if v.id % 1000 == 0
    #		  puts v.id
    #	  end
    #      end
    Skip.find_each do |s|
      if s.appearance_id
        @appearance = Appearance.find(s.appearance_id)

        if @appearance.answerable
          puts "Appearance #{@appearance.id} has more than one skip!"
        else
          @appearance.answerable = s
          @appearance.save
        end
      end
    end
  end

  task(:remove_double_counted_votes_with_same_appearance => :environment) do 

    votes_with_no_appearance = []
    Vote.find_each(:include => :appearance) do |v|
      puts v.id if v.id % 1000 == 0

      votes_with_no_appearance << v if v.appearance.nil?
    end

    skips_with_no_appearance = []
    Skip.find_each(:include => :appearance) do |s|
      puts s.id if s.id % 1000 == 0

      skips_with_no_appearance << s if s.appearance.nil?
    end


    puts "#{votes_with_no_appearance.size} Votes"
    puts "#{skips_with_no_appearance.size} Skips"

    votes_with_no_appearance.each do |v|
      v.valid_record = false
      v.validity_information = "No associated appearance object"
      v.save!
    end

    skips_with_no_appearance.each do |s|
      s.valid_record = false
      s.validity_information = "No associated appearance object"
      s.save!
    end

  end

  #call this by doing rake prune_db:populate_seed_ideas['blahblah',questionnum], where blahblah is the filename
  task(:populate_seed_ideas, :args1, :args2, :needs => :environment) do | task, arguments|
  filename = arguments[:args1]
  question_num = arguments[:args2]

  puts filename
  puts question_num

  q = Question.find(question_num)
  creator_id = q.creator_id

  File.open(filename, "r") do |infile|
    while( data= infile.gets)
      c = Choice.new(:creator_id => creator_id,
                     :question_id => q.id,
                     :active => true,
                     :data => data.chomp)

      c.save
    end
  end

  end

  desc "Searches questions for orphaned votes (votes with no appearance) and marks them as invalid"
  task :invalidate_orphaned_votes => :environment do
    question_ids = ENV["question_ids"].split(/[\s,]+/)
    question_ids.each do |question_id|
      question = Question.find(question_id)

      orphaned_votes = Vote.find(:all,
                                 :select => "votes.id",
                                 :joins  => "LEFT JOIN appearances ON (votes.id = appearances.answerable_id AND answerable_type <> 'Skip')",
                                 :conditions => ["answerable_id IS NULL AND votes.valid_record = 1 AND votes.question_id = ?", question.id])
      puts "Question ##{question.id} has #{orphaned_votes.count} orphaned votes"
      orphaned_votes.each do |orphaned_vote_id|
        orphaned_vote = Vote.find(orphaned_vote_id.id)

        # attempt to find sibling vote
        # sibling vote is one that is valid has the same voter and prompt,
        # is associated with an appearance, and created within 10 seconds
        sibling_vote = nil
        votes = Vote.find(:all, :conditions => {:voter_id => orphaned_vote.voter_id, :prompt_id => orphaned_vote.prompt_id})
        votes.each do |vote|
          next if vote.id == orphaned_vote.id
          next if vote.created_at > orphaned_vote.created_at + 5.seconds
          next if vote.created_at < orphaned_vote.created_at - 5.seconds
          next if vote.appearance == nil
          sibling_vote = vote
          break
        end
        info = "Appearance XXXX already answered"
        if sibling_vote
          info = "Appearance #{sibling_vote.appearance.id} already answered"
        end
        orphaned_vote.update_attributes!(:valid_record => false, :validity_information => info)
      end
    end
  end

  desc "Updates cached values for losses and wins for choices."
  task :update_cached_losses_wins => :environment do
    Question.all.each do |question|
      question.choices.each do |choice|
        choice.reload
        true_losses = question.votes.count(:conditions => {:loser_choice_id => choice.id})
        true_wins = choice.votes.count
        Choice.update_counters choice.id,
          :losses => (true_losses - choice.losses), 
          :wins   => (true_wins - choice.wins)
        choice.reload
        choice.score = choice.compute_score
        choice.save(false)
      end
    end
  end

  desc "Update cached values for prompts on left and right for choices."
  task :update_cached_prompts_on_left_right => :environment do
    Question.all.each do |question|
      question.choices.each do |choice|
        choice.reload
        Choice.update_counters choice.id,
          :prompts_on_the_left_count => choice.prompts_on_the_left.count - choice.prompts_on_the_left_count,
          :prompts_on_the_right_count => choice.prompts_on_the_right.count - choice.prompts_on_the_right_count
      end
    end
  end

  desc "Recomputes scores for all choices."
  task :recompute_scores => :environment do
    Choice.find_each do |choice|
      choice.reload
      choice.score = choice.compute_score
      choice.save(false)
    end
  end

end