Commit 31b2eb9f019cbc319be7a3bd6ddcd6961f15d1a9

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

add --correct option

Showing 2 changed files with 58 additions and 61 deletions   Show diff stats
perguntations/app.py
@@ -8,6 +8,7 @@ Description: Main application logic. @@ -8,6 +8,7 @@ Description: Main application logic.
8 import asyncio 8 import asyncio
9 import csv 9 import csv
10 import io 10 import io
  11 +import json
11 import logging 12 import logging
12 import os 13 import os
13 from typing import Optional 14 from typing import Optional
@@ -23,6 +24,8 @@ import yaml @@ -23,6 +24,8 @@ import yaml
23 from .models import Student, Test, Question 24 from .models import Student, Test, Question
24 from .tools import load_yaml 25 from .tools import load_yaml
25 from .testfactory import TestFactory, TestFactoryException 26 from .testfactory import TestFactory, TestFactoryException
  27 +from .test import Test as TestInstance
  28 +from .questions import question_from
26 29
27 # setup logger for this module 30 # setup logger for this module
28 logger = logging.getLogger(__name__) 31 logger = logging.getLogger(__name__)
@@ -59,6 +62,8 @@ class App(): @@ -59,6 +62,8 @@ class App():
59 self._make_test_factory(config['testfile']) 62 self._make_test_factory(config['testfile'])
60 self._db_setup() # setup engine and load all students 63 self._db_setup() # setup engine and load all students
61 64
  65 + asyncio.get_event_loop().run_until_complete(self._assign_tests())
  66 +
62 # command line options: --allow-all, --allow-list filename 67 # command line options: --allow-all, --allow-list filename
63 if config['allow_all']: 68 if config['allow_all']:
64 self.allow_all_students() 69 self.allow_all_students()
@@ -67,8 +72,8 @@ class App(): @@ -67,8 +72,8 @@ class App():
67 else: 72 else:
68 logger.info('Students login not yet allowed') 73 logger.info('Students login not yet allowed')
69 74
70 - # if config['correct']:  
71 - # self._correct_tests() 75 + if config['correct']:
  76 + self._correct_tests()
72 77
73 # ------------------------------------------------------------------------ 78 # ------------------------------------------------------------------------
74 def _db_setup(self) -> None: 79 def _db_setup(self) -> None:
@@ -255,65 +260,57 @@ class App(): @@ -255,65 +260,57 @@ class App():
255 session.commit() 260 session.commit()
256 logger.info('"%s" database updated.', uid) 261 logger.info('"%s" database updated.', uid)
257 262
258 -# # ------------------------------------------------------------------------  
259 -# def _correct_tests(self):  
260 -# with Session(self._engine, future=True) as session:  
261 -# # Find which tests have to be corrected  
262 -# dbtests = session.execute(  
263 -# select(Test).  
264 -# where(Test.ref == self.testfactory['ref']).  
265 -# where(Test.state == "SUBMITTED")  
266 -# ).all()  
267 -# # dbtests = session.query(Test)\  
268 -# # .filter(Test.ref == self.testfactory['ref'])\  
269 -# # .filter(Test.state == "SUBMITTED")\  
270 -# # .all()  
271 -  
272 -# logger.info('Correcting %d tests...', len(dbtests))  
273 -# for dbtest in dbtests:  
274 -# try:  
275 -# with open(dbtest.filename) as file:  
276 -# testdict = json.load(file)  
277 -# except FileNotFoundError:  
278 -# logger.error('File not found: %s', dbtest.filename)  
279 -# continue  
280 -  
281 -# # creates a class Test with the methods to correct it  
282 -# # the questions are still dictionaries, so we have to call  
283 -# # question_from() to produce Question() instances that can be  
284 -# # corrected. Finally the test can be corrected.  
285 -# test = perguntations.test.Test(testdict)  
286 -# test['questions'] = [question_from(q) for q in test['questions']]  
287 -# test.correct()  
288 -# logger.info('Student %s: grade = %f', test['student']['number'], test['grade'])  
289 -  
290 -# # save JSON file (overwriting the old one)  
291 -# uid = test['student']['number']  
292 -# ref = test['ref']  
293 -# finish_time = test['finish_time']  
294 -# answers_dir = test['answers_dir']  
295 -# fname = f'{uid}--{ref}--{finish_time}.json'  
296 -# fpath = os.path.join(answers_dir, fname)  
297 -# test.save_json(fpath)  
298 -# logger.info('%s saved JSON file.', uid)  
299 -  
300 -# # update database  
301 -# dbtest.grade = test['grade']  
302 -# dbtest.state = test['state']  
303 -# dbtest.questions = [  
304 -# Question(  
305 -# number=n,  
306 -# ref=q['ref'],  
307 -# grade=q['grade'],  
308 -# comment=q.get('comment', ''),  
309 -# starttime=str(test['start_time']),  
310 -# finishtime=str(test['finish_time']),  
311 -# test_id=test['ref']  
312 -# )  
313 -# for n, q in enumerate(test['questions'])  
314 -# ]  
315 -# logger.info('%s database updated.', uid) 263 + # ------------------------------------------------------------------------
  264 + def _correct_tests(self) -> None:
  265 + with Session(self._engine, future=True) as session:
  266 + # Find which tests have to be corrected
  267 + query = select(Test) \
  268 + .where(Test.ref == self._testfactory['ref']) \
  269 + .where(Test.state == "SUBMITTED")
  270 + dbtests = session.execute(query).scalars().all()
  271 + if not dbtests:
  272 + logger.info('No tests to correct')
  273 + return
