ui: Add dependency handling to UserInterface.get_question
authorW. Trevor King <wking@tremily.us>
Tue, 5 Feb 2013 15:37:41 +0000 (10:37 -0500)
committerW. Trevor King <wking@tremily.us>
Tue, 5 Feb 2013 15:37:44 +0000 (10:37 -0500)
We start the stack with all the leaf questions (i.e. questions that
are not dependencies of other question).  If the user gets one wrong,
we push the question back on the stack (so they can try again later),
and also push all of that questions direct dependencies onto the stack
(so they can get the background they need to answer the question they
got wrong).

quizzer/quiz.py
quizzer/ui/__init__.py

index 86b029ad526feb51a6770fcf01ed6a26aadfa364..c3fa5a5df5a0ff6f4e19fc4913fa72bccd415df9 100644 (file)
@@ -41,3 +41,19 @@ class Quiz (list):
             _json.dump(
                 data, f, indent=2, separators=(',', ': '), sort_keys=True)
             f.write('\n')
+
+    def leaf_questions(self):
+        "Questions that are not dependencies of other question"
+        dependents = set()
+        for question in self:
+            dependents.update(question.dependencies)
+        return [q for q in self if q.id not in dependents]
+
+    def get(self, id=None):
+        matches = [q for q in self if q.id == id]
+        if len(matches) == 1:
+            return matches[0]
+        elif len(matches) == 0:
+            raise KeyError(id)
+        raise NotImplementedError(
+            'multiple questions with one ID: {}'.format(matches))
index 8fb8b06cd9f53abfca28a39d7e031699b24687cb..3a1c37fe174c7ab3521bfb83603e4fc4928685db 100644 (file)
@@ -3,11 +3,14 @@ from .. import answerdb as _answerdb
 
 class UserInterface (object):
     "Give a quiz over a generic user interface"
-    def __init__(self, quiz=None, answers=None):
+    def __init__(self, quiz=None, answers=None, stack=None):
         self.quiz = quiz
         if answers is None:
             answers = _answerdb.AnswerDatabase()
         self.answers = answers
+        if stack is None:
+            stack = quiz.leaf_questions()
+        self.stack = stack
 
     def run(self):
         raise NotImplementedError()
@@ -16,11 +19,15 @@ class UserInterface (object):
         raise NotImplementedError()
 
     def get_question(self):
-        remaining = self.answers.get_unanswered(questions=self.quiz)
-        if remaining:
-            return remaining[0]
+        if self.stack:
+            print(self.stack)
+            return self.stack.pop(0)
 
     def process_answer(self, question, answer):
         correct = question.check(answer)
         self.answers.add(question=question, answer=answer, correct=correct)
+        if not correct:
+            self.stack.insert(0, question)
+            for qid in reversed(question.dependencies):
+                self.stack.insert(0, self.quiz.get(id=qid))
         return correct