mirror of
https://github.com/moodle/moodle.git
synced 2025-08-06 17:36:38 +02:00
MDL-48634 grades: Add an option to rescale when changing the maxgrade
This commit is contained in:
parent
9d5d9c64ff
commit
d629c601c5
12 changed files with 422 additions and 11 deletions
|
@ -354,6 +354,20 @@ class grade_item extends grade_object {
|
|||
return grade_object::fetch_helper('grade_items', 'grade_item', $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if there are any existing grades for this grade_item.
|
||||
*
|
||||
* @return boolean - true if there are valid grades for this grade_item.
|
||||
*/
|
||||
public function has_grades() {
|
||||
global $DB;
|
||||
|
||||
$count = $DB->count_records_select('grade_grades',
|
||||
'itemid = :gradeitemid AND finalgrade IS NOT NULL',
|
||||
array('gradeitemid' => $this->id));
|
||||
return $count > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and returns all grade_item instances based on params.
|
||||
*
|
||||
|
@ -819,6 +833,60 @@ class grade_item extends grade_object {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the rawgrademax and rawgrademin for all grade_grades records for this item.
|
||||
* Scale every rawgrade to maintain the percentage. This function should be called
|
||||
* after the gradeitem has been updated to the new min and max values.
|
||||
*
|
||||
* @param float $oldgrademin The previous grade min value
|
||||
* @param float $oldgrademax The previous grade max value
|
||||
* @param float $newgrademin The new grade min value
|
||||
* @param float $newgrademax The new grade max value
|
||||
* @param string $source from where was the object inserted (mod/forum, manual, etc.)
|
||||
* @return bool True on success
|
||||
*/
|
||||
public function rescale_grades_keep_percentage($oldgrademin, $oldgrademax, $newgrademin, $newgrademax, $source = null) {
|
||||
global $DB;
|
||||
|
||||
if (empty($this->id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($oldgrademax <= $oldgrademin) {
|
||||
// Grades cannot be scaled.
|
||||
return false;
|
||||
}
|
||||
$scale = ($newgrademax - $newgrademin) / ($oldgrademax - $oldgrademin);
|
||||
if (($newgrademax - $newgrademin) <= 1) {
|
||||
// We would lose too much precision, lets bail.
|
||||
return false;
|
||||
}
|
||||
|
||||
$rs = $DB->get_recordset('grade_grades', array('itemid' => $this->id));
|
||||
|
||||
foreach ($rs as $graderecord) {
|
||||
// For each record, create an object to work on.
|
||||
$grade = new grade_grade($graderecord, false);
|
||||
// Set this object in the item so it doesn't re-fetch it.
|
||||
$grade->grade_item = $this;
|
||||
|
||||
// Updating the raw grade automatically updates the min/max.
|
||||
if ($this->is_raw_used()) {
|
||||
$rawgrade = (($grade->rawgrade - $oldgrademin) * $scale) + $newgrademin;
|
||||
$this->update_raw_grade(false, $rawgrade, $source, false, FORMAT_MOODLE, null, null, null, $grade);
|
||||
} else {
|
||||
$finalgrade = (($grade->finalgrade - $oldgrademin) * $scale) + $newgrademin;
|
||||
$this->update_final_grade($grade->userid, $finalgrade, $source);
|
||||
}
|
||||
}
|
||||
$rs->close();
|
||||
|
||||
// Mark this item for regrading.
|
||||
$this->force_regrading();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this grade_item's needsupdate to true. Also marks the course item as needing update.
|
||||
*
|
||||
|
@ -1649,6 +1717,8 @@ class grade_item extends grade_object {
|
|||
$oldgrade->overridden = $grade->overridden;
|
||||
$oldgrade->feedback = $grade->feedback;
|
||||
$oldgrade->feedbackformat = $grade->feedbackformat;
|
||||
$oldgrade->rawgrademin = $grade->rawgrademin;
|
||||
$oldgrade->rawgrademax = $grade->rawgrademax;
|
||||
|
||||
// MDL-31713 rawgramemin and max must be up to date so conditional access %'s works properly.
|
||||
$grade->rawgrademin = $this->grademin;
|
||||
|
@ -1687,6 +1757,8 @@ class grade_item extends grade_object {
|
|||
} else if (grade_floats_different($grade->finalgrade, $oldgrade->finalgrade)
|
||||
or $grade->feedback !== $oldgrade->feedback
|
||||
or $grade->feedbackformat != $oldgrade->feedbackformat
|
||||
or grade_floats_different($grade->rawgrademin, $oldgrade->rawgrademin)
|
||||
or grade_floats_different($grade->rawgrademax, $oldgrade->rawgrademax)
|
||||
or ($oldgrade->overridden == 0 and $grade->overridden > 0)) {
|
||||
$grade->timemodified = time(); // hack alert - date graded
|
||||
$result = $grade->update($source);
|
||||
|
|
|
@ -50,6 +50,7 @@ class core_grade_item_testcase extends grade_base_testcase {
|
|||
$this->sub_test_grade_item_load_item_category();
|
||||
$this->sub_test_grade_item_regrade_final_grades();
|
||||
$this->sub_test_grade_item_adjust_raw_grade();
|
||||
$this->sub_test_grade_item_rescale_grades_keep_percentage();
|
||||
$this->sub_test_grade_item_set_locked();
|
||||
$this->sub_test_grade_item_is_locked();
|
||||
$this->sub_test_grade_item_set_hidden();
|
||||
|
@ -371,6 +372,46 @@ class core_grade_item_testcase extends grade_base_testcase {
|
|||
$this->assertEquals(round(1.6), round($grade_item->adjust_raw_grade($grade_raw->rawgrade, $grade_raw->grademin, $grade_raw->grademax)));
|
||||
}
|
||||
|
||||
protected function sub_test_grade_item_rescale_grades_keep_percentage() {
|
||||
global $DB;
|
||||
$gradeitem = new grade_item($this->grade_items[10], false); // 10 is the manual grade item.
|
||||
|
||||
// Create some grades to go with the grade item.
|
||||
$gradeids = array();
|
||||
$grade = new stdClass();
|
||||
$grade->itemid = $gradeitem->id;
|
||||
$grade->userid = $this->user[2]->id;
|
||||
$grade->finalgrade = 10;
|
||||
$grade->rawgrademax = $gradeitem->grademax;
|
||||
$grade->rawgrademin = $gradeitem->grademin;
|
||||
$grade->timecreated = time();
|
||||
$grade->timemodified = time();
|
||||
$gradeids[] = $DB->insert_record('grade_grades', $grade);
|
||||
|
||||
$grade->userid = $this->user[3]->id;
|
||||
$grade->finalgrade = 50;
|
||||
$grade->rawgrademax = $gradeitem->grademax;
|
||||
$grade->rawgrademin = $gradeitem->grademin;
|
||||
$gradeids[] = $DB->insert_record('grade_grades', $grade);
|
||||
|
||||
// Run the function.
|
||||
$gradeitem->grademax = 33;
|
||||
$gradeitem->grademin = 3;
|
||||
$gradeitem->update();
|
||||
$gradeitem->rescale_grades_keep_percentage(0, 100, 3, 33, 'test');
|
||||
|
||||
// Check that the grades were updated to match the grade item.
|
||||
$grade = $DB->get_record('grade_grades', array('id' => $gradeids[0]));
|
||||
$this->assertEquals($gradeitem->grademax, $grade->rawgrademax, 'Max grade mismatch', 0.0001);
|
||||
$this->assertEquals($gradeitem->grademin, $grade->rawgrademin, 'Min grade mismatch', 0.0001);
|
||||
$this->assertEquals(6, $grade->finalgrade, 'Min grade mismatch', 0.0001);
|
||||
|
||||
$grade = $DB->get_record('grade_grades', array('id' => $gradeids[1]));
|
||||
$this->assertEquals($gradeitem->grademax, $grade->rawgrademax, 'Max grade mismatch', 0.0001);
|
||||
$this->assertEquals($gradeitem->grademin, $grade->rawgrademin, 'Min grade mismatch', 0.0001);
|
||||
$this->assertEquals(18, $grade->finalgrade, 'Min grade mismatch', 0.0001);
|
||||
}
|
||||
|
||||
protected function sub_test_grade_item_set_locked() {
|
||||
// Getting a grade_item from the DB as set_locked() will fail if the grade items needs to be updated
|
||||
// also needs to have at least one grade_grade or $grade_item->get_final(1) returns null.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue