diff options
| author | Karan Jayachandra <mail@karanjayachandra.com> | 2025-07-14 13:33:24 +0200 |
|---|---|---|
| committer | Karan Jayachandra <mail@karanjayachandra.com> | 2025-07-14 13:33:24 +0200 |
| commit | 7e4c451c052c9fc33136d184cdedec251f9ef6fd (patch) | |
| tree | 5cef1d2b3f7bb61551dd105974e66b11b81fff98 /app/controller.py | |
| parent | 078e792c73f1583433c745695a3b1a9630cedeb3 (diff) | |
| parent | 729203409fb73fdbac19b8af9d647883a5ac96b0 (diff) | |
Merge branch 'develop' into 'main'
Develop
See merge request KaranJayachandra/match_up!14
Diffstat (limited to 'app/controller.py')
| -rw-r--r-- | app/controller.py | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/app/controller.py b/app/controller.py new file mode 100644 index 0000000..1c2c5bf --- /dev/null +++ b/app/controller.py @@ -0,0 +1,195 @@ +from math import floor +from app import app, db +from datetime import date +from typing import Sequence +from pandas import DataFrame +from operator import attrgetter +from sqlalchemy import func, select, not_ +from app.model import ( + Player, + Court, + Game, + DisplayGame, +) +from app.utilities import ( + get_placeholder_games, + get_team_games, + get_shuffle_games, + separate_teams_and_players, + initialize_random_database, + initialize_default_players, +) + + +class Courts: + + def __init__(self): + with app.app_context(): + courts = db.session.query(Court).all() + if len(courts) == 0: + for _ in range(app.config["COURT_COUNT"]): + db.session.add(Court()) + db.session.commit() + + def toggle(self, id: int) -> bool: + court = db.session.get(Court, id) + if court is None: + raise ValueError(f"Court {id} doesn't exist.") + new_status = not court.status + court.status = new_status + db.session.commit() + return new_status + + def active(self): + return db.session.query(Court).where(Court.status).all() + + def inactive(self): + return db.session.query(Court).where(not_(Court.status)).all() + + def all(self) -> list[Court]: + return db.session.query(Court).order_by(Court.id).all() + + +class Players: + + def __init__(self) -> None: + with app.app_context(): + if len(self.regulars()) == 0: + initialize_random_database() + + def update(self, data: DataFrame): + initialize_default_players() + for entry in data.to_dict("records"): + args = entry | {"status": False} + db.session.add(Player(**args)) # type: ignore + db.session.commit() + + def get(self, id: int) -> bool: + player = db.session.get(Player, id) + if player is None: + raise ValueError(f"User {id} doesn't exist.") + return player.status + + def toggle(self, id: int) -> Player: + player = db.session.get(Player, id) + if player is None: + raise ValueError(f"User {id} doesn't exist.") + player.status = not player.status + db.session.commit() + return player + + def regulars(self) -> list[Player]: + filter_list = list(app.config["GUESTS"].keys()) + list( + app.config["DEFAULTS"].keys() + ) + return ( + db.session.query(Player) + .where(Player.id > 1) + .where(Player.first_name.not_in(filter_list)) + .order_by(Player.first_name, Player.last_name) + .all() + ) + + def guests(self) -> list[Player]: + return ( + db.session.query(Player) + .where(Player.id > 1) + .where(Player.first_name.in_(app.config["GUESTS"].keys())) + .order_by(Player.first_name, Player.last_name) + .all() + ) + + def active(self) -> Sequence[Player]: + query = ( + select(Player) + .where(Player.status) + .order_by(Player.first_name, Player.last_name) + ) + return db.session.scalars(query).all() + + def reset(self): + for player in db.session.scalars(select(Player)): + player.status = False + db.session.commit() + + +class Session: + levels: int = 10 + teams: bool = False + proposal: list[DisplayGame] = [] + courts: Courts = Courts() + players: Players = Players() + + def _today(self): + games = ( + db.session.query(Game).filter(func.date(Game.date) == date.today()).all() + ) + return games + + def __init__(self): + with app.app_context(): + if len(self._today()) == 0: + query = select(Player).where(Player.first_name == "---") + player = db.session.scalars(query).first() + if player is None: + raise ValueError(f"Database isn't initialized.") + player_data = {f"player_{i+1}": player.id for i in range(4)} + for court in self.courts.all(): + args = {"round_id": 0, "court_id": court.id} | player_data + db.session.add(Game(**args)) + db.session.commit() + + def round(self) -> int: + games = self._today() + round_id = max([game.round_id for game in games]) + if round_id is None: + raise ValueError(f"Database isn't initialized") + return round_id + + def current_round(self) -> list[DisplayGame]: + games = ( + db.session.query(Game) + .filter(func.date(Game.date) == date.today()) + .filter(Game.round_id == self.round()) + .order_by(Game.court_id) + .all() + ) + games = [DisplayGame(game) for game in games] + return games + + def propose(self) -> list[DisplayGame]: + reserved_courts = self.courts.inactive() + reserved_games = get_placeholder_games(reserved_courts, "RESERVED") + active_courts = self.courts.active() + active_players = self.players.active() + game_count = floor(len(active_players) / app.config["PLAYERS_PER_COURT"]) + game_count = min(len(active_courts), game_count) + used_courts = active_courts[:game_count] + unused_courts = active_courts[game_count:] + blank_games = get_placeholder_games(unused_courts, "---") + active_teams = {} + if self.teams: + active_teams, active_players = separate_teams_and_players(active_players) + team_courts = used_courts[: len(active_teams)] + shuffle_courts = used_courts[len(active_teams) :] + team_games = get_team_games(team_courts, active_teams) + shuffle_games = get_shuffle_games(shuffle_courts, active_players, self.levels) + self.proposal = shuffle_games + team_games + blank_games + reserved_games + self.proposal.sort(key=attrgetter("court.id")) + return self.proposal + + def confirm(self) -> list[DisplayGame]: + if len(self.proposal) == 0: + return self.current_round() + round_id = self.round() + 1 + for game in self.proposal: + db.session.add(game.to_game(round_id)) + db.session.commit() + self.proposal = [] + return self.current_round() + + def reset(self) -> list[DisplayGame]: + db.session.query(Game).filter(func.date(Game.date) == date.today()).delete() + db.session.commit() + self.__init__() + return self.current_round() |
