]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-9506 Issue 1: adjusting a gradeitem's value would result in a grade_final object...
authornicolasconnault <nicolasconnault>
Tue, 8 May 2007 02:20:26 +0000 (02:20 +0000)
committernicolasconnault <nicolasconnault>
Tue, 8 May 2007 02:20:26 +0000 (02:20 +0000)
13 files changed:
lib/grade/grade_calculation.php
lib/grade/grade_category.php
lib/grade/grade_grades_raw.php
lib/grade/grade_item.php
lib/simpletest/grade/simpletest/testgradecalculation.php
lib/simpletest/grade/simpletest/testgradecategory.php
lib/simpletest/grade/simpletest/testgradefinal.php
lib/simpletest/grade/simpletest/testgradehistory.php
lib/simpletest/grade/simpletest/testgradeitem.php
lib/simpletest/grade/simpletest/testgradeoutcome.php
lib/simpletest/grade/simpletest/testgraderaw.php
lib/simpletest/grade/simpletest/testgradescale.php
lib/simpletest/grade/simpletest/testgradetext.php

index 1508dc89a2188cc16960a95ef3f9de260c1082fd..8fec2e23d3f8562ccab812e83ff8fb1135a5ac76 100644 (file)
@@ -70,9 +70,10 @@ class grade_calculation extends grade_object {
     /**
      * Applies the formula represented by this object to the value given, and returns the result.
      * @param float $oldvalue
+     * @param string $valuetype Either 'gradevalue' or 'gradescale'
      * @return float result
      */
-    function compute($oldvalue) {
+    function compute($oldvalue, $valuetype = 'gradevalue') {
         return $oldvalue; // TODO implement computation using parser
     }
 
index d3458dd9d08e6e76631311456a5bde694b98ee46..e05f223e1b4bb4abb04191a29eea39de6f7ce5a0 100644 (file)
@@ -210,7 +210,55 @@ class grade_category extends grade_object {
 
         return $result;
     }
-    
+   
+    /**
+     * Generates and saves raw_grades, based on this category's immediate children, then uses the 
+     * associated grade_item to generate matching final grades. These immediate children must first have their own
+     * raw and final grades, which means that ultimately we must get grade_items as children. The category's aggregation
+     * method is used to generate these raw grades, which can then be used by the category's associated grade_item
+     * to apply calculations to and generate final grades.
+     */
+    function generate_grades() {
+        // Check that the children have final grades. If not, call their generate_raw_grades method (recursion)
+        if (empty($this->children)) {
+            $this->children = $this->get_children(1, 'flat');
+        }
+        
+        $category_raw_grades = array();
+        $aggregated_grades = array();
+
+        foreach ($this->children as $child) {
+            if (get_class($child) == 'grade_item') {
+                $category_raw_grades[$child->id] = $child->load_final();
+            } elseif ($get_class($child) == 'grade_category') {
+                $category_raw_grades[$child->id] = $child->load_final();
+                if (empty($category_raw_grades)) {
+                    $category_raw_grades[$child->id] = $child->generate_grades();
+                } 
+            }
+        }
+
+        if (empty($category_raw_grades)) {
+            return null;
+        } else {
+            $aggregated_grades = $this->aggregate_grades($category_raw_grades);
+            foreach ($aggregated_grades as $raw_grade) {
+                $raw_grade->insert();
+            }
+            $this->grade_item->generate_final();
+        }
+    }
+
+    /**
+     * Given an array of arrays of grade objects (raw or final), uses this category's aggregation method to 
+     * compute and return a single array of grade_raw objects with the aggregated gradevalue.
+     * @param array $raw_grade_sets
+     * @return array Raw grade objects
+     */
+    function aggregate_grades($raw_grade_sets) {
+        
+    }
+
     /**
      * Looks at a path string (e.g. /2/45/56) and returns the depth level represented by this path (in this example, 3).
      * If no string is given, it looks at the obect's path and assigns the resulting depth to its $depth variable.
index dd62c4f5b39bd666ad44c82a9db6db6dd2581394..57ba56567038968f0a9cfdcffdb40aeaea63c64b 100644 (file)
@@ -59,9 +59,9 @@ class grade_grades_raw extends grade_object {
    
     /**
      * The scale value of this raw grade, if such was provided by the module.
-     * @var int $scalevalue
+     * @var int $gradescale
      */
-    var $scalevalue;
+    var $gradescale;
 
     /**
      * The maximum allowable grade when this grade was created.
index 6fcac6265a9adc7c4bddb4c46041d5bc0bfb3890..c559469c5d42fba9a2e0f4910ad19b73ec3ccae7 100644 (file)
@@ -328,12 +328,47 @@ class grade_item extends grade_object {
      */      
     function load_final() {
         $grade_final_array = get_records('grade_grades_final', 'itemid', $this->id);
+        
+        if (empty($grade_final_array)) {
+            $this->generate_final();
+            $grade_final_array = get_records('grade_grades_final', 'itemid', $this->id);
+        }
+        
+        if (empty($grade_final_array)) {
+            return false;
+        }
+
         foreach ($grade_final_array as $f) {
             $this->grade_grades_final[$f->userid] = new grade_grades_final($f);
         }
         return $this->grade_grades_final;
     }
 
+    /**
+     * Once the raw_grades are imported or entered, this method uses the grade_item's calculation and rules to 
+     * generate final grade entries in the DB.
+     * @return array final grade objects (grade_grades_final).
+     */
+    function generate_final() {
+        if (empty($this->grade_grades_raw)) {
+            $this->load_raw();
+        }
+        
+        $success = true;
+
+        foreach ($this->grade_grades_raw as $raw_grade) {
+            $final_grade = new grade_grades_final();
+            $final_grade->gradevalue = $this->adjust_grade($raw_grade, null, 'gradevalue');
+            $final_grade->gradescale = $this->adjust_grade($raw_grade, null, 'gradescale');
+            $final_grade->itemid = $this->id;
+            $final_grade->userid = $raw_grade->userid;
+            $success = $success & $final_grade->insert();
+            $this->grade_grades_final[$final_grade->userid] = $final_grade;
+        }
+        
+        return $success;
+    }
+
     /**
      * Returns this object's calculation.
      * @param boolean $fetch Whether to fetch the value from the DB or not (false == just use the object's value)
@@ -522,19 +557,36 @@ class grade_item extends grade_object {
             $grade_raw_array = $this->grade_grades_raw;
         }
 
+        // The following code assumes that there is a grade_final object in DB for every
+        // grade_raw object. This assumption depends on the correct creation of grade_final entries.
+        // This also assumes that the two arrays $this->grade_grades_raw and its final counterpart are
+        // indexed by userid, not sequentially or by grade_id
+        if (count($this->grade_grades_final) != count($this->grade_grades_raw)) {
+            $this->generate_final();
+        }
+
         foreach ($grade_raw_array as $userid => $raw) {
-            $newgradevalue = $raw->gradevalue;
+            // the value could be gradevalue or gradescale
+            $valuetype = null;
+            
+            if (!empty($raw->gradevalue)) {
+                $valuetype = 'gradevalue';
+            } elseif (!empty($raw->gradescale)) {
+                $valuetype = 'gradescale';
+            }
+
+            $newgradevalue = $raw->$valuetype;
             
             if (!empty($this->calculation)) {
                 $this->upgrade_calculation_to_object();
-                $newgradevalue = $this->calculation->compute($raw->gradevalue);
+                $newgradevalue = $this->calculation->compute($raw->$valuetype, $valuetype);
             }
             
             $final = $this->grade_grades_final[$userid];
 
-            $final->gradevalue = $this->adjust_grade($raw, $newgradevalue);
+            $final->$valuetype = $this->adjust_grade($raw, $newgradevalue, $valuetype);
             
-            if ($final->update($newgradevalue)) {
+            if ($final->update()) {
                 $count++;
             } else {
                 return false;
@@ -558,19 +610,21 @@ class grade_item extends grade_object {
      * Given a float grade value or integer grade scale, applies a number of adjustment based on 
      * grade_item variables and returns the result.
      * @param object $grade_raw The raw object to compare with this grade_item's rules
-     * @param mixed $gradevalue The new gradevalue (after calculations are performed)
+     * @param mixed $gradevalue The new gradevalue (after calculations are performed).
+     *                          If null, the raw_grade's gradevalue or gradescale will be used.
+     * @param string $valuetype Either 'gradevalue' or 'gradescale'
      * @return mixed 
      */
-    function adjust_grade($grade_raw, $gradevalue=NULL) {
+    function adjust_grade($grade_raw, $gradevalue=NULL, $valuetype='gradevalue') {
         $raw_offset = 0;
         $item_offset = 0;
-
-        if (!empty($grade_raw->gradevalue)) { // Dealing with numerical grade
+        
+        if ($valuetype == 'gradevalue') { // Dealing with numerical grade
             if (empty($gradevalue)) {
                 $gradevalue = $grade_raw->gradevalue;
             }
 
-        } elseif(!empty($grade_raw->gradescale)) { // Dealing with a scale value
+        } elseif($valuetype == 'gradescale') { // Dealing with a scale value
             if (empty($gradevalue)) {
                 $gradevalue = $grade_raw->gradescale;
             }
@@ -601,11 +655,11 @@ class grade_item extends grade_object {
         $gradevalue = $factor * $diff + $this->grademin;
 
         // Apply rounding or factors, depending on whether it's a scale or value
-        if (!empty($grade_raw->gradevalue)) {
+        if ($valuetype == 'gradevalue') {
             // Apply other grade_item factors
             $gradevalue *= $this->multfactor;
             $gradevalue += $this->plusfactor;
-        } elseif (!empty($grade_raw->gradescale)) {
+        } elseif ($valuetype == 'gradescale') {
             $gradevalue = (int) round($gradevalue);
         }
 
index b92a0ad1f84e208832a52f9679d6535ee309048f..b4631d237de4d0745b6c84550d1e553515e07e43 100644 (file)
@@ -61,7 +61,6 @@ class grade_calculation_test extends gradelib_test {
         $this->assertEqual($grade_calculation->id, $last_grade_calculation->id + 1);
         $this->assertFalse(empty($grade_calculation->timecreated));
         $this->assertFalse(empty($grade_calculation->timemodified));
-        $this->grade_calculations[] = $grade_calculation; 
 
     }
 
index 65ab8269804b7387375b3c3b1b3bc14551de8478..a89a56e6603911dacec1610bdfb0bb58f83ff978 100755 (executable)
@@ -45,8 +45,6 @@ class grade_category_test extends gradelib_test {
         $grade_category = new grade_category($params, false);
         $grade_category->insert();
 
-        $this->grade_categories[] = $grade_category;
-        $this->grade_items[] = $grade_category->grade_item;
         $this->assertEqual($params->courseid, $grade_category->courseid);
         $this->assertEqual($params->fullname, $grade_category->fullname);
         $this->assertEqual(1, $grade_category->depth);
@@ -58,8 +56,6 @@ class grade_category_test extends gradelib_test {
         $params->fullname = 'unittestcategory5';
         $grade_category = new grade_category($params, false);
         $grade_category->insert();
-        $this->grade_categories[] = $grade_category;
-        $this->grade_items[] = $grade_category->grade_item;
         $this->assertEqual(2, $grade_category->depth);
         $this->assertEqual("$parentpath/$grade_category->id", $grade_category->path); 
         $parentpath = $grade_category->path;
@@ -69,8 +65,6 @@ class grade_category_test extends gradelib_test {
         $params->fullname = 'unittestcategory6';
         $grade_category = new grade_category($params, false);
         $grade_category->insert();
-        $this->grade_categories[] = $grade_category;
-        $this->grade_items[] = $grade_category->grade_item;
         $this->assertEqual(3, $grade_category->depth);
         $this->assertEqual("$parentpath/$grade_category->id", $grade_category->path); 
     }
@@ -90,12 +84,14 @@ class grade_category_test extends gradelib_test {
         $grade_category->insert();
 
         $last_grade_category = end($this->grade_categories);
+        
+        $this->assertFalse(empty($grade_category->grade_item));
+        $this->assertEqual($grade_category->id, $grade_category->grade_item->iteminstance);
+        $this->assertEqual('category', $grade_category->grade_item->itemtype);
 
         $this->assertEqual($grade_category->id, $last_grade_category->id + 1);
-        $this->assertTrue(!empty($grade_category->timecreated));
-        $this->assertTrue(!empty($grade_category->timemodified));
-        $this->grade_categories[] = $grade_category; 
-        $this->grade_items[] = $grade_category->grade_item;
+        $this->assertFalse(empty($grade_category->timecreated));
+        $this->assertFalse(empty($grade_category->timemodified));
     }
 
     function test_grade_category_update() {
index e822bf6058d727028aab5b081cdf54d81c68f636..ff90461cc5f09cdb1cc63728f27b9af4a772bae0 100644 (file)
@@ -63,8 +63,6 @@ class grade_final_test extends gradelib_test {
         $this->assertEqual($grade_grades_final->id, $last_grade_grades_final->id + 1);
         $this->assertFalse(empty($grade_grades_final->timecreated));
         $this->assertFalse(empty($grade_grades_final->timemodified));
-        $this->grade_grades_final[] = $grade_grades_final; 
-
     }
 
     function test_grade_grades_final_update() {
index 2943da14f6f3280dc88f49fa414f8d8c4e7528b7..e54922373da5b0252db4cfb2859b82d38a0445c4 100644 (file)
@@ -69,8 +69,6 @@ class grade_history_test extends gradelib_test {
         $this->assertEqual($grade_history->id, $last_grade_history->id + 1);
         $this->assertFalse(empty($grade_history->timecreated));
         $this->assertFalse(empty($grade_history->timemodified));
-        $this->grade_history[] = $grade_history; 
-
     }
 
     function test_grade_history_update() {
index faa81e0bf8fbd1c95e9d1f566dd905c4d2199a6e..c6cf4a102cf7f9ee4aba8e8c5993d7f803adf5c9 100755 (executable)
@@ -40,11 +40,10 @@ class grade_item_test extends gradelib_test {
         $params = new stdClass();
 
         $params->courseid = $this->courseid;
-        $params->categoryid = $this->grade_categories[0]->id;
+        $params->categoryid = $this->grade_categories[1]->id;
         $params->itemname = 'unittestgradeitem4';
         $params->itemtype = 'mod';
         $params->itemmodule = 'database';
-        $params->iteminstance = 4;
         $params->iteminfo = 'Grade item used for unit testing';
 
         $grade_item = new grade_item($params, false);
@@ -59,11 +58,10 @@ class grade_item_test extends gradelib_test {
         $this->assertTrue(method_exists($grade_item, 'insert'));
         
         $grade_item->courseid = $this->courseid;
-        $grade_item->categoryid = $this->grade_categories[0]->id;
+        $grade_item->categoryid = $this->grade_categories[1]->id;
         $grade_item->itemname = 'unittestgradeitem4';
         $grade_item->itemtype = 'mod';
         $grade_item->itemmodule = 'quiz';
-        $grade_item->iteminstance = 1;
         $grade_item->iteminfo = 'Grade item used for unit testing';
 
         $grade_item->insert();
@@ -71,7 +69,6 @@ class grade_item_test extends gradelib_test {
         $last_grade_item = end($this->grade_items);
 
         $this->assertEqual($grade_item->id, $last_grade_item->id + 1);
-        $this->grade_items[] = $grade_item; 
     }
 
     function test_grade_item_delete() {
@@ -191,7 +188,6 @@ class grade_item_test extends gradelib_test {
         $calculation = 'SUM([unittestgradeitem1], [unittestgradeitem3])';
         $grade_item->set_calculation($calculation);
         $new_calculation = $grade_item->get_calculation();
-        $this->grade_calculations[] = $new_calculation;
 
         $this->assertEqual($calculation, $new_calculation->calculation);
     }
@@ -301,21 +297,33 @@ class grade_item_test extends gradelib_test {
     }
 
     function test_grade_item_adjust_scale_grade() {
+        // Load grade item and its scale
+        $grade_item = new grade_item(array('scaleid' => $this->scale[1]->id), false);
+        $grade_item->insert();
+        $grade_item->load_scale();
+        $this->assertEqual('Very Good', $grade_item->scale->scale_items[1]);
+        
         // Load raw grade and its scale
-        $grade_raw = new grade_grades_raw(array('scaleid' => $this->scale[0]->id));
+        $grade_raw = new grade_grades_raw(array('scaleid' => $this->scale[0]->id), false);
         $grade_raw->gradescale = 4;
+        $grade_raw->itemid = $grade_item->id;
+        $grade_raw->userid = 1;
+        $grade_raw->insert();
         $grade_raw->load_scale();
         $this->assertEqual('Fairly neutral', $grade_raw->scale->scale_items[2]);
-        
-        // Load grade item and its scale
-        $grade_item = new grade_item(array('scaleid' => $this->scale[1]->id));
-        $grade_item->load_scale();
-        $this->assertEqual('Very Good', $grade_item->scale->scale_items[1]);
 
         // Test grade_item::adjust_scale
-        $this->assertEqual(3, $grade_item->adjust_grade($grade_raw));
+        $this->assertEqual(3, $grade_item->adjust_grade($grade_raw, null, 'gradescale'));
         $grade_raw->gradescale = 6;
-        $this->assertEqual(4, $grade_item->adjust_grade($grade_raw));
+        $this->assertEqual(4, $grade_item->adjust_grade($grade_raw, null, 'gradescale'));
+
+        // Check that the final grades have the correct values now
+        $grade_item->load_raw();
+        $grade_item->update_final_grade();
+        $this->assertFalse(empty($grade_item->grade_grades_final));
+        $this->assertEqual($grade_item->id, $grade_item->grade_grades_final[1]->itemid);
+        $this->assertEqual(3, $grade_item->grade_grades_final[1]->gradescale);
+        $this->assertEqual(1, $grade_item->grade_grades_final[1]->userid);
     }
 
     function test_grade_item_toggle_locking() {
@@ -353,5 +361,48 @@ class grade_item_test extends gradelib_test {
         $this->assertTrue($grade_item->grade_grades_final[2]->hidden);
         $this->assertTrue($grade_item->grade_grades_final[3]->hidden);
     } 
+
+    function test_grade_item_generate_final() {
+        $grade_item = new grade_item();
+        $grade_item->courseid = $this->courseid;
+        $grade_item->categoryid = $this->grade_categories[1]->id;
+        $grade_item->itemname = 'unittestgradeitem4';
+        $grade_item->itemtype = 'mod';
+        $grade_item->itemmodule = 'quiz';
+        $grade_item->iteminfo = 'Grade item used for unit testing';
+
+        $grade_item->insert();
+
+        $grade_grades_raw = new grade_grades_raw();
+        $grade_grades_raw->itemid = $grade_item->id;
+        $grade_grades_raw->userid = 1;
+        $grade_grades_raw->gradevalue = 88;
+        $grade_grades_raw->grademax = 110;
+        $grade_grades_raw->grademin = 18;
+        $grade_grades_raw->insert();
+
+        $grade_grades_raw = new grade_grades_raw();
+        $grade_grades_raw->itemid = $grade_item->id;
+        $grade_grades_raw->userid = 2;
+        $grade_grades_raw->gradevalue = 68;
+        $grade_grades_raw->grademax = 110;
+        $grade_grades_raw->grademin = 18;
+        $grade_grades_raw->insert();
+
+        $grade_grades_raw = new grade_grades_raw();
+        $grade_grades_raw->itemid = $grade_item->id;
+        $grade_grades_raw->userid = 3;
+        $grade_grades_raw->gradevalue = 81;
+        $grade_grades_raw->grademax = 110;
+        $grade_grades_raw->grademin = 18;
+        $grade_grades_raw->insert();
+
+        $grade_item->load_raw();
+        $this->assertEqual(3, count($grade_item->grade_grades_raw));
+
+        $grade_item->generate_final();
+        $this->assertEqual(3, count($grade_item->grade_grades_final));
+
+    }
 } 
 ?>
index c5d113fbf8dd3b08328427c5ed5edf7cac4376e1..23f61a0897606178eb52a5eb5e4ca487208e1e00 100644 (file)
@@ -61,7 +61,6 @@ class grade_outcome_test extends gradelib_test {
         $this->assertEqual($grade_outcome->id, $last_grade_outcome->id + 1);
         $this->assertFalse(empty($grade_outcome->timecreated));
         $this->assertFalse(empty($grade_outcome->timemodified));
-        $this->grade_outcomes[] = $grade_outcome; 
     }
 
     function test_grade_outcome_update() {
index d67490605a75aa25c09aa2d671e5a39c3a265fb2..d69a70f879bda829ba443e1c82cafe0558caf155 100755 (executable)
@@ -67,8 +67,6 @@ class grade_raw_test extends gradelib_test {
         $this->assertEqual($grade_grades_raw->id, $last_grade_grades_raw->id + 1);
         $this->assertFalse(empty($grade_grades_raw->timecreated));
         $this->assertFalse(empty($grade_grades_raw->timemodified));
-        $this->grade_grades_raw[] = $grade_grades_raw; 
-
     }
 
     function test_grade_grades_raw_update() {
index e4e75a67ca51e02f587ac2621a60f71c878f5c0d..c4bf9e2771608f1c0ff96410f8edc325b6410da7 100755 (executable)
@@ -71,8 +71,6 @@ class grade_scale_test extends gradelib_test {
         $this->assertEqual($grade_scale->id, $last_grade_scale->id + 1);
         $this->assertTrue(!empty($grade_scale->timecreated));
         $this->assertTrue(!empty($grade_scale->timemodified));
-        $this->scale[] = $grade_scale; 
-
     }
 
     function test_grade_scale_update() {
index fa29636e94340529c42f287a15a5a3bd7ccc6cd8..e4b0d02f64c0d8c8e3cdf945ec0bfc996c3a505c 100755 (executable)
@@ -73,8 +73,6 @@ class grade_text_test extends gradelib_test {
         $this->assertFalse(empty($grade_grades_text->timecreated));
         $this->assertFalse(empty($grade_grades_text->timemodified));
         $this->assertEqual($USER->id, $grade_grades_text->usermodified);
-        $this->grade_grades_text[] = $grade_grades_text; 
-
     }
 
     function test_grade_grades_text_update() {