2013-02-05 14:16:51 -05:00
class ScoreCalculator
2013-02-25 19:42:20 +03:00
def self . default_score_weights
2013-02-05 14:16:51 -05:00
{
reply_count : 5 ,
2013-05-27 12:45:10 -04:00
like_score : 15 ,
2013-02-05 14:16:51 -05:00
incoming_link_count : 5 ,
bookmark_count : 2 ,
avg_time : 0 . 05 ,
reads : 0 . 2
}
end
def initialize ( weightings = nil )
@weightings = weightings || ScoreCalculator . default_score_weights
end
# Calculate the score for all posts based on the weightings
2013-02-25 19:42:20 +03:00
def calculate
2013-02-05 14:16:51 -05:00
# First update the scores of the posts
exec_sql ( post_score_sql , @weightings )
2013-03-22 15:43:57 -04:00
# Update the percent rankings of the posts
exec_sql ( " UPDATE posts SET percent_rank = x.percent_rank
FROM ( SELECT id , percent_rank ( )
OVER ( PARTITION BY topic_id ORDER BY SCORE DESC ) as percent_rank
FROM posts ) AS x
WHERE x . id = posts . id " )
2013-03-28 13:02:59 -04:00
# Update the topics
exec_sql " UPDATE topics AS t
SET has_best_of = ( t . like_count > = :likes_required AND
t . posts_count > = :posts_required AND
2013-03-29 12:54:16 -04:00
x . max_score > = :score_required ) ,
2013-03-28 13:02:59 -04:00
score = x . avg_score
FROM ( SELECT p . topic_id ,
2013-03-29 12:54:16 -04:00
MAX ( p . score ) AS max_score ,
2013-03-28 13:02:59 -04:00
AVG ( p . score ) AS avg_score
FROM posts AS p
GROUP BY p . topic_id ) AS x
WHERE x . topic_id = t . id " ,
likes_required : SiteSetting . best_of_likes_required ,
posts_required : SiteSetting . best_of_posts_required ,
score_required : SiteSetting . best_of_score_threshold
2013-02-25 19:42:20 +03:00
2013-03-28 13:02:59 -04:00
# Update percentage rank of topics
exec_sql ( " UPDATE topics SET percent_rank = x.percent_rank
FROM ( SELECT id , percent_rank ( )
OVER ( ORDER BY SCORE DESC ) as percent_rank
FROM topics ) AS x
WHERE x . id = topics . id " )
2013-02-05 14:16:51 -05:00
end
private
2013-03-22 15:43:57 -04:00
def exec_sql ( sql , params = nil )
2013-02-05 14:16:51 -05:00
ActiveRecord :: Base . exec_sql ( sql , params )
end
# Generate a SQL statement to update the scores of all posts
def post_score_sql
" UPDATE posts SET score = " . tap do | sql |
components = [ ]
@weightings . keys . each do | k |
components << " COALESCE( #{ k . to_s } , 0) * : #{ k . to_s } "
end
sql << components . join ( " + " )
2013-02-25 19:42:20 +03:00
end
2013-02-05 14:16:51 -05:00
end
end