Commit 70459fa790dfb9c805e7e06ff83ebf19702080df

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

- names CSV file to download with grades after the test "ref" key.

1 1
2 # BUGS 2 # BUGS
3 3
  4 +- botao de autorizar desliga-se, fazer debounce.
  5 +e.g. retornar None quando nao ha alteracoes relativamente à última vez.
  6 +ou usar push (websockets?)
4 - quando scale_max não é 20, as cores das barras continuam a reflectir a escala 0,20 7 - quando scale_max não é 20, as cores das barras continuam a reflectir a escala 0,20
5 - CRITICAL se answer for `i<n` a revisão de provas mostra apenas i (interpreta `<` como tag?) 8 - CRITICAL se answer for `i<n` a revisão de provas mostra apenas i (interpreta `<` como tag?)
6 - na pagina grade.html as barras estao normalizadas para os limites scale_min e max do teste actual e nao do realizado. 9 - na pagina grade.html as barras estao normalizadas para os limites scale_min e max do teste actual e nao do realizado.
7 - codigo `hello world` nao esta a preservar o whitespace. O renderer de markdown gera a tag <code> que não preserva whitespace. Necessario adicionar <pre>. 10 - codigo `hello world` nao esta a preservar o whitespace. O renderer de markdown gera a tag <code> que não preserva whitespace. Necessario adicionar <pre>.
8 - teste nao esta a mostrar imagens de vez em quando. 11 - teste nao esta a mostrar imagens de vez em quando.
9 -- ordenacao das notas em /admin nao é numerica, é ascii...  
10 - mensagems de erro do assembler aparecem na mesma linha na correcao e nao fazerm rendering do `$t`, ver se servidor faz parse do markdown dessas mensagens. 12 - mensagems de erro do assembler aparecem na mesma linha na correcao e nao fazerm rendering do `$t`, ver se servidor faz parse do markdown dessas mensagens.
11 - impedir os eventos copy/paste. alunos usam isso para trazer codigo ja feito nos computadores. Obrigar a fazer reset? fazer um copy automaticamente? 13 - impedir os eventos copy/paste. alunos usam isso para trazer codigo ja feito nos computadores. Obrigar a fazer reset? fazer um copy automaticamente?
12 - a revisao do teste não mostra as imagens. 14 - a revisao do teste não mostra as imagens.
13 -- melhorar o botao de autorizar (desliga-se), usar antes um botao?  
14 -e.g. retornar None quando nao ha alteracoes relativamente à última vez.  
15 -ou usar push (websockets?)  
16 - Test.reset_answers() unused. 15 - Test.reset_answers() unused.
17 -- mudar ref do test para test_id (ref já é usado nas perguntas)  
18 - incluir test_id na tabela questions (futuro semestre, pode quebrar compatibilidade). 16 - incluir test_id na tabela questions (futuro semestre, pode quebrar compatibilidade).
19 - na pagina admin, mostrar com cor vermelha as horas de entrada dos alunos que ja tenham excedido o tempo 17 - na pagina admin, mostrar com cor vermelha as horas de entrada dos alunos que ja tenham excedido o tempo
20 18
21 # TODO 19 # TODO
22 20
23 -- servidor ntpd para configurar a data/hora dos portateis dell 21 +- mudar ref do test para test_id (ref já é usado nas perguntas)
  22 +- servidor ntpd no x220 para configurar a data/hora dos portateis dell
