Commit 1e53d0f7b15c754a5b3e3c15996a8ecdb72bb9c2
1 parent
6c831b0d
Exists in
master
and in
1 other branch
- replaced loggedin by tags 'online' and 'finished'. Tags are shown in
/students.
Showing
5 changed files
with
49 additions
and
34 deletions
Show diff stats
BUGS.md
1 | - | |
1 | + | |
2 | 2 | |
3 | 3 | # BUGS |
4 | 4 | |
5 | +!!! - questions type script, necessário dar um caminho exacto relativamete ao directorio do server em vez da pergunta. deveria ser possivel mover as perguntas de directorio sem rebentar os caminhos. | |
5 | 6 | - se database for mal configurada, é criada uma base de dados vazia e rebenta na autenticacao. |
6 | -- hash das passwords obtidas da concatenacao do numero de aluno com password (evita que passwords repetidas sejam detectadas). | |
7 | 7 | - mostrar erro quando nao consegue importar questions files |
8 | -- numeros das perguntas não fazem sentido quando há caixas de informação (numerar informacao tb?) | |
9 | 8 | - testar regex na definicao das perguntas. como se faz rawstring em yaml? singlequote? problemas de backslash??? sim... necessário fazer \\ em varios casos, mas não é claro! e.g. \n é convertido em espaço mas \w é convertido em \\ e w. |
10 | 9 | |
11 | 10 | |
12 | 11 | # TODO |
13 | 12 | |
14 | -- Quando apresenta o teste, preencher com os valores definidos em answer (permite que professor dê informação à partida, e no modo practice fiquem com o preenchido anteriormente) | |
15 | -- testar envio de parametros para stdin para perguntas tipo generator | |
13 | +- Criar botão para o docente fazer enable/disable do aluno explicitamente (exames presenciais). | |
14 | +- testar envio de parametros para stdin para perguntas tipo generator. | |
15 | +- hash das passwords obtidas da concatenacao do numero de aluno com password (evita que passwords repetidas sejam detectadas). | |
16 | 16 | - permitir enviar varios testes, aluno escolhe qual o teste que quer fazer. |
17 | 17 | - criar script json2md.py ou outra forma de gerar um teste ja realizado |
18 | 18 | - Menu para professor com link para /results e /students |
19 | 19 | - implementar singlepage/multipage. Fazer uma class para single page que trate de andar gerir o avanco e correcao das perguntas |
20 | 20 | - permitir adicionar imagens nas perguntas |
21 | 21 | - criar perguntas de outros tipos, e.g. associação, ordenação, varios textinput |
22 | +- perguntas para professor corrigir mais tarde. | |
23 | +- testar com microsoft surface. | |
22 | 24 | |
23 | 25 | |
24 | 26 | # FIXED |
25 | 27 | |
28 | +- numeros das perguntas não fazem sentido quando há caixas de informação (numerar informacao tb?) | |
29 | +- Quando apresenta o teste, preencher com os valores definidos em answer (permite que professor dê informação à partida, e no modo practice fiquem com o preenchido anteriormente) | |
26 | 30 | - information points é definido onde? test.y ou questions.py? |
27 | 31 | - textarea monospace |
28 | 32 | - disable tab behavior in textarea. | ... | ... |
questions.py
... | ... | @@ -95,7 +95,12 @@ def create_question(q): |
95 | 95 | questiontype = Question |
96 | 96 | |
97 | 97 | # create question instance and return |
98 | - return questiontype(q) | |
98 | + try: | |
99 | + qinstance = questiontype(q) | |
100 | + except: | |
101 | + print(' * Error creating question "{0}" from file "{1}".'.format(q['ref'], q['filename'])) | |
102 | + | |
103 | + return qinstance | |
99 | 104 | |
100 | 105 | |
101 | 106 | # --------------------------------------------------------------------------- | ... | ... |
serve.py
... | ... | @@ -23,7 +23,8 @@ class Root(object): |
23 | 23 | self.database = database.Database(testconf['database']) |
24 | 24 | self.auth = AuthController(database=testconf['database']) |
25 | 25 | self.templates = TemplateLookup(directories=['templates'], input_encoding='utf-8') |
26 | - self.loggedin = set() # students currently logged in | |
26 | + self.tags = {'online': set(), 'finished': set()} | |
27 | + # self.loggedin = set() # students currently logged in | |
27 | 28 | |
28 | 29 | # --- DEFAULT ------------------------------------------------------------ |
29 | 30 | # any path, e.g. /xpto/aargh is redirected to the test |
... | ... | @@ -37,7 +38,7 @@ class Root(object): |
37 | 38 | @require() |
38 | 39 | def logout(self): |
39 | 40 | uid = cherrypy.session.get('userid') |
40 | - self.loggedin.discard(uid) | |
41 | + self.tags['online'].discard(uid) | |
41 | 42 | cherrypy.lib.sessions.expire() # session coockie expires client side |
42 | 43 | cherrypy.session['userid'] = cherrypy.request.login = None |
43 | 44 | cherrypy.log.error('Student {0} logged out.'.format(uid), 'APPLICATION') |
... | ... | @@ -58,7 +59,7 @@ class Root(object): |
58 | 59 | |
59 | 60 | students = self.database.get_students() |
60 | 61 | template = self.templates.get_template('students.html') |
61 | - return template.render(students=students, loggedin=self.loggedin) | |
62 | + return template.render(students=students, tags=self.tags) | |
62 | 63 | |
63 | 64 | # --- RESULTS ------------------------------------------------------------ |
64 | 65 | @cherrypy.expose |
... | ... | @@ -82,7 +83,7 @@ class Root(object): |
82 | 83 | cherrypy.session['test'] = t = test.Test(self.testconf) |
83 | 84 | t['number'] = uid |
84 | 85 | t['name'] = name |
85 | - self.loggedin.add(uid) # track logged in students | |
86 | + self.tags['online'].add(uid) # track logged in students | |
86 | 87 | |
87 | 88 | # Generate question |
88 | 89 | template = self.templates.get_template('test.html') |
... | ... | @@ -126,7 +127,8 @@ class Root(object): |
126 | 127 | |
127 | 128 | else: |
128 | 129 | # ---- Expire session ---- |
129 | - self.loggedin.discard(t['number']) | |
130 | + self.tags['online'].discard(t['number']) | |
131 | + self.tags['finished'].add(t['number']) | |
130 | 132 | cherrypy.lib.sessions.expire() # session coockie expires client side |
131 | 133 | cherrypy.session['userid'] = cherrypy.request.login = None |
132 | 134 | cherrypy.log.error('Student %s terminated with grade = %.2f points.' % | ... | ... |
templates/students.html
... | ... | @@ -33,12 +33,13 @@ |
33 | 33 | <div class="container"> |
34 | 34 | <div class="panel panel-default drop-shadow"> |
35 | 35 | <div class="panel-heading"> |
36 | - List of students (${len(loggedin)} online) | |
36 | + <span class="badge">${len(tags['online'])} online</span> <span class="badge">${len(tags['finished'])} finished</span> | |
37 | 37 | </div> |
38 | 38 | <!-- <div class="panel-body"> --> |
39 | 39 | <table class="table"> |
40 | 40 | <thead> |
41 | 41 | <tr> |
42 | + <th>Tags</th> | |
42 | 43 | <th>Número</th> |
43 | 44 | <th>Nome</th> |
44 | 45 | <th>Password</th> |
... | ... | @@ -46,27 +47,31 @@ |
46 | 47 | </thead> |
47 | 48 | <tbody> |
48 | 49 | % for r in students: |
49 | - % if r[0] in loggedin: | |
50 | - <tr class="danger"> | |
51 | - % else: | |
52 | - <tr> | |
53 | - % endif | |
54 | - <td>${r[0]}</td> <!-- numero --> | |
55 | - <td>${r[1]}</td> <!-- nome --> | |
56 | - <td class="col-sm-6"> | |
57 | - <form action="/students/" method="post" id="${r[0]}"> | |
58 | - <div class="input-group"> | |
59 | - <span class="input-group-btn"> | |
60 | - <!-- <button class="btn btn-danger" type="submit">reset</button> --> | |
61 | - <button form="${r[0]}" type="submit" value="submit" class="btn btn-danger">reset</button> | |
50 | + <tr> | |
51 | + <td> | |
52 | + % if r[0] in tags['online']: | |
53 | + <span class="label label-primary">online</span> | |
54 | + % endif | |
55 | + % if r[0] in tags['finished']: | |
56 | + <span class="label label-success">finished</span> | |
57 | + % endif | |
58 | + </td> | |
59 | + <td>${r[0]}</td> <!-- numero --> | |
60 | + <td>${r[1]}</td> <!-- nome --> | |
61 | + <td class="col-sm-3"> | |
62 | + <form action="/students/" method="post" id="${r[0]}"> | |
63 | + <div class="input-group"> | |
64 | + <input type="password" class="form-control" placeholder="${r[2][:8]}" name="${r[0]}"> | |
65 | + <span class="input-group-btn"> | |
66 | + <!-- <button class="btn btn-danger" type="submit">reset</button> --> | |
67 | + <button form="${r[0]}" type="submit" value="submit" class="btn btn-danger">reset</button> | |
62 | 68 | |
63 | - </span> | |
64 | - <input type="password" class="form-control" placeholder="${r[2]}" name="${r[0]}"> | |
65 | - </div><!-- /input-group --> | |
66 | - </form> | |
67 | - </td> <!-- password --> | |
68 | - </tr> | |
69 | - % endfor | |
69 | + </span> | |
70 | + </div><!-- /input-group --> | |
71 | + </form> | |
72 | + </td> <!-- password --> | |
73 | + </tr> | |
74 | + % endfor | |
70 | 75 | </tbody> |
71 | 76 | </table> |
72 | 77 | </div> <!-- panel --> | ... | ... |
templates/test.html
... | ... | @@ -88,7 +88,7 @@ |
88 | 88 | ${t['name']} (${t['number']}) <span class="caret"></span> |
89 | 89 | </a> |
90 | 90 | <ul class="dropdown-menu"> |
91 | - <li><a href="/logout"><span class="glyphicon glyphicon-log-out" aria-hidden="true"></span> Logout</a></li> | |
91 | + <li><a href="/logout"><span class="glyphicon glyphicon-log-out" aria-hidden="true"></span> Sair</a></li> | |
92 | 92 | <!-- <li><a href="#">Change password</a></li> --> |
93 | 93 | </ul> |
94 | 94 | </li> |
... | ... | @@ -101,7 +101,6 @@ |
101 | 101 | <div class="container"> |
102 | 102 | <div class="row"> |
103 | 103 | <form action="/correct/" method="post" id="test"> |
104 | - | |
105 | 104 | <%! |
106 | 105 | import markdown as md |
107 | 106 | import yaml | ... | ... |