Added models and views

This commit is contained in:
2022-06-12 21:03:51 +01:00
parent 66e7b2b9f8
commit 8439d99949
12 changed files with 276 additions and 125 deletions

View File

@@ -1,112 +1,91 @@
class Test:
def __init__(self, _id=None, start_date=None, expiry_date=None, time_limit=None, creator=None, dataset=None):
self._id = _id
self.start_date = start_date
self.expiry_date = expiry_date
self.time_limit = None if time_limit == 'none' or time_limit == '' or time_limit == None else int(time_limit)
self.creator = creator
self.dataset = dataset
from ..modules import db
from ..tools.encryption import decrypt, encrypt
from ..tools.forms import JsonEncodedDict
from ..tools.logs import write
from flask import jsonify
from flask.helpers import flash
from flask_login import current_user
from datetime import datetime
from json import dump, loads
import os
import secrets
class Test(db.Model):
id = db.Column(db.String(36), primary_key=True)
code = db.Column(db.String(36), nullable=False)
start_date = db.Column(db.DateTime, nullable=True)
end_date = db.Column(db.DateTime, nullable=True)
time_limit = db.Column(db.Integer, nullable=True)
creator = db.Column(db.String(36), db.ForeignKey('user.id'))
data = db.Column(db.String(36), nullable=False)
adjustments = db.Column(JsonEncodedDict, nullable=True)
def __repr__(self):
return f'<test with code {self.code} was created by {current_user.get_username()}.>'
def get_code(self):
code = self.code.upper()
return ''.join([code[:4], code[4:8], code[8:]])
def create(self):
from main import app, db
test = {
'_id': self._id,
'date_created': datetime.today(),
'start_date': self.start_date,
'expiry_date': self.expiry_date,
'time_limit': self.time_limit,
'creator': encrypt(self.creator),
'test_code': secrets.token_hex(6).upper(),
'dataset': self.dataset
}
if db.tests.insert_one(test):
dataset_file_path = os.path.join(app.config["DATA_FILE_DIRECTORY"],self.dataset)
with open(dataset_file_path, 'r') as dataset_file:
data = loads(dataset_file.read())
data['meta']['tests'].append(self._id)
with open(dataset_file_path, 'w') as dataset_file:
dump(data, dataset_file, indent=2)
flash(f'Created a new exam with Exam Code <strong>{self.render_test_code(test["test_code"])}</strong>.', 'success')
return jsonify({'success': test}), 200
return jsonify({'error': f'Could not create exam. An error occurred.'}), 400
def add_time_adjustment(self, time_adjustment):
from main import db
user_code = secrets.token_hex(3).upper()
adjustment = {
user_code: time_adjustment
}
if db.tests.find_one_and_update({'_id': self._id}, {'$set': {'time_adjustments': adjustment}},upsert=False):
flash(f'Time adjustment for {time_adjustment} minutes has been added. This can be enabled using the user code {user_code}.')
return jsonify({'success': adjustment})
return jsonify({'error': 'Failed to add the time adjustment. An error occurred.'}), 400
def remove_time_adjustment(self, user_code):
from main import db
if db.tests.find_one_and_update({'_id': self._id}, {'$unset': {f'time_adjustments.{user_code}': {}}}):
message = 'Time adjustment has been deleted.'
flash(message, 'success')
return jsonify({'success': message})
return jsonify({'error': 'Failed to delete the time adjustment. An error occurred.'}), 400
def render_test_code(self, test_code):
return ''.join([test_code[:4], test_code[4:8], test_code[8:]])
def parse_test_code(self, test_code):
return test_code.replace('', '')
db.session.add(self)
db.session.commit()
write('system.log', f'Test with code {self.code} created by {current_user.get_username()}.')
def delete(self):
from main import app, db
test = db.tests.find_one({'_id': self._id})
if 'entries' in test:
if test['entries']:
return jsonify({'error': 'Cannot delete an exam that has entries submitted to it.'}), 400
if self.dataset is None:
self.dataset = db.tests.find_one({'_id': self._id})['dataset']
if db.tests.delete_one({'_id': self._id}):
dataset_file_path = os.path.join(app.config["DATA_FILE_DIRECTORY"],self.dataset)
with open(dataset_file_path, 'r') as dataset_file:
data = loads(dataset_file.read())
data['meta']['tests'].remove(self._id)
with open(dataset_file_path, 'w') as dataset_file:
dump(data, dataset_file, indent=2)
message = 'Deleted exam.'
flash(message, 'alert')
return jsonify({'success': message}), 200
return jsonify({'error': f'Could not create exam. An error occurred.'}), 400
code = self.code
db.session.delete(self)
db.session.commit()
write('system.log', f'Test with code {code} deleted by {current_user.get_username()}.')
def start(self):
now = datetime.now()
if self.start_date > now:
self.start_date = now
db.session.commit()
message = f'Test with code {self.code} started by {current_user.get_username()}.'
write('system.log', message)
return True, jsonify({'success': message})
return False, jsonify({'error': f'Test with code {self.code} has already started.'})
def update(self):
from main import db
test = {}
updated = []
if not self.start_date == '' and self.start_date is not None:
test['start_date'] = self.start_date
updated.append('start date')
if not self.expiry_date == '' and self.expiry_date is not None:
test['expiry_date'] = self.expiry_date
updated.append('expiry date')
if not self.time_limit == '' and self.time_limit is not None:
test['time_limit'] = int(self.time_limit)
updated.append('time limit')
output = ''
if len(updated) == 0:
flash(f'There were no changes requested for your account.', 'alert'), 200
return jsonify({'success': 'There were no changes requested for your account.'}), 200
elif len(updated) == 1:
output = updated[0]
elif len(updated) == 2:
output = ' and '.join(updated)
elif len(updated) > 2:
output = updated[0]
for index in range(1,len(updated)):
if index < len(updated) - 2:
output = ', '.join([output, updated[index]])
elif index == len(updated) - 2:
output = ', and '.join([output, updated[index]])
else:
output = ''.join([output, updated[index]])
db.tests.find_one_and_update({'_id': self._id}, {'$set': test})
_output = f'The {output} of the test {"has" if len(updated) == 1 else "have"} been updated.'
flash(_output)
return jsonify({'success': _output}), 200
def end(self):
now = datetime.now()
if self.end_date > now:
self.end_date = now
db.session.commit()
message = f'Test with code {self.code} ended by {current_user.get_username()}.'
write('system.log', message)
return True, jsonify({'success': message})
return False, jsonify({'error': f'Test with code {self.code} has already started.'})
def add_adjustment(self, time:int):
adjustments = self.adjustments if self.adjustments is not None else {}
code = secrets.token_hex(3).lower()
adjustments[code] = time
self.adjustments = adjustments
db.session.commit()
write('system.log', f'Time adjustment for {time} minutes with code {code} added to test {self.get_code()} by {current_user.get_username()}.')
return True, jsonify({'success': f'Time adjustment for {time} minutes added to test {self.get_code()}. This can be accessed using the user code {code.upper()}.'})
def remove_adjustment(self, code:str):
if not self.adjustments: return False, jsonify({'error': f'There are no adjustments configured for test {self.get_code()}.'})
self.adjustments.pop(code)
if not self.adjustments: self.adjustments = None
db.session.commit()
message = f'Time adjustment for with code {code} removed from test {self.get_code()} by {current_user.get_username()}.'
write('system.log', message)
return True, jsonify({'success': message})
def update(self, start_date:datetime=None, end_date:datetime=None, time_limit:int=None):
if not start_date and not end_date and time_limit is None: return False, jsonify({'error': 'There were no changes requested.'})
if start_date: self.start_date = start_date
if end_date: self.end_date = end_date
if time_limit is not None: self.time_limit = time_limit
db.session.commit()
message = f'Test with code {self.get_code()} has been updated by user {current_user.get_username()}'
write('system.log', message)
return True, jsonify({'success': message})