]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-10901 new SUM aggregation type
authorskodak <skodak>
Tue, 13 Nov 2007 15:08:59 +0000 (15:08 +0000)
committerskodak <skodak>
Tue, 13 Nov 2007 15:08:59 +0000 (15:08 +0000)
MDL-12154 used proper cast to float before !== comparison

grade/edit/tree/category.php
grade/edit/tree/category_form.php
grade/edit/tree/item_form.php
grade/lib.php
lang/en_utf8/grades.php
lib/grade/constants.php
lib/grade/grade_category.php

index b30f948bf8221c3e74157df7bf91ae5cf37137fc..05c7c417e98d5a552abea834e5a57d1dba7ea2c6 100644 (file)
@@ -51,7 +51,7 @@ if ($id) {
         error('Incorrect category id!');
     }
     $grade_category->apply_forced_settings();
-    $category = $grade_category->get_record_data(); 
+    $category = $grade_category->get_record_data();
     // Get Category preferences
     $category->pref_aggregationview = grade_report::get_pref('aggregationview', $id);
 
@@ -59,7 +59,7 @@ if ($id) {
     $grade_category = new grade_category();
     $grade_category->courseid = $course->id;
     $grade_category->apply_forced_settings();
-    $category = $grade_category->get_record_data(); 
+    $category = $grade_category->get_record_data();
 }
 
 $mform->set_data($category);
