1

I'm awarding users points for passing a quiz successfully. However, there's nothing stopping the user taking the quiz again and again to score more points.

I have thought of these options, but I don't know how to implement them:

  1. check if the user has achieved a certain score before awarding points

  2. lock down the quiz for users who have already passed it, redirecting them to their results page

  3. tagging the quiz with users ID when they complete it the first time and and denying points when they complete it again.

Any help?

4
  • I don't know the Quiz module, so this is just a suggestion: can you flag quizzes with the Flag module? If so, you can let any user flag all quizzes by default and unflag them after completing them. That would allow you to only grant userpoints if the quiz is still flagged.
    – Jeroen
    Commented Sep 6, 2017 at 14:41
  • 1
    @Jeroen (aka Mr. "Flag" ...) I think you should say "if the quiz is still NOT flagged", wouldn't you agree? If not I may not fully understand what you mean ... Commented Sep 6, 2017 at 15:27
  • @Pierre.Vriens: It depends. Caution is needed because of an issue I once faced: drupal.stackexchange.com/questions/88529/…
    – Jeroen
    Commented Sep 6, 2017 at 15:40
  • But once again, I cannot do any tests for the moment...
    – Jeroen
    Commented Sep 6, 2017 at 15:48

2 Answers 2

1

Step 1 - Create a flag for tracking Passed Quizes

Use the Flag module to create a flag labeled (e.g) Passed Quizes. Here is an export of the flag I used for this (you should be able to import it in your own site also):

$flags = array();
// Exported flag: "Passed Quizes".
$flags['passed_quizes'] = array (
  'entity_type' => 'node',
  'title' => 'Passed Quizes',
  'global' => '0',
  'types' => 
  array (
    0 => 'quiz',
  ),
  'flag_short' => 'Flag this item',
  'flag_long' => '',
  'flag_message' => '',
  'unflag_short' => 'Unflag this item',
  'unflag_long' => '',
  'unflag_message' => '',
  'unflag_denied_text' => '',
  'link_type' => 'toggle',
  'weight' => 0,
  'show_in_links' => 
  array (
    'full' => 'full',
    'teaser' => 'teaser',
    'rss' => 0,
    'search_index' => 0,
    'search_result' => 0,
    'answers_full_node' => 0,
    'print' => 0,
    'question' => 0,
    'token' => 0,
  ),
  'show_as_field' => 0,
  'show_on_form' => 0,
  'access_author' => '',
  'show_contextual_link' => 0,
  'i18n' => 0,
  'api_version' => 3,
);
return $flags;

This flag will be used in the custom rule, detailed in the next step.

Step 2 - Create a single rule to cover all situations

Here is a rule which illustrates how to resolve the challenge in your question:

{ "rules_process_a_quiz_when_passed_the_very_first_time" : {
    "LABEL" : "Process a quiz when passed the very first time",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "TAGS" : [ "quiz" ],
    "REQUIRES" : [ "rules", "rules_conditional", "flag", "entity" ],
    "ON" : { "quiz_result_update" : [] },
    "IF" : [
      { "entity_is_of_type" : { "entity" : [ "quiz-result:nid" ], "type" : "node" } },
      { "data_is" : { "data" : [ "quiz-result-unchanged:is-evaluated" ], "value" : "0" } },
      { "data_is" : { "data" : [ "quiz-result:is-evaluated" ], "value" : "1" } },
      { "NOT data_is" : {
          "data" : [ "quiz-result:score" ],
          "op" : "\u003C",
          "value" : [ "quiz-result:nid:quiz:pass-rate" ]
        }
      }
    ],
    "DO" : [
      { "CONDITIONAL" : [
          {
            "IF" : { "NOT flag_flagged_node" : {
                "flag" : "passed_quizes",
                "node" : [ "quiz-result:nid" ],
                "flagging_user" : [ "site:current-user" ]
              }
            },
            "DO" : [
              { "drupal_message" : { "message" : "Congratulations, this is the FIRST time you passed this quiz (with a score of [quiz-result:score] %, whereas the pass rate is [quiz-result:nid:quiz:pass-rate] %)." } },
              { "flag_flagnode" : {
                  "flag" : "passed_quizes",
                  "node" : [ "quiz-result:nid" ],
                  "flagging_user" : [ "site:current-user" ],
                  "permission_check" : "1"
                }
              }
            ]
          },
          { "ELSE" : [
              { "drupal_message" : { "message" : "Congratulations, you passed this quiz yet ANOTHER time (with a score of [quiz-result:score] %, whereas the pass rate is [quiz-result:nid:quiz:pass-rate] %)." } }
            ]
          }
        ]
      }
    ]
  }
}

This rule requires the Conditional Rules module to be enabled (head over to the next step for some (multiple!) alternatives which does not need this extra module).

