mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-27 17:46:05 -05:00
Merge pull request #3968 from techAPJ/top-topics
FEATURE: make top criteria formula multipliers controlled by site setting
This commit is contained in:
commit
590adb5899
4 changed files with 126 additions and 5 deletions
|
@ -147,6 +147,15 @@ class TopTopic < ActiveRecord::Base
|
|||
|
||||
def self.compute_top_score_for(period)
|
||||
|
||||
log_views_multiplier = SiteSetting.top_topics_formula_log_views_multiplier.to_f
|
||||
log_views_multiplier = 2 if log_views_multiplier == 0
|
||||
|
||||
first_post_likes_multiplier = SiteSetting.top_topics_formula_first_post_likes_multiplier.to_f
|
||||
first_post_likes_multiplier = 0.5 if first_post_likes_multiplier == 0
|
||||
|
||||
least_likes_per_post_multiplier = SiteSetting.top_topics_formula_least_likes_per_post_multiplier.to_f
|
||||
least_likes_per_post_multiplier = 3 if least_likes_per_post_multiplier == 0
|
||||
|
||||
if period == :all
|
||||
top_topics = "(
|
||||
SELECT t.like_count all_likes_count,
|
||||
|
@ -167,11 +176,11 @@ class TopTopic < ActiveRecord::Base
|
|||
WITH top AS (
|
||||
SELECT CASE
|
||||
WHEN #{time_filter} THEN 0
|
||||
ELSE log(GREATEST(#{period}_views_count, 1)) * 2 +
|
||||
#{period}_op_likes_count * 0.5 +
|
||||
ELSE log(GREATEST(#{period}_views_count, 1)) * #{log_views_multiplier} +
|
||||
#{period}_op_likes_count * #{first_post_likes_multiplier} +
|
||||
CASE WHEN #{period}_likes_count > 0 AND #{period}_posts_count > 0
|
||||
THEN
|
||||
LEAST(#{period}_likes_count / #{period}_posts_count, 3)
|
||||
LEAST(#{period}_likes_count / #{period}_posts_count, #{least_likes_per_post_multiplier})
|
||||
ELSE 0
|
||||
END +
|
||||
CASE WHEN topics.posts_count < 10 THEN
|
||||
|
|
|
@ -945,6 +945,10 @@ en:
|
|||
verbose_localization: "Show extended localization tips in the UI"
|
||||
previous_visit_timeout_hours: "How long a visit lasts before we consider it the 'previous' visit, in hours"
|
||||
|
||||
top_topics_formula_log_views_multiplier: "value of log views multiplier (n) in top topics formula: `log(views_count) * (n) + op_likes_count * 0.5 + LEAST(likes_count / posts_count, 3) + 10 + log(posts_count)`"
|
||||
top_topics_formula_first_post_likes_multiplier: "value of first post likes multiplier (n) in top topics formula: `log(views_count) * 2 + op_likes_count * (n) + LEAST(likes_count / posts_count, 3) + 10 + log(posts_count)`"
|
||||
top_topics_formula_least_likes_per_post_multiplier: "value of least likes per post multiplier (n) in top topics formula: `log(views_count) * 2 + op_likes_count * 0.5 + LEAST(likes_count / posts_count, (n)) + 10 + log(posts_count)`"
|
||||
|
||||
rate_limit_create_topic: "After creating a topic, users must wait (n) seconds before creating another topic."
|
||||
rate_limit_create_post: "After posting, users must wait (n) seconds before creating another post."
|
||||
rate_limit_new_user_create_topic: "After creating a topic, new users must wait (n) seconds before creating another topic."
|
||||
|
|
|
@ -803,6 +803,15 @@ developer:
|
|||
verbose_localization:
|
||||
default: false
|
||||
client: true
|
||||
top_topics_formula_log_views_multiplier:
|
||||
default: 2
|
||||
min: 0
|
||||
top_topics_formula_first_post_likes_multiplier:
|
||||
default: 0.5
|
||||
min: 0
|
||||
top_topics_formula_least_likes_per_post_multiplier:
|
||||
default: 3
|
||||
min: 0
|
||||
migrate_to_new_scheme:
|
||||
hidden: true
|
||||
default: false
|
||||
|
|
|
@ -38,9 +38,108 @@ describe TopTopic do
|
|||
it "should have top topics" do
|
||||
expect(TopTopic.pluck(:topic_id)).to match_array([t1.id, t2.id])
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
describe "#compute_top_score_for" do
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:coding_horror) { Fabricate(:coding_horror) }
|
||||
|
||||
let!(:topic_1) { Fabricate(:topic, posts_count: 10, like_count: 28) }
|
||||
let!(:t1_post_1) { Fabricate(:post, topic: topic_1, like_count: 28, post_number: 1)}
|
||||
|
||||
let!(:topic_2) { Fabricate(:topic, posts_count: 10, like_count: 20) }
|
||||
let!(:t2_post_1) { Fabricate(:post, topic: topic_2, like_count: 10, post_number: 1) }
|
||||
let!(:t2_post_2) { Fabricate(:post, topic: topic_2, like_count: 10) }
|
||||
|
||||
let!(:topic_3) { Fabricate(:topic, posts_count: 10) }
|
||||
let!(:t3_post_1) { Fabricate(:post, topic_id: topic_3.id) }
|
||||
let!(:t3_view_1) { TopicViewItem.add(topic_3.id, '127.0.0.1', user) }
|
||||
let!(:t3_view_2) { TopicViewItem.add(topic_3.id, '127.0.0.2', coding_horror) }
|
||||
|
||||
# Note: all topics has 10 posts so we can skip "0 - ((10 - topics.posts_count) / 20) * #{period}_op_likes_count" calculation
|
||||
|
||||
it "should compute top score" do
|
||||
# Default Formula: log(views_count) * {2} + op_likes_count * {0.5} + LEAST(likes_count / posts_count, {3}) + 10 + log(posts_count)
|
||||
#
|
||||
# topic_1 => 0 + 14 + 3 + 10 + 0 => 27
|
||||
# topic_2 => 0 + 5 + 3 + 10 + 0.301029995664 => 18.301029995664
|
||||
# topic_3 => 0.602059991328 + 0 + 0 + 10 + 0 => 10.602059991328
|
||||
|
||||
TopTopic.refresh!
|
||||
top_topics = TopTopic.all
|
||||
|
||||
expect(top_topics.where(topic_id: topic_1.id).pluck(:yearly_score).first).to eq(27)
|
||||
expect(top_topics.where(topic_id: topic_2.id).pluck(:yearly_score).first).to eq(18.301029995664)
|
||||
expect(top_topics.where(topic_id: topic_3.id).pluck(:yearly_score).first).to eq(10.602059991328)
|
||||
|
||||
# when 'top_topics_formula_log_views_multiplier' setting is changed
|
||||
SiteSetting.top_topics_formula_log_views_multiplier = 4
|
||||
SiteSetting.top_topics_formula_first_post_likes_multiplier = 0.5 # unchanged
|
||||
SiteSetting.top_topics_formula_least_likes_per_post_multiplier = 3 # unchanged
|
||||
|
||||
# New Formula: log(views_count) * {4} + op_likes_count * {0.5} + LEAST(likes_count / posts_count, {3}) + 10 + log(posts_count)
|
||||
#
|
||||
# topic_1 => 0 + 14 + 3 + 10 + 0 => 27
|
||||
# topic_2 => 0 + 5 + 3 + 10 + 0.301029995664 => 18.301029995664
|
||||
# topic_3 => 1.2041199826559 + 0 + 0 + 10 + 0 => 11.2041199826559
|
||||
|
||||
TopTopic.refresh!
|
||||
top_topics = TopTopic.all
|
||||
|
||||
expect(top_topics.where(topic_id: topic_1.id).pluck(:yearly_score).first).to eq(27)
|
||||
expect(top_topics.where(topic_id: topic_2.id).pluck(:yearly_score).first).to eq(18.301029995664)
|
||||
expect(top_topics.where(topic_id: topic_3.id).pluck(:yearly_score).first).to eq(11.2041199826559)
|
||||
|
||||
# when 'top_topics_formula_first_post_likes_multiplier' setting is changed
|
||||
SiteSetting.top_topics_formula_log_views_multiplier = 2 # unchanged
|
||||
SiteSetting.top_topics_formula_first_post_likes_multiplier = 2
|
||||
SiteSetting.top_topics_formula_least_likes_per_post_multiplier = 3 # unchanged
|
||||
|
||||
# New Formula: log(views_count) * {2} + op_likes_count * {2} + LEAST(likes_count / posts_count, {3}) + 10 + log(posts_count)
|
||||
#
|
||||
# topic_1 => 0 + 56 + 3 + 10 + 0 => 69
|
||||
# topic_2 => 0 + 20 + 3 + 10 + 0.301029995664 => 33.301029995664
|
||||
# topic_3 => 0.602059991328 + 0 + 0 + 10 + 0 => 10.602059991328
|
||||
|
||||
TopTopic.refresh!
|
||||
top_topics = TopTopic.all
|
||||
|
||||
expect(top_topics.where(topic_id: topic_1.id).pluck(:yearly_score).first).to eq(69)
|
||||
expect(top_topics.where(topic_id: topic_2.id).pluck(:yearly_score).first).to eq(33.301029995664)
|
||||
expect(top_topics.where(topic_id: topic_3.id).pluck(:yearly_score).first).to eq(10.602059991328)
|
||||
|
||||
# when 'top_topics_formula_least_likes_per_post_multiplier' setting is changed
|
||||
SiteSetting.top_topics_formula_log_views_multiplier = 2 # unchanged
|
||||
SiteSetting.top_topics_formula_first_post_likes_multiplier = 0.5 # unchanged
|
||||
SiteSetting.top_topics_formula_least_likes_per_post_multiplier = 6
|
||||
|
||||
# New Formula: log(views_count) * {2} + op_likes_count * {0.5} + LEAST(likes_count / posts_count, {6}) + 10 + log(posts_count)
|
||||
#
|
||||
# topic_1 => 0 + 14 + 6 + 10 + 0 => 30
|
||||
# topic_2 => 0 + 5 + 6 + 10 + 0.301029995664 => 21.301029995664
|
||||
# topic_3 => 0.602059991328 + 0 + 0 + 10 + 0 => 10.602059991328
|
||||
|
||||
TopTopic.refresh!
|
||||
top_topics = TopTopic.all
|
||||
|
||||
expect(top_topics.where(topic_id: topic_1.id).pluck(:yearly_score).first).to eq(30)
|
||||
expect(top_topics.where(topic_id: topic_2.id).pluck(:yearly_score).first).to eq(21.301029995664)
|
||||
expect(top_topics.where(topic_id: topic_3.id).pluck(:yearly_score).first).to eq(10.602059991328)
|
||||
|
||||
# handles invalid string value
|
||||
SiteSetting.top_topics_formula_log_views_multiplier = "not good"
|
||||
SiteSetting.top_topics_formula_first_post_likes_multiplier = "not good"
|
||||
SiteSetting.top_topics_formula_least_likes_per_post_multiplier = "not good"
|
||||
|
||||
TopTopic.refresh!
|
||||
top_topics = TopTopic.all
|
||||
|
||||
expect(top_topics.where(topic_id: topic_1.id).pluck(:yearly_score).first).to eq(27)
|
||||
expect(top_topics.where(topic_id: topic_2.id).pluck(:yearly_score).first).to eq(18.301029995664)
|
||||
expect(top_topics.where(topic_id: topic_3.id).pluck(:yearly_score).first).to eq(10.602059991328)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue