summaryrefslogtreecommitdiff
path: root/controller.py
blob: 45ae2bf4ee97cb9700e58363221021db1b44906e (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
101
102
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