Commit 667f624a3b3efd564c06865f48e02f3186efb60c
1 parent
4cbc74ad
Exists in
master
and in
1 other branch
- question type text now has a transformed option that is applied to
the answers before the correction.
Showing
3 changed files
with
30 additions
and
5 deletions
Show diff stats
aprendizations/learnapp.py
@@ -370,7 +370,6 @@ class LearnApp(object): | @@ -370,7 +370,6 @@ class LearnApp(object): | ||
370 | 370 | ||
371 | t['path'] = path.join(g.graph['prefix'], tref) # prefix/topic | 371 | t['path'] = path.join(g.graph['prefix'], tref) # prefix/topic |
372 | 372 | ||
373 | - | ||
374 | # ======================================================================== | 373 | # ======================================================================== |
375 | # methods that do not change state (pure functions) | 374 | # methods that do not change state (pure functions) |
376 | # ======================================================================== | 375 | # ======================================================================== |
@@ -379,6 +378,7 @@ class LearnApp(object): | @@ -379,6 +378,7 @@ class LearnApp(object): | ||
379 | # Buils dictionary of question factories | 378 | # Buils dictionary of question factories |
380 | # ------------------------------------------------------------------------ | 379 | # ------------------------------------------------------------------------ |
381 | def make_factory(self) -> Dict[str, QFactory]: | 380 | def make_factory(self) -> Dict[str, QFactory]: |
381 | + | ||
382 | logger.info('Building questions factory:') | 382 | logger.info('Building questions factory:') |
383 | factory: Dict[str, QFactory] = {} | 383 | factory: Dict[str, QFactory] = {} |
384 | g = self.deps | 384 | g = self.deps |
aprendizations/questions.py
@@ -234,7 +234,8 @@ class QuestionText(Question): | @@ -234,7 +234,8 @@ class QuestionText(Question): | ||
234 | 234 | ||
235 | self.set_defaults(QDict({ | 235 | self.set_defaults(QDict({ |
236 | 'text': '', | 236 | 'text': '', |
237 | - 'correct': [], | 237 | + 'correct': [], # no correct answers, always wrong |
238 | + 'transform': [], # transformations applied to the answer, in order | ||
238 | })) | 239 | })) |
239 | 240 | ||
240 | # make sure its always a list of possible correct answers | 241 | # make sure its always a list of possible correct answers |
@@ -244,12 +245,36 @@ class QuestionText(Question): | @@ -244,12 +245,36 @@ class QuestionText(Question): | ||
244 | # make sure all elements of the list are strings | 245 | # make sure all elements of the list are strings |
245 | self['correct'] = [str(a) for a in self['correct']] | 246 | self['correct'] = [str(a) for a in self['correct']] |
246 | 247 | ||
248 | + # make sure that the answers are invariant with respect to the filters | ||
249 | + if any(c != self.transform(c) for c in self['correct']): | ||
250 | + logger.warning(f'in "{self["ref"]}", correct answers are not ' | ||
251 | + 'invariant wrt transformations') | ||
252 | + | ||
253 | + # ------------------------------------------------------------------------ | ||
254 | + # apply optional filters to the answer | ||
255 | + def transform(self, ans): | ||
256 | + for f in self['transform']: | ||
257 | + if f == 'remove_space': | ||
258 | + ans = ans.replace(' ', '') | ||
259 | + elif f == 'trim': | ||
260 | + ans = ans.strip() | ||
261 | + elif f == 'normalize_space': | ||
262 | + ans = re.sub(r'\s+', ' ', ans.strip()) | ||
263 | + elif f == 'lower': | ||
264 | + ans = ans.lower() | ||
265 | + elif f == 'upper': | ||
266 | + ans = ans.upper() | ||
267 | + else: | ||
268 | + logger.warning(f'in "{self["ref"]}", unknown transform "{f}"') | ||
269 | + return ans | ||
270 | + | ||
247 | # ------------------------------------------------------------------------ | 271 | # ------------------------------------------------------------------------ |
248 | def correct(self) -> None: | 272 | def correct(self) -> None: |
249 | super().correct() | 273 | super().correct() |
250 | 274 | ||
251 | if self['answer'] is not None: | 275 | if self['answer'] is not None: |
252 | - self['grade'] = 1.0 if self['answer'] in self['correct'] else 0.0 | 276 | + answer = self.transform(self['answer']) # apply transformations |
277 | + self['grade'] = 1.0 if answer in self['correct'] else 0.0 | ||
253 | 278 | ||
254 | 279 | ||
255 | # ============================================================================ | 280 | # ============================================================================ |
aprendizations/student.py
@@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
3 | from datetime import datetime | 3 | from datetime import datetime |
4 | import logging | 4 | import logging |
5 | import random | 5 | import random |
6 | -from typing import Dict, List, Optional, Tuple | 6 | +from typing import List, Optional, Tuple |
7 | 7 | ||
8 | # third party libraries | 8 | # third party libraries |
9 | import networkx as nx | 9 | import networkx as nx |
@@ -176,7 +176,7 @@ class StudentState(object): | @@ -176,7 +176,7 @@ class StudentState(object): | ||
176 | dt = now - s['date'] | 176 | dt = now - s['date'] |
177 | try: | 177 | try: |
178 | forgetting_factor = self.deps.nodes[tref]['forgetting_factor'] | 178 | forgetting_factor = self.deps.nodes[tref]['forgetting_factor'] |
179 | - s['level'] *= forgetting_factor ** dt.days # forgetting factor | 179 | + s['level'] *= forgetting_factor ** dt.days # forgetting factor |
180 | except KeyError: | 180 | except KeyError: |
181 | logger.warning(f'Topic {tref} is not on the graph!') | 181 | logger.warning(f'Topic {tref} is not on the graph!') |
182 | 182 |