Browse Source

fix issues that arise from updating to database model 1.4

testing
Burathar 5 years ago
parent
commit
182eebbc35
  1. 7
      app/auth/forms.py
  2. 16
      app/auth/routes.py
  3. 9
      app/main/forms.py
  4. 56
      app/main/routes.py
  5. 2
      app/models/__init__.py
  6. 14
      app/models/game.py
  7. 7
      app/models/game_player.py
  8. 4
      app/models/location.py
  9. 4
      app/models/user.py
  10. 4
      app/templates/add_player.html
  11. 7
      app/templates/auth/user.html
  12. 4
      app/templates/game_bunny_dashboard.html
  13. 2
      app/templates/game_hunter_dashboard.html
  14. 18
      app/templates/game_owner_dashboard.html
  15. 14
      app/templates/game_player.html
  16. 2
      app/templates/index.html
  17. 74
      app/tests/test_models.py
  18. 121
      database_dump.txt
  19. 50
      migrations/versions/1d844798c277_reset_migrations.py
  20. 32
      the_hunt.py

7
app/auth/forms.py

@ -1,8 +1,7 @@
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, BooleanField from wtforms import StringField, PasswordField, SubmitField, BooleanField
from wtforms.validators import DataRequired, EqualTo, ValidationError, Length from wtforms.validators import DataRequired, EqualTo, ValidationError, Length
from pytz import timezone from app.models import User
from app.models import Player
class LoginForm(FlaskForm): class LoginForm(FlaskForm):
@ -19,6 +18,6 @@ class RegistrationForm(FlaskForm):
submit = SubmitField('Register') submit = SubmitField('Register')
def validate_username(self, username): def validate_username(self, username):
player = Player.query.filter_by(name=username.data).first() user = User.query.filter_by(name=username.data).first()
if player is not None: if user is not None:
raise ValidationError('Please use a different username.') raise ValidationError('Please use a different username.')

16
app/auth/routes.py

@ -2,7 +2,7 @@ from flask import render_template, flash, redirect, url_for
from flask_login import login_user, logout_user, current_user, login_required from flask_login import login_user, logout_user, current_user, login_required
from app import db from app import db
from app.auth import bp from app.auth import bp
from app.models import Player from app.models import User
from app.auth.forms import LoginForm, RegistrationForm from app.auth.forms import LoginForm, RegistrationForm
@bp.route('/login', methods=['GET', 'POST']) @bp.route('/login', methods=['GET', 'POST'])
@ -11,11 +11,11 @@ def login():
return redirect(url_for('main.index')) return redirect(url_for('main.index'))
form = LoginForm() form = LoginForm()
if form.validate_on_submit(): if form.validate_on_submit():
player = Player.query.filter_by(name=form.username.data).first() user = User.query.filter_by(name=form.username.data).first()
if player is None or not player.check_password(form.password.data): if user is None or not user.check_password(form.password.data):
flash('Invalid username or password') flash('Invalid username or password')
return redirect(url_for('auth.login')) return redirect(url_for('auth.login'))
login_user(player, remember=form.remember_me.data) login_user(user, remember=form.remember_me.data)
return redirect(url_for('main.index')) return redirect(url_for('main.index'))
return render_template('auth/login.html', title='Sign In', form=form) return render_template('auth/login.html', title='Sign In', form=form)
@ -31,10 +31,10 @@ def register():
return redirect(url_for('main.index')) return redirect(url_for('main.index'))
form = RegistrationForm() form = RegistrationForm()
if form.validate_on_submit(): if form.validate_on_submit():
player = Player(name=form.username.data) user = User(name=form.username.data)
player.set_password(form.password.data) user.set_password(form.password.data)
player.set_auth_hash() user.set_auth_hash()
db.session.add(player) db.session.add(user)
db.session.commit() db.session.commit()
flash('Congratulations, you are now a registered user!') flash('Congratulations, you are now a registered user!')
return redirect(url_for('auth.login')) return redirect(url_for('auth.login'))

9
app/main/forms.py

@ -34,7 +34,8 @@ class ObjectiveForm(FlaskForm):
submit = SubmitField('Save') submit = SubmitField('Save')
def validate_objective_name(self, objective_name): def validate_objective_name(self, objective_name):
if objective_name.data == '': return if objective_name.data == '':
return
objective = Objective.query.filter_by(name=objective_name.data).first() objective = Objective.query.filter_by(name=objective_name.data).first()
if objective is not None: if objective is not None:
raise ValidationError('Please use a different name.') raise ValidationError('Please use a different name.')
@ -44,11 +45,11 @@ class PlayerUpdateForm(FlaskForm):
submit = SubmitField('Update') submit = SubmitField('Update')
class PlayerAddForm(FlaskForm): class PlayerAddForm(FlaskForm):
name = StringField('Player Name', validators=[DataRequired(), Length(min=0, max=64)]) name = StringField('Username', validators=[DataRequired(), Length(min=0, max=64)])
role = SelectField('Player Role', choices=[('none', 'none'), ('owner', 'owner'), ('hunter', 'hunter'), ('bunny', 'bunny')], validators=[DataRequired()]) role = SelectField('Player Role', choices=[('none', 'none'), ('owner', 'owner'), ('hunter', 'hunter'), ('bunny', 'bunny')], validators=[DataRequired()])
submit_add = SubmitField('Create') submit_add = SubmitField('Create')
class PlayerCreateForm(FlaskForm): class UserCreateForm(FlaskForm):
name = StringField('Player Name', validators=[DataRequired(), Length(min=0, max=64)]) name = StringField('Username', validators=[DataRequired(), Length(min=0, max=64)])
role = SelectField('Player Role', choices=[('none', 'none'), ('owner', 'owner'), ('hunter', 'hunter'), ('bunny', 'bunny')], validators=[DataRequired()]) role = SelectField('Player Role', choices=[('none', 'none'), ('owner', 'owner'), ('hunter', 'hunter'), ('bunny', 'bunny')], validators=[DataRequired()])
submit_create = SubmitField('Create') submit_create = SubmitField('Create')

