From bdfa2c74766c994f0cead86d806e78c3f65855e4 Mon Sep 17 00:00:00 2001 From: Gordon Bateson Date: Tue, 1 Aug 2017 07:57:11 +0900 Subject: [PATCH] MDL-79863 qtype_ordering: qtype_ordering fix score calculation for individual items on RELATIVE_TO_CORRET grading method --- .../type/ordering/lang/en/qtype_ordering.php | 6 ++++- question/type/ordering/question.php | 25 ++++++++++++++++--- question/type/ordering/questiontype.php | 6 +++++ question/type/ordering/renderer.php | 13 ++++++++++ question/type/ordering/version.php | 4 +-- 5 files changed, 48 insertions(+), 6 deletions(-) diff --git a/question/type/ordering/lang/en/qtype_ordering.php b/question/type/ordering/lang/en/qtype_ordering.php index 46fb521d791..26dbc93d593 100644 --- a/question/type/ordering/lang/en/qtype_ordering.php +++ b/question/type/ordering/lang/en/qtype_ordering.php @@ -50,6 +50,9 @@ $string['gradingtype_help'] = 'Choose the type of grading calculation. **Absolute position** : An item is considered correct if it is in the same position as in the correct answer. The highest possible score for the question is **the same as** the number of items displayed to the student. +**Relative to correct position** +: An item is considered correct if it is in the same position as in the correct answer. Correct items receive a score equal to the number of items displayed minus one. Incorrect items receive a score equal to the number of items displayed minus one and minus the distance of the item from its correct position. Thus, if ***n*** items are displayed to the student, the number of marks available for each item is ***(n - 1)***, and the highest mark available for the question is ***n x (n - 1)***, which is the same as ***(n² - n)***. + **Relative to the next item (excluding last)** : An item is considered correct if it is followed by the same item as it is in the correct answer. The item in the last position is not checked. Thus, the highest possible score for the question is **one less than** the number of items displayed to the student. @@ -60,7 +63,7 @@ $string['gradingtype_help'] = 'Choose the type of grading calculation. : An item is considered correct if both the previous and next items are the same as they are in the correct answer. The first item should have no previous item, and the last item should have no next item. Thus, there are two possible points for each item, and the highest possible score for the question is **twice** the number of items displayed to the student. **Relative to ALL previous and next items** -: An item is considered correct if it is preceded by all the same items as it is in the correct answer, and it is followed by all the same items as it is in the correct answer. The order of the previous items does not matter, and nor does the order of the following items. Thus, if ***n*** items are displayed to the student, the number of marks available for each item is ***(n - 1)***, and the highest mark availabe for the question is ***n x (n - 1)***, which is the same as ***(n² - n)***. +: An item is considered correct if it is preceded by all the same items as it is in the correct answer, and it is followed by all the same items as it is in the correct answer. The order of the previous items does not matter, and nor does the order of the following items. Thus, if ***n*** items are displayed to the student, the number of marks available for each item is ***(n - 1)***, and the highest mark available for the question is ***n x (n - 1)***, which is the same as ***(n² - n)***. **Longest ordered subset** : The grade is the number of items in the longest ordered subset of items. The highest possible grade is the same as the number of items displayed. A subset must have at least two items. Subsets do not need to start at the first item (but they can) and they do not need to be contiguous (but they can be). Where there are multiple subsets of equal length, items in the subset that is found first, when searching from left to right, will be displayed as correct. Other items will be marked as incorrect. @@ -79,6 +82,7 @@ $string['relativeallpreviousandnext'] = 'Relative to ALL the previous and next i $string['relativenextexcludelast'] = 'Relative to the next item (excluding last)'; $string['relativenextincludelast'] = 'Relative to the next item (including last)'; $string['relativeonepreviousandnext'] = 'Relative to both the previous and next items'; +$string['relativetocorrect'] = 'Relative to correct position'; $string['removeeditor'] = 'Remove HTML editor'; $string['removeitem'] = 'Remove draggable item'; $string['scoredetails'] = 'Here are the scores for each item in this response:'; diff --git a/question/type/ordering/question.php b/question/type/ordering/question.php index cc98dd58e78..89949abe279 100644 --- a/question/type/ordering/question.php +++ b/question/type/ordering/question.php @@ -62,6 +62,8 @@ class qtype_ordering_question extends question_graded_automatically { const GRADING_LONGEST_ORDERED_SUBSET = 5; /** @var int Only longest ordered and contignous subset is graded */ const GRADING_LONGEST_CONTIGUOUS_SUBSET = 6; + /** @var int Items are graded relative to their position in the correct answer */ + const GRADING_RELATIVE_TO_CORRECT = 7; // Fields from "qtype_ordering_options" table. /** @var string */ @@ -328,7 +330,7 @@ class qtype_ordering_question extends question_graded_automatically { $correctresponse = $this->correctresponse; $currentresponse = $this->currentresponse; foreach ($correctresponse as $position => $answerid) { - if (isset($currentresponse[$position])) { + if (array_key_exists($position, $currentresponse)) { if ($currentresponse[$position] == $answerid) { $countcorrect++; } @@ -346,7 +348,7 @@ class qtype_ordering_question extends question_graded_automatically { $currentresponse = $this->get_next_answerids($this->currentresponse, $lastitem); $correctresponse = $this->get_next_answerids($this->correctresponse, $lastitem); foreach ($correctresponse as $thisanswerid => $nextanswerid) { - if (isset($currentresponse[$thisanswerid])) { + if (array_key_exists($thisanswerid, $currentresponse)) { if ($currentresponse[$thisanswerid] == $nextanswerid) { $countcorrect++; } @@ -361,7 +363,7 @@ class qtype_ordering_question extends question_graded_automatically { $currentresponse = $this->get_previous_and_next_answerids($this->currentresponse, $all); $correctresponse = $this->get_previous_and_next_answerids($this->correctresponse, $all); foreach ($correctresponse as $thisanswerid => $answerids) { - if (isset($currentresponse[$thisanswerid])) { + if (array_key_exists($thisanswerid, $currentresponse)) { $prev = $currentresponse[$thisanswerid]->prev; $prev = array_intersect($prev, $answerids->prev); $countcorrect += count($prev); @@ -381,6 +383,22 @@ class qtype_ordering_question extends question_graded_automatically { $countcorrect = count($subset); $countanswers = count($this->currentresponse); break; + + case self::GRADING_RELATIVE_TO_CORRECT: + $correctresponse = $this->correctresponse; + $currentresponse = $this->currentresponse; + $count = (count($correctresponse) - 1); + foreach ($correctresponse as $position => $answerid) { + if (in_array($answerid, $currentresponse)) { + $currentposition = array_search($answerid, $currentresponse); + $currentscore = ($count - abs($position - $currentposition)); + if ($currentscore > 0) { + $countcorrect += $currentscore; + } + } + $countanswers += $count; + } + break; } if ($countanswers == 0) { $fraction = 0; @@ -793,6 +811,7 @@ class qtype_ordering_question extends question_graded_automatically { $types = array( self::GRADING_ALL_OR_NOTHING => get_string('allornothing', $plugin), self::GRADING_ABSOLUTE_POSITION => get_string('absoluteposition', $plugin), + self::GRADING_RELATIVE_TO_CORRECT => get_string('relativetocorrect', $plugin), self::GRADING_RELATIVE_NEXT_EXCLUDE_LAST => get_string('relativenextexcludelast', $plugin), self::GRADING_RELATIVE_NEXT_INCLUDE_LAST => get_string('relativenextincludelast', $plugin), self::GRADING_RELATIVE_ONE_PREVIOUS_AND_NEXT => get_string('relativeonepreviousandnext', $plugin), diff --git a/question/type/ordering/questiontype.php b/question/type/ordering/questiontype.php index 8971a3226ed..7c0d8ad8a10 100644 --- a/question/type/ordering/questiontype.php +++ b/question/type/ordering/questiontype.php @@ -522,6 +522,9 @@ class qtype_ordering extends question_type { case qtype_ordering_question::GRADING_LONGEST_CONTIGUOUS_SUBSET: $grading = 'LONGEST_CONTIGUOUS_SUBSET'; break; + case qtype_ordering_question::GRADING_RELATIVE_TO_CORRECT: + $grading = 'RELATIVE_TO_CORRECT'; + break; default: $grading = ''; // Shouldn't happen !! } @@ -788,6 +791,9 @@ class qtype_ordering extends question_type { case 'LONGEST_CONTIGUOUS_SUBSET': $gradingtype = qtype_ordering_question::GRADING_LONGEST_CONTIGUOUS_SUBSET; break; + case 'RELATIVE_TO_CORRECT': + $gradingtype = qtype_ordering_question::GRADING_RELATIVE_TO_CORRECT; + break; } // Set "showgrading" from $show. diff --git a/question/type/ordering/renderer.php b/question/type/ordering/renderer.php index c3097968fd6..0b385ab0141 100644 --- a/question/type/ordering/renderer.php +++ b/question/type/ordering/renderer.php @@ -346,6 +346,7 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer { case qtype_ordering_question::GRADING_ALL_OR_NOTHING: case qtype_ordering_question::GRADING_ABSOLUTE_POSITION: + case qtype_ordering_question::GRADING_RELATIVE_TO_CORRECT: $this->correctinfo = $question->correctresponse; $this->currentinfo = $question->currentresponse; break; @@ -459,6 +460,18 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer { $maxscore = 1; } break; + + case qtype_ordering_question::GRADING_RELATIVE_TO_CORRECT: + if (isset($correctinfo[$position])) { + $maxscore = (count($correctinfo) - 1); + $answerid = $currentinfo[$position]; + $correctposition = array_search($answerid, $correctinfo); + $score = ($maxscore - abs($correctposition - $position)); + if ($score < 0) { + $score = 0; + } + } + break; } if ($maxscore === null) { diff --git a/question/type/ordering/version.php b/question/type/ordering/version.php index 1dac8e4aca7..c1300d90701 100644 --- a/question/type/ordering/version.php +++ b/question/type/ordering/version.php @@ -29,5 +29,5 @@ $plugin->cron = 0; $plugin->component = 'qtype_ordering'; $plugin->maturity = MATURITY_STABLE; $plugin->requires = 2010112400; // Moodle 2.0 -$plugin->version = 2017070160; -$plugin->release = '2017-07-01 (60)'; +$plugin->version = 2017072563; +$plugin->release = '2017-07-25 (63)';