Commit d5ac4a8b612e977d9b6102f0e73de16a1fc1cb96
1 parent
3cd9487a
Exists in
master
and in
1 other branch
- Added new question type text_numeric. Expects a numerical answer and checks if…
… it's in a given interval.
Showing
5 changed files
with
67 additions
and
22 deletions
Show diff stats
demo/questions/questions.yaml
| @@ -67,6 +67,12 @@ | @@ -67,6 +67,12 @@ | ||
| 67 | type: text_regex | 67 | type: text_regex |
| 68 | text: O nosso planeta chama-se planeta... | 68 | text: O nosso planeta chama-se planeta... |
| 69 | correct: !regex '[Tt]erra' | 69 | correct: !regex '[Tt]erra' |
| 70 | + # --------------------------------------------------------------------------- | ||
| 71 | +- | ||
| 72 | + ref: fractions | ||
| 73 | + type: text_numeric | ||
| 74 | + text: Quanto é 1/4? | ||
| 75 | + correct: [0.249, 0.251] | ||
| 70 | # --------------------------------------------------------------------------- | 76 | # --------------------------------------------------------------------------- |
| 71 | - | 77 | - |
| 72 | ref: basic-colors | 78 | ref: basic-colors |
demo/test.yaml
| @@ -40,30 +40,32 @@ files: | @@ -40,30 +40,32 @@ files: | ||
| 40 | # The order is preserved. | 40 | # The order is preserved. |
| 41 | # There are several ways to define each question (explained below). | 41 | # There are several ways to define each question (explained below). |
| 42 | questions: | 42 | questions: |
| 43 | - # show question where ref=instructions | ||
| 44 | - - ref: instructions | 43 | + # # show question where ref=instructions |
| 44 | + # - ref: instructions | ||
| 45 | 45 | ||
| 46 | - # show question where ref=flags and assigns 0.5 points (unnormalized) | ||
| 47 | - - ref: flags | ||
| 48 | - points: 0.5 | 46 | + # # show question where ref=flags and assigns 0.5 points (unnormalized) |
| 47 | + # - ref: flags | ||
| 48 | + # points: 0.5 | ||
| 49 | 49 | ||
| 50 | - # idem | ||
| 51 | - - ref: math-expressions | ||
| 52 | - points: 2.0 | 50 | + # # idem |
| 51 | + # - ref: math-expressions | ||
| 52 | + # points: 2.0 | ||
| 53 | 53 | ||
| 54 | - # show question where ref=solar-system and assign the default of 1.0 point (unnormalized) | ||
| 55 | - - ref: solar-system | 54 | + # # show question where ref=solar-system and assign the default of 1.0 point (unnormalized) |
| 55 | + # - ref: solar-system | ||
| 56 | 56 | ||
| 57 | - # select one questions from the list [our_planet1, our_planet2] | ||
| 58 | - # and assign 0.75 points (unnormalized) | ||
| 59 | - - ref: | ||
| 60 | - - our_planet1 | ||
| 61 | - - our_planet2 | ||
| 62 | - points: 0.75 | 57 | + # # select one questions from the list [our_planet1, our_planet2] |
| 58 | + # # and assign 0.75 points (unnormalized) | ||
| 59 | + # - ref: | ||
| 60 | + # - our_planet1 | ||
| 61 | + # - our_planet2 | ||
| 62 | + # points: 0.75 | ||
| 63 | 63 | ||
| 64 | - # the key 'ref:' can be omitted, a default of 1.0 points is assigned | ||
| 65 | - - basic-colors | 64 | + # # the key 'ref:' can be omitted, a default of 1.0 points is assigned |
| 65 | + # - basic-colors | ||
| 66 | 66 | ||
| 67 | - - question-whatever | 67 | + - fractions |
| 68 | 68 | ||
| 69 | - - markdown_instructions | 69 | + # - question-whatever |
| 70 | + | ||
| 71 | + # - markdown_instructions |
questions.py
| @@ -122,6 +122,7 @@ class QuestionFactory(dict): | @@ -122,6 +122,7 @@ class QuestionFactory(dict): | ||
| 122 | 'checkbox' : QuestionCheckbox, | 122 | 'checkbox' : QuestionCheckbox, |
| 123 | 'text' : QuestionText, | 123 | 'text' : QuestionText, |
| 124 | 'text_regex': QuestionTextRegex, | 124 | 'text_regex': QuestionTextRegex, |
| 125 | + 'text_numeric': QuestionTextNumeric, | ||
| 125 | 'textarea' : QuestionTextArea, | 126 | 'textarea' : QuestionTextArea, |
| 126 | # informative panels | 127 | # informative panels |
| 127 | 'information': QuestionInformation, | 128 | 'information': QuestionInformation, |
| @@ -383,6 +384,42 @@ class QuestionTextRegex(Question): | @@ -383,6 +384,42 @@ class QuestionTextRegex(Question): | ||
| 383 | 384 | ||
| 384 | 385 | ||
| 385 | # =========================================================================== | 386 | # =========================================================================== |
| 387 | +class QuestionTextNumeric(Question): | ||
| 388 | + '''An instance of QuestionTextNumeric will always have the keys: | ||
| 389 | + type (str) | ||
| 390 | + text (str) | ||
| 391 | + correct (list [lower bound, upper bound]) | ||
| 392 | + answer (None or an actual answer) | ||
| 393 | + An answer is correct if it's in the closed interval. | ||
| 394 | + ''' | ||
| 395 | + | ||
| 396 | + #------------------------------------------------------------------------ | ||
| 397 | + def __init__(self, q): | ||
| 398 | + super().__init__(q) | ||
| 399 | + | ||
| 400 | + self.set_defaults({ | ||
| 401 | + 'text': '', | ||
| 402 | + 'correct': [1.0, -1.0], # will always return false | ||
| 403 | + }) | ||
| 404 | + | ||
| 405 | + #------------------------------------------------------------------------ | ||
| 406 | + # can return negative values for wrong answers | ||
| 407 | + def correct(self): | ||
| 408 | + super().correct() | ||
| 409 | + if self['answer'] is not None: | ||
| 410 | + lower, upper = self['correct'] | ||
| 411 | + print(lower) | ||
| 412 | + print(upper) | ||
| 413 | + try: | ||
| 414 | + self['grade'] = 1.0 if lower <= float(self['answer']) <= upper else 0.0 | ||
| 415 | + except TypeError: | ||
| 416 | + logger.error('While matching regex {0} with answer {1}.'.format(self['correct'], self['answer'])) | ||
| 417 | + except ValueError: | ||
| 418 | + self['comments'] = f'A resposta "{self["answer"]}" não é numérica.' | ||
| 419 | + return self['grade'] | ||
| 420 | + | ||
| 421 | + | ||
| 422 | +# =========================================================================== | ||
| 386 | class QuestionTextArea(Question): | 423 | class QuestionTextArea(Question): |
| 387 | '''An instance of QuestionTextArea will always have the keys: | 424 | '''An instance of QuestionTextArea will always have the keys: |
| 388 | type (str) | 425 | type (str) |
templates/review.html
| @@ -207,7 +207,7 @@ | @@ -207,7 +207,7 @@ | ||
| 207 | </li> | 207 | </li> |
| 208 | % endfor | 208 | % endfor |
| 209 | </ul> | 209 | </ul> |
| 210 | - % elif q['type'] in ('text', 'text_regex', 'textarea'): | 210 | + % elif q['type'] in ('text', 'text_regex', 'text_numeric', 'textarea'): |
| 211 | <pre>${q['answer'] if q['answer'] is not None else ''}</pre> | 211 | <pre>${q['answer'] if q['answer'] is not None else ''}</pre> |
| 212 | % endif | 212 | % endif |
| 213 | 213 |
templates/test.html
| @@ -157,7 +157,7 @@ | @@ -157,7 +157,7 @@ | ||
| 157 | </a> | 157 | </a> |
| 158 | % endfor | 158 | % endfor |
| 159 | </div> | 159 | </div> |
| 160 | - % elif q['type'] in ('text', 'text_regex'): | 160 | + % elif q['type'] in ('text', 'text_regex', 'text_numeric'): |
| 161 | <input type="text" name="${i}" class="form-control" value="${q['answer'] if q['answer'] is not None else ''}"> | 161 | <input type="text" name="${i}" class="form-control" value="${q['answer'] if q['answer'] is not None else ''}"> |
| 162 | % elif q['type'] == 'textarea': | 162 | % elif q['type'] == 'textarea': |
| 163 | <textarea class="form-control" rows="${q['lines']}" name="${i}">${q['answer'] if q['answer'] is not None else ''}</textarea><br /> | 163 | <textarea class="form-control" rows="${q['lines']}" name="${i}">${q['answer'] if q['answer'] is not None else ''}</textarea><br /> |