Spaces:
Running
Running
File size: 4,612 Bytes
5b07ff1 d48eef6 38c6a34 5b07ff1 d48eef6 5b07ff1 e012a04 5b07ff1 e012a04 5b07ff1 e012a04 5b07ff1 e012a04 5b07ff1 e012a04 5b07ff1 d48eef6 5b07ff1 9678fdb |
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 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
import csv
import os
from datetime import datetime
from ..config import FIGHTS_CSV_PATH, FIGHTERS_CSV_PATH
# --- ELO Configuration ---
INITIAL_ELO = 1500
K_FACTOR = 40
# --- End Configuration ---
def calculate_expected_score(rating1, rating2):
"""Calculates the expected score for player 1 against player 2."""
return 1 / (1 + 10 ** ((rating2 - rating1) / 400))
def update_elo(winner_elo, loser_elo):
"""Calculates the new ELO ratings for a win/loss scenario."""
expected_win = calculate_expected_score(winner_elo, loser_elo)
change = K_FACTOR * (1 - expected_win)
return winner_elo + change, loser_elo - change
def update_elo_draw(elo1, elo2):
"""Calculates the new ELO ratings for a draw."""
expected1 = calculate_expected_score(elo1, elo2)
change1 = K_FACTOR * (0.5 - expected1)
expected2 = calculate_expected_score(elo2, elo1)
change2 = K_FACTOR * (0.5 - expected2)
return elo1 + change1, elo2 + change2
def process_fights_for_elo(fights_data=FIGHTS_CSV_PATH):
"""
Processes fights chronologically to calculate ELO scores.
Accepts either a CSV file path or a pre-loaded list of fights.
"""
fights = []
if isinstance(fights_data, str):
# If a string is passed, treat it as a file path
if not os.path.exists(fights_data):
print(f"Error: Fights data file not found at '{fights_data}'.")
return None
with open(fights_data, 'r', encoding='utf-8') as f:
fights = list(csv.DictReader(f))
elif isinstance(fights_data, list):
# If a list is passed, use it directly
fights = fights_data
else:
print(f"Error: Invalid data type passed to process_fights_for_elo: {type(fights_data)}")
return None
# Sort fights by date to process them in chronological order.
# This is crucial if loading from a file and a good safeguard if a list is passed.
try:
fights.sort(key=lambda x: datetime.strptime(x['event_date'], '%B %d, %Y'))
except (ValueError, KeyError) as e:
print(f"Error sorting fights by date: {e}")
return None
elos = {}
for fight in fights:
fighter1 = fight.get('fighter_1')
fighter2 = fight.get('fighter_2')
winner = fight.get('winner')
# Initialize ELO for new fighters
if fighter1 not in elos: elos[fighter1] = INITIAL_ELO
if fighter2 not in elos: elos[fighter2] = INITIAL_ELO
elo1 = elos[fighter1]
elo2 = elos[fighter2]
if winner == fighter1:
elos[fighter1], elos[fighter2] = update_elo(elo1, elo2)
elif winner == fighter2:
elos[fighter2], elos[fighter1] = update_elo(elo2, elo1)
elif winner == "Draw":
elos[fighter1], elos[fighter2] = update_elo_draw(elo1, elo2)
# NC (No Contest) fights do not affect ELO
return elos
def add_elo_to_fighters_csv(elos, fighters_csv_path=FIGHTERS_CSV_PATH):
"""
Adds the final ELO scores as a new column to the fighters CSV data.
"""
if not elos:
print("No ELO data to process. Aborting.")
return
if not os.path.exists(fighters_csv_path):
print(f"Error: Fighters data file not found at '{fighters_csv_path}'. Cannot add ELO column.")
return
rows = []
with open(fighters_csv_path, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
headers = reader.fieldnames
# Ensure 'elo' column is added if not present
if 'elo' not in headers:
headers.append('elo')
rows = list(reader)
for row in rows:
full_name = f"{row.get('first_name', '')} {row.get('last_name', '')}".strip()
row['elo'] = round(elos.get(full_name, INITIAL_ELO))
with open(fighters_csv_path, 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=headers)
writer.writeheader()
writer.writerows(rows)
print(f"Successfully updated '{fighters_csv_path}' with ELO ratings.")
def main():
print("--- Starting ELO Calculation ---")
final_elos = process_fights_for_elo()
if final_elos:
add_elo_to_fighters_csv(final_elos)
# Sort fighters by ELO and print the top 10
sorted_fighters = sorted(final_elos.items(), key=lambda item: item[1], reverse=True)
print("\n--- Top 10 Fighters by ELO Rating ---")
for i, (fighter, elo) in enumerate(sorted_fighters[:10]):
print(f"{i+1}. {fighter}: {round(elo)}")
print("------------------------------------") |