Permalink
Browse files

MDL-41954 Fix the grade for assessment calculation in the Workshop mo…

…dule

In a pretty rare case of zero variance of received assessments, the "distance"
of the evaluated assessment from the referential ("best") one was not increased
regardless it's actual value. This led to higher grades for assessments in
certain situations (see the tracker for a particular example).
  • Loading branch information...
1 parent ca1c4ba commit b5b58382fb6294e18775e5a2d7eb122a51bd3a8e @mudrd8mz mudrd8mz committed Sep 24, 2013
Showing with 79 additions and 1 deletion.
  1. +3 −1 mod/workshop/eval/best/lib.php
  2. +76 −0 mod/workshop/eval/best/tests/lib_test.php
@@ -386,7 +386,9 @@ protected function assessments_distance(stdclass $assessment, stdclass $referent
$n += $weight;
// variations very close to zero are too sensitive to a small change of data values
- if ($var > 0.01 and $agrade != $rgrade) {
+ $var = max($var, 0.01);
+
+ if ($agrade != $rgrade) {
$absdelta = abs($agrade - $rgrade);
$reldelta = pow($agrade - $rgrade, 2) / ($settings->comparison * $var);
$distance += $absdelta * $reldelta * $weight;
@@ -239,6 +239,82 @@ public function test_assessments_distance_equals() {
$this->evaluator->assessments_distance($assessment2, $referential, $diminfo, $settings));
}
+
+ public function test_assessments_distance_zero_variance() {
+ // Fixture set-up: an assessment form of the strategy "Number of errors",
+ // three assertions, same weight.
+ $diminfo = array(
+ 1 => (object)array('min' => 0, 'max' => 1, 'weight' => 1),
+ 2 => (object)array('min' => 0, 'max' => 1, 'weight' => 1),
+ 3 => (object)array('min' => 0, 'max' => 1, 'weight' => 1),
+ );
+
+ // Simulate structure returned by {@link workshop_best_evaluation::prepare_data_from_recordset()}
+ $assessments = array(
+ // The first assessment has weight 0 and the assessment was No, No, No.
+ 10 => (object)array(
+ 'assessmentid' => 10,
+ 'weight' => 0,
+ 'reviewerid' => 56,
+ 'gradinggrade' => null,
+ 'submissionid' => 99,
+ 'dimgrades' => array(
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ ),
+ ),
+ // The second assessment has weight 1 and assessments was Yes, Yes, Yes.
+ 20 => (object)array(
+ 'assessmentid' => 20,
+ 'weight' => 1,
+ 'reviewerid' => 76,
+ 'gradinggrade' => null,
+ 'submissionid' => 99,
+ 'dimgrades' => array(
+ 1 => 1,
+ 2 => 1,
+ 3 => 1,
+ ),
+ ),
+ // The third assessment has weight 1 and assessments was Yes, Yes, Yes too.
+ 30 => (object)array(
+ 'assessmentid' => 30,
+ 'weight' => 1,
+ 'reviewerid' => 97,
+ 'gradinggrade' => null,
+ 'submissionid' => 99,
+ 'dimgrades' => array(
+ 1 => 1,
+ 2 => 1,
+ 3 => 1,
+ ),
+ ),
+ );
+
+ // Process assessments in the same way as in the {@link workshop_best_evaluation::process_assessments()}
+ $assessments = $this->evaluator->normalize_grades($assessments, $diminfo);
+ $average = $this->evaluator->average_assessment($assessments);
+ $variances = $this->evaluator->weighted_variance($assessments);
+ foreach ($variances as $dimid => $variance) {
+ $diminfo[$dimid]->variance = $variance;
+ }
+
+ // Simulate the chosen comparison of assessments "fair" (does not really matter here but we need something).
+ $settings = (object)array('comparison' => 5);
+
+ // Exercise SUT: for every assessment, calculate its distance from the average one.
+ $distances = array();
+ foreach ($assessments as $asid => $assessment) {
+ $distances[$asid] = $this->evaluator->assessments_distance($assessment, $average, $diminfo, $settings);
+ }
+
+ // Validate: the first assessment is far far away from the average one ...
+ $this->assertTrue($distances[10] > 0);
+ // ... while the two others were both picked as the referential ones.
+ $this->assertTrue($distances[20] == 0);
+ $this->assertTrue($distances[30] == 0);
+ }
}

0 comments on commit b5b5838

Please sign in to comment.