56
app/main/routes.py

@ -6,8 +6,8 @@ from sqlalchemy import and_
from io import BytesIO from io import BytesIO
from app import db from app import db
from app.main import bp from app.main import bp
from app.models import Player, Game, Role, GamePlayer, Objective, ObjectiveMinimalEncoder, LocationEncoder from app.models import User, Game, Role, GamePlayer, Objective, ObjectiveMinimalEncoder, LocationEncoder
from app.main.forms import CreateGameForm, ObjectiveForm, PlayerAddForm, PlayerCreateForm, PlayerUpdateForm from app.main.forms import CreateGameForm, ObjectiveForm, PlayerAddForm, UserCreateForm, PlayerUpdateForm
@bp.route('/') @bp.route('/')
@bp.route('/index') @bp.route('/index')
@ -24,7 +24,7 @@ def create_game():
form = CreateGameForm() form = CreateGameForm()
if form.validate_on_submit(): 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 = Game(name=form.game_name.data, start_time=form.start_time.data, end_time=form.end_time.data)
game.game_players.append(GamePlayer(player=current_user, role=Role['owner'])) game.game_players.append(GamePlayer(game_player=current_user, role=Role['owner']))
db.session.add(game) db.session.add(game)
db.session.commit() db.session.commit()
flash(f"'{game.name}' had been created!") flash(f"'{game.name}' had been created!")
@ -51,6 +51,7 @@ def game_dashboard(game_name):
if role is None: if role is None:
abort(403) abort(403)
@bp.route('/game/<game_name>/adduser', methods=['GET', 'POST'])
@bp.route('/game/<game_name>/addplayer', methods=['GET', 'POST']) @bp.route('/game/<game_name>/addplayer', methods=['GET', 'POST'])
@login_required @login_required
def add_player(game_name): def add_player(game_name):
@ -58,62 +59,63 @@ def add_player(game_name):
if not game.owned_by(current_user): if not game.owned_by(current_user):
abort(403) abort(403)
form_add = PlayerAddForm() form_add = PlayerAddForm()
form_create = PlayerCreateForm() form_create = UserCreateForm()
if form_add.submit_add.data and form_add.validate_on_submit(): if form_add.submit_add.data and form_add.validate_on_submit():
player = Player.query.filter_by(form_add.name.data).first_or_404() user = User.query.filter_by(form_add.name.data).first_or_404()
game.game_players.append(GamePlayer(player=player, role=Role[form_create.role.data])) game.game_players.append(GamePlayer(user=user, role=Role[form_create.role.data]))
return redirect(url_for('main.game_dashboard', game_name=game.name)) return redirect(url_for('main.game_dashboard', game_name=game.name))
if form_create.submit_create.data and form_create.validate_on_submit(): if form_create.submit_create.data and form_create.validate_on_submit():
player = Player(name=form_create.name.data) user = User(name=form_create.name.data)
player.set_auth_hash() user.set_auth_hash()
game.game_players.append(GamePlayer(player=player, role=Role[form_create.role.data])) game.game_players.append(GamePlayer(user=user, role=Role[form_create.role.data]))
db.session.commit() db.session.commit()
return redirect(url_for('main.game_dashboard', game_name=game.name)) return redirect(url_for('main.game_dashboard', game_name=game.name))
return render_template('add_player.html', title=f'Add Player for {game_name}', form_add=form_add, form_create=form_create, game=game) 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>/removeplayer/<player_name>') @bp.route('/game/<game_name>/removeuser/<username>')
@bp.route('/game/<game_name>/removeplayer/<username>')
@login_required @login_required
def remove_player(game_name, player_name): def remove_player(game_name, username):
game = Game.query.filter_by(name=game_name).first_or_404() game = Game.query.filter_by(name=game_name).first_or_404()
if not game.owned_by(current_user): if not game.owned_by(current_user):
abort(403) abort(403)
player = Player.query.filter(and_(Player.name == player_name, Player.games.contains(game))).first_or_404() user = User.query.filter(and_(User.name == username, User.games.contains(game))).first_or_404()
game.players.remove(player) game.players.remove(user)
db.session.commit() db.session.commit()
return redirect(url_for('main.game_dashboard', game_name=game.name)) return redirect(url_for('main.game_dashboard', game_name=game.name))
@bp.route('/game/<game_name>/player/<player_name>', methods=['GET', 'POST']) @bp.route('/game/<game_name>/player/<username>', methods=['GET', 'POST'])
@login_required @login_required
def game_player(game_name, player_name): def game_player(game_name, username):
game = Game.query.filter_by(name=game_name).first_or_404() game = Game.query.filter_by(name=game_name).first_or_404()
if not game.owned_by(current_user): if not game.owned_by(current_user):
abort(403) abort(403)
player = Player.query.filter(and_(Player.name == player_name, Player.games.contains(game))).first_or_404() user = User.query.filter(and_(User.name == username, User.games.contains(game))).first_or_404()
gameplayer = [gameplayer for gameplayer in player.player_games if gameplayer.game == game][0] gameplayer = [gameplayer for gameplayer in user.user_games if gameplayer.game == game][0]
form = PlayerUpdateForm(role=gameplayer.role.name) form = PlayerUpdateForm(role=gameplayer.role.name)
if form.validate_on_submit(): if form.validate_on_submit():
gameplayer.role = Role[form.role.data] gameplayer.role = Role[form.role.data]
db.session.commit() db.session.commit()
return redirect(url_for('main.game_dashboard', game_name=game.name)) return redirect(url_for('main.game_dashboard', game_name=game.name))
return render_template('player.html', title=f'{player.name} in {game_name}', game=game, player=player, form=form, json=json, location_encoder=LocationEncoder) return render_template('game_player.html', title=f'{user.name} in {game_name}', game=game, user=user, form=form, json=json, location_encoder=LocationEncoder)
@bp.route('/player/<auth_hash>/qrcode.png') @bp.route('/user/<auth_hash>/qrcode.png')
@login_required @login_required
def player_qrcode(auth_hash): def user_qrcode(auth_hash):
player = Player.query.filter_by(auth_hash=auth_hash).first_or_404() user = User.query.filter_by(auth_hash=auth_hash).first_or_404()
if not current_user.owns_game_played_by(player): if not current_user.owns_game_played_by(user):
abort(403) abort(403)
img = generate_qr_code(url_for('main.player', auth_hash=auth_hash, _external=True)) img = generate_qr_code(url_for('main.player', auth_hash=auth_hash, _external=True))
return serve_pil_image(img) return serve_pil_image(img)
@bp.route('/player/<auth_hash>') @bp.route('/user/<auth_hash>')
@login_required @login_required
def player(auth_hash): def user(auth_hash):
player = Player.query.filter_by(auth_hash=auth_hash).first_or_404() user = User.query.filter_by(auth_hash=auth_hash).first_or_404()
return render_template('player.html',title=f'Player: {player.name}', player=player) return render_template('auth/user.html', title=f'User: {user.name}', user=user)
@bp.route('/game/<game_name>/add_objective', methods=['GET', 'POST']) @bp.route('/game/<game_name>/add_objective', methods=['GET', 'POST'])
@login_required @login_required

