Index: lib/grade/grade_category.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/grade/grade_category.php,v
retrieving revision 1.96.2.21
diff -u -r1.96.2.21 grade_category.php
--- lib/grade/grade_category.php	12 Mar 2008 19:44:39 -0000	1.96.2.21
+++ lib/grade/grade_category.php	27 Oct 2008 14:56:59 -0000
@@ -695,12 +695,48 @@
             }
         }
 
+        $grade_rank = array();
+
         // use 0 if grade missing, droplow used and aggregating all items
         if (!$this->aggregateonlygraded and !empty($this->droplow)) {
             foreach($items as $itemid=>$value) {
+                # Only set the item grade to zero if it is not set and we've
+                # been asked to drop lowest grades
                 if (!isset($grade_values[$itemid]) and !in_array($itemid, $excluded)) {
                     $grade_values[$itemid] = 0;
                 }
+                #$grade_rank[$itemid] = $grade_values[$itemid] / $value->grademax;
+                //Collect the absolute value of the grades as opposed to a
+                //normalized value above.
+                $grade_rank[$itemid] = $grade_values[$itemid];
+                debugging("itemid = " . $itemid . " = " . $grade_rank[$itemid]);
+            }
+        }
+      
+        $negmax = 0;
+        if (!empty($this->droplow))
+        {
+            //sort the grade_rank from worst to best
+            asort($grade_rank);
+            $drop_cnt = $this->droplow;
+            foreach ($grade_rank as $itemid => $value)
+            {
+                //Drop the lowest $drop_cnt and also remove their maxvalue from
+                //the total number of points.  NOTE: this max value is possibly
+                //different for each user if the items in the category have
+                //different maxgrade values.  This breaks the "range" number in
+                //the grader report to be the max maximum value for all users of
+                //the item.
+                if ($drop_cnt < 1) { break; }
+                if ($items[$itemid]->gradetype == GRADE_TYPE_VALUE)
+                {
+                   $negmax += $items[$itemid]->grademax;
+                } else if ($items[$itemid]->gradetype == GRADE_TYPE_SCALE)
+                {
+                   $negmax += $items[$itemid]->grademax - 1; // scales min is 1
+                }
+                $grade_values[$itemid] = 0;
+                $drop_cnt--;
             }
         }
 
@@ -719,6 +755,8 @@
             }
         }
 
+        $max = $max - $negmax;
+
         if ($this->grade_item->grademax != $max or $this->grade_item->grademin != 0 or $this->grade_item->gradetype != GRADE_TYPE_VALUE){
             $this->grade_item->grademax = $max;
             $this->grade_item->grademin = 0;
