Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/quizdata/question.py
blob: e507c0f248a8fb94d50dab5d93b2a09d516e9b7e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
'''
    quizdata.Question implementation and support functions
'''
class Question(object):
    '''
        Base question type, abstract(-ish).

        Required attributes for 'concrete' implementations:

        :Attributes:
            answered : boolean
                True if the student has selected an answer (if the answer
                attribute is valid)
            correct : boolean
                True if the answer currently selected is correct. (may, in the
                future, expand to include a fractional value for partial
                credit.) Only valid if answered is True.
            answer : marktup_type
                The answer selected by the student, or None if no answer
                selected. (None is not guaranteed as a value, so use the
                answered attribute to determine the validity of this
                attribute's value.)
    '''
    def __init__(self, *args, **kwargs):
        '''
            Takes all a the data elements for the construction of the question
            object.

            :Parameters:
                title : str or unicode
                    the title of the question. optional.  if not supplied, set
                    to None.
                markup_type : type or factory
                    the type used to coerce or adapt the raw 'markup' supplied
                    by the backend to the correct format for use by the
                    application. if not supplied a default of 'str' is used.
                text : str or unicode
                    the text of the question, assigned the result of
                    markup_type(text)
                tags : list of str  or unicode
                    a list of textual  tags used to categorize or filter the
                    question.
        '''
        if 'title' in kwargs:
            self.title = kwargs['title']
        else:
            self.title = None

        if 'markup_type' in kwargs:
            self.markup_type = kwargs['markup_type']
        else:
            self.markup_type = str

        if 'text' in kwargs:
            self.text = self.markup_type(kwargs['text'])
        else:
            raise Exception("Questions must have text!")

        if 'tags' in kwargs:
            self.tags = kwargs['tags']
        else:
            self.tags = []

    def __repr__(self):
        if self.title:
            txt = self.title
        else:
            txt = self.text
        return "<%s %r>" % (self.__class__.__name__, txt)


class MultipleChoiceQuestion(Question):
    def __init__(self, *args, **kwargs):
        super(MultipleChoiceQuestion, self).__init__(*args, **kwargs)
        if 'answers' in kwargs:
            self.answers = []
            for ans in kwargs['answers']:
                self.answers.append(self.markup_type(ans))
        else:
            raise Exception("MultipleChoiceQuestion requires answers!")

        if 'correct' in kwargs:
            self._correct = self.markup_type(kwargs['correct']) 
        else:
            raise Exception("MultipleChoiceQuestion requires a correct answer!")

        self.answered = False
        self._answer = None

    def answer():
        def _fget(self):
            return self._answer
        def _fset(self, val):
            if self.markup_type(val) in self.answers:
                self._answer = val
                self.answered = True
            else:
                self.answered = False
                self._answer = None
                raise ValueError("answer supplied not valid for this question.")
        def _fdel(self):
            self.answered = False
            self._answer = None
        return property(_fget, _fset, _fdel)
    answer = answer()

    @property
    def correct(self):
        #print "DEBUG: self.answer: ", self.answer
        #print "DEBUG: self._correct: ", self._correct
        return self.answer == self._correct


class TrueFalseQuestion(MultipleChoiceQuestion):
    def __init__(self, *args, **kwargs):
        kwargs['answers'] = ['True', 'False']
        super(TrueFalseQuestion, self).__init__(*args, **kwargs)

    @property
    def correct(self):
        #print "DEBUG: self.answer: ", self.answer
        #print "DEBUG: self._correct: ", self._correct
        return self.answer.lower().startswith(self._correct.lower()) #XXX: hack?


#### XXX: The below classes aren't completely implemented. ####


class MissingWordQuestion(MultipleChoiceQuestion):
    def __init__(self, *args, **kwargs):
        super(MissingWordQuestion, self).__init__(*args, **kwargs)
        if 'tail_text' in kwargs:
            self.tail_text = self.markup_type(kwargs['tail_text'])
        else:
            raise Exception("MissingWordQuestion requires a tail_text!")


class ShortAnswerQuestion(Question):
    def __init__(self, *args, **kwargs):
        super(ShortAnswerQuestion, self).__init__(*args, **kwargs)
        if 'correct' in kwargs:
            self.correct = self.markup_type(kwargs['correct'])
        else:
            raise Exception("ShortAnswerQuestion requires a correct answer!")


class NumericalQuestion(Question):
    def __init__(self, *args, **kwargs):
        super(NumericalQuestion, self).__init__(self, *args, **kwargs)
        raise NotImplementedError("Not implemented yet!")


class MatchingQuestion(Question):
    def __init__(self, *args, **kwargs):
        super(MatchingQuestion, self).__init__(*args, **kwargs)
        if 'answers' in kwargs:
            ans = []
            for a1, a2 in kwargs['answers']:
                ans.append((self.markup_type(a1), self.markup_type(a2)))
            self.answers = ans
        else:
            raise Exception("MatchingQuestion must have answers!")