Commit 285737793e41c26cb755229456943354128ee906

Authored by Miguel Barão
1 parent 8f643ad6
Exists in master and in 1 other branch dev

- changes checkbox correct list to the same semantics as radio with

interval values in the interval [0,1]
BUGS.md
... ... @@ -14,7 +14,6 @@
14 14  
15 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 17 - registar last_seen e remover os antigos de cada vez que houver um login.
19 18 - indicar qtos topicos faltam (>=50%) para terminar o curso.
20 19 - ao fim de 3 tentativas com password errada, envia email com nova password.
... ... @@ -35,6 +34,7 @@
35 34  
36 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 38 - marking all options right in a radio question breaks!
39 39 - implementar servidor http com redirect para https.
40 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 113 # check grade boundaries
114 114 if self['discount'] and not all(0.0 <= x <= 1.0
115 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 118 raise QuestionException(msg)
119 119  
120 120 # at least one correct option
... ... @@ -217,12 +217,18 @@ class QuestionCheckbox(Question):
217 217 f'booleans in "{self["ref"]}"')
218 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 233 # if an option is a list of (right, wrong), pick one
228 234 options = []
... ... @@ -232,9 +238,10 @@ class QuestionCheckbox(Question):
232 238 r = random.randint(0, 1)
233 239 o = o[r]
234 240 if r == 1:
235   - c = -c
  241 + # c = -c
  242 + c = 1.0 - c
236 243 options.append(str(o))
237   - correct.append(float(c))
  244 + correct.append(c)
238 245  
239 246 # generate random permutation, e.g. [2,1,4,0,3]
240 247 # and apply to `options` and `correct`
... ... @@ -252,21 +259,20 @@ class QuestionCheckbox(Question):
252 259 super().correct()
253 260  
254 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 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 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 18 - Propriedade comutativa, $x+y=y+x$.
19 19 # wrong
20 20 - Existência de elemento absorvente, $x+1=1$.
21   - correct: [1, 1, 1, 1, -1]
  21 + correct: [1, 1, 1, 1, 0]
22 22 solution: |
23 23 A adição não tem elemento absorvente.
... ...