aboutsummaryrefslogtreecommitdiff
path: root/src/match_up/controller.py
blob: a02dd0439eb56ef389fa0e032e4259517d52d34b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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