From 45da5361132e6ea64e2fba1e25812cf3acb14120 Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Sun, 31 Aug 2014 19:08:50 +0800 Subject: [PATCH] MDL-47011 core_grade: added the ability to override grade_item weight --- grade/edit/tree/index.php | 22 +++++++++++++++++++++- grade/edit/tree/lib.php | 6 +++++- lang/en/grades.php | 1 + lib/db/install.xml | 1 + lib/db/upgrade.php | 12 ++++++++++++ lib/grade/grade_category.php | 19 +++++++++++++++++-- lib/grade/grade_item.php | 7 ++++++- 7 files changed, 63 insertions(+), 5 deletions(-) diff --git a/grade/edit/tree/index.php b/grade/edit/tree/index.php index b0e9ed3473a..129e6303f66 100644 --- a/grade/edit/tree/index.php +++ b/grade/edit/tree/index.php @@ -240,6 +240,21 @@ if ($data = data_submitted() and confirm_sesskey()) { $grade_edit_tree->move_elements($elements, $returnurl); } + // Preload grade_items so we can determine if weights have been manually changed or been automatically adjusted. + // As soon as we touch one grade item the others will be re-weighted automatically. + $oldgradeitems = Array(); + foreach ($data as $key => $value) { + if (preg_match('/^(aggregationcoef2)_([0-9]+)$/', $key, $matches)) { + $param = $matches[1]; + $aid = $matches[2]; + + $value = unformat_float($value); + $value = clean_param($value, PARAM_FLOAT); + + $oldgradeitems[$aid] = grade_item::fetch(array('id' => $aid, 'courseid' => $courseid)); + } + } + // Category and item field updates foreach ($data as $key => $value) { // Grade category text inputs @@ -267,12 +282,17 @@ if ($data = data_submitted() and confirm_sesskey()) { $value = unformat_float($value); $value = clean_param($value, PARAM_FLOAT); - $grade_item = grade_item::fetch(array('id'=>$aid, 'courseid'=>$courseid)); + $grade_item = $oldgradeitems[$aid]; if ($param === 'grademax' and $value < $grade_item->grademin) { // better not allow values lower than grade min $value = $grade_item->grademin; } + + if ($param === 'aggregationcoef2' && round($grade_item->aggregationcoef2, 4) != round($value, 4)) { + $grade_item->weightoverride = 1; + } + $grade_item->$param = $value; $grade_item->update(); diff --git a/grade/edit/tree/lib.php b/grade/edit/tree/lib.php index a3898e75a97..744b52d427c 100644 --- a/grade/edit/tree/lib.php +++ b/grade/edit/tree/lib.php @@ -396,10 +396,14 @@ class grade_edit_tree { get_string('extracreditvalue', 'grades', $item->itemname).' \n"; } else if ($aggcoef == 'aggregationcoefextrasum' && $type == 'weight') { + $label = ''; + if ($item->weightoverride) { + $label = get_string('adjusted', 'grades'); + } return ''. ''; + value="'.grade_edit_tree::format_number($item->aggregationcoef2).'" />'.$label; } else { return ''; } diff --git a/lang/en/grades.php b/lang/en/grades.php index a6362976e54..3b43a88bc7e 100644 --- a/lang/en/grades.php +++ b/lang/en/grades.php @@ -34,6 +34,7 @@ $string['additem'] = 'Add grade item'; $string['addoutcome'] = 'Add an outcome'; $string['addoutcomeitem'] = 'Add outcome item'; $string['addscale'] = 'Add a scale'; +$string['adjusted'] = 'Adjusted'; $string['aggregateextracreditmean'] = 'Mean of grades (with extra credits)'; $string['aggregatemax'] = 'Highest grade'; $string['aggregatemean'] = 'Mean of grades'; diff --git a/lib/db/install.xml b/lib/db/install.xml index c8689163fab..1c935d558ed 100755 --- a/lib/db/install.xml +++ b/lib/db/install.xml @@ -1725,6 +1725,7 @@ + diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index 73dbcdc854e..277adb6b50e 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -3874,6 +3874,18 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2014082700.01); } + if ($oldversion < 2014082700.02) { + + // Define the field weightoverride to be added to grade_items. + $table = new xmldb_table('grade_items'); + + $field = new xmldb_field('weightoverride', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'needsupdate'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + upgrade_main_savepoint(true, 2014082700.02); + } return true; } diff --git a/lib/grade/grade_category.php b/lib/grade/grade_category.php index a7f8caea339..9ec498eace1 100644 --- a/lib/grade/grade_category.php +++ b/lib/grade/grade_category.php @@ -1044,6 +1044,10 @@ class grade_category extends grade_object { // Calculate the sum of the grademax's of all the items within this category. $totalgrademax = 0; + + // Out of 1, how much weight has been manually overriden by a user? + $totaloverriddenweight = 0; + $totaloverriddengrademax = 0; foreach ($children as $sortorder => $child) { $grade_item = null; @@ -1052,9 +1056,16 @@ class grade_category extends grade_object { } else if ($child['type'] == 'category') { $grade_item = $child['object']->load_grade_item(); } + $totalgrademax += $grade_item->grademax; + if ($grade_item->weightoverride) { + $totaloverriddenweight += $grade_item->aggregationcoef2; + $totaloverriddengrademax += $grade_item->grademax; + } } + $totalgrademax -= $totaloverriddengrademax; + reset($children); foreach ($children as $sortorder => $child) { $grade_item = null; @@ -1064,8 +1075,12 @@ class grade_category extends grade_object { } else if ($child['type'] == 'category') { $grade_item = $child['object']->load_grade_item(); } - $grade_item->aggregationcoef2 = $grade_item->grademax/$totalgrademax; - $grade_item->update(); + if (!$grade_item->weightoverride) { + // Calculate this item's weight as a percentage of the non-overridden total grade maxes + // then convert it to a proportion of the available non-overriden weight. + $grade_item->aggregationcoef2 = ($grade_item->grademax/$totalgrademax) * (1 - $totaloverriddenweight); + $grade_item->update(); + } } } diff --git a/lib/grade/grade_item.php b/lib/grade/grade_item.php index 0bf12ef5426..537e657719c 100644 --- a/lib/grade/grade_item.php +++ b/lib/grade/grade_item.php @@ -51,7 +51,7 @@ class grade_item extends grade_object { 'itemnumber', 'iteminfo', 'idnumber', 'calculation', 'gradetype', 'grademax', 'grademin', 'scaleid', 'outcomeid', 'gradepass', 'multfactor', 'plusfactor', 'aggregationcoef', 'aggregationcoef2', 'sortorder', 'display', 'decimals', 'hidden', 'locked', 'locktime', - 'needsupdate', 'timecreated', 'timemodified'); + 'needsupdate', 'weightoverride', 'timecreated', 'timemodified'); /** * The course this grade_item belongs to. @@ -246,6 +246,11 @@ class grade_item extends grade_object { */ public $needsupdate = 1; + /** + * If set, the grade item's weight has been overridden by a user and should not be automatically adjusted. + */ + public $weightoverride = 0; + /** * Cached dependson array * @var array An array of cached grade item dependencies.