com web/php: Improved comment sorting algorithm. It probably still has some room for improvements. The weights are probably not quite right, either.:
include/shared-manual.inc
| From: | Levi Morrison | Date: | Fri, 06 Dec 2013 19:58:32 +0000 |
| Subject: | com web/php: Improved comment sorting algorithm. It probably still has some room for improvements. The weights are probably not quite right, either.: include/shared-manual.inc |
||
| Groups: | php.webmaster | ||
| Request: | Send a blank email to php-webmaster+get-17422@lists.php.net to get a copy of this message | ||
Commit: 2eb10d3d2873cb00ed9068d899e5322759cd4297
Author: Levi Morrison <levim@php.net> Fri, 6 Dec 2013 12:58:32 -0700
Parents: b469860e79d564c0040b5b45eae20fcf0f68a45a
Branches: master
Link: http://git.php.net/?p=web/php.git;a=commitdiff;h=2eb10d3d2873cb00ed9068d899e5322759cd4297
Log:
Improved comment sorting algorithm. It probably still has some room for improvements. The weights
are probably not quite right, either.
Changed paths:
M include/shared-manual.inc
Diff:
diff --git a/include/shared-manual.inc b/include/shared-manual.inc
index 67b3607..49dadc2 100644
--- a/include/shared-manual.inc
+++ b/include/shared-manual.inc
@@ -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: */