Browse Source

move player routes to routes_player.py

testing
Burathar 4 years ago
parent
commit
4d2f85d288
  1. 4
      app/game_settings/routes.py
  2. 2
      app/main/__init__.py
  3. 155
      app/main/routes.py
  4. 116
      app/main/routes_player.py
  5. 25
      app/utils.py

4
app/game_settings/routes.py

@ -22,7 +22,7 @@ def create_game():
return redirect(url_for('main.game_dashboard', game_name=game.name)) return redirect(url_for('main.game_dashboard', game_name=game.name))
else: else:
flash_errors(form) flash_errors(form)
return render_template('game_settings.create_game.html', title='Create Game', form=form) return render_template('game_settings/create_game.html', title='Create Game', form=form)
@bp.route('/game/<game_name>/change_settings', methods=['GET', 'POST']) @bp.route('/game/<game_name>/change_settings', methods=['GET', 'POST'])
@login_required @login_required
@ -56,7 +56,7 @@ def change_game_settings(game_name):
return redirect(url_for('main.game_dashboard', game_name=game.name)) return redirect(url_for('main.game_dashboard', game_name=game.name))
else: else:
flash_errors(form) flash_errors(form)
return render_template('game_settings.edit_game.html', title='Chage Game Settings', form=form, game=game) return render_template('game_settings/edit_game.html', title='Chage Game Settings', form=form, game=game)
@bp.route('/game/<game_name>/delete') @bp.route('/game/<game_name>/delete')
@login_required @login_required

2
app/main/__init__.py

@ -2,4 +2,4 @@ from flask import Blueprint
bp = Blueprint('main', __name__) bp = Blueprint('main', __name__)
from app.main import routes, routes_objective from app.main import routes, routes_objective, routes_player

155
app/main/routes.py

