Commit 7f38a110684591236eb205c0678d8e6b0abfae05
1 parent
dbe2b67c
Exists in
master
and in
1 other branch
merged questions.py from perguntations
Showing
2 changed files
with
16 additions
and
14 deletions
Show diff stats
BUGS.md
1 | 1 | ||
2 | # BUGS | 2 | # BUGS |
3 | 3 | ||
4 | -- max tries não avança para seguinte ao fim das tentativas. | 4 | +- quando a pergunta devolve comments, este é apresentado, mas fica persistente nas tentativas seguintes. devia ser limpo apos a segunda submissao. |
5 | +- a opcao max_tries na especificacao das perguntas é cumbersome... usar antes tries? | ||
5 | - tabelas nas perguntas radio/checkbox não ocupam todo o espaço como em question. | 6 | - tabelas nas perguntas radio/checkbox não ocupam todo o espaço como em question. |
6 | - nas perguntas de código, quando erra nao se devia acrescentar mesma pergunta no fim. | 7 | - nas perguntas de código, quando erra nao se devia acrescentar mesma pergunta no fim. |
7 | 8 | ||
@@ -28,6 +29,7 @@ | @@ -28,6 +29,7 @@ | ||
28 | 29 | ||
29 | # FIXED | 30 | # FIXED |
30 | 31 | ||
32 | +- max tries não avança para seguinte ao fim das tentativas. | ||
31 | - ver se ref guardada na BD é só a da pergunta ou inclui o path. -> so ref | 33 | - ver se ref guardada na BD é só a da pergunta ou inclui o path. -> so ref |
32 | - nao esta a guardar as respostas erradas. | 34 | - nao esta a guardar as respostas erradas. |
33 | - reload do topic não gera novas perguntas (alunos abusavam do reload) | 35 | - reload do topic não gera novas perguntas (alunos abusavam do reload) |
questions.py
1 | 1 | ||
2 | -# base | 2 | +# python standard library |
3 | import random | 3 | import random |
4 | import re | 4 | import re |
5 | from os import path | 5 | from os import path |
6 | import logging | 6 | import logging |
7 | +import asyncio | ||
7 | 8 | ||
8 | -# packages | 9 | +# user installed libraries |
9 | import yaml | 10 | import yaml |
10 | 11 | ||
11 | # this project | 12 | # this project |
@@ -41,7 +42,7 @@ class Question(dict): | @@ -41,7 +42,7 @@ class Question(dict): | ||
41 | 'files': {}, | 42 | 'files': {}, |
42 | }) | 43 | }) |
43 | 44 | ||
44 | - # FIXME unused. does childs need do override this? | 45 | + # FIXME unused. do childs need do override this? |
45 | # def updateAnswer(answer=None): | 46 | # def updateAnswer(answer=None): |
46 | # self['answer'] = answer | 47 | # self['answer'] = answer |
47 | 48 | ||
@@ -49,6 +50,11 @@ class Question(dict): | @@ -49,6 +50,11 @@ class Question(dict): | ||
49 | self['grade'] = 0.0 | 50 | self['grade'] = 0.0 |
50 | return 0.0 | 51 | return 0.0 |
51 | 52 | ||
53 | + async def correct_async(self): | ||
54 | + loop = asyncio.get_running_loop() | ||
55 | + grade = await loop.run_in_executor(None, self.correct) | ||
56 | + return grade | ||
57 | + | ||
52 | def set_defaults(self, d): | 58 | def set_defaults(self, d): |
53 | 'Add k:v pairs from default dict d for nonexistent keys' | 59 | 'Add k:v pairs from default dict d for nonexistent keys' |
54 | for k,v in d.items(): | 60 | for k,v in d.items(): |
@@ -148,7 +154,7 @@ class QuestionCheckbox(Question): | @@ -148,7 +154,7 @@ class QuestionCheckbox(Question): | ||
148 | # set defaults if missing | 154 | # set defaults if missing |
149 | self.set_defaults({ | 155 | self.set_defaults({ |
150 | 'text': '', | 156 | 'text': '', |
151 | - 'correct': [1.0] * n, # useful for questionaries | 157 | + 'correct': [0.0] * n, # useful for questionaries |
152 | 'shuffle': True, | 158 | 'shuffle': True, |
153 | 'discount': True, | 159 | 'discount': True, |
154 | 'choose': n, # number of options | 160 | 'choose': n, # number of options |
@@ -184,7 +190,7 @@ class QuestionCheckbox(Question): | @@ -184,7 +190,7 @@ class QuestionCheckbox(Question): | ||
184 | if self['answer'] is not None: | 190 | if self['answer'] is not None: |
185 | sum_abs = sum(abs(p) for p in self['correct']) | 191 | sum_abs = sum(abs(p) for p in self['correct']) |
186 | if sum_abs < 1e-6: # case correct [0,...,0] avoid div-by-zero | 192 | if sum_abs < 1e-6: # case correct [0,...,0] avoid div-by-zero |
187 | - self['grade'] = 0.0 | 193 | + self['grade'] = 1.0 |
188 | 194 | ||
189 | else: | 195 | else: |
190 | x = 0.0 | 196 | x = 0.0 |
@@ -293,15 +299,9 @@ class QuestionNumericInterval(Question): | @@ -293,15 +299,9 @@ class QuestionNumericInterval(Question): | ||
293 | super().correct() | 299 | super().correct() |
294 | if self['answer'] is not None: | 300 | if self['answer'] is not None: |
295 | lower, upper = self['correct'] | 301 | lower, upper = self['correct'] |
296 | - try: | ||
297 | - answer = float(self['answer']) | ||
298 | - | ||
299 | - # TODO: | ||
300 | - # alternative using locale (1.2 vs 1,2) | ||
301 | - # import locale | ||
302 | - # locale.setlocale(locale.LC_ALL, 'pt_PT') | ||
303 | - # answer = locale.atof(self['answer']) | ||
304 | 302 | ||
303 | + try: # replace , by . and convert to float | ||
304 | + answer = float(self['answer'].replace(',', '.', 1)) | ||
305 | except ValueError: | 305 | except ValueError: |
306 | self['comments'] = 'A resposta não é numérica.' | 306 | self['comments'] = 'A resposta não é numérica.' |
307 | self['grade'] = 0.0 | 307 | self['grade'] = 0.0 |