152 lines
5.8 KiB
Python
152 lines
5.8 KiB
Python
from .data import randomise_list
|
|
from ..models import Entry
|
|
from ..tools.logs import write
|
|
|
|
from flask import request, session
|
|
from flask.helpers import abort, redirect, url_for
|
|
from sqlalchemy.exc import SQLAlchemyError
|
|
|
|
from functools import wraps
|
|
|
|
def parse_test_code(code):
|
|
return code.replace('—', '').lower()
|
|
|
|
def generate_questions(dataset:list):
|
|
output = []
|
|
for block in randomise_list(dataset):
|
|
if block['type'] == 'question':
|
|
question = {
|
|
'type': 'question',
|
|
'q_no': block['q_no'],
|
|
'question_header': '',
|
|
'text': block['text']
|
|
}
|
|
if block['q_type'] == 'Multiple Choice': question['options'] = randomise_list([*enumerate(block['options'])])
|
|
else: question['options'] = [*enumerate(block['options'])]
|
|
output.append(question)
|
|
elif block['type'] == 'block':
|
|
for key, _question in enumerate(randomise_list(block['questions'])):
|
|
question = {
|
|
'type': 'block',
|
|
'q_no': _question['q_no'],
|
|
'question_header': block['question_header'] if 'question_header' in block else '',
|
|
'block_length': len(block['questions']),
|
|
'block_q_no': key,
|
|
'text': _question['text']
|
|
}
|
|
if _question['q_type'] == 'Multiple Choice': question['options'] = randomise_list([*enumerate(_question['options'])])
|
|
else: question['options'] = [*enumerate(_question['options'])]
|
|
output.append(question)
|
|
return output
|
|
|
|
def evaluate_answers(answers:dict, key:list):
|
|
score = 0
|
|
max = 0
|
|
tags = {}
|
|
for block in key:
|
|
if block['type'] == 'question':
|
|
max += 1
|
|
q_no = block['q_no']
|
|
if str(q_no) in answers:
|
|
submitted_answer = int(answers[str(q_no)])
|
|
if submitted_answer == block['correct']:
|
|
score += 1
|
|
for tag in block['tags']:
|
|
if tag not in tags:
|
|
tags[tag] = {
|
|
'scored': 1,
|
|
'max': 1
|
|
}
|
|
else:
|
|
tags[tag]['scored'] += 1
|
|
tags[tag]['max'] += 1
|
|
else:
|
|
for tag in block['tags']:
|
|
if tag not in tags:
|
|
tags[tag] = {
|
|
'scored': 0,
|
|
'max': 1
|
|
}
|
|
else: tags[tag]['max'] += 1
|
|
else:
|
|
for tag in block['tags']:
|
|
if tag not in tags:
|
|
tags[tag] = {
|
|
'scored': 0,
|
|
'max': 1
|
|
}
|
|
else: tags[tag]['max'] += 1
|
|
elif block['type'] == 'block':
|
|
for question in block['questions']:
|
|
max += 1
|
|
q_no = question['q_no']
|
|
if str(q_no) in answers:
|
|
submitted_answer = int(answers[str(q_no)])
|
|
if submitted_answer == question['correct']:
|
|
score += 1
|
|
for tag in question['tags']:
|
|
if tag not in tags:
|
|
tags[tag] = {
|
|
'scored': 1,
|
|
'max': 1
|
|
}
|
|
else:
|
|
tags[tag]['scored'] += 1
|
|
tags[tag]['max'] += 1
|
|
else:
|
|
for tag in question['tags']:
|
|
if tag not in tags:
|
|
tags[tag] = {
|
|
'scored': 0,
|
|
'max': 1
|
|
}
|
|
else: tags[tag]['max'] += 1
|
|
else:
|
|
for tag in question['tags']:
|
|
if tag not in tags:
|
|
tags[tag] = {
|
|
'scored': 0,
|
|
'max': 1
|
|
}
|
|
else: tags[tag]['max'] += 1
|
|
grade = 'merit' if score/max >= .85 else 'pass' if score/max >= .70 else 'fail'
|
|
return {
|
|
'grade': grade,
|
|
'tags': tags,
|
|
'score': score,
|
|
'max': max
|
|
}
|
|
|
|
def get_correct_answers(dataset:list):
|
|
output = {}
|
|
for block in dataset:
|
|
if block['type'] == 'question':
|
|
output[str(block['q_no'])] = block['correct']
|
|
if block['type'] == 'block':
|
|
for question in block['questions']:
|
|
output[str(question['q_no'])] = question['correct']
|
|
return output
|
|
|
|
def redirect_if_started(function):
|
|
@wraps(function)
|
|
def wrapper(*args, **kwargs):
|
|
id = session.get('id')
|
|
try:
|
|
if request.method == 'GET' and id and Entry.query.filter_by(id=id).first(): return redirect(url_for('quiz._quiz'))
|
|
except SQLAlchemyError as exception:
|
|
write('system.log', f'Database error when checking if test has been started: {exception}')
|
|
return abort(500)
|
|
return function(*args, **kwargs)
|
|
return wrapper
|
|
|
|
def answer_options(dataset:list):
|
|
output = []
|
|
for block in dataset:
|
|
if block['type'] == 'question':
|
|
question = block['options'].copy()
|
|
output.append(question)
|
|
elif block['type'] == 'block':
|
|
for _question in block['questions']:
|
|
question = _question['options'].copy()
|
|
output.append(question)
|
|
return output |