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,7 +70,6 @@ class StudentKnowledge(object):
70 # questions: list of generated questions to do in the topic 70 # questions: list of generated questions to do in the topic
71 # current_question: the current question to be presented 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 async def start_topic(self, topic): 73 async def start_topic(self, topic):
75 logger.debug('StudentKnowledge.start_topic()') 74 logger.debug('StudentKnowledge.start_topic()')
76 if self.current_topic == topic: 75 if self.current_topic == topic:
aprendizations/learnapp.py
@@ -8,7 +8,7 @@ from datetime import datetime @@ -8,7 +8,7 @@ from datetime import datetime
8 8
9 # user installed libraries 9 # user installed libraries
10 import bcrypt 10 import bcrypt
11 -from sqlalchemy import create_engine 11 +from sqlalchemy import create_engine, func
12 from sqlalchemy.orm import sessionmaker 12 from sqlalchemy.orm import sessionmaker
13 import networkx as nx 13 import networkx as nx
14 14
@@ -381,32 +381,36 @@ class LearnApp(object): @@ -381,32 +381,36 @@ class LearnApp(object):
381 381
382 # ------------------------------------------------------------------------ 382 # ------------------------------------------------------------------------
383 def get_rankings(self, uid): 383 def get_rankings(self, uid):
384 - logger.info(f'User {uid} get rankings') 384 + logger.info(f'User "{uid}" get rankings')
385 with self.db_session() as s: 385 with self.db_session() as s:
386 students = s.query(Student.id, Student.name).all() 386 students = s.query(Student.id, Student.name).all()
  387 + # topic progress
387 student_topics = s.query(StudentTopic.student_id, 388 student_topics = s.query(StudentTopic.student_id,
388 StudentTopic.topic_id, 389 StudentTopic.topic_id,
389 StudentTopic.level, 390 StudentTopic.level,
390 StudentTopic.date).all() 391 StudentTopic.date).all()
391 total_topics = s.query(Topic).count() 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 now = datetime.now() 408 now = datetime.now()
395 for uid, topic, level, date in student_topics: 409 for uid, topic, level, date in student_topics:
396 date = datetime.strptime(date, "%Y-%m-%d %H:%M:%S.%f") 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 for uid, name in students if uid != '0'] 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,21 +88,24 @@ class BaseHandler(tornado.web.RequestHandler):
88 return uid 88 return uid
89 89
90 90
  91 +# ----------------------------------------------------------------------------
  92 +# /rankings
  93 +# ----------------------------------------------------------------------------
91 class RankingsHandler(BaseHandler): 94 class RankingsHandler(BaseHandler):
92 @tornado.web.authenticated 95 @tornado.web.authenticated
93 def get(self): 96 def get(self):
94 uid = self.current_user 97 uid = self.current_user
95 rankings = self.learn.get_rankings(uid) 98 rankings = self.learn.get_rankings(uid)
96 - performance = self.learn.get_performance() 99 + # performance = self.learn.get_performance()
97 self.render('rankings.html', 100 self.render('rankings.html',
98 uid=uid, 101 uid=uid,
99 name=self.learn.get_student_name(uid), 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 class LoginHandler(BaseHandler): 110 class LoginHandler(BaseHandler):
108 def get(self): 111 def get(self):
@@ -124,6 +127,8 @@ class LoginHandler(BaseHandler): @@ -124,6 +127,8 @@ class LoginHandler(BaseHandler):
124 127
125 128
126 # ---------------------------------------------------------------------------- 129 # ----------------------------------------------------------------------------
  130 +# /auth/logout
  131 +# ----------------------------------------------------------------------------
127 class LogoutHandler(BaseHandler): 132 class LogoutHandler(BaseHandler):
128 @tornado.web.authenticated 133 @tornado.web.authenticated
129 def get(self): 134 def get(self):
@@ -157,7 +162,7 @@ class ChangePasswordHandler(BaseHandler): @@ -157,7 +162,7 @@ class ChangePasswordHandler(BaseHandler):
157 162
158 163
159 # ---------------------------------------------------------------------------- 164 # ----------------------------------------------------------------------------
160 -# Main page: / 165 +# / (main page)
161 # Shows a list of topics and proficiency (stars, locked). 166 # Shows a list of topics and proficiency (stars, locked).
162 # ---------------------------------------------------------------------------- 167 # ----------------------------------------------------------------------------
163 class RootHandler(BaseHandler): 168 class RootHandler(BaseHandler):
@@ -173,7 +178,9 @@ 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 class TopicHandler(BaseHandler): 185 class TopicHandler(BaseHandler):
179 SUPPORTED_METHODS = ['GET'] 186 SUPPORTED_METHODS = ['GET']
aprendizations/templates/rankings.html
@@ -87,8 +87,8 @@ @@ -87,8 +87,8 @@
87 <td> <!-- student name --> 87 <td> <!-- student name -->
88 {{ ' '.join(r[1].split()[n] for n in (0,-1)) }} 88 {{ ' '.join(r[1].split()[n] for n in (0,-1)) }}
89 &nbsp; 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 </td> 92 </td>
93 <td> <!-- progress --> 93 <td> <!-- progress -->
94 <div class="progress"> 94 <div class="progress">