Commit 94b0dd76345d616bd319a464778ad836923185ec

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

fixes error in checkbox questions when shuffle=false.

aprendizations/learnapp.py
@@ -44,8 +44,8 @@ class LearnApp(object): @@ -44,8 +44,8 @@ class LearnApp(object):
44 yield session 44 yield session
45 session.commit() 45 session.commit()
46 except Exception: 46 except Exception:
47 - session.rollback()  
48 logger.error('DB rollback!!!') 47 logger.error('DB rollback!!!')
  48 + session.rollback()
49 finally: 49 finally:
50 session.close() 50 session.close()
51 51
aprendizations/questions.py
@@ -50,8 +50,6 @@ class Question(dict): @@ -50,8 +50,6 @@ class Question(dict):
50 50
51 async def correct_async(self) -> None: 51 async def correct_async(self) -> None:
52 self.correct() 52 self.correct()
53 - # loop = asyncio.get_running_loop()  
54 - # await loop.run_in_executor(None, self.correct)  
55 53
56 def set_defaults(self, d: QDict) -> None: 54 def set_defaults(self, d: QDict) -> None:
57 'Add k:v pairs from default dict d for nonexistent keys' 55 'Add k:v pairs from default dict d for nonexistent keys'
@@ -94,7 +92,9 @@ class QuestionRadio(Question): @@ -94,7 +92,9 @@ class QuestionRadio(Question):
94 for x in range(n)] 92 for x in range(n)]
95 93
96 if len(self['correct']) != n: 94 if len(self['correct']) != n:
97 - msg = f'Options and correct mismatch in "{self["ref"]}"' 95 + msg = (f'Options and correct mismatch in '
  96 + f'"{self["ref"]}", file "{self["filename"]}".')
  97 + logger.error(msg)
98 raise QuestionException(msg) 98 raise QuestionException(msg)
99 99
100 if self['shuffle']: 100 if self['shuffle']:
@@ -168,18 +168,20 @@ class QuestionCheckbox(Question): @@ -168,18 +168,20 @@ class QuestionCheckbox(Question):
168 })) 168 }))
169 169
170 if len(self['correct']) != n: 170 if len(self['correct']) != n:
171 - msg = f'Options and correct mismatch in "{self["ref"]}"' 171 + msg = (f'Options and correct size mismatch in '
  172 + f'"{self["ref"]}", file "{self["filename"]}".')
  173 + logger.error(msg)
172 raise QuestionException(msg) 174 raise QuestionException(msg)
173 175
174 # if an option is a list of (right, wrong), pick one 176 # if an option is a list of (right, wrong), pick one
175 - # FIXME it's possible that all options are chosen wrong  
176 options = [] 177 options = []
177 correct = [] 178 correct = []
178 for o, c in zip(self['options'], self['correct']): 179 for o, c in zip(self['options'], self['correct']):
179 if isinstance(o, list): 180 if isinstance(o, list):
180 r = random.randint(0, 1) 181 r = random.randint(0, 1)
181 o = o[r] 182 o = o[r]
182 - c = c if r == 0 else -c 183 + if r == 1:
  184 + c = -c
183 options.append(str(o)) 185 options.append(str(o))
184 correct.append(float(c)) 186 correct.append(float(c))
185 187
@@ -187,8 +189,11 @@ class QuestionCheckbox(Question): @@ -187,8 +189,11 @@ class QuestionCheckbox(Question):
187 # and apply to `options` and `correct` 189 # and apply to `options` and `correct`
188 if self['shuffle']: 190 if self['shuffle']:
189 perm = random.sample(range(n), k=self['choose']) 191 perm = random.sample(range(n), k=self['choose'])
190 - self['options'] = [str(options[i]) for i in perm]  
191 - self['correct'] = [float(correct[i]) for i in perm] 192 + self['options'] = [options[i] for i in perm]
  193 + self['correct'] = [correct[i] for i in perm]
  194 + else:
  195 + self['options'] = options[:self['choose']]
  196 + self['correct'] = correct[:self['choose']]
192 197
193 # ------------------------------------------------------------------------ 198 # ------------------------------------------------------------------------
194 # can return negative values for wrong answers 199 # can return negative values for wrong answers
@@ -443,20 +448,20 @@ class QFactory(object): @@ -443,20 +448,20 @@ class QFactory(object):
443 'textarea': QuestionTextArea, 448 'textarea': QuestionTextArea,
444 # -- informative panels -- 449 # -- informative panels --
445 'information': QuestionInformation, 450 'information': QuestionInformation,
  451 + 'success': QuestionInformation,
446 'warning': QuestionInformation, 452 'warning': QuestionInformation,
447 'alert': QuestionInformation, 453 'alert': QuestionInformation,
448 - 'success': QuestionInformation,  
449 } 454 }
450 455
451 - def __init__(self, question_dict: QDict = QDict({})) -> None:  
452 - self.question = question_dict 456 + def __init__(self, qdict: QDict = QDict({})) -> None:
  457 + self.question = qdict
453 458
454 # ----------------------------------------------------------------------- 459 # -----------------------------------------------------------------------
455 # Given a ref returns an instance of a descendent of Question(), 460 # Given a ref returns an instance of a descendent of Question(),
456 # i.e. a question object (radio, checkbox, ...). 461 # i.e. a question object (radio, checkbox, ...).
457 # ----------------------------------------------------------------------- 462 # -----------------------------------------------------------------------
458 def generate(self) -> Question: 463 def generate(self) -> Question:
459 - logger.debug(f'[generate] "{self.question["ref"]}"...') 464 + logger.debug(f'[QFactory.generate] "{self.question["ref"]}"...')
460 # Shallow copy so that script generated questions will not replace 465 # Shallow copy so that script generated questions will not replace
461 # the original generators 466 # the original generators
462 q = self.question.copy() 467 q = self.question.copy()
@@ -487,7 +492,7 @@ class QFactory(object): @@ -487,7 +492,7 @@ class QFactory(object):
487 492
488 # ----------------------------------------------------------------------- 493 # -----------------------------------------------------------------------
489 async def generate_async(self) -> Question: 494 async def generate_async(self) -> Question:
490 - logger.debug(f'[generate_async] "{self.question["ref"]}"...') 495 + logger.debug(f'[QFactory.generate_async] "{self.question["ref"]}"...')
491 # Shallow copy so that script generated questions will not replace 496 # Shallow copy so that script generated questions will not replace
492 # the original generators 497 # the original generators
493 q = self.question.copy() 498 q = self.question.copy()
aprendizations/tools.py
@@ -145,7 +145,7 @@ def load_yaml(filename: str, default: Any = None) -> Any: @@ -145,7 +145,7 @@ def load_yaml(filename: str, default: Any = None) -> Any:
145 logger.error(f'Cannot open "{filename}": not found') 145 logger.error(f'Cannot open "{filename}": not found')
146 except PermissionError: 146 except PermissionError:
147 logger.error(f'Cannot open "{filename}": no permission') 147 logger.error(f'Cannot open "{filename}": no permission')
148 - except IOError: 148 + except OSError:
149 logger.error(f'Cannot open file "{filename}"') 149 logger.error(f'Cannot open file "{filename}"')
150 else: 150 else:
151 with f: 151 with f: