Commit f1e8c08273b422a8d93bd62deac64030dcd81cad
1 parent
f37c5e30
Exists in
master
and in
1 other branch
don't show topic dependencies that are not goals if already done
Showing
4 changed files
with
42 additions
and
17 deletions
Show diff stats
aprendizations/learnapp.py
... | ... | @@ -36,6 +36,16 @@ class DatabaseUnusableError(LearnException): |
36 | 36 | |
37 | 37 | # ============================================================================ |
38 | 38 | # LearnApp - application logic |
39 | +# | |
40 | +# self.deps - networkx topic dependencies | |
41 | +# self.courses - dict {course_id: {'title': ..., | |
42 | +# 'description': ..., | |
43 | +# 'goals': ...,}, ...} | |
44 | +# self.factory = dict {qref: QFactory()} | |
45 | +# self.online - dict {student_id: {'number': ..., | |
46 | +# 'name': ..., | |
47 | +# 'state': StudentState(), | |
48 | +# 'counter': ...}, ...} | |
39 | 49 | # ============================================================================ |
40 | 50 | class LearnApp(object): |
41 | 51 | # ------------------------------------------------------------------------ |
... | ... | @@ -95,8 +105,9 @@ class LearnApp(object): |
95 | 105 | d.setdefault('title', '') # course title undefined |
96 | 106 | for goal in d['goals']: |
97 | 107 | if goal not in self.deps.nodes(): |
98 | - raise LearnException(f'Goal "{goal}" from course "{c}" ' | |
99 | - ' does not exist') | |
108 | + msg = f'Goal "{goal}" from course "{c}" does not exist' | |
109 | + logger.error(msg) | |
110 | + raise LearnException(msg) | |
100 | 111 | |
101 | 112 | # --- factory is a dict with question generators for all topics |
102 | 113 | self.factory: Dict[str, QFactory] = self.make_factory() |
... | ... | @@ -291,15 +302,15 @@ class LearnApp(object): |
291 | 302 | # ------------------------------------------------------------------------ |
292 | 303 | # Start course |
293 | 304 | # ------------------------------------------------------------------------ |
294 | - def start_course(self, uid: str, course: str) -> None: | |
305 | + def start_course(self, uid: str, course_id: str) -> None: | |
295 | 306 | student = self.online[uid]['state'] |
296 | 307 | try: |
297 | - student.start_course(course) | |
298 | - except Exception as e: | |
299 | - logger.warning(f'"{uid}" could not start course "{course}": {e}') | |
308 | + student.start_course(course_id) | |
309 | + except Exception: | |
310 | + logger.warning(f'"{uid}" could not start course "{course_id}"') | |
300 | 311 | raise |
301 | 312 | else: |
302 | - logger.info(f'User "{uid}" started course "{course}"') | |
313 | + logger.info(f'User "{uid}" started course "{course_id}"') | |
303 | 314 | |
304 | 315 | # ------------------------------------------------------------------------ |
305 | 316 | # Start new topic |
... | ... | @@ -516,6 +527,11 @@ class LearnApp(object): |
516 | 527 | return self.online[uid]['state'].get_current_course_id() |
517 | 528 | |
518 | 529 | # ------------------------------------------------------------------------ |
530 | + # def get_student_course(self, uid: str) -> Optional[str]: | |
531 | + # course_id = self.online[uid]['state'].get_current_course_id() | |
532 | + # return course_id, self.courses[course_id] | |
533 | + | |
534 | + # ------------------------------------------------------------------------ | |
519 | 535 | def get_topic_name(self, ref: str) -> str: |
520 | 536 | return self.deps.nodes[ref]['name'] |
521 | 537 | |
... | ... | @@ -529,6 +545,9 @@ class LearnApp(object): |
529 | 545 | def get_courses(self, uid: str) -> Dict: |
530 | 546 | return self.courses |
531 | 547 | |
548 | + def get_course(self, course_id: str) -> Dict: | |
549 | + return self.courses[course_id] | |
550 | + | |
532 | 551 | # ------------------------------------------------------------------------ |
533 | 552 | def get_rankings(self, uid: str, course_id: str) -> Iterable[Tuple[str, str, float, float]]: |
534 | 553 | ... | ... |
aprendizations/serve.py
... | ... | @@ -205,13 +205,11 @@ class CoursesHandler(BaseHandler): |
205 | 205 | # ---------------------------------------------------------------------------- |
206 | 206 | class CourseHandler(BaseHandler): |
207 | 207 | @tornado.web.authenticated |
208 | - def get(self, course): | |
208 | + def get(self, course_id): | |
209 | 209 | uid = self.current_user |
210 | - if course == '': | |
211 | - course = self.learn.get_student_course_id(uid) | |
212 | 210 | |
213 | 211 | try: |
214 | - self.learn.start_course(uid, course) | |
212 | + self.learn.start_course(uid, course_id) | |
215 | 213 | except KeyError: |
216 | 214 | self.redirect('/courses') |
217 | 215 | |
... | ... | @@ -220,8 +218,8 @@ class CourseHandler(BaseHandler): |
220 | 218 | uid=uid, |
221 | 219 | name=self.learn.get_student_name(uid), |
222 | 220 | state=self.learn.get_student_state(uid), |
223 | - course_title=self.learn.get_student_course_title(uid), | |
224 | - course_id=self.learn.get_student_course_id(uid), | |
221 | + course_id=course_id, | |
222 | + course=self.learn.get_course(course_id) | |
225 | 223 | ) |
226 | 224 | |
227 | 225 | ... | ... |
aprendizations/student.py
... | ... | @@ -236,9 +236,17 @@ class StudentState(object): |
236 | 236 | G = self.deps |
237 | 237 | ts = set(goals) |
238 | 238 | for t in goals: |
239 | - ts.update(nx.ancestors(G, t)) | |
240 | - # FIXME filter by level done, only level < 50% are included | |
241 | - tl = list(nx.topological_sort(G.subgraph(ts))) | |
239 | + ts.update(nx.ancestors(G, t)) # include dependencies not in goals | |
240 | + | |
241 | + todo = [] | |
242 | + for t in ts: | |
243 | + level = self.state[t]['level'] if t in self.state else 0.0 | |
244 | + min_level = G.nodes[t]['min_level'] | |
245 | + if t in goals or level < min_level: | |
246 | + todo.append(t) | |
247 | + | |
248 | + # FIXME topological sort is a poor way to sort topics | |
249 | + tl = list(nx.topological_sort(G.subgraph(todo))) | |
242 | 250 | |
243 | 251 | # sort with unlocked first |
244 | 252 | unlocked = [t for t in tl if t in self.state] | ... | ... |
aprendizations/templates/maintopics-table.html