diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/match_up/controller.py | 58 | ||||
| -rw-r--r-- | src/match_up/data.py | 7 | ||||
| -rw-r--r-- | src/match_up/model.py | 7 | ||||
| -rw-r--r-- | src/match_up/routes.py | 5 | ||||
| -rw-r--r-- | src/match_up/templates/controls.j2 | 12 | ||||
| -rw-r--r-- | src/match_up/utilities.py | 43 |
6 files changed, 86 insertions, 46 deletions
diff --git a/src/match_up/controller.py b/src/match_up/controller.py index 0e08cae..585160f 100644 --- a/src/match_up/controller.py +++ b/src/match_up/controller.py @@ -2,7 +2,7 @@ from typing import Tuple from operator import attrgetter from match_up.data import Game, PLAYER_PER_COURT from match_up.model import Player, PlayerList, CourtList -from match_up.utilities import _create_placeholders, _select_players, _create_games +from match_up.utilities import _create_placeholders, _select_players, _create_games, _create_team_games class RoundGenerator: @@ -30,21 +30,44 @@ class RoundGenerator: return games def _create_active_games( - self, total_levels: int + self, total_levels: int, group_by_team: bool ) -> Tuple[list[Game], list[Player]]: - active_courts, _ = self.courts.separate_courts() - used_courts, _ = self._separate_courts(active_courts) + active_courts = self.courts.separate_courts()[0] + used_courts = self._separate_courts(active_courts)[0] required_player_count = len(used_courts) * PLAYER_PER_COURT active_players = self.players.get_players() - selected_players = _select_players(active_players, required_player_count) - games = _create_games(used_courts, selected_players, total_levels) - return games, selected_players + if group_by_team: + unique_team_id = {player.team for player in active_players} + grouped_players_by_team = {team_id: [] for team_id in unique_team_id} + for player in active_players: + team = player.team + grouped_players_by_team[team].append(player) + active_teams = {} + players_without_team = [] + for team_id in grouped_players_by_team: + if team_id == 0: + players_without_team += [player for player in grouped_players_by_team[team_id]] + else: + if len(grouped_players_by_team[team_id]) >= 4: + active_teams[team_id] = grouped_players_by_team[team_id] + else: + players_without_team += [player for player in grouped_players_by_team[team_id]] + + regular_courts = len(used_courts) - len(active_teams) + reg_courts = {A:N for (A,N) in [x for x in used_courts.items()][:regular_courts]} + team_courts = {A:N for (A,N) in [x for x in used_courts.items()][regular_courts:]} - def _generate_proposal(self, total_levels: int) -> Tuple[list[Game], list[Player]]: - inactive_games = self._create_inactive_games() - active_games, selected_players = self._create_active_games(total_levels) - games = active_games + inactive_games - games.sort(key=attrgetter("court")) + required_player_count = required_player_count - (4 * len(active_teams)) + selected_players_without_team = _select_players(players_without_team, required_player_count) + regular_games = _create_games(reg_courts, selected_players_without_team, total_levels) + + team_games, selected_players_with_team = _create_team_games(team_courts, active_teams) + + selected_players = selected_players_without_team + selected_players_with_team + games = regular_games + team_games + else: + selected_players = _select_players(active_players, required_player_count) + games = _create_games(used_courts, selected_players, total_levels) return games, selected_players def update_player_list(self, csv_location): @@ -55,10 +78,13 @@ class RoundGenerator: self.proposed_players = [] return self.games - def propose(self, levels: int) -> list[Game]: - proposal = self._generate_proposal(levels) - self.proposed_games = proposal[0] - self.proposed_players = proposal[1] + def propose(self, levels: int, group_by_team: bool) -> list[Game]: + inactive_games = self._create_inactive_games() + active_games, selected_players = self._create_active_games(levels, group_by_team) + games = active_games + inactive_games + games.sort(key=attrgetter("court")) + self.proposed_games = games + self.proposed_players = selected_players return self.proposed_games def confirm(self) -> list[Game]: diff --git a/src/match_up/data.py b/src/match_up/data.py index 636a5eb..d8996fe 100644 --- a/src/match_up/data.py +++ b/src/match_up/data.py @@ -18,15 +18,18 @@ class Player(BASE): first = Column("first", String) last = Column("last", String) level = Column("level", Integer) + team = Column("team", Integer) status = Column("status", Integer) count = Column("count", Integer) + def __init__( self, id: int, first: str = "", last: str = "", level: int = 0, + team: int = 0, status: bool = True, count: int = 0, ): @@ -34,12 +37,14 @@ class Player(BASE): self.first = first self.last = last self.status = status + self.team = team self.level = level self.count = count def __repr__(self): + team = f" of Team {self.team}" if self.team else "" status = "active" if self.status else "inactive" - return f"{self.first} {self.last} (Level {self.level}) is {status} and has played {self.count} games" + return f"{self.first} {self.last} (Level {self.level}){team} is {status} and has played {self.count} games" class DisplayPlayer: diff --git a/src/match_up/model.py b/src/match_up/model.py index 4ac8c54..52d72b2 100644 --- a/src/match_up/model.py +++ b/src/match_up/model.py @@ -5,13 +5,8 @@ from dataclasses import dataclass from importlib.resources import path from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine, not_ +from match_up.data import PLAYER_PER_COURT, BASE, Player, DisplayPlayer from match_up.utilities import _init_database_from_csv, _init_random_database -from match_up.data import ( - Player, - DisplayPlayer, - PLAYER_PER_COURT, - BASE, -) @dataclass diff --git a/src/match_up/routes.py b/src/match_up/routes.py index 8ae18ce..f9cd2fa 100644 --- a/src/match_up/routes.py +++ b/src/match_up/routes.py @@ -17,8 +17,9 @@ def get_controls(): @_app.route("/propose", methods=["POST"]) def get_random_games(): - levels = int(request.form["type"].split()[0]) - return render_template("games.j2", games=_rg.propose(levels), title="Proposal") + levels = int(request.form["levels"].split()[0]) + team_practice = request.form["team"] == "Teams" + return render_template("games.j2", games=_rg.propose(levels, team_practice), title="Proposal") @_app.route("/confirm", methods=["POST"]) diff --git a/src/match_up/templates/controls.j2 b/src/match_up/templates/controls.j2 index 95584f7..0183c97 100644 --- a/src/match_up/templates/controls.j2 +++ b/src/match_up/templates/controls.j2 @@ -9,7 +9,7 @@ <div class="columns"> <div class="column"> <div class="select is-responsive"> - <select name="type"> + <select name="levels"> <option>10 Levels</option> <option>8 Levels</option> <option>6 Levels</option> @@ -20,10 +20,18 @@ </div> </div> <div class="column"> + <div class="select is-responsive"> + <select name="team"> + <option>Random</option> + <option>Teams</option> + </select> + </div> + </div> + <div class="column"> <button class="button is-dark is-responsive" hx-post="/propose" hx-target="#games" - hx-include="[name='type']">Generate</button> + hx-include="[name='levels'], [name='team']">Generate</button> </div> <div class="column"></div> <div class="column"> diff --git a/src/match_up/utilities.py b/src/match_up/utilities.py index 9fc31fa..dd9568c 100644 --- a/src/match_up/utilities.py +++ b/src/match_up/utilities.py @@ -1,13 +1,11 @@ +from math import floor from typing import Tuple -from pandas import read_csv from random import shuffle +from pandas import read_csv from random import randint, getrandbits from names import get_first_name, get_last_name +from match_up.data import Player, DisplayPlayer, Team, Game from match_up.data import ( - Player, - DisplayPlayer, - Team, - Game, MIN_LEVEL, MAX_LEVEL, PLAYER_PER_COURT, @@ -86,27 +84,27 @@ def _create_games(courts: dict, players: list[Player], levels: int) -> list[Game games.append(Game(court, team1, team2)) return games - -def _textualize_guest(level, value) -> str: - match level: - case 1: - text = "Beginners" - case 3: - text = "Novices" - case 5: - text = "Intermediates" - if value == 1: - text = text[:-1] - return f"{value} {text}" +def _create_team_games(courts: dict, teams: dict) -> tuple[list[Game], list[Player]]: + games = [] + selected_players = [] + for court, (_, players) in zip(courts, teams.items()): + selected_players.append(players[:3]) + team1 = Team( + player1=DisplayPlayer(players[0]), player2=DisplayPlayer(players[3]) + ) + team2 = Team( + player1=DisplayPlayer(players[1]), player2=DisplayPlayer(players[2]) + ) + games.append(Game(court, team1, team2)) + return games, selected_players def _init_guests(session) -> None: for level_id, level in enumerate(GUEST_LEVELS): for player_id in range(GUESTS_PER_LEVEL): unique_id = (level_id * GUESTS_PER_LEVEL) + player_id + 1 - id = 1000 + unique_id player = Player( - id=id, + id=-unique_id, first="Guest", last=str(unique_id), level=level, @@ -135,12 +133,19 @@ def _init_database_from_csv(session, csv_location: str) -> None: def _init_random_database(session, player_count: int = 80) -> None: + total_teams = 5 + players_per_team = 5 for i in range(player_count): + if i < total_teams * players_per_team: + team = floor(i / players_per_team) + 1 + else: + team = 0 player = Player( id=i, first=get_first_name(), last=get_last_name(), level=randint(MIN_LEVEL, MAX_LEVEL), + team=team, status=bool(getrandbits(1)), count=0, ) |
