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,6 +36,16 @@ class DatabaseUnusableError(LearnException): | ||
| 36 | 36 | ||
| 37 | # ============================================================================ | 37 | # ============================================================================ |
| 38 | # LearnApp - application logic | 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 | class LearnApp(object): | 50 | class LearnApp(object): |
| 41 | # ------------------------------------------------------------------------ | 51 | # ------------------------------------------------------------------------ |
| @@ -95,8 +105,9 @@ class LearnApp(object): | @@ -95,8 +105,9 @@ class LearnApp(object): | ||
| 95 | d.setdefault('title', '') # course title undefined | 105 | d.setdefault('title', '') # course title undefined |
| 96 | for goal in d['goals']: | 106 | for goal in d['goals']: |
| 97 | if goal not in self.deps.nodes(): | 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 | # --- factory is a dict with question generators for all topics | 112 | # --- factory is a dict with question generators for all topics |
| 102 | self.factory: Dict[str, QFactory] = self.make_factory() | 113 | self.factory: Dict[str, QFactory] = self.make_factory() |
| @@ -291,15 +302,15 @@ class LearnApp(object): | @@ -291,15 +302,15 @@ class LearnApp(object): | ||
| 291 | # ------------------------------------------------------------------------ | 302 | # ------------------------------------------------------------------------ |
| 292 | # Start course | 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 | student = self.online[uid]['state'] | 306 | student = self.online[uid]['state'] |
| 296 | try: | 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 | raise | 311 | raise |
| 301 | else: | 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 | # Start new topic | 316 | # Start new topic |
| @@ -516,6 +527,11 @@ class LearnApp(object): | @@ -516,6 +527,11 @@ class LearnApp(object): | ||
| 516 | return self.online[uid]['state'].get_current_course_id() | 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 | def get_topic_name(self, ref: str) -> str: | 535 | def get_topic_name(self, ref: str) -> str: |
| 520 | return self.deps.nodes[ref]['name'] | 536 | return self.deps.nodes[ref]['name'] |
| 521 | 537 | ||
| @@ -529,6 +545,9 @@ class LearnApp(object): | @@ -529,6 +545,9 @@ class LearnApp(object): | ||
| 529 | def get_courses(self, uid: str) -> Dict: | 545 | def get_courses(self, uid: str) -> Dict: |
| 530 | return self.courses | 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 | def get_rankings(self, uid: str, course_id: str) -> Iterable[Tuple[str, str, float, float]]: | 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,13 +205,11 @@ class CoursesHandler(BaseHandler): | ||
| 205 | # ---------------------------------------------------------------------------- | 205 | # ---------------------------------------------------------------------------- |
| 206 | class CourseHandler(BaseHandler): | 206 | class CourseHandler(BaseHandler): |
| 207 | @tornado.web.authenticated | 207 | @tornado.web.authenticated |
| 208 | - def get(self, course): | 208 | + def get(self, course_id): |
| 209 | uid = self.current_user | 209 | uid = self.current_user |
| 210 | - if course == '': | ||
| 211 | - course = self.learn.get_student_course_id(uid) | ||
| 212 | 210 | ||
| 213 | try: | 211 | try: |
| 214 | - self.learn.start_course(uid, course) | 212 | + self.learn.start_course(uid, course_id) |
| 215 | except KeyError: | 213 | except KeyError: |
| 216 | self.redirect('/courses') | 214 | self.redirect('/courses') |
| 217 | 215 | ||
| @@ -220,8 +218,8 @@ class CourseHandler(BaseHandler): | @@ -220,8 +218,8 @@ class CourseHandler(BaseHandler): | ||
| 220 | uid=uid, | 218 | uid=uid, |
| 221 | name=self.learn.get_student_name(uid), | 219 | name=self.learn.get_student_name(uid), |
| 222 | state=self.learn.get_student_state(uid), | 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,9 +236,17 @@ class StudentState(object): | ||
| 236 | G = self.deps | 236 | G = self.deps |
| 237 | ts = set(goals) | 237 | ts = set(goals) |
| 238 | for t in goals: | 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 | # sort with unlocked first | 251 | # sort with unlocked first |
| 244 | unlocked = [t for t in tl if t in self.state] | 252 | unlocked = [t for t in tl if t in self.state] |
aprendizations/templates/maintopics-table.html
| @@ -60,7 +60,7 @@ | @@ -60,7 +60,7 @@ | ||
| 60 | 60 | ||
| 61 | <div id="notifications"></div> | 61 | <div id="notifications"></div> |
| 62 | 62 | ||
| 63 | - <h4>{{ course_title }}</h4> | 63 | + <h4>{{ course['title'] }}</h4> |
| 64 | 64 | ||
| 65 | <table class="table table-hover"> | 65 | <table class="table table-hover"> |
| 66 | <thead class=""> | 66 | <thead class=""> |