discourse/spec/models/topic_hot_scores_spec.rb
Sam 690ff4499c
DEV: adjustments to hot algorithm (#25517)
1. Serial likers will just like a bunch of posts on the same topic, this will
heavily inflate hot score. To avoid artificial "heat" generated by one user only count
the first like on the topic within the recent_cutoff range per topic

2. When looking at recent topics prefer "unique likers", defer to total likes on
older topics cause we do not have an easy count for unique likers

3. Stop taking 1 off like_count, it is not needed - platforms like reddit
allow you to like own post so they need to remove it.
2024-02-01 17:11:40 +11:00

82 lines
2.8 KiB
Ruby

# frozen_string_literal: true
RSpec.describe TopicHotScore do
describe ".update_scores" do
fab!(:user)
fab!(:user2) { Fabricate(:user) }
fab!(:user3) { Fabricate(:user) }
it "can correctly update like counts and post counts and account for activity" do
freeze_time
TopicHotScore.create!(topic_id: -1, score: 0.0, recent_likes: 99, recent_posters: 0)
old_post = Fabricate(:post, created_at: 10.months.ago)
topic = old_post.topic
new_reply = Fabricate(:post, user: user, topic: topic, created_at: 4.hours.ago)
newer_reply = Fabricate(:post, user: user2, topic: topic, created_at: 1.hour.ago)
Fabricate(:post, user: user2, topic: topic, created_at: 1.minute.ago)
freeze_time(1.year.ago)
PostActionCreator.like(user, old_post)
freeze_time(1.year.from_now)
PostActionCreator.like(user2, new_reply)
PostActionCreator.like(user, newer_reply)
# user 3 likes two posts, but we should only count 1
# this avoids a single user from trivially inflating hot scores
PostActionCreator.like(user3, new_reply)
PostActionCreator.like(user3, newer_reply)
TopicHotScore.update_scores
hot_scoring = TopicHotScore.find_by(topic_id: topic.id)
expect(hot_scoring.recent_likes).to eq(3)
expect(hot_scoring.recent_posters).to eq(2)
expect(hot_scoring.recent_first_bumped_at).to eq_time(new_reply.created_at)
expect(hot_scoring.score).to be_within(0.001).of(1.771)
expect(TopicHotScore.find_by(topic_id: -1).recent_likes).to eq(0)
end
it "prefers recent_likes to topic like count for recent topics" do
freeze_time
topic = Fabricate(:topic, created_at: 1.hour.ago)
post = Fabricate(:post, topic: topic, created_at: 1.minute.ago)
PostActionCreator.like(user, post)
TopicHotScore.update_scores
score = TopicHotScore.find_by(topic_id: topic.id).score
topic.update!(like_count: 100)
TopicHotScore.update_scores
expect(TopicHotScore.find_by(topic_id: topic.id).score).to be_within(0.001).of(score)
end
it "can correctly set scores for topics" do
freeze_time
topic1 = Fabricate(:topic, like_count: 3, created_at: 2.weeks.ago)
topic2 = Fabricate(:topic, like_count: 10, created_at: 2.weeks.ago)
TopicHotScore.update_scores
expect(TopicHotScore.find_by(topic_id: topic1.id).score).to be_within(0.001).of(0.002)
expect(TopicHotScore.find_by(topic_id: topic2.id).score).to be_within(0.001).of(0.009)
freeze_time(6.weeks.from_now)
TopicHotScore.update_scores
expect(TopicHotScore.find_by(topic_id: topic1.id).score).to be_within(0.0001).of(0.0005)
expect(TopicHotScore.find_by(topic_id: topic2.id).score).to be_within(0.001).of(0.001)
end
end
end