"""ELO Rating System for ServeSync""" K_FACTOR = 32 # Standard K-factor def expected_score(rating_a: float, rating_b: float) -> float: """Calculate expected score for player A vs player B""" return 1 / (1 + 10 ** ((rating_b - rating_a) / 400)) def calculate_elo_change(winner_rating: float, loser_rating: float) -> tuple[float, float]: """ Calculate ELO changes after a match. Returns (winner_change, loser_change) """ expected_winner = expected_score(winner_rating, loser_rating) expected_loser = expected_score(loser_rating, winner_rating) winner_change = K_FACTOR * (1 - expected_winner) loser_change = K_FACTOR * (0 - expected_loser) return round(winner_change, 2), round(loser_change, 2) def calculate_team_elo(player1_rating: float, player2_rating: float = None) -> float: """Calculate team ELO (average for doubles)""" if player2_rating is None: return player1_rating return (player1_rating + player2_rating) / 2 def get_tier_from_elo(elo: float) -> str: """Get membership tier based on ELO rating""" if elo < 1000: return "bronze" elif elo < 1200: return "silver" elif elo < 1500: return "gold" elif elo < 1800: return "platinum" else: return "elite" def is_valid_match(player_elo: float, match_min_elo: float, match_max_elo: float) -> bool: """Check if player is within ELO range for skill-based match""" return match_min_elo <= player_elo <= match_max_elo def get_elo_range(player_elo: float, tolerance: float = 200) -> tuple[float, float]: """Get valid ELO range for matching""" return (max(0, player_elo - tolerance), player_elo + tolerance)