2
app/models/__init__.py

@ -1,8 +1,8 @@
from .game import Game from .game import Game
from .game_player import GamePlayer from .game_player import GamePlayer
from .game_state import GameState from .game_state import GameState
from .location import Location, LocationEncoder from .location import Location, LocationEncoder
from .notification import Notification
from .notification_player import NotificationPlayer from .notification_player import NotificationPlayer
from .objective import Objective, ObjectiveMinimalEncoder from .objective import Objective, ObjectiveMinimalEncoder
from .player_caught_player import PlayerCaughtPlayer from .player_caught_player import PlayerCaughtPlayer

14
app/models/game.py

@ -15,8 +15,10 @@ class Game(db.Model):
'GamePlayer', 'GamePlayer',
back_populates='game', back_populates='game',
cascade="save-update, merge, delete, delete-orphan") cascade="save-update, merge, delete, delete-orphan")
players = association_proxy('game_players', 'user',
creator=lambda user: GamePlayer(user=user))
users = association_proxy('game_players', 'user', users = association_proxy('game_players', 'user',
creator=lambda user: GamePlayer(user=user)) # to enable game.players.append(player) creator=lambda user: GamePlayer(user=user))
objectives = db.relationship( objectives = db.relationship(
'Objective', 'Objective',
lazy='select', lazy='select',
@ -27,11 +29,11 @@ class Game(db.Model):
backref=db.backref('game', lazy='joined')) backref=db.backref('game', lazy='joined'))
def last_player_locations(self): def last_player_locations(self):
return [player.last_location(self) for player in self.users if player.locations] return [user.last_location(self) for user in self.players if user.locations]
def bunnies(self): def bunnies(self):
# pylint: disable=not-an-iterable # pylint: disable=not-an-iterable
return [gameplayer.player for gameplayer in self.game_players if gameplayer.role == Role.bunny] return [gameplayer.user for gameplayer in self.game_players if gameplayer.role == Role.bunny]
def last_locations(self, players): def last_locations(self, players):
locations = [] locations = []
@ -39,7 +41,7 @@ class Game(db.Model):
locations.append(player.last_location(self)) locations.append(player.last_location(self))
return locations return locations
def owned_by(self, player): def owned_by(self, user):
# pylint: disable=not-an-iterable # pylint: disable=not-an-iterable
'''given player is an owner of game''' '''given user is an owner of this game'''
return player in [gameplayer.player for gameplayer in self.game_players if gameplayer.role == Role.owner] return user in [gameplayer.user for gameplayer in self.game_players if gameplayer.role == Role.owner]

7
app/models/game_player.py

@ -1,4 +1,5 @@
from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.schema import UniqueConstraint
from app import db from app import db
from .role import Role from .role import Role
@ -9,11 +10,13 @@ from .player_caught_player import PlayerCaughtPlayer
class GamePlayer(db.Model): class GamePlayer(db.Model):
__tablename__ = 'game_player' __tablename__ = 'game_player'
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
game_id = db.Column(db.Integer, db.ForeignKey('game.id'), primary_key=True, nullable=False) game_id = db.Column(db.Integer, db.ForeignKey('game.id'), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True, nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
role = db.Column(db.Enum(Role), server_default=Role(0).name, nullable=False) role = db.Column(db.Enum(Role), server_default=Role(0).name, nullable=False)
game = db.relationship('Game', back_populates='game_players') game = db.relationship('Game', back_populates='game_players')
user = db.relationship('User', back_populates='user_games') user = db.relationship('User', back_populates='user_games')
__table_args__ = (UniqueConstraint('game_id', 'user_id', name='_game_user_uc'),
)
player_notifications = db.relationship( player_notifications = db.relationship(
'NotificationPlayer', 'NotificationPlayer',

4
app/models/location.py

@ -6,7 +6,7 @@ from app import db
class Location(db.Model): class Location(db.Model):
__tablename__ = 'location' __tablename__ = 'location'
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
player_id = db.Column(db.Integer, db.ForeignKey('player.id'), nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
longitude = db.Column(db.Numeric(precision=15, scale=10, asdecimal=False, decimal_return_scale=None), nullable=False) # maybe check asdecimal and decimal_return_scale later? longitude = db.Column(db.Numeric(precision=15, scale=10, asdecimal=False, decimal_return_scale=None), nullable=False) # maybe check asdecimal and decimal_return_scale later?
latitude = db.Column(db.Numeric(precision=15, scale=10, asdecimal=False, decimal_return_scale=None), nullable=False) latitude = db.Column(db.Numeric(precision=15, scale=10, asdecimal=False, decimal_return_scale=None), nullable=False)
timestamp = db.Column(db.DateTime, server_default=func.now(), nullable=False) timestamp = db.Column(db.DateTime, server_default=func.now(), nullable=False)
@ -17,7 +17,7 @@ class Location(db.Model):
class LocationEncoder(JSONEncoder): class LocationEncoder(JSONEncoder):
def default(self, location): def default(self, location):
return { return {
'player_name' : location.player.name, 'username' : location.user.name,
'longitude' : location.longitude, 'longitude' : location.longitude,
'latitude' : location.latitude, 'latitude' : location.latitude,
'timestamp_utc' : str(location.timestamp) 'timestamp_utc' : str(location.timestamp)

4
app/models/user.py

@ -10,7 +10,7 @@ from app.models import GamePlayer, Role
class User(UserMixin, db.Model): class User(UserMixin, db.Model):
""" !Always call set_auth_hash() after creating new instance! """ """ !Always call set_auth_hash() after creating new instance! """
__tablename__ = 'player' __tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True, nullable=False) name = db.Column(db.String(64), unique=True, nullable=False)
auth_hash = db.Column(db.String(32), unique=True, nullable=True) auth_hash = db.Column(db.String(32), unique=True, nullable=True)
@ -36,6 +36,8 @@ class User(UserMixin, db.Model):
self.auth_hash = token_hex(16) self.auth_hash = token_hex(16)
def check_password(self, password): def check_password(self, password):
if not password or not self.password_hash:
return False
return check_password_hash(self.password_hash, password) return check_password_hash(self.password_hash, password)
def locations_during_game(self, game): def locations_during_game(self, game):

4
app/templates/add_player.html

@ -3,7 +3,7 @@
{% block app_content %} {% block app_content %}
<h1>Add Player To Game</h1> <h1>Add Player To Game</h1>
<h2>Add Existing Player</h2> <h2>Add Existing User</h2>
<div class="row"> <div class="row">
<div class="col-md-4"> <div class="col-md-4">
<form action="" method="post" class="form" role="form"> <form action="" method="post" class="form" role="form">
@ -14,7 +14,7 @@
</form> </form>
</div> </div>
</div> </div>
<h2>Create new Player</h2> <h2>Create new User</h2>
<div class="row"> <div class="row">
<div class="col-md-4"> <div class="col-md-4">
<form action="" method="post" class="form" role="form"> <form action="" method="post" class="form" role="form">

7
app/templates/auth/user.html

@ -0,0 +1,7 @@
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
<h1>User</h1>
This page is is progress, it should enable you to claim a player account using the authhash, as long as the player hasnt logged in yet.
{% endblock %}

4
app/templates/game_bunny_dashboard.html

@ -28,7 +28,7 @@
{% for player in game.players %} {% for player in game.players %}
<tr> <tr>
<td><a href="{{ url_for('main.game_player', game_name = game.name, player_name = player.name) }}">{{ player.name }}</a></td> <td><a href="{{ url_for('main.game_player', game_name = game.name, player_name = player.name) }}">{{ player.name }}</a></td>
{% for gameplayer in player.player_games if gameplayer.game == game %} {% for gameplayer in player.user_games if gameplayer.game == game %}
<td>{{ gameplayer.role.name }}</td> <td>{{ gameplayer.role.name }}</td>
{% endfor %} {% endfor %}
<td>{{ player.found_objectives | selectattr('game', '==', game)|list|length}}</td> <td>{{ player.found_objectives | selectattr('game', '==', game)|list|length}}</td>
@ -129,7 +129,7 @@
], {icon: greenIcon}).addTo(map); ], {icon: greenIcon}).addTo(map);
var timestamp_utc = moment.utc(players[i]['timestamp_utc']).toDate() var timestamp_utc = moment.utc(players[i]['timestamp_utc']).toDate()
var timestamp_local = moment(timestamp_utc).local().format('YYYY-MM-DD HH:mm'); var timestamp_local = moment(timestamp_utc).local().format('YYYY-MM-DD HH:mm');
playerMarker.bindTooltip(`<b>${players[i]['player_name']}</b><br> playerMarker.bindTooltip(`<b>${players[i]['username']}</b><br>
${timestamp_local}`).openPopup(); ${timestamp_local}`).openPopup();
} }

