from flask import Blueprint, render_template, request, redirect, jsonify, session, abort, flash from flask.helpers import url_for from datetime import datetime from uuid import uuid4 import os from json import loads from main import app, db from common.security import encrypt from common.data_tools import generate_questions views = Blueprint( 'quiz_views', __name__, static_url_path='', template_folder='templates', static_folder='static' ) @views.route('/') @views.route('/home/') def home(): return render_template('/quiz/index.html') @views.route('/start/', methods = ['GET', 'POST']) def start(): from .forms import StartQuiz form = StartQuiz() if request.method == 'GET': return render_template('/quiz/start-quiz.html', form=form) if request.method == 'POST': if form.validate_on_submit(): name = { 'first_name': request.form.get('first_name'), 'surname': request.form.get('surname') } email = request.form.get('email') club = request.form.get('club') test_code = request.form.get('test_code').replace('—', '') user_code = request.form.get('user_code') user_code = None if user_code == '' else user_code if not db.tests.find_one({'test_code': test_code}): return jsonify({'error': 'The exam code you entered is invalid.'}), 400 entry = { '_id': uuid4().hex, 'name': encrypt(name), 'email': encrypt(email), 'club': encrypt(club), 'test_code': test_code, 'user_code': user_code, # 'start_time': datetime.utcnow(), TODO move start time to after configuration. # 'status': 'started' } if db.entries.insert(entry): session['_id'] = entry['_id'] # TODO Change this to return _id via JSON so client can access. Client will not be able to decrypt session cookie. return jsonify({ 'success': 'Received and validated test and/or user code. Redirecting to test client.', '_id': entry['_id'] }), 200 else: errors = [*form.errors] return jsonify({ 'error': errors}), 400 @views.route('/api/questions/', methods=['POST']) def fetch_questions(): _id = request.get_json()['_id'] entry = db.entries.find_one({'_id': _id}) if not entry: return abort(404) test_code = entry['test_code'] # user_code = entry['user_code'] TODO Implement functionality for adjustments test = db.tests.find_one({'test_code' : test_code}) dataset = test['dataset'] dataset_path = os.path.join(app.config['DATA_FILE_DIRECTORY'], dataset) with open(dataset_path, 'r') as data_file: data = loads(data_file.read()) questions = generate_questions(data) time_limit = test['time_limit'] return jsonify({ 'time_limit': time_limit, 'questions': questions }) @views.route('/test/') def start_quiz(): _id = session.get('_id') if not _id or not db.entries.find_one({'_id': _id}): flash('Your log in was not recognised. Please sign in to the quiz again.', 'error') return redirect(url_for('quiz_views.start')) return render_template('quiz/client.html') @views.route('/privacy/') def privacy(): return render_template('/quiz/privacy.html')