Commit 0f88b4f185d910e4efc368988e8a28f2c5aa9a50
1 parent
2c577830
Exists in
master
and in
1 other branch
fix error where topics declared in chapters but not in goals were not shown.
fix error where finishing a course would try to start empty course. goals that are chapters will recursively import dependencies.
Showing
4 changed files
with
21 additions
and
10 deletions
Show diff stats
BUGS.md
1 | 1 | |
2 | 2 | # BUGS |
3 | 3 | |
4 | -- goals se forem do tipo chapter deve importar todas as dependencias do chapter (e não mostrar chapters?). | |
5 | 4 | - nao esta a seguir o max_tries definido no ficheiro de dependencias. |
6 | 5 | - devia mostrar timeout para o aluno saber a razao. |
7 | 6 | - permitir configuracao para escolher entre static files locais ou remotos |
8 | -- templates question-*.html tem input hidden question_ref que não é usado. remover? | |
9 | 7 | - shift-enter não está a funcionar |
10 | 8 | - default prefix should be obtained from each course (yaml conf)? |
11 | 9 | |
... | ... | @@ -32,6 +30,8 @@ |
32 | 30 | |
33 | 31 | # FIXED |
34 | 32 | |
33 | +- templates question-*.html tem input hidden question_ref que não é usado. remover? | |
34 | +- goals se forem do tipo chapter deve importar todas as dependencias do chapter. | |
35 | 35 | - initdb da integrity error se no mesmo comando existirem alunos repetidos (p.ex em ficheiros csv diferentes ou entre csv e opcao -a) |
36 | 36 | - dependencias que não são goals de um curso, só devem aparecer se ainda não tiverem sido feitas. |
37 | 37 | - ir para inicio da pagina quando le nova pergunta. | ... | ... |
aprendizations/learnapp.py
... | ... | @@ -108,6 +108,9 @@ class LearnApp(object): |
108 | 108 | msg = f'Goal "{goal}" from course "{c}" does not exist' |
109 | 109 | logger.error(msg) |
110 | 110 | raise LearnException(msg) |
111 | + elif self.deps.nodes[goal]['type'] == 'chapter': | |
112 | + d['goals'] += [g for g in self.deps.predecessors(goal) | |
113 | + if g not in d['goals']] | |
111 | 114 | |
112 | 115 | # --- factory is a dict with question generators for all topics |
113 | 116 | self.factory: Dict[str, QFactory] = self.make_factory() |
... | ... | @@ -318,7 +321,7 @@ class LearnApp(object): |
318 | 321 | async def start_topic(self, uid: str, topic: str) -> None: |
319 | 322 | student = self.online[uid]['state'] |
320 | 323 | if uid == '0': |
321 | - logger.warning(f'Reloading "{topic}"') | |
324 | + logger.warning(f'Reloading "{topic}"') # FIXME should be an option | |
322 | 325 | self.factory.update(self.factory_for(topic)) |
323 | 326 | |
324 | 327 | try: |
... | ... | @@ -406,6 +409,7 @@ class LearnApp(object): |
406 | 409 | |
407 | 410 | t['path'] = path.join(g.graph['prefix'], tref) # prefix/topic |
408 | 411 | |
412 | + | |
409 | 413 | # ======================================================================== |
410 | 414 | # methods that do not change state (pure functions) |
411 | 415 | # ======================================================================== | ... | ... |
aprendizations/serve.py
... | ... | @@ -201,12 +201,14 @@ class CoursesHandler(BaseHandler): |
201 | 201 | |
202 | 202 | # ---------------------------------------------------------------------------- |
203 | 203 | # /course/... |
204 | -# Start a given course | |
204 | +# Start a given course and show list of topics | |
205 | 205 | # ---------------------------------------------------------------------------- |
206 | 206 | class CourseHandler(BaseHandler): |
207 | 207 | @tornado.web.authenticated |
208 | 208 | def get(self, course_id): |
209 | 209 | uid = self.current_user |
210 | + if course_id == '': | |
211 | + course_id = self.learn.get_current_course_id(uid) | |
210 | 212 | |
211 | 213 | try: |
212 | 214 | self.learn.start_course(uid, course_id) | ... | ... |
aprendizations/student.py
... | ... | @@ -59,12 +59,15 @@ class StudentState(object): |
59 | 59 | self.current_course: Optional[str] = None |
60 | 60 | self.topic_sequence: List[str] = [] |
61 | 61 | self.current_topic: Optional[str] = None |
62 | - # self.previous_topic: Optional[str] = None | |
63 | 62 | else: |
64 | - logger.debug(f'starting course {course}') | |
63 | + try: | |
64 | + topics = self.courses[course]['goals'] | |
65 | + except KeyError: | |
66 | + logger.debug(f'course "{course}" does not exist') | |
67 | + raise | |
68 | + logger.debug(f'starting course "{course}"') | |
65 | 69 | self.current_course = course |
66 | - topics = self.courses[course]['goals'] | |
67 | - self.topic_sequence = self.recommend_topic_sequence(topics) | |
70 | + self.topic_sequence = self.recommend_sequence(topics) | |
68 | 71 | |
69 | 72 | # ------------------------------------------------------------------------ |
70 | 73 | # Start a new topic. |
... | ... | @@ -178,7 +181,7 @@ class StudentState(object): |
178 | 181 | # The current topic is unchanged. |
179 | 182 | # ------------------------------------------------------------------------ |
180 | 183 | def finish_topic(self) -> None: |
181 | - logger.debug(f'finished "{self.current_topic}"') | |
184 | + logger.debug(f'finished {self.current_topic} in {self.current_course}') | |
182 | 185 | |
183 | 186 | self.state[self.current_topic] = { |
184 | 187 | 'date': datetime.now(), |
... | ... | @@ -232,7 +235,7 @@ class StudentState(object): |
232 | 235 | # ------------------------------------------------------------------------ |
233 | 236 | # compute recommended sequence of topics ['a', 'b', ...] |
234 | 237 | # ------------------------------------------------------------------------ |
235 | - def recommend_topic_sequence(self, goals: List[str] = []) -> List[str]: | |
238 | + def recommend_sequence(self, goals: List[str] = []) -> List[str]: | |
236 | 239 | G = self.deps |
237 | 240 | ts = set(goals) |
238 | 241 | for t in goals: |
... | ... | @@ -245,6 +248,8 @@ class StudentState(object): |
245 | 248 | if t in goals or level < min_level: |
246 | 249 | todo.append(t) |
247 | 250 | |
251 | + logger.debug(f' {len(ts)} total topics, {len(todo)} listed ') | |
252 | + | |
248 | 253 | # FIXME topological sort is a poor way to sort topics |
249 | 254 | tl = list(nx.topological_sort(G.subgraph(todo))) |
250 | 255 | ... | ... |