投票排名算法(php版),参考了reddit的排名算法。<?php
/**
算法预习
abs:取绝对值
max:取最大值
log10:常用对数,log10(x) = y,随着x的增大,y的增加越来越小
使用方法:
$time = time();
$vote = new \Common\VoteScore($ups, $downs, $time);
$score = $vote->getScore();
*/
namespace Common;
class VoteScore
{
function __construct($ups, $downs, $time)
{
$this->_ups = $ups;
$this->_downs = $downs;
$this->_time = $time;
}
/**
基本问题
差值越大,得分越高
*/
function score1()
{
$score = log10(max(abs($this->_ups - $this->_downs),1));
return $score;
}
/**
解决争议
总数越多,得分越高 1000:999 大于 10:9
1000:999 和 10:9 在score1里得出的值相等,score2就是为了解决这个问题
*/
function score2()
{
$sum = $this->_ups+$this->_downs;
if($sum < 1){
return 0;
}
$score = log10($sum);
return $score;
}
/**
解决方向
差值越大,方向越远
1000:600 大于 600:1000
1000:600 大于 1000:700
700:1000 大于 600:1000
*/
function score3()
{
if($this->_ups > $this->_downs){
$y = 1;
if($this->_downs > 0){
$y = $y*log10($this->_ups/$this->_downs);
}
}elseif($this->_ups == $this->_downs){
$y = 0;
}else{
$y = -1;
if($this->_ups > 0){
$y = $y*log10($this->_downs/$this->_ups);
}
}
return $y;
}
/**
时间因素
投票时间离现在越近,权重越高
*/
function score4()
{
if($this->_ups > $this->_downs){
$y = 1;
if($this->_downs > 0){
$y = $y*(log10($this->_time)-9);
}
}elseif($this->_ups == $this->_downs){
$y = 0;
}else{
$y = -1;
if($this->_ups > 0){
$y = $y*(log10($this->_time)-9);
}
}
return $y;
}
public function getScore()
{
//默认都有一票赞成票和一票反对票
$this->_ups = $this->_ups+1;
$this->_downs = $this->_downs+1;
$score = $this->score1() + $this->score2() + $this->score3() + $this->score4();
$score = round($score, 4);
return $score;
}
}
?>
测试数据如下:<?php
$ups = 2;
$downs = 0;
$time = time()+3600*24*2;
$vote = new \Common\VoteScore($ups, $downs, $time);
$score = $vote->getScore();
echo $score;
echo "\n";
$ups = 3;
$downs = 0;
$time = time();
$vote = new \Common\VoteScore($ups, $downs, $time);
$score = $vote->getScore();
echo $score;
echo "\n";
$ups = 10;
$downs = 2;
$time = time();
$vote = new \Common\VoteScore($ups, $downs, $time);
$score = $vote->getScore();
echo $score;
echo "\n";
$ups = 100;
$downs = 101;
$time = time();
$vote = new \Common\VoteScore($ups, $downs, $time);
$score = $vote->getScore();
echo $score;
echo "\n";
$ups = 10000;
$downs = 10001;
$time = time();
$vote = new \Common\VoteScore($ups, $downs, $time);
$score = $vote->getScore();
echo $score;
echo "\n";
$ups = 1000;
$downs = 100;
$time = time();
$vote = new \Common\VoteScore($ups, $downs, $time);
$score = $vote->getScore();
echo $score;
echo "\n";
$ups = 1000;
$downs = 10;
$time = time();
$vote = new \Common\VoteScore($ups, $downs, $time);
$score = $vote->getScore();
echo $score;
echo "\n";
$ups = 90;
$downs = 100;
$time = time();
$vote = new \Common\VoteScore($ups, $downs, $time);
$score = $vote->getScore();
echo $score;
echo "\n";
$ups = 100;
$downs = 100;
$time = time();
$vote = new \Common\VoteScore($ups, $downs, $time);
$score = $vote->getScore();
echo $score;
echo "\n";
$ups = 20;
$downs = 100;
$time = time();
$vote = new \Common\VoteScore($ups, $downs, $time);
$score = $vote->getScore();
echo $score;
echo "\n";
$ups = 0;
$downs = 1;
$time = time();
$vote = new \Common\VoteScore($ups, $downs, $time);
$score = $vote->getScore();
echo $score;
echo "\n";
$ups = 10;
$downs = 0;
$time = time();
$vote = new \Common\VoteScore($ups, $downs, $time);
$score = $vote->getScore();
echo $score;
echo "\n";
$ups = 0;
$downs = 1000;
$time = time();
$vote = new \Common\VoteScore($ups, $downs, $time);
$score = $vote->getScore();
echo $score;
echo "\n";
?>