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_shuffle_games, _create_team_games class RoundGenerator: proposed_games: list[Game] = [] proposed_players: list[Player] = [] def __init__(self) -> None: self.courts = CourtList() self.players = PlayerList() self.reset() def _separate_courts(self, courts: dict) -> Tuple[dict, dict]: possible_games = min(len(courts), self.players.get_possible_game_count()) courts_as_list = list(courts.items()) used_courts = dict(courts_as_list[:possible_games]) unused_courts = dict(courts_as_list[possible_games:]) return used_courts, unused_courts def _create_inactive_games(self) -> list[Game]: active_courts, reserved_courts = self.courts.separate_courts() reserved_games = _create_placeholders(reserved_courts, "RESERVED") _, unused_courts = self._separate_courts(active_courts) blank_games = _create_placeholders(unused_courts, "---") games = reserved_games + blank_games return games def _create_active_games( self, total_levels: int, group_by_team: bool ) -> Tuple[list[Game], list[Player]]: 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() 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 or len(grouped_players_by_team[team_id]) < 4: players_without_team += [player for player in grouped_players_by_team[team_id]] else: active_teams[team_id] = 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:]} required_player_count = required_player_count - (PLAYER_PER_COURT * len(active_teams)) selected_players_without_team = _select_players(players_without_team, required_player_count) regular_games = _create_shuffle_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_shuffle_games(used_courts, selected_players, total_levels) return games, selected_players def update_player_list(self, csv_location): self.players = PlayerList(csv_location) def clear(self) -> list[Game]: self.proposed_games = [] self.proposed_players = [] return self.games 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]: if len(self.proposed_games) == 0: return self.games self.games = self.proposed_games identifiers = [int(player.id) for player in self.proposed_players] self.players.increment_game_count(identifiers) self.round += 1 return self.clear() def reset(self): self.round = 0 self.games = _create_placeholders(self.courts.get_courts(), "---") self.players.reset_game_count() return self.games