class Bat(DB.Model): """ A class that stores information about a Bat. Columns: id: the bat id game_id: the game that bat took place in team_id: the team the bat was for player_id: the player who took the bat rbi: the number of runs batted in inning: the inning the bat took place classification: how the bat would be classified (see BATS) """ id = DB.Column(DB.Integer, primary_key=True) game_id = DB.Column(DB.Integer, DB.ForeignKey('game.id')) team_id = DB.Column(DB.Integer, DB.ForeignKey('team.id')) player_id = DB.Column(DB.Integer, DB.ForeignKey('player.id')) rbi = DB.Column(DB.Integer) inning = DB.Column(DB.Integer) classification = DB.Column(DB.String(2)) def __init__(self, player_id, team_id, game_id, classification, inning=1, rbi=0): """The constructor. Raises: PlayerDoesNotExist InvalidField TeamDoesNotExist GameDoesNotExist """ # check for exceptions classification = classification.lower().strip() player = Player.query.get(player_id) if player is None: raise PlayerDoesNotExist(payload={'details': player_id}) if not hit_validator(classification, player.gender): raise InvalidField(payload={'details': "Bat - hit"}) if not rbi_validator(rbi): raise InvalidField(payload={'details': "Bat - rbi"}) if not inning_validator(inning): raise InvalidField(payload={'details': "Bat - inning"}) if Team.query.get(team_id) is None: raise TeamDoesNotExist(payload={'details': team_id}) if Game.query.get(game_id) is None: raise GameDoesNotExist(payload={'details': game_id}) # otherwise good and a valid object self.classification = classification self.rbi = rbi self.player_id = player_id self.team_id = team_id self.game_id = game_id self.inning = inning def __repr__(self): """Returns the string representation of the Bat.""" player = Player.query.get(self.player_id) return (player.name + "-" + self.classification + " in " + str(self.inning)) def json(self): """Returns a jsonserializable object.""" return { 'bat_id': self.id, 'game_id': self.game_id, 'team_id': self.team_id, 'team': str(Player.query.get(self.team_id)), 'rbi': self.rbi, 'hit': self.classification, 'inning': self.inning, 'player_id': self.player_id, 'player': str(Player.query.get(self.player_id)) } def update(self, player_id=None, team_id=None, game_id=None, rbi=None, hit=None, inning=None): """Update an existing bat. Raises: TeamDoesNotExist GameDoesNotExist PlayerDoesNotExist InvalidField """ if team_id is not None and Team.query.get(team_id) is not None: self.team_id = team_id elif team_id is not None: raise TeamDoesNotExist(payload={'details': team_id}) if game_id is not None and Game.query.get(game_id) is not None: self.game_id = game_id elif game_id is not None: raise GameDoesNotExist(payload={'details': game_id}) if player_id is not None and Player.query.get(player_id) is not None: self.player_id = player_id elif player_id is not None: raise PlayerDoesNotExist(payload={'details': player_id}) if rbi is not None and rbi_validator(rbi): self.rbi = rbi elif rbi is not None: raise InvalidField(payload={'details': "Bat - rbi"}) if hit is not None and hit_validator(hit): self.classification = hit elif hit is not None: raise InvalidField(payload={'details': "Bat - hit"}) if inning is not None and inning_validator(inning): self.inning = inning elif inning is not None: raise InvalidField(payload={'details': "Bat - inning"})
class Espys(DB.Model): """ A class that stores transaction for ESPY points. Columns: id: the unique id description: the description of the transaction (additional notes) sponsor_id: the id of sponsor that was involved in the transaction points: the amount of points awarded for the transaction ($1=1 pt) date: the date of the transaction receipt: any information regarding the receipt (receipt number) """ id = DB.Column(DB.Integer, primary_key=True) team_id = DB.Column(DB.Integer, DB.ForeignKey('team.id')) description = DB.Column(DB.String(120)) sponsor_id = DB.Column(DB.Integer, DB.ForeignKey('sponsor.id')) points = DB.Column(DB.Float) date = DB.Column(DB.DateTime) receipt = DB.Column(DB.String(30)) def __init__(self, team_id, sponsor_id=None, description=None, points=0.0, receipt=None, time=None, date=None): """The constructor. Raises: SponsorDoesNotExist TeamDoesNotExist """ if not float_validator(points): raise InvalidField(payload={"details": "Game - points"}) self.points = float(points) self.date = datetime.now() sponsor = None if sponsor_id is not None: sponsor = Sponsor.query.get(sponsor_id) self.receipt = receipt if sponsor_id is not None and sponsor is None: raise SponsorDoesNotExist(payload={"details": sponsor_id}) team = Team.query.get(team_id) if team is None: raise TeamDoesNotExist(payload={"details": team_id}) self.description = description self.team_id = team_id self.sponsor_id = sponsor_id self.kik = None if date is not None and not date_validator(date): raise InvalidField(payload={'details': "Game - date"}) if time is not None and not time_validator(time): raise InvalidField(payload={'details': "Game - time"}) if date is not None and time is None: self.date = datetime.strptime(date + "-" + time, '%Y-%m-%d-%H:%M') else: self.date = datetime.today() def update(self, team_id=None, sponsor_id=None, description=None, points=None, receipt=None, date=None, time=None): """Used to update an existing espy transaction. Raises: TeamDoesNotExist SponsorDoesNotExist """ if points is not None: self.points = points if description is not None: self.description = description if team_id is not None: if Team.query.get(team_id) is not None: self.team_id = team_id else: raise TeamDoesNotExist(payload={"details": team_id}) if sponsor_id is not None: if Sponsor.query.get(sponsor_id) is not None: self.sponsor_id = sponsor_id else: raise SponsorDoesNotExist(payload={"details": sponsor_id}) if receipt is not None: self.receipt = receipt if date is not None and time is None: self.date = datetime.strptime(date + "-" + time, '%Y-%m-%d-%H:%M') if date is not None and time is not None: if date is not None and not date_validator(date): raise InvalidField(payload={'details': "Game - date"}) if time is not None and not time_validator(time): raise InvalidField(payload={'details': "Game - time"}) self.date = datetime.strptime(date + "-" + time, '%Y-%m-%d-%H:%M') def json(self): """Returns a jsonserializable object.""" sponsor = (None if self.sponsor_id is None else str( Sponsor.query.get(self.sponsor_id))) team = (None if self.team_id is None else str( Team.query.get(self.team_id))) date = None time = None if self.date is not None: date = self.date.strftime("%Y-%m-%d") time = self.date.strftime("%H:%M") return { 'espy_id': self.id, 'team': team, 'team_id': self.team_id, 'sponsor': sponsor, 'sponsor_id': self.sponsor_id, 'description': self.description, 'points': self.points, 'receipt': self.receipt, 'date': date, 'time': time }
class Game(DB.Model): """ A class that holds information about a Game. Columns: id: the game id home_team_id: the home team's id away_team_id: the away team's id league_id: the league id the game is part of date: the date of the game status: the status of the game field: the field the game is to be played on """ id = DB.Column(DB.Integer, primary_key=True) home_team_id = DB.Column( DB.Integer, DB.ForeignKey('team.id', use_alter=True, name='fk_home_team_game')) away_team_id = DB.Column( DB.Integer, DB.ForeignKey('team.id', use_alter=True, name='fk_away_team_game')) league_id = DB.Column(DB.Integer, DB.ForeignKey('league.id')) bats = DB.relationship("Bat", backref="game", lazy='dynamic') date = DB.Column(DB.DateTime) status = DB.Column(DB.String(120)) field = DB.Column(DB.String(120)) def __init__(self, date, time, home_team_id, away_team_id, league_id, status="", field=""): """The Constructor. Raises: InvalidField TeamDoesNotExist LeagueDoesNotExist """ # check for all the invalid parameters if not date_validator(date): raise InvalidField(payload={'details': "Game - date"}) if not time_validator(time): raise InvalidField(payload={'details': "Game - time"}) self.date = datetime.strptime(date + "-" + time, '%Y-%m-%d-%H:%M') if (Team.query.get(home_team_id) is None): raise TeamDoesNotExist(payload={'details': home_team_id}) if Team.query.get(away_team_id) is None: raise TeamDoesNotExist(payload={'details': away_team_id}) if League.query.get(league_id) is None: raise LeagueDoesNotExist(payload={'details': league_id}) if ((status != "" and not string_validator(status)) or (field != "" and not field_validator(field))): raise InvalidField(payload={'details': "Game - field/status"}) # must be good now self.home_team_id = home_team_id self.away_team_id = away_team_id self.league_id = league_id self.status = status self.field = field def __repr__(self): """Returns the string representation of the Game.""" home = str(Team.query.get(self.home_team_id)) away = str(Team.query.get(self.away_team_id)) result = (home + " vs " + away + " on " + self.date.strftime("%Y-%m-%d %H:%M")) if self.field != "": result += " at " + self.field return result def json(self): """Returns a jsonserializable object.""" return { 'game_id': self.id, 'home_team_id': self.home_team_id, 'home_team': str(Team.query.get(self.home_team_id)), 'away_team_id': self.away_team_id, 'away_team': str(Team.query.get(self.away_team_id)), 'league_id': self.league_id, 'date': self.date.strftime("%Y-%m-%d"), 'time': self.date.strftime("%H:%M"), 'status': self.status, 'field': self.field } def update(self, date=None, time=None, home_team_id=None, away_team_id=None, league_id=None, status=None, field=None): """Update an existing game. Raises: InvalidField TeamDoesNotExist LeagueDoesNotExist """ d = self.date.strftime("%Y-%m-%d") t = self.date.strftime("%H:%M") if date is not None and date_validator(date): d = date elif date is not None: raise InvalidField(payload={'details': "Game - date"}) if time is not None and time_validator(time): t = time elif time is not None: raise InvalidField(payload={'details': "Game - time"}) if (home_team_id is not None and Team.query.get(home_team_id) is not None): self.home_team_id = home_team_id elif home_team_id is not None: raise TeamDoesNotExist(payload={'details': home_team_id}) if (away_team_id is not None and Team.query.get(away_team_id) is not None): self.away_team_id = away_team_id elif away_team_id is not None: raise TeamDoesNotExist(payload={'details': away_team_id}) if league_id is not None and League.query.get(league_id) is not None: self.league_id = league_id elif league_id is not None: raise LeagueDoesNotExist(payload={'details': league_id}) if status is not None and string_validator(status): self.status = status elif status is not None: raise InvalidField(payload={'details': "Game - status"}) if field is not None and field_validator(field): self.field = field elif field is not None: raise InvalidField(payload={'details': "Game - field"}) # worse case just overwrites it with same date or time self.date = datetime.strptime(d + "-" + t, '%Y-%m-%d-%H:%M') def summary(self): """Returns a game summary.""" away_score = DB.session.query( func.sum(Bat.rbi).filter(Bat.game_id == self.id).filter( Bat.team_id == self.away_team_id)).first()[0] away_bats = DB.session.query( func.count( Bat.classification).filter(Bat.game_id == self.id).filter( Bat.team_id == self.away_team_id).filter( Bat.classification.in_(HITS))).first()[0] home_score = DB.session.query( func.sum(Bat.rbi).filter(Bat.game_id == self.id).filter( Bat.team_id == self.home_team_id)).first()[0] home_bats = DB.session.query( func.count( Bat.classification).filter(Bat.game_id == self.id).filter( Bat.team_id == self.home_team_id).filter( Bat.classification.in_(HITS))).first()[0] if away_score is None: away_score = 0 if home_score is None: home_score = 0 if away_bats is None: away_bats = 0 if home_bats is None: home_bats = 0 return { 'away_score': away_score, 'away_bats': away_bats, 'home_score': home_score, 'home_bats': home_bats }
class Team(DB.Model): """ A class that stores information about a team. Columns: id: the unique team id sponsor_id: the sposor id the team is associated with home_games: the home games of the team away_games: the away games of the team players: the players on the team's roster bats: the bats of the team league_id: the league id the team is part of year: the year the team played espys: the espy transaction that team has """ id = DB.Column(DB.Integer, primary_key=True) color = DB.Column(DB.String(120)) sponsor_id = DB.Column(DB.Integer, DB.ForeignKey('sponsor.id')) home_games = DB.relationship('Game', backref='home_team', lazy='dynamic', foreign_keys='[Game.home_team_id]') away_games = DB.relationship('Game', backref='away_team', lazy='dynamic', foreign_keys='[Game.away_team_id]') players = DB.relationship('Player', secondary=roster, backref=DB.backref('teams', lazy='dynamic')) bats = DB.relationship('Bat', backref='team', lazy='dynamic') league_id = DB.Column(DB.Integer, DB.ForeignKey('league.id')) year = DB.Column(DB.Integer) player_id = DB.Column(DB.Integer, DB.ForeignKey('player.id')) espys = DB.relationship('Espys', backref='team', lazy='dynamic') def __init__(self, color=None, sponsor_id=None, league_id=None, year=date.today().year): """ The constructor. Raises InvalidField SponsorDoesNotExist LeagueDoesNotExist """ if color is not None and not string_validator(color): raise InvalidField(payload={'details': "Team - color"}) if sponsor_id is not None and Sponsor.query.get(sponsor_id) is None: raise SponsorDoesNotExist(payload={'details': sponsor_id}) if league_id is not None and League.query.get(league_id) is None: raise LeagueDoesNotExist(payload={'details': league_id}) if year is not None and not year_validator(year): raise InvalidField(payload={'details': "Team - year"}) self.color = color self.sponsor_id = sponsor_id self.league_id = league_id self.year = year self.kik = None def __repr__(self): """Returns the string representation.""" result = [] if self.sponsor_id is not None: sponsor = Sponsor.query.get(self.sponsor_id) if sponsor is not None and sponsor.nickname is not None: result.append(sponsor.nickname) if self.color is not None: result.append(self.color) return " ".join(result) def espys_awarded(self): """Returns the number of espy ponts the team has.""" count = 0 for espy in self.espys: count += espy.points return count def json(self): """Returns a jsonserializable object.""" captain = (None if self.player_id is None else Player.query.get( self.player_id).json()) return { 'team_id': self.id, 'team_name': str(self), 'color': self.color, 'sponsor_id': self.sponsor_id, 'league_id': self.league_id, 'year': self.year, 'espys': self.espys_awarded(), 'captain': captain } def update(self, color=None, sponsor_id=None, league_id=None, year=None): """Updates an existing team. Raises: InvalidField SponsorDoesNotExist LeagueDoesNotExist """ # does nothing with espys given if color is not None and string_validator(color): self.color = color elif color is not None: raise InvalidField(payload={'details': "Team - color"}) if (sponsor_id is not None and Sponsor.query.get(sponsor_id) is not None): self.sponsor_id = sponsor_id elif sponsor_id is not None: raise SponsorDoesNotExist(payload={'details': sponsor_id}) if league_id is not None and League.query.get(league_id) is not None: self.league_id = league_id elif league_id is not None: raise LeagueDoesNotExist(payload={'details': league_id}) if year is not None and year_validator(year): self.year = year elif year is not None: raise InvalidField(payload={'details': "Team - year"}) def insert_player(self, player_id, captain=False): """Insert a player on to the team. Parameter: player_id: the id of the player to add captain: True if the player is the team's captain Returns: True if player was added False otherwise Raises: PlayerDoesNotExist """ valid = False player = Player.query.get(player_id) if player is None: raise PlayerDoesNotExist(payload={'details': player_id}) if captain: self.player_id = player_id if player not in self.players: self.players.append(player) else: if player not in self.players: self.players.append(player) return valid def remove_player(self, player_id): """Removes a player from a team. Parameter: player_id: the id of the player to remove Raises: MissingPlayer """ player = Player.query.get(player_id) if player not in self.players: raise PlayerNotOnTeam(payload={'details': player_id}) self.players.remove(player) def check_captain(self, player_name, password): """Checks if the player is the captain of the team. Parameters: player_name: the name of the player (str) password: the password of the player (str) Return: True of player is the captain False otherwise """ player = Player.query.get(self.player_id) return player.name == player_name and player.check_password(password) def team_stats(self): pass
""" from api import DB from sqlalchemy import func from werkzeug.security import generate_password_hash, check_password_hash from datetime import date, datetime, time from api.variables import HITS, KIKPOINTS from api.errors import TeamDoesNotExist, PlayerDoesNotExist, GameDoesNotExist,\ InvalidField, LeagueDoesNotExist, SponsorDoesNotExist,\ NonUniqueEmail, PlayerNotOnTeam, PlayerNotSubscribed,\ BadRequestError from api.validators import rbi_validator, hit_validator, inning_validator,\ string_validator, date_validator, time_validator,\ field_validator, year_validator, gender_validator,\ float_validator, boolean_validator roster = DB.Table( 'roster', DB.Column('player_id', DB.Integer, DB.ForeignKey('player.id')), DB.Column('team_id', DB.Integer, DB.ForeignKey('team.id'))) SUBSCRIBED = "{} SUBSCRIBED" AWARD_POINTS = "{} awarded espy points for subscribing: {}" class Fun(DB.Model): """ A class used to store the amount of fun had by all. Columns: id: the unique id year: the year the fun count is for count: the total count for the year """ id = DB.Column(DB.Integer, primary_key=True) year = DB.Column(DB.Integer)
class Team(DB.Model): """ A class that stores information about a team. Columns: id: the unique team id sponsor_id: the sposor id the team is associated with home_games: the home games of the team away_games: the away games of the team players: the players on the team's roster bats: the bats of the team league_id: the league id the team is part of year: the year the team played espys: the espy transaction that team has """ id = DB.Column(DB.Integer, primary_key=True) color = DB.Column(DB.String(120)) sponsor_id = DB.Column(DB.Integer, DB.ForeignKey('sponsor.id')) home_games = DB.relationship('Game', backref='home_team', lazy='dynamic', foreign_keys='[Game.home_team_id]') away_games = DB.relationship('Game', backref='away_team', lazy='dynamic', foreign_keys='[Game.away_team_id]') players = DB.relationship('Player', secondary=roster, backref=DB.backref('teams', lazy='dynamic')) bats = DB.relationship('Bat', backref='team', lazy='dynamic') league_id = DB.Column(DB.Integer, DB.ForeignKey('league.id')) year = DB.Column(DB.Integer) player_id = DB.Column(DB.Integer, DB.ForeignKey('player.id')) espys = DB.relationship('Espys', backref='team', lazy='dynamic') espys_total = column_property(select([func.sum(Espys.points)]).where( Espys.team_id == id).correlate_except(Espys), deferred=True) sponsor_name = column_property(select([Sponsor.nickname]).where( Sponsor.id == sponsor_id).correlate_except(Sponsor)) def __init__(self, color: str = None, sponsor_id: int = None, league_id: int = None, year: int = date.today().year): """ The constructor. Raises InvalidField SponsorDoesNotExist LeagueDoesNotExist """ if color is not None and not string_validator(color): raise InvalidField(payload={'details': "Team - color"}) if sponsor_id is not None and Sponsor.query.get(sponsor_id) is None: raise SponsorDoesNotExist(payload={'details': sponsor_id}) if league_id is not None and League.query.get(league_id) is None: raise LeagueDoesNotExist(payload={'details': league_id}) if year is not None and not year_validator(year): raise InvalidField(payload={'details': "Team - year"}) self.color = color self.sponsor_id = sponsor_id self.league_id = league_id self.year = year self.kik = None def __repr__(self) -> str: """Returns the string representation.""" if self.sponsor_name is not None and self.color is not None: return f"{self.sponsor_name} {self.color}" elif self.sponsor_name is not None: return f"{self.sponsor_name}" elif self.color is not None: return f"{self.color}" else: return f"Team: {self.id}" def json(self, admin: bool = False) -> dict: """Returns a jsonserializable object.""" if admin: captain = (None if self.player_id is None else Player.query.get(self.player_id).admin_json()) else: captain = (None if self.player_id is None else Player.query.get(self.player_id).json()) return { 'team_id': self.id, 'team_name': str(self), 'color': self.color, 'sponsor_id': self.sponsor_id, 'league_id': self.league_id, 'year': self.year, 'espys': self.espys_total if self.espys_total is not None else 0, 'captain': captain} def update(self, color: str = None, sponsor_id: int = None, league_id: int = None, year: int = None) -> None: """Updates an existing team. Raises: InvalidField SponsorDoesNotExist LeagueDoesNotExist """ # does nothing with espys given if color is not None and string_validator(color): self.color = color elif color is not None: raise InvalidField(payload={'details': "Team - color"}) if (sponsor_id is not None and Sponsor.query.get(sponsor_id) is not None): self.sponsor_id = sponsor_id elif sponsor_id is not None: raise SponsorDoesNotExist(payload={'details': sponsor_id}) if league_id is not None and League.query.get(league_id) is not None: self.league_id = league_id elif league_id is not None: raise LeagueDoesNotExist(payload={'details': league_id}) if year is not None and year_validator(year): self.year = year elif year is not None: raise InvalidField(payload={'details': "Team - year"}) def insert_player(self, player_id: int, captain: bool = False) -> None: """Insert a player on to the team. Parameter: player_id: the id of the player to add captain: True if the player is the team's captain Returns: True if player was added False otherwise Raises: PlayerDoesNotExist """ valid = False player = Player.query.get(player_id) if player is None: raise PlayerDoesNotExist(payload={'details': player_id}) if not self.is_player_on_team(player): self.players.append(player) valid = True if captain: self.player_id = player_id valid = True return valid def remove_player(self, player_id: int) -> None: """Removes a player from a team. Parameter: player_id: the id of the player to remove Raises: MissingPlayer """ player = Player.query.get(player_id) if not self.is_player_on_team(player): raise PlayerNotOnTeam(payload={'details': player_id}) self.players.remove(player) def is_player_on_team(self, player: 'Player') -> bool: """Returns whether the given player is on the team Parameter: player: the player model Returns: True if player on team otherwise False (boolean) """ if player is None: return False return player.id in [p.id for p in self.players] def check_captain(self, player_name: str, password: str) -> str: """Checks if the player is the captain of the team. Parameters: player_name: the name of the player (str) password: the password of the player (str) Return: True of player is the captain False otherwise """ player = Player.query.get(self.player_id) return player.name == player_name and player.check_password(password) def team_stats(self) -> None: pass
class OAuth(OAuthConsumerMixin, DB.Model): """A model for storing information about oauth""" provider_user_id = DB.Column(DB.String(256), unique=True, nullable=False) player_id = DB.Column(DB.Integer, DB.ForeignKey(Player.id), nullable=False) player = DB.relationship(Player)
class JoinLeagueRequest(DB.Model): """ A class used to store requests to join a league. Columns: team_id: the team they want to join name: the name they want to use email: the email from the Oauth provider pending: whether waiting for the outcome of the request """ id = DB.Column(DB.Integer, primary_key=True) team_id = DB.Column(DB.Integer, DB.ForeignKey(Team.id), nullable=False) team = DB.relationship(Team) email = DB.Column(DB.String(120), nullable=False) name = DB.Column(DB.String(120), nullable=False) pending = DB.Column(DB.Boolean) gender = DB.Column(DB.String(1)) def __init__(self, email: str, name: str, team: 'Team', gender: str): if team is None or not isinstance(team, Team) or team.id is None: raise TeamDoesNotExist("Given team does not exist") if not gender_validator(gender): raise InvalidField(payload={ 'details': "Player League Request - gender"}) if not string_validator(email): raise InvalidField(payload="Player League Request - email") if not string_validator(name): raise InvalidField(payload="Player League Request - name") self.email = email.lower() self.name = name self.team_id = team.id self.pending = True self.gender = gender.lower() def accept_request(self) -> 'Player': """Accept the request and add the player to the team""" # create a player if they do not exit already if not self.pending: raise HaveLeagueRequestException("Request already submitted") player = Player.query.filter( func.lower(Player.email) == self.email.lower()).first() if player is None: player = Player(self.name, self.email, gender=self.gender) DB.session.add(player) DB.session.commit() self.pending = False team = Team.query.get(self.team_id) team.insert_player(player.id) DB.session.commit() return player def decline_request(self) -> None: """Decline the request.""" self.pending = False DB.session.commit() def json(self) -> dict: """Get a json version of the model""" team = (None if self.team_id is None else Team.query.get(self.team_id).json()) return { "team": team, "email": self.email, "id": self.id, "pending": self.pending, "player_name": self.name, "gender": self.gender }