2021-11-24 17:17:56 +00:00
import secrets
from datetime import datetime
from uuid import uuid4
from flask import flash , jsonify
2021-11-25 20:12:50 +00:00
import secrets
2021-11-28 17:28:14 +00:00
import os
from json import dump , loads
2021-11-24 17:17:56 +00:00
2021-11-28 17:28:14 +00:00
from main import app , db
2021-11-28 02:30:46 +00:00
from common . security import encrypt
2021-11-24 17:17:56 +00:00
class Test :
2021-11-28 17:28:14 +00:00
def __init__ ( self , _id = None , start_date = None , expiry_date = None , time_limit = None , creator = None , dataset = None ) :
2021-11-24 17:17:56 +00:00
self . _id = _id
2021-11-25 20:12:50 +00:00
self . start_date = start_date
self . expiry_date = expiry_date
2021-12-01 08:26:08 +00:00
self . time_limit = None if time_limit == ' none ' or time_limit == ' ' or time_limit == None else int ( time_limit )
2021-11-24 17:17:56 +00:00
self . creator = creator
2021-11-28 17:28:14 +00:00
self . dataset = dataset
2021-11-24 17:17:56 +00:00
def create ( self ) :
test = {
' _id ' : self . _id ,
2021-11-25 20:12:50 +00:00
' date_created ' : datetime . today ( ) ,
' start_date ' : self . start_date ,
' expiry_date ' : self . expiry_date ,
2021-11-24 17:17:56 +00:00
' time_limit ' : self . time_limit ,
' creator ' : encrypt ( self . creator ) ,
2021-11-28 17:28:14 +00:00
' test_code ' : secrets . token_hex ( 6 ) . upper ( ) ,
' dataset ' : self . dataset
2021-11-24 17:17:56 +00:00
}
if db . tests . insert_one ( test ) :
2021-11-28 17:28:14 +00:00
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 )
2021-11-24 17:17:56 +00:00
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
2021-11-25 20:12:50 +00:00
def add_time_adjustment ( self , time_adjustment ) :
2021-12-04 15:41:47 +00:00
adjustment = {
2021-11-24 17:17:56 +00:00
' _id ' : uuid4 ( ) . hex ,
2021-12-04 15:41:47 +00:00
' user_code ' : secrets . token_hex ( 3 ) . upper ( ) ,
2021-11-24 17:17:56 +00:00
' time_adjustment ' : time_adjustment
}
2021-12-04 15:41:47 +00:00
if db . tests . find_one_and_update ( { ' _id ' : self . _id } , { ' $push ' : { ' time_adjustments ' : adjustment } } , upsert = False ) :
flash ( f ' Time adjustment for { adjustment [ " time_adjustment " ] } minutes has been added. This can be enabled using the user code { adjustment [ " user_code " ] } . ' )
return jsonify ( { ' success ' : adjustment } )
2021-11-25 20:12:50 +00:00
return jsonify ( { ' error ' : ' Failed to add the time adjustment. An error occurred. ' } ) , 400
def remove_time_adjustment ( self , _id ) :
if db . tests . find_one_and_update ( { ' _id ' : self . _id } , { ' $pull ' : { ' time_adjustments ' : { ' _id ' : _id } } } ) :
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
2021-11-24 17:17:56 +00:00
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 ) :
2021-11-25 20:12:50 +00:00
return test_code . replace ( ' — ' , ' ' )
def delete ( self ) :
2021-12-04 12:20:03 +00:00
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
2021-11-28 17:28:14 +00:00
if self . dataset is None :
self . dataset = db . tests . find_one ( { ' _id ' : self . _id } ) [ ' dataset ' ]
2021-11-25 20:12:50 +00:00
if db . tests . delete_one ( { ' _id ' : self . _id } ) :
2021-11-28 17:28:14 +00:00
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 )
2021-11-25 20:12:50 +00:00
message = ' Deleted exam. '
flash ( message , ' alert ' )
return jsonify ( { ' success ' : message } ) , 200
return jsonify ( { ' error ' : f ' Could not create exam. An error occurred. ' } ) , 400
def update ( self ) :
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 :
2021-11-30 18:06:24 +00:00
test [ ' time_limit ' ] = int ( self . time_limit )
2021-11-25 20:12:50 +00:00
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