@ -1,21 +1,13 @@
import fnmatch
import json import json
from os import listdir
from pathlib import Path
from datetime import datetime, timedelta from datetime import datetime, timedelta
from flask import render_template, redirect, url_for, request, abort, send_file, current_app
from flask import render_template, flash, redirect, url_for, request, abort, send_file, current_app
from flask_login import current_user, login_required from flask_login import current_user, login_required
from werkzeug.utils import secure_filename
from werkzeug.security import safe_join from werkzeug.security import safe_join
from sqlalchemy import and_
from app import db from app import db
from app.main import bp from app.main import bp
from app.utils import get_game_if_owner from app.utils import get_game_if_owner, get_caught_bunny_photo_directory, get_bunny_photo_filename
from app.models import User, Game, Role, GamePlayer, ObjectiveMinimalEncoder,\ from app.models import User, Game, Role, GamePlayer, ObjectiveMinimalEncoder, LocationEncoder, \
LocationEncoder, PlayerCaughtPlayer, Review, Location PlayerCaughtPlayer, Review, Location
from app.main.forms import PlayerAddForm, UserCreateForm, PlayerUpdateForm, CatchBunnyForm
@bp.before_app_request @bp.before_app_request
def before_request(): def before_request():
@ -46,60 +38,14 @@ def game_dashboard(game_name):
if role == Role.hunter: if role == Role.hunter:
hunter_delay = current_app.config['HUNTER_LOCATION_DELAY'] hunter_delay = current_app.config['HUNTER_LOCATION_DELAY']
return render_template('game_hunter_dashboard.html', title='Game Dashboard', game=game, return render_template('game_hunter_dashboard.html', title='Game Dashboard', game=game,
hunter_delay=hunter_delay, json=json, location_encoder=LocationEncoder) hunter_delay=hunter_delay, json=json,
location_encoder=LocationEncoder)
if role == Role.none: if role == Role.none:
return render_template('game_hunter_dashboard.html', title='Game Dashboard', game=game, return render_template('game_hunter_dashboard.html', title='Game Dashboard', game=game,
json=json, location_encoder=LocationEncoder) json=json, location_encoder=LocationEncoder)
if role is None: if role is None:
abort(403) abort(403)
@bp.route('/game/<game_name>/catch_bunny', methods=['GET', 'POST'])
@login_required
def catch_bunny(game_name):
game = Game.query.filter_by(name=game_name).first_or_404()
if current_user.role_in_game(game) is not Role.hunter:
flash('Only hunters can catch bunnies!')
abort(403)
if not game.is_active():
flash("Its not possible to catch a bunny before or after a game, or if the game is not in 'active' mode.")
return redirect(url_for('main.game_dashboard', game_name=game.name))
game_bunnies = game.bunnies()
form = CatchBunnyForm()
form.bunny.choices = [(player.user.id, player.user.name) for player in game_bunnies]
if request.method == 'GET':
parsed_bunny_name = request.args.get('bunny_name', default='', type=str)
if parsed_bunny_name:
bunny = [gameplayer for gameplayer in game_bunnies if gameplayer.user.name == parsed_bunny_name]
if bunny:
# pylint: disable=no-member
form.bunny.default = bunny[0].user.id
form.process()
if form.validate_on_submit():
bunny = [gameplayer for gameplayer in game_bunnies if gameplayer.user.id == form.bunny.data]
if not bunny:
flash('Please choose a bunny')
return request.url
bunny = bunny[0]
pcp = PlayerCaughtPlayer(catching_player=current_user.player_in(game), caught_player=bunny, timestamp=datetime.utcnow())
save_player_caught_player_photo(form.photo.data, game, pcp)
db.session.add(pcp)
db.session.commit()
flash(f"You caught {bunny.user.name}! The submitted photo will be reviewed by a game owner.")
return redirect(url_for('main.game_dashboard', game_name=game.name))
return render_template('catch_bunny.html', title='Catch Bunny', form=form, game=game)
def save_player_caught_player_photo(file_storage, game, pcp):
timestamp = pcp.timestamp.strftime('%Y%m%d%H%M%S')
extension = Path(file_storage.filename).suffix
filename = secure_filename(f'{timestamp}_{pcp.catching_player.user.name}_caught_{pcp.caught_player.user.name}{extension}')
path = get_caught_bunny_photo_directory(game)
path.mkdir(parents=True, exist_ok=True)
file_storage.save(path / filename)
@bp.route('/game/<game_name>/caught_bunny_photo', methods=['GET']) @bp.route('/game/<game_name>/caught_bunny_photo', methods=['GET'])
@login_required @login_required
def caught_bunny_photo(game_name): def caught_bunny_photo(game_name):
@ -120,17 +66,6 @@ def caught_bunny_photo(game_name):
#TODO: Implement switch between serve self and serve by webserver #TODO: Implement switch between serve self and serve by webserver
return send_file(photo_path, conditional=True, as_attachment=False) return send_file(photo_path, conditional=True, as_attachment=False)
def get_bunny_photo_filename(directory, timestamp, hunter_name, bunny_name):
filename = secure_filename(f'{timestamp}_{hunter_name}_caught_{bunny_name}') + '.*'
matches = fnmatch.filter(listdir(directory), filename)
return matches[0] if matches else ''
def get_caught_bunny_photo_directory(game):
return Path(current_app.root_path).parent / \
current_app.config['UPLOAD_FOLDER'] / \
secure_filename(game.name) / \
current_app.config['PLAYER_CAUGHT_PLAYER_PHOTO_DIR_NAME']
@bp.route('/game/<game_name>/review') @bp.route('/game/<game_name>/review')
@login_required @login_required
def review_caught_bunny_photos(game_name): def review_caught_bunny_photos(game_name):
@ -144,91 +79,33 @@ def review_caught_bunny_photos(game_name):
db.session.commit() db.session.commit()
return render_template('review_caught_bunny_photos.html', game=game) return render_template('review_caught_bunny_photos.html', game=game)
@bp.route('/game/<game_name>/adduser', methods=['GET', 'POST'])
@bp.route('/game/<game_name>/addplayer', methods=['GET', 'POST'])
@login_required
def add_player(game_name):
game = get_game_if_owner(game_name)
form_add = PlayerAddForm()
form_add.role.choices = [(role.value, role.name) for role in Role]
form_create = UserCreateForm()
form_create.role.choices = [(role.value, role.name) for role in Role]
if form_add.submit_add.data and form_add.validate_on_submit():
user = User.query.filter_by(name=form_add.name.data).first_or_404()
game.players.append(GamePlayer(user=user, role=Role(form_add.role.data)))
db.session.commit()
return redirect(url_for('main.game_dashboard', game_name=game.name))
if form_create.submit_create.data and form_create.validate_on_submit():
user = User(name=form_create.name.data)
user.set_auth_hash()
game.players.append(GamePlayer(user=user, role=Role(form_create.role.data)))
db.session.commit()
return redirect(url_for('main.game_dashboard', game_name=game.name))
return render_template('add_player.html', title=f'Add User for {game_name}',
form_add=form_add, form_create=form_create, game=game)
@bp.route('/game/<game_name>/removeuser/<username>')
@bp.route('/game/<game_name>/removeplayer/<username>')
@login_required
def remove_player(game_name, username):
game = get_game_if_owner(game_name)
user = User.query.filter(and_(User.name == username, User.games.contains(game))).first_or_404()
game.users.remove(user)
if not user.last_login:
db.session.delete(user)
db.session.commit()
return redirect(url_for('main.game_dashboard', game_name=game.name))
@bp.route('/game/<game_name>/user/<username>', methods=['GET', 'POST'])
@bp.route('/game/<game_name>/player/<username>', methods=['GET', 'POST'])
@login_required
def game_player(game_name, username):
game = get_game_if_owner(game_name)
user = User.query.filter((User.name == username) & (User.games.contains(game))).first_or_404()
player = user.player_in(game)
# pylint: disable=no-member
form = PlayerUpdateForm(role=player.role.name)
form.role.choices = [(role.value, role.name) for role in Role]
if request.method == 'GET':
form.role.default = player.role.value
form.process()
if form.validate_on_submit():
player.role = Role(form.role.data)
print(form.role.data)
db.session.commit()
return redirect(url_for('main.game_dashboard', game_name=game.name))
return render_template('game_player.html', title=f'{user.name} in {game_name}', player=player, form=form, json=json, location_encoder=LocationEncoder)
@bp.route('/user/<username>/send_location', methods=['POST']) @bp.route('/user/<username>/send_location', methods=['POST'])
@login_required @login_required
def send_location(username): def send_location(username):
user = User.query.filter_by(name=username).first_or_404() user = User.query.filter_by(name=username).first_or_404()
last_location = user.last_location() last_location = user.last_location()
latitude = request.form.get('lat', default=None, type=float) latitude = request.form.get('lat', default=None, type=float)
longitude = request.form.get('long', default=None, type=float) longitude = request.form.get('long', default=None, type=float)
if latitude is None or longitude is None: if latitude is None or longitude is None:
return '', 400 return '', 400
# Check if previous two locations are exactly the same, if so, only update timestamp of last location # Check if previous two locations are exactly the same,
# if so, only update timestamp of last location
if last_location: if last_location:
if datetime.utcnow() - last_location.timestamp < timedelta(minutes=1): if datetime.utcnow() - last_location.timestamp < timedelta(minutes=1):
return '', 204 return '', 204
if latitude == last_location.latitude and longitude == last_location.longitude and len(user.locations) >= 2: if (latitude == last_location.latitude and
longitude == last_location.longitude and
len(user.locations) >= 2):
before_last_location = user.locations[-2] before_last_location = user.locations[-2]
if before_last_location: if before_last_location:
if latitude == before_last_location.latitude and longitude == before_last_location.longitude: if (latitude == before_last_location.latitude and
longitude == before_last_location.longitude):
last_location.timestamp = datetime.utcnow() last_location.timestamp = datetime.utcnow()
db.session.commit() db.session.commit()
return '', 204 return '', 204
user.locations.append(Location(longitude=longitude, latitude=latitude)) user.locations.append(Location(longitude=longitude, latitude=latitude))
db.session.commit() db.session.commit()
return '', 204 return '', 204

