Skip to content

Instantly share code, notes, and snippets.

@slogsdon
Created September 15, 2012 03:42
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save slogsdon/3726272 to your computer and use it in GitHub Desktop.
Save slogsdon/3726272 to your computer and use it in GitHub Desktop.
Reddit Ranking Algorithms in PHP
<?php
/**
* Ranking Library
* contains alogrithms for story ranking
* Basically a PHP Implementation of reddits algorithms
*
* @author Lucas Nolte <lnolte@i.biz>
* @since 0.1
* @package Polska Wiadomosc
* @subpackage Libraries
* @see https://github.com/reddit/reddit/blob/master/r2/r2/lib/db/_sorts.pyx
*/
class Ranking {
/**
* calculates the score for a link (upvotes - downvotes)
*
* @access private
* @since 0.1
* @param int $upvotes, int $downvotes
* @return int
*/
private function _score($upvotes = 0, $downvotes = 0) {
return $upvotes - $downvotes;
}
/**
* calculates the hotness of an article
*
* @access private
* @since 0.1
* @param int $upvotes, int $downvotes, int $posted
* @return float
*/
private function _hotness($upvotes = 0, $downvotes = 0, $posted = 0) {
$s = $this->_score($upvotes, $downvotes);
$order = log(max(abs($s), 1), 10);
if($s > 0) {
$sign = 1;
} elseif($s < 0) {
$sign = -1;
} else {
$sign = 0;
}
$seconds = $posted - 1134028003;
return round($order + (($sign * $seconds)/45000), 7);
}
/**
* confidence sort based on http://www.evanmiller.org/how-not-to-sort-by-average-rating.html
*
* @since 0.1
* @access private
* @param int $upvotes, int $downvotes
* @return double
* @see http://www.evanmiller.org/how-not-to-sort-by-average-rating.html
*/
private function _confidence($upvotes = 0, $downvotes = 0) {
$n = $upvotes + $downvotes;
if($n === 0) {
return 0;
}
$z = 1.281551565545; // 80% confidence
$p = floor($upvotes) / $n;
$left = $p + 1/(2*$n)*$z*$z;
$right = $z*sqrt($p*(1-$p)/$n + $z*$z/(4*$n*$n));
$under = 1+1/$n*$z*$z;
return ($left - $right) / $under;
}
/**
* calculates the controversy score for a link
*
* @since 0.1
* @param int $upvotes, int $downvotes
* @access public
* @return float
*/
public function controversy($upvotes = 0, $downvotes = 0) {
return ($upvotes + $downvotes) / max(abs($this->_score($upvotes, $downvotes)), 1);
}
/**
* public method to calculate a post's hotness
*
* @since 0.1
* @param int $upvotes, int $downvotes, int $posted
* @access public
* @return float
*/
public function hotness($upvotes, $downvotes, $posted) {
return $this->_hotness($upvotes, $downvotes, $posted);
}
/**
* public method to calculate a posts confidence
*
* @since 0.1
* @param int $upvotes, int $downvotes
* @access public
* @return double
*/
public function confidence($upvotes, $downvotes) {
return $this->_confidence($upvotes, $downvotes);
}
}
@robinlahtinen
Copy link

robinlahtinen commented Mar 3, 2017

What about using$order = log10(max(abs($s), 1)); instead of log()

@adampatterson
Copy link

Do you have an example ussage?

@alexweissman
Copy link

alexweissman commented Jul 28, 2022

Where are the upvotes and downvotes sourced from? Is it just from the post, or do comments get factored in somehow?

My hunch is that only the immediate children of a post or top-level comment are counted in ranking that entity. But it would be nice to get confirmation from someone who has been on the team at some point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment