diff --git a/BUGS.md b/BUGS.md index a13ed05..9ce78fb 100644 --- a/BUGS.md +++ b/BUGS.md @@ -1,20 +1,21 @@ # BUGS -- implementar practice mode. - usar thread.Lock para aceder a variaveis de estado? +- visualizar um teste ja realizado na página de administração # TODO +- usar http://wtfforms.com para radio e checkboxes +- usar http://fontawesome.io/examples/ em vez dos do bootstrap3 +- implementar practice mode. - abrir o teste numa janela maximizada e que nao permite que o aluno a redimensione/mova. - detectar scroll e enviar posição para servidor (analise de scroll para detectar copianço? ou simplesmente para analisar como os alunos percorrem o teste) -- detectar se janela perde focus e alertar o prof (http://stackoverflow.com/questions/1060008/is-there-a-way-to-detect-if-a-browser-window-is-not-currently-active) - single page web no teste/correcçao. Página construída em javascript, obter perguntas com ajax (para practice?). - aviso na pagina principal para quem usa browser da treta - permitir varios testes, aluno escolhe qual o teste que quer fazer. - criar perguntas de outros tipos, e.g. associação, ordenação, varios textinput - perguntas para professor corrigir mais tarde. -- visualizar um teste ja realizado na página de administração - fazer uma calculadora javascript e por no menu. surge como modal - GeoIP? - alunos online têm acesso a /correct e servidor rebenta. (não é fácil impedir...) @@ -22,6 +23,8 @@ # FIXED +- Depois da correcção, mostra testes realizados que não foram realizados pelo próprio +- detectar se janela perde focus e alertar o prof (http://stackoverflow.com/questions/1060008/is-there-a-way-to-detect-if-a-browser-window-is-not-currently-active) - server nao esta a receber eventos focus/blur dos utilizadores diferentes de '0', estranho... - permitir adicionar imagens nas perguntas. - detect_unfocus.js so funciona se estiver inline no html. porquê??? diff --git a/app.py b/app.py index 6cc5a43..16e17ca 100644 --- a/app.py +++ b/app.py @@ -131,22 +131,25 @@ class App(object): grade = t.correct() logger.info('Student {0}: finished with {1} points.'.format(uid, grade)) - if t['save_answers']: - fname = ' -- '.join((t['student']['number'], t['ref'], str(t['finish_time']))) + '.json' - fpath = path.abspath(path.join(t['answers_dir'], fname)) - t.save_json(fpath) + # save JSON with the test + fname = ' -- '.join((t['student']['number'], t['ref'], str(t['finish_time']))) + '.json' + fpath = path.abspath(path.join(t['answers_dir'], fname)) + t.save_json(fpath) + # insert test and questions into database with self.db_session() as s: s.add(Test( ref=t['ref'], + title=t['title'], grade=t['grade'], starttime=str(t['start_time']), finishtime=str(t['finish_time']), + filename=fpath, student_id=t['student']['number'])) s.add_all([Question( ref=q['ref'], grade=q['grade'], - starttime='', + starttime=str(t['start_time']), finishtime=str(t['finish_time']), student_id=t['student']['number'], test_id=t['ref']) for q in t['questions'] if 'grade' in q]) @@ -176,9 +179,12 @@ class App(object): return {q['ref']:q['type'] for q in self.online[uid]['test']['questions']} def get_student_grades_from_all_tests(self, uid): with self.db_session() as s: - r = s.query(Test).filter(Student.id == uid).all() - return [(t.id, t.grade, t.finishtime) for t in r] - + r = s.query(Test).filter(Test.student_id == uid).all() + return [(t.title, t.grade, t.finishtime) for t in r] + # def get_saved_tests_filenames(self): + # with self.db_session() as s: + # rr = s.query(Test).filter(Test.ref == self.testfactory['ref']).all() + # return [(r.student_id, r.finishtime, r.grade) for r in rr] def get_online_students(self): # [('uid', 'name', 'starttime')] return [(k, v['student']['name'], str(v.get('test', {}).get('start_time', '---'))) for k,v in self.online.items() if k != '0'] diff --git a/models.py b/models.py index 4dbaa89..a8cb15d 100644 --- a/models.py +++ b/models.py @@ -29,9 +29,11 @@ class Test(Base): __tablename__ = 'tests' id = Column(Integer, primary_key=True) # auto_increment ref = Column(String) + title = Column(String) grade = Column(Float) starttime = Column(String) finishtime = Column(String) + filename = Column(String) student_id = Column(String, ForeignKey('students.id')) # --- diff --git a/serve.py b/serve.py index 03a8a8f..4fb605c 100755 --- a/serve.py +++ b/serve.py @@ -198,7 +198,6 @@ class Root(object): # text - always returns string. no answer '', otherwise 'dskdjs' uid = cherrypy.session.get(SESSION_KEY) name = self.app.get_student_name(uid) - title = self.app.get_test(uid)['title'] qq = self.app.get_test_qtypes(uid) # {'q1_ref': 'checkbox', ...} # each question that is marked to be classified must have an answer. @@ -215,6 +214,7 @@ class Root(object): ans[qref] = a grade = self.app.correct_test(uid, ans) + t = self.app.get_test(uid) self.app.logout(uid) # --- Expire session @@ -223,9 +223,7 @@ class Root(object): # --- Show result to student return self.template['grade'].render( - title=title, - student_id=uid + ' - ' + name, - grade=grade, + t=t, allgrades=self.app.get_student_grades_from_all_tests(uid) ) @@ -267,6 +265,14 @@ class Root(object): def admin(self, **reset_pw): return self.template['admin'].render() + # --- REVIEW ------------------------------------------------------------- + @cherrypy.expose + @require(name_is('0')) + def review(self, uid=None): + if uid is None: + # get show list of files + pass + # ============================================================================ def parse_arguments(): argparser = argparse.ArgumentParser(description='Server for online tests. Enrolled students and tests have to be previously configured. Please read the documentation included with this software before running the server.') diff --git a/templates/grade.html b/templates/grade.html index 4ef5759..92e74bd 100644 --- a/templates/grade.html +++ b/templates/grade.html @@ -4,34 +4,17 @@ -