116
app/main/routes_player.py

@ -0,0 +1,116 @@
import json
from datetime import datetime
from flask import render_template, flash, redirect, url_for, request, abort
from flask_login import current_user, login_required
from sqlalchemy import and_
from app import db
from app.main import bp
from app.utils import get_game_if_owner, save_player_caught_player_photo
from app.models import User, Game, Role, GamePlayer, PlayerCaughtPlayer, LocationEncoder
from app.main.forms import PlayerAddForm, UserCreateForm, CatchBunnyForm, PlayerUpdateForm
@bp.route('/game/<game_name>/adduser', methods=['GET', 'POST'])
@bp.route('/game/<game_name>/addplayer', methods=['GET', 'POST'])
@login_required
def add_player(game_name):
game = get_game_if_owner(game_name)
form_add = PlayerAddForm()
form_add.role.choices = [(role.value, role.name) for role in Role]
form_create = UserCreateForm()
form_create.role.choices = [(role.value, role.name) for role in Role]
if form_add.submit_add.data and form_add.validate_on_submit():
user = User.query.filter_by(name=form_add.name.data).first_or_404()
game.players.append(GamePlayer(user=user, role=Role(form_add.role.data)))
db.session.commit()
return redirect(url_for('main.game_dashboard', game_name=game.name))
if form_create.submit_create.data and form_create.validate_on_submit():
user = User(name=form_create.name.data)
user.set_auth_hash()
game.players.append(GamePlayer(user=user, role=Role(form_create.role.data)))
db.session.commit()
return redirect(url_for('main.game_dashboard', game_name=game.name))
return render_template('add_player.html', title=f'Add User for {game_name}',
form_add=form_add, form_create=form_create, game=game)
@bp.route('/game/<game_name>/removeuser/<username>')
@bp.route('/game/<game_name>/removeplayer/<username>')
@login_required
def remove_player(game_name, username):
game = get_game_if_owner(game_name)
user = User.query.filter(and_(User.name == username, User.games.contains(game))).first_or_404()
game.users.remove(user)
if not user.last_login:
db.session.delete(user)
db.session.commit()
return redirect(url_for('main.game_dashboard', game_name=game.name))
@bp.route('/game/<game_name>/user/<username>', methods=['GET', 'POST'])
@bp.route('/game/<game_name>/player/<username>', methods=['GET', 'POST'])
@login_required
def game_player(game_name, username):
game = get_game_if_owner(game_name)
user = User.query.filter((User.name == username) & (User.games.contains(game))).first_or_404()
player = user.player_in(game)
# pylint: disable=no-member
form = PlayerUpdateForm(role=player.role.name)
form.role.choices = [(role.value, role.name) for role in Role]
if request.method == 'GET':
form.role.default = player.role.value
form.process()
if form.validate_on_submit():
player.role = Role(form.role.data)
print(form.role.data)
db.session.commit()
return redirect(url_for('main.game_dashboard', game_name=game.name))
return render_template('game_player.html', title=f'{user.name} in {game_name}',
player=player, form=form, json=json, location_encoder=LocationEncoder)
@bp.route('/game/<game_name>/catch_bunny', methods=['GET', 'POST'])
@login_required
def catch_bunny(game_name):
game = Game.query.filter_by(name=game_name).first_or_404()
if current_user.role_in_game(game) is not Role.hunter:
flash('Only hunters can catch bunnies!')
abort(403)
if not game.is_active():
flash("Its not possible to catch a bunny before or after a game, "
"or if the game is not in 'active' mode.")
return redirect(url_for('main.game_dashboard', game_name=game.name))
game_bunnies = game.bunnies()
form = CatchBunnyForm()
form.bunny.choices = [(player.user.id, player.user.name) for player in game_bunnies]
if request.method == 'GET':
parsed_bunny_name = request.args.get('bunny_name', default='', type=str)
if parsed_bunny_name:
bunny = [gameplayer for gameplayer in game_bunnies
if gameplayer.user.name == parsed_bunny_name]
if bunny:
# pylint: disable=no-member
form.bunny.default = bunny[0].user.id
form.process()
if form.validate_on_submit():
bunny = [gameplayer for gameplayer in game_bunnies if gameplayer.user.id == form.bunny.data]
if not bunny:
flash('Please choose a bunny')
return request.url
bunny = bunny[0]
pcp = PlayerCaughtPlayer(catching_player=current_user.player_in(game),
caught_player=bunny, timestamp=datetime.utcnow())
save_player_caught_player_photo(form.photo.data, game, pcp)
db.session.add(pcp)
db.session.commit()
flash(f"You caught {bunny.user.name}! "
"The submitted photo will be reviewed by a game owner.")
return redirect(url_for('main.game_dashboard', game_name=game.name))
return render_template('catch_bunny.html', title='Catch Bunny', form=form, game=game)

