Finish script cleanup: PEP8, PEP257
This commit is contained in:
parent
021398c573
commit
0b7faf8784
@ -1,71 +1,202 @@
|
||||
from flask import Flask, render_template, request, redirect, url_for
|
||||
from wtforms import Form, StringField, SelectField, RadioField, TextAreaField, BooleanField, validators
|
||||
"""A script for the Sortierhut Game
|
||||
|
||||
Based on the Flask and WTForms web frameworks.
|
||||
"""
|
||||
|
||||
__version__ = '0.0'
|
||||
__author__ = 'aamma, asauer'
|
||||
|
||||
import uuid
|
||||
import csv
|
||||
import os
|
||||
|
||||
from flask import Flask, render_template, request, redirect, url_for
|
||||
from wtforms import Form, StringField, SelectField, RadioField, TextAreaField, BooleanField, validators
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
app.jinja_env.trim_blocks = True
|
||||
app.jinja_env.lstrip_blocks = True
|
||||
|
||||
|
||||
datafile = "data.csv"
|
||||
solutionfile = "solutions.csv"
|
||||
datafile = 'data.csv'
|
||||
solutionfile = 'solutions.csv'
|
||||
|
||||
|
||||
def create_used_id_list():
|
||||
"""Read datafile and create a list of the id in each row.
|
||||
|
||||
Useful to compare if a given id is already used.
|
||||
"""
|
||||
data = list()
|
||||
if not os.path.exists(datafile):
|
||||
open(datafile, 'a').close()
|
||||
|
||||
with open(datafile, 'r') as f:
|
||||
reader = csv.reader(f)
|
||||
|
||||
for line in reader:
|
||||
# line[0] is the row's id
|
||||
data.append(line[0])
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def convert_csv_to_list_of_lists(csv_file):
|
||||
"""Convert a csv file to a list whose items are lists.
|
||||
|
||||
csv_file -- a valid comma-separated file.
|
||||
|
||||
Useful because a list of lists can be easily iterated.
|
||||
"""
|
||||
list_of_lists = list()
|
||||
|
||||
if not os.path.exists(csv_file):
|
||||
open(csv_file, 'a').close()
|
||||
|
||||
with open(csv_file, 'r', newline='') as f:
|
||||
reader = csv.reader(f)
|
||||
|
||||
for line in reader:
|
||||
list_of_lists.append(line)
|
||||
|
||||
return list_of_lists
|
||||
|
||||
|
||||
def check_input(form, field):
|
||||
"""Check if a SelectField from the questions() is still in default mode.
|
||||
|
||||
form -- the form on which this function is called (instance of QuestionForm).
|
||||
field -- the form field whose input is checked.
|
||||
"""
|
||||
if field.data == 'default':
|
||||
raise validators.ValidationError('Bitte wähle eine Option aus')
|
||||
|
||||
|
||||
class QuestionForm(Form):
|
||||
computers = [('default', 'Bitte auswählen'), ('hal', 'HAL 9000 (2001: Odyssee im Weltraum)'), ('deepthought', 'Deep Thought (Hitchhiker\'s Guide)'), ('neuromancer', 'Neuromancer (Neuromancer)'), ('samantha', 'Samatha (Her)'), ('tars', 'TARS und CASE (Interstellar)')]
|
||||
computer = SelectField(u'Fiktionaler Lieblingscomputer', choices=computers, validators=[validators.InputRequired(), check_input])
|
||||
statuses = [('default', 'Bitte auswählen'), ('200', '200 OK'), ('300', '300 Multiple Choices'), ('301', '301 Moved Permanently'), ('402', '402 Payment Required'), ('404', '404 (Sleep) Not Found'), ('408', '408 Request Timeout'), ('418', '418 I am a teapot'), ('450', '450 Blocked by Windows Parental Controls'), ('451', '451 Unavailable For Legal Reasons'), ('502', '502 Bad Gateway (Internetkurort)')]
|
||||
status = SelectField(u'Welcher HTTP-Statuscode trifft am häufigsten auf dich zu?', choices=statuses, validators=[validators.InputRequired(), check_input])
|
||||
vegetables = [('default', 'Bitte auswählen'), ('karotte', '🥕'), ('broccoli','🥦'), ('aubergine', '🍆'), ('kartoffel', '🥔'), ('bretzel', '🥨'), ('tomate', '🍅'), ('chili', '🌶️')]
|
||||
vegetable = SelectField(u'Lieblingsgemüse', choices=vegetables, validators=[validators.InputRequired(), check_input])
|
||||
spirit_animals = [('default', 'Bitte auswählen'), ('feuer', 'Feuerfuchs'), ('wasser', 'Wasserhahn'), ('erde', 'Erdferkel'), ('luft', 'Luftschlange')]
|
||||
spirit_animal = SelectField(u'Spirit Animal', choices=spirit_animals, validators=[validators.InputRequired(), check_input])
|
||||
operating_systems = [('default', 'Bitte auswählen'), ('windows', 'Windows'), ('mac', 'Mac'), ('linux', 'Linux'), ('kaffee', 'Kaffee'), ('glados', 'GLaDOS')]
|
||||
operating_system = SelectField(u'Bevorzugtes Betriebssystem', choices=operating_systems, validators=[validators.InputRequired(), check_input])
|
||||
check = BooleanField('Bitte nicht ankreuzen')
|
||||
|
||||
|
||||
class SolutionForm(Form):
|
||||
user_id = StringField('id', [validators.InputRequired()])
|
||||
choices = [('computer', 'Fiktionaler Lieblingscomputer'), ('status', 'HTTP-Statuscode'), ('vegetable', 'Lieblingsgemüse'), ('spirit_animal', 'Spirit Animal'), ('operating system', 'Betriebssystem'), ('check', 'Bitte nicht ankreuzen')]
|
||||
question = RadioField(u'Welche Frage ist ausschlaggebend für die Hauszuordnung?', choices=choices, validators=[validators.InputRequired(message='Bitte ankreuzen'),])
|
||||
solution_text = TextAreaField(u'Textfeld')
|
||||
|
||||
def create_used_id_list():
|
||||
data = list()
|
||||
if not os.path.exists(datafile):
|
||||
open(datafile, "a").close()
|
||||
|
||||
with open(datafile, "r") as f:
|
||||
reader = csv.reader(f)
|
||||
for line in reader:
|
||||
data.append(line[0])
|
||||
return data
|
||||
|
||||
def check_id(form, field):
|
||||
"""Check if the datafile contains a given id.
|
||||
|
||||
form -- the form on which this function is called (instance of AnswerForm).
|
||||
field -- the id input field whose input is checked.
|
||||
"""
|
||||
used_ids = create_used_id_list()
|
||||
if field.data not in used_ids:
|
||||
raise validators.ValidationError('Leider keine gültige ID')
|
||||
|
||||
|
||||
class QuestionForm(Form):
|
||||
"""A form of humorous questions."""
|
||||
computers = [
|
||||
('default', 'Bitte auswählen'),
|
||||
('hal', 'HAL 9000 (2001: Odyssee im Weltraum)'),
|
||||
('deepthought', 'Deep Thought (Hitchhiker\'s Guide)'),
|
||||
('neuromancer', 'Neuromancer (Neuromancer)'),
|
||||
('samantha', 'Samatha (Her)'),
|
||||
('tars', 'TARS und CASE (Interstellar)')
|
||||
]
|
||||
statuses = [
|
||||
('default', 'Bitte auswählen'),
|
||||
('200', '200 OK'),
|
||||
('300', '300 Multiple Choices'),
|
||||
('301', '301 Moved Permanently'),
|
||||
('402', '402 Payment Required'),
|
||||
('404', '404 (Sleep) Not Found'),
|
||||
('408', '408 Request Timeout'),
|
||||
('418', '418 I am a teapot'),
|
||||
('450', '450 Blocked by Windows Parental Controls'),
|
||||
('451', '451 Unavailable For Legal Reasons'),
|
||||
('502', '502 Bad Gateway (Internetkurort)')
|
||||
]
|
||||
vegetables = [
|
||||
('default', 'Bitte auswählen'),
|
||||
('karotte', '🥕 Karotte'),
|
||||
('broccoli','🥦 Brokkoli'),
|
||||
('aubergine', '🍆 Aubergine'),
|
||||
('kartoffel', '🥔 Kartoffel'),
|
||||
('bretzel', '🥨 Bretzel'),
|
||||
('tomate', '🍅 Tomate'),
|
||||
('chili', '🌶️ Chili')
|
||||
]
|
||||
spirit_animals = [
|
||||
('default', 'Bitte auswählen'),
|
||||
('feuer', 'Feuerfuchs'),
|
||||
('wasser', 'Wasserhahn'),
|
||||
('erde', 'Erdferkel'),
|
||||
('luft', 'Luftschlange')
|
||||
]
|
||||
operating_systems = [
|
||||
('default', 'Bitte auswählen'),
|
||||
('windows', 'Windows'),
|
||||
('mac', 'Mac'),
|
||||
('linux', 'Linux'),
|
||||
('kaffee', 'Kaffee'),
|
||||
('glados', 'GLaDOS')
|
||||
]
|
||||
|
||||
computer = SelectField(u'Fiktionaler Lieblingscomputer', choices=computers,
|
||||
validators=[validators.InputRequired(), check_input])
|
||||
status = SelectField(u'Welcher HTTP-Statuscode trifft am häufigsten auf dich zu?',
|
||||
choices=statuses,
|
||||
validators=[validators.InputRequired(), check_input])
|
||||
vegetable = SelectField(u'Lieblingsgemüse', choices=vegetables,
|
||||
validators=[validators.InputRequired(), check_input])
|
||||
spirit_animal = SelectField(u'Spirit Animal', choices=spirit_animals,
|
||||
validators=[validators.InputRequired(), check_input])
|
||||
operating_system = SelectField(u'Bevorzugtes Betriebssystem', choices=operating_systems,
|
||||
validators=[validators.InputRequired(), check_input])
|
||||
check = BooleanField('Bitte nicht ankreuzen')
|
||||
|
||||
|
||||
class AnswerForm(Form):
|
||||
"""A form for a user_id as a sort of password."""
|
||||
user_id = StringField('Id', [validators.InputRequired(), check_id])
|
||||
|
||||
|
||||
class SolutionForm(Form):
|
||||
"""A form for a solution idea for the Sortierhut riddle."""
|
||||
choices = [
|
||||
('computer', 'Fiktionaler Lieblingscomputer'),
|
||||
('status', 'HTTP-Statuscode'),
|
||||
('vegetable', 'Lieblingsgemüse'),
|
||||
('spirit_animal', 'Spirit Animal'),
|
||||
('operating system', 'Betriebssystem'),
|
||||
('check', 'Bitte nicht ankreuzen')
|
||||
]
|
||||
|
||||
user_id = StringField('id', [validators.InputRequired(),])
|
||||
question = RadioField(choices=choices, validators=[validators.InputRequired(),])
|
||||
solution_text = TextAreaField(u'Textfeld')
|
||||
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
"""Display a home page with an explanation and many navigation links."""
|
||||
return render_template('index.html', title='Sortierhut')
|
||||
|
||||
|
||||
@app.route('/questions', methods=['GET', 'POST'])
|
||||
def questions():
|
||||
"""Display a form with some questions.
|
||||
|
||||
Raise ValidationError and stay on questions() page
|
||||
if any of the dropdown fields are still in the default position on
|
||||
"Bitte auswählen".
|
||||
|
||||
Else redirect to result().
|
||||
"""
|
||||
def generate_id():
|
||||
"""Generate a new unique user id."""
|
||||
data = create_used_id_list()
|
||||
# best loop ever
|
||||
while True:
|
||||
new_id = str(uuid.uuid1()).split('-')[0]
|
||||
if new_id in data:
|
||||
break
|
||||
else:
|
||||
return new_id
|
||||
|
||||
form = QuestionForm(request.form)
|
||||
# Assign a number to each house
|
||||
houses = dict()
|
||||
houses[0] = 'knuth'
|
||||
houses[1] = 'lovelace'
|
||||
@ -74,97 +205,139 @@ def questions():
|
||||
houses[8] = 'lamarr'
|
||||
|
||||
if request.method == 'POST' and form.validate():
|
||||
with open(datafile, "a", newline='') as f:
|
||||
with open(datafile, 'a', newline='') as f:
|
||||
new_row = list()
|
||||
new_id = generate_id()
|
||||
new_row.append(new_id)
|
||||
|
||||
for item in request.form:
|
||||
new_row.append(request.form[item])
|
||||
|
||||
# If the BooleanField is not checked,
|
||||
# the request.form dict does not contain an entry for 'check'
|
||||
if len(new_row) == 6:
|
||||
new_row.append('n')
|
||||
|
||||
|
||||
# This is the riddle's kern:
|
||||
# Compute the mod 10 of the selected http status code
|
||||
# and this then determines the sorting
|
||||
magical_house_number = int(new_row[2]) % 10
|
||||
new_row.append(houses[magical_house_number])
|
||||
|
||||
writer = csv.writer(f)
|
||||
writer.writerow(new_row)
|
||||
|
||||
return redirect(url_for('result', user_id=new_id))
|
||||
|
||||
return render_template('questions.html', form=form, title='Sortierhut')
|
||||
|
||||
@app.route('/submit_solution', methods=['GET', 'POST'])
|
||||
def submit_solution():
|
||||
form = SolutionForm(request.form)
|
||||
if request.method == 'POST' and form.validate():
|
||||
with open(solutionfile, "a", newline='') as f:
|
||||
solution_list = list()
|
||||
for item in request.form:
|
||||
solution_list.append(request.form[item])
|
||||
writer = csv.writer(f)
|
||||
writer.writerow(solution_list)
|
||||
return redirect(url_for('thanks'))
|
||||
return render_template('submit_solution.html', form=form, title='Sortierhut')
|
||||
|
||||
@app.route('/result<user_id>')
|
||||
def result(user_id):
|
||||
"""Display the user's id and a comment on what to do next.
|
||||
|
||||
user_id -- argument passed by redirect call in the questions() function.
|
||||
|
||||
Only called in questions().
|
||||
"""
|
||||
return render_template('result.html', title='Sortierhut', id=user_id)
|
||||
|
||||
def convert_csv_to_list_of_lists(csv_file):
|
||||
list_of_lists = list()
|
||||
|
||||
if not os.path.exists(csv_file):
|
||||
open(csv_file, 'a').close()
|
||||
|
||||
with open(csv_file, 'r', newline='') as f:
|
||||
reader = csv.reader(f)
|
||||
for line in reader:
|
||||
list_of_lists.append(line)
|
||||
return list_of_lists
|
||||
|
||||
@app.route('/admint_form')
|
||||
def admin_form():
|
||||
file_data = convert_csv_to_list_of_lists(datafile)
|
||||
return render_template('admin_form.html', title='Sortierhut', text='Hallo, Admin Fooboar', file_data=file_data)
|
||||
|
||||
@app.route('/admint_solution')
|
||||
def admin_solution():
|
||||
file_data = convert_csv_to_list_of_lists(solutionfile)
|
||||
return render_template('admin_solution.html', title='Sortierhut', file_data=file_data)
|
||||
|
||||
@app.route('/answers', methods=['GET', 'POST'])
|
||||
def access_answers():
|
||||
"""Display a form for an id that is needed to access the corresponded answers.
|
||||
|
||||
Raise ValidationError and stay on access_answers() page
|
||||
if no id is submitted or the id is not valid.
|
||||
|
||||
Else redirect to view_answers() page.
|
||||
"""
|
||||
form = AnswerForm(request.form)
|
||||
|
||||
if request.method == 'POST' and form.validate():
|
||||
ident = request.form['user_id']
|
||||
return redirect(url_for('view_access_answers', user_id=ident))
|
||||
return redirect(url_for('view_answers', user_id=ident))
|
||||
|
||||
return render_template('access_answers.html', form=form, title='Sortierhut')
|
||||
|
||||
|
||||
@app.route('/view_answers<user_id>')
|
||||
def view_answers(user_id):
|
||||
"""Display the user's answers.
|
||||
|
||||
user_id -- argument passed by the redirect call in the access_answers() function.
|
||||
|
||||
Only called in access_answers().
|
||||
"""
|
||||
# Create list object to be filled with the datafile row matching the user_id
|
||||
user_row = list()
|
||||
with open(datafile, "r", newline='') as f:
|
||||
|
||||
with open(datafile, 'r', newline='') as f:
|
||||
reader = csv.reader(f)
|
||||
|
||||
for line in reader:
|
||||
# line[0] is the row's id
|
||||
if line[0] == user_id:
|
||||
user_row = line
|
||||
break
|
||||
return render_template('view_answers.html', title='Sortierhut', user_id=user_id, user_row=user_row)
|
||||
|
||||
return render_template('view_answers.html', title='Sortierhut',
|
||||
user_id=user_id, user_row=user_row)
|
||||
|
||||
|
||||
@app.route('/submit_solution', methods=['GET', 'POST'])
|
||||
def submit_solution():
|
||||
"""Display a form for solution ideas.
|
||||
|
||||
Raise ValidationError and stay on submit_solution() page
|
||||
if the form input is not valid.
|
||||
|
||||
Else redirect to thanks() page.
|
||||
"""
|
||||
form = SolutionForm(request.form)
|
||||
|
||||
if request.method == 'POST' and form.validate():
|
||||
with open(solutionfile, 'a', newline='') as f:
|
||||
solution_list = list()
|
||||
|
||||
# Transfer input data from request.form dict to solution_list list
|
||||
for item in request.form:
|
||||
solution_list.append(request.form[item])
|
||||
|
||||
writer = csv.writer(f)
|
||||
writer.writerow(solution_list)
|
||||
|
||||
return redirect(url_for('thanks'))
|
||||
|
||||
return render_template('submit_solution.html', form=form, title='Sortierhut')
|
||||
|
||||
|
||||
@app.route('/thanks')
|
||||
def thanks():
|
||||
"""Display how the right solution will be announced.
|
||||
|
||||
Only called in submit_solution().
|
||||
"""
|
||||
return render_template('thanks.html', title='Sortierhut')
|
||||
|
||||
|
||||
@app.route('/houses')
|
||||
def houses():
|
||||
"""Display a description of the 5 groups (=houses)."""
|
||||
return render_template('houses.html', title='Sortierhut')
|
||||
|
||||
def generate_id():
|
||||
data = create_used_id_list()
|
||||
# best loop ever
|
||||
while True:
|
||||
new_id = str(uuid.uuid1()).split("-")[0]
|
||||
|
||||
if new_id in data:
|
||||
break
|
||||
else:
|
||||
return new_id
|
||||
@app.route('/admint_form')
|
||||
def admin_form():
|
||||
"""Display a table of the data from submitted question form."""
|
||||
file_data = convert_csv_to_list_of_lists(datafile)
|
||||
return render_template('admin_form.html', title='Sortierhut',
|
||||
text='Hallo, Admin Fooboar', file_data=file_data)
|
||||
|
||||
|
||||
@app.route('/admint_solution')
|
||||
def admin_solution():
|
||||
"""Display a table of the submitted solutions."""
|
||||
file_data = convert_csv_to_list_of_lists(solutionfile)
|
||||
return render_template('admin_solution.html', title='Sortierhut', file_data=file_data)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user