Files
ska-referee-test/ref-test/app/quiz/views.py

110 lines
4.8 KiB
Python

from ..forms.quiz import StartQuiz
from ..models import Entry, Test
from ..tools.forms import send_errors_to_client
from ..tools.logs import write
from ..tools.test import redirect_if_started
from flask import Blueprint, jsonify, render_template, request, session
from flask.helpers import abort, flash, redirect, url_for
from datetime import datetime
quiz = Blueprint(
name='quiz',
import_name=__name__,
template_folder='templates',
static_folder='static',
static_url_path='/quiz/static'
)
@quiz.route('/')
@quiz.route('/home/')
@redirect_if_started
def _home():
return render_template('/quiz/index.html')
@quiz.route('/instructions/')
def _instructions():
return render_template('/quiz/instructions.html')
@quiz.route('/start/', methods=['GET', 'POST'])
def _start():
clubs = [
'Barrowland Bears Korfball Club',
'Dundee Korfball Club',
'Edinburgh City Korfball Club',
'Edinburgh Mavericks Korfball Club',
'Edinburgh University Korfball Club',
'Glasgow Korfball Club',
'Saint Andrews University Korfball Club',
'Strathclyde University Korfball Club'
]
try: entries = Entry.query.all()
except Exception as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
for entry in entries: clubs.append(entry.get_club())
clubs = list(set(clubs))
try: clubs.remove('')
except: pass
form = StartQuiz()
if request.method == 'POST':
if form.validate_on_submit():
entry = Entry()
entry.set_first_name(request.form.get('first_name'))
entry.set_surname(request.form.get('surname'))
entry.set_club(request.form.get('club'))
entry.set_email(request.form.get('email'))
code = request.form.get('test_code').replace('', '').lower()
try: test = Test.query.filter_by(code=code).first()
except Exception as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
if not test: return jsonify({'error': 'The exam code you entered is invalid.'}), 400
entry.test = test
entry.dataset = test.dataset
entry.user_code = request.form.get('user_code')
entry.user_code = None if entry.user_code == '' else entry.user_code.lower()
if entry.user_code and entry.user_code not in test.adjustments: return jsonify({'error': f'The user code you entered is not valid.'}), 400
if test.end_date < datetime.now(): return jsonify({'error': f'The exam code you entered expired on {test["expiry_date"].strftime("%d %b %Y %H:%M")}.'}), 400
if test.start_date > datetime.now(): return jsonify({'error': f'The exam has not yet opened. Your exam code will be valid from {test["start_date"].strftime("%d %b %Y %H:%M")}.'}), 400
success, message = entry.ready()
if success:
session['id'] = entry.id
return jsonify({
'success': 'Received and validated test and/or user code. Redirecting to test client.',
'id': entry.id
}), 200
return jsonify({'error': 'There was an error processing the user test and/or user codes.'}), 400
return send_errors_to_client(form=form)
return render_template('/quiz/start_quiz.html', form = form, clubs = clubs)
@quiz.route('/quiz/')
def _quiz():
id = session.get('id')
try:
if not id or not Entry.query.filter_by(id=id).first():
flash('Your session was not recognised. Please sign in to the quiz again.', 'error')
session.pop('id', None)
return redirect(url_for('quiz._start'))
except Exception as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
return render_template('/quiz/client.html')
@quiz.route('/result/')
def _result():
id = session.get('id')
try: entry = Entry.query.filter_by(id=id).first()
except Exception as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
if not entry: return abort(404)
session.pop('id',None)
score = round(100*entry.result['score']/entry.result['max'])
tags_low = { tag: tag_result['max'] - tag_result['scored'] for tag, tag_result in entry.result['tags'].items() }
sorted_low_tags = sorted(tags_low.items(), key=lambda x: x[1], reverse=True)
tag_output = [ tag[0] for tag in sorted_low_tags[0:3] if tag[1] > 3]
if not entry.status == 'late':
entry.notify_result()
return render_template('/quiz/result.html', entry=entry, score=score, tag_output=tag_output)