MDL-35055 question import: slight error with the Match grades option.

Even in the 'Error if grade not listed case', it was applying a small
tolerance. In the case of a fuzzy match, it was returning the inexact
grade from the import file, rather than the precise grade that Moodle
was expecting.

That causes problems when the editing form is displayed, because the
value from the database does not match any of the available options, so
the grade is changed to 0%.
This commit is contained in:
Tim Hunt 2012-08-24 15:34:20 +01:00
parent d71c486507
commit aa5f05110f
2 changed files with 38 additions and 18 deletions

View File

@ -209,39 +209,44 @@ function get_grade_options() {
}
/**
* match grade options
* if no match return error or match nearest
* Check whether a given grade is one of a list of allowed options. If not,
* depending on $matchgrades, either return the nearest match, or return false
* to signal an error.
* @param array $gradeoptionsfull list of valid options
* @param int $grade grade to be tested
* @param string $matchgrades 'error' or 'nearest'
* @return mixed either 'fixed' value or false if erro
* @return mixed either 'fixed' value or false if error.
*/
function match_grade_options($gradeoptionsfull, $grade, $matchgrades='error') {
function match_grade_options($gradeoptionsfull, $grade, $matchgrades = 'error') {
if ($matchgrades == 'error') {
// if we just need an error...
// (Almost) exact match, or an error.
foreach ($gradeoptionsfull as $value => $option) {
// slightly fuzzy test, never check floats for equality :-)
// Slightly fuzzy test, never check floats for equality.
if (abs($grade - $value) < 0.00001) {
return $grade;
return $value; // Be sure the return the proper value.
}
}
// didn't find a match so that's an error
// Didn't find a match so that's an error.
return false;
} else if ($matchgrades == 'nearest') {
// work out nearest value
$hownear = array();
// Work out nearest value
$best = false;
$bestmismatch = 2;
foreach ($gradeoptionsfull as $value => $option) {
if ($grade==$value) {
return $grade;
$newmismatch = abs($grade - $value);
if ($newmismatch < $bestmismatch) {
$best = $value;
$bestmismatch = $newmismatch;
}
$hownear[ $value ] = abs( $grade - $value );
}
// reverse sort list of deltas and grab the last (smallest)
asort( $hownear, SORT_NUMERIC );
reset( $hownear );
return key( $hownear );
return $best;
} else {
return false;
// Unknow option passed.
throw new coding_exception('Unknown $matchgrades ' . $matchgrades .
' passed to match_grade_options');
}
}

View File

@ -55,4 +55,19 @@ class questionlib_testcase extends basic_testcase {
array(0 => 't1', 1 => 't2', 2 => 't3'));
}
public function test_match_grade_options() {
$gradeoptions = question_bank::fraction_options_full();
$this->assertEquals(0.3333333, match_grade_options($gradeoptions, 0.3333333, 'error'));
$this->assertEquals(0.3333333, match_grade_options($gradeoptions, 0.333333, 'error'));
$this->assertEquals(0.3333333, match_grade_options($gradeoptions, 0.33333, 'error'));
$this->assertFalse(match_grade_options($gradeoptions, 0.3333, 'error'));
$this->assertEquals(0.3333333, match_grade_options($gradeoptions, 0.3333333, 'nearest'));
$this->assertEquals(0.3333333, match_grade_options($gradeoptions, 0.333333, 'nearest'));
$this->assertEquals(0.3333333, match_grade_options($gradeoptions, 0.33333, 'nearest'));
$this->assertEquals(0.3333333, match_grade_options($gradeoptions, 0.33, 'nearest'));
$this->assertEquals(-0.1428571, match_grade_options($gradeoptions, -0.15, 'nearest'));
}
}