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