Commit a850fbe084f4ded2a81c36d05eb446ea173fd683
1 parent
3f6a1c20
Exists in
master
and in
1 other branch
- show rankings by course
- don't show students with no activity
Showing
3 changed files
with
14 additions
and
12 deletions
Show diff stats
BUGS.md
| 1 | 1 | ||
| 2 | # BUGS | 2 | # BUGS |
| 3 | 3 | ||
| 4 | -- obter rankings por curso GET course=course_id | ||
| 5 | -- indicar qtos topicos faltam (>=50%) para terminar o curso. | 4 | +- initdb da integrity error se no mesmo comando existirem alunos repetidos (p.ex em ficheiros csv diferentes ou entre csv e opcao -a) |
| 6 | - permite definir goal, mas nao verifica se esta no grafo. rebenta no start_topic. | 5 | - permite definir goal, mas nao verifica se esta no grafo. rebenta no start_topic. |
| 7 | - double click submits twice. | 6 | - double click submits twice. |
| 8 | - nao esta a seguir o max_tries definido no ficheiro de dependencias. | 7 | - nao esta a seguir o max_tries definido no ficheiro de dependencias. |
| @@ -29,6 +28,7 @@ sqlite3.ProgrammingError: SQLite objects created in a thread can only be used in | @@ -29,6 +28,7 @@ sqlite3.ProgrammingError: SQLite objects created in a thread can only be used in | ||
| 29 | 28 | ||
| 30 | # TODO | 29 | # TODO |
| 31 | 30 | ||
| 31 | +- indicar qtos topicos faltam (>=50%) para terminar o curso. | ||
| 32 | - use run_script_async to run run_script using asyncio.run? | 32 | - use run_script_async to run run_script using asyncio.run? |
| 33 | - ao fim de 3 tentativas de login, envial email para aluno com link para definir nova password (com timeout de 5 minutos). | 33 | - ao fim de 3 tentativas de login, envial email para aluno com link para definir nova password (com timeout de 5 minutos). |
| 34 | - mostrar capitulos e subtopicos de forma hierarquica. clicar no capitulo expande as dependencias. | 34 | - mostrar capitulos e subtopicos de forma hierarquica. clicar no capitulo expande as dependencias. |
| @@ -50,6 +50,7 @@ sqlite3.ProgrammingError: SQLite objects created in a thread can only be used in | @@ -50,6 +50,7 @@ sqlite3.ProgrammingError: SQLite objects created in a thread can only be used in | ||
| 50 | 50 | ||
| 51 | # FIXED | 51 | # FIXED |
| 52 | 52 | ||
| 53 | +- obter rankings por curso GET course=course_id | ||
| 53 | - no curso de linear algebra, as perguntas estao shuffled, mas nao deviam estar... nao esta a obedecer a keyword shuffle. | 54 | - no curso de linear algebra, as perguntas estao shuffled, mas nao deviam estar... nao esta a obedecer a keyword shuffle. |
| 54 | - menu nao mostra as opcoes correctamente | 55 | - menu nao mostra as opcoes correctamente |
| 55 | - finish topic vai para a lista de cursos. devia ficar no mesmo curso. | 56 | - finish topic vai para a lista de cursos. devia ficar no mesmo curso. |
aprendizations/learnapp.py
| 1 | 1 | ||
| 2 | # python standard library | 2 | # python standard library |
| 3 | import asyncio | 3 | import asyncio |
| 4 | +from collections import defaultdict | ||
| 4 | from contextlib import contextmanager # `with` statement in db sessions | 5 | from contextlib import contextmanager # `with` statement in db sessions |
| 5 | from datetime import datetime | 6 | from datetime import datetime |
| 6 | import logging | 7 | import logging |
| @@ -478,10 +479,9 @@ class LearnApp(object): | @@ -478,10 +479,9 @@ class LearnApp(object): | ||
| 478 | 479 | ||
| 479 | # topic progress | 480 | # topic progress |
| 480 | student_topics = s.query(StudentTopic.student_id, | 481 | student_topics = s.query(StudentTopic.student_id, |
| 481 | - StudentTopic.topic_id, # FIXME Filter topics of the course | 482 | + StudentTopic.topic_id, |
| 482 | StudentTopic.level, | 483 | StudentTopic.level, |
| 483 | StudentTopic.date).all() | 484 | StudentTopic.date).all() |
| 484 | - total_topics = s.query(Topic).count() | ||
| 485 | 485 | ||
| 486 | # answer performance | 486 | # answer performance |
| 487 | total = dict(s.query(Answer.student_id, sa.func.count(Answer.ref)). | 487 | total = dict(s.query(Answer.student_id, sa.func.count(Answer.ref)). |
| @@ -497,15 +497,18 @@ class LearnApp(object): | @@ -497,15 +497,18 @@ class LearnApp(object): | ||
| 497 | for uid in total} | 497 | for uid in total} |
| 498 | 498 | ||
| 499 | # compute topic progress | 499 | # compute topic progress |
| 500 | - prog: Dict[str, float] = {s[0]: 0.0 for s in students} | ||
| 501 | now = datetime.now() | 500 | now = datetime.now() |
| 501 | + goals = self.courses[course_id]['goals'] | ||
| 502 | + prog = defaultdict(int) | ||
| 503 | + | ||
| 502 | for uid, topic, level, date in student_topics: | 504 | for uid, topic, level, date in student_topics: |
| 503 | - date = datetime.strptime(date, "%Y-%m-%d %H:%M:%S.%f") | ||
| 504 | - prog[uid] += level**(now - date).days / total_topics | 505 | + if topic in goals: |
| 506 | + date = datetime.strptime(date, "%Y-%m-%d %H:%M:%S.%f") | ||
| 507 | + prog[uid] += level**(now - date).days / len(goals) | ||
| 505 | 508 | ||
| 506 | rankings = [(uid, name, prog[uid], perf.get(uid, 0.0)) | 509 | rankings = [(uid, name, prog[uid], perf.get(uid, 0.0)) |
| 507 | - for uid, name in students if uid != '0'] | ||
| 508 | - | ||
| 509 | - return sorted(rankings, key=lambda x: x[2], reverse=True) | 510 | + for uid, name in students if uid != '0' and uid in prog] |
| 511 | + rankings.sort(key=lambda x: x[2], reverse=True) | ||
| 512 | + return rankings | ||
| 510 | 513 | ||
| 511 | # ------------------------------------------------------------------------ | 514 | # ------------------------------------------------------------------------ |
aprendizations/templates/rankings.html
| @@ -71,8 +71,6 @@ | @@ -71,8 +71,6 @@ | ||
| 71 | {% for i,r in enumerate(rankings) %} | 71 | {% for i,r in enumerate(rankings) %} |
| 72 | {% if r[0] == uid %} | 72 | {% if r[0] == uid %} |
| 73 | <tr class="table-primary"> <!-- this is me --> | 73 | <tr class="table-primary"> <!-- this is me --> |
| 74 | - {% elif r[2] == 0 %} | ||
| 75 | - <tr class="table-secondary"> <!-- level = 0 --> | ||
| 76 | {% else %} | 74 | {% else %} |
| 77 | <tr> | 75 | <tr> |
| 78 | {% end %} | 76 | {% end %} |