from math import floor from typing import Tuple from os.path import join, isfile from dataclasses import dataclass from importlib.resources import path from pandas import read_csv, DataFrame from sqlalchemy.orm import sessionmaker from random import randint, getrandbits from names import get_first_name, get_last_name from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import create_engine, Column, String, Integer, not_ MIN_LEVEL = 1 MAX_LEVEL = 10 DEFAULT_COURTS = 12 PLAYER_PER_COURT = 4 Base = declarative_base() class Player(Base): __tablename__ = "players" id = Column("id", Integer, primary_key=True) first = Column("first", String) last = Column("last", String) level = Column("level", Integer) status = Column("status", Integer) count = Column("count", Integer) def __init__( self, id: int = None, first: str = "", last: str = "", level: int = None, status: bool = None, count: int = None, ): self.id = id self.first = first self.last = last self.status = status self.level = level self.count = count def __repr__(self): status = "active" if self.status else "inactive" return f"{self.first} {self.last} (Level {self.level}) is {status} and has played {self.count} games" class DisplayPlayer: id: int first: str last: str status: bool def __init__(self, player: Player): self.id = player.id self.first = player.first self.last = player.last self.status = player.status def __repr__(self): status = "active" if self.status else "inactive" return f"{self.first} {self.last} is {status}" @dataclass class Team: player1: DisplayPlayer player2: DisplayPlayer @dataclass class Game: court: int team1: Team team2: Team @dataclass class CourtList: total: int = DEFAULT_COURTS def __post_init__(self) -> None: self.courts = {i + 1: True for i in range(self.total)} def get_court_status(self, court_number: int) -> bool: return self.courts[court_number] def toggle_court_status(self, court_number: int) -> None: new_status = not self.courts[court_number] self.courts[court_number] = new_status return new_status def get_courts(self) -> dict: return self.courts def separate_courts(self) -> Tuple[dict, dict]: active_courts = {k: v for k, v in self.courts.items() if v} inactive_courts = {k: v for k, v in self.courts.items() if not v} return active_courts, inactive_courts class PlayerList: guests: dict = {"low": 0, "mid": 0, "high": 0} def __init__(self, csv_location: str = None) -> None: with path("match_up") as p: self.db_location = join(p, "players.db") generate_random_players = False if not isfile(self.db_location): print(f"No database file found") if csv_location is None: generate_random_players = True engine = create_engine("sqlite:///" + self.db_location, echo=True) Base.metadata.create_all(bind=engine) self.session = sessionmaker(bind=engine)() if csv_location is not None: print(f"CSV file provided, updating the database") self.session.query(Player).delete() self._init_database_from_csv(read_csv(self.csv_location)) elif generate_random_players: print(f"Generating random players for testing") self._init_random_database() def increment_guests(self, level: str): self.guests[level] = self.guests[level] + 1 return self.guests[level] def decrement_guests(self, level: str): if self.guests[level] == 0: return 0 self.guests[level] = self.guests[level] - 1 return self.guests[level] def get_player_status(self, id: int) -> bool: return self.session.query(Player).filter(Player.id == id).first().status def toggle_player_status(self, id: int) -> DisplayPlayer: player = self.session.query(Player).filter(Player.id == id).first() player.status = not player.status self.session.commit() return DisplayPlayer(player) def get_all_players(self) -> list[Player]: all_players = [DisplayPlayer(p) for p in self.session.query(Player).all()] return all_players def get_possible_game_count(self) -> int: total_players = len(self.get_players()) possible_games = floor(total_players / PLAYER_PER_COURT) return possible_games def get_players(self, rounds: int = 0) -> list[Player]: active_players = ( self.session.query(Player).filter(not_(Player.status == 0)).all() ) low_guests = [ Player( id=1000 + i, first=f"Beginner", last=f"{i}", level=1, status=True, count=rounds, ) for i in range(1, self.guests["low"] + 1) ] mid_guests = [ Player( id=2000 + i, first=f"Novice", last=f"{i}", level=4, status=True, count=rounds, ) for i in range(1, self.guests["mid"] + 1) ] high_guests = [ Player( id=3000 + i, first=f"Intermediate", last=f"{i}", level=7, status=True, count=rounds, ) for i in range(1, self.guests["high"] + 1) ] return active_players + low_guests + mid_guests + high_guests def increment_game_count(self, player_ids: list[int]): return 0 def _init_database_from_csv(self, data: DataFrame) -> None: for _, entry in data.iterrows(): player = Player( id=entry["id"], first=entry["first"], last=entry["last"], level=entry["skill"], status=False, count=0, ) self.session.add(player) self.session.commit() def _init_random_database(self, player_count: int = 80) -> None: for i in range(player_count): player = Player( id=i, first=get_first_name(), last=get_last_name(), level=randint(MIN_LEVEL, MAX_LEVEL), status=getrandbits(1), count=0, ) self.session.add(player) self.session.commit()