316 274
  275 + logger.info('Correcting %d tests...', len(dbtests))
  276 + for dbtest in dbtests:
  277 + try:
  278 + with open(dbtest.filename) as file:
  279 + testdict = json.load(file)
  280 + except OSError:
  281 + logger.error('Failed: %s', dbtest.filename)
  282 + continue
  283 +
  284 + # creates a class Test with the methods to correct it
  285 + # the questions are still dictionaries, so we have to call
  286 + # question_from() to produce Question() instances that can be
  287 + # corrected. Finally the test can be corrected.
  288 + test = TestInstance(testdict)
  289 + test['questions'] = [question_from(q) for q in test['questions']]
  290 + test.correct()
  291 + logger.info(' %s: %f', test['student'], test['grade'])
  292 +
  293 + # save JSON file (overwriting the old one)
  294 + uid = test['student']
  295 + test.save_json(dbtest.filename)
  296 + logger.debug('%s saved JSON file.', uid)
  297 +
  298 + # update database
  299 + dbtest.grade = test['grade']
  300 + dbtest.state = test['state']
  301 + dbtest.questions = [
  302 + Question(
  303 + number=n,
  304 + ref=q['ref'],
  305 + grade=q['grade'],
  306 + comment=q.get('comment', ''),
  307 + starttime=str(test['start_time']),
  308 + finishtime=str(test['finish_time']),
  309 + test_id=test['ref']
  310 + ) for n, q in enumerate(test['questions'])
  311 + ]
  312 + session.commit()
  313 + logger.info('Database updated')
317 314
318 # ------------------------------------------------------------------------ 315 # ------------------------------------------------------------------------
319 # def giveup_test(self, uid): 316 # def giveup_test(self, uid):
perguntations/main.py
@@ -76,7 +76,7 @@ def get_logger_config(debug=False) -> dict: @@ -76,7 +76,7 @@ def get_logger_config(debug=False) -> dict:
76 dateformat = '' 76 dateformat = ''
77 else: 77 else:
78 level = 'INFO' 78 level = 'INFO'
79 - fmt = '%(asctime)s |%(levelname)-8s| %(message)s' 79 + fmt = '%(asctime)s| %(levelname)-8s| %(message)s'
80 dateformat = '%Y-%m-%d %H:%M:%S' 80 dateformat = '%Y-%m-%d %H:%M:%S'
81 modules = ['main', 'serve', 'app', 'models', 'questions', 'test', 81 modules = ['main', 'serve', 'app', 'models', 'questions', 'test',
82 'testfactory', 'tools'] 82 'testfactory', 'tools']