From 25bcd90821162e526bd124696b62eb8b918ba657 Mon Sep 17 00:00:00 2001 From: skodak Date: Wed, 12 Mar 2008 19:45:17 +0000 Subject: [PATCH] MDL-13845 rewritten rounding in grades classes again - rounding done also before storage into db so that we can compare the values properly and skip db updates if possible + some more optimisations; merged from MOODLE_19_STABLE --- grade/edit/tree/grade.php | 3 +++ lib/grade/grade_category.php | 4 +-- lib/grade/grade_grade.php | 18 +++++++++++-- lib/grade/grade_item.php | 50 +++++++++++++++++++++--------------- lib/gradelib.php | 30 +++++++++++++++++++--- 5 files changed, 78 insertions(+), 27 deletions(-) diff --git a/grade/edit/tree/grade.php b/grade/edit/tree/grade.php index 52f027ce87..4e5e28696a 100644 --- a/grade/edit/tree/grade.php +++ b/grade/edit/tree/grade.php @@ -217,6 +217,9 @@ if ($mform->is_cancelled()) { } else { $grade_grade->set_locktime($data->locktime); //set_lock may reset locktime $grade_grade->set_locked($data->locked, false, true); + // reload grade in case it was regraded from activity + $grade_grade = new grade_grade(array('userid'=>$data->userid, 'itemid'=>$grade_item->id), true); + $grade_grade->grade_item =& $grade_item; // no db fetching } } diff --git a/lib/grade/grade_category.php b/lib/grade/grade_category.php index 114d3195aa..d678c1a9da 100644 --- a/lib/grade/grade_category.php +++ b/lib/grade/grade_category.php @@ -571,7 +571,7 @@ class grade_category extends grade_object { } // update in db if changed - if (grade_floatval($grade->finalgrade) !== grade_floatval($oldfinalgrade)) { + if (grade_floats_different($grade->finalgrade, $oldfinalgrade)) { $grade->update('aggregation'); } @@ -732,7 +732,7 @@ class grade_category extends grade_object { $grade->finalgrade = bounded_number($this->grade_item->grademin, $sum, $this->grade_item->grademax); // update in db if changed - if (grade_floatval($grade->finalgrade) !== grade_floatval($oldfinalgrade)) { + if (grade_floats_different($grade->finalgrade, $oldfinalgrade)) { $grade->update('aggregation'); } diff --git a/lib/grade/grade_grade.php b/lib/grade/grade_grade.php index 7c72ef4bcc..5c291c7d5a 100644 --- a/lib/grade/grade_grade.php +++ b/lib/grade/grade_grade.php @@ -366,8 +366,8 @@ class grade_grade extends grade_object { $this->locked = 0; $this->update(); - if ($refresh) { - //refresh when unlocking + if ($refresh and !$this->is_overridden()) { + //refresh when unlocking and not overridden $this->grade_item->refresh_grades($this->userid); } @@ -719,5 +719,19 @@ class grade_grade extends grade_object { $this->timecreated = $this->timemodified = time(); return parent::insert($source); } + + /** + * In addition to update() as defined in grade_object rounds the float numbers using php function, + * the reason is we need to compare the db value with computed number to skip updates if possible. + * @param string $source from where was the object inserted (mod/forum, manual, etc.) + * @return boolean success + */ + function update($source=null) { + $this->rawgrade = grade_floatval($this->rawgrade); + $this->finalgrade = grade_floatval($this->finalgrade); + $this->rawgrademin = grade_floatval($this->rawgrademin); + $this->rawgrademax = grade_floatval($this->rawgrademax); + return parent::update($source); + } } ?> diff --git a/lib/grade/grade_item.php b/lib/grade/grade_item.php index 0eb79ec915..c4a11fbf8d 100644 --- a/lib/grade/grade_item.php +++ b/lib/grade/grade_item.php @@ -245,7 +245,8 @@ class grade_item extends grade_object { /** * In addition to update() as defined in grade_object, handle the grade_outcome and grade_scale objects. - * Force regrading if necessary + * Force regrading if necessary, rounds the float numbers using php function, + * the reason is we need to compare the db value with computed number to skip regrading if possible. * @param string $source from where was the object inserted (mod/forum, manual, etc.) * @return boolean success */ @@ -267,6 +268,12 @@ class grade_item extends grade_object { $this->timemodified = time(); + $this->grademin = grade_floatval($this->grademin); + $this->grademax = grade_floatval($this->grademax); + $this->multfactor = grade_floatval($this->multfactor); + $this->plusfactor = grade_floatval($this->plusfactor); + $this->aggregationcoef = grade_floatval($this->aggregationcoef); + return parent::update($source); } @@ -286,14 +293,14 @@ class grade_item extends grade_object { $calculationdiff = $db_item->calculation != $this->calculation; $categorydiff = $db_item->categoryid != $this->categoryid; $gradetypediff = $db_item->gradetype != $this->gradetype; - $grademindiff = $db_item->grademin != $this->grademin; $scaleiddiff = $db_item->scaleid != $this->scaleid; $outcomeiddiff = $db_item->outcomeid != $this->outcomeid; $locktimediff = $db_item->locktime != $this->locktime; - $grademaxdiff = grade_floatval($db_item->grademax) !== grade_floatval($this->grademax); - $multfactordiff = grade_floatval($db_item->multfactor) !== grade_floatval($this->multfactor); - $plusfactordiff = grade_floatval($db_item->plusfactor) !== grade_floatval($this->plusfactor); - $acoefdiff = grade_floatval($db_item->aggregationcoef) !== grade_floatval($this->aggregationcoef); + $grademindiff = grade_floats_different($db_item->grademin, $this->grademin); + $grademaxdiff = grade_floats_different($db_item->grademax, $this->grademax); + $multfactordiff = grade_floats_different($db_item->multfactor, $this->multfactor); + $plusfactordiff = grade_floats_different($db_item->plusfactor, $this->plusfactor); + $acoefdiff = grade_floats_different($db_item->aggregationcoef, $this->aggregationcoef); $needsupdatediff = !$db_item->needsupdate && $this->needsupdate; // force regrading only if setting the flag first time $lockeddiff = !empty($db_item->locked) && empty($this->locked); // force regrading only when unlocking @@ -683,7 +690,7 @@ class grade_item extends grade_object { $grade->finalgrade = $this->adjust_raw_grade($grade->rawgrade, $grade->rawgrademin, $grade->rawgrademax); - if (grade_floatval($grade_record->finalgrade) !== grade_floatval($grade->finalgrade)) { + if (grade_floats_different($grade_record->finalgrade, $grade->finalgrade)) { if (!$grade->update('system')) { $result = "Internal error updating final grade"; } @@ -965,7 +972,7 @@ class grade_item extends grade_object { */ // first detect if we need to change calculation formula from [[idnumber]] to ##giXXX## (after backup, etc.) - if (!$this->calculation_normalized and strpos('[[', $this->calculation) !== 0) { + if (!$this->calculation_normalized and strpos('[[', $this->calculation) !== false) { $this->set_calculation($this->calculation); } @@ -1126,6 +1133,9 @@ class grade_item extends grade_object { * @return void */ function set_sortorder($sortorder) { + if ($this->sortorder == $sortorder) { + return; + } $this->sortorder = $sortorder; $this->update(); } @@ -1393,9 +1403,9 @@ class grade_item extends grade_object { $grade->timemodified = time(); // overridden flag might take over, but anyway $result = (boolean)$grade->insert($source); - } else if (grade_floatval($grade->finalgrade) !== grade_floatval($oldgrade->finalgrade) - or grade_floatval($grade->feedback) !== grade_floatval($oldgrade->feedback) - or grade_floatval($grade->feedbackformat) !== grade_floatval($oldgrade->feedbackformat)) { + } else if (grade_floats_different($grade->finalgrade, $oldgrade->finalgrade) + or $grade->feedback !== $oldgrade->feedback + or $grade->feedbackformat != $oldgrade->feedbackformat) { $grade->timemodified = time(); // overridden flag might take over, but anyway $result = $grade->update($source); } else { @@ -1505,7 +1515,7 @@ class grade_item extends grade_object { } // do we have comment from teacher? - if ($feedback !== false) { + if ($feedback !== false and !$grade->is_overridden()) { $grade->feedback = $feedback; $grade->feedbackformat = $feedbackformat; } @@ -1522,13 +1532,13 @@ class grade_item extends grade_object { if (empty($grade->id)) { $result = (boolean)$grade->insert($source); - } else if (grade_floatval($grade->finalgrade) !== grade_floatval($oldgrade->finalgrade) - or grade_floatval($grade->rawgrade) !== grade_floatval($oldgrade->rawgrade) - or grade_floatval($grade->rawgrademin) !== grade_floatval($oldgrade->rawgrademin) - or grade_floatval($grade->rawgrademax) !== grade_floatval($oldgrade->rawgrademax) - or grade_floatval($grade->rawscaleid) !== grade_floatval($oldgrade->rawscaleid) - or grade_floatval($grade->feedback) !== grade_floatval($oldgrade->feedback) - or grade_floatval($grade->feedbackformat) !== grade_floatval($oldgrade->feedbackformat)) { + } else if (grade_floats_different($grade->finalgrade, $oldgrade->finalgrade) + or grade_floats_different($grade->rawgrade, $oldgrade->rawgrade) + or grade_floats_different($grade->rawgrademin, $oldgrade->rawgrademin) + or grade_floats_different($grade->rawgrademax, $oldgrade->rawgrademax) + or $grade->rawscaleid != $oldgrade->rawscaleid + or $grade->feedback !== $oldgrade->feedback + or $grade->feedbackformat != $oldgrade->feedbackformat) { $result = $grade->update($source); } else { return $result; @@ -1699,7 +1709,7 @@ class grade_item extends grade_object { } // update in db if changed - if (grade_floatval($grade->finalgrade) !== grade_floatval($oldfinalgrade)) { + if (grade_floats_different($grade->finalgrade, $oldfinalgrade)) { $grade->update('compute'); } diff --git a/lib/gradelib.php b/lib/gradelib.php index b3c993fd03..145db5ce0d 100644 --- a/lib/gradelib.php +++ b/lib/gradelib.php @@ -67,6 +67,8 @@ function grade_update($source, $courseid, $itemtype, $itemmodule, $iteminstance, // only following grade_item properties can be changed in this function $allowed = array('itemname', 'idnumber', 'gradetype', 'grademax', 'grademin', 'scaleid', 'multfactor', 'plusfactor', 'deleted', 'hidden'); + // list of 10,5 numeric fields + $floats = array('grademin', 'grademax', 'multfactor', 'plusfactor'); // grade item identification $params = compact('courseid', 'itemtype', 'itemmodule', 'iteminstance', 'itemnumber'); @@ -143,9 +145,17 @@ function grade_update($source, $courseid, $itemtype, $itemmodule, $iteminstance, // ignore it continue; } - if ($grade_item->{$k} != $v) { - $grade_item->{$k} = $v; - $update = true; + if (in_array($k, $floats)) { + if (grade_floats_different($grade_item->{$k}, $v)) { + $grade_item->{$k} = $v; + $update = true; + } + + } else { + if ($grade_item->{$k} != $v) { + $grade_item->{$k} = $v; + $update = true; + } } } if ($update) { @@ -1254,6 +1264,20 @@ function grade_floatval($number) { return null; } // we must round to 5 digits to get the same precision as in 10,5 db fields + // note: db rounding for 10,5 is different from php round() function return round($number, 5); } + +/** + * Compare two float numbers safely. Uses 5 decimals php precision. Nulls accepted too. + * Used for skipping of db updates + * @param float $f1 + * @param float $f2 + * @return true if different + */ +function grade_floats_different($f1, $f2) { + // note: db rounding for 10,5 is different from php round() function + return (grade_floatval($f1) !== grade_floatval($f2)); +} + ?> -- 2.39.5