2
app/templates/game_hunter_dashboard.html

@ -72,7 +72,7 @@
], {icon: greenIcon}).addTo(map); ], {icon: greenIcon}).addTo(map);
var timestamp_utc = moment.utc(players[i]['timestamp_utc']).toDate() var timestamp_utc = moment.utc(players[i]['timestamp_utc']).toDate()
var timestamp_local = moment(timestamp_utc).local().format('YYYY-MM-DD HH:mm'); var timestamp_local = moment(timestamp_utc).local().format('YYYY-MM-DD HH:mm');
playerMarker.bindTooltip(`<b>${players[i]['player_name']}</b><br> playerMarker.bindTooltip(`<b>${players[i]['username']}</b><br>
${timestamp_local}`).openPopup(); ${timestamp_local}`).openPopup();
} }

18
app/templates/game_owner_dashboard.html

@ -25,20 +25,20 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for player in game.players %} {% for user in game.users %}
<tr> <tr>
<td><a href="{{ url_for('main.game_player', game_name = game.name, player_name = player.name) }}">{{ player.name }}</a></td> <td><a href="{{ url_for('main.game_player', game_name = game.name, username = user.name) }}">{{ user.name }}</a></td>
{% for gameplayer in player.player_games if gameplayer.game == game %} {% for gameplayer in user.user_games if gameplayer.game == game %}
<td>{{ gameplayer.role.name }}</td> <td>{{ gameplayer.role.name }}</td>
{% endfor %} {% endfor %}
<td>{{ player.found_objectives | selectattr('game', '==', game)|list|length}}</td> <td>{{ user.found_objectives | selectattr('game', '==', game)|list|length}}</td>
<td>{{ player.caught_players | selectattr('game', '==', game)|list|length}}</td> <td>{{ user.caught_players | selectattr('game', '==', game)|list|length}}</td>
<td>{{ player.caught_by_players | selectattr('game', '==', game)|list|length}}</td> <td>{{ user.caught_by_players | selectattr('game', '==', game)|list|length}}</td>
<td>{% with location = player.last_location(game) %} <td>{% with location = user.last_location(game) %}
{% if location %}{{ moment(location.timestamp).fromNow()}}: {% endif %} {% if location %}{{ moment(location.timestamp).fromNow()}}: {% endif %}
{{ location }} {{ location }}
{% endwith %}</td> {% endwith %}</td>
<td><a href="{{ url_for('main.remove_player', game_name=game.name, player_name=player.name) }}"> <td><a href="{{ url_for('main.remove_player', game_name=game.name, username=user.name) }}">
<button class="btn btn-danger">Delete</button></a> <button class="btn btn-danger">Delete</button></a>
</td> </td>
</tr> </tr>
@ -129,7 +129,7 @@
], {icon: greenIcon}).addTo(map); ], {icon: greenIcon}).addTo(map);
var timestamp_utc = moment.utc(players[i]['timestamp_utc']).toDate() var timestamp_utc = moment.utc(players[i]['timestamp_utc']).toDate()
var timestamp_local = moment(timestamp_utc).local().format('YYYY-MM-DD HH:mm'); var timestamp_local = moment(timestamp_utc).local().format('YYYY-MM-DD HH:mm');
playerMarker.bindTooltip(`<b>${players[i]['player_name']}</b><br> playerMarker.bindTooltip(`<b>${players[i]['username']}</b><br>
${timestamp_local}`).openPopup(); ${timestamp_local}`).openPopup();
} }

