new algorithm for filter 'most active'
This commit is contained in:
@@ -122,14 +122,11 @@ class Debate < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def after_commented
|
def after_commented
|
||||||
save # updates the hot_score because there is a before_save
|
save # update cache when it has a new comment
|
||||||
end
|
end
|
||||||
|
|
||||||
def calculate_hot_score
|
def calculate_hot_score
|
||||||
self.hot_score = ScoreCalculator.hot_score(created_at,
|
self.hot_score = ScoreCalculator.hot_score(self)
|
||||||
cached_votes_total,
|
|
||||||
cached_votes_up,
|
|
||||||
comments_count)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def calculate_confidence_score
|
def calculate_confidence_score
|
||||||
|
|||||||
@@ -121,14 +121,11 @@ class Legislation::Proposal < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def after_commented
|
def after_commented
|
||||||
save # updates the hot_score because there is a before_save
|
save # update cache when it has a new comment
|
||||||
end
|
end
|
||||||
|
|
||||||
def calculate_hot_score
|
def calculate_hot_score
|
||||||
self.hot_score = ScoreCalculator.hot_score(created_at,
|
self.hot_score = ScoreCalculator.hot_score(self)
|
||||||
total_votes,
|
|
||||||
total_votes,
|
|
||||||
comments_count)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def calculate_confidence_score
|
def calculate_confidence_score
|
||||||
|
|||||||
@@ -166,14 +166,11 @@ class Proposal < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def after_commented
|
def after_commented
|
||||||
save # updates the hot_score because there is a before_save
|
save # update cache when it has a new comment
|
||||||
end
|
end
|
||||||
|
|
||||||
def calculate_hot_score
|
def calculate_hot_score
|
||||||
self.hot_score = ScoreCalculator.hot_score(created_at,
|
self.hot_score = ScoreCalculator.hot_score(self)
|
||||||
total_votes,
|
|
||||||
total_votes,
|
|
||||||
comments_count)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def calculate_confidence_score
|
def calculate_confidence_score
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ es:
|
|||||||
orders:
|
orders:
|
||||||
confidence_score: Mejor valorados
|
confidence_score: Mejor valorados
|
||||||
created_at: Nuevos
|
created_at: Nuevos
|
||||||
hot_score: Más activos hoy
|
hot_score: Más activos
|
||||||
most_commented: Más comentados
|
most_commented: Más comentados
|
||||||
relevance: Más relevantes
|
relevance: Más relevantes
|
||||||
recommendations: Recomendaciones
|
recommendations: Recomendaciones
|
||||||
@@ -346,7 +346,7 @@ es:
|
|||||||
orders:
|
orders:
|
||||||
confidence_score: Más apoyadas
|
confidence_score: Más apoyadas
|
||||||
created_at: Nuevas
|
created_at: Nuevas
|
||||||
hot_score: Más activas hoy
|
hot_score: Más activas
|
||||||
most_commented: Más comentadas
|
most_commented: Más comentadas
|
||||||
relevance: Más relevantes
|
relevance: Más relevantes
|
||||||
archival_date: Archivadas
|
archival_date: Archivadas
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
module ScoreCalculator
|
module ScoreCalculator
|
||||||
|
|
||||||
EPOC = Time.new(2015, 6, 15).in_time_zone
|
def self.hot_score(resource)
|
||||||
COMMENT_WEIGHT = 1.0 / 5 # 1 positive vote / x comments
|
return 0 unless resource.created_at
|
||||||
TIME_UNIT = 24.hours.to_f
|
|
||||||
|
|
||||||
def self.hot_score(date, votes_total, votes_up, comments_count)
|
period = [
|
||||||
total = (votes_total + COMMENT_WEIGHT * comments_count).to_f
|
Setting['hot_score_period_in_days'].to_i,
|
||||||
ups = (votes_up + COMMENT_WEIGHT * comments_count).to_f
|
((Time.current - resource.created_at) / 1.day).ceil
|
||||||
downs = total - ups
|
].min
|
||||||
score = ups - downs
|
|
||||||
offset = Math.log([score.abs, 1].max, 10) * (ups / [total, 1].max)
|
|
||||||
sign = score <=> 0
|
|
||||||
seconds = ((date || Time.current) - EPOC).to_f
|
|
||||||
|
|
||||||
(((offset * sign) + (seconds / TIME_UNIT)) * 10000000).round
|
votes_total = resource.votes_for.where("created_at >= ?", period.days.ago).count
|
||||||
|
votes_up = resource.get_upvotes.where("created_at >= ?", period.days.ago).count
|
||||||
|
votes_down = votes_total - votes_up
|
||||||
|
votes_score = votes_up - votes_down
|
||||||
|
|
||||||
|
(votes_score.to_f / period).round
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.confidence_score(votes_total, votes_up)
|
def self.confidence_score(votes_total, votes_up)
|
||||||
|
|||||||
@@ -13,4 +13,15 @@ namespace :votes do
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
desc "Resets hot_score to its new value"
|
||||||
|
task reset_hot_score: :environment do
|
||||||
|
models = [Debate, Proposal, Legislation::Proposal]
|
||||||
|
|
||||||
|
models.each do |model|
|
||||||
|
model.find_each do |resource|
|
||||||
|
resource.save
|
||||||
|
print "."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -236,57 +236,91 @@ describe Debate do
|
|||||||
describe '#hot_score' do
|
describe '#hot_score' do
|
||||||
let(:now) { Time.current }
|
let(:now) { Time.current }
|
||||||
|
|
||||||
it "increases for newer debates" do
|
it "period is correctly calculated to get exact votes per day" do
|
||||||
old = create(:debate, :with_hot_score, created_at: now - 1.day)
|
new_debate = create(:debate, created_at: 23.hours.ago)
|
||||||
new = create(:debate, :with_hot_score, created_at: now)
|
2.times { new_debate.vote_by(voter: create(:user), vote: "yes") }
|
||||||
expect(new.hot_score).to be > old.hot_score
|
expect(new_debate.hot_score).to be 2
|
||||||
|
|
||||||
|
old_debate = create(:debate, created_at: 25.hours.ago)
|
||||||
|
2.times { old_debate.vote_by(voter: create(:user), vote: "yes") }
|
||||||
|
expect(old_debate.hot_score).to be 1
|
||||||
|
|
||||||
|
older_debate = create(:debate, created_at: 49.hours.ago)
|
||||||
|
3.times { older_debate.vote_by(voter: create(:user), vote: "yes") }
|
||||||
|
expect(old_debate.hot_score).to be 1
|
||||||
end
|
end
|
||||||
|
|
||||||
it "increases for debates with more comments" do
|
it "remains the same for not voted debates" do
|
||||||
more_comments = create(:debate, :with_hot_score, created_at: now, comments_count: 25)
|
new = create(:debate, created_at: now)
|
||||||
less_comments = create(:debate, :with_hot_score, created_at: now, comments_count: 1)
|
old = create(:debate, created_at: 1.day.ago)
|
||||||
expect(more_comments.hot_score).to be > less_comments.hot_score
|
older = create(:debate, created_at: 2.month.ago)
|
||||||
|
expect(new.hot_score).to be 0
|
||||||
|
expect(old.hot_score).to be 0
|
||||||
|
expect(older.hot_score).to be 0
|
||||||
end
|
end
|
||||||
|
|
||||||
it "increases for debates with more positive votes" do
|
it "increases 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)
|
more_positive_votes = create(:debate)
|
||||||
less_likes = create(:debate, :with_hot_score, created_at: now, cached_votes_total: 10, cached_votes_up: 1)
|
2.times { more_positive_votes.vote_by(voter: create(:user), vote: "yes") }
|
||||||
expect(more_likes.hot_score).to be > less_likes.hot_score
|
|
||||||
|
less_positive_votes = create(:debate)
|
||||||
|
less_positive_votes.vote_by(voter: create(:user), vote: "yes")
|
||||||
|
|
||||||
|
expect(more_positive_votes.hot_score).to be > less_positive_votes.hot_score
|
||||||
end
|
end
|
||||||
|
|
||||||
it "increases for debates with more confidence" do
|
it "increases for debates with the same amount of positive votes within less days" do
|
||||||
more_confidence = create(:debate, :with_hot_score, created_at: now, cached_votes_total: 1000, cached_votes_up: 700)
|
newer_debate = create(:debate, created_at: now)
|
||||||
less_confidence = create(:debate, :with_hot_score, created_at: now, cached_votes_total: 10, cached_votes_up: 9)
|
5.times { newer_debate.vote_by(voter: create(:user), vote: "yes") }
|
||||||
expect(more_confidence.hot_score).to be > less_confidence.hot_score
|
|
||||||
|
older_debate = create(:debate, created_at: 1.day.ago)
|
||||||
|
5.times { older_debate.vote_by(voter: create(:user), vote: "yes") }
|
||||||
|
|
||||||
|
expect(newer_debate.hot_score).to be > older_debate.hot_score
|
||||||
end
|
end
|
||||||
|
|
||||||
it "decays in older debates, even if they have more votes" do
|
it "decreases for debates with more negative votes" do
|
||||||
older_more_voted = create(:debate, :with_hot_score, created_at: now - 5.days, cached_votes_total: 1000, cached_votes_up: 900)
|
more_negative_votes = create(:debate)
|
||||||
new_less_voted = create(:debate, :with_hot_score, created_at: now, cached_votes_total: 10, cached_votes_up: 9)
|
5.times { more_negative_votes.vote_by(voter: create(:user), vote: "yes") }
|
||||||
expect(new_less_voted.hot_score).to be > older_more_voted.hot_score
|
3.times { more_negative_votes.vote_by(voter: create(:user), vote: "no") }
|
||||||
|
|
||||||
|
less_negative_votes = create(:debate)
|
||||||
|
5.times { less_negative_votes.vote_by(voter: create(:user), vote: "yes") }
|
||||||
|
2.times { less_negative_votes.vote_by(voter: create(:user), vote: "no") }
|
||||||
|
|
||||||
|
expect(more_negative_votes.hot_score).to be < less_negative_votes.hot_score
|
||||||
|
end
|
||||||
|
|
||||||
|
it "increases for debates voted within the period (last month by default)" do
|
||||||
|
newer_debate = create(:debate, created_at: 2.months.ago)
|
||||||
|
20.times { create(:vote, votable: newer_debate, created_at: 3.days.ago) }
|
||||||
|
|
||||||
|
older_debate = create(:debate, created_at: 2.months.ago)
|
||||||
|
20.times { create(:vote, votable: older_debate, created_at: 40.days.ago) }
|
||||||
|
|
||||||
|
expect(newer_debate.hot_score).to be > older_debate.hot_score
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'actions which affect it' do
|
describe 'actions which affect it' do
|
||||||
let(:debate) { create(:debate, :with_hot_score) }
|
|
||||||
|
|
||||||
it "increases with likes" do
|
let(:debate) { create(:debate) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
5.times { debate.vote_by(voter: create(:user), vote: "yes") }
|
||||||
|
2.times { debate.vote_by(voter: create(:user), vote: "no") }
|
||||||
|
end
|
||||||
|
|
||||||
|
it "increases with positive votes" do
|
||||||
previous = debate.hot_score
|
previous = debate.hot_score
|
||||||
5.times { debate.register_vote(create(:user), true) }
|
3.times { debate.vote_by(voter: create(:user), vote: "yes") }
|
||||||
expect(previous).to be < debate.hot_score
|
expect(previous).to be < debate.hot_score
|
||||||
end
|
end
|
||||||
|
|
||||||
it "decreases with dislikes" do
|
it "decreases with negative votes" do
|
||||||
debate.register_vote(create(:user), true)
|
|
||||||
previous = debate.hot_score
|
previous = debate.hot_score
|
||||||
3.times { debate.register_vote(create(:user), false) }
|
3.times { debate.vote_by(voter: create(:user), vote: "no") }
|
||||||
expect(previous).to be > debate.hot_score
|
expect(previous).to be > debate.hot_score
|
||||||
end
|
end
|
||||||
|
|
||||||
it "increases with comments" do
|
|
||||||
previous = debate.hot_score
|
|
||||||
25.times{ Comment.create(user: create(:user), commentable: debate, body: 'foobarbaz') }
|
|
||||||
expect(previous).to be < debate.reload.hot_score
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -27,4 +27,82 @@ describe Legislation::Proposal do
|
|||||||
expect(proposal).not_to be_valid
|
expect(proposal).not_to be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#hot_score' do
|
||||||
|
let(:now) { Time.current }
|
||||||
|
|
||||||
|
it "period is correctly calculated to get exact votes per day" do
|
||||||
|
new_proposal = create(:legislation_proposal, created_at: 23.hours.ago)
|
||||||
|
2.times { new_proposal.vote_by(voter: create(:user), vote: "yes") }
|
||||||
|
expect(new_proposal.hot_score).to be 2
|
||||||
|
|
||||||
|
old_proposal = create(:legislation_proposal, created_at: 25.hours.ago)
|
||||||
|
2.times { old_proposal.vote_by(voter: create(:user), vote: "yes") }
|
||||||
|
expect(old_proposal.hot_score).to be 1
|
||||||
|
|
||||||
|
older_proposal = create(:legislation_proposal, created_at: 49.hours.ago)
|
||||||
|
3.times { older_proposal.vote_by(voter: create(:user), vote: "yes") }
|
||||||
|
expect(old_proposal.hot_score).to be 1
|
||||||
|
end
|
||||||
|
|
||||||
|
it "remains the same for not voted proposals" do
|
||||||
|
new = create(:legislation_proposal, created_at: now)
|
||||||
|
old = create(:legislation_proposal, created_at: 1.day.ago)
|
||||||
|
older = create(:legislation_proposal, created_at: 2.month.ago)
|
||||||
|
expect(new.hot_score).to be 0
|
||||||
|
expect(old.hot_score).to be 0
|
||||||
|
expect(older.hot_score).to be 0
|
||||||
|
end
|
||||||
|
|
||||||
|
it "increases for proposals with more positive votes" do
|
||||||
|
more_positive_votes = create(:legislation_proposal)
|
||||||
|
2.times { more_positive_votes.vote_by(voter: create(:user), vote: "yes") }
|
||||||
|
|
||||||
|
less_positive_votes = create(:legislation_proposal)
|
||||||
|
less_positive_votes.vote_by(voter: create(:user), vote: "yes")
|
||||||
|
|
||||||
|
expect(more_positive_votes.hot_score).to be > less_positive_votes.hot_score
|
||||||
|
end
|
||||||
|
|
||||||
|
it "increases for proposals with the same amount of positive votes within less days" do
|
||||||
|
newer_proposal = create(:legislation_proposal, created_at: now)
|
||||||
|
5.times { newer_proposal.vote_by(voter: create(:user), vote: "yes") }
|
||||||
|
|
||||||
|
older_proposal = create(:legislation_proposal, created_at: 1.day.ago)
|
||||||
|
5.times { older_proposal.vote_by(voter: create(:user), vote: "yes") }
|
||||||
|
|
||||||
|
expect(newer_proposal.hot_score).to be > older_proposal.hot_score
|
||||||
|
end
|
||||||
|
|
||||||
|
it "increases for proposals voted within the period (last month by default)" do
|
||||||
|
newer_proposal = create(:legislation_proposal, created_at: 2.months.ago)
|
||||||
|
20.times { create(:vote, votable: newer_proposal, created_at: 3.days.ago) }
|
||||||
|
|
||||||
|
older_proposal = create(:legislation_proposal, created_at: 2.months.ago)
|
||||||
|
20.times { create(:vote, votable: older_proposal, created_at: 40.days.ago) }
|
||||||
|
|
||||||
|
expect(newer_proposal.hot_score).to be > older_proposal.hot_score
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'actions which affect it' do
|
||||||
|
|
||||||
|
let(:proposal) { create(:legislation_proposal) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
5.times { proposal.vote_by(voter: create(:user), vote: "yes") }
|
||||||
|
2.times { proposal.vote_by(voter: create(:user), vote: "no") }
|
||||||
|
end
|
||||||
|
|
||||||
|
it "increases with positive votes" do
|
||||||
|
previous = proposal.hot_score
|
||||||
|
3.times { proposal.vote_by(voter: create(:user), vote: "yes") }
|
||||||
|
expect(previous).to be < proposal.hot_score
|
||||||
|
end
|
||||||
|
|
||||||
|
it "decreases with negative votes" do
|
||||||
|
previous = proposal.hot_score
|
||||||
|
3.times { proposal.vote_by(voter: create(:user), vote: "no") }
|
||||||
|
expect(previous).to be > proposal.hot_score
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -254,49 +254,78 @@ describe Proposal do
|
|||||||
describe '#hot_score' do
|
describe '#hot_score' do
|
||||||
let(:now) { Time.current }
|
let(:now) { Time.current }
|
||||||
|
|
||||||
it "increases for newer proposals" do
|
it "period is correctly calculated to get exact votes per day" do
|
||||||
old = create(:proposal, :with_hot_score, created_at: now - 1.day)
|
new_proposal = create(:proposal, created_at: 23.hours.ago)
|
||||||
new = create(:proposal, :with_hot_score, created_at: now)
|
2.times { new_proposal.vote_by(voter: create(:user), vote: "yes") }
|
||||||
expect(new.hot_score).to be > old.hot_score
|
expect(new_proposal.hot_score).to be 2
|
||||||
|
|
||||||
|
old_proposal = create(:proposal, created_at: 25.hours.ago)
|
||||||
|
2.times { old_proposal.vote_by(voter: create(:user), vote: "yes") }
|
||||||
|
expect(old_proposal.hot_score).to be 1
|
||||||
|
|
||||||
|
older_proposal = create(:proposal, created_at: 49.hours.ago)
|
||||||
|
3.times { older_proposal.vote_by(voter: create(:user), vote: "yes") }
|
||||||
|
expect(old_proposal.hot_score).to be 1
|
||||||
end
|
end
|
||||||
|
|
||||||
it "increases for proposals with more comments" do
|
it "remains the same for not voted proposals" do
|
||||||
more_comments = create(:proposal, :with_hot_score, created_at: now, comments_count: 25)
|
new = create(:proposal, created_at: now)
|
||||||
less_comments = create(:proposal, :with_hot_score, created_at: now, comments_count: 1)
|
old = create(:proposal, created_at: 1.day.ago)
|
||||||
expect(more_comments.hot_score).to be > less_comments.hot_score
|
older = create(:proposal, created_at: 2.month.ago)
|
||||||
|
expect(new.hot_score).to be 0
|
||||||
|
expect(old.hot_score).to be 0
|
||||||
|
expect(older.hot_score).to be 0
|
||||||
end
|
end
|
||||||
|
|
||||||
it "increases for proposals with more positive votes" do
|
it "increases for proposals with more positive votes" do
|
||||||
more_likes = create(:proposal, :with_hot_score, created_at: now, cached_votes_up: 5)
|
more_positive_votes = create(:proposal)
|
||||||
less_likes = create(:proposal, :with_hot_score, created_at: now, cached_votes_up: 1)
|
2.times { more_positive_votes.vote_by(voter: create(:user), vote: "yes") }
|
||||||
expect(more_likes.hot_score).to be > less_likes.hot_score
|
|
||||||
|
less_positive_votes = create(:proposal)
|
||||||
|
less_positive_votes.vote_by(voter: create(:user), vote: "yes")
|
||||||
|
|
||||||
|
expect(more_positive_votes.hot_score).to be > less_positive_votes.hot_score
|
||||||
end
|
end
|
||||||
|
|
||||||
it "increases for proposals with more confidence" do
|
it "increases for proposals with the same amount of positive votes within less days" do
|
||||||
more_confidence = create(:proposal, :with_hot_score, created_at: now, cached_votes_up: 700)
|
newer_proposal = create(:proposal, created_at: now)
|
||||||
less_confidence = create(:proposal, :with_hot_score, created_at: now, cached_votes_up: 9)
|
5.times { newer_proposal.vote_by(voter: create(:user), vote: "yes") }
|
||||||
expect(more_confidence.hot_score).to be > less_confidence.hot_score
|
|
||||||
|
older_proposal = create(:proposal, created_at: 1.day.ago)
|
||||||
|
5.times { older_proposal.vote_by(voter: create(:user), vote: "yes") }
|
||||||
|
|
||||||
|
expect(newer_proposal.hot_score).to be > older_proposal.hot_score
|
||||||
end
|
end
|
||||||
|
|
||||||
it "decays in older proposals, even if they have more votes" do
|
it "increases for proposals voted within the period (last month by default)" do
|
||||||
older_more_voted = create(:proposal, :with_hot_score, created_at: now - 5.days, cached_votes_up: 900)
|
newer_proposal = create(:proposal, created_at: 2.months.ago)
|
||||||
new_less_voted = create(:proposal, :with_hot_score, created_at: now, cached_votes_up: 9)
|
20.times { create(:vote, votable: newer_proposal, created_at: 3.days.ago) }
|
||||||
expect(new_less_voted.hot_score).to be > older_more_voted.hot_score
|
|
||||||
|
older_proposal = create(:proposal, created_at: 2.months.ago)
|
||||||
|
20.times { create(:vote, votable: older_proposal, created_at: 40.days.ago) }
|
||||||
|
|
||||||
|
expect(newer_proposal.hot_score).to be > older_proposal.hot_score
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'actions which affect it' do
|
describe 'actions which affect it' do
|
||||||
let(:proposal) { create(:proposal, :with_hot_score) }
|
|
||||||
|
|
||||||
it "increases with votes" do
|
let(:proposal) { create(:proposal) }
|
||||||
previous = proposal.hot_score
|
|
||||||
5.times { proposal.register_vote(create(:user, verified_at: Time.current), true) }
|
before do
|
||||||
expect(previous).to be < proposal.reload.hot_score
|
5.times { proposal.vote_by(voter: create(:user), vote: "yes") }
|
||||||
|
2.times { proposal.vote_by(voter: create(:user), vote: "no") }
|
||||||
end
|
end
|
||||||
|
|
||||||
it "increases with comments" do
|
it "increases with positive votes" do
|
||||||
previous = proposal.hot_score
|
previous = proposal.hot_score
|
||||||
25.times{ Comment.create(user: create(:user), commentable: proposal, body: 'foobarbaz') }
|
3.times { proposal.vote_by(voter: create(:user), vote: "yes") }
|
||||||
expect(previous).to be < proposal.reload.hot_score
|
expect(previous).to be < proposal.hot_score
|
||||||
|
end
|
||||||
|
|
||||||
|
it "decreases with negative votes" do
|
||||||
|
previous = proposal.hot_score
|
||||||
|
3.times { proposal.vote_by(voter: create(:user), vote: "no") }
|
||||||
|
expect(previous).to be > proposal.hot_score
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user