Commit 861d9ae5ba6dfc9fe2b16f0265701d06e00c65a5
1 parent
e3d61b82
Exists in
master
and in
1 other branch
Much faster rankings
Showing
4 changed files
with
35 additions
and
25 deletions
Show diff stats
aprendizations/knowledge.py
| ... | ... | @@ -70,7 +70,6 @@ class StudentKnowledge(object): |
| 70 | 70 | # questions: list of generated questions to do in the topic |
| 71 | 71 | # current_question: the current question to be presented |
| 72 | 72 | # ------------------------------------------------------------------------ |
| 73 | - # FIXME async mas nao tem awaits... do not allow restart same topic | |
| 74 | 73 | async def start_topic(self, topic): |
| 75 | 74 | logger.debug('StudentKnowledge.start_topic()') |
| 76 | 75 | if self.current_topic == topic: | ... | ... |
aprendizations/learnapp.py
| ... | ... | @@ -8,7 +8,7 @@ from datetime import datetime |
| 8 | 8 | |
| 9 | 9 | # user installed libraries |
| 10 | 10 | import bcrypt |
| 11 | -from sqlalchemy import create_engine | |
| 11 | +from sqlalchemy import create_engine, func | |
| 12 | 12 | from sqlalchemy.orm import sessionmaker |
| 13 | 13 | import networkx as nx |
| 14 | 14 | |
| ... | ... | @@ -381,32 +381,36 @@ class LearnApp(object): |
| 381 | 381 | |
| 382 | 382 | # ------------------------------------------------------------------------ |
| 383 | 383 | def get_rankings(self, uid): |
| 384 | - logger.info(f'User {uid} get rankings') | |
| 384 | + logger.info(f'User "{uid}" get rankings') | |
| 385 | 385 | with self.db_session() as s: |
| 386 | 386 | students = s.query(Student.id, Student.name).all() |
| 387 | + # topic progress | |
| 387 | 388 | student_topics = s.query(StudentTopic.student_id, |
| 388 | 389 | StudentTopic.topic_id, |
| 389 | 390 | StudentTopic.level, |
| 390 | 391 | StudentTopic.date).all() |
| 391 | 392 | total_topics = s.query(Topic).count() |
| 392 | 393 | |
| 393 | - rankings = {s[0]: 0.0 for s in students} | |
| 394 | + # answer performance | |
| 395 | + totalans = dict(s.query(Answer.student_id, func.count(Answer.ref)). | |
| 396 | + group_by(Answer.student_id). | |
| 397 | + all()) | |
| 398 | + rightans = dict(s.query(Answer.student_id, func.count(Answer.ref)). | |
| 399 | + filter(Answer.grade == 1.0). | |
| 400 | + group_by(Answer.student_id). | |
| 401 | + all()) | |
| 402 | + | |
| 403 | + # compute percentage of right answers | |
| 404 | + perf = {uid: rightans.get(uid, 0.0)/totalans[uid] for uid in totalans} | |
| 405 | + | |
| 406 | + # compute topic progress | |
| 407 | + prog = {s[0]: 0.0 for s in students} | |
| 394 | 408 | now = datetime.now() |
| 395 | 409 | for uid, topic, level, date in student_topics: |
| 396 | 410 | date = datetime.strptime(date, "%Y-%m-%d %H:%M:%S.%f") |
| 397 | - rankings[uid] += level**(now - date).days / total_topics | |
| 411 | + prog[uid] += level**(now - date).days / total_topics | |
| 398 | 412 | |
| 399 | - rankings = [(uid, name, rankings[uid]) | |
| 413 | + rankings = [(uid, name, prog[uid], perf.get(uid, 0.0)) | |
| 400 | 414 | for uid, name in students if uid != '0'] |
| 401 | - return sorted(rankings, key=lambda x: x[2], reverse=True) | |
| 402 | 415 | |
| 403 | - def get_performance(self): | |
| 404 | - perf = {} | |
| 405 | - with self.db_session() as s: | |
| 406 | - students = s.query(Student.id).all() | |
| 407 | - for uid, in students: | |
| 408 | - ans = s.query(Answer).filter_by(student_id=uid) | |
| 409 | - total = ans.count() | |
| 410 | - right = ans.filter_by(grade=1.0).count() | |
| 411 | - perf[uid] = right / total if total > 0 else 0.0 | |
| 412 | - return perf | |
| 416 | + return sorted(rankings, key=lambda x: x[2], reverse=True) | ... | ... |
aprendizations/serve.py
| ... | ... | @@ -88,21 +88,24 @@ class BaseHandler(tornado.web.RequestHandler): |
| 88 | 88 | return uid |
| 89 | 89 | |
| 90 | 90 | |
| 91 | +# ---------------------------------------------------------------------------- | |
| 92 | +# /rankings | |
| 93 | +# ---------------------------------------------------------------------------- | |
| 91 | 94 | class RankingsHandler(BaseHandler): |
| 92 | 95 | @tornado.web.authenticated |
| 93 | 96 | def get(self): |
| 94 | 97 | uid = self.current_user |
| 95 | 98 | rankings = self.learn.get_rankings(uid) |
| 96 | - performance = self.learn.get_performance() | |
| 99 | + # performance = self.learn.get_performance() | |
| 97 | 100 | self.render('rankings.html', |
| 98 | 101 | uid=uid, |
| 99 | 102 | name=self.learn.get_student_name(uid), |
| 100 | - rankings=rankings, | |
| 101 | - performance=performance) | |
| 103 | + rankings=rankings) | |
| 104 | + # performance=performance) | |
| 102 | 105 | |
| 103 | 106 | |
| 104 | 107 | # ---------------------------------------------------------------------------- |
| 105 | -# /auth/login and /auth/logout | |
| 108 | +# /auth/login | |
| 106 | 109 | # ---------------------------------------------------------------------------- |
| 107 | 110 | class LoginHandler(BaseHandler): |
| 108 | 111 | def get(self): |
| ... | ... | @@ -124,6 +127,8 @@ class LoginHandler(BaseHandler): |
| 124 | 127 | |
| 125 | 128 | |
| 126 | 129 | # ---------------------------------------------------------------------------- |
| 130 | +# /auth/logout | |
| 131 | +# ---------------------------------------------------------------------------- | |
| 127 | 132 | class LogoutHandler(BaseHandler): |
| 128 | 133 | @tornado.web.authenticated |
| 129 | 134 | def get(self): |
| ... | ... | @@ -157,7 +162,7 @@ class ChangePasswordHandler(BaseHandler): |
| 157 | 162 | |
| 158 | 163 | |
| 159 | 164 | # ---------------------------------------------------------------------------- |
| 160 | -# Main page: / | |
| 165 | +# / (main page) | |
| 161 | 166 | # Shows a list of topics and proficiency (stars, locked). |
| 162 | 167 | # ---------------------------------------------------------------------------- |
| 163 | 168 | class RootHandler(BaseHandler): |
| ... | ... | @@ -173,7 +178,9 @@ class RootHandler(BaseHandler): |
| 173 | 178 | |
| 174 | 179 | |
| 175 | 180 | # ---------------------------------------------------------------------------- |
| 176 | -# Start a given topic: /topic/... | |
| 181 | +# /topic/... | |
| 182 | +# Start a given topic | |
| 183 | +# FIXME should not change state... | |
| 177 | 184 | # ---------------------------------------------------------------------------- |
| 178 | 185 | class TopicHandler(BaseHandler): |
| 179 | 186 | SUPPORTED_METHODS = ['GET'] | ... | ... |
aprendizations/templates/rankings.html
| ... | ... | @@ -87,8 +87,8 @@ |
| 87 | 87 | <td> <!-- student name --> |
| 88 | 88 | {{ ' '.join(r[1].split()[n] for n in (0,-1)) }} |
| 89 | 89 | |
| 90 | - {{ '<i class="fas fa-brain fa-2x text-success" title="Mais de 75% das respostas correctas"></i>' if performance[r[0]] > 0.75 else '' }} | |
| 91 | - {{ '<i class="fas fa-frown text-secondary" title="Menos de 50% das respostas correctas" ></i>' if 0.0 < performance[r[0]] < 0.5 else '' }} | |
| 90 | + {{ '<i class="fas fa-brain fa-2x text-success" title="Mais de 75% de respostas correctas"></i>' if r[3] > 0.75 else '' }} | |
| 91 | + {{ '<i class="fas fa-frown text-secondary" title="Menos de 50% de respostas correctas" ></i>' if 0.0 < r[3] < 0.5 else '' }} | |
| 92 | 92 | </td> |
| 93 | 93 | <td> <!-- progress --> |
| 94 | 94 | <div class="progress"> | ... | ... |