diff --git a/app/controllers/super_voters_controller.rb b/app/controllers/super_voters_controller.rb new file mode 100644 index 000000000..a1d82bbb4 --- /dev/null +++ b/app/controllers/super_voters_controller.rb @@ -0,0 +1,8 @@ +class SuperVotersController < ApplicationController + before_filter :member_only + + def index + @super_voters = SuperVoter.all + end +end + diff --git a/app/logical/post_vote_similarity.rb b/app/logical/post_vote_similarity.rb new file mode 100644 index 000000000..f83e6b820 --- /dev/null +++ b/app/logical/post_vote_similarity.rb @@ -0,0 +1,58 @@ +require "set" + +class PostVoteSimilarity + class Element + attr_reader :user_id, :score + + def initialize(user_id, score) + @user_id = user_id + @score = score + end + + def <=>(rhs) + score <=> rhs.score + end + end + + attr_reader :user_id + + def initialize(user_id) + @user_id = user_id + end + + # returns user ids with strong negative correlation + def calculate_negative(limit = 10) + posts0 = PostVote.negative_post_ids(user_id) + set = SortedSet.new + + PostVote.positive_user_ids.each do |uid| + posts1 = PostVote.positive_post_ids(uid) + set.add(Element.new(uid, calculate_with_cosine(posts0, posts1))) + end + + set.first(limit) + end + + # returns user ids with strong positive correlation + def calculate_positive(limit = 10) + posts0 = PostVote.positive_post_ids(user_id) + set = SortedSet.new + + PostVote.positive_user_ids.each do |uid| + posts1 = PostVote.positive_post_ids(uid) + set.add(Element.new(uid, calculate_with_cosine(posts0, posts1))) + end + + set.first(limit) + end + + def calculate_with_cosine(posts0, posts1) + a = (posts0 & posts1).size + div = Math.sqrt(posts0.size * posts1.size) + if div == 0 + 0 + else + a / div + end + end +end diff --git a/app/models/post_vote.rb b/app/models/post_vote.rb index bf4c79e94..d92f9fe20 100644 --- a/app/models/post_vote.rb +++ b/app/models/post_vote.rb @@ -12,6 +12,18 @@ class PostVote < ActiveRecord::Base where("created_at < ?", 30.days.ago).delete_all end + def self.positive_user_ids + select_values_sql("select user_id from post_votes where score > 0 group by user_id having count(*) > 100") + end + + def self.negative_post_ids(user_id) + select_values_sql("select post_id from post_votes where score < 0 and user_id = ?", user_id) + end + + def self.positive_post_ids(user_id) + select_values_sql("select post_id from post_votes where score > 0 and user_id = ?", user_id) + end + def score=(x) if x == "up" Post.where(:id => post_id).update_all("score = score + #{magnitude}, up_score = up_score + #{magnitude}") diff --git a/app/models/super_voter.rb b/app/models/super_voter.rb index 51e7b35d3..135c92333 100644 --- a/app/models/super_voter.rb +++ b/app/models/super_voter.rb @@ -13,18 +13,11 @@ class SuperVoter < ActiveRecord::Base def self.init! prune! - report = Reports::UserSimilarity.new(User.admins.first.id) - report.prime("post_vote_similarity") + report = PostVoteSimilarity.new(User.admins.first.id) - report.result.scan(/\S+/).in_groups_of(2).each do |user_id, score| - unless where("user_id = ?", user_id.to_i).exists? - create(:user_id => user_id) - end - end - - User.admins.each do |user| - unless where("user_id = ?", user.id).exists? - create(:user_id => user.id) + report.calculate_positive.each do |element| + unless where("user_id = ?", element.user_id).exists? + create(:user_id => element.user_id) end end end diff --git a/app/views/static/site_map.html.erb b/app/views/static/site_map.html.erb index 7e3d527c6..8651c95a2 100644 --- a/app/views/static/site_map.html.erb +++ b/app/views/static/site_map.html.erb @@ -109,6 +109,7 @@
  • <%= link_to("Signup", new_user_path) %>
  • <%= link_to("Terms of Service", terms_of_service_path) %>
  • <%= link_to("Upgrade Information", new_user_upgrade_path) %>
  • +
  • <%= link_to("Super Voters", super_voters_path)