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

This commit is contained in:
skodak
2008-03-12 19:44:39 +00:00
parent 5673b0ce58
commit 65299ae590
5 changed files with 78 additions and 27 deletions
+3
View File
@@ -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
}
}
+2 -2
View File
@@ -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');
}
+16 -2
View File
@@ -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);
}
}
?>
+30 -20
View File
@@ -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');
}
+27 -3
View File
@@ -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));
}
?>