@@ -68,6 +68,12 @@ if ($mform->is_cancelled()) {
     redirect($returnurl);
 
 } else if ($data = $mform->get_data(false)) {
+    if (!isset($data->aggregateonlygraded)) {
+        $data->aggregateonlygraded = 0;
+    }
+    if (!isset($data->aggregateoutcomes)) {
+        $data->aggregateoutcomes = 0;
+    }
     grade_category::set_properties($grade_category, $data);
 
     if (empty($grade_category->id)) {
index ceb14a8706f67df042c56fb63c4ad6c37a06bb82..234a74a4af17a57da70909c236462b73bb76eb07 100644 (file)
@@ -37,24 +37,30 @@ class edit_category_form extends moodleform {
                          GRADE_AGGREGATE_MAX             =>get_string('aggregatemax', 'grades'),
                          GRADE_AGGREGATE_MODE            =>get_string('aggregatemode', 'grades'),
                          GRADE_AGGREGATE_WEIGHTED_MEAN   =>get_string('aggregateweightedmean', 'grades'),
-                         GRADE_AGGREGATE_EXTRACREDIT_MEAN=>get_string('aggregateextracreditmean', 'grades'));
+                         GRADE_AGGREGATE_EXTRACREDIT_MEAN=>get_string('aggregateextracreditmean', 'grades'),
+                         GRADE_AGGREGATE_SUM             =>get_string('aggregatesum', 'grades'));
 
         // visible elements
         $mform->addElement('header', 'gradecat', get_string('gradecategory', 'grades'));
         $mform->addElement('text', 'fullname', get_string('categoryname', 'grades'));
         $mform->addRule('fullname', null, 'required', null, 'client');
-        
+
         $mform->addElement('select', 'aggregation', get_string('aggregation', 'grades'), $options);
         $mform->setHelpButton('aggregation', array('aggregation', get_string('aggregation', 'grades'), 'grade'));
 
-        $mform->addElement('advcheckbox', 'aggregateonlygraded', get_string('aggregateonlygraded', 'grades'));
+        $mform->addElement('checkbox', 'aggregateonlygraded', get_string('aggregateonlygraded', 'grades'));
         $mform->setHelpButton('aggregateonlygraded', array(false, get_string('aggregateonlygraded', 'grades'),
                           false, true, false, get_string('aggregateonlygradedhelp', 'grades')));
+        $mform->disabledIf('aggregateonlygraded', 'aggregation', 'eq', GRADE_AGGREGATE_SUM);
 
-        if (!empty($CFG->enableoutcomes)) {
-            $mform->addElement('advcheckbox', 'aggregateoutcomes', get_string('aggregateoutcomes', 'grades'));
+        if (empty($CFG->enableoutcomes)) {
+            $mform->addElement('hidden', 'aggregateoutcomes');
+            $mform->setType('aggregateoutcomes', PARAM_INT);
+        } else {
+            $mform->addElement('checkbox', 'aggregateoutcomes', get_string('aggregateoutcomes', 'grades'));
             $mform->setHelpButton('aggregateoutcomes', array(false, get_string('aggregateoutcomes', 'grades'),
                               false, true, false, get_string('aggregateoutcomeshelp', 'grades')));
+            $mform->disabledIf('aggregateoutcomes', 'aggregation', 'eq', GRADE_AGGREGATE_SUM);
         }
 
         $mform->addElement('advcheckbox', 'aggregatesubcats', get_string('aggregatesubcats', 'grades'));
index ed952d9ec105e13f840a612a039d7b92780122ee..3d4838a8e611fba71a7fb23374506d10493e62d3 100644 (file)
@@ -197,6 +197,7 @@ class edit_item_form extends moodleform {
                     //$mform->removeElement('calculation');
                 }
             }
+
             //remove the aggregation coef element if not needed
             if ($grade_item->is_course_item()) {
                 $mform->removeElement('aggregationcoef');
@@ -227,6 +228,23 @@ class edit_item_form extends moodleform {
                 }
             }
 
+            if ($category = $grade_item->get_item_category()) {
+                if ($category->aggregation == GRADE_AGGREGATE_SUM) {
+                    if ($mform->elementExists('gradetype')) {
+                        $mform->hardFreeze('gradetype');
+                    }
+                    if ($mform->elementExists('grademin')) {
+                        $mform->hardFreeze('grademin');
+                    }
+                    if ($mform->elementExists('grademax')) {
+                        $mform->hardFreeze('grademax');
+                    }
+                    if ($mform->elementExists('scaleid')) {
+                        $mform->removeElement('scaleid');
+                    }
+                }
+            }
+
         } else {
             // all new items are manual, children of course category
             $mform->removeElement('plusfactor');
index bc2cb67e955454091ff5412bf6882b9cefd9736d..321558a075b4147cd93757d5e7e8fb80bb95d24a 100644 (file)
@@ -740,8 +740,8 @@ class grade_structure {
                             case GRADE_AGGREGATE_WEIGHTED_MEAN:
                             case GRADE_AGGREGATE_EXTRACREDIT_MEAN:
                                 return '<img src="'.$CFG->pixpath.'/i/agg_mean.gif" class="icon itemicon" alt="'.get_string('aggregation', 'grades').'"/>';
-                            //case GRADE_AGGREGATE_SUM:
-                                //return '<img src="'.$CFG->pixpath.'/i/agg_sum.gif" class="icon itemicon" alt="'.get_string('aggregation', 'grades').'"/>';
+                            case GRADE_AGGREGATE_SUM:
+                                return '<img src="'.$CFG->pixpath.'/i/agg_sum.gif" class="icon itemicon" alt="'.get_string('aggregation', 'grades').'"/>';
                         }
                     }
 
index 2bf9c64c48b6c4d80395a17e002e926c24244a82..b57e4c4ee1afce3b0848cab28808f670b15f091c 100644 (file)
@@ -23,6 +23,7 @@ $string['aggregateoutcomes'] = 'Include outcomes in aggregation';
 $string['aggregateoutcomeshelp'] = 'Including outcomes in aggregation may not lead to the desired overall grade, so you have the option to include or leave them out.';
 $string['aggregatesubcats'] = 'Aggregate including subcategories';
 $string['aggregatesubcatshelp'] = 'The aggregation is usually done only with immediate children, it is also possible to aggregate grades in all subcategories excluding other aggregated grades.';
