Problem/Motivation

A question with the "Simple scoring" option selected (choice_boolean) should result in the question being marked correct only if all correct answers are selected. Otherwise the totals for quizzes exceed 100%.

Steps to reproduce

  1. Create a quiz with a question that has 4 options. 3 of the options are correct. For correct answers 1 point if selected -1 if not selected.
  2. Set the question to have "Simple scoring"
  3. Set the max score on the questions page for this question to 1.
  4. Answering all three correctly results in points_awarded of 3 for the quiz question result.

Repeat the steps above, but uncheck simple scoring.
Answering all three correctly still results in points_awarded of 3 for the quiz question result

Repeat the steps in the first scenario, but change the max score to 1 on the questions page (so keep as simple scoring)
Answering all three correctly still results in points_awarded of 3 for the quiz question result.

Repeat the steps in the first scenario, but on the questions page, set to "automatic scoring"
Answering all three correctly still results in points_awarded of 3

Proposed resolution

It appears the problem may be QuizQuestionEntityTrait.php::getAnsweringFormValidate();
Shouldnt' there be a line here to determine if quiz_question__choice_boolean is 1 then set points_awarded to max_score?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Chris Dart created an issue. See original summary.

Chris Dart’s picture

It looks like the actual fix should be here:
quiz/src/Form/QuizQuestionAnsweringForm.php:230

          $score = $qra->score($form_state->getValues()['question'][$qqid]) * $qra->getWeightedRatio();
          $question = $qra->getQuizQuestion();
          $max_score = $question->getMaximumScore();
          if($question->get('choice_boolean')->value == 1 && $score >=$max_score){
            $qra->points_awarded = $max_score;
          }
          else {
            $qra->points_awarded= $score;
          }
djdevin’s picture

It's strange because a question should not be able to make the score in the quiz anything higher than the scaled max. If the question in the quiz is worth 1 point then it shouldn't be possible for a 3 point question to award more than 1 point in the quiz.

There's a few tests that should be looked at, that doesn't seem right...

QuizMultichoiceTestCase::testSimpleScoring

QuizGradingTest::testWeightedScore

QuizGradingTest::testManualWeightedScore

Chris Dart’s picture

My guess is that this patch is just a hack because the real problem is further upstream in the process.

martin@infinitynetmedia.co.uk’s picture

Isn't the issue here:

multichoiceResponse.php

foreach ($alternatives as $alternative) {
      // Take action on each alternative being selected (or not).
      $vid = $alternative->getRevisionId();
      // If this alternative was selected.
      $selected = in_array($vid, $selected_vids);
      $correct = $alternative->get('multichoice_correct')->getString();

      if (!$selected && $simple && $correct) {
        // Selected this answer, simple scoring on, and the answer was incorrect.
        $score = 0;
        break;
      }

      if ($selected && $correct && !$multi) {
        // User selected a correct answer and this is not a multiple answer
        // question. User gets the point value of the question.
        $score = $alternative->get('multichoice_score_chosen')->getString();
        break;
      }

      if ($multi) {
        // In multiple answer questions we sum up all the points.
        if ($selected) {
          // Add (or subtract) some points.
          $score += $alternative->get('multichoice_score_chosen')->getString();
        }
        else {
          $score += $alternative->get('multichoice_score_not_chosen')->getString();
        }
      }
    }

    $this->setEvaluated();
    return $score;

ie: if it's a multi choice answer, the score is incremented by score_chosen / not_chosen. If we want simple scoring, wouldn't this be a better solution?


  foreach ($alternatives as $alternative) {
      $vid = $alternative->getRevisionId();
      // If this alternative was selected.
      $selected = in_array($vid, $selected_vids);
      $correct = $alternative->get('multichoice_correct')->getString();
      if ($simple){
        if (!$selected && $correct) {
          // Selected this answer, simple scoring on, and the answer was incorrect.
          $score = 0;
          break;
        }
        if ($selected && $correct) {
          $score=1;
        }
      }else{
        if ($selected && $correct && !$multi) {
          // User selected a correct answer and this is not a multiple answer
          // question. User gets the point value of the question.
          $score = $alternative->get('multichoice_score_chosen')->getString();
          break;
        }

        if ($multi) {
          // In multiple answer questions we sum up all the points.
          if ($selected) {
            // Add (or subtract) some points.
            $score += $alternative->get('multichoice_score_chosen')->getString();
          }
          else {
            $score += $alternative->get('multichoice_score_not_chosen')->getString();
          }
        }
      }
    }
    $this->setEvaluated();
    return $score;

ie: if you want simple scoring (0 or 1) any incorrect response receives a score of zero, and only gets 1 mark if there are no incorrect answers.

hb3’s picture

I slightly updated Martins solution, to prevent that a user gets points if he/she selects all alternatives of a multiplechoice question (both correct and wrong ones) and created a patch.
if ((!$selected && $correct) || ($selected && !$correct))

apaderno’s picture

Status: Active » Needs review
djdevin’s picture

Version: 6.0.0-alpha4 » 6.x-dev
FileSize
6.1 KB

There's a couple issue here contributing to the issue:

1. The forgive() method which corrects the multichoice_score_[not_]chosen if omitted, was broken from D7
2. score() was returning more points than the max points when using simple scoring
3. The warn() method was still broken from D7

This should fix that all up against 6.x. Test has to be updated.

Status: Needs review » Needs work

The last submitted patch, 8: 3198222-mcq.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

djdevin’s picture

Status: Needs work » Needs review
FileSize
6.11 KB

Fix MCQ test

djdevin’s picture

Updated testSimpleScoring to set 2 correct answers and then check for the proper score, it wasn't doing that before.

  • djdevin committed 2c48eea on 6.x
    Issue #3198222 by djdevin, Chris Dart, hb3, martin@infinitynetmedia.co....
djdevin’s picture

Status: Needs review » Fixed

Test patch fails, full patch passes.

Thanks all, fixed!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.