ska-referee-test/ref-test/app/tools/test.py

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, ConnectionError) 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