Skip to content
Browse files

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%.
  • Loading branch information...
1 parent bac15e5 commit 4d0a7e2b1f755888d9ac4c94a6f34c2ef6d92aa6 @timhunt timhunt committed
Showing with 38 additions and 18 deletions.
  1. +23 −18 lib/questionlib.php
  2. +15 −0 lib/tests/questionlib_test.php
View
41 lib/questionlib.php
@@ -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
15 lib/tests/questionlib_test.php
@@ -55,4 +55,19 @@ public function test_question_reorder_qtypes() {
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'));
+ }
}

0 comments on commit 4d0a7e2

Please sign in to comment.
Something went wrong with that request. Please try again.