Commit 861d9ae5ba6dfc9fe2b16f0265701d06e00c65a5

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

Much faster rankings

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 &nbsp;
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">
... ...