leaderboard-hackaton-2025 / calculate_team_scores.py
mariagrandury's picture
add rules to calculate team scores
8a9ef5d
import os
import pandas as pd
from dotenv import load_dotenv
from calculate_personal_scores import get_discord_username
load_dotenv()
# Constants
DATA_DIR = "data"
PARTICIPANTS_CSV = os.path.join(DATA_DIR, "participants.csv")
EQUIPOS_CSV = os.path.join(DATA_DIR, "equipos.csv")
LEADERBOARD_PERSONAL_CSV = "leaderboard_personal.csv"
LEADERBOARD_EQUIPOS_CSV = "leaderboard_equipos.csv"
# Column mappings for teams info
TEAM_COLUMNS = {
"team_name": "Nombre del equipo",
"email_1": "Email 1",
"email_2": "Email 2",
"email_3": "Email 3",
"email_4": "Email 4",
"email_5": "Email 5",
}
# INCLUDE: Cada 100 preguntas validadas extraídas por equipo = 0.5 ptos (máx 1 pto)
# Estereotipos: Cada 10 estereotipos validados por equipo = 0.1 ptos (máx 1 pto)
# BLEND: Cada 50 preguntas por equipo = 0.5 ptos (máx 2 ptos)
# Arena: Cada 50 prompts por equipo = 0.5 ptos (máx 2 ptos)
POINTS = {
"INCLUDE": {"points": 0.5, "max_points": 1, "questions": 100},
"ESTEREOTIPOS": {"points": 0.1, "max_points": 1, "questions": 10},
"BLEND": {"points": 0.5, "max_points": 2, "questions": 50},
"ARENA": {"points": 0.5, "max_points": 2, "questions": 50},
}
def calculate_challenge_points(total_score, challenge_name):
"""Calculate points for a specific challenge based on the POINTS rules."""
if challenge_name not in POINTS:
return 0
challenge_rules = POINTS[challenge_name]
points_per_unit = challenge_rules["points"]
max_points = challenge_rules["max_points"]
questions_per_unit = challenge_rules["questions"]
calculated_points = (total_score / questions_per_unit) * points_per_unit
final_points = min(calculated_points, max_points)
return round(final_points, 2)
def get_team_leaderboard(personal_leaderboard_df):
"""Calculate team leaderboard based on personal scores."""
if not os.path.exists(EQUIPOS_CSV):
return pd.DataFrame()
try:
teams_df = pd.read_csv(EQUIPOS_CSV)
team_leaderboard = []
for _, team_row in teams_df.iterrows():
team_name = team_row.get(TEAM_COLUMNS["team_name"], "")
if not team_name:
continue
# Get team member emails
team_emails = []
for i in range(1, 6):
email_col = TEAM_COLUMNS[f"email_{i}"]
email = team_row.get(email_col, "")
if pd.notna(email) and email.strip():
team_emails.append(email.lower())
if not team_emails:
continue
# Map emails to Discord usernames and get scores
discord_usernames = []
team_scores = {"arena": 0, "blend_es": 0, "estereotipos": 0, "include": 0}
for email in team_emails:
# Get Discord username from email
discord_username = get_discord_username(email)
discord_usernames.append(discord_username)
# Find this user in the personal leaderboard
user_scores = personal_leaderboard_df[
personal_leaderboard_df["Username"].str.lower()
== discord_username.lower()
]
if not user_scores.empty:
team_scores["arena"] += user_scores.iloc[0]["Arena"]
team_scores["blend_es"] += user_scores.iloc[0]["Blend-ES"]
team_scores["estereotipos"] += user_scores.iloc[0]["Estereotipos"]
team_scores["include"] += user_scores.iloc[0]["INCLUDE"]
# Pad Discord usernames list to 5 elements
while len(discord_usernames) < 5:
discord_usernames.append("")
# Calculate points for each challenge
ptos_arena = calculate_challenge_points(team_scores["arena"], "ARENA")
ptos_blend_es = calculate_challenge_points(team_scores["blend_es"], "BLEND")
ptos_estereotipos = calculate_challenge_points(
team_scores["estereotipos"], "ESTEREOTIPOS"
)
ptos_include = calculate_challenge_points(team_scores["include"], "INCLUDE")
# Calculate total points
ptos_total = ptos_arena + ptos_blend_es + ptos_estereotipos + ptos_include
# Create team row
team_row_data = {
"team_name": team_name,
"discord_1": discord_usernames[0],
"discord_2": discord_usernames[1],
"discord_3": discord_usernames[2],
"discord_4": discord_usernames[3],
"discord_5": discord_usernames[4],
"total_arena": team_scores["arena"],
"ptos_arena": ptos_arena,
"total_blend_es": team_scores["blend_es"],
"ptos_blend_es": ptos_blend_es,
"total_estereotipos": team_scores["estereotipos"],
"ptos_estereotipos": ptos_estereotipos,
"total_include": team_scores["include"],
"ptos_include": ptos_include,
"ptos_total": ptos_total,
}
team_leaderboard.append(team_row_data)
# Create DataFrame and sort by total points (ptos_total) instead of just arena
if team_leaderboard:
team_df = pd.DataFrame(team_leaderboard)
team_df.sort_values("ptos_total", ascending=False, inplace=True)
return team_df
else:
return pd.DataFrame()
except Exception as e:
print(f"Error calculating team leaderboard: {e}")
return pd.DataFrame()
def calculate_team_scores():
personal_leaderboard_df = pd.read_csv(LEADERBOARD_PERSONAL_CSV)
team_leaderboard_df = get_team_leaderboard(personal_leaderboard_df)
team_leaderboard_df.to_csv(LEADERBOARD_EQUIPOS_CSV, index=False, encoding="utf-8")
print("Team scores calculated and saved successfully!")
print(f"Generated leaderboard with {len(team_leaderboard_df)} teams")
if __name__ == "__main__":
calculate_team_scores()