14
app/templates/player.html → app/templates/game_player.html

@ -8,22 +8,22 @@
{% endblock %} {% endblock %}
{% block app_content %} {% block app_content %}
<h1>Player: {{ player.name }}</h1> <h1>Player: {{ user.name }}</h1>
<hr> <hr>
<div class="row"> <div class="row">
<div class="col-md-4 col-sm-6 col-xs-8"> <div class="col-md-4 col-sm-6 col-xs-8">
<div class="row"> <div class="row">
<form action="" method="post" class="form" role="form"> <form action="" method="post" class="form" role="form">
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
{% for gameplayer in player.player_games if gameplayer.game == game %} {% for gameplayer in user.user_games if gameplayer.game == game %}
{{ wtf.form_field(form.role, class='form-control') }} {{ wtf.form_field(form.role, class='form-control') }}
{% endfor %} {% endfor %}
{{ wtf.form_field(form.submit, class='btn btn-primary', value='Update') }} {{ wtf.form_field(form.submit, class='btn btn-primary', value='Update') }}
</form> </form>
</div> </div>
{% if player.auth_hash %} {% if user.auth_hash %}
<div class="row"> <div class="row">
<img src="{{ url_for('main.player_qrcode', auth_hash=player.auth_hash) }}" alt="qr_code_failed", width="100%"> <img src="{{ url_for('main.user_qrcode', auth_hash=user.auth_hash) }}" alt="qr_code_failed", width="100%">
</div> </div>
{% endif %} {% endif %}
</div> </div>
@ -37,7 +37,7 @@
{{ moment.include_moment() }} {{ moment.include_moment() }}
<script type="text/javascript", crossorigin="anonymous"> <script type="text/javascript", crossorigin="anonymous">
// Leaflet Map // Leaflet Map
'{% set last_location = player.last_location(game) %}' '{% set last_location = user.last_location(game) %}'
var map = L.map( 'map', { var map = L.map( 'map', {
center: ['{{ last_location.latitude or 52.2 }}', '{{ last_location.longitude or 5.3 }}'], center: ['{{ last_location.latitude or 52.2 }}', '{{ last_location.longitude or 5.3 }}'],
minZoom: 6, minZoom: 6,
@ -60,7 +60,7 @@
shadowSize: [41, 41] shadowSize: [41, 41]
}); });
var locations = JSON.parse('{{ json.dumps(player.locations, cls=location_encoder)|safe }}') var locations = JSON.parse('{{ json.dumps(user.locations_during_game(game)), cls=location_encoder)|safe }}')
for (var i = 0; i < locations.length; i++){ for (var i = 0; i < locations.length; i++){
var playerMarker = L.marker([ var playerMarker = L.marker([
locations[i]['latitude'], locations[i]['latitude'],
@ -68,7 +68,7 @@
], {icon: greenIcon}).addTo(map); ], {icon: greenIcon}).addTo(map);
var timestamp_utc = moment.utc(locations[i]['timestamp_utc']).toDate() var timestamp_utc = moment.utc(locations[i]['timestamp_utc']).toDate()
var timestamp_local = moment(timestamp_utc).local().format('YYYY-MM-DD HH:mm'); var timestamp_local = moment(timestamp_utc).local().format('YYYY-MM-DD HH:mm');
playerMarker.bindTooltip(`<b>${locations[i]['player_name']}</b><br> playerMarker.bindTooltip(`<b>${locations[i]['username']}</b><br>
${timestamp_local}`).openPopup(); ${timestamp_local}`).openPopup();
} }

2
app/templates/index.html

@ -24,7 +24,7 @@
<td>{{ game.start_time }}</td> <td>{{ game.start_time }}</td>
<td>{{ game.end_time }}</td> <td>{{ game.end_time }}</td>
<td> <td>
{% for gameplayer in current_user.player_games if gameplayer.game == game %} {% for gameplayer in current_user.user_games if gameplayer.game == game %}
{{ gameplayer.role.name }} {{ gameplayer.role.name }}
{% endfor %} {% endfor %}
</td> </td>

