from math import floor from random import sample from operator import attrgetter from dataclasses import dataclass, field from model import Team, Game, PlayerList, CourtList PLAYER_PER_COURT = 4 def _create_placeholders(courts: dict, name: str): dummy_team = Team(player1=name, player2=name) return [Game(court, dummy_team, dummy_team) for court in courts] def create_game(court: int, players: dict): ids = list(players.keys()) team1 = Team(player1=players[ids[0]].name, player2=players[ids[3]].name) team2 = Team(player1=players[ids[1]].name, player2=players[ids[2]].name) return Game(court, team1, team2) def select_players(players: dict, count: int): identifiers = sample(sorted(players), count) return {id: players[id] for id in identifiers} def get_random_combinations(players: dict) -> list[dict]: ids = list(players.keys()) clumps = [ ids[i : i + PLAYER_PER_COURT] for i in range(0, len(players), PLAYER_PER_COURT) ] combinations = [{id: players[id] for id in clump} for clump in clumps] return combinations def create_random_games(courts: CourtList, players: PlayerList): active_courts, reserved_courts = courts.separate_courts() # Block the courts for other activities reserved_games = _create_placeholders(reserved_courts, "RESERVED") # Check if there are too many courts possible_players = players.separate_players()[0] possible_games = floor(len(possible_players) / PLAYER_PER_COURT) # Create the games selected_players = select_players( possible_players, possible_games * PLAYER_PER_COURT ) combinations = get_random_combinations(selected_players) used_courts = dict(list(active_courts.items())[:possible_games]) active_games = [ create_game(court, clump) for court, clump in zip(used_courts, combinations) ] # Create dummy games if there are empty courts dummy_games = [] if possible_games < len(active_courts): unused_courts = dict(list(active_courts.items())[possible_games:]) dummy_games = _create_placeholders(unused_courts, "---") # Return the list of games games = active_games + dummy_games + reserved_games games.sort(key=attrgetter("court")) games = {idx: value for idx, value in enumerate(games)} return games @dataclass class Session: courts: CourtList players: PlayerList round: int = 0 games: dict = field(default_factory=dict) proposal: dict = field(default_factory=dict) history: list[dict] = field(default_factory=list) def __post_init__(self): self.history = [] active_courts, inactive_courts = self.courts.separate_courts() dummy_games = _create_placeholders(active_courts, "---") reserved_games = _create_placeholders(inactive_courts, "RESERVED") games = dummy_games + reserved_games games.sort(key=attrgetter("court")) games = {idx: value for idx, value in enumerate(games)} self.games = games def clear_round(self): self.proposal = {} return self.games def propose_round(self, levels: int = 10): self.proposal = create_random_games(self.courts, self.players) return self.proposal def confirm_round(self): self.games = self.proposal self.history.append(self.proposal) self.proposal = {} self.round += 1 return self.games