def hot
s = self.score # upvotes - downvotes
interval = 69000 # originally 45000
order = Math.log([s.abs(), 1].max, 10)
sign = if s > 0
1.75 # originally 1
elsif s < 0
-1.75 # originally -1
else
0
end
seconds = self.created_at.to_i - 1134028003
(sign * order + seconds / interval).round 7
end
I created a site where people can vote and submit projects they want me to build.
It had 2 ranking modes, "top scoring" and "newest"
This was fine when there was only a dozen projects, but as the list grew, two problems arose:
In the "top scoring view", the top few projects were monopolizing views and votes. Most people just weren't reading down the page enough to see the other ideas.
In the "newest" view, an idea only had a little time to be seen before it was buried by bad ideas or even spam. Also, spammy/bad ideas were invincible to downvotes by virtue of being new.
I needed a middle ground that would show the top ideas while also allowing new ideas a chance in the spotlight.
I found reddit's Hot algorithm, translated it from Python to Ruby, and put it on the site.
It was kind of working, but it seems like it was weighing "recency" too much and not weighing the project's score enough. I think Reddit has such high voting volumes that my site's small vote counts was barely moving the needle for their algorithm.
I don't know much math beyond basic algebra. I was pretty mystified by this seemingly simple algorithm, but I got help from an engineer friend.
I found out that if I increased
sign
, I would amplify the effect of the score on the final ranking. And if I increased interval
, I would decrease the importance of a project's recency. I tweaked the values, eyed the effect, tweaked again, and eventually settled on a setting that resulted in a satisfying blend of the best projects from both "Top Ranked" and "Newest"
Hope this is useful/interesting :)
Previously published on IndieHackers.