Adds initial hot score implementation for debates

This commit is contained in:
kikito
2015-09-04 12:34:17 +02:00
parent 9f970568ac
commit fba4f1fade
3 changed files with 58 additions and 1 deletions

View File

@@ -21,6 +21,8 @@ class Debate < ActiveRecord::Base
before_validation :sanitize_description before_validation :sanitize_description
before_validation :sanitize_tag_list before_validation :sanitize_tag_list
before_save :calculate_hot_score
scope :sorted_for_moderation, -> { order(flags_count: :desc, updated_at: :desc) } scope :sorted_for_moderation, -> { order(flags_count: :desc, updated_at: :desc) }
scope :pending_flag_review, -> { where(ignored_flag_at: nil, hidden_at: nil) } scope :pending_flag_review, -> { where(ignored_flag_at: nil, hidden_at: nil) }
scope :with_ignored_flag, -> { where("ignored_flag_at IS NOT NULL AND hidden_at IS NULL") } scope :with_ignored_flag, -> { where("ignored_flag_at IS NOT NULL AND hidden_at IS NULL") }
@@ -102,6 +104,24 @@ class Debate < ActiveRecord::Base
update(ignored_flag_at: Time.now) update(ignored_flag_at: Time.now)
end end
def calculate_hot_score
z = 1.96 # Normal distribution with a confidence of 0.95
time_unit = 12.hours
start = Time.new(2015, 6, 15)
n = cached_votes_total + comments_count / 3
pos = cached_votes_up + comments_count / 3
phat = 1.0 * pos / n
weigted_score = n == 0 ? 0 :
(phat + z*z/(2*n) - z * Math.sqrt((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n)
age_in_units = ((created_at || Time.now) - start) / time_unit
self.hot_score = (age_in_units**3 + weigted_score * 1000).round
end
protected protected
def sanitize_description def sanitize_description
@@ -111,5 +131,4 @@ class Debate < ActiveRecord::Base
def sanitize_tag_list def sanitize_tag_list
self.tag_list = TagSanitizer.new.sanitize_tag_list(self.tag_list) self.tag_list = TagSanitizer.new.sanitize_tag_list(self.tag_list)
end end
end end

View File

@@ -71,6 +71,10 @@ FactoryGirl.define do
Flag.flag(FactoryGirl.create(:user), debate) Flag.flag(FactoryGirl.create(:user), debate)
end end
end end
trait :with_hot_score do
before(:save) { |d| d.calculate_hot_score }
end
end end
factory :vote do factory :vote do

View File

@@ -181,4 +181,38 @@ describe Debate do
end end
end end
describe '#hot_score' do
let(:now) { Time.now }
it "gets bigger for newer debates" do
old = create(:debate, :with_hot_score, created_at: now - 1.day)
new = create(:debate, :with_hot_score, created_at: now)
expect(new.hot_score).to be > old.hot_score
end
it "gets bigger for debates with more comments" do
more_comments = create(:debate, :with_hot_score, created_at: now, comments_count: 10)
less_comments = create(:debate, :with_hot_score, created_at: now, comments_count: 1)
expect(more_comments.hot_score).to be > less_comments.hot_score
end
it "gets bigger for debates with more positive votes" do
more_likes = create(:debate, :with_hot_score, created_at: now, cached_votes_total: 10, cached_votes_up: 5)
less_likes = create(:debate, :with_hot_score, created_at: now, cached_votes_total: 10, cached_votes_up: 1)
expect(more_likes.hot_score).to be > less_likes.hot_score
end
it "gets bigger for debates with more confidence" do
more_confidence = create(:debate, :with_hot_score, created_at: now, cached_votes_total: 1000, cached_votes_up: 700)
less_confidence = create(:debate, :with_hot_score, created_at: now, cached_votes_total: 10, cached_votes_up: 9)
expect(more_confidence.hot_score).to be > less_confidence.hot_score
end
it "decays older debates, even if they have more votes" do
older_more_voted = create(:debate, :with_hot_score, created_at: now - 2.days, cached_votes_total: 1000, cached_votes_up: 900)
new_less_voted = create(:debate, :with_hot_score, created_at: now, cached_votes_total: 10, cached_votes_up: 9)
expect(new_less_voted.hot_score).to be > older_more_voted.hot_score
end
end
end end