+$string['aggregatesum'] = 'Sum of grades';
 $string['aggregatesonly'] = 'Aggregates only';
 $string['aggregateweightedmean'] = 'Weighted mean of grades';
 $string['aggregation'] = 'Aggregation';
index fabb36dc63ffdbf88903db043fb0fdd7ac1756dc..b35a45c02d2d0919b171d20513c5b60ca4788d5b 100644 (file)
@@ -40,6 +40,7 @@ define('GRADE_AGGREGATE_MAX', 6);
 define('GRADE_AGGREGATE_MODE', 8);
 define('GRADE_AGGREGATE_WEIGHTED_MEAN', 10);
 define('GRADE_AGGREGATE_EXTRACREDIT_MEAN', 12);
+define('GRADE_AGGREGATE_SUM', 13);
 
 // grade types
 define('GRADE_TYPE_NONE', 0);
index a5165beb1e8448d6c6766dda608f0586cd61c4fa..0b31735d8894cd617855ab7439ba2615947ccf4f 100644 (file)
@@ -375,9 +375,9 @@ class grade_category extends grade_object {
     }
 
     /**
-     * Generates and saves raw_grades in associated category grade item.
+     * Generates and saves final grades in associated category grade item.
      * These immediate children must already have their own final grades.
-     * The category's aggregation method is used to generate raw grades.
+     * The category's aggregation method is used to generate final grades.
      *
      * Please note that category grade is either calculated or aggregated - not both at the same time.
      *
@@ -387,7 +387,7 @@ class grade_category extends grade_object {
      * Steps to follow:
      *  1. Get final grades from immediate children
      *  3. Aggregate these grades
-     *  4. Save them in raw grades of associated category grade item
+     *  4. Save them in final grades of associated category grade item
      */
     function generate_grades($userid=null) {
         global $CFG;
@@ -474,6 +474,10 @@ class grade_category extends grade_object {
         }
 
         if ($oldgrade) {
+            if (!is_null($oldgrade->finalgrade)) {
+                // we need proper floats here for !== comparison later
+                $oldgrade->finalgrade = (float)$oldgrade->finalgrade;
+            }
             $grade = $this->get_instance('grade_grade', $oldgrade, false);
             $grade->grade_item =& $this->grade_item;
 
@@ -485,10 +489,6 @@ class grade_category extends grade_object {
 
             $oldgrade = new object();
             $oldgrade->finalgrade  = $grade->finalgrade;
-            $oldgrade->rawgrade    = $grade->rawgrade;
-            $oldgrade->rawgrademin = $grade->rawgrademin;
-            $oldgrade->rawgrademax = $grade->rawgrademax;
-            $oldgrade->rawscaleid  = $grade->rawscaleid;
         }
         
         $grade->itemid = $this->grade_item->id; // For testability, avoids the need for load_grade_item()
@@ -501,15 +501,20 @@ class grade_category extends grade_object {
         // can not use own final category grade in calculation
         unset($grade_values[$this->grade_item->id]);
 
-        // if no grades calculation possible or grading not allowed clear both final and raw
+        // if no grades calculation possible or grading not allowed clear final grade
         if (empty($grade_values) or empty($items) or ($this->grade_item->gradetype != GRADE_TYPE_VALUE and $this->grade_item->gradetype != GRADE_TYPE_SCALE)) {
             $grade->finalgrade = null;
-            $grade->rawgrade   = null;
-            if ($grade->finalgrade !== $oldgrade->finalgrade or $grade->rawgrade !== $oldgrade->rawgrade) {
-                $grade->update('system');
+            if ($grade->finalgrade !== $oldgrade->finalgrade) {
+                $grade->update('aggregation');
             }
             return;
         }
+
+    /// sum is a special aggregation types - it adjusts the min max, does not use relative values
+        if ($this->aggregation == GRADE_AGGREGATE_SUM) {
+            $this->sum_grades($grade, $oldgrade, $items, $grade_values, $excluded);
+            return;
+        }
     /// normalize the grades first - all will have value 0...1
         // ungraded items are not used in aggregation
         foreach ($grade_values as $itemid=>$v) {
@@ -541,9 +546,8 @@ class grade_category extends grade_object {
         if (count($grade_values) == 0) {
             // not enough attempts yet
             $grade->finalgrade = null;
-            $grade->rawgrade   = null;
-            if ($grade->finalgrade !== $oldgrade->finalgrade or $grade->rawgrade !== $oldgrade->rawgrade) {
-                $grade->update('system');
+            if ($grade->finalgrade !== $oldgrade->finalgrade) {
+                $grade->update('aggregation');
             }
             return;
         }
@@ -551,13 +555,7 @@ class grade_category extends grade_object {
         // do the maths
         $agg_grade = $this->aggregate_values($grade_values, $items);
 
-    /// prepare update of new raw grade
-        $grade->rawgrademin = $this->grade_item->grademin;
-        $grade->rawgrademax = $this->grade_item->grademax;
-        $grade->rawscaleid  = $this->grade_item->scaleid;
-        $grade->rawgrade    = null; // categories do not use raw grades
-        
-        // recalculate the rawgrade back to requested range
+        // recalculate the grade back to requested range
         $finalgrade = grade_grade::standardise_score($agg_grade, 0, 1, $this->grade_item->grademin, $this->grade_item->grademax);
 
         if (!is_null($finalgrade)) {
@@ -567,13 +565,8 @@ class grade_category extends grade_object {
         }
 
         // update in db if changed
-        if (   $grade->finalgrade  !== $oldgrade->finalgrade
-            or $grade->rawgrade    !== $oldgrade->rawgrade
-            or $grade->rawgrademin !== $oldgrade->rawgrademin
-            or $grade->rawgrademax !== $oldgrade->rawgrademax
-            or $grade->rawscaleid  !== $oldgrade->rawscaleid) {
-
-            $grade->update('system');
+        if ($grade->finalgrade !== $oldgrade->finalgrade) {
+            $grade->update('aggregation');
         }
 
         return;
@@ -656,6 +649,58 @@ class grade_category extends grade_object {
 
         return $agg_grade;
     }
+
+
+    /**
+     * internal function for category grades summing
+     *
+     * @param int $userid
+     * @param array $items
+     * @param array $grade_values
+     * @param float $oldgrade
+     * @param bool $excluded
+     * @return boolean (just plain return;)
+     */
+    function sum_grades(&$grade, &$oldgrade, $items, $grade_values, $excluded) {
+        // ungraded and exluded items are not used in aggregation
+        foreach ($grade_values as $itemid=>$v) {
+            if (is_null($v)) {
+                unset($grade_values[$itemid]);
+            } else if (in_array($itemid, $excluded)) {
+                unset($grade_values[$itemid]);
+            }
+        }
+
+        $max = 0;
+
+        //find max grade
+        foreach ($items as $item) {
+            if ($item->gradetype != GRADE_TYPE_VALUE) {
+                continue; // sum only items with value grades, no scales and outcomes!
+            }
+            $max += $item->grademax;
+        }
+
+        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;
+            $this->grade_item->gradetype = GRADE_TYPE_VALUE;
+            $this->grade_item->update('aggregation');
+        }
+
+        $this->apply_limit_rules($grade_values);
+
+        $sum = array_sum($grade_values);
+        $grade->finalgrade = bounded_number($this->grade_item->grademin, $sum, $this->grade_item->grademax);
+
+        // update in db if changed
+        if ($grade->finalgrade !== $oldgrade->finalgrade) {
+            $grade->update('aggregation');
+        }
+
+        return;
+    }
+
     /**
      * Given an array of grade values (numerical indices), applies droplow or keephigh
      * rules to limit the final array.