*/
var $grade_grades_raw = array();
+ /**
+ * Array of grade_grades_final objects linked to this grade_item. They are indexed by userid.
+ * @var array $grade_grades_final
+ */
+ var $grade_grades_final = array();
+
/**
* Finds and returns a grade_item object based on 1-3 field values.
*
* requested. Also resets the needs_update flag once successfully performed.
*
* @param int $userid
- * @param string $howmodified What caused the modification? manual/module/import/cron...
- * @param string $note A note attached to this modification.
- * @return boolean Success or failure
+ * @return int Number of grades updated, or false if error
*/
- function update_final_grade($userid=NULL, $howmodified='manual', $note=NULL) {
+ function update_final_grade($userid=NULL) {
if (empty($this->grade_grades_final)) {
$this->load_final();
}
+ if (empty($this->grade_grades_raw)) {
+ $this->load_raw();
+ }
- // TODO implement parsing of formula and calculation MDL-9643
- foreach ($this->grade_grades_final as $f) {
- $newgradevalue = 0; // TODO replace '0' with calculated value
- $f->update($newgradevalue, $howmodified, $note);
+ $count = 0;
+
+ $grade_final_array = array();
+
+ if (!empty($userid)) {
+ $grade_final_array[$userid] = $this->grade_grades_final[$userid];
+ } else {
+ $grade_final_array = $this->grade_grades_final;
}
- return true;
+ foreach ($grade_raw_array as $userid => $raw) {
+ $newgradevalue = $raw->gradevalue;
+
+ if (!empty($this->calculation)) {
+ $this->upgrade_calculation_to_object();
+ $newgradevalue = $this->calculation->compute($raw->gradevalue);
+ }
+
+ $final = $this->grade_grades_final[$userid];
+
+ $final->gradevalue = $this->adjust_grade($raw, $newgradevalue);
+ if ($final->update($newgradevalue)) {
+ $count++;
+ } else {
+ return false;
+ }
+ }
+
+ return $count;
+ }
+
+ /**
+ * Use this when the calculation object is a stdClass (rare) and you need it to have full
+ * object status (with methods and all).
+ */
+ function upgrade_calculation_to_object() {
+ if (!is_a($this->calculation, 'grade_calculation')) {
+ $this->calculation = new grade_calculation($this->calculation, false);
+ }
+ }
+
+ /**
+ * 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)
+ * @return mixed
+ */
+ function adjust_grade($grade_raw, $gradevalue=NULL) {
+ if (!empty($grade_raw->gradevalue)) { // Dealing with numerical grade
+ if (empty($gradevalue)) {
+ $gradevalue = $grade_raw->gradevalue;
+ }
+ } elseif(!empty($grade_raw->gradescale)) { // Dealing with a scale value
+ if (empty($gradevalue)) {
+ $gradevalue = $grade_raw->gradescale;
+ }
+
+ } else { // Something's wrong, the raw grade has no value!?
+
+ }
+
+ $raw_diff = $grade_raw->grademax - $grade_raw->grademin;
+ $item_diff = $this->grademax - $this->grademin;
+ $min_diff = $grade_raw->grademin - $this->grademin;
+
+ $diff_factor = max($raw_diff, $item_diff) / min($raw_diff, $item_diff);
+
+ if ($raw_diff > $item_diff) {
+ $gradevalue = $gradevalue / $diff_factor;
+ } else {
+ $gradevalue = $gradevalue * $diff_factor;
+ }
+
+ // Apply factors
+ $gradevalue *= $this->multfactor;
+ $gradevalue += $this->plusfactor;
+
+ return $gradevalue;
}
}
?>
$this->assertEqual($this->grade_categories[0]->fullname, $category->fullname);
}
+ /**
+ * Test update of all final grades
+ */
+ function test_grade_item_update_final_grades() {
+ $grade_item = new grade_item($this->grade_items[0]);
+ $this->assertTrue(method_exists($grade_item, 'update_final_grade'));
+ $this->assertEqual(3, $grade_item->update_final_grade());
+ $this->assertEqual(1, $grade_item->update_final_grade(1));
+ }
+
+ /**
+ * Test loading of raw and final items into grade_item.
+ */
+ function test_grade_item_load() {
+ $grade_item = new grade_item($this->grade_items[0]);
+ $this->assertTrue(method_exists($grade_item, 'load_final'));
+ $this->assertTrue(method_exists($grade_item, 'load_raw'));
+
+ // Check that final and raw items are not yet loaded
+ $this->assertTrue(empty($grade_item->grade_grades_final));
+ $this->assertTrue(empty($grade_item->grade_grades_raw));
+
+ // Load raw and final grades
+ $grade_item->load_final();
+ $grade_item->load_raw();
+
+ // Check that final and raw grades are now loaded
+ $this->assertFalse(empty($grade_item->grade_grades_final));
+ $this->assertFalse(empty($grade_item->grade_grades_raw));
+ $this->assertEqual($this->grade_grades_final[0]->gradevalue, $grade_item->grade_grades_final[1]->gradevalue);
+ $this->assertEqual($this->grade_grades_raw[0]->gradevalue, $grade_item->grade_grades_raw[1]->gradevalue);
+ }
+
+ /**
+ * Test the adjust_grade method
+ */
+ function test_grade_item_adjust_grade() {
+ $grade_item = new grade_item($this->grade_items[0]);
+ $this->assertTrue(method_exists($grade_item, 'adjust_grade'));
+ $grade_raw = new stdClass();
+ $grade_raw->gradevalue = 40;
+ $grade_raw->grademax = 100;
+ $grade_raw->grademin = 0;
+ $grade_item->multfactor = 1;
+ $grade_item->plusfactor = 0;
+ $grade_item->grademax = 50;
+ $grade_item->grademin = 0;
+
+ $this->assertEqual(20, $grade_item->adjust_grade($grade_raw));
+
+ $grade_item->grademax = 150;
+ $grade_item->grademin = 0;
+
+ $this->assertEqual(60, $grade_item->adjust_grade($grade_raw));
+
+ $grade_item->grademax = 150;
+ $grade_item->grademin = 50;
+
+ $this->assertEqual(40, $grade_item->adjust_grade($grade_raw));
+ }
+
// GRADE_CATEGORY OBJECT
function test_grade_category_construct() {