from app import app, db from typing import Tuple, Sequence from random import shuffle, sample from app.model import Player, DisplayPlayer, Court, DisplayGame, DisplayTeam def _shuffle_two_lists(a: list, b: list) -> Tuple[list, list]: indices = list(range(len(a))) shuffle(indices) a = [a[index] for index in indices] b = [b[index] for index in indices] return a, b def _pick_from_list_after_sorting_other(a: list, b: list[int]) -> list: indices = [i[0] for i in sorted(enumerate(b), key=lambda x: x[1])] return [a[index] for index in indices] def sample_list(indices: list, cost: list[int], count=None) -> list: if count is None: count = len(indices) indices, cost = _shuffle_two_lists(indices, cost) indices = _pick_from_list_after_sorting_other(indices, cost)[:count] return indices def _normalize_skill(level: int, new_max: int) -> int: new_level = round((new_max - 1) * (level / app.config["MAX_PLAYER_LEVEL"])) + 1 return new_level def select_players(players: Sequence[Player], count: int) -> list[Player]: identifiers = [player.id for player in players] play_count = [int(player.id) for player in players] ids = sample_list(identifiers, play_count, count) selected_players = [player for player in players if player.id in ids] return selected_players def group_by_four(players: list[Player], new_max: int) -> list[list[Player]]: identifiers = [player.id for player in players] player_levels = [_normalize_skill(int(player.level), new_max) for player in players] identifiers = sample_list(identifiers, player_levels) court_players = [] for i in range(0, len(players), app.config["PLAYERS_PER_COURT"]): court_ids = identifiers[i : i + app.config["PLAYERS_PER_COURT"]] selected_players = [player for player in players if player.id in court_ids] court_players.append(selected_players) return court_players def separate_teams_and_players( players: Sequence[Player], ) -> tuple[dict[int, list[Player]], list[Player]]: unique_team_id = {player.team for player in players} grouped_players_by_team = {team_id: [] for team_id in unique_team_id} for player in 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] ] return active_teams, players_without_team def get_placeholder_games(courts: list[Court], name: str) -> list[DisplayGame]: p = db.session.query(Player).where(Player.first_name == name).first() if p is None: raise ValueError(f"Database isn't initialized.") dummy_team = DisplayTeam(DisplayPlayer(p), DisplayPlayer(p)) games = [DisplayGame(court.id, dummy_team, dummy_team) for court in courts] return games def get_team_games( courts: list[Court], teams: dict[int, list[Player]] ) -> list[DisplayGame]: games = [] for court, (_, players) in zip(courts, teams.items()): players = sample(players, app.config["PLAYER_PER_COURT"]) players.sort(key=lambda x: x.level, reverse=True) dp = [DisplayPlayer(p) for p in players] games.append( DisplayGame(court.id, DisplayTeam(dp[0], dp[3]), DisplayTeam(dp[1], dp[2])) ) return games def get_shuffle_games( courts: list[Court], players: Sequence[Player], total_levels: int ) -> list[DisplayGame]: required_player_count = len(courts) * app.config["PLAYER_PER_COURT"] selected_players = select_players(players, required_player_count) court_players = group_by_four(selected_players, total_levels) games = [] for court, players in zip(courts, court_players): dp = [DisplayPlayer(p) for p in players] games.append( DisplayGame(court.id, DisplayTeam(dp[0], dp[3]), DisplayTeam(dp[1], dp[2])) ) return games