import datetime import enum from numbers import Rational from typing import Dict, List, Union, Optional from dataclasses import dataclass from typing import TYPE_CHECKING if TYPE_CHECKING: from estusshots import forms, util class EventType(enum.Enum): Pause = 0 Death = 1 Victory = 2 @dataclass class GenericFormModel: page_title: str form_title: str post_url: str errors: Dict[str, List[str]] = None @dataclass class Player: id: int real_name: str alias: str hex_id: str anon: bool = False @property def name(self) -> str: return self.real_name if self.real_name and not self.anon else self.alias @classmethod def from_form(cls, form: "forms.PlayerForm"): id = int(form.player_id.data) if form.player_id.data else None real_name = str(form.real_name.data) if form.real_name.data else None alias = str(form.alias.data) hex_id = str(form.hex_id.data) if form.hex_id.data else None anon = bool(form.anonymize.data) return cls(id=id, real_name=real_name, alias=alias, hex_id=hex_id, anon=anon) @dataclass class Drink: id: int name: str vol: float @classmethod def from_form(cls, form: "forms.DrinkForm"): id = int(form.drink_id.data) if form.drink_id.data else None name = str(form.name.data) vol = float(form.vol.data) self = cls(id=id, name=name, vol=vol) return self @dataclass class Enemy: id: int name: str boss: bool season_id: int @classmethod def from_form(cls, form: "forms.EnemyForm"): id = int(form.enemy_id.data) if form.enemy_id.data else None name = str(form.name.data) boss = bool(form.is_boss.data) season = int(form.season_id.data) self = cls(id=id, name=name, boss=boss, season_id=season) return self @dataclass class Season: id: int game: str description: str start: datetime.date end: datetime.date code: str def __post_init__(self): try: self.start = datetime.datetime.strptime(self.start, "%Y-%m-%d").date() except Exception: pass try: self.end = datetime.datetime.strptime(self.end, "%Y-%m-%d").date() except Exception: pass @classmethod def from_form(cls, form: "forms.SeasonForm"): season_id = int(form.season_id.data) if form.season_id.data else None code = str(form.code.data) game = str(form.game_name.data) description = str(form.description.data) if form.description.data else None start = form.start.data end = form.end.data self = cls(season_id, game, description, start, end, code) return self @dataclass class Episode: id: int season_id: int title: str date: Union[datetime.date, Rational] start: Union[datetime.datetime, Rational] end: Union[datetime.datetime, Rational] code: str @property def playtime(self): return self.end - self.start def __post_init__(self): if isinstance(self.date, str): self.date = datetime.datetime.strptime(self.date, util.DATE_FMT).date() if isinstance(self.start, Rational): self.start = datetime.datetime.fromtimestamp(self.start) if isinstance(self.end, Rational): self.end = datetime.datetime.fromtimestamp(self.end) @classmethod def from_form(cls, form: "forms.EpisodeForm"): episode_id = int(form.episode_id.data) if form.episode_id.data else None season_id = int(form.season_id.data) code = str(form.code.data) title = str(form.title.data) date = form.date.data start = util.combine_datetime(date, form.start.data) end = util.combine_datetime(date, form.end.data) if end < start: end = end + datetime.timedelta(days=1) return cls(episode_id, season_id, title, date, start, end, code) @dataclass class Penalty: penalty_id: int player_id: int drink_id: int @dataclass class Event: event_id: int episode_id: int type: EventType time: datetime.datetime comment: str player_id: Optional[int] enemy_id: Optional[int] penalties: List[Penalty] @classmethod def from_form(cls, form: "forms.EventForm"): event_id = int(form.event_id.data) if form.event_id.data else None episode_id = int(form.episode_id.data) event_type = EventType(form.event_type.data) time = util.combine_datetime(datetime.datetime.today(), form.time.data) comment = str(form.comment.data) if form.comment.data else None player_id = int(form.player.data) if form.player.data else None enemy_id = int(form.enemy.data) if form.enemy.data else None penalties = [] for entry in form.penalties: penalties.append(Penalty( penalty_id=int(entry.penalty_id.data) if entry.penalty_id.data else None, player_id=int(entry.player_id.data), drink_id=int(entry.drink.data) )) return cls(event_id, episode_id, event_type, time, comment, player_id, enemy_id, penalties)