Burathar
4 years ago
13 changed files with 308 additions and 268 deletions
@ -1,268 +0,0 @@
@@ -1,268 +0,0 @@
|
||||
from enum import Enum |
||||
from secrets import token_hex |
||||
from datetime import datetime |
||||
from json import JSONEncoder |
||||
from flask_login import UserMixin |
||||
from werkzeug.security import generate_password_hash, check_password_hash |
||||
from sqlalchemy.ext.associationproxy import association_proxy |
||||
from sqlalchemy.sql import func |
||||
from flask_moment import Moment |
||||
from app import db, login |
||||
|
||||
moment = Moment() |
||||
|
||||
class Role(Enum): |
||||
none = 0 |
||||
owner = 1 |
||||
hunter = 2 |
||||
bunny = 3 |
||||
|
||||
class GameState(Enum): |
||||
initiated = 1 |
||||
published = 2 |
||||
started = 3 |
||||
interrupted = 4 |
||||
finished = 5 |
||||
|
||||
class GamePlayer(db.Model): |
||||
__tablename__ = 'game_player' |
||||
game_id = db.Column(db.Integer, db.ForeignKey('game.id'), primary_key=True, nullable=False) |
||||
player_id = db.Column(db.Integer, db.ForeignKey('player.id'), primary_key=True, nullable=False) |
||||
role = db.Column(db.Enum(Role), server_default=Role(0).name, nullable=False) |
||||
game = db.relationship('Game', back_populates='game_players') |
||||
player = db.relationship('Player', back_populates='player_games') |
||||
|
||||
class PlayerFoundObjective(db.Model): |
||||
__tablename__ = 'player_found_objective' |
||||
objective_id = db.Column(db.Integer, db.ForeignKey('objective.id'), primary_key=True, nullable=False, server_default='-1') |
||||
player_id = db.Column(db.Integer, db.ForeignKey('player.id'), primary_key=True, nullable=False, server_default='-1') |
||||
timestamp = db.Column(db.DateTime, server_default=func.now(), nullable=False) |
||||
player = db.relationship('Player', back_populates='player_found_objectives') |
||||
objective = db.relationship('Objective', back_populates='objective_found_by') |
||||
|
||||
class NotificationPlayer(db.Model): |
||||
__tablename__ = 'notification_player' |
||||
notification_id = db.Column(db.Integer, db.ForeignKey('notification.id'), primary_key=True, nullable=False) |
||||
player_id= db.Column(db.Integer, db.ForeignKey('player.id'), primary_key=True, nullable=False) |
||||
been_shown = db.Column(db.Boolean, server_default='True', nullable=False) |
||||
notification = db.relationship('Notification', back_populates='notification_recipients') |
||||
recipient = db.relationship('Player', back_populates='player_notifications') |
||||
|
||||
class PlayerCaughtPlayer(db.Model): |
||||
__tablename__ = 'player_caught_player' |
||||
id = db.Column(db.Integer, primary_key=True, autoincrement=True, server_default='-1') |
||||
catching_player_id = db.Column(db.Integer, db.ForeignKey('player.id'), nullable=False) |
||||
caught_player_id = db.Column(db.Integer, db.ForeignKey('player.id'), nullable=False) |
||||
photo_reference = db.Column(db.String(128), unique=True, nullable=False) |
||||
timestamp = db.Column(db.DateTime, server_default=func.now(), nullable=False) |
||||
catching_player = db.relationship('Player', back_populates='player_caught_by_players', foreign_keys=[catching_player_id]) |
||||
caught_player = db.relationship('Player', back_populates='player_caught_players', foreign_keys=[caught_player_id]) |
||||
|
||||
class Game(db.Model): |
||||
__tablename__ = 'game' |
||||
id = db.Column(db.Integer, primary_key=True) |
||||
name = db.Column(db.String(64), index=True, unique=True, nullable=False) |
||||
state = db.Column(db.Enum(GameState), server_default=GameState(1).name, nullable=False) |
||||
start_time = db.Column(db.DateTime) |
||||
end_time = db.Column(db.DateTime) |
||||
game_players = db.relationship( |
||||
'GamePlayer', |
||||
back_populates='game', |
||||
cascade="save-update, merge, delete, delete-orphan") |
||||
players = association_proxy('game_players', 'player', |
||||
creator=lambda player: GamePlayer(player=player)) # to enable game.players.append(player) |
||||
objectives = db.relationship( |
||||
'Objective', |
||||
lazy='select', |
||||
backref=db.backref('game', lazy='joined')) |
||||
notifications = db.relationship( |
||||
'Notification', |
||||
lazy='select', |
||||
backref=db.backref('game', lazy='joined')) |
||||
|
||||
def last_player_locations(self): |
||||
return [player.last_location(self) for player in self.players if player.locations] |
||||
|
||||
def bunnies(self): |
||||
# pylint: disable=not-an-iterable |
||||
return [gameplayer.player for gameplayer in self.game_players if gameplayer.role == Role.bunny] |
||||
|
||||
def last_locations(self, players): |
||||
locations = [] |
||||
for player in players: |
||||
locations.append(player.last_location(self)) |
||||
return locations |
||||
|
||||
def owned_by(self, player): |
||||
# pylint: disable=not-an-iterable |
||||
'''given player is an owner of game''' |
||||
return player in [gameplayer.player for gameplayer in self.game_players if gameplayer.role == Role.owner] |
||||
|
||||
class Player(UserMixin, db.Model): |
||||
""" !Always call set_auth_hash() after creating new instance! """ |
||||
__tablename__ = 'player' |
||||
id = db.Column(db.Integer, primary_key=True) |
||||
name = db.Column(db.String(64), unique=True, nullable=False) |
||||
auth_hash = db.Column(db.String(32), unique=True, nullable=True) |
||||
password_hash = db.Column(db.String(128)) |
||||
|
||||
player_games = db.relationship( |
||||
'GamePlayer', |
||||
back_populates='player', |
||||
cascade='save-update, merge, delete, delete-orphan') |
||||
games = association_proxy('player_games', 'game', |
||||
creator=lambda game: GamePlayer(game=game)) |
||||
|
||||
player_found_objectives = db.relationship( |
||||
'PlayerFoundObjective', |
||||
back_populates='player', |
||||
cascade='save-update, merge, delete, delete-orphan') |
||||
found_objectives = association_proxy('player_found_objectives', 'objective', |
||||
creator=lambda objective: PlayerFoundObjective(objective=objective)) |
||||
|
||||
player_notifications = db.relationship( |
||||
'NotificationPlayer', |
||||
back_populates='recipient', |
||||
cascade='save-update, merge, delete, delete-orphan') |
||||
notifications = association_proxy('player_notifications', 'notification', |
||||
creator=lambda notification: NotificationPlayer(notification=notification)) |
||||
|
||||
player_caught_players = db.relationship( |
||||
'PlayerCaughtPlayer', |
||||
back_populates='catching_player', |
||||
cascade='save-update, merge, delete, delete-orphan', |
||||
foreign_keys=[PlayerCaughtPlayer.catching_player_id]) |
||||
caught_players = association_proxy('player_caught_players', 'player', |
||||
creator=lambda player: PlayerCaughtPlayer(caught_player=player)) |
||||
|
||||
player_caught_by_players = db.relationship( |
||||
'PlayerCaughtPlayer', |
||||
back_populates='caught_player', |
||||
cascade='save-update, merge, delete, delete-orphan', |
||||
foreign_keys=[PlayerCaughtPlayer.caught_player_id]) |
||||
caught_by_players = association_proxy('player_caught_by_players', 'player', |
||||
creator=lambda player: PlayerCaughtPlayer(catching_player=player)) |
||||
|
||||
locations = db.relationship( |
||||
'Location', |
||||
lazy='select', |
||||
backref=db.backref('player', lazy='joined')) |
||||
|
||||
def set_password(self, password): |
||||
self.password_hash = generate_password_hash(password) |
||||
|
||||
def set_auth_hash(self): |
||||
self.auth_hash = token_hex(16) |
||||
|
||||
def check_password(self, password): |
||||
return check_password_hash(self.password_hash, password) |
||||
|
||||
def locations_during_game(self, game): |
||||
# pylint: disable=not-an-iterable |
||||
if not self.locations: |
||||
return None |
||||
if game is None: |
||||
return self.locations |
||||
game_start = game.start_time or datetime.min |
||||
game_end = game.end_time or datetime.max |
||||
return (location for location in self.locations if location.timestamp > game_start and location.timestamp < game_end) |
||||
|
||||
def last_location(self, game=None): |
||||
# pylint: disable=not-an-iterable |
||||
if not self.locations: |
||||
return None |
||||
if game is None: |
||||
return max(self.locations, key=lambda location: location.timestamp) |
||||
return max(self.locations_during_game(game), key=lambda location: location.timestamp) |
||||
|
||||
def role_in_game(self, game): |
||||
'''returns the role as Role enum of player in given game. Returns None if player does not participate in game''' |
||||
# pylint: disable=not-an-iterable |
||||
gameplayers = [gameplayer for gameplayer in self.player_games if gameplayer.game == game] |
||||
if not gameplayers: |
||||
return None |
||||
return gameplayers[0].role |
||||
|
||||
def owns_game_played_by(self, player): |
||||
'''self is an owner of a game the player participates in''' |
||||
return self in [gameplayer.player for gameplayers in |
||||
[game.game_players for game in player.games] |
||||
for gameplayer in gameplayers if gameplayer.role == Role.owner] |
||||
|
||||
@staticmethod |
||||
def delete_orphans(): |
||||
Player.query.filter(~Player.player_games.any()).delete() |
||||
db.session.commit() |
||||
|
||||
@login.user_loader |
||||
def load_user(id): |
||||
return Player.query.get(int(id)) |
||||
|
||||
class Objective(db.Model): |
||||
""" !Always call set_hash after() creating new instance! """ |
||||
__tablename__ = 'objective' |
||||
id = db.Column(db.Integer, primary_key=True) |
||||
name = db.Column(db.String(64)) |
||||
game_id = db.Column(db.Integer, db.ForeignKey('game.id'), nullable=False) |
||||
hash = db.Column(db.String(32), unique=True, nullable=False) |
||||
longitude = db.Column(db.Numeric(precision=15, scale=10, asdecimal=False, decimal_return_scale=None)) # maybe check asdecimal and decimal_return_scale later? |
||||
latitude = db.Column(db.Numeric(precision=15, scale=10, asdecimal=False, decimal_return_scale=None)) |
||||
objective_found_by = db.relationship( |
||||
'PlayerFoundObjective', |
||||
back_populates='objective', |
||||
cascade='save-update, merge, delete, delete-orphan') |
||||
found_by = association_proxy('objective_found_by', 'player', |
||||
creator=lambda player: PlayerFoundObjective(player=player)) |
||||
|
||||
def set_hash(self): |
||||
self.hash = token_hex(16) |
||||
|
||||
def owned_by(self, player): |
||||
'''given player is an owner of a game object is part of''' |
||||
return player in [gameplayer.player for gameplayer in self.game.game_players if gameplayer.role == Role.owner] |
||||
|
||||
class ObjectiveMinimalEncoder(JSONEncoder): |
||||
def default(self, objective): |
||||
return { |
||||
'name' : objective.name, |
||||
'hash' : objective.hash, |
||||
'longitude' : objective.longitude, |
||||
'latitude' : objective.latitude |
||||
} |
||||
|
||||
class Location(db.Model): |
||||
__tablename__ = 'location' |
||||
id = db.Column(db.Integer, primary_key=True) |
||||
player_id = db.Column(db.Integer, db.ForeignKey('player.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? |
||||
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) |
||||
|
||||
def __str__(self): |
||||
return f'{self.longitude}, {self.latitude}' |
||||
|
||||
class LocationEncoder(JSONEncoder): |
||||
def default(self, location): |
||||
return { |
||||
'player_name' : location.player.name, |
||||
'longitude' : location.longitude, |
||||
'latitude' : location.latitude, |
||||
'timestamp_utc' : str(location.timestamp) |
||||
} |
||||
|
||||
class Notification(db.Model): |
||||
__tablename__ = 'notification' |
||||
id = db.Column(db.Integer, primary_key=True) |
||||
game_id = db.Column(db.Integer, db.ForeignKey('game.id'), nullable=False) |
||||
message = db.Column(db.Text, nullable=False) |
||||
type = db.Column(db.String(64), nullable=False, default='General') |
||||
timestamp = db.Column(db.DateTime, server_default=func.now(), nullable=False) |
||||
|
||||
notification_recipients = db.relationship( |
||||
'NotificationPlayer', |
||||
back_populates='notification', |
||||
cascade='save-update, merge, delete, delete-orphan') |
||||
recipients = association_proxy('notification_recipients', 'player', |
||||
creator=lambda player: NotificationPlayer(recipient=player)) |
||||
|
||||
#start_time = db.Column(db.DateTime, server_default=func.now()) |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
from app import login |
||||
|
||||
from app.models.game import Game |
||||
from app.models.game_player import GamePlayer |
||||
from app.models.game_state import GameState |
||||
from app.models.location import Location, LocationEncoder |
||||
from app.models.notification_player import NotificationPlayer |
||||
from app.models.objective import Objective, ObjectiveMinimalEncoder |
||||
from app.models.player_caught_player import PlayerCaughtPlayer |
||||
from app.models.player_found_objective import PlayerFoundObjective |
||||
from app.models.role import Role |
||||
from app.models.user import User |
||||
|
||||
@login.user_loader |
||||
def load_user(id): |
||||
return User.query.get(int(id)) |
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
from sqlalchemy.ext.associationproxy import association_proxy |
||||
from app import db |
||||
from app.models import GameState, GamePlayer, Role |
||||
|
||||
class Game(db.Model): |
||||
__tablename__ = 'game' |
||||
id = db.Column(db.Integer, primary_key=True) |
||||
name = db.Column(db.String(64), index=True, unique=True, nullable=False) |
||||
state = db.Column(db.Enum(GameState), server_default=GameState(1).name, nullable=False) |
||||
start_time = db.Column(db.DateTime) |
||||
end_time = db.Column(db.DateTime) |
||||
game_players = db.relationship( |
||||
'GamePlayer', |
||||
back_populates='game', |
||||
cascade="save-update, merge, delete, delete-orphan") |
||||
users = association_proxy('game_players', 'user', |
||||
creator=lambda user: GamePlayer(user=user)) # to enable game.players.append(player) |
||||
objectives = db.relationship( |
||||
'Objective', |
||||
lazy='select', |
||||
backref=db.backref('game', lazy='joined')) |
||||
notifications = db.relationship( |
||||
'Notification', |
||||
lazy='select', |
||||
backref=db.backref('game', lazy='joined')) |
||||
|
||||
def last_player_locations(self): |
||||
return [player.last_location(self) for player in self.users if player.locations] |
||||
|
||||
def bunnies(self): |
||||
# pylint: disable=not-an-iterable |
||||
return [gameplayer.player for gameplayer in self.game_players if gameplayer.role == Role.bunny] |
||||
|
||||
def last_locations(self, players): |
||||
locations = [] |
||||
for player in players: |
||||
locations.append(player.last_location(self)) |
||||
return locations |
||||
|
||||
def owned_by(self, player): |
||||
# pylint: disable=not-an-iterable |
||||
'''given player is an owner of game''' |
||||
return player in [gameplayer.player for gameplayer in self.game_players if gameplayer.role == Role.owner] |
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
from app import db |
||||
from app.models import Role |
||||
|
||||
class GamePlayer(db.Model): |
||||
__tablename__ = 'game_player' |
||||
game_id = db.Column(db.Integer, db.ForeignKey('game.id'), primary_key=True, nullable=False) |
||||
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True, nullable=False) |
||||
role = db.Column(db.Enum(Role), server_default=Role(0).name, nullable=False) |
||||
game = db.relationship('Game', back_populates='game_players') |
||||
user = db.relationship('User', back_populates='user_games') |
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
from enum import Enum |
||||
|
||||
class GameState(Enum): |
||||
initiated = 1 |
||||
published = 2 |
||||
started = 3 |
||||
interrupted = 4 |
||||
finished = 5 |
||||
|
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
from json import JSONEncoder |
||||
from sqlalchemy.sql import func |
||||
|
||||
from app import db |
||||
|
||||
class Location(db.Model): |
||||
__tablename__ = 'location' |
||||
id = db.Column(db.Integer, primary_key=True) |
||||
player_id = db.Column(db.Integer, db.ForeignKey('player.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? |
||||
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) |
||||
|
||||
def __str__(self): |
||||
return f'{self.longitude}, {self.latitude}' |
||||
|
||||
class LocationEncoder(JSONEncoder): |
||||
def default(self, location): |
||||
return { |
||||
'player_name' : location.player.name, |
||||
'longitude' : location.longitude, |
||||
'latitude' : location.latitude, |
||||
'timestamp_utc' : str(location.timestamp) |
||||
} |
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
from sqlalchemy.ext.associationproxy import association_proxy |
||||
from sqlalchemy.sql import func |
||||
|
||||
from app import db |
||||
from app.models import NotificationPlayer |
||||
|
||||
class Notification(db.Model): |
||||
__tablename__ = 'notification' |
||||
id = db.Column(db.Integer, primary_key=True) |
||||
game_id = db.Column(db.Integer, db.ForeignKey('game.id'), nullable=False) |
||||
message = db.Column(db.Text, nullable=False) |
||||
type = db.Column(db.String(64), nullable=False, default='General') |
||||
timestamp = db.Column(db.DateTime, server_default=func.now(), nullable=False) |
||||
|
||||
notification_recipients = db.relationship( |
||||
'NotificationPlayer', |
||||
back_populates='notification', |
||||
cascade='save-update, merge, delete, delete-orphan') |
||||
recipients = association_proxy('notification_recipients', 'player', |
||||
creator=lambda player: NotificationPlayer(recipient=player)) |
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
from app import db |
||||
|
||||
class NotificationPlayer(db.Model): |
||||
__tablename__ = 'notification_player' |
||||
notification_id = db.Column(db.Integer, db.ForeignKey('notification.id'), primary_key=True, nullable=False) |
||||
player_id = db.Column(db.Integer, db.ForeignKey('player.id'), primary_key=True, nullable=False) |
||||
been_shown = db.Column(db.Boolean, server_default='True', nullable=False) |
||||
notification = db.relationship('Notification', back_populates='notification_recipients') |
||||
recipient = db.relationship('Player', back_populates='player_notifications') |
||||
|
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
from secrets import token_hex |
||||
from json import JSONEncoder |
||||
from sqlalchemy.ext.associationproxy import association_proxy |
||||
|
||||
from app import db |
||||
from app.models import PlayerFoundObjective, Role |
||||
|
||||
class Objective(db.Model): |
||||
""" !Always call set_hash after() creating new instance! """ |
||||
__tablename__ = 'objective' |
||||
id = db.Column(db.Integer, primary_key=True) |
||||
name = db.Column(db.String(64)) |
||||
game_id = db.Column(db.Integer, db.ForeignKey('game.id'), nullable=False) |
||||
hash = db.Column(db.String(32), unique=True, nullable=False) |
||||
longitude = db.Column(db.Numeric(precision=15, scale=10, asdecimal=False, decimal_return_scale=None)) # maybe check asdecimal and decimal_return_scale later? |
||||
latitude = db.Column(db.Numeric(precision=15, scale=10, asdecimal=False, decimal_return_scale=None)) |
||||
objective_found_by = db.relationship( |
||||
'PlayerFoundObjective', |
||||
back_populates='objective', |
||||
cascade='save-update, merge, delete, delete-orphan') |
||||
found_by = association_proxy('objective_found_by', 'player', |
||||
creator=lambda player: PlayerFoundObjective(player=player)) |
||||
|
||||
def set_hash(self): |
||||
self.hash = token_hex(16) |
||||
|
||||
def owned_by(self, player): |
||||
'''given player is an owner of a game object is part of''' |
||||
return player in [gameplayer.player for gameplayer in self.game.game_players if gameplayer.role == Role.owner] |
||||
|
||||
class ObjectiveMinimalEncoder(JSONEncoder): |
||||
def default(self, objective): |
||||
return { |
||||
'name' : objective.name, |
||||
'hash' : objective.hash, |
||||
'longitude' : objective.longitude, |
||||
'latitude' : objective.latitude |
||||
} |
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
from sqlalchemy.sql import func |
||||
|
||||
from app import db |
||||
|
||||
class PlayerCaughtPlayer(db.Model): |
||||
__tablename__ = 'player_caught_player' |
||||
id = db.Column(db.Integer, primary_key=True, autoincrement=True, server_default='-1') |
||||
catching_player_id = db.Column(db.Integer, db.ForeignKey('player.id'), nullable=False) |
||||
caught_player_id = db.Column(db.Integer, db.ForeignKey('player.id'), nullable=False) |
||||
photo_reference = db.Column(db.String(128), unique=True, nullable=False) |
||||
timestamp = db.Column(db.DateTime, server_default=func.now(), nullable=False) |
||||
catching_player = db.relationship('Player', back_populates='player_caught_by_players', foreign_keys=[catching_player_id]) |
||||
caught_player = db.relationship('Player', back_populates='player_caught_players', foreign_keys=[caught_player_id]) |
||||
|
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
from sqlalchemy.sql import func |
||||
|
||||
from app import db |
||||
|
||||
class PlayerFoundObjective(db.Model): |
||||
__tablename__ = 'player_found_objective' |
||||
objective_id = db.Column(db.Integer, db.ForeignKey('objective.id'), primary_key=True, nullable=False, server_default='-1') |
||||
player_id = db.Column(db.Integer, db.ForeignKey('player.id'), primary_key=True, nullable=False, server_default='-1') |
||||
timestamp = db.Column(db.DateTime, server_default=func.now(), nullable=False) |
||||
player = db.relationship('Player', back_populates='player_found_objectives') |
||||
objective = db.relationship('Objective', back_populates='objective_found_by') |
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
from enum import Enum |
||||
|
||||
class Role(Enum): |
||||
none = 0 |
||||
owner = 1 |
||||
hunter = 2 |
||||
bunny = 3 |
||||
|
@ -0,0 +1,105 @@
@@ -0,0 +1,105 @@
|
||||
from secrets import token_hex |
||||
from datetime import datetime |
||||
|
||||
from flask_login import UserMixin |
||||
from sqlalchemy.ext.associationproxy import association_proxy |
||||
from werkzeug.security import generate_password_hash, check_password_hash |
||||
|
||||
from app import db |
||||
from app.models import GamePlayer, PlayerFoundObjective, PlayerCaughtPlayer, NotificationPlayer, Role |
||||
|
||||
class User(UserMixin, db.Model): |
||||
""" !Always call set_auth_hash() after creating new instance! """ |
||||
__tablename__ = 'player' |
||||
id = db.Column(db.Integer, primary_key=True) |
||||
name = db.Column(db.String(64), unique=True, nullable=False) |
||||
auth_hash = db.Column(db.String(32), unique=True, nullable=True) |
||||
password_hash = db.Column(db.String(128)) |
||||
|
||||
user_games = db.relationship( |
||||
'GamePlayer', |
||||
back_populates='user', |
||||
cascade='save-update, merge, delete, delete-orphan') |
||||
games = association_proxy('user_games', 'game', |
||||
creator=lambda game: GamePlayer(game=game)) |
||||
|
||||
player_found_objectives = db.relationship( |
||||
'PlayerFoundObjective', |
||||
back_populates='player', |
||||
cascade='save-update, merge, delete, delete-orphan') |
||||
found_objectives = association_proxy('player_found_objectives', 'objective', |
||||
creator=lambda objective: PlayerFoundObjective(objective=objective)) |
||||
|
||||
player_notifications = db.relationship( |
||||
'NotificationPlayer', |
||||
back_populates='recipient', |
||||
cascade='save-update, merge, delete, delete-orphan') |
||||
notifications = association_proxy('player_notifications', 'notification', |
||||
creator=lambda notification: NotificationPlayer(notification=notification)) |
||||
|
||||
player_caught_players = db.relationship( |
||||
'PlayerCaughtPlayer', |
||||
back_populates='catching_player', |
||||
cascade='save-update, merge, delete, delete-orphan', |
||||
foreign_keys=[PlayerCaughtPlayer.catching_player_id]) |
||||
caught_players = association_proxy('player_caught_players', 'player', |
||||
creator=lambda player: PlayerCaughtPlayer(caught_player=player)) |
||||
|
||||
player_caught_by_players = db.relationship( |
||||
'PlayerCaughtPlayer', |
||||
back_populates='caught_player', |
||||
cascade='save-update, merge, delete, delete-orphan', |
||||
foreign_keys=[PlayerCaughtPlayer.caught_player_id]) |
||||
caught_by_players = association_proxy('player_caught_by_players', 'player', |
||||
creator=lambda player: PlayerCaughtPlayer(catching_player=player)) |
||||
|
||||
locations = db.relationship( |
||||
'Location', |
||||
lazy='select', |
||||
backref=db.backref('player', lazy='joined')) |
||||
|
||||
def set_password(self, password): |
||||
self.password_hash = generate_password_hash(password) |
||||
|
||||
def set_auth_hash(self): |
||||
self.auth_hash = token_hex(16) |
||||
|
||||
def check_password(self, password): |
||||
return check_password_hash(self.password_hash, password) |
||||
|
||||
def locations_during_game(self, game): |
||||
# pylint: disable=not-an-iterable |
||||
if not self.locations: |
||||
return None |
||||
if game is None: |
||||
return self.locations |
||||
game_start = game.start_time or datetime.min |
||||
game_end = game.end_time or datetime.max |
||||
return (location for location in self.locations if location.timestamp > game_start and location.timestamp < game_end) |
||||
|
||||
def last_location(self, game=None): |
||||
# pylint: disable=not-an-iterable |
||||
if not self.locations: |
||||
return None |
||||
if game is None: |
||||
return max(self.locations, key=lambda location: location.timestamp) |
||||
return max(self.locations_during_game(game), key=lambda location: location.timestamp) |
||||
|
||||
def role_in_game(self, game): |
||||
'''returns the role as Role enum of player in given game. Returns None if player does not participate in game''' |
||||
# pylint: disable=not-an-iterable |
||||
gameplayers = [gameplayer for gameplayer in self.user_games if gameplayer.game == game] |
||||
if not gameplayers: |
||||
return None |
||||
return gameplayers[0].role |
||||
|
||||
def owns_game_played_by(self, player): |
||||
'''self is an owner of a game the player participates in''' |
||||
return self in [gameplayer.player for gameplayers in |
||||
[game.game_players for game in player.games] |
||||
for gameplayer in gameplayers if gameplayer.role == Role.owner] |
||||
|
||||
@staticmethod |
||||
def delete_orphans(): |
||||
User.query.filter(~User.user_games.any()).delete() |
||||
db.session.commit() |
Loading…
Reference in new issue