diff --git a/BUGS.md b/BUGS.md index 5d17782..2c8ccb3 100644 --- a/BUGS.md +++ b/BUGS.md @@ -1,9 +1,6 @@ # BUGS -- se um teste tiver a mesma pergunta (ref igual) varias vezes, rebenta na correcçao. As respostas são agregadas numa lista para cada ref. Ex: - {'ref1': 'resposta1', 'ref2': ['resposta2a', 'resposta2b']} -possivelmente as referencias das perguntas deveriam ser o "testeRef:numPergunta"... é preciso ver como depois estao associadas às correcções. - se directorio logs não existir no directorio actual (não perguntations) rebenta. - usar thread.Lock para aceder a variaveis de estado? - servidor nao esta a lidar com eventos scroll/resize @@ -27,6 +24,7 @@ possivelmente as referencias das perguntas deveriam ser o "testeRef:numPergunta" # FIXED +- se um teste tiver a mesma pergunta repetida (ref igual), rebenta na correcçao. As respostas são agregadas numa lista para cada ref. Ex: {'ref1': 'resposta1', 'ref2': ['resposta2a', 'resposta2b']} - usar http://fontawesome.io/examples/ em vez dos do bootstrap3 - se pergunta tiver 'type:' errado, rebenta. - se submeter um teste so com information, da divisao por zero. diff --git a/app.py b/app.py index d73479b..0fba2e8 100644 --- a/app.py +++ b/app.py @@ -124,6 +124,8 @@ class App(object): return None # ----------------------------------------------------------------------- + # ans is a dictionary {question_index: answer, ...} + # for example: {0:'hello', 1:[1,2]} def correct_test(self, uid, ans): t = self.online[uid]['test'] t.update_answers(ans) @@ -161,7 +163,7 @@ class App(object): # ----------------------------------------------------------------------- def giveup_test(self, uid): t = self.online[uid]['test'] - grade = t.giveup() + t.giveup() # save JSON with the test fname = ' -- '.join((t['student']['number'], t['ref'], str(t['finish_time']))) + '.json' @@ -194,8 +196,6 @@ class App(object): return self.online[uid].get('test', default) def get_questions_path(self): return self.testfactory['questions_dir'] - def get_test_qtypes(self, uid): - 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_by(student_id=uid).order_by(Test.finishtime).all() diff --git a/serve.py b/serve.py index c72923d..838d410 100755 --- a/serve.py +++ b/serve.py @@ -192,30 +192,35 @@ class Root(object): @require() def correct(self, **kwargs): # receives dictionary with answers - # kwargs = {'answered-xpto': 'on', 'xpto': '13.45', ...} + # kwargs = {'answered-0': 'on', '0': '13.45', ...} # Format: # checkbox - all off -> no key, 1 on -> string '0', >1 on -> ['0', '1'] # radio - all off -> no key, 1 on -> string '0' # text - always returns string. no answer '', otherwise 'dskdjs' uid = cherrypy.session.get(SESSION_KEY) - name = self.app.get_student_name(uid) - qq = self.app.get_test_qtypes(uid) # {'q1_ref': 'checkbox', ...} + t = self.app.get_test(uid) - # each question that is marked to be classified must have an answer. - # `ans` contains the answers to be corrected. The missing ones were - # disabled by the student + # build dictionary ans={0: 'answer0', 1:, 'answer1', ...} + # questions not answer are not included. ans = {} - for qref, qtype in qq.items(): - if 'answered-' + qref in kwargs: - # HTML HACK: checkboxes in html return None instead of an empty list if none is selected. Also, if only one is selected returns string instead of list of strings. - default_ans = [] if qtype == 'checkbox' else None - a = kwargs.get(qref, default_ans) - if qtype == 'checkbox' and isinstance(a, str): - a = [a] - ans[qref] = a - - grade = self.app.correct_test(uid, ans) - t = self.app.get_test(uid) + for i, q in enumerate(t['questions']): + if 'answered-' + str(i) in kwargs: + ans[i] = kwargs.get(str(i), None) + + # Begin HACK + # checkboxes in html do not have a stable type: + # returns None instead of [], when no checkboxes are selected + # returns '5' instead of ['5'], when one checkbox is selected + # returns correctly ['1', '3'], on multiple selections + # we fix it to always return a list + if q['type'] == 'checkbox': + if ans[i] is None: + ans[i] = [] + elif isinstance(ans[i], str): + ans[i] = [ans[i]] + # end HACK + + self.app.correct_test(uid, ans) self.app.logout(uid) # --- Expire session diff --git a/templates/test.html b/templates/test.html index 6c758d8..35571e4 100644 --- a/templates/test.html +++ b/templates/test.html @@ -130,7 +130,7 @@
Classificar  - +
@@ -143,7 +143,7 @@
% for opt in q['options']: - ${md_to_html(' '.format(q['ref'], loop.index, 'checked' if q['answer'] is not None and str(loop.index) == q['answer'] else '') + opt, q['ref'], q['files'])} + ${md_to_html(' '.format(i, loop.index, 'checked' if q['answer'] is not None and str(loop.index) == q['answer'] else '') + opt, q['ref'], q['files'])} % endfor
@@ -152,25 +152,25 @@
% for opt in q['options']: - ${md_to_html(' {3}'.format(q['ref'], loop.index, 'checked' if q['answer'] is not None and str(loop.index) in q['answer'] else '', opt), q['ref'], q['files'])} + ${md_to_html(' '.format(i, loop.index, 'checked' if q['answer'] is not None and str(loop.index) in q['answer'] else '') + opt, q['ref'], q['files'])} % endfor
% elif q['type'] in ('text', 'text_regex'): - + % elif q['type'] == 'textarea': -
+
% endif % if t['show_hints']: % if 'hint' in q:

-

-
+
${md_to_html(q['hint'], q['ref'], q['files'])}
diff --git a/test.py b/test.py index eeebd79..bd7578d 100644 --- a/test.py +++ b/test.py @@ -9,9 +9,7 @@ import logging logger = logging.getLogger(__name__) try: - # import yaml import json - import markdown except ImportError: logger.critical('Python package missing. See README.md for instructions.') sys.exit(1) @@ -213,13 +211,12 @@ class Test(dict): logger.info('Student {}: all answers cleared.'.format(self['student']['number'])) # ----------------------------------------------------------------------- - # Given a dictionary ans={'someref': 'some answer'} updates the + # Given a dictionary ans={index: 'some answer'} updates the # answers of the test. Only affects questions referred. def update_answers(self, ans): - for q in self['questions']: - if q['ref'] in ans: - q['answer'] = ans[q['ref']] - logger.info('Student {}: answers updated.'.format(self['student']['number'])) + for i in ans: + self['questions'][i]['answer'] = ans[i] + logger.info('Student {}: {} answers updated.'.format(self['student']['number'], len(ans))) # ----------------------------------------------------------------------- # Corrects all the answers and computes the final grade -- libgit2 0.21.2