1
0
mirror of https://github.com/php/web-php.git synced 2026-03-23 23:02:13 +01:00

Improved comment sorting algorithm. It probably still has some room for improvements. The weights are probably not quite right, either.

This commit is contained in:
Levi Morrison
2013-12-06 12:58:32 -07:00
parent b469860e79
commit 2eb10d3d28

View File

@@ -25,6 +25,118 @@ $PGI = array(); $SIDEBAR_DATA = '';
// User note display functions
// =============================================================================
class ManualNotesSorter {
private $maxVote;
private $minVote;
private $maxAge;
private $minAge;
private $voteFactor;
private $ratingFactor;
private $ageFactor;
private $voteWeight = 38;
private $ratingWeight = 60;
private $ageWeight = 2;
function sort(array &$notes) {
// First we make a pass over the data to get the min and max values
// for data normalization.
$this->findMinMaxValues($notes);
$this->voteFactor = $this->maxVote - $this->minVote
? (1 - .3)/ ($this->maxVote - $this->minVote)
: .5;
$this->ageFactor = $this->maxAge - $this->minAge
? 1 / ($this->maxAge - $this->minAge)
: .5;
$this->ageFactor *= $this->ageWeight;
// Second we loop through to calculate sort priority using the above numbers
$this->calcSortPriority($notes);
// Third we sort the data.
uasort($notes, array($this, 'factorSort'));
}
private function calcVotePriority(array $note) {
return ($note['score'] - $this->minVote) * $this->voteFactor + .3;
}
private function calcRatingPriority(array $note) {
if ($note['total'] <= 2) {
return 0.5;
} else {
return $note['rating'];
}
}
private function calcSortPriority(array &$notes) {
foreach ($notes as &$note) {
$prio = array(
'vote' => $this->calcVotePriority($note) * $this->voteWeight,
'rating' => $this->calcRatingPriority($note) * $this->ratingWeight,
'age' => ($note['xwhen'] - $this->minAge) * $this->ageFactor
);
$note['sort'] = $prio['value'] = array_sum($prio);
}
}
/*
* Not sure why, but using `$b['sort'] - $a['sort']` does not seem to
* work properly.
*/
private function factorSort($a, $b) {
if ($a['sort'] < $b['sort']) {
return 1;
} elseif ($a['sort'] == $b['sort']) {
return 0;
} else {
return -1;
}
}
private function findMinMaxValues(array &$notes) {
$count = count($notes);
if ($count <= 0) {
return;
}
$note = array_shift($notes);
$note['score'] = $net = ($note['votes']['up'] - $note['votes']['down']);
$note['total'] = $totalVotes = ($note['votes']['up'] + $note['votes']['down']);
$note['rating'] = $totalVotes > 0
? $note['votes']['up'] / $totalVotes
: .5;
$this->minVote = $this->maxVote = $net;
$this->minAge = $this->maxAge = $age = $note['xwhen'];
$first = $note;
foreach ($notes as &$note) {
$note['score'] = $net = ($note['votes']['up'] - $note['votes']['down']);
$note['total'] = $totalVotes = ($note['votes']['up'] + $note['votes']['down']);
$note['rating'] = $totalVotes > 0
? $note['votes']['up'] / $totalVotes
: .5;
$age = $note['xwhen'];
$this->maxVote = max($this->maxVote, $net);
$this->minVote = min($this->minVote, $net);
$this->maxAge = max($this->maxAge, $age);
$this->minAge = min($this->minAge, $age);
}
array_unshift($notes, $first);
}
}
// Print out all user notes for this manual page
function manual_notes() {
// Get needed values
@@ -37,7 +149,9 @@ function manual_notes() {
// Load user note for this page
$notes = manual_notes_load($filename);
uasort($notes, "manual_notes_sort");
$sorter = new ManualNotesSorter;
$sorter->sort($notes);
// Link target to add a note to the current manual page,
// and it's extended form with a [+] image
@@ -336,60 +450,5 @@ function relTime(DateTime $date) {
return $out;
}
// Sort notes by rating and group by date
function manual_notes_sort($a, $b)
{
if ($a['votes']['up'] + $a['votes']['down'] < 1) {
$c = 1;
} else {
$c = $a['votes']['up'] + $a['votes']['down'];
}
if ($b['votes']['up'] + $b['votes']['down'] < 1) {
$d = 1;
} else {
$d = $b['votes']['up'] + $b['votes']['down'];
}
$voteA = $a['votes']['up'] / $c;
$voteB = $b['votes']['up'] / $d;
$rateA = $a['votes']['up'] - $a['votes']['down'];
$rateB = $b['votes']['up'] - $b['votes']['down'];
// Lower voted notes go to the bottom regardless of date
if ($voteA > $voteB) {
// Exception to the rule for today's notes
if ($b['xwhen'] >= mktime(0,0,0,date('n'),date('j'),date('Y')) && $voteB > -1) return 1;
// Another exception for notes with no votes compared to notes with more than 4 votes and 30% or less rating
if ($voteB === 0 && $d === 1 && $voteA <= 0.30 && $c >= 4) return 1;
return -1;
}
// Higher voted notes go to the top regardless of date
elseif ($voteA < $voteB) {
// Exception to the rule for today's notes
if ($a['xwhen'] >= mktime(0,0,0,date('n'),date('j'),date('Y')) && $voteA > -1) return -1;
// Another exception for notes with no votes compared to notes with more than 4 votes and 30% or less rating
if ($voteA === 0 && $c === 1 && $voteB <= 0.30 && $d >= 4) return -1;
return 1;
}
// Votes of equal amounts are sorted based on the overall rating and in descending order by date
else {
if ($rateA > $rateB) {
return -1;
}
elseif ($rateA < $rateB) {
return 1;
}
else {
if ($a['xwhen'] > $b['xwhen']) {
return -1;
}
elseif ($a['xwhen'] < $b['xwhen']) {
return 1;
}
else {
return 0;
}
}
}
}
/* vim: set et ts=4 sw=4: */