Commit 65a5ad4aceead32255bb3bbd04a3f0d715c63519
1 parent
0392a334
Exists in
master
and in
1 other branch
Small fixes
Showing
2 changed files
with
31 additions
and
71 deletions
Show diff stats
aprendizations/learnapp.py
... | ... | @@ -6,7 +6,6 @@ This is the main controller of the application. |
6 | 6 | # python standard library |
7 | 7 | import asyncio |
8 | 8 | from collections import defaultdict |
9 | -# from contextlib import contextmanager # `with` statement in db sessions | |
10 | 9 | from datetime import datetime |
11 | 10 | import logging |
12 | 11 | from random import random |
... | ... | @@ -45,18 +44,25 @@ class LearnApp(): |
45 | 44 | ''' |
46 | 45 | LearnApp - application logic |
47 | 46 | |
48 | - self.deps - networkx topic dependencies | |
49 | - self.courses - dict {course_id: {'title': ..., | |
50 | - 'description': ..., | |
51 | - 'goals': ...,}, ...} | |
52 | - self.factory = dict {qref: QFactory()} | |
53 | - self.online - dict {student_id: {'number': ..., | |
54 | - 'name': ..., | |
55 | - 'state': StudentState(), | |
56 | - 'counter': ...}, ...} | |
47 | + self.deps = networkx topic dependencies | |
48 | + self.courses = { | |
49 | + course_id: { | |
50 | + 'title': ..., | |
51 | + 'description': ..., | |
52 | + 'goals': ..., | |
53 | + }, ... | |
54 | + } | |
55 | + self.factory = { qref: QFactory() } | |
56 | + self.online = { | |
57 | + student_id: { | |
58 | + 'number': ..., | |
59 | + 'name': ..., | |
60 | + 'state': StudentState(), | |
61 | + 'counter': ... | |
62 | + }, ... | |
63 | + } | |
57 | 64 | ''' |
58 | 65 | |
59 | - # ------------------------------------------------------------------------ | |
60 | 66 | def __init__(self, |
61 | 67 | courses: str, # filename with course configurations |
62 | 68 | prefix: str, # path to topics |
... | ... | @@ -114,7 +120,6 @@ class LearnApp(): |
114 | 120 | if check: |
115 | 121 | self._sanity_check_questions() |
116 | 122 | |
117 | - # ------------------------------------------------------------------------ | |
118 | 123 | def _sanity_check_questions(self) -> None: |
119 | 124 | ''' |
120 | 125 | Unit tests for all questions |
... | ... | @@ -159,7 +164,6 @@ class LearnApp(): |
159 | 164 | raise LearnException('Sanity checks') |
160 | 165 | logger.info(' 0 errors found.') |
161 | 166 | |
162 | - # ------------------------------------------------------------------------ | |
163 | 167 | async def login(self, uid: str, password: str) -> bool: |
164 | 168 | '''user login''' |
165 | 169 | |
... | ... | @@ -212,13 +216,11 @@ class LearnApp(): |
212 | 216 | |
213 | 217 | return pw_ok |
214 | 218 | |
215 | - # ------------------------------------------------------------------------ | |
216 | 219 | def logout(self, uid: str) -> None: |
217 | 220 | '''User logout''' |
218 | 221 | del self.online[uid] |
219 | 222 | logger.info('User "%s" logged out', uid) |
220 | 223 | |
221 | - # ------------------------------------------------------------------------ | |
222 | 224 | async def change_password(self, uid: str, password: str) -> bool: |
223 | 225 | ''' |
224 | 226 | Change user Password. |
... | ... | @@ -242,7 +244,6 @@ class LearnApp(): |
242 | 244 | logger.info('User "%s" changed password', uid) |
243 | 245 | return True |
244 | 246 | |
245 | - # ------------------------------------------------------------------------ | |
246 | 247 | async def check_answer(self, uid: str, answer) -> Question: |
247 | 248 | ''' |
248 | 249 | Checks answer and update database. |
... | ... | @@ -271,7 +272,6 @@ class LearnApp(): |
271 | 272 | |
272 | 273 | return question |
273 | 274 | |
274 | - # ------------------------------------------------------------------------ | |
275 | 275 | async def get_question(self, uid: str) -> Optional[Question]: |
276 | 276 | ''' |
277 | 277 | Get the question to show (current or new one) |
... | ... | @@ -318,7 +318,6 @@ class LearnApp(): |
318 | 318 | |
319 | 319 | return question |
320 | 320 | |
321 | - # ------------------------------------------------------------------------ | |
322 | 321 | def start_course(self, uid: str, course_id: str) -> None: |
323 | 322 | '''Start course''' |
324 | 323 | |
... | ... | @@ -331,9 +330,6 @@ class LearnApp(): |
331 | 330 | else: |
332 | 331 | logger.info('User "%s" course "%s"', uid, course_id) |
333 | 332 | |
334 | - # ------------------------------------------------------------------------ | |
335 | - # | |
336 | - # ------------------------------------------------------------------------ | |
337 | 333 | async def start_topic(self, uid: str, topic: str) -> None: |
338 | 334 | '''Start new topic''' |
339 | 335 | |
... | ... | @@ -350,9 +346,6 @@ class LearnApp(): |
350 | 346 | else: |
351 | 347 | logger.info('User "%s" started topic "%s"', uid, topic) |
352 | 348 | |
353 | - # ------------------------------------------------------------------------ | |
354 | - # | |
355 | - # ------------------------------------------------------------------------ | |
356 | 349 | def _add_missing_topics(self, topics: Iterable[str]) -> None: |
357 | 350 | ''' |
358 | 351 | Fill db table 'Topic' with topics from the graph, if new |
... | ... | @@ -365,7 +358,6 @@ class LearnApp(): |
365 | 358 | session.commit() |
366 | 359 | logger.info('Added %d new topic(s) to the database', len(new)) |
367 | 360 | |
368 | - # ------------------------------------------------------------------------ | |
369 | 361 | def _db_setup(self, database: str) -> None: |
370 | 362 | ''' |
371 | 363 | Setup and check database contents |
... | ... | @@ -395,7 +387,6 @@ class LearnApp(): |
395 | 387 | logger.info('%6d topics', count_topics) |
396 | 388 | logger.info('%6d answers', count_answers) |
397 | 389 | |
398 | - # ------------------------------------------------------------------------ | |
399 | 390 | def _populate_graph(self, config: Dict[str, Any]) -> None: |
400 | 391 | ''' |
401 | 392 | Populates a digraph. |
... | ... | @@ -437,12 +428,10 @@ class LearnApp(): |
437 | 428 | # prefix/topic |
438 | 429 | topic['path'] = join(self.deps.graph['prefix'], tref) |
439 | 430 | |
440 | - | |
441 | - # ======================================================================== | |
431 | + # ------------------------------------------------------------------------ | |
442 | 432 | # methods that do not change state (pure functions) |
443 | - # ======================================================================== | |
444 | - | |
445 | 433 | # ------------------------------------------------------------------------ |
434 | + | |
446 | 435 | def _make_factory(self) -> Dict[str, QFactory]: |
447 | 436 | ''' |
448 | 437 | Buils dictionary of question factories |
... | ... | @@ -519,38 +508,31 @@ class LearnApp(): |
519 | 508 | |
520 | 509 | return factory |
521 | 510 | |
522 | - # ------------------------------------------------------------------------ | |
523 | 511 | def get_login_counter(self, uid: str) -> int: |
524 | 512 | '''login counter''' # FIXME |
525 | 513 | return int(self.online[uid]['counter']) |
526 | 514 | |
527 | - # ------------------------------------------------------------------------ | |
528 | 515 | def get_student_name(self, uid: str) -> str: |
529 | 516 | '''Get the username''' |
530 | 517 | return self.online[uid].get('name', '') |
531 | 518 | |
532 | - # ------------------------------------------------------------------------ | |
533 | 519 | def get_student_state(self, uid: str) -> List[Dict[str, Any]]: |
534 | 520 | '''Get the knowledge state of a given user''' |
535 | 521 | return self.online[uid]['state'].get_knowledge_state() |
536 | 522 | |
537 | - # ------------------------------------------------------------------------ | |
538 | 523 | def get_student_progress(self, uid: str) -> float: |
539 | 524 | '''Get the current topic progress of a given user''' |
540 | 525 | return float(self.online[uid]['state'].get_topic_progress()) |
541 | 526 | |
542 | - # ------------------------------------------------------------------------ | |
543 | 527 | def get_current_question(self, uid: str) -> Optional[Question]: |
544 | 528 | '''Get the current question of a given user''' |
545 | 529 | question: Optional[Question] = self.online[uid]['state'].get_current_question() |
546 | 530 | return question |
547 | 531 | |
548 | - # ------------------------------------------------------------------------ | |
549 | 532 | def get_current_question_id(self, uid: str) -> str: |
550 | 533 | '''Get id of the current question for a given user''' |
551 | 534 | return str(self.online[uid]['state'].get_current_question()['qid']) |
552 | 535 | |
553 | - # ------------------------------------------------------------------------ | |
554 | 536 | def get_student_question_type(self, uid: str) -> str: |
555 | 537 | '''Get type of the current question for a given user''' |
556 | 538 | return str(self.online[uid]['state'].get_current_question()['type']) |
... | ... | @@ -559,12 +541,10 @@ class LearnApp(): |
559 | 541 | # def get_student_topic(self, uid: str) -> str: |
560 | 542 | # return str(self.online[uid]['state'].get_current_topic()) |
561 | 543 | |
562 | - # ------------------------------------------------------------------------ | |
563 | 544 | def get_student_course_title(self, uid: str) -> str: |
564 | 545 | '''get the title of the current course for a given user''' |
565 | 546 | return str(self.online[uid]['state'].get_current_course_title()) |
566 | 547 | |
567 | - # ------------------------------------------------------------------------ | |
568 | 548 | def get_current_course_id(self, uid: str) -> Optional[str]: |
569 | 549 | '''get the current course (id) of a given user''' |
570 | 550 | cid: Optional[str] = self.online[uid]['state'].get_current_course_id() |
... | ... | @@ -574,7 +554,6 @@ class LearnApp(): |
574 | 554 | # def get_topic_name(self, ref: str) -> str: |
575 | 555 | # return str(self.deps.nodes[ref]['name']) |
576 | 556 | |
577 | - # ------------------------------------------------------------------------ | |
578 | 557 | def get_current_public_dir(self, uid: str) -> str: |
579 | 558 | ''' |
580 | 559 | Get the path for the 'public' directory of the current topic of the |
... | ... | @@ -586,21 +565,18 @@ class LearnApp(): |
586 | 565 | prefix: str = self.deps.graph['prefix'] |
587 | 566 | return join(prefix, topic, 'public') |
588 | 567 | |
589 | - # ------------------------------------------------------------------------ | |
590 | 568 | def get_courses(self) -> Dict[str, Dict[str, Any]]: |
591 | 569 | ''' |
592 | 570 | Get dictionary with all courses {'course1': {...}, 'course2': {...}} |
593 | 571 | ''' |
594 | 572 | return self.courses |
595 | 573 | |
596 | - # ------------------------------------------------------------------------ | |
597 | 574 | def get_course(self, course_id: str) -> Dict[str, Any]: |
598 | 575 | ''' |
599 | 576 | Get dictionary {'title': ..., 'description':..., 'goals':...} |
600 | 577 | ''' |
601 | 578 | return self.courses[course_id] |
602 | 579 | |
603 | - # ------------------------------------------------------------------------ | |
604 | 580 | def get_rankings(self, uid: str, cid: str) -> List[Tuple[str, str, float]]: |
605 | 581 | ''' |
606 | 582 | Returns rankings for a certain cid (course_id). |
... | ... | @@ -639,5 +615,3 @@ class LearnApp(): |
639 | 615 | for u, name in students |
640 | 616 | if u in progress and (len(u) > 2 or len(uid) <= 2)), |
641 | 617 | key=lambda x: x[2], reverse=True) |
642 | - | |
643 | - # ------------------------------------------------------------------------ | ... | ... |
aprendizations/templates/maintopics-table.html
... | ... | @@ -105,23 +105,23 @@ |
105 | 105 | <tr> |
106 | 106 | <th scope="row" class="text-muted text-center"> |
107 | 107 | {% if t['type']=='chapter' %} |
108 | - <i class="bi bi-flag-fill"></i> | |
108 | + <h5><i class="bi bi-flag-fill"></i></h5> | |
109 | 109 | {% elif t['type']=='learn' %} |
110 | - <i class="bi bi-book"></i> | |
110 | + <h5><i class="bi bi-book"></i></h5> | |
111 | 111 | {% else %} |
112 | - <i class="bi bi-pencil"></i> | |
112 | + <h5><i class="bi bi-pencil"></i></h5> | |
113 | 113 | {% end %} |
114 | 114 | </th> |
115 | 115 | <td> |
116 | 116 | <div class="text-muted"> |
117 | 117 | {% if t['ref'] not in course['goals'] %} |
118 | - <i class="bi bi-puzzle-fill"></i> | |
118 | + <h5><i class="bi bi-puzzle-fill"></i></h5> | |
119 | 119 | {% end %} |
120 | 120 | {{ t['name'] }} |
121 | 121 | </div> |
122 | 122 | </td> |
123 | 123 | <td class="text-center"> |
124 | - <i class="bi bi-lock-fill text-muted"></i> | |
124 | + <h5><i class="bi bi-lock-fill text-muted"></i></h5> | |
125 | 125 | </td> |
126 | 126 | </tr> |
127 | 127 | |
... | ... | @@ -131,30 +131,22 @@ |
131 | 131 | <th scope="row" class="text-primary text-center"> |
132 | 132 | {% if t['type']=='chapter' %} |
133 | 133 | <span class="text-nowrap" data-toggle="tooltip" data-placement="bottom" title="Fim do capítulo"> |
134 | - <h5> | |
135 | - <i class="bi bi-flag-fill"></i> | |
136 | - </h5> | |
134 | + <h5><i class="bi bi-flag-fill"></i></h5> | |
137 | 135 | </span> |
138 | 136 | {% elif t['type']=='learn' %} |
139 | 137 | <span class="text-nowrap" data-toggle="tooltip" data-placement="bottom" title="Texto com matéria"> |
140 | - <h5> | |
141 | - <i class="bi bi-book"></i> | |
142 | - </h5> | |
138 | + <h5><i class="bi bi-book"></i></h5> | |
143 | 139 | </span> |
144 | 140 | {% else %} |
145 | 141 | <span class="text-nowrap" data-toggle="tooltip" data-placement="bottom" title="Exercícios"> |
146 | - <h5> | |
147 | - <i class="bi bi-pencil"></i> | |
148 | - </h5> | |
142 | + <h5><i class="bi bi-pencil"></i></h5> | |
149 | 143 | </span> |
150 | 144 | {% end %} |
151 | 145 | </th> |
152 | 146 | <td class="text-primary"> |
153 | 147 | {% if t['ref'] not in course['goals'] %} |
154 | 148 | <span class="text-nowrap" data-toggle="tooltip" data-placement="bottom" title="Pré-requisito para este curso"> |
155 | - <h5> | |
156 | - <i class="bi bi-puzzle-fill"></i> | |
157 | - </h5> | |
149 | + <h5><i class="bi bi-puzzle-fill"></i></h5> | |
158 | 150 | </span> |
159 | 151 | {% end %} |
160 | 152 | {{ t['name'] }} |
... | ... | @@ -162,18 +154,12 @@ |
162 | 154 | |
163 | 155 | <td class="text-center"> |
164 | 156 | {% if t['level'] < 0.01 %} |
165 | - <h5> | |
166 | - <i class="bi bi-unlock-fill text-success"></i> | |
167 | - </h5> | |
157 | + <h5><i class="bi bi-unlock-fill text-success"></i></h5> | |
168 | 158 | {% elif t['type']=='chapter' %} |
169 | - <h5> | |
170 | - <i class="bi bi-award-fill"></i> | |
171 | - </h5> | |
159 | + <h5><i class="bi bi-award-fill"></i></h5> | |
172 | 160 | {% else %} |
173 | 161 | <span class="text-nowrap text-warning" data-toggle="tooltip" data-placement="bottom" title="{{round(t['level']*5, 3)}}"> |
174 | - <h5> | |
175 | - {{ int(t['level']*5+0.25)*'<i class="bi bi-star-fill"></i>' }}{% if int(t['level']*5+0.25) < 5 %}{{'<i class="bi bi-star-half"></i>' if 0.25 <= t['level']*5-int(t['level']*5) < 0.75 else '<i class="bi bi-star"></i>'}}{% end %}{{ (4-int(t['level']*5+0.25))*'<i class="bi bi-star"></i>' }} | |
176 | - </h5> | |
162 | + <h5>{{ int(t['level']*5+0.25)*'<i class="bi bi-star-fill"></i>' }}{% if int(t['level']*5+0.25) < 5 %}{{'<i class="bi bi-star-half"></i>' if 0.25 <= t['level']*5-int(t['level']*5) < 0.75 else '<i class="bi bi-star"></i>'}}{% end %}{{ (4-int(t['level']*5+0.25))*'<i class="bi bi-star"></i>' }}</h5> | |
177 | 163 | </span> |
178 | 164 | {% end %} <!-- if --> |
179 | 165 | </td> | ... | ... |