Vote: x (GroupID, 'Up'|'Down') */ public static function get_user_votes($UserID) { if ((int)$UserID == 0) { return array(); } $UserVotes = G::$Cache->get_value("voted_albums_$UserID"); if ($UserVotes === false) { $QueryID = G::$DB->get_query_id(); G::$DB->query(" SELECT GroupID, Type FROM users_votes WHERE UserID = $UserID"); $UserVotes = G::$DB->to_array('GroupID', MYSQL_ASSOC, false); G::$DB->set_query_id($QueryID); G::$Cache->cache_value("voted_albums_$UserID", $UserVotes); } return $UserVotes; } /** * Returns an array with torrent group vote data * @param string|int $GroupID * @return array (Upvotes, Total Votes) */ public static function get_group_votes($GroupID) { $GroupVotes = G::$Cache->get_value("votes_$GroupID"); if ($GroupVotes === false) { $QueryID = G::$DB->get_query_id(); G::$DB->query(" SELECT Ups AS Ups, Total AS Total FROM torrents_votes WHERE GroupID = $GroupID"); if (!G::$DB->has_results()) { $GroupVotes = array('Ups' => 0, 'Total' => 0); } else { $GroupVotes = G::$DB->next_record(MYSQLI_ASSOC, false); } G::$DB->set_query_id($QueryID); G::$Cache->cache_value("votes_$GroupID", $GroupVotes, 259200); // 3 days } return $GroupVotes; } /** * Computes the inverse normal CDF of a p-value * @param float $GroupID * @return float Inverse Normal CDF */ private function inverse_ncdf($p) { /*************************************************************************** * inverse_ncdf.php * ------------------- * begin : Friday, January 16, 2004 * copyright : (C) 2004 Michael Nickerson * email : nickersonm@yahoo.com * ***************************************************************************/ //Inverse ncdf approximation by Peter John Acklam, implementation adapted to //PHP by Michael Nickerson, using Dr. Thomas Ziegler's C implementation as //a guide. http://home.online.no/~pjacklam/notes/invnorm/index.html //I have not checked the accuracy of this implementation. Be aware that PHP //will truncate the coeficcients to 14 digits. //You have permission to use and distribute this function freely for //whatever purpose you want, but please show common courtesy and give credit //where credit is due. //Input paramater is $p - probability - where 0 < p < 1. //Coefficients in rational approximations $a = array(1 => -3.969683028665376e+01, 2 => 2.209460984245205e+02, 3 => -2.759285104469687e+02, 4 => 1.383577518672690e+02, 5 => -3.066479806614716e+01, 6 => 2.506628277459239e+00); $b = array(1 => -5.447609879822406e+01, 2 => 1.615858368580409e+02, 3 => -1.556989798598866e+02, 4 => 6.680131188771972e+01, 5 => -1.328068155288572e+01); $c = array(1 => -7.784894002430293e-03, 2 => -3.223964580411365e-01, 3 => -2.400758277161838e+00, 4 => -2.549732539343734e+00, 5 => 4.374664141464968e+00, 6 => 2.938163982698783e+00); $d = array(1 => 7.784695709041462e-03, 2 => 3.224671290700398e-01, 3 => 2.445134137142996e+00, 4 => 3.754408661907416e+00); //Define break-points. $p_low = 0.02425; //Use lower region approx. below this $p_high = 1 - $p_low; //Use upper region approx. above this //Define/list variables (doesn't really need a definition) //$p (probability), $sigma (std. deviation), and $mu (mean) are user inputs $q = null; $x = null; $y = null; $r = null; //Rational approximation for lower region. if (0 < $p && $p < $p_low) { $q = sqrt(-2 * log($p)); $x = ((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * $q + $c[6]) / (((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * $q + 1); } //Rational approximation for central region. elseif ($p_low <= $p && $p <= $p_high) { $q = $p - 0.5; $r = $q * $q; $x = ((((($a[1] * $r + $a[2]) * $r + $a[3]) * $r + $a[4]) * $r + $a[5]) * $r + $a[6]) * $q / ((((($b[1] * $r + $b[2]) * $r + $b[3]) * $r + $b[4]) * $r + $b[5]) * $r + 1); } //Rational approximation for upper region. elseif ($p_high < $p && $p < 1) { $q = sqrt(-2 * log(1 - $p)); $x = -((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * $q + $c[6]) / (((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * $q + 1); } //If 0 < p < 1, return a null value else { $x = null; } return $x; //END inverse ncdf implementation. } /** * Implementation of the algorithm described at http://www.evanmiller.org/how-not-to-sort-by-average-rating.html * @param int $Ups Number of upvotes * @param int $Total Number of total votes * @return float Ranking score */ public static function binomial_score($Ups, $Total) { if (($Total <= 0) || ($Ups < 0)) { return 0; } $phat = $Ups / $Total; $Numerator = ($phat + self::Z_VAL * self::Z_VAL / (2 * $Total) - self::Z_VAL * sqrt(($phat * (1 - $phat) + self::Z_VAL * self::Z_VAL / (4 * $Total)) / $Total)); $Denominator = (1 + self::Z_VAL * self::Z_VAL / $Total); return ($Numerator / $Denominator); } /** * Gets where this album ranks overall, for its year, and for its decade. This is really just a wrapper. * @param int $GroupID GroupID of the album * @param int $Year Year it was released * @return array ('overall'=>, 'year'=>, 'decade'=>) */ public static function get_ranking($GroupID, $Year) { $GroupID = (int)$GroupID; $Year = (int)$Year; if ($GroupID <= 0 || $Year <= 0) { return false; } return array( 'overall' => Votes::get_rank_all($GroupID), 'year' => Votes::get_rank_year($GroupID, $Year), 'decade' => Votes::get_rank_decade($GroupID, $Year)); } /** * Gets where this album ranks overall. * @param int $GroupID GroupID of the album * @return int Rank */ public static function get_rank_all($GroupID) { $GroupID = (int)$GroupID; if ($GroupID <= 0) { return false; } $Rankings = G::$Cache->get_value('voting_ranks_overall'); if ($Rankings === false) { $QueryID = G::$DB->get_query_id(); G::$DB->query(' SELECT GroupID, Score FROM torrents_votes ORDER BY Score DESC LIMIT 100'); $Rankings = self::calc_ranks(G::$DB->to_pair(0, 1, false)); G::$DB->set_query_id($QueryID); G::$Cache->cache_value('voting_ranks_overall', $Rankings, 259200); // 3 days } return (isset($Rankings[$GroupID]) ? $Rankings[$GroupID] : false); } /** * Gets where this album ranks in its year. * @param int $GroupID GroupID of the album * @param int $Year Year it was released * @return int Rank for its year */ public static function get_rank_year($GroupID, $Year) { $GroupID = (int)$GroupID; $Year = (int)$Year; if ($GroupID <= 0 || $Year <= 0) { return false; } $Rankings = G::$Cache->get_value("voting_ranks_year_$Year"); if ($Rankings === false) { $QueryID = G::$DB->get_query_id(); G::$DB->query(" SELECT GroupID, Score FROM torrents_votes AS v JOIN torrents_group AS g ON g.ID = v.GroupID WHERE g.Year = $Year ORDER BY Score DESC LIMIT 100"); $Rankings = self::calc_ranks(G::$DB->to_pair(0, 1, false)); G::$DB->set_query_id($QueryID); G::$Cache->cache_value("voting_ranks_year_$Year", $Rankings, 259200); // 3 days } return (isset($Rankings[$GroupID]) ? $Rankings[$GroupID] : false); } /** * Gets where this album ranks in its decade. * @param int $GroupID GroupID of the album * @param int $Year Year it was released * @return int Rank for its year */ public static function get_rank_decade($GroupID, $Year) { $GroupID = (int)$GroupID; $Year = (int)$Year; if ($GroupID <= 0 || $Year <= 0) { return false; } // First year of the decade $Year = $Year - ($Year % 10); $Rankings = G::$Cache->get_value("voting_ranks_decade_$Year"); if ($Rankings === false) { $QueryID = G::$DB->get_query_id(); G::$DB->query(" SELECT GroupID, Score FROM torrents_votes AS v JOIN torrents_group AS g ON g.ID = v.GroupID WHERE g.Year BETWEEN $Year AND " . ($Year + 9) . " AND g.CategoryID = 1 ORDER BY Score DESC LIMIT 100"); $Rankings = self::calc_ranks(G::$DB->to_pair(0, 1, false)); G::$DB->set_query_id($QueryID); G::$Cache->cache_value("voting_ranks_decade_$Year", $Rankings, 259200); // 3 days } return (isset($Rankings[$GroupID]) ? $Rankings[$GroupID] : false); } /** * Turn vote scores into vote ranks. This basically only sorts out tied ranks * * @param array $GroupScores array ( => ) ordered by Score * @return array ( => ) */ public static function calc_ranks($GroupScores) { $Rankings = array(); $PrevScore = $PrevRank = false; $Rank = 1; foreach ($GroupScores as $GroupID => $Score) { if ($Score === $PrevScore) { $Rankings[$GroupID] = $PrevRank; } else { $Rankings[$GroupID] = $Rank; $PrevRank = $Rank; $PrevScore = $Score; } $Rank++; } return $Rankings; } } ?>