Commit 0265ea3af016870a628b568d002c800e0ab3eb24

Authored by Miguel Barão
2 parents 14aad665 4d7a7e9a
Exists in master and in 1 other branch dev

Merge branch 'dev'

demo/questions/questions-tutorial.yaml
... ... @@ -264,7 +264,28 @@
264 264 ```
265 265  
266 266 Neste caso, as respostas aceites são `azul`, `Azul` ou `AZUL`.
267   - correct: ['azul', 'Azul', 'AZUL']
  267 +
  268 + Em alguns casos pode ser conveniente transformar a resposta antes de a
  269 + comparar, por exemplo para remover espaços ou converter para maiúsculas ou
  270 + maiúsculas.
  271 + A opção `transform` permite dar uma sequência de transformações a aplicar à
  272 + resposta do aluno, por exemplo:
  273 +
  274 + ```yaml
  275 + transform: ['trim', 'lower']
  276 + correct: ['azul']
  277 + ```
  278 +
  279 + Neste momento estão disponíveis as seguintes transformações:
  280 +
  281 + * `trim` remove os espaços do início e fim da resposta, os do meio mantêm-se
  282 + inalterados.
  283 + * `remove_space` remove todos os espaços (início, meio e fim).
  284 + * `normalize_space` remove espaços do início e fim (trim), e substitui
  285 + múltiplos espaços por um único espaço (no meio).
  286 + * `lower` e `upper` convertem respectivamente para minúsculas e maiúsculas.
  287 + transform: ['remove_spaces', 'lower']
  288 + correct: ['azul']
268 289  
269 290 # ---------------------------------------------------------------------------
270 291 - type: text-regex
... ...
perguntations/questions.py
... ... @@ -234,7 +234,8 @@ class QuestionText(Question):
234 234  
235 235 self.set_defaults(QDict({
236 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 241 # make sure its always a list of possible correct answers
... ... @@ -244,12 +245,36 @@ class QuestionText(Question):
244 245 # make sure all elements of the list are strings
245 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 272 def correct(self) -> None:
249 273 super().correct()
250 274  
251 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 # ============================================================================
... ...
perguntations/static/css/test.css
1 1 /* Fixes navigation panel overlaying content */
2 2 html {
3   - font-size: 13px;
  3 + font-size: 11pt;
4 4 }
5 5  
6 6 body {
... ... @@ -15,9 +15,12 @@ body {
15 15 }
16 16  
17 17 .card {
18   - margin-top: 5em;
  18 + margin-bottom: 1em;
19 19 }
20 20  
  21 +.alert {
  22 + margin-top: 3em;
  23 +}
21 24  
22 25 textarea {
23 26 font-family: monospace !important;
... ...
perguntations/templates/question.html
1 1 {% autoescape %}
2 2  
3 3 {% block question %}
4   -<div class="card border-dark mb-3">
  4 +<div class="card border-dark">
5 5 <h5 class="card-header text-white bg-dark">
6 6 {{ q['number'] }}. {{ q['title'] }}
7 7 <div class="float-right">
... ...
perguntations/test.py
1 1  
2 2 # python standard library
3   -from os import path, listdir
4   -import fnmatch
  3 +from os import path
5 4 import random
6 5 from datetime import datetime
7 6 import logging
... ...