74
app/tests/test_models.py

@ -1,6 +1,6 @@
import unittest import unittest
from app import create_app, db from app import create_app, db
from app.models import Player, Game, Role, GamePlayer, Objective, ObjectiveMinimalEncoder, LocationEncoder from app.models import User, Game, Role, GamePlayer, Objective, ObjectiveMinimalEncoder, LocationEncoder
from config import Config from config import Config
class TestConfig(Config): class TestConfig(Config):
@ -24,49 +24,49 @@ class ModelsCase(unittest.TestCase):
def test_is_game_owner(self): def test_is_game_owner(self):
g1 = Game(name='TestGame') g1 = Game(name='TestGame')
p1 = Player(name='Henk') u1 = User(name='Henk')
p2 = Player(name='Alfred') u2 = User(name='Alfred')
g1.game_players.append(GamePlayer(player=p1, role=Role.owner)) g1.game_players.append(GamePlayer(player=u1, role=Role.owner))
g1.game_players.append(GamePlayer(player=p2, role=Role.bunny)) g1.game_players.append(GamePlayer(player=u2, role=Role.bunny))
db.session.add(g1) db.session.add(g1)
db.session.commit() db.session.commit()
self.assertTrue(g1.is_game_owner(p1)) self.assertTrue(g1.is_game_owner(u1))
self.assertFalse(g1.is_game_owner(p2)) self.assertFalse(g1.is_game_owner(u2))
def test_is_player_game_owner(self): def test_is_player_game_owner(self):
g1 = Game(name='TestGame') g1 = Game(name='TestGame')
g2 = Game(name='AnotherGame') g2 = Game(name='AnotherGame')
p1 = Player(name='Henk') u1 = User(name='Henk')
p2 = Player(name='Alfred') u2 = User(name='Alfred')
p3 = Player(name='Sasha') u3 = User(name='Sasha')
g1.game_players.append(GamePlayer(player=p1, role=Role.owner)) g1.game_players.append(GamePlayer(player=u1, role=Role.owner))
g1.game_players.append(GamePlayer(player=p2, role=Role.bunny)) g1.game_players.append(GamePlayer(player=u2, role=Role.bunny))
g2.game_players.append(GamePlayer(player=p1, role=Role.hunter)) g2.game_players.append(GamePlayer(player=u1, role=Role.hunter))
g2.game_players.append(GamePlayer(player=p3, role=Role.bunny)) g2.game_players.append(GamePlayer(player=u3, role=Role.bunny))
db.session.add(g1) db.session.add(g1)
db.session.add(g2) db.session.add(g2)
db.session.commit() db.session.commit()
self.assertTrue(p1.owns_game_played_by(player=p2), "owner owns subject_player's game") self.assertTrue(u1.owns_game_played_by(player=u2), "owner owns subject_player's game")
self.assertFalse(p1.owns_game_played_by(player=p3), "owner doesn't own subject_player's game") self.assertFalse(u1.owns_game_played_by(player=u3), "owner doesn't own subject_player's game")
self.assertTrue(p1.owns_game_played_by(player=p1), "owner owns it own's game") self.assertTrue(u1.owns_game_played_by(player=u1), "owner owns it own's game")
def test_is_objective_owner(self): def test_is_objective_owner(self):
g1 = Game(name='TestGame') g1 = Game(name='TestGame')
g2 = Game(name='AnotherGame') g2 = Game(name='AnotherGame')
p1 = Player(name='Henk') u1 = User(name='Henk')
g1.game_players.append(GamePlayer(player=p1, role=Role.owner)) g1.game_players.append(GamePlayer(player=u1, role=Role.owner))
g2.game_players.append(GamePlayer(player=p1, role=Role.bunny)) g2.game_players.append(GamePlayer(player=u1, role=Role.bunny))
o1 = Objective(name='o1') o1 = Objective(name='o1')
o1.set_hash() o1.set_hash()
@ -80,32 +80,32 @@ class ModelsCase(unittest.TestCase):
db.session.add(g2) db.session.add(g2)
db.session.commit() db.session.commit()
self.assertTrue(o1.owned_by(p1)) self.assertTrue(o1.owned_by(u1))
self.assertFalse(o2.owned_by(p1)) self.assertFalse(o2.owned_by(u1))
def test_role_in_game(self): def test_role_in_game(self):
g1 = Game(name='TestGame') g1 = Game(name='TestGame')
p1 = Player(name='Henk') u1 = User(name='Henk')
p2 = Player(name='Alfred') u2 = User(name='Alfred')
p3 = Player(name='Sasha') u3 = User(name='Sasha')
p4 = Player(name='Demian') u4 = User(name='Demian')
p5 = Player(name='Karl') u5 = User(name='Karl')
g1.game_players.append(GamePlayer(player=p1, role=Role.owner)) g1.game_players.append(GamePlayer(player=u1, role=Role.owner))
g1.game_players.append(GamePlayer(player=p2, role=Role.bunny)) g1.game_players.append(GamePlayer(player=u2, role=Role.bunny))
g1.game_players.append(GamePlayer(player=p3, role=Role.hunter)) g1.game_players.append(GamePlayer(player=u3, role=Role.hunter))
g1.game_players.append(GamePlayer(player=p4, role=Role.none)) g1.game_players.append(GamePlayer(player=u4, role=Role.none))
db.session.add(g1) db.session.add(g1)
db.session.add(p5) db.session.add(u5)
db.session.commit() db.session.commit()
self.assertEqual(p1.role_in_game(g1), Role.owner) self.assertEqual(u1.role_in_game(g1), Role.owner)
self.assertEqual(p2.role_in_game(g1), Role.bunny) self.assertEqual(u2.role_in_game(g1), Role.bunny)
self.assertEqual(p3.role_in_game(g1), Role.hunter) self.assertEqual(u3.role_in_game(g1), Role.hunter)
self.assertEqual(p4.role_in_game(g1), Role.none) self.assertEqual(u4.role_in_game(g1), Role.none)
self.assertEqual(p5.role_in_game(g1), None) self.assertEqual(u5.role_in_game(g1), None)
with self.assertRaises(AttributeError): with self.assertRaises(AttributeError):
g1.get_role_for_game(None) g1.get_role_for_game(None)

