summaryrefslogtreecommitdiff
path: root/app/controller.py
diff options
context:
space:
mode:
Diffstat (limited to 'app/controller.py')
-rw-r--r--app/controller.py195
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()