Commit 8e02b9b9774fdd596761b809d92a0b72de8b0456
1 parent
99ccba47
Exists in
master
and in
1 other branch
text-regex questions now accept also a list of regular expressions to
match. It's considered correct if any match is found.
Showing
1 changed file
with
23 additions
and
10 deletions
Show diff stats
aprendizations/questions.py
| ... | ... | @@ -257,8 +257,11 @@ class QuestionTextRegex(Question): |
| 257 | 257 | '''An instance of QuestionTextRegex will always have the keys: |
| 258 | 258 | type (str) |
| 259 | 259 | text (str) |
| 260 | - correct (str with regex) | |
| 260 | + correct (str or list[str]) | |
| 261 | 261 | answer (None or an actual answer) |
| 262 | + | |
| 263 | + The correct strings are python standard regular expressions. | |
| 264 | + Grade is 1.0 when the answer matches any of the regex in the list. | |
| 262 | 265 | ''' |
| 263 | 266 | |
| 264 | 267 | # ------------------------------------------------------------------------ |
| ... | ... | @@ -267,19 +270,29 @@ class QuestionTextRegex(Question): |
| 267 | 270 | |
| 268 | 271 | self.set_defaults(QDict({ |
| 269 | 272 | 'text': '', |
| 270 | - 'correct': '$.^', # will always return false | |
| 273 | + 'correct': ['$.^'], # will always return false | |
| 271 | 274 | })) |
| 272 | 275 | |
| 276 | + # make sure its always a list of regular expressions | |
| 277 | + if not isinstance(self['correct'], list): | |
| 278 | + self['correct'] = [self['correct']] | |
| 279 | + | |
| 280 | + # make sure all elements of the list are strings | |
| 281 | + self['correct'] = [str(a) for a in self['correct']] | |
| 282 | + | |
| 273 | 283 | # ------------------------------------------------------------------------ |
| 274 | 284 | def correct(self) -> None: |
| 275 | 285 | super().correct() |
| 276 | 286 | if self['answer'] is not None: |
| 277 | - try: | |
| 278 | - ok = re.match(self['correct'], self['answer']) | |
| 279 | - except TypeError: | |
| 280 | - logger.error(f'While matching regex {self["correct"]} with ' | |
| 281 | - f'answer {self["answer"]}.') | |
| 282 | - self['grade'] = 1.0 if ok else 0.0 | |
| 287 | + self['grade'] = 0.0 | |
| 288 | + for r in self['correct']: | |
| 289 | + try: | |
| 290 | + if re.match(r, self['answer']): | |
| 291 | + self['grade'] = 1.0 | |
| 292 | + return | |
| 293 | + except TypeError: | |
| 294 | + logger.error(f'While matching regex {self["correct"]} with' | |
| 295 | + f' answer "{self["answer"]}".') | |
| 283 | 296 | |
| 284 | 297 | |
| 285 | 298 | # ============================================================================ |
| ... | ... | @@ -421,8 +434,8 @@ class QuestionInformation(Question): |
| 421 | 434 | # To generate an instance of a question we use the method generate(). |
| 422 | 435 | # It returns a question instance of the correct class. |
| 423 | 436 | # There is also an asynchronous version called gen_async(). This version is |
| 424 | -# synchronous for all question types (radio, checkbox, etc) except for generator | |
| 425 | -# types which run asynchronously. | |
| 437 | +# synchronous for all question types (radio, checkbox, etc) except for | |
| 438 | +# generator types which run asynchronously. | |
| 426 | 439 | # |
| 427 | 440 | # Example: |
| 428 | 441 | # | ... | ... |