Files
estus-shots-py/estusshots/orm.py
2019-10-17 20:35:18 +02:00

185 lines
5.7 KiB
Python

import enum
from typing import Iterable, List
import sqlalchemy
from sqlalchemy import create_engine, ForeignKey, Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Boolean, Float, Enum, Date, Time
from sqlalchemy.orm import sessionmaker, relationship
from estusshots import util, forms
engine = create_engine('sqlite:///../databases/test.db')
Base = declarative_base()
player_episode = Table(
'player_episode',
Base.metadata,
Column('player_id', ForeignKey('players.id'), primary_key=True),
Column('episode_id', ForeignKey('episodes.id'), primary_key=True)
)
class EventType(enum.Enum):
Pause = 0
Death = 1
Victory = 2
class Player(Base):
__tablename__ = "players"
id = Column(Integer, primary_key=True)
real_name = Column(String)
alias = Column(String)
hex_id = Column(String)
anon = Column(Boolean, default=False)
events = relationship("Event", back_populates="player")
episodes = relationship("Episode", secondary=player_episode, back_populates="players")
@property
def name(self) -> str:
return self.real_name if self.real_name and not self.anon else self.alias
def populate_from_form(self, form: "forms.PlayerForm"):
self.real_name = str(form.real_name.data) if form.real_name.data else None
self.alias = str(form.alias.data)
self.hex_id = str(form.hex_id.data) if form.hex_id.data else None
self.anon = bool(form.anonymize.data)
class Drink(Base):
__tablename__ = "drinks"
id = Column(Integer, primary_key=True)
name = Column(String)
vol = Column(Float)
def populate_from_form(self, form: "forms.DrinkForm"):
self.name = str(form.name.data)
self.vol = float(form.vol.data)
class Season(Base):
__tablename__ = "seasons"
id = Column(Integer, primary_key=True)
code = Column(String, default='SXX')
game = Column(String)
description = Column(String)
start = Column(Date)
end = Column(Date)
episodes: Iterable["Episode"] = relationship("Episode", back_populates="season")
enemies: Iterable["Enemy"] = relationship("Enemy", back_populates="season")
def populate_from_form(self, form: "forms.SeasonForm"):
self.code = str(form.code.data)
self.game = str(form.game_name.data)
self.description = str(form.description.data) if form.description.data else None
self.start = form.start.data
self.end = form.end.data
class Enemy(Base):
__tablename__ = "enemies"
id = Column(Integer, primary_key=True)
name = Column(String)
boss = Column(Boolean, default=True)
season_id = Column(Integer, ForeignKey('seasons.id'))
season = relationship("Season", back_populates="enemies")
events: Iterable["Event"] = relationship('Event', back_populates="enemy")
@property
def is_defeated(self):
return any([e for e in self.events if e.type == EventType.Victory])
def populate_from_form(self, form: "forms.EnemyForm"):
self.name = str(form.name.data)
self.boss = bool(form.is_boss.data)
self.season_id = int(form.season_id.data)
class Episode(Base):
__tablename__ = "episodes"
id = Column(Integer, primary_key=True)
code = Column(String, default='EXX')
title = Column(String)
date = Column(Date)
start = Column(Time)
end = Column(Time)
season_id = Column(Integer, ForeignKey('seasons.id'))
season = relationship("Season", back_populates="episodes")
events: List["Event"] = relationship('Event', back_populates='episode')
players = relationship("Player", secondary=player_episode, back_populates="episodes")
@property
def playtime(self):
return util.compute_timedelta(self.start, self.end)
def populate_from_form(self, form: "forms.EpisodeForm"):
self.code = str(form.code.data)
self.title = str(form.title.data)
self.date = form.date.data
self.start = form.start.data
self.end = form.end.data
class Event(Base):
__tablename__ = 'events'
id = Column(Integer, primary_key=True)
type: EventType = Column(Enum(EventType))
time = Column(Time)
comment = Column(String)
episode_id = Column(Integer, ForeignKey('episodes.id'))
episode = relationship('Episode', back_populates='events')
player_id = Column(Integer, ForeignKey('players.id'))
player = relationship('Player', back_populates='events')
enemy_id = Column(Integer, ForeignKey('enemies.id'))
enemy = relationship('Enemy', back_populates='events')
penalties: List["Penalty"] = relationship('Penalty', back_populates='event')
def populate_from_form(self, form: "forms.EventForm"):
self.episode_id = int(form.episode_id.data)
self.type = EventType(form.event_type.data)
self.time = form.time.data
self.comment = str(form.comment.data) if form.comment.data else None
self.player_id = int(form.player.data) if form.player.data else None
self.enemy_id = int(form.enemy.data) if form.enemy.data else None
class Penalty(Base):
__tablename__ = 'penalties'
id = Column(Integer, primary_key=True)
player_id = Column(Integer, ForeignKey('players.id'))
player = relationship('Player')
drink_id = Column(Integer, ForeignKey('drinks.id'))
drink = relationship('Drink')
event_id = Column(Integer, ForeignKey('events.id'))
event = relationship('Event', back_populates='penalties')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
def new_session() -> sqlalchemy.orm.Session:
"""Open up a new session. This function exists for ease of use, as the return type is hinted for the IDE."""
return Session()