MDL-19008 extra credis should not be dropped when drop low or keep high specified (including unit tests); backported from HAED and full regrading which is also needed for MDL-18993
This commit is contained in:
+4
-2
@@ -3147,8 +3147,10 @@ function xmldb_main_upgrade($oldversion=0) {
|
||||
upgrade_main_savepoint($result, 2007101546.03);
|
||||
}
|
||||
|
||||
if ($result && $oldversion < 2007101546.04) {
|
||||
// force full regrading - the max grade for sum aggregation was not correct when scales involved
|
||||
if ($result && $oldversion < 2007101546.05) {
|
||||
// force full regrading - the max grade for sum aggregation was not correct when scales involved,
|
||||
// extra credit grade is not dropped anymore in aggregations if drop low or keep high specified
|
||||
// sum aggragetion respects drop low and keep high when calculation max value
|
||||
set_field('grade_items', 'needsupdate', 1, 'needsupdate', 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -553,7 +553,7 @@ class grade_category extends grade_object {
|
||||
}
|
||||
|
||||
// limit and sort
|
||||
$this->apply_limit_rules($grade_values);
|
||||
$this->apply_limit_rules($grade_values, $items);
|
||||
asort($grade_values, SORT_NUMERIC);
|
||||
|
||||
// let's see we have still enough grades to do any statistics
|
||||
@@ -728,7 +728,7 @@ class grade_category extends grade_object {
|
||||
}
|
||||
}
|
||||
// apply droplow and keephigh
|
||||
$this->apply_limit_rules($maxes);
|
||||
$this->apply_limit_rules($maxes, $items);
|
||||
$max = array_sum($maxes);
|
||||
|
||||
// update db if anything changed
|
||||
@@ -774,7 +774,7 @@ class grade_category extends grade_object {
|
||||
}
|
||||
}
|
||||
|
||||
$this->apply_limit_rules($grade_values);
|
||||
$this->apply_limit_rules($grade_values, $items);
|
||||
|
||||
$sum = array_sum($grade_values);
|
||||
$grade->finalgrade = $this->grade_item->bounded_grade($sum);
|
||||
@@ -790,26 +790,54 @@ class grade_category extends grade_object {
|
||||
/**
|
||||
* Given an array of grade values (numerical indices), applies droplow or keephigh
|
||||
* rules to limit the final array.
|
||||
* @param array $grade_values
|
||||
* @param array $grade_values itemid=>$grade_value float
|
||||
* @param array $items grade titem objects
|
||||
* @return array Limited grades.
|
||||
*/
|
||||
function apply_limit_rules(&$grade_values) {
|
||||
arsort($grade_values, SORT_NUMERIC);
|
||||
function apply_limit_rules(&$grade_values, $items) {
|
||||
$extraused = $this->is_extracredit_used();
|
||||
|
||||
if (!empty($this->droplow)) {
|
||||
for ($i = 0; $i < $this->droplow; $i++) {
|
||||
if (empty($grade_values)) {
|
||||
// nothing to remove
|
||||
return;
|
||||
asort($grade_values, SORT_NUMERIC);
|
||||
$dropped = 0;
|
||||
foreach ($grade_values as $itemid=>$value) {
|
||||
if ($dropped < $this->droplow) {
|
||||
if ($extraused and $items[$itemid]->aggregationcoef > 0) {
|
||||
// no drop low for extra credits
|
||||
} else {
|
||||
unset($grade_values[$itemid]);
|
||||
$dropped++;
|
||||
}
|
||||
} else {
|
||||
// we have dropped enough
|
||||
break;
|
||||
}
|
||||
array_pop($grade_values);
|
||||
}
|
||||
} elseif (!empty($this->keephigh)) {
|
||||
while (count($grade_values) > $this->keephigh) {
|
||||
array_pop($grade_values);
|
||||
|
||||
} else if (!empty($this->keephigh)) {
|
||||
arsort($grade_values, SORT_NUMERIC);
|
||||
$kept = 0;
|
||||
foreach ($grade_values as $itemid=>$value) {
|
||||
if ($extraused and $items[$itemid]->aggregationcoef > 0) {
|
||||
// we keep all extra credits
|
||||
} else if ($kept < $this->keephigh) {
|
||||
$kept++;
|
||||
} else {
|
||||
unset($grade_values[$itemid]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if category uses extra credit of any kind
|
||||
* @return boolean true if extra credit used
|
||||
*/
|
||||
function is_extracredit_used() {
|
||||
return ($this->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN2
|
||||
or $this->aggregation == GRADE_AGGREGATE_EXTRACREDIT_MEAN
|
||||
or $this->aggregation == GRADE_AGGREGATE_SUM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if category uses special aggregation coeficient
|
||||
|
||||
@@ -650,7 +650,7 @@ class grade_grade extends grade_object {
|
||||
}
|
||||
|
||||
// limit and sort
|
||||
$grade_category->apply_limit_rules($values);
|
||||
$grade_category->apply_limit_rules($values, $grade_items);
|
||||
asort($values, SORT_NUMERIC);
|
||||
|
||||
// let's see we have still enough grades to do any statistics
|
||||
|
||||
@@ -246,23 +246,61 @@ class grade_category_test extends grade_test {
|
||||
}
|
||||
|
||||
function test_grade_category_apply_limit_rules() {
|
||||
$category = new grade_category();
|
||||
$grades = array(5.374, 9.4743, 2.5474, 7.3754);
|
||||
$items[$this->grade_items[0]->id] = new grade_item($this->grade_items[0], false);
|
||||
$items[$this->grade_items[1]->id] = new grade_item($this->grade_items[1], false);
|
||||
$items[$this->grade_items[2]->id] = new grade_item($this->grade_items[2], false);
|
||||
$items[$this->grade_items[4]->id] = new grade_item($this->grade_items[4], false);
|
||||
|
||||
$category = new grade_category();
|
||||
$category->droplow = 2;
|
||||
$category->apply_limit_rules($grades);
|
||||
sort($grades, SORT_NUMERIC);
|
||||
$this->assertEqual(array(7.3754, 9.4743), $grades);
|
||||
$grades = array($this->grade_items[0]->id=>5.374,
|
||||
$this->grade_items[1]->id=>9.4743,
|
||||
$this->grade_items[2]->id=>2.5474,
|
||||
$this->grade_items[4]->id=>7.3754);
|
||||
$category->apply_limit_rules($grades, $items);
|
||||
$this->assertEqual(count($grades), 2);
|
||||
$this->assertEqual($grades[$this->grade_items[1]->id], 9.4743);
|
||||
$this->assertEqual($grades[$this->grade_items[4]->id], 7.3754);
|
||||
|
||||
$category = new grade_category();
|
||||
$grades = array(5.374, 9.4743, 2.5474, 7.3754);
|
||||
|
||||
$category->keephigh = 1;
|
||||
$category->droplow = 0;
|
||||
$category->apply_limit_rules($grades);
|
||||
$grades = array($this->grade_items[0]->id=>5.374,
|
||||
$this->grade_items[1]->id=>9.4743,
|
||||
$this->grade_items[2]->id=>2.5474,
|
||||
$this->grade_items[4]->id=>7.3754);
|
||||
$category->apply_limit_rules($grades, $items);
|
||||
$this->assertEqual(count($grades), 1);
|
||||
$grade = reset($grades);
|
||||
$this->assertEqual(9.4743, $grade);
|
||||
|
||||
$category = new grade_category();
|
||||
$category->droplow = 2;
|
||||
$category->aggregation = GRADE_AGGREGATE_SUM;
|
||||
$items[$this->grade_items[2]->id]->aggregationcoef = 1;
|
||||
$grades = array($this->grade_items[0]->id=>5.374,
|
||||
$this->grade_items[1]->id=>9.4743,
|
||||
$this->grade_items[2]->id=>2.5474,
|
||||
$this->grade_items[4]->id=>7.3754);
|
||||
|
||||
$category->apply_limit_rules($grades, $items);
|
||||
$this->assertEqual(count($grades), 2);
|
||||
$this->assertEqual($grades[$this->grade_items[1]->id], 9.4743);
|
||||
$this->assertEqual($grades[$this->grade_items[2]->id], 2.5474);
|
||||
|
||||
$category = new grade_category();
|
||||
$category->keephigh = 1;
|
||||
$category->droplow = 0;
|
||||
$category->aggregation = GRADE_AGGREGATE_SUM;
|
||||
$items[$this->grade_items[2]->id]->aggregationcoef = 1;
|
||||
$grades = array($this->grade_items[0]->id=>5.374,
|
||||
$this->grade_items[1]->id=>9.4743,
|
||||
$this->grade_items[2]->id=>2.5474,
|
||||
$this->grade_items[4]->id=>7.3754);
|
||||
$category->apply_limit_rules($grades, $items);
|
||||
$this->assertEqual(count($grades), 2);
|
||||
$this->assertEqual($grades[$this->grade_items[1]->id], 9.4743);
|
||||
$this->assertEqual($grades[$this->grade_items[2]->id], 2.5474);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
// This is compared against the values stored in the database to determine
|
||||
// whether upgrades should be performed (see lib/db/*.php)
|
||||
|
||||
$version = 2007101546.04; // YYYYMMDD = date of the 1.9 branch (don't change)
|
||||
$version = 2007101546.05; // YYYYMMDD = date of the 1.9 branch (don't change)
|
||||
// X = release number 1.9.[0,1,2,3,4,5...]
|
||||
// Y.YY = micro-increments between releases
|
||||
|
||||
|
||||
Reference in New Issue
Block a user