diff options
Diffstat (limited to 'main.py')
| -rw-r--r-- | main.py | 212 |
1 files changed, 99 insertions, 113 deletions
@@ -1,122 +1,58 @@ -from __future__ import annotations -from dataclasses import dataclass from datetime import datetime -from enum import Enum -from typing import Protocol - - -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" - - -@dataclass(frozen=True) -class PlayerStatus: - player: Player - elo: int - total_games: int - - @staticmethod - def create(player: Player) -> PlayerStatus: - return PlayerStatus(player=player, elo=1000, total_games=0) - - def update_elo(self, elo_update: int) -> PlayerStatus: - return PlayerStatus(player=self.player, elo=self.elo + elo_update, total_games=self.total_games + 1) - - -@dataclass(frozen=True) -class Game: - 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)" - - -class GameEloChangeStrategy(Protocol): - def proccess_game(self, game: Game, current_elo: dict[Player, int]) -> dict[Player, float]: - ... - -class SimpleEloChangeStrategy(GameEloChangeStrategy): - def proccess_game(self, game: Game, current_elo: dict[Player, int]) -> 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 ** ((current_elo[player_2] - current_elo[player_1]) / 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) - - return players_elo_updates - - -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 = self.strategy.proccess_game(game, self.current_elo()) - - for player, elo_update in players_elo_updates.items(): - self.players[player] = self.players[player].update_elo(int(elo_update)) - - 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.value:<20}: {player.elo:>4d} points, {player.total_games:>3d} games" - ) - +from game import Game +from ladder import Ladder +from player import Player +from strategy import SimpleEloChangeStrategy ladder = Ladder() ladder.strategy = SimpleEloChangeStrategy() -D = 400 -K = 32 - - - games: list[Game] = [ Game( datetime(2022, 11, 11, 16, 30), - {Player.Theo: 53, Player.Leila: 32, Player.Clementine: 53, Player.Emma: 48, Player.Kim: 50, Player.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), - {Player.Emma: 53, Player.Kim: 57, Player.Pierre: 48, Player.Theo: 44, Player.Leila: 32, Player.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), - {Player.Thomas: 58, Player.Baptiste: 45, Player.Pierre: 54, Player.Theo: 65, Player.Emma: 42, Player.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), - {Player.Kim: 50, Player.Theo: 50, Player.Emma: 53, Player.Clementine: 55, Player.Pierre: 46, Player.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), @@ -131,29 +67,58 @@ games: list[Game] = [ }, ), Game( - datetime(2022, 11, 11, 22, 0), {Player.Clementine: 47, Player.Pierre: 46, Player.Theo: 57, Player.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), {Player.Clementine: 43, Player.Pierre: 51, Player.Theo: 40, Player.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), - {Player.Pierre: 58, Player.Theo: 52, Player.Emma: 59, Player.Thomas: 50, Player.Baptiste: 52}, + { + Player.Pierre: 58, + Player.Theo: 52, + Player.Emma: 59, + Player.Thomas: 50, + Player.Baptiste: 52, + }, + ), + 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, 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), {Player.Pierre: 57, Player.Emma: 52, Player.Martin: 45, Player.Clementine: 47}, ), - Game(datetime(2022, 11, 12, 14, 47), {Player.Pierre: 51, Player.Emma: 47, Player.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), - {Player.Clementine: 43, Player.Kim: 47, Player.Theo: 13, Player.Pierre: 47, Player.Emma: 62}, + { + Player.Clementine: 43, + Player.Kim: 47, + Player.Theo: 13, + Player.Pierre: 47, + Player.Emma: 62, + }, ), Game( datetime(2022, 11, 13, 12, 31), - {Player.Theo: 43, Player.Thomas: 37, Player.Tanguy: 44, Player.Pierre: 47, Player.Emma: 61}, + { + Player.Theo: 43, + Player.Thomas: 37, + Player.Tanguy: 44, + Player.Pierre: 47, + Player.Emma: 61, + }, ), Game( datetime(2022, 11, 13, 12, 54), @@ -167,15 +132,34 @@ games: list[Game] = [ Player.Emma: 46, }, ), - Game(datetime(2022, 11, 13, 13, 25), {Player.Pierre: 52, Player.Emma: 68, Player.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), - {Player.Felix: 34, Player.Frost: 64, Player.Thomas: 51, Player.Baptiste: 53, Player.Emma: 68}, + { + Player.Felix: 34, + Player.Frost: 64, + Player.Thomas: 51, + Player.Baptiste: 53, + Player.Emma: 68, + }, + ), + Game( + datetime(2023, 1, 2, 10, 30), + {Player.Felix: 64, Player.Frost: 55, Player.Thomas: 62, Player.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), - {Player.Thomas: 56, Player.Axel: 53, Player.Emma: 61, Player.Theo: 57, Player.Pierre: 55, Player.Martin: 36}, + { + Player.Thomas: 56, + Player.Axel: 53, + Player.Emma: 61, + Player.Theo: 57, + Player.Pierre: 55, + Player.Martin: 36, + }, ), ] @@ -185,6 +169,8 @@ for game in games: players_elo_updates = ladder.proccess_game(game) for (player, elo_update) in players_elo_updates.items(): - print(f"\t{player.value:<20}{int(elo_update):+}\t({ladder.players[player].elo:>4d})") + print( + f"\t{player.value:<20}{int(elo_update):+}\t({ladder.players[player].elo:>4d})" + ) ladder.print_current() |