121
database_dump.txt

@ -0,0 +1,121 @@
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 'initiated' NOT NULL,
start_time DATETIME,
end_time DATETIME,
PRIMARY KEY (id),
CONSTRAINT gamestate CHECK (state IN ('initiated', 'published', 'started', 'interrupted', 'finished'))
);
INSERT INTO game VALUES(1,'Marijns Game','initiated','2020-07-09 12:56:00.000000',NULL);
INSERT INTO game VALUES(2,'Spelletje','initiated',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;

50
migrations/versions/35d99c2732cb_reset_migrations.py → migrations/versions/1d844798c277_reset_migrations.py

@ -1,8 +1,8 @@
"""reset migrations """reset migrations
Revision ID: 35d99c2732cb Revision ID: 1d844798c277
Revises: Revises:
Create Date: 2020-07-18 18:02:51.537046 Create Date: 2020-07-18 23:47:44.369860
""" """
from alembic import op from alembic import op
@ -10,7 +10,7 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = '35d99c2732cb' revision = '1d844798c277'
down_revision = None down_revision = None
branch_labels = None branch_labels = None
depends_on = None depends_on = None
@ -27,7 +27,7 @@ def upgrade():
sa.PrimaryKeyConstraint('id') sa.PrimaryKeyConstraint('id')
) )
op.create_index(op.f('ix_game_name'), 'game', ['name'], unique=True) op.create_index(op.f('ix_game_name'), 'game', ['name'], unique=True)
op.create_table('player', op.create_table('user',
sa.Column('id', sa.Integer(), nullable=False), sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=64), nullable=False), sa.Column('name', sa.String(length=64), nullable=False),
sa.Column('auth_hash', sa.String(length=32), nullable=True), sa.Column('auth_hash', sa.String(length=32), nullable=True),
@ -37,20 +37,22 @@ def upgrade():
sa.UniqueConstraint('name') sa.UniqueConstraint('name')
) )
op.create_table('game_player', op.create_table('game_player',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('game_id', sa.Integer(), nullable=False), sa.Column('game_id', sa.Integer(), nullable=False),
sa.Column('player_id', sa.Integer(), nullable=False), sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('role', sa.Enum('none', 'owner', 'hunter', 'bunny', name='role'), server_default='none', nullable=False), sa.Column('role', sa.Enum('none', 'owner', 'hunter', 'bunny', name='role'), server_default='none', nullable=False),
sa.ForeignKeyConstraint(['game_id'], ['game.id'], ), sa.ForeignKeyConstraint(['game_id'], ['game.id'], ),
sa.ForeignKeyConstraint(['player_id'], ['player.id'], ), sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('game_id', 'player_id') sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('game_id', 'user_id', name='_game_user_uc')
) )
op.create_table('location', op.create_table('location',
sa.Column('id', sa.Integer(), nullable=False), sa.Column('id', sa.Integer(), nullable=False),
sa.Column('player_id', sa.Integer(), nullable=False), sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('longitude', sa.Numeric(precision=15, scale=10, asdecimal=False), nullable=False), sa.Column('longitude', sa.Numeric(precision=15, scale=10, asdecimal=False), nullable=False),
sa.Column('latitude', sa.Numeric(precision=15, scale=10, asdecimal=False), nullable=False), sa.Column('latitude', sa.Numeric(precision=15, scale=10, asdecimal=False), nullable=False),
sa.Column('timestamp', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False), sa.Column('timestamp', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False),
sa.ForeignKeyConstraint(['player_id'], ['player.id'], ), sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id') sa.PrimaryKeyConstraint('id')
) )
op.create_table('notification', op.create_table('notification',
@ -73,32 +75,32 @@ def upgrade():
sa.PrimaryKeyConstraint('id'), sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('hash') sa.UniqueConstraint('hash')
) )
op.create_table('notification_player',
sa.Column('notification_id', sa.Integer(), nullable=False),
sa.Column('game_player_id', sa.Integer(), nullable=False),
sa.Column('been_shown', sa.Boolean(), server_default='True', nullable=False),
sa.ForeignKeyConstraint(['game_player_id'], ['game_player.id'], ),
sa.ForeignKeyConstraint(['notification_id'], ['notification.id'], ),
sa.PrimaryKeyConstraint('notification_id', 'game_player_id')
)
op.create_table('player_caught_player', op.create_table('player_caught_player',
sa.Column('id', sa.Integer(), server_default='-1', autoincrement=True, nullable=False), sa.Column('id', sa.Integer(), server_default='-1', autoincrement=True, nullable=False),
sa.Column('catching_player_id', sa.Integer(), nullable=False), sa.Column('catching_player_id', sa.Integer(), nullable=False),
sa.Column('caught_player_id', sa.Integer(), nullable=False), sa.Column('caught_player_id', sa.Integer(), nullable=False),
sa.Column('photo_reference', sa.String(length=128), nullable=False), sa.Column('photo_reference', sa.String(length=128), nullable=False),
sa.Column('timestamp', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False), sa.Column('timestamp', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False),
sa.ForeignKeyConstraint(['catching_player_id'], ['player.id'], ), sa.ForeignKeyConstraint(['catching_player_id'], ['game_player.id'], ),
sa.ForeignKeyConstraint(['caught_player_id'], ['player.id'], ), sa.ForeignKeyConstraint(['caught_player_id'], ['game_player.id'], ),
sa.PrimaryKeyConstraint('id'), sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('photo_reference') sa.UniqueConstraint('photo_reference')
) )
op.create_table('notification_player',
sa.Column('notification_id', sa.Integer(), nullable=False),
sa.Column('player_id', sa.Integer(), nullable=False),
sa.Column('been_shown', sa.Boolean(), server_default='True', nullable=False),
sa.ForeignKeyConstraint(['notification_id'], ['notification.id'], ),
sa.ForeignKeyConstraint(['player_id'], ['player.id'], ),
sa.PrimaryKeyConstraint('notification_id', 'player_id')
)
op.create_table('player_found_objective', op.create_table('player_found_objective',
sa.Column('objective_id', sa.Integer(), server_default='-1', nullable=False), sa.Column('objective_id', sa.Integer(), server_default='-1', nullable=False),
sa.Column('player_id', sa.Integer(), server_default='-1', nullable=False), sa.Column('game_player_id', sa.Integer(), server_default='-1', nullable=False),
sa.Column('timestamp', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False), sa.Column('timestamp', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False),
sa.ForeignKeyConstraint(['game_player_id'], ['game_player.id'], ),
sa.ForeignKeyConstraint(['objective_id'], ['objective.id'], ), sa.ForeignKeyConstraint(['objective_id'], ['objective.id'], ),
sa.ForeignKeyConstraint(['player_id'], ['player.id'], ), sa.PrimaryKeyConstraint('objective_id', 'game_player_id')
sa.PrimaryKeyConstraint('objective_id', 'player_id')
) )
# ### end Alembic commands ### # ### end Alembic commands ###
@ -106,13 +108,13 @@ def upgrade():
def downgrade(): def downgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_table('player_found_objective') op.drop_table('player_found_objective')
op.drop_table('notification_player')
op.drop_table('player_caught_player') op.drop_table('player_caught_player')
op.drop_table('notification_player')
op.drop_table('objective') op.drop_table('objective')
op.drop_table('notification') op.drop_table('notification')
op.drop_table('location') op.drop_table('location')
op.drop_table('game_player') op.drop_table('game_player')
op.drop_table('player') op.drop_table('user')
op.drop_index(op.f('ix_game_name'), table_name='game') op.drop_index(op.f('ix_game_name'), table_name='game')
op.drop_table('game') op.drop_table('game')
# ### end Alembic commands ### # ### end Alembic commands ###