Here are the critical pieces of this rule to make Rules-magic happen:

  • The very first Rules Condition, which is "the" way to get access to all sorts of data about the quiz node itself (starting from "a" quiz result).
  • If the quiz node (to which this quiz result relates) is not yet flagged (by the flag from Step 1), and the quiz result is that it is at leastd equal to the pass rate of that quiz, then you have your very first hit you're looking for. At which time the quiz node gets flagged.

Use the Rules UI to import the above rule in your own site, after you enabled the Conditional Rules module and completed Step 1. After you are convinced it works as designed, simply add your additional Rules Action(s) to grant the User points ... only the very first time.

Step 3 - Possible Rules variations

Some variations of the rule included in Step 2, which should also achieve a similar result:

  • Replace the logic implemented via the Condtional Rules module by 2 equivalent Rules Components (so that you don't need the extra module). Refer to "What's the alternative to using the Conditional Rules module?" for way more details on this.
  • If you DO NOT want anything to happen if the quiz was already passed before, then the "else"-part of the Conditional Rules logic is empty. In that case you could rework the remaining Conditional Rules logic to a regular Rules Condition (to be executed as the very last one). As a variation, clone such rule variation in a 2nd variation, in which you just reverse that very same Rules Condition (with Rules Action as in the "else" part of the Conditional Rules logic).

Showtime

Here is a sample of a message I received after passing a quiz:

  • The very first time:

    Congratulations, this is the FIRST time you passed this quiz (with a score of 80 %, whereas the pass rate is 75 %).

  • The next time:

    Congratulations, you passed this quiz yet ANOTHER time (with a score of 100 %, whereas the pass rate is 75 %).

PS: I'm assuming this question is about D7 ...

5
  • Thanks for the quick reply! That solution is for the "store best results" setting? Can you please explain what the IF statements are doing? The problem with that storing only latest results breaks the quiz results page for the user. Right now I'm storing all results because it's the only option that works properly. I also just realized that once the user has completed the quiz and goes to it again "You have already passed this quiz" message is shown. Is that what "quiz-result:is-evaluated" stores?
    – zoom-ping
    Commented Sep 6, 2017 at 16:06
  • I've messed with it a bit more and tried using the proposed rule, but no dice. "quiz-result-unchanged:is-evaluated" always returns false, and this rule will always give points if the user passes with the required score. As far as I can tell there's no way of checking if the user has passed the quiz before. Giving user roles is out of the question because I can't do it for every single quiz in the future.
    – zoom-ping
    Commented Sep 7, 2017 at 14:48
  • @zoom-ping please let me know what you think of my updated answer ... if would be great if you could import the flag setup and the custom rule in your own site to QA test it (in my site it works like a charm ...). I must admit this was a pretty tough Rules question (way behond a typical set of Quiz questions ...). Curious now if this answer will "pass" your QA-review ... Commented Sep 10, 2017 at 9:08
  • Thank you so much for taking the time to write and test all this! I'll try to implement it on my site in the next couple of days and will let you know how it goes.
    – zoom-ping
    Commented Sep 10, 2017 at 20:40
  • I used your solution at drupal.stackexchange.com/questions/245442/… and it worked like a charm! Thank you so much for taking the time to help!
    – zoom-ping
    Commented Sep 12, 2017 at 8:42
0

What version of the quiz module are you taking? The quiz settings do allow you to restrict how many times a user is able to take a quiz.

This answer doesn't address points, it simply limits the number of times that they can take the quiz.

Go to the quiz or the global quiz settings. Under "availability options" there is an option near the bottom to select how many times a user can take the quiz:

enter image description here

So this might be a way to address the second point of locking down a quiz and redirecting the users to their results page.

5
  • 1
    Hey Christia, everything you wrote in your answer is correct. But the way I understand the question is that (a) OPer wants to allow the quiz to be taken multiple times and (b) only grant userpoints for passing "a" quiz the very first time and (c) also grant userponts for some other quiz (the very first time such other quiz is passed) ... Commented Sep 8, 2017 at 19:18
  • I think you may be right but I just wanted to make sure because of OP's second point of locking down a quiz and redirecting them to their results page.
    – Christia
    Commented Sep 8, 2017 at 20:07
  • aha, that helps a bit. Agree with my minor edit of your post? If not just rollback or refine, ok? Commented Sep 8, 2017 at 20:14
  • Thanks for replying. Pierre got what i need exactly right in a previous comment. I don't want to restrict the number of attempts, just lock down the quiz after the user has successfully passed. Right now it looks like I need a custom module for that.
    – zoom-ping
    Commented Sep 9, 2017 at 12:59
  • @zoom-ping merci for the first part of your last comment, but sorry to say I 100% disagree with your last phrase ... check my updated answer to understand what I mean. To Christia: want to participate in the QA-review of what I came up with in my updated answer? Commented Sep 10, 2017 at 9:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.