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