Commit b6f3badfe6abdd4ccbc68f525e0ee547e05a3570
1 parent
7e984525
Exists in
master
and in
1 other branch
- fix some mypy errors.
- added some type annotations - fix recomment_topic_sequence argument not being used - fix load_yaml error line number info
Showing
5 changed files
with
20 additions
and
17 deletions
Show diff stats
BUGS.md
... | ... | @@ -40,6 +40,7 @@ sqlite3.ProgrammingError: SQLite objects created in a thread can only be used in |
40 | 40 | |
41 | 41 | # FIXED |
42 | 42 | |
43 | +- forgetting factor is hardcoded in student.py | |
43 | 44 | - add aprendizatons --version |
44 | 45 | - se aluno abre dois tabs no browser, conseque navegar em simultaneo para perguntas diferentes. quando submete uma delas dá asneira. Tem de haver um campo hidden que tenha um céodigo único que indique qual a pergunta. do lado do servidor apnas há o codigo da pergunta corrente, se forem diferentes faz redirect para /. |
45 | 46 | - nos topicos learn.yaml, qd falha acrescenta no fim. nao faz sentido. | ... | ... |
aprendizations/serve.py
... | ... | @@ -299,14 +299,14 @@ class QuestionHandler(BaseHandler): |
299 | 299 | # --- answers are in a list. fix depending on question type |
300 | 300 | qtype = self.learn.get_student_question_type(user) |
301 | 301 | if qtype in ('success', 'information', 'info'): |
302 | - answer = None | |
302 | + ans = None | |
303 | 303 | elif qtype == 'radio' and not answer: |
304 | - answer = None | |
304 | + ans = None | |
305 | 305 | elif qtype != 'checkbox': # radio, text, textarea, ... |
306 | - answer = answer[0] | |
306 | + ans = answer[0] | |
307 | 307 | |
308 | 308 | # --- check answer (nonblocking) and get corrected question and action |
309 | - q, action = await self.learn.check_answer(user, answer) | |
309 | + q, action = await self.learn.check_answer(user, ans) | |
310 | 310 | |
311 | 311 | # --- built response to return |
312 | 312 | response = {'method': action, 'params': {}} | ... | ... |
aprendizations/student.py
... | ... | @@ -3,6 +3,7 @@ |
3 | 3 | import random |
4 | 4 | from datetime import datetime |
5 | 5 | import logging |
6 | +from typing import List | |
6 | 7 | |
7 | 8 | # third party libraries |
8 | 9 | import networkx as nx |
... | ... | @@ -52,7 +53,7 @@ class StudentState(object): |
52 | 53 | pred = self.deps.predecessors(topic) |
53 | 54 | min_level = self.deps.node[topic]['min_level'] |
54 | 55 | if all(d in self.state and self.state[d]['level'] > min_level |
55 | - for d in pred): # all deps are greater than min_level | |
56 | + for d in pred): # all deps are greater than min_level | |
56 | 57 | |
57 | 58 | self.state[topic] = { |
58 | 59 | 'level': 0.0, # unlocked |
... | ... | @@ -92,11 +93,6 @@ class StudentState(object): |
92 | 93 | questions = t['questions'][:k] |
93 | 94 | logger.debug(f'[start_topic] questions: {", ".join(questions)}') |
94 | 95 | |
95 | - # synchronous | |
96 | - # self.questions = [self.factory[ref].generate() | |
97 | - # for ref in questions] | |
98 | - | |
99 | - # asynchronous: | |
100 | 96 | self.questions = [await self.factory[ref].generate_async() |
101 | 97 | for ref in questions] |
102 | 98 | |
... | ... | @@ -180,14 +176,21 @@ class StudentState(object): |
180 | 176 | # pure functions of the state (no side effects) |
181 | 177 | # ======================================================================== |
182 | 178 | |
183 | - def topic_has_finished(self): | |
179 | + def topic_has_finished(self) -> bool: | |
184 | 180 | return self.current_question is None |
185 | 181 | |
186 | 182 | # ------------------------------------------------------------------------ |
187 | 183 | # compute recommended sequence of topics ['a', 'b', ...] |
188 | 184 | # ------------------------------------------------------------------------ |
189 | - def recommend_topic_sequence(self, target=None): | |
185 | + def recommend_topic_sequence(self, target: str = '') -> List[str]: | |
190 | 186 | tt = list(nx.topological_sort(self.deps)) |
187 | + try: | |
188 | + idx = tt.index(target) | |
189 | + except ValueError: | |
190 | + pass | |
191 | + else: | |
192 | + del tt[idx:] | |
193 | + | |
191 | 194 | unlocked = [t for t in tt if t in self.state] |
192 | 195 | locked = [t for t in tt if t not in unlocked] |
193 | 196 | return unlocked + locked |
... | ... | @@ -197,11 +200,11 @@ class StudentState(object): |
197 | 200 | return self.current_question |
198 | 201 | |
199 | 202 | # ------------------------------------------------------------------------ |
200 | - def get_current_topic(self): | |
203 | + def get_current_topic(self) -> str: | |
201 | 204 | return self.current_topic |
202 | 205 | |
203 | 206 | # ------------------------------------------------------------------------ |
204 | - def is_locked(self, topic): | |
207 | + def is_locked(self, topic: str) -> bool: | |
205 | 208 | return topic not in self.state |
206 | 209 | |
207 | 210 | # ------------------------------------------------------------------------ |
... | ... | @@ -227,7 +230,7 @@ class StudentState(object): |
227 | 230 | return self.state[topic]['level'] |
228 | 231 | |
229 | 232 | # ------------------------------------------------------------------------ |
230 | - def get_topic_date(self, topic): | |
233 | + def get_topic_date(self, topic: str): | |
231 | 234 | return self.state[topic]['date'] |
232 | 235 | |
233 | 236 | # ------------------------------------------------------------------------ | ... | ... |
aprendizations/tools.py
... | ... | @@ -154,7 +154,7 @@ def load_yaml(filename: str, default: Any = None) -> Any: |
154 | 154 | except yaml.YAMLError as e: |
155 | 155 | if hasattr(e, 'problem_mark'): |
156 | 156 | mark = e.problem_mark |
157 | - logger.error(f'File "{filename}" near line {mark.line}, ' | |
157 | + logger.error(f'File "{filename}" near line {mark.line+1}, ' | |
158 | 158 | f'column {mark.column+1}') |
159 | 159 | else: |
160 | 160 | logger.error(f'File "{filename}"') | ... | ... |