32
the_hunt.py

@ -1,12 +1,12 @@
from app import create_app, db from app import create_app, db
from app.models import Game, Player, Objective, Location, Notification, GamePlayer, \ from app.models import Game, User, Objective, Location, Notification, GamePlayer, \
PlayerFoundObjective, NotificationPlayer, PlayerCaughtPlayer, Role, GameState PlayerFoundObjective, NotificationPlayer, PlayerCaughtPlayer, Role, GameState
app = create_app() app = create_app()
@app.shell_context_processor @app.shell_context_processor
def make_shell_context(): def make_shell_context():
return {'db': db, 'Game' : Game, 'Player' : Player, 'Objective' : Objective, return {'db': db, 'Game' : Game, 'User' : User, 'Objective' : Objective,
'Location' : Location, 'Notification' : Notification, 'GamePlayer' : GamePlayer, 'Location' : Location, 'Notification' : Notification, 'GamePlayer' : GamePlayer,
'PlayerFoundObjective' : PlayerFoundObjective, 'NotificationPlayer' : NotificationPlayer, 'PlayerFoundObjective' : PlayerFoundObjective, 'NotificationPlayer' : NotificationPlayer,
'PlayerCaughtPlayer' : PlayerCaughtPlayer, 'Role' : Role, 'GameState' : GameState, 'PlayerCaughtPlayer' : PlayerCaughtPlayer, 'Role' : Role, 'GameState' : GameState,
@ -16,21 +16,23 @@ def create_objects():
g1 = Game(name='TestGame') g1 = Game(name='TestGame')
g2 = Game(name='MyGame') g2 = Game(name='MyGame')
p1 = Player(name='Marijn') u1 = User(name='Marijn')
p2 = Player(name='Rogier') u1.set_password('123')
p3 = Player(name='Henk') u2 = User(name='Rogier')
p4 = Player(name='Emma') u2.set_password('123')
p5 = Player(name='Demi') u3 = User(name='Henk')
u4 = User(name='Emma')
u5 = User(name='Demi')
g1.game_players.append(GamePlayer(player=p1, role=Role.owner)) g1.game_players.append(GamePlayer(user=u1, role=Role.owner))
g1.game_players.append(GamePlayer(player=p2, role=Role.hunter)) g1.game_players.append(GamePlayer(user=u2, role=Role.hunter))
g1.game_players.append(GamePlayer(player=p3, role=Role.hunter)) g1.game_players.append(GamePlayer(user=u3, role=Role.hunter))
g1.game_players.append(GamePlayer(player=p4, role=Role.bunny)) g1.game_players.append(GamePlayer(user=u4, role=Role.bunny))
g1.game_players.append(GamePlayer(player=p5, role=Role.bunny)) g1.game_players.append(GamePlayer(user=u5, role=Role.bunny))
g2.game_players.append(GamePlayer(player=p1, role=Role.bunny)) g2.game_players.append(GamePlayer(user=u1, role=Role.bunny))
g2.game_players.append(GamePlayer(player=p2, role=Role.owner)) g2.game_players.append(GamePlayer(user=u2, role=Role.owner))
g2.game_players.append(GamePlayer(player=p3, role=Role.hunter)) g2.game_players.append(GamePlayer(user=u3, role=Role.hunter))
db.session.add(g1) db.session.add(g1)
db.session.add(g2) db.session.add(g2)

Loading…
Cancel
Save