]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-9506 Finished grade_item::adjust_grade, which now also adjusts scale grades corre...
authornicolasconnault <nicolasconnault>
Tue, 1 May 2007 05:45:54 +0000 (05:45 +0000)
committernicolasconnault <nicolasconnault>
Tue, 1 May 2007 05:45:54 +0000 (05:45 +0000)
lib/grade/grade_grades_raw.php
lib/grade/grade_item.php
lib/gradelib.php
lib/simpletest/testgradelib.php

index 02b81c4e09bedb8820b5e9683934336a9a318a45..79216c3d98f4ccbebcbb6c2ce6cdce9c58934779 100644 (file)
@@ -36,7 +36,7 @@ class grade_grades_raw extends grade_object {
      * Array of class variables that are not part of the DB table fields
      * @var array $nonfields
      */
-    var $nonfields = array('table', 'nonfields');
+    var $nonfields = array('table', 'nonfields', 'scale');
     
     /**
      * The id of the grade_item this raw grade belongs to.
@@ -79,7 +79,13 @@ class grade_grades_raw extends grade_object {
      * @var int $scaleid
      */
     var $scaleid;
-    
+   
+    /**
+     * A grade_scale object (referenced by $this->scaleid).
+     * @var object $scale
+     */
+    var $scale;
+
     /**
      * The userid of the person who last modified this grade.
      * @var int $usermodified
@@ -93,6 +99,10 @@ class grade_grades_raw extends grade_object {
      */
     function grade_grades_raw($params=NULL, $fetch=true) {
         $this->grade_object($params, $fetch);
+        if (!empty($this->scaleid)) {
+            $this->scale = new grade_scale(array('id' => $this->scaleid));
+            $this->scale->load_items();
+        }
     }
 
 
@@ -138,6 +148,11 @@ class grade_grades_raw extends grade_object {
         global $USER;
         $oldgrade = $this->gradevalue;
         $this->gradevalue = $newgrade;
+        
+        // Update this scaleid if it has changed (use the largest integer (most recent))
+        if ($this->scale->id != $this->scaleid) {
+            $this->scaleid = max($this->scale->id, $this->scaleid);
+        }
 
         $result = parent::update();
         
index c19670322cc4c2242d5b78ef6f4d6e79548b1490..00d865cf83854b9184a3417d1d4423a3399f032f 100644 (file)
@@ -40,7 +40,7 @@ class grade_item extends grade_object {
      * Array of class variables that are not part of the DB table fields
      * @var array $nonfields
      */
-    var $nonfields = array('table', 'nonfields', 'calculation', 'grade_grades_raw');
+    var $nonfields = array('table', 'nonfields', 'calculation', 'grade_grades_raw', 'scale');
   
     /**
      * The course this grade_item belongs to.
@@ -109,11 +109,17 @@ class grade_item extends grade_object {
     var $grademin;
     
     /**
-     * The scale this grade is based on, if applicable.
+     * id of the scale, if this grade is based on a scale.
+     * @var int $scaleid
+     */
+    var $scaleid;
+   
+    /**
+     * A grade_scale object (referenced by $this->scaleid).
      * @var object $scale
      */
     var $scale;
-    
+
     /**
      * The Outcome this grade is associated with, if applicable.
      * @var object $outcome
@@ -180,6 +186,19 @@ class grade_item extends grade_object {
      */
     var $grade_grades_final = array();
 
+    /**
+     * Constructor. Extends the basic functionality defined in grade_object.
+     * @param array $params Can also be a standard object.
+     * @param boolean $fetch Wether or not to fetch the corresponding row from the DB.
+     */
+    function grade_item($params=NULL, $fetch=true) {
+        $this->grade_object($params, $fetch);
+        if (!empty($this->scaleid)) {
+            $this->scale = new grade_scale(array('id' => $this->scaleid));
+            $this->scale->load_items();
+        }
+    }
+
     /**
      * Finds and returns a grade_item object based on 1-3 field values.
      *
@@ -433,33 +452,48 @@ class grade_item extends grade_object {
      * @return mixed 
      */
     function adjust_grade($grade_raw, $gradevalue=NULL) {
+        $raw_offset = 0;
+        $item_offset = 0;
+
         if (!empty($grade_raw->gradevalue)) { // Dealing with numerical grade
             if (empty($gradevalue)) {
                 $gradevalue = $grade_raw->gradevalue;
             }
+            
+            // Adjust both scales to 0-? and store offsets
+            $raw_offset = -(0 - $grade_raw->grademin);
+            $item_offset = -(0 - $this->grademin);
+            $raw_adjusted_max = $grade_raw->grademax - $raw_offset;
+            $item_adjusted_max = $this->grademax - $item_offset;
+
         } elseif(!empty($grade_raw->gradescale)) { // Dealing with a scale value
             if (empty($gradevalue)) {
                 $gradevalue = $grade_raw->gradescale;
             }
+            
+            $raw_adjusted_max = count($grade_raw->scale->scale_items) - 1;
+            $item_adjusted_max = count($this->scale->scale_items) - 1;
 
         } else { // Something's wrong, the raw grade has no value!?
-
+            return false;
         }
-
-        // Adjust both scales to 0-? and store offsets
-        $raw_offset = -(0 - $grade_raw->grademin);
-        $item_offset = -(0 - $this->grademin);
-        $raw_adjusted_max = $grade_raw->grademax - $raw_offset;
-        $item_adjusted_max = $this->grademax - $item_offset;
-        
-        // Compute factor from adjusted scales
+        // Compute factor from grademax of adjusted scales
         $factor = ($item_adjusted_max) / ($raw_adjusted_max);
+        
+        // Multiply adjusted grade value (using source offset) by factor
         $gradevalue = ($gradevalue - $raw_offset) * $factor;
-        $gradevalue += $item_offset;
 
-        // Apply factors
-        $gradevalue *= $this->multfactor;
-        $gradevalue += $this->plusfactor;
+        // Add target offset to resulting grade value
+        $gradevalue += $item_offset;
+        
+        // Apply rounding or factors, depending on whether it's a scale or value
+        if (!empty($grade_raw->gradevalue)) {
+            // Apply other grade_item factors
+            $gradevalue *= $this->multfactor;
+            $gradevalue += $this->plusfactor;
+        } elseif (!empty($grade_raw->gradescale)) {
+            $gradevalue = (int) round($gradevalue);
+        }
 
         return $gradevalue;
     }
index e713d59e8b304e7476194b510e887bbe307dc2ca..ff1e3028a6639701ea5c0a534b23a2f3dd73d5f0 100644 (file)
@@ -42,6 +42,7 @@ require_once($CFG->libdir . '/grade/grade_item.php');
 require_once($CFG->libdir . '/grade/grade_calculation.php');
 require_once($CFG->libdir . '/grade/grade_grades_raw.php');
 require_once($CFG->libdir . '/grade/grade_grades_final.php');
+require_once($CFG->libdir . '/grade/grade_scale.php');
 
 /**
 * Extracts from the gradebook all the grade items attached to the calling object. 
index 56a0d331fc6c434cc8ef3cb73528162cfca284ef..954b34ad03f4ced4ca095a477aa5dd1aa9e65120 100644 (file)
@@ -41,11 +41,14 @@ require_once($CFG->libdir . '/dmllib.php');
 
 /**
  * A cleanup of the tables is a good idea before we start, in case the last unit test
- * crashed before running its tearDown method.
+ * crashed before running its tearDown method. Be careful because ANY record matching
+ * this search (%unittest%) will be deleted! Maybe a good idea to switch this off in
+ * production environment.
  */
 delete_records_select('grade_categories', 'fullname LIKE "%unittest%"');
 delete_records_select('grade_items', 'itemname LIKE "%unittest%"');
 delete_records_select('grade_calculation', 'calculation LIKE "%unittest%"');
+delete_records_select('scale', 'name LIKE "%unittest%"');
 
 class gradelib_test extends UnitTestCase {
    
@@ -62,7 +65,8 @@ class gradelib_test extends UnitTestCase {
                         'grade_grades_final',
                         'grade_grades_text',
                         'grade_outcomes',
-                        'grade_history');
+                        'grade_history',
+                        'scale');
 
     var $grade_items = array();
     var $grade_categories = array();
@@ -72,6 +76,7 @@ class gradelib_test extends UnitTestCase {
     var $grade_grades_text = array();
     var $grade_outcomes = array();
     var $grade_history = array();
+    var $scale = array();
 
     var $courseid = 1;
     var $userid = 1;
@@ -472,6 +477,36 @@ class gradelib_test extends UnitTestCase {
 
     }
 
+    /**
+     * Load scale data into the database, and adds the corresponding objects to this class' variable.
+     */
+    function load_scale() {
+        $scale = new stdClass();
+        
+        $scale->name        = 'unittestscale1';
+        $scale->courseid    = $this->courseid;
+        $scale->userid      = $this->userid;
+        $scale->scale       = 'Way off topic, Not very helpful, Fairly neutral, Fairly helpful, Supportive, Some good information, Perfect answer!';
+        $scale->description = 'This scale defines some of qualities that make posts helpful within the Moodle help forums.\n Your feedback will help others see how their posts are being received.';
+        $scale->timemodified = mktime();
+        
+        if ($scale->id = insert_record('scale', $scale)) {
+            $this->scale[] = $scale;
+        } 
+
+        $scale = new stdClass();
+        
+        $scale->name        = 'unittestscale2';
+        $scale->courseid    = $this->courseid;
+        $scale->userid      = $this->userid;
+        $scale->scale       = 'Distinction, Very Good, Good, Pass, Fail';
+        $scale->description = 'This scale is used to mark standard assignments.';
+        $scale->timemodified = mktime();
+        
+        if ($scale->id = insert_record('scale', $scale)) {
+            $this->scale[] = $scale;
+        } 
+    }
 /** 
  * TESTS BEGIN HERE
  */
@@ -537,7 +572,7 @@ class gradelib_test extends UnitTestCase {
         $params->iteminstance = 4;
         $params->iteminfo = 'Grade item used for unit testing';
 
-        $grade_item = new grade_item($params);
+        $grade_item = new grade_item($params, false);
 
         $this->assertEqual($params->courseid, $grade_item->courseid);
         $this->assertEqual($params->categoryid, $grade_item->categoryid);
@@ -752,7 +787,6 @@ class gradelib_test extends UnitTestCase {
         // Try a larger maximum grade
         $grade_item->grademax = 150;
         $grade_item->grademin = 0;
-
         $this->assertEqual(60, $grade_item->adjust_grade($grade_raw)); 
 
         // Try larger minimum grade
@@ -791,6 +825,22 @@ class gradelib_test extends UnitTestCase {
         $this->assertEqual(round(1.6), round($grade_item->adjust_grade($grade_raw))); 
     }
 
+    function test_grade_item_adjust_scale_grade() {
+        // Load raw grade and its scale
+        $grade_raw = new grade_grades_raw(array('scaleid' => $this->scale[0]->id));
+        $grade_raw->gradescale = 4;
+        $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));
+        $this->assertEqual('Very Good', $grade_item->scale->scale_items[1]);
+
+        // Test grade_item::adjust_scale
+        $this->assertEqual(3, $grade_item->adjust_grade($grade_raw));
+        $grade_raw->gradescale = 6;
+        $this->assertEqual(4, $grade_item->adjust_grade($grade_raw));
+    }
+
 // GRADE_CATEGORY OBJECT
 
     function test_grade_category_construct() {
@@ -815,6 +865,46 @@ class gradelib_test extends UnitTestCase {
 
 // GRADE_CALCULATION OBJECT
 
+// SCALE OBJECT
+
+    function test_scale_constructor() {
+        $params = new stdClass();
+        
+        $params->name        = 'unittestscale3';
+        $params->courseid    = $this->courseid;
+        $params->userid      = $this->userid;
+        $params->scale       = 'Distinction, Very Good, Good, Pass, Fail';
+        $params->description = 'This scale is used to mark standard assignments.';
+        $params->timemodified = mktime();
+        
+        $scale = new grade_scale($params, false);
+
+        $this->assertEqual($params->name, $scale->name);
+        $this->assertEqual($params->scale, $scale->scale);
+        $this->assertEqual($params->description, $scale->description);
+
+    }
+
+    function test_scale_load_items() {
+        $scale = new grade_scale($this->scale[0]);
+        $this->assertTrue(method_exists($scale, 'load_items'));
+
+        $scale->load_items();
+        $this->assertEqual(7, count($scale->scale_items));
+        $this->assertEqual('Fairly neutral', $scale->scale_items[2]);
+    }
+
+    function test_scale_compact_items() {
+        $scale = new grade_scale($this->scale[0]);
+        $this->assertTrue(method_exists($scale, 'compact_items'));
+
+        $scale->load_items();
+        $scale->scale = null;
+        $scale->compact_items();
+        
+        // The original string and the new string may have differences in whitespace around the delimiter, and that's OK 
+        $this->assertEqual(preg_replace('/\s*,\s*/', ',', $this->scale[0]->scale), $scale->scale);
+    }
 // SCENARIOS: define use cases here by defining tests and implementing code until the tests pass.
 
 }