From 60a489cfb3fb7a12a06212c2c7ed3c05cd0757b5 Mon Sep 17 00:00:00 2001 From: Karan Jayachandra Date: Fri, 25 Oct 2024 18:03:18 +0200 Subject: Moved the files into a folder structure --- src/match_up/model.py | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/match_up/model.py (limited to 'src/match_up/model.py') diff --git a/src/match_up/model.py b/src/match_up/model.py new file mode 100644 index 0000000..c652ce8 --- /dev/null +++ b/src/match_up/model.py @@ -0,0 +1,104 @@ +from os import getenv +from math import floor +from csv import reader +from typing import Tuple +from dataclasses import dataclass + +MIN_LEVEL = 1 +MAX_LEVEL = 10 +PLAYER_PER_COURT = 4 + + +@dataclass +class Player: + name: str + skill: int = 1 + status: bool = False + + +@dataclass +class Team: + player1: str + player2: str + + +@dataclass +class Game: + court: int + team1: Team + team2: Team + + +@dataclass +class CourtList: + total: int = int(getenv("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 + + +@dataclass +class PlayerList: + location: str = getenv("DATABASE") + guests: int = 0 + + def __post_init__(self) -> None: + with open("data/" + self.location, newline="") as file: + pointer = reader(file) + next(pointer, None) + players = { + id: Player(row[0], int(row[1])) for id, row in enumerate(pointer) + } + self.guest_id_start = len(players) + 1 + self.players = players + + def increment_guests(self): + self.guests = self.guests + 1 + return self.guests + + def decrement_guests(self): + if self.guests == 0: + return 0 + self.guests = self.guests - 1 + return self.guests + + def get_player_status(self, player_number: int) -> bool: + return self.players[player_number].status + + def toggle_player_status(self, player_number: int) -> Tuple[bool, str]: + new_status = not self.players[player_number].status + self.players[player_number].status = new_status + return new_status, self.players[player_number].name + + def get_players(self) -> dict: + return self.players + + def get_possible_game_count(self) -> int: + total_players = len(self.get_potential_players()) + possible_games = floor(total_players / PLAYER_PER_COURT) + return possible_games + + def get_potential_players(self) -> dict: + players = {k: v for k, v in self.players.items() if v.status} + guests = { + self.guest_id_start + k: Player(name=f"Guest {k}") + for k in range(1, self.guests + 1) + } + players.update(guests) + return players -- cgit v1.3.1 From 14df28d5b8d3d9d80f24c532e1c096f8ac997e5b Mon Sep 17 00:00:00 2001 From: Karan Jayachandra Date: Sat, 9 Nov 2024 18:49:40 +0100 Subject: Added the random name generation to be part of the package --- src/match_up/__init__.py | 12 ++++++++++-- src/match_up/controller.py | 6 +++--- src/match_up/gen_test_data.py | 32 -------------------------------- src/match_up/model.py | 36 ++++++++++++++++++++++++------------ src/match_up/utilities.py | 5 +++-- 5 files changed, 40 insertions(+), 51 deletions(-) delete mode 100644 src/match_up/gen_test_data.py (limited to 'src/match_up/model.py') diff --git a/src/match_up/__init__.py b/src/match_up/__init__.py index 1f625a7..3967cb9 100644 --- a/src/match_up/__init__.py +++ b/src/match_up/__init__.py @@ -1,9 +1,10 @@ from flask import Flask from dotenv import load_dotenv +from argparse import ArgumentParser from importlib.resources import path from match_up.controller import RoundGenerator from match_up.model import CourtList, PlayerList - +from match_up.utilities import Timer load_dotenv() with path("match_up", "static") as p: @@ -11,10 +12,17 @@ with path("match_up", "static") as p: with path("match_up", "templates") as p: template_folder = p app = Flask("Match Up! Backend", static_folder=static_folder, template_folder=template_folder) -rg = RoundGenerator(courts=CourtList(), players=PlayerList()) +rg = RoundGenerator() from match_up import routes def main(): + parser = ArgumentParser() + parser.add_argument("-t", "--timer", help="Total mins per round", type=float, default=12) + parser.add_argument("-c", "--courts", help="Total number of courts", type=int, default=12) + args = parser.parse_args() + global rg + rg.courts = CourtList(total=args.courts) + rg.timer = Timer(max_mins=args.timer) app.run() diff --git a/src/match_up/controller.py b/src/match_up/controller.py index 2f8bfaf..6188b3e 100644 --- a/src/match_up/controller.py +++ b/src/match_up/controller.py @@ -1,6 +1,6 @@ from typing import Tuple from operator import attrgetter -from dataclasses import dataclass +from dataclasses import dataclass, field from match_up.utilities import sample_list, Timer from match_up.model import Team, Game, PlayerList, CourtList, MAX_LEVEL, PLAYER_PER_COURT @@ -43,8 +43,8 @@ def _create_games(courts: dict, players: list[dict], levels: int): @dataclass class RoundGenerator: - courts: CourtList - players: PlayerList + courts: CourtList = field(default_factory=lambda: CourtList()) + players: PlayerList = field(default_factory=lambda: PlayerList()) round: int = 0 proposal: tuple = tuple() diff --git a/src/match_up/gen_test_data.py b/src/match_up/gen_test_data.py deleted file mode 100644 index a49594f..0000000 --- a/src/match_up/gen_test_data.py +++ /dev/null @@ -1,32 +0,0 @@ -from csv import writer -from random import randint -from names import get_full_name -from model import Player, MIN_LEVEL, MAX_LEVEL - -PLAYER_COUNT = 80 - - -def _generate_players(player_count: int) -> list[Player]: - players = [] - for _ in range(player_count): - random_name = get_full_name() - random_skill = randint(MIN_LEVEL, MAX_LEVEL) - players.append(Player(name=random_name, skill=random_skill)) - return players - - -def _write_players_to_csv(player_list: list[Player]) -> None: - with open("database_test.csv", "w", newline="") as file: - data_writer = writer(file) - data_writer.writerow(["name", "skill"]) - for player in player_list: - data_writer.writerow([player.name, player.skill]) - - -def main(player_count: int): - players = _generate_players(player_count) - _write_players_to_csv(players) - - -if __name__ == "__main__": - main(PLAYER_COUNT) diff --git a/src/match_up/model.py b/src/match_up/model.py index c652ce8..592d60f 100644 --- a/src/match_up/model.py +++ b/src/match_up/model.py @@ -1,11 +1,13 @@ -from os import getenv from math import floor from csv import reader from typing import Tuple +from names import get_full_name from dataclasses import dataclass +from random import randint, getrandbits MIN_LEVEL = 1 MAX_LEVEL = 10 +DEFAULT_COURTS = 12 PLAYER_PER_COURT = 4 @@ -28,10 +30,9 @@ class Game: team1: Team team2: Team - @dataclass class CourtList: - total: int = int(getenv("COURTS")) + total: int = DEFAULT_COURTS def __post_init__(self) -> None: self.courts = {i + 1: True for i in range(self.total)} @@ -52,21 +53,32 @@ class CourtList: inactive_courts = {k: v for k, v in self.courts.items() if not v} return active_courts, inactive_courts +def _load_csv_players(file_name: str) -> dict: + with open(file_name, newline="") as file: + pointer = reader(file) + next(pointer, None) + players = { + id: Player(row[0], int(row[1])) for id, row in enumerate(pointer) + } + return players + +def _generate_random_players(player_count: int = 80) -> list[Player]: + players = {i: Player(name=get_full_name(), + skill=randint(MIN_LEVEL, MAX_LEVEL), + status=bool(getrandbits(1))) for i in range(player_count)} + return players @dataclass class PlayerList: - location: str = getenv("DATABASE") + location: str = None guests: int = 0 def __post_init__(self) -> None: - with open("data/" + self.location, newline="") as file: - pointer = reader(file) - next(pointer, None) - players = { - id: Player(row[0], int(row[1])) for id, row in enumerate(pointer) - } - self.guest_id_start = len(players) + 1 - self.players = players + if self.location is not None: + self.players = _load_csv_players(self.location) + else: + self.players = _generate_random_players() + self.guest_id_start = len(self.players) + 1 def increment_guests(self): self.guests = self.guests + 1 diff --git a/src/match_up/utilities.py b/src/match_up/utilities.py index 7a9d55d..8a905ba 100644 --- a/src/match_up/utilities.py +++ b/src/match_up/utilities.py @@ -1,10 +1,11 @@ -from os import getenv from time import time from typing import Tuple from random import shuffle from dataclasses import dataclass + SECS_IN_MIN = 60 +DEFAULT_TIMER = 12.0 def _shuffle_two_lists(a: list, b: list) -> Tuple[list, list]: @@ -30,9 +31,9 @@ def sample_list(indices: list, cost: list[int], count: int = None) -> list: @dataclass class Timer: + max_mins: float = DEFAULT_TIMER ref: float = None running: bool = False - max_mins: float = float(getenv("TIMER")) default: str = ("00", "00") def __post_init__(self): -- cgit v1.3.1 From aa73a7618075b54940d32b7b1e0e751b301bee4d Mon Sep 17 00:00:00 2001 From: Karan Jayachandra Date: Sat, 9 Nov 2024 18:52:45 +0100 Subject: Formatted the package with black --- src/match_up/__init__.py | 15 +++++++++++---- src/match_up/controller.py | 9 ++++++++- src/match_up/model.py | 19 +++++++++++++------ src/match_up/routes.py | 11 ++++++----- 4 files changed, 38 insertions(+), 16 deletions(-) (limited to 'src/match_up/model.py') diff --git a/src/match_up/__init__.py b/src/match_up/__init__.py index 3967cb9..996bf9a 100644 --- a/src/match_up/__init__.py +++ b/src/match_up/__init__.py @@ -2,25 +2,32 @@ from flask import Flask from dotenv import load_dotenv from argparse import ArgumentParser from importlib.resources import path +from match_up.utilities import Timer from match_up.controller import RoundGenerator from match_up.model import CourtList, PlayerList -from match_up.utilities import Timer load_dotenv() with path("match_up", "static") as p: static_folder = p with path("match_up", "templates") as p: template_folder = p -app = Flask("Match Up! Backend", static_folder=static_folder, template_folder=template_folder) +app = Flask( + "Match Up! Backend", static_folder=static_folder, template_folder=template_folder +) rg = RoundGenerator() from match_up import routes + def main(): parser = ArgumentParser() - parser.add_argument("-t", "--timer", help="Total mins per round", type=float, default=12) - parser.add_argument("-c", "--courts", help="Total number of courts", type=int, default=12) + parser.add_argument( + "-t", "--timer", help="Total mins per round", type=float, default=12 + ) + parser.add_argument( + "-c", "--courts", help="Total number of courts", type=int, default=12 + ) args = parser.parse_args() global rg rg.courts = CourtList(total=args.courts) diff --git a/src/match_up/controller.py b/src/match_up/controller.py index 6188b3e..a21fced 100644 --- a/src/match_up/controller.py +++ b/src/match_up/controller.py @@ -2,7 +2,14 @@ from typing import Tuple from operator import attrgetter from dataclasses import dataclass, field from match_up.utilities import sample_list, Timer -from match_up.model import Team, Game, PlayerList, CourtList, MAX_LEVEL, PLAYER_PER_COURT +from match_up.model import ( + Team, + Game, + PlayerList, + CourtList, + MAX_LEVEL, + PLAYER_PER_COURT, +) def _create_placeholders(courts: dict, name: str) -> list[Game]: diff --git a/src/match_up/model.py b/src/match_up/model.py index 592d60f..5d6c0f5 100644 --- a/src/match_up/model.py +++ b/src/match_up/model.py @@ -30,6 +30,7 @@ class Game: team1: Team team2: Team + @dataclass class CourtList: total: int = DEFAULT_COURTS @@ -53,21 +54,27 @@ class CourtList: inactive_courts = {k: v for k, v in self.courts.items() if not v} return active_courts, inactive_courts + def _load_csv_players(file_name: str) -> dict: with open(file_name, newline="") as file: pointer = reader(file) next(pointer, None) - players = { - id: Player(row[0], int(row[1])) for id, row in enumerate(pointer) - } + players = {id: Player(row[0], int(row[1])) for id, row in enumerate(pointer)} return players + def _generate_random_players(player_count: int = 80) -> list[Player]: - players = {i: Player(name=get_full_name(), - skill=randint(MIN_LEVEL, MAX_LEVEL), - status=bool(getrandbits(1))) for i in range(player_count)} + players = { + i: Player( + name=get_full_name(), + skill=randint(MIN_LEVEL, MAX_LEVEL), + status=bool(getrandbits(1)), + ) + for i in range(player_count) + } return players + @dataclass class PlayerList: location: str = None diff --git a/src/match_up/routes.py b/src/match_up/routes.py index 524d50b..319b111 100644 --- a/src/match_up/routes.py +++ b/src/match_up/routes.py @@ -4,10 +4,10 @@ from flask import render_template, request, url_for re = Environment(loader=PackageLoader("match_up")) + @app.route("/", methods=["GET"]) def home(): - template = re.get_template("index.j2").render(url_for=url_for) - return template + return re.get_template("index.j2").render(url_for=url_for) @app.route("/time", methods=["GET"]) @@ -68,8 +68,9 @@ def toggle_player(player_request): @app.route("/players", methods=["GET"]) def get_list_of_players(): - template = re.get_template("players.j2").render(players=rg.players.get_players(), url_for=url_for) - return template + return re.get_template("players.j2").render( + players=rg.players.get_players(), url_for=url_for + ) @app.route("/court-toggle/", methods=["POST"]) @@ -82,4 +83,4 @@ def toggle_court(court_number): @app.route("/courts", methods=["GET"]) def get_list_of_courts(): - return render_template("courts.j2", courts=rg.courts.get_courts()) \ No newline at end of file + return render_template("courts.j2", courts=rg.courts.get_courts()) -- cgit v1.3.1