25
app/utils.py

@ -1,7 +1,11 @@
import fnmatch
from os import listdir
from io import BytesIO from io import BytesIO
from pathlib import Path
import qrcode import qrcode
from flask import send_file, flash, abort from flask import send_file, flash, abort, current_app
from flask_login import current_user from flask_login import current_user
from werkzeug.utils import secure_filename
from app.models import Game from app.models import Game
def generate_qr_code(url): def generate_qr_code(url):
@ -37,3 +41,22 @@ def get_game_if_owner(game_name):
if not game.owned_by(current_user): if not game.owned_by(current_user):
abort(403) abort(403)
return game return game
def save_player_caught_player_photo(file_storage, game, pcp):
timestamp = pcp.timestamp.strftime('%Y%m%d%H%M%S')
extension = Path(file_storage.filename).suffix
filename = secure_filename(f'{timestamp}_{pcp.catching_player.user.name}_caught_{pcp.caught_player.user.name}{extension}')
path = get_caught_bunny_photo_directory(game)
path.mkdir(parents=True, exist_ok=True)
file_storage.save(path / filename)
def get_bunny_photo_filename(directory, timestamp, hunter_name, bunny_name):
filename = secure_filename(f'{timestamp}_{hunter_name}_caught_{bunny_name}') + '.*'
matches = fnmatch.filter(listdir(directory), filename)
return matches[0] if matches else ''
def get_caught_bunny_photo_directory(game):
return Path(current_app.root_path).parent / \
current_app.config['UPLOAD_FOLDER'] / \
secure_filename(game.name) / \
current_app.config['PLAYER_CAUGHT_PLAYER_PHOTO_DIR_NAME']

Loading…
Cancel
Save