Commit:    2eb10d3d2873cb00ed9068d899e5322759cd4297
Author:    Levi Morrison <[email protected]>         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: */


--
PHP Webmaster List Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to