From 6a3f42ea09cc6c875ead1ecd8d63e19a958c63f1 Mon Sep 17 00:00:00 2001 From: Burathar Date: Wed, 29 Jul 2020 11:32:18 +0200 Subject: [PATCH] Move game settings into separate blueprint --- .gitignore | 3 +- app/__init__.py | 3 + app/game_settings/__init__.py | 5 + app/game_settings/forms.py | 45 +++++++ app/game_settings/routes.py | 109 ++++++++++++++++ app/main/forms.py | 45 +------ app/main/routes.py | 107 +--------------- .../{ => game_settings}/create_game.html | 0 .../{ => game_settings}/edit_game.html | 0 database_dump.txt | 121 ------------------ 10 files changed, 169 insertions(+), 269 deletions(-) create mode 100644 app/game_settings/__init__.py create mode 100644 app/game_settings/forms.py create mode 100644 app/game_settings/routes.py rename app/templates/{ => game_settings}/create_game.html (100%) rename app/templates/{ => game_settings}/edit_game.html (100%) delete mode 100644 database_dump.txt diff --git a/.gitignore b/.gitignore index 871ffb8..fc7b7a8 100644 --- a/.gitignore +++ b/.gitignore @@ -145,4 +145,5 @@ cython_debug/ # the-hunt specific: logs/ app.db -uploads/ \ No newline at end of file +uploads/ +database_dump.txt \ No newline at end of file diff --git a/app/__init__.py b/app/__init__.py index 674f8f4..5830ec1 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -41,6 +41,9 @@ def create_app(config_class=Config): from app.auth import bp as auth_bp app.register_blueprint(auth_bp, url_prefix='/auth') + from app.game_settings import bp as game_settings_bp + app.register_blueprint(game_settings_bp) + from app.main import bp as main_bp app.register_blueprint(main_bp) diff --git a/app/game_settings/__init__.py b/app/game_settings/__init__.py new file mode 100644 index 0000000..d123274 --- /dev/null +++ b/app/game_settings/__init__.py @@ -0,0 +1,5 @@ +from flask import Blueprint + +bp = Blueprint('game', __name__) + +from app.game_settings import handlers diff --git a/app/game_settings/forms.py b/app/game_settings/forms.py new file mode 100644 index 0000000..d6bea01 --- /dev/null +++ b/app/game_settings/forms.py @@ -0,0 +1,45 @@ +from flask_wtf import FlaskForm +from wtforms import StringField, SubmitField, DateTimeField, BooleanField, HiddenField +from wtforms.validators import InputRequired, DataRequired, ValidationError, Length +from pytz import timezone +from app.models import Game + +class CreateGameForm(FlaskForm): + game_name = StringField('Game Name', validators=[InputRequired(), Length(min=0, max=64)]) + start_time_disabled = BooleanField('No start time') + start_time = DateTimeField(id='datetimepicker_start', format="%d-%m-%Y %H:%M") + end_time_disabled = BooleanField('No end time') + end_time = DateTimeField(id='datetimepicker_end', format="%d-%m-%Y %H:%M") + timezone = HiddenField(validators=[DataRequired()]) + submit = SubmitField('Create') + old_name = '' + + def validate_start_time(self, start_time): + self.date_time_validator(self.start_time_disabled, start_time) + + def validate_end_time(self, end_time): + self.date_time_validator(self.end_time_disabled, end_time) + if self.start_time.data and end_time.data: + if self.start_time.data > end_time.data: + raise ValidationError('Start Time must be before End Time.') + + def date_time_validator(self, disabled, date_time): + print(1) + if disabled.data: + date_time.data = None + return + clientzone = timezone(self.timezone.data) + print(clientzone) + print(date_time.data) + date_time_utc = clientzone.localize(date_time.data).astimezone(timezone('UTC')) + date_time.data = date_time_utc + print(date_time.data) + + def validate_game_name(self, game_name): + if game_name.data == '': + return + if game_name.data == self.old_name: + return + game = Game.query.filter_by(name=game_name.data).first() + if game is not None: + raise ValidationError('Please use a different name.') diff --git a/app/game_settings/routes.py b/app/game_settings/routes.py new file mode 100644 index 0000000..bf8b549 --- /dev/null +++ b/app/game_settings/routes.py @@ -0,0 +1,109 @@ +from flask import render_template, flash, redirect, url_for, request +from flask_login import login_required, current_user +from app import db +from app.models import Game, GamePlayer, Role +from app.utils import flash_errors, get_game_if_owner +from app.game_settings import bp +from app.game_settings.forms import CreateGameForm + +@bp.route('/create_game', methods=['GET', 'POST']) +@login_required +def create_game(): + form = CreateGameForm() + + if form.validate_on_submit(): + game = Game(name=form.game_name.data, + start_time=form.start_time.data, + end_time=form.end_time.data) + game.players.append(GamePlayer(user=current_user, role=Role['owner'])) + db.session.add(game) + db.session.commit() + flash(f"'{game.name}' had been created!") + return redirect(url_for('main.game_dashboard', game_name=game.name)) + else: + flash_errors(form) + return render_template('game_settings.create_game.html', title='Create Game', form=form) + +@bp.route('/game//change_settings', methods=['GET', 'POST']) +@login_required +def change_game_settings(game_name): + game = get_game_if_owner(game_name) + + form = CreateGameForm() + form.old_name = game.name + + if request.method == 'GET': + # pylint: disable=no-member + form.process() + form.game_name.data = game.name + if game.start_time: + form.start_time.data = game.start_time + else: + form.start_time_disabled.data = True + form.start_time.data = None + if game.end_time: + form.end_time.data = game.end_time + else: + form.end_time_disabled.data = True + form.end_time.data = None + + if form.validate_on_submit(): + game.name = form.game_name.data + game.start_time = form.start_time.data + game.end_time = form.end_time.data + db.session.commit() + flash(f"'{game.name}' had been updated!") + return redirect(url_for('main.game_dashboard', game_name=game.name)) + else: + flash_errors(form) + return render_template('game_settings.edit_game.html', title='Chage Game Settings', form=form, game=game) + +@bp.route('/game//delete') +@login_required +def delete_game(game_name): + game = get_game_if_owner(game_name) + db.session.delete(game) + for user in game.users: + if not user.last_login: + db.session.delete(user) + db.session.commit() + flash(f"Game '{game.name}' has been deleted!") + return redirect(url_for('main.index')) + +@bp.route('/game//unhide') +@bp.route('/game//publish') +@login_required +def publish_game(game_name): + game = get_game_if_owner(game_name) + game.hidden = False + db.session.commit() + flash(f"Game '{game.name}' has been published!") + return redirect(url_for('main.game_dashboard', game_name=game.name)) + +@bp.route('/game//hide') +@login_required +def hide_game(game_name): + game = get_game_if_owner(game_name) + game.hidden = True + db.session.commit() + flash(f"Game '{game.name}' has been hidden!") + return redirect(url_for('main.game_dashboard', game_name=game.name)) + +@bp.route('/game//pause') +@login_required +def pause_game(game_name): + game = get_game_if_owner(game_name) + game.paused = True + db.session.commit() + flash(f"Game '{game.name}' has been paused!") + return redirect(url_for('main.game_dashboard', game_name=game.name)) + +@bp.route('/game//unpause') +@bp.route('/game//resume') +@login_required +def resume_game(game_name): + game = get_game_if_owner(game_name) + game.paused = False + db.session.commit() + flash(f"Game '{game.name}' has been resumed!") + return redirect(url_for('main.game_dashboard', game_name=game.name)) diff --git a/app/main/forms.py b/app/main/forms.py index 75cacb5..5f5c305 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -1,51 +1,10 @@ from flask_wtf import FlaskForm from flask_wtf.file import FileField, FileAllowed, FileRequired -from wtforms import StringField, SubmitField, DateTimeField, BooleanField, HiddenField, FloatField, SelectField +from wtforms import StringField, SubmitField, FloatField, SelectField from wtforms.validators import InputRequired, DataRequired, ValidationError, Length, NumberRange -from pytz import timezone -from app.models import Objective, Game +from app.models import Objective from app import Config -class CreateGameForm(FlaskForm): - game_name = StringField('Game Name', validators=[InputRequired(), Length(min=0, max=64)]) - start_time_disabled = BooleanField('No start time') - start_time = DateTimeField(id='datetimepicker_start', format="%d-%m-%Y %H:%M") - end_time_disabled = BooleanField('No end time') - end_time = DateTimeField(id='datetimepicker_end', format="%d-%m-%Y %H:%M") - timezone = HiddenField(validators=[DataRequired()]) - submit = SubmitField('Create') - old_name = '' - - def validate_start_time(self, start_time): - self.date_time_validator(self.start_time_disabled, start_time) - - def validate_end_time(self, end_time): - self.date_time_validator(self.end_time_disabled, end_time) - if self.start_time.data and end_time.data: - if self.start_time.data > end_time.data: - raise ValidationError('Start Time must be before End Time.') - - def date_time_validator(self, disabled, date_time): - print(1) - if disabled.data: - date_time.data = None - return - clientzone = timezone(self.timezone.data) - print(clientzone) - print(date_time.data) - date_time_utc = clientzone.localize(date_time.data).astimezone(timezone('UTC')) - date_time.data = date_time_utc - print(date_time.data) - - def validate_game_name(self, game_name): - if game_name.data == '': - return - if game_name.data == self.old_name: - return - game = Game.query.filter_by(name=game_name.data).first() - if game is not None: - raise ValidationError('Please use a different name.') - class ObjectiveForm(FlaskForm): objective_name = StringField('Objective Name', validators=[Length(min=0, max=64)]) latitude = FloatField('Latitude', validators=[DataRequired(), NumberRange(min=-90, max=90)]) diff --git a/app/main/routes.py b/app/main/routes.py index 5a4872c..0b6e26a 100644 --- a/app/main/routes.py +++ b/app/main/routes.py @@ -12,10 +12,10 @@ from sqlalchemy import and_ from app import db from app.main import bp -from app.utils import generate_qr_code, serve_pil_image, flash_errors, get_game_if_owner -from app.models import User, Game, Role, GamePlayer, GameState, Objective, ObjectiveMinimalEncoder,\ +from app.utils import generate_qr_code, serve_pil_image, get_game_if_owner +from app.models import User, Game, Role, GamePlayer, Objective, ObjectiveMinimalEncoder,\ LocationEncoder, PlayerCaughtPlayer, Review, Location -from app.main.forms import CreateGameForm, ObjectiveForm, PlayerAddForm, UserCreateForm, \ +from app.main.forms import ObjectiveForm, PlayerAddForm, UserCreateForm, \ PlayerUpdateForm, CatchBunnyForm @bp.before_app_request @@ -32,107 +32,6 @@ def index(): return redirect(url_for('main.game_dashboard', game_name=current_user.games[0].name)) return render_template("index.html", title='Home') -@bp.route('/create_game', methods=['GET', 'POST']) -@login_required -def create_game(): - form = CreateGameForm() - - if form.validate_on_submit(): - game = Game(name=form.game_name.data, - start_time=form.start_time.data, - end_time=form.end_time.data) - game.players.append(GamePlayer(user=current_user, role=Role['owner'])) - db.session.add(game) - db.session.commit() - flash(f"'{game.name}' had been created!") - return redirect(url_for('main.game_dashboard', game_name=game.name)) - else: - flash_errors(form) - return render_template('create_game.html', title='Create Game', form=form) - -@bp.route('/game//change_settings', methods=['GET', 'POST']) -@login_required -def change_game_settings(game_name): - game = get_game_if_owner(game_name) - - form = CreateGameForm() - form.old_name = game.name - - if request.method == 'GET': - # pylint: disable=no-member - form.process() - form.game_name.data = game.name - if game.start_time: - form.start_time.data = game.start_time - else: - form.start_time_disabled.data = True - form.start_time.data = None - if game.end_time: - form.end_time.data = game.end_time - else: - form.end_time_disabled.data = True - form.end_time.data = None - - if form.validate_on_submit(): - game.name = form.game_name.data - game.start_time = form.start_time.data - game.end_time = form.end_time.data - db.session.commit() - flash(f"'{game.name}' had been updated!") - return redirect(url_for('main.game_dashboard', game_name=game.name)) - else: - flash_errors(form) - return render_template('edit_game.html', title='Chage Game Settings', form=form, game=game) - -@bp.route('/game//delete') -@login_required -def delete_game(game_name): - game = get_game_if_owner(game_name) - db.session.delete(game) - for user in game.users: - if not user.last_login: - db.session.delete(user) - db.session.commit() - flash(f"Game '{game.name}' has been deleted!") - return redirect(url_for('main.index')) - -@bp.route('/game//unhide') -@bp.route('/game//publish') -@login_required -def publish_game(game_name): - game = get_game_if_owner(game_name) - game.hidden = False - db.session.commit() - flash(f"Game '{game.name}' has been published!") - return redirect(url_for('main.game_dashboard', game_name=game.name)) - -@bp.route('/game//hide') -@login_required -def hide_game(game_name): - game = get_game_if_owner(game_name) - game.hidden = True - db.session.commit() - flash(f"Game '{game.name}' has been hidden!") - return redirect(url_for('main.game_dashboard', game_name=game.name)) - -@bp.route('/game//pause') -@login_required -def pause_game(game_name): - game = get_game_if_owner(game_name) - game.paused = True - db.session.commit() - flash(f"Game '{game.name}' has been paused!") - return redirect(url_for('main.game_dashboard', game_name=game.name)) - -@bp.route('/game//unpause') -@bp.route('/game//resume') -@login_required -def resume_game(game_name): - game = get_game_if_owner(game_name) - game.paused = False - db.session.commit() - flash(f"Game '{game.name}' has been resumed!") - return redirect(url_for('main.game_dashboard', game_name=game.name)) @bp.route('/game//dashboard') diff --git a/app/templates/create_game.html b/app/templates/game_settings/create_game.html similarity index 100% rename from app/templates/create_game.html rename to app/templates/game_settings/create_game.html diff --git a/app/templates/edit_game.html b/app/templates/game_settings/edit_game.html similarity index 100% rename from app/templates/edit_game.html rename to app/templates/game_settings/edit_game.html diff --git a/database_dump.txt b/database_dump.txt deleted file mode 100644 index b78e4de..0000000 --- a/database_dump.txt +++ /dev/null @@ -1,121 +0,0 @@ -PRAGMA foreign_keys=OFF; -BEGIN TRANSACTION; -CREATE TABLE alembic_version ( - version_num VARCHAR(32) NOT NULL, - CONSTRAINT alembic_version_pkc PRIMARY KEY (version_num) -); -INSERT INTO alembic_version VALUES('3ef4c34115fd'); -CREATE TABLE game ( - id INTEGER NOT NULL, - name VARCHAR(64) NOT NULL, - state VARCHAR(11) DEFAULT 'hidden' NOT NULL, - start_time DATETIME, - end_time DATETIME, - PRIMARY KEY (id), - CONSTRAINT gamestate CHECK (state IN ('hidden', 'published', 'active', 'interrupted', 'finished')) -); -INSERT INTO game VALUES(1,'Marijns Game','hidden','2020-07-09 12:56:00.000000',NULL); -INSERT INTO game VALUES(2,'Spelletje','hidden',NULL,NULL); -CREATE TABLE player ( - id INTEGER NOT NULL, - name VARCHAR(64) NOT NULL, - auth_hash VARCHAR(32), - password_hash VARCHAR(128), - PRIMARY KEY (id), - UNIQUE (auth_hash), - UNIQUE (name) -); -INSERT INTO player VALUES(1,'Marijn','a9df90398c66181bcb9e826e48c97d8a','pbkdf2:sha256:150000$WLe3pHiQ$ff75a3c2e8e0345be88f7f59b57f1cc27f710ef9012995b752f71d8914282cda'); -INSERT INTO player VALUES(2,'Rogier','6a18131cea1be566c6a33e91349f7d91','pbkdf2:sha256:150000$YbcS3JRB$60c71304b2d148f82cd954f57d68ceb15b66fedc23bbe740cd5d97f0a60f7ce4'); -INSERT INTO player VALUES(3,'Henk','df6a22a4c50abba430b82ab9e07d533e','pbkdf2:sha256:150000$PNIf5rdP$81cba639a9d12c946230411d2ba0d5bc22be4509578d7b0c9409047d907c26fc'); -INSERT INTO player VALUES(4,'testplayer','79404d0d9dc869fb421c051790e74b38',NULL); -INSERT INTO player VALUES(5,'test','9a9f90e959261adb50fee40b4bf0ec35',NULL); -INSERT INTO player VALUES(6,'Tessa','f74c9e3d76b22368722d76a5b2445c23',NULL); -INSERT INTO player VALUES(7,'Jemoeder','fc14d4b87f28da7f88c496c33b2d9fe8',NULL); -INSERT INTO player VALUES(8,'jevader','a43c1704562a456bc1f098fab200805a',NULL); -INSERT INTO player VALUES(9,'jekind','0e6cb60258ed1fd71a95fbd13d6751e1',NULL); -CREATE TABLE game_player ( - game_id INTEGER NOT NULL, - player_id INTEGER NOT NULL, - role VARCHAR(6) DEFAULT 'none' NOT NULL, - PRIMARY KEY (game_id, player_id), - FOREIGN KEY(game_id) REFERENCES game (id), - FOREIGN KEY(player_id) REFERENCES player (id), - CONSTRAINT role CHECK (role IN ('none', 'owner', 'hunter', 'bunny')) -); -INSERT INTO game_player VALUES(1,1,'owner'); -INSERT INTO game_player VALUES(1,2,'hunter'); -INSERT INTO game_player VALUES(1,3,'bunny'); -INSERT INTO game_player VALUES(2,1,'hunter'); -INSERT INTO game_player VALUES(2,3,'bunny'); -INSERT INTO game_player VALUES(2,2,'owner'); -CREATE TABLE location ( - id INTEGER NOT NULL, - player_id INTEGER NOT NULL, - longitude NUMERIC(15, 10) NOT NULL, - latitude NUMERIC(15, 10) NOT NULL, - timestamp DATETIME DEFAULT (CURRENT_TIMESTAMP) NOT NULL, - PRIMARY KEY (id), - FOREIGN KEY(player_id) REFERENCES player (id) -); -INSERT INTO location VALUES(1,2,5.1690699999999996094,52.224429999999998131,'2020-07-10 10:36:26'); -INSERT INTO location VALUES(2,2,6.0314899999999997959,52.180669999999999219,'2020-07-10 10:37:19'); -INSERT INTO location VALUES(3,2,5.4217500000000002913,51.882429999999999381,'2020-07-11 10:15:12'); -INSERT INTO location VALUES(4,3,4.4604499999999998038,51.905310000000000059,'2020-07-17 20:50:00'); -INSERT INTO location VALUES(5,3,4.4604499999999998038,52.236209999999999808,'2020-07-17 20:50:00'); -CREATE TABLE notification ( - id INTEGER NOT NULL, - game_id INTEGER NOT NULL, - message TEXT NOT NULL, - type VARCHAR(64) NOT NULL, - timestamp DATETIME DEFAULT (CURRENT_TIMESTAMP) NOT NULL, - PRIMARY KEY (id), - FOREIGN KEY(game_id) REFERENCES game (id) -); -CREATE TABLE objective ( - id INTEGER NOT NULL, - name VARCHAR(64), - game_id INTEGER NOT NULL, - hash VARCHAR(32) NOT NULL, - longitude NUMERIC(15, 10), - latitude NUMERIC(15, 10), - PRIMARY KEY (id), - FOREIGN KEY(game_id) REFERENCES game (id), - UNIQUE (hash) -); -INSERT INTO objective VALUES(1,'Je Moeder',1,'6d6ea175f38a912624b0d842230ec5a0',5.2999999999999998223,52.200000000000002843); -INSERT INTO objective VALUES(5,'Amsterdam',1,'2cb430ba9120fd92ad2694ef59e8232a',4.8120099999999998985,52.37225000000000108); -INSERT INTO objective VALUES(6,'Blok beton',1,'2a94b2b7ca0f01d6d6a025644ce47e46',5.2349899999999998101,52.549639999999996574); -INSERT INTO objective VALUES(7,'testdit',2,'d813048690c6b804bfce0268ccd60995',5.1240500000000004376,52.093200000000003057); -CREATE TABLE player_caught_player ( - id INTEGER DEFAULT '-1' NOT NULL, - catching_player_id INTEGER NOT NULL, - caught_player_id INTEGER NOT NULL, - photo_reference VARCHAR(128) NOT NULL, - timestamp DATETIME DEFAULT (CURRENT_TIMESTAMP) NOT NULL, - PRIMARY KEY (id), - FOREIGN KEY(catching_player_id) REFERENCES player (id), - FOREIGN KEY(caught_player_id) REFERENCES player (id), - UNIQUE (photo_reference) -); -CREATE TABLE notification_player ( - notification_id INTEGER NOT NULL, - player_id INTEGER NOT NULL, - been_shown BOOLEAN DEFAULT 'True' NOT NULL, - PRIMARY KEY (notification_id, player_id), - FOREIGN KEY(notification_id) REFERENCES notification (id), - FOREIGN KEY(player_id) REFERENCES player (id), - CHECK (been_shown IN (0, 1)) -); -CREATE TABLE player_found_objective ( - objective_id INTEGER DEFAULT '-1' NOT NULL, - player_id INTEGER DEFAULT '-1' NOT NULL, - timestamp DATETIME DEFAULT (CURRENT_TIMESTAMP) NOT NULL, - PRIMARY KEY (objective_id, player_id), - FOREIGN KEY(objective_id) REFERENCES objective (id), - FOREIGN KEY(player_id) REFERENCES player (id) -); -INSERT INTO player_found_objective VALUES(1,2,'2020-07-10 09:49:10'); -INSERT INTO player_found_objective VALUES(1,3,'2020-07-10 09:49:10'); -CREATE UNIQUE INDEX ix_game_name ON game (name); -COMMIT;