Commit cc63d37e7b4dad1a1a6ca42d8eaba062f2ed744c

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

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.
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  
... ...