diff options
| -rw-r--r-- | .vscode/settings.json | 3 | ||||
| -rw-r--r-- | main.py | 188 |
2 files changed, 105 insertions, 86 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d6e2638 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.analysis.typeCheckingMode": "strict" +} @@ -1,166 +1,182 @@ from __future__ import annotations +from dataclasses import dataclass from datetime import datetime +from enum import Enum +from typing import Protocol -class Player: - all_players: list[Player] = [] +class Player(Enum): + Emma = "Emma" + Kim = "Kim" + Pierre = "Pierre" + Theo = "Théo" + Leila = "Leïla" + Martin = "Martin" + Clementine = "Clémentine" + Thomas = "Thomas" + Baptiste = "Baptiste" + Tanguy = "Tanguy" + Frost = "Frost" + Felix = "Félix" + Axel = "Axel" - name: str + +@dataclass(frozen=True) +class PlayerStatus: + player: Player elo: int total_games: int - def __init__(self, name: str): - self.name = name - self.elo = 1000 - self.total_games = 0 - self.all_players.append(self) - - def __str__(self): - return self.name - @staticmethod - def print_ladder(): - print(f"Ladder ({datetime.now().strftime('%d/%m/%Y %H:%M')}):") - print("=" * 30) - for rank, player in enumerate( - sorted(Player.all_players, key=lambda player: player.elo, reverse=True) - ): - print( - f"{rank+1}.\t{player.name:<20}: {player.elo:>4d} points, {player.total_games:>3d} games" - ) - - -Emma = Player(name="Emma") -Kim = Player(name="Kim") -Pierre = Player(name="Pierre") -Theo = Player(name="Théo") -Leila = Player(name="Leïla") -Martin = Player(name="Martin") -Clementine = Player(name="Clémentine") -Thomas = Player(name="Thomas") -Baptiste = Player(name="Baptiste") -Tanguy = Player(name="Tanguy") -Frost = Player(name="Frost") -Felix = Player(name="Félix") -Axel = Player(name="Axel") - -D = 400 -K = 32 - + def create(player: Player) -> PlayerStatus: + return PlayerStatus(player=player, elo=1000, total_games=0) + +@dataclass(frozen=True) class Game: - scores: dict[Player, int] played_at: datetime + scores: dict[Player, int] def __str__(self) -> str: total_points = sum(self.scores.values()) return f"Game played at {self.played_at} ({total_points} total points)" - def __init__(self, played_at: datetime, scores: dict[Player, int]): - self.scores = scores - self.played_at = played_at - def get_players_elo_updates(self) -> dict[Player, float]: - players_elo_updates = {player: 0.0 for player in self.scores} - for player in self.scores: - player.total_games += 1 - for player_1, score_1 in self.scores.items(): - for player_2, score_2 in self.scores.items(): +class GameEloChangeStrategy(Protocol): + pass + + +class Ladder: + strategy: GameEloChangeStrategy + players: dict[Player, PlayerStatus] = {player: PlayerStatus.create(player) for player in Player} + + def current_elo(self) -> dict[Player, int]: + return {player: player_status.elo for player, player_status in self.players.items()} + + def proccess_game(self, game: Game) -> dict[Player, float]: + players_elo_updates = {player: 0.0 for player in game.scores} + for player_1, score_1 in game.scores.items(): + for player_2, score_2 in game.scores.items(): if player_1 != player_2: - expected_score = 1 / (1 + 10 ** ((player_2.elo - player_1.elo) / D)) + expected_score = 1 / (1 + 10 ** ((self.players[player_2].elo - self.players[player_1].elo) / D)) result = ( 1.0 if score_1 > score_2 else 0.0 if score_1 < score_2 else 0.5 ) players_elo_updates[player_1] += K * (result - expected_score) + for player, elo_update in players_elo_updates.items(): + self.players[player] = PlayerStatus( + player=player, + elo=self.players[player].elo + int(elo_update), + total_games=self.players[player].total_games + 1, + ) + return players_elo_updates + def print_current(self): + print(f"Ladder ({datetime.now().strftime('%d/%m/%Y %H:%M')}):") + print("=" * 30) + for rank, player in enumerate( + sorted(self.players.values(), key=lambda player: player.elo, reverse=True) + ): + print( + f"{rank+1}.\t{player.player:<20}: {player.elo:>4d} points, {player.total_games:>3d} games" + ) + + + +ladder = Ladder() + +D = 400 +K = 32 + + + games: list[Game] = [ Game( datetime(2022, 11, 11, 16, 30), - {Theo: 53, Leila: 32, Clementine: 53, Emma: 48, Kim: 50, Martin: 51}, + {Player.Theo: 53, Player.Leila: 32, Player.Clementine: 53, Player.Emma: 48, Player.Kim: 50, Player.Martin: 51}, ), Game( datetime(2022, 11, 11, 17, 0), - {Emma: 53, Kim: 57, Pierre: 48, Theo: 44, Leila: 32, Martin: 57}, + {Player.Emma: 53, Player.Kim: 57, Player.Pierre: 48, Player.Theo: 44, Player.Leila: 32, Player.Martin: 57}, ), Game( datetime(2022, 11, 11, 18, 45), - {Thomas: 58, Baptiste: 45, Pierre: 54, Theo: 65, Emma: 42, Martin: 53}, + {Player.Thomas: 58, Player.Baptiste: 45, Player.Pierre: 54, Player.Theo: 65, Player.Emma: 42, Player.Martin: 53}, ), Game( datetime(2022, 11, 11, 21, 0), - {Kim: 50, Theo: 50, Emma: 53, Clementine: 55, Pierre: 46, Baptiste: 54}, + {Player.Kim: 50, Player.Theo: 50, Player.Emma: 53, Player.Clementine: 55, Player.Pierre: 46, Player.Baptiste: 54}, ), Game( datetime(2022, 11, 11, 21, 30), { - Kim: 41, - Leila: 32, - Theo: 48, - Emma: 49, - Clementine: 52, - Pierre: 54, - Baptiste: 59, + Player.Kim: 41, + Player.Leila: 32, + Player.Theo: 48, + Player.Emma: 49, + Player.Clementine: 52, + Player.Pierre: 54, + Player.Baptiste: 59, }, ), Game( - datetime(2022, 11, 11, 22, 0), {Clementine: 47, Pierre: 46, Theo: 57, Emma: 42} + datetime(2022, 11, 11, 22, 0), {Player.Clementine: 47, Player.Pierre: 46, Player.Theo: 57, Player.Emma: 42} ), Game( - datetime(2022, 11, 11, 22, 32), {Clementine: 43, Pierre: 51, Theo: 40, Emma: 39} + datetime(2022, 11, 11, 22, 32), {Player.Clementine: 43, Player.Pierre: 51, Player.Theo: 40, Player.Emma: 39} ), Game( datetime(2022, 11, 12, 12, 48), - {Pierre: 58, Theo: 52, Emma: 59, Thomas: 50, Baptiste: 52}, + {Player.Pierre: 58, Player.Theo: 52, Player.Emma: 59, Player.Thomas: 50, Player.Baptiste: 52}, ), - Game(datetime(2022, 11, 12, 13, 18), {Emma: 41, Theo: 53, Pierre: 44}), - Game(datetime(2022, 11, 12, 13, 47), {Emma: 65, Thomas: 59, Pierre: 54}), + Game(datetime(2022, 11, 12, 13, 18), {Player.Emma: 41, Player.Theo: 53, Player.Pierre: 44}), + Game(datetime(2022, 11, 12, 13, 47), {Player.Emma: 65, Player.Thomas: 59, Player.Pierre: 54}), Game( datetime(2022, 11, 12, 14, 15), - {Pierre: 57, Emma: 52, Martin: 45, Clementine: 47}, + {Player.Pierre: 57, Player.Emma: 52, Player.Martin: 45, Player.Clementine: 47}, ), - Game(datetime(2022, 11, 12, 14, 47), {Pierre: 51, Emma: 47, Clementine: 56}), + Game(datetime(2022, 11, 12, 14, 47), {Player.Pierre: 51, Player.Emma: 47, Player.Clementine: 56}), Game( datetime(2022, 11, 12, 19, 6), - {Clementine: 43, Kim: 47, Theo: 13, Pierre: 47, Emma: 62}, + {Player.Clementine: 43, Player.Kim: 47, Player.Theo: 13, Player.Pierre: 47, Player.Emma: 62}, ), Game( datetime(2022, 11, 13, 12, 31), - {Theo: 43, Thomas: 37, Tanguy: 44, Pierre: 47, Emma: 61}, + {Player.Theo: 43, Player.Thomas: 37, Player.Tanguy: 44, Player.Pierre: 47, Player.Emma: 61}, ), Game( datetime(2022, 11, 13, 12, 54), { - Tanguy: 54, - Clementine: 47, - Theo: 65, - Thomas: 44, - Pierre: 60, - Kim: 58, - Emma: 46, + Player.Tanguy: 54, + Player.Clementine: 47, + Player.Theo: 65, + Player.Thomas: 44, + Player.Pierre: 60, + Player.Kim: 58, + Player.Emma: 46, }, ), - Game(datetime(2022, 11, 13, 13, 25), {Pierre: 52, Emma: 68, Clementine: 57}), + Game(datetime(2022, 11, 13, 13, 25), {Player.Pierre: 52, Player.Emma: 68, Player.Clementine: 57}), Game( datetime(2023, 1, 2, 10, 0), - {Felix: 34, Frost: 64, Thomas: 51, Baptiste: 53, Emma: 68}, + {Player.Felix: 34, Player.Frost: 64, Player.Thomas: 51, Player.Baptiste: 53, Player.Emma: 68}, ), - Game(datetime(2023, 1, 2, 10, 30), {Felix: 64, Frost: 55, Thomas: 62, Emma: 67}), + Game(datetime(2023, 1, 2, 10, 30), {Player.Felix: 64, Player.Frost: 55, Player.Thomas: 62, Player.Emma: 67}), Game( datetime(2023, 2, 19, 12, 0), - {Thomas: 56, Axel: 53, Emma: 61, Theo: 57, Pierre: 55, Martin: 36}, + {Player.Thomas: 56, Player.Axel: 53, Player.Emma: 61, Player.Theo: 57, Player.Pierre: 55, Player.Martin: 36}, ), ] for game in games: print(game) print("=" * 30) - players_elo_updates = game.get_players_elo_updates() + players_elo_updates = ladder.proccess_game(game) for (player, elo_update) in players_elo_updates.items(): - player.elo += int(elo_update) - print(f"\t{player.name:<20}{int(elo_update):+}\t({player.elo:>4d})") + print(f"\t{player:<20}{int(elo_update):+}\t({ladder.players[player].elo:>4d})") -Player.print_ladder() +ladder.print_current() |