24 - autorização dada, mas teste não disponível até que seja dada ordem para começar. 23 - autorização dada, mas teste não disponível até que seja dada ordem para começar.
25 - alunos com necessidades especiais nao podem ter autosubmit. ter um autosubmit_exceptions: ['123', '456'] 24 - alunos com necessidades especiais nao podem ter autosubmit. ter um autosubmit_exceptions: ['123', '456']
26 - mostrar unfocus e window area em /admin 25 - mostrar unfocus e window area em /admin
perguntations/__init__.py
@@ -32,7 +32,7 @@ proof of submission and for review. @@ -32,7 +32,7 @@ proof of submission and for review.
32 ''' 32 '''
33 33
34 APP_NAME = 'perguntations' 34 APP_NAME = 'perguntations'
35 -APP_VERSION = '2020.05.dev1' 35 +APP_VERSION = '2020.05.dev2'
36 APP_DESCRIPTION = __doc__ 36 APP_DESCRIPTION = __doc__
37 37
38 __author__ = 'Miguel Barão' 38 __author__ = 'Miguel Barão'
perguntations/app.py
@@ -294,7 +294,7 @@ class App(): @@ -294,7 +294,7 @@ class App():
294 writer = csv.writer(csvstr, delimiter=';', quoting=csv.QUOTE_ALL) 294 writer = csv.writer(csvstr, delimiter=';', quoting=csv.QUOTE_ALL)
295 writer.writerow(('Número', 'Nota', 'Início', 'Fim')) 295 writer.writerow(('Número', 'Nota', 'Início', 'Fim'))
296 writer.writerows(grades) 296 writer.writerows(grades)
297 - return csvstr.getvalue() 297 + return self.testfactory['ref'], csvstr.getvalue()
298 298
299 def get_student_test(self, uid, default=None): 299 def get_student_test(self, uid, default=None):
300 '''get test from online student''' 300 '''get test from online student'''
perguntations/serve.py
@@ -184,10 +184,11 @@ class AdminWebservice(BaseHandler): @@ -184,10 +184,11 @@ class AdminWebservice(BaseHandler):
184 '''admin webservices that do not change state''' 184 '''admin webservices that do not change state'''
185 cmd = self.get_query_argument('cmd') 185 cmd = self.get_query_argument('cmd')
186 if cmd == 'testcsv': 186 if cmd == 'testcsv':
  187 + test_ref, data = self.testapp.get_test_csv()
187 self.set_header('Content-Type', 'text/csv') 188 self.set_header('Content-Type', 'text/csv')
188 self.set_header('content-Disposition', 189 self.set_header('content-Disposition',
189 - 'attachment; filename=notas.csv')  
190 - self.write(self.testapp.get_test_csv()) 190 + f'attachment; filename={test_ref}.csv')
  191 + self.write(data)
191 await self.flush() 192 await self.flush()
192 193
193 # ---------------------------------------------------------------------------- 194 # ----------------------------------------------------------------------------
perguntations/test.py
@@ -9,6 +9,7 @@ from os import path @@ -9,6 +9,7 @@ from os import path
9 import random 9 import random
10 from datetime import datetime 10 from datetime import datetime
11 import logging 11 import logging
  12 +import re
12 13
13 # this project 14 # this project
14 from perguntations.questions import QFactory, QuestionException 15 from perguntations.questions import QFactory, QuestionException
@@ -123,10 +124,13 @@ class TestFactory(dict): @@ -123,10 +124,13 @@ class TestFactory(dict):
123 124
124 125
125 # ------------------------------------------------------------------------ 126 # ------------------------------------------------------------------------
126 - def check_missing_ref(self): 127 + def check_test_ref(self):
127 '''Test must have a `ref`''' 128 '''Test must have a `ref`'''
128 if 'ref' not in self: 129 if 'ref' not in self:
129 raise TestFactoryException('Missing "ref" in configuration!') 130 raise TestFactoryException('Missing "ref" in configuration!')
  131 + if not re.match(r'^[a-zA-Z0-9_-]+$', self['ref']):
  132 + raise TestFactoryException('Test "ref" can only contain the '
  133 + 'characters a-zA-Z0-9_-')
130 134
131 def check_missing_database(self): 135 def check_missing_database(self):
132 '''Test must have a database''' 136 '''Test must have a database'''
@@ -208,7 +212,7 @@ class TestFactory(dict): @@ -208,7 +212,7 @@ class TestFactory(dict):
208 Checks for valid keys and sets default values. 212 Checks for valid keys and sets default values.
209 Also checks if some files and directories exist 213 Also checks if some files and directories exist
210 ''' 214 '''
211 - self.check_missing_ref() 215 + self.check_test_ref()
212 self.check_missing_database() 216 self.check_missing_database()
213 self.check_missing_answers_directory() 217 self.check_missing_answers_directory()
214 self.check_answers_directory_writable() 218 self.check_answers_directory_writable()