Commit 65a5ad4aceead32255bb3bbd04a3f0d715c63519

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

Small fixes

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>&nbsp;
  108 + <h5><i class="bi bi-flag-fill"></i></h5>
109 109 {% elif t['type']=='learn' %}
110   - <i class="bi bi-book"></i>&nbsp;
  110 + <h5><i class="bi bi-book"></i></h5>
111 111 {% else %}
112   - <i class="bi bi-pencil"></i>&nbsp;
  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>&nbsp;
  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>&nbsp;
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>&nbsp;
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>&nbsp;
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>
... ...