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:
@@ -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: */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user