diff --git a/BUGS.md b/BUGS.md index 3da7246..81b6095 100644 --- a/BUGS.md +++ b/BUGS.md @@ -14,7 +14,6 @@ # TODO -- 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. - registar last_seen e remover os antigos de cada vez que houver um login. - indicar qtos topicos faltam (>=50%) para terminar o curso. - ao fim de 3 tentativas com password errada, envia email com nova password. @@ -35,6 +34,7 @@ # FIXED +- 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. - marking all options right in a radio question breaks! - implementar servidor http com redirect para https. - tabelas nas perguntas radio/checkbox não ocupam todo o espaço como em question. diff --git a/aprendizations/questions.py b/aprendizations/questions.py index 689f913..474860a 100644 --- a/aprendizations/questions.py +++ b/aprendizations/questions.py @@ -113,8 +113,8 @@ class QuestionRadio(Question): # check grade boundaries if self['discount'] and not all(0.0 <= x <= 1.0 for x in self['correct']): - msg = (f'If discount=true, correct values must be in the ' - f'interval [0.0, 1.0] in "{self["ref"]}"') + msg = (f'Correct values must be in the interval [0.0, 1.0] in ' + f'"{self["ref"]}"') raise QuestionException(msg) # at least one correct option @@ -217,12 +217,18 @@ class QuestionCheckbox(Question): f'booleans in "{self["ref"]}"') raise QuestionException(msg) - # check grade boundaries (FUTURE) - # if self['discount'] and not all(0.0 <= x <= 1.0 - # for x in self['correct']): - # msg = (f'If discount=true, correct values must be in the ' - # f'interval [0.0, 1.0] in "{self["ref"]}"') - # raise QuestionException(msg) + # check grade boundaries + if self['discount'] and not all(0.0 <= x <= 1.0 + for x in self['correct']): + logger.warning(' * * * BEHAVIOR CHANGE NOTICE * * *') + msg = (f'Correct values must be in the interval [0.0, 1.0] in ' + f'"{self["ref"]}"') + logger.warning(msg) + logger.warning('I will convert "correct" to the new behavior, but ' + 'you should change it in the questions') + logger.warning(' * * * END OF NOTICE * * *') + # normalize to [0,1] + self['correct'] = [(x+1)/2 for x in self['correct']] # if an option is a list of (right, wrong), pick one options = [] @@ -232,9 +238,10 @@ class QuestionCheckbox(Question): r = random.randint(0, 1) o = o[r] if r == 1: - c = -c + # c = -c + c = 1.0 - c options.append(str(o)) - correct.append(float(c)) + correct.append(c) # generate random permutation, e.g. [2,1,4,0,3] # and apply to `options` and `correct` @@ -252,21 +259,20 @@ class QuestionCheckbox(Question): super().correct() if self['answer'] is not None: - sum_abs = sum(abs(p) for p in self['correct']) - if sum_abs < 1e-6: # case correct [0,...,0] avoid div-by-zero - self['grade'] = 1.0 - + x = 0.0 + if self['discount']: + sum_abs = sum(abs(2*p-1) for p in self['correct']) + for i, p in enumerate(self['correct']): + x += 2*p-1 if str(i) in self['answer'] else 1-2*p else: - x = 0.0 - - if self['discount']: - for i, p in enumerate(self['correct']): - x += p if str(i) in self['answer'] else -p - else: - for i, p in enumerate(self['correct']): - x += p if str(i) in self['answer'] else 0.0 + sum_abs = sum(abs(p) for p in self['correct']) + for i, p in enumerate(self['correct']): + x += p if str(i) in self['answer'] else 0.0 + try: self['grade'] = x / sum_abs + except ZeroDivisionError: + self['grade'] = 1.0 # limit p->0 # ============================================================================ diff --git a/demo/math/addition/questions.yaml b/demo/math/addition/questions.yaml index 6480bd4..903dace 100644 --- a/demo/math/addition/questions.yaml +++ b/demo/math/addition/questions.yaml @@ -18,6 +18,6 @@ - Propriedade comutativa, $x+y=y+x$. # wrong - Existência de elemento absorvente, $x+1=1$. - correct: [1, 1, 1, 1, -1] + correct: [1, 1, 1, 1, 0] solution: | A adição não tem elemento absorvente. -- libgit2 0.21.2