Commit 285737793e41c26cb755229456943354128ee906
1 parent
8f643ad6
Exists in
master
and in
1 other branch
- changes checkbox correct list to the same semantics as radio with
interval values in the interval [0,1]
Showing
3 changed files
with
30 additions
and
24 deletions
Show diff stats
BUGS.md
@@ -14,7 +14,6 @@ | @@ -14,7 +14,6 @@ | ||
14 | 14 | ||
15 | # TODO | 15 | # TODO |
16 | 16 | ||
17 | -- checkbox devia ter correct no intervalo [0,1] tal como radio. em caso de desconto a correccção faz 2*x-1. isto permite a mesma semantica nos dois tipos de perguntas. | ||
18 | - registar last_seen e remover os antigos de cada vez que houver um login. | 17 | - registar last_seen e remover os antigos de cada vez que houver um login. |
19 | - indicar qtos topicos faltam (>=50%) para terminar o curso. | 18 | - indicar qtos topicos faltam (>=50%) para terminar o curso. |
20 | - ao fim de 3 tentativas com password errada, envia email com nova password. | 19 | - ao fim de 3 tentativas com password errada, envia email com nova password. |
@@ -35,6 +34,7 @@ | @@ -35,6 +34,7 @@ | ||
35 | 34 | ||
36 | # FIXED | 35 | # FIXED |
37 | 36 | ||
37 | +- checkbox devia ter correct no intervalo [0,1] tal como radio. em caso de desconto a correccção faz 2*x-1. isto permite a mesma semantica nos dois tipos de perguntas. | ||
38 | - marking all options right in a radio question breaks! | 38 | - marking all options right in a radio question breaks! |
39 | - implementar servidor http com redirect para https. | 39 | - implementar servidor http com redirect para https. |
40 | - tabelas nas perguntas radio/checkbox não ocupam todo o espaço como em question. | 40 | - tabelas nas perguntas radio/checkbox não ocupam todo o espaço como em question. |
aprendizations/questions.py
@@ -113,8 +113,8 @@ class QuestionRadio(Question): | @@ -113,8 +113,8 @@ class QuestionRadio(Question): | ||
113 | # check grade boundaries | 113 | # check grade boundaries |
114 | if self['discount'] and not all(0.0 <= x <= 1.0 | 114 | if self['discount'] and not all(0.0 <= x <= 1.0 |
115 | for x in self['correct']): | 115 | for x in self['correct']): |
116 | - msg = (f'If discount=true, correct values must be in the ' | ||
117 | - f'interval [0.0, 1.0] in "{self["ref"]}"') | 116 | + msg = (f'Correct values must be in the interval [0.0, 1.0] in ' |
117 | + f'"{self["ref"]}"') | ||
118 | raise QuestionException(msg) | 118 | raise QuestionException(msg) |
119 | 119 | ||
120 | # at least one correct option | 120 | # at least one correct option |
@@ -217,12 +217,18 @@ class QuestionCheckbox(Question): | @@ -217,12 +217,18 @@ class QuestionCheckbox(Question): | ||
217 | f'booleans in "{self["ref"]}"') | 217 | f'booleans in "{self["ref"]}"') |
218 | raise QuestionException(msg) | 218 | raise QuestionException(msg) |
219 | 219 | ||
220 | - # check grade boundaries (FUTURE) | ||
221 | - # if self['discount'] and not all(0.0 <= x <= 1.0 | ||
222 | - # for x in self['correct']): | ||
223 | - # msg = (f'If discount=true, correct values must be in the ' | ||
224 | - # f'interval [0.0, 1.0] in "{self["ref"]}"') | ||
225 | - # raise QuestionException(msg) | 220 | + # check grade boundaries |
221 | + if self['discount'] and not all(0.0 <= x <= 1.0 | ||
222 | + for x in self['correct']): | ||
223 | + logger.warning(' * * * BEHAVIOR CHANGE NOTICE * * *') | ||
224 | + msg = (f'Correct values must be in the interval [0.0, 1.0] in ' | ||
225 | + f'"{self["ref"]}"') | ||
226 | + logger.warning(msg) | ||
227 | + logger.warning('I will convert "correct" to the new behavior, but ' | ||
228 | + 'you should change it in the questions') | ||
229 | + logger.warning(' * * * END OF NOTICE * * *') | ||
230 | + # normalize to [0,1] | ||
231 | + self['correct'] = [(x+1)/2 for x in self['correct']] | ||
226 | 232 | ||
227 | # if an option is a list of (right, wrong), pick one | 233 | # if an option is a list of (right, wrong), pick one |
228 | options = [] | 234 | options = [] |
@@ -232,9 +238,10 @@ class QuestionCheckbox(Question): | @@ -232,9 +238,10 @@ class QuestionCheckbox(Question): | ||
232 | r = random.randint(0, 1) | 238 | r = random.randint(0, 1) |
233 | o = o[r] | 239 | o = o[r] |
234 | if r == 1: | 240 | if r == 1: |
235 | - c = -c | 241 | + # c = -c |
242 | + c = 1.0 - c | ||
236 | options.append(str(o)) | 243 | options.append(str(o)) |
237 | - correct.append(float(c)) | 244 | + correct.append(c) |
238 | 245 | ||
239 | # generate random permutation, e.g. [2,1,4,0,3] | 246 | # generate random permutation, e.g. [2,1,4,0,3] |
240 | # and apply to `options` and `correct` | 247 | # and apply to `options` and `correct` |
@@ -252,21 +259,20 @@ class QuestionCheckbox(Question): | @@ -252,21 +259,20 @@ class QuestionCheckbox(Question): | ||
252 | super().correct() | 259 | super().correct() |
253 | 260 | ||
254 | if self['answer'] is not None: | 261 | if self['answer'] is not None: |
255 | - sum_abs = sum(abs(p) for p in self['correct']) | ||
256 | - if sum_abs < 1e-6: # case correct [0,...,0] avoid div-by-zero | ||
257 | - self['grade'] = 1.0 | ||
258 | - | 262 | + x = 0.0 |
263 | + if self['discount']: | ||
264 | + sum_abs = sum(abs(2*p-1) for p in self['correct']) | ||
265 | + for i, p in enumerate(self['correct']): | ||
266 | + x += 2*p-1 if str(i) in self['answer'] else 1-2*p | ||
259 | else: | 267 | else: |
260 | - x = 0.0 | ||
261 | - | ||
262 | - if self['discount']: | ||
263 | - for i, p in enumerate(self['correct']): | ||
264 | - x += p if str(i) in self['answer'] else -p | ||
265 | - else: | ||
266 | - for i, p in enumerate(self['correct']): | ||
267 | - x += p if str(i) in self['answer'] else 0.0 | 268 | + sum_abs = sum(abs(p) for p in self['correct']) |
269 | + for i, p in enumerate(self['correct']): | ||
270 | + x += p if str(i) in self['answer'] else 0.0 | ||
268 | 271 | ||
272 | + try: | ||
269 | self['grade'] = x / sum_abs | 273 | self['grade'] = x / sum_abs |
274 | + except ZeroDivisionError: | ||
275 | + self['grade'] = 1.0 # limit p->0 | ||
270 | 276 | ||
271 | 277 | ||
272 | # ============================================================================ | 278 | # ============================================================================ |
demo/math/addition/questions.yaml
@@ -18,6 +18,6 @@ | @@ -18,6 +18,6 @@ | ||
18 | - Propriedade comutativa, $x+y=y+x$. | 18 | - Propriedade comutativa, $x+y=y+x$. |
19 | # wrong | 19 | # wrong |
20 | - Existência de elemento absorvente, $x+1=1$. | 20 | - Existência de elemento absorvente, $x+1=1$. |
21 | - correct: [1, 1, 1, 1, -1] | 21 | + correct: [1, 1, 1, 1, 0] |
22 | solution: | | 22 | solution: | |
23 | A adição não tem elemento absorvente. | 23 | A adição não tem elemento absorvente. |