Shuffle answers in multiple choice questions
[oweals/karmaworld.git] / karmaworld / apps / quizzes / create_quiz.py
index cd3bb6c1e6c0db193d79acd94413de84ac83b6e9..a61d236cf1340b77c82e24ef2ab339b70dab041e 100644 (file)
@@ -1,3 +1,4 @@
+from copy import copy
 import random
 from karmaworld.apps.quizzes.models import Keyword
 
@@ -53,13 +54,35 @@ class TrueFalseQuestion(BaseQuizQuestion):
         return str(self)
 
 
+class MatchingQuestion(BaseQuizQuestion):
+    def __init__(self, question_text, left_column, right_column, left_right_mapping):
+        self.question_text = question_text
+        self.left_column = left_column
+        self.right_column = right_column
+        self.left_right_mapping = left_right_mapping
+
+    def rows(self):
+        return zip(self.left_column, self.right_column)
+
+    def __unicode__(self):
+        return u"Matching question: {0} / {1}".format(self.left_column, self.right_column)
+
+    def __str__(self):
+        return unicode(self)
+
+    def __repr__(self):
+        return str(self)
+
+
 KEYWORD_MULTIPLE_CHOICE = 1
 DEFINITION_MULTIPLE_CHOICE = 2
 KEYWORD_DEFINITION_TRUE_FALSE = 3
+KEYWORD_DEFINITION_MATCHING = 4
 GENERATED_QUESTION_TYPE = (
     KEYWORD_MULTIPLE_CHOICE,
     DEFINITION_MULTIPLE_CHOICE,
     KEYWORD_DEFINITION_TRUE_FALSE,
+    KEYWORD_DEFINITION_MATCHING,
 )
 
 MULTIPLE_CHOICE_CHOICES = 4
@@ -75,6 +98,8 @@ def _create_keyword_multiple_choice(keyword, keywords):
 
     question_text = u'Pick the keyword to match "{d}"'.format(d=keyword.definition)
 
+    random.shuffle(choices)
+
     return MultipleChoiceQuestion(question_text, choices)
 
 
@@ -88,6 +113,8 @@ def _create_definition_multiple_choice(keyword, keywords):
 
     question_text = u'Pick the definition to match "{w}"'.format(w=keyword.word)
 
+    random.shuffle(choices)
+
     return MultipleChoiceQuestion(question_text, choices)
 
 
@@ -106,8 +133,24 @@ def _create_keyword_definition_true_false(keyword, keywords):
     return TrueFalseQuestion(question_text, true)
 
 
+def _create_keyword_definition_matching(keyword, keywords):
+    question_keywords = [keyword]
+    question_keywords.extend(random.sample(keywords.exclude(id=keyword.id), MULTIPLE_CHOICE_CHOICES - 1))
+
+    answer_mapping = {k.word: k.definition for k in question_keywords}
+    word_column = [k.word for k in question_keywords]
+    random.shuffle(word_column)
+    definition_column = [k.definition for k in question_keywords]
+    random.shuffle(definition_column)
+
+    question_text = u'Match the words with their definitions'
+
+    return MatchingQuestion(question_text, left_column=word_column,
+                            right_column=definition_column, left_right_mapping=answer_mapping)
+
+
 def quiz_from_keywords(note):
-    keywords = Keyword.objects.filter(note=note)
+    keywords = Keyword.objects.filter(note=note).exclude(word__iexact='').exclude(definition__iexact='')
     questions = []
 
     if len(keywords) < 4:
@@ -126,6 +169,9 @@ def quiz_from_keywords(note):
             elif question_type is KEYWORD_DEFINITION_TRUE_FALSE:
                 questions.append(_create_keyword_definition_true_false(keyword, keywords))
 
+            elif question_type is KEYWORD_DEFINITION_MATCHING:
+                questions.append(_create_keyword_definition_matching(keyword, keywords))
+
     return questions