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:
skodak
2009-04-29 13:44:17 +00:00
parent 3cee044c01
commit f53d2cf806
5 changed files with 94 additions and 26 deletions
+4 -2
View File
@@ -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);
}
+42 -14
View File
@@ -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
+1 -1
View File
@@ -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
+46 -8
View File
@@ -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
View File
@@ -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