#!/usr/bin/env python3 """ Update player statistics (ELO, gamesPlayed, wins, losses) based on matches in the database """ import sqlite3 import math DB_PATH = "prisma/prisma/dev.db" K_FACTOR = 32 # Standard K-factor for Elo calculations def get_all_matches(): """Get all matches from the database""" conn = sqlite3.connect(DB_PATH) cursor = conn.cursor() cursor.execute(""" SELECT id, team1P1Id, team1P2Id, team2P1Id, team2P2Id, team1Score, team2Score, playedAt FROM matches ORDER BY playedAt """) matches = cursor.fetchall() conn.close() return matches def get_player(player_id): """Get a player by ID""" conn = sqlite3.connect(DB_PATH) cursor = conn.cursor() cursor.execute( "SELECT id, name, currentElo, gamesPlayed, wins, losses FROM players WHERE id = ?", (player_id,), ) player = cursor.fetchone() conn.close() return player def update_player(player_id, current_elo, games_played, wins, losses): """Update a player's statistics""" conn = sqlite3.connect(DB_PATH) cursor = conn.cursor() cursor.execute( """ UPDATE players SET currentElo = ?, gamesPlayed = ?, wins = ?, losses = ? WHERE id = ? """, (current_elo, games_played, wins, losses, player_id), ) conn.commit() conn.close() def calculate_elo_change(rating_a, rating_b, score_a, score_b): """Calculate Elo change for a match""" # Calculate expected scores expected_a = 1 / (1 + math.pow(10, (rating_b - rating_a) / 400)) expected_b = 1 - expected_a # Actual scores (1 for win, 0.5 for tie, 0 for loss) actual_a = 0.5 if score_a == score_b else (1 if score_a > score_b else 0) actual_b = 0.5 if score_a == score_b else (1 if score_b > score_a else 0) # Calculate Elo change elo_change_a = K_FACTOR * (actual_a - expected_a) elo_change_b = K_FACTOR * (actual_b - expected_b) return elo_change_a, elo_change_b def main(): print("Updating player statistics based on matches in database...") print("=" * 60) # Get all matches matches = get_all_matches() print(f"Found {len(matches)} matches in database") # Reset all player stats to 0 before recalculating conn = sqlite3.connect(DB_PATH) cursor = conn.cursor() cursor.execute( "UPDATE players SET currentElo = 1000, gamesPlayed = 0, wins = 0, losses = 0" ) conn.commit() conn.close() print("Reset all player statistics to initial values (ELO: 1000, games: 0)") # Process each match match_count = 0 for ( match_id, team1_p1, team1_p2, team2_p1, team2_p2, team1_score, team2_score, played_at, ) in matches: # Get player data p1 = get_player(team1_p1) p2 = get_player(team1_p2) p3 = get_player(team2_p1) p4 = get_player(team2_p2) if not all([p1, p2, p3, p4]): print(f"Warning: Could not find all players for match {match_id}") continue # Calculate team ratings team1_rating = (p1[2] + p2[2]) / 2 # currentElo team2_rating = (p3[2] + p4[2]) / 2 # currentElo # Calculate Elo changes team1_elo_change, team2_elo_change = calculate_elo_change( team1_rating, team2_rating, team1_score, team2_score ) # Individual Elo changes (split evenly between team members) p1_elo_change = team1_elo_change / 2 p2_elo_change = team1_elo_change / 2 p3_elo_change = team2_elo_change / 2 p4_elo_change = team2_elo_change / 2 # Determine winners team1_won = team1_score > team2_score team2_won = team2_score > team1_score # Update player 1 stats p1_new_elo = int(p1[2] + p1_elo_change) p1_new_games = p1[3] + 1 p1_new_wins = p1[4] + 1 if team1_won else p1[4] p1_new_losses = p1[5] if team1_won else p1[5] + 1 update_player(p1[0], p1_new_elo, p1_new_games, p1_new_wins, p1_new_losses) # Update player 2 stats p2_new_elo = int(p2[2] + p2_elo_change) p2_new_games = p2[3] + 1 p2_new_wins = p2[4] + 1 if team1_won else p2[4] p2_new_losses = p2[5] if team1_won else p2[5] + 1 update_player(p2[0], p2_new_elo, p2_new_games, p2_new_wins, p2_new_losses) # Update player 3 stats p3_new_elo = int(p3[2] + p3_elo_change) p3_new_games = p3[3] + 1 p3_new_wins = p3[4] + 1 if team2_won else p3[4] p3_new_losses = p3[5] if team2_won else p3[5] + 1 update_player(p3[0], p3_new_elo, p3_new_games, p3_new_wins, p3_new_losses) # Update player 4 stats p4_new_elo = int(p4[2] + p4_elo_change) p4_new_games = p4[3] + 1 p4_new_wins = p4[4] + 1 if team2_won else p4[4] p4_new_losses = p4[5] if team2_won else p4[5] + 1 update_player(p4[0], p4_new_elo, p4_new_games, p4_new_wins, p4_new_losses) match_count += 1 if match_count % 20 == 0: print(f"Processed {match_count}/{len(matches)} matches...") print(f"Processed {match_count} matches") # Display updated player rankings print("\n" + "=" * 60) print("Top 10 Players by ELO Rating:") print("-" * 60) conn = sqlite3.connect(DB_PATH) cursor = conn.cursor() cursor.execute(""" SELECT id, name, currentElo, gamesPlayed, wins, losses FROM players ORDER BY currentElo DESC LIMIT 10 """) top_players = cursor.fetchall() conn.close() for rank, (player_id, name, elo, games, wins, losses) in enumerate(top_players, 1): win_rate = (wins / games * 100) if games > 0 else 0 print( f"{rank:2}. {name:15} | ELO: {elo:4} | Games: {games:3} | W/L: {wins}/{losses} ({win_rate:.1f}%)" ) print("\n" + "=" * 60) print("Player statistics updated successfully!") print("Now run the application to see updated rankings.") if __name__ == "__main__": main()