ouhenio's picture
Update app.py
eacf514 verified
import gradio as gr
import argilla as rg
import pandas as pd
import os
import time
from collections import defaultdict
from fastapi import FastAPI
from functools import lru_cache
client = rg.Argilla(
api_url=os.getenv("ARGILLA_API_URL", ""),
api_key=os.getenv("ARGILLA_API_KEY", "")
)
countries = {
"Argentina": {
"iso": "ARG",
"emoji": "🇦🇷"
},
"Bolivia": {
"iso": "BOL",
"emoji": "🇧🇴"
},
"Chile": {
"iso": "CHL",
"emoji": "🇨🇱"
},
"Colombia": {
"iso": "COL",
"emoji": "🇨🇴"
},
"Costa Rica": {
"iso": "CRI",
"emoji": "🇨🇷"
},
"Cuba": {
"iso": "CUB",
"emoji": "🇨🇺"
},
"Ecuador": {
"iso": "ECU",
"emoji": "🇪🇨"
},
"El Salvador": {
"iso": "SLV",
"emoji": "🇸🇻"
},
"España": {
"iso": "ESP",
"emoji": "🇪🇸"
},
"Guatemala": {
"iso": "GTM",
"emoji": "🇬🇹"
},
"Honduras": {
"iso": "HND",
"emoji": "🇭🇳"
},
"México": {
"iso": "MEX",
"emoji": "🇲🇽"
},
"Nicaragua": {
"iso": "NIC",
"emoji": "🇳🇮"
},
"Panamá": {
"iso": "PAN",
"emoji": "🇵🇦"
},
"Paraguay": {
"iso": "PRY",
"emoji": "🇵🇾"
},
"Perú": {
"iso": "PER",
"emoji": "🇵🇪"
},
"Puerto Rico": {
"iso": "PRI",
"emoji": "🇵🇷"
},
"República Dominicana": {
"iso": "DOM",
"emoji": "🇩🇴"
},
"Uruguay": {
"iso": "URY",
"emoji": "🇺🇾"
},
"Venezuela": {
"iso": "VEN",
"emoji": "🇻🇪"
}
}
def get_blend_es_data():
data = []
for country in countries.keys():
iso = countries[country]["iso"]
emoji = countries[country]["emoji"]
dataset_name = f"{emoji} {country} - {iso} - Responder"
try:
print(f"Processing dataset: {dataset_name}")
dataset = client.datasets(dataset_name)
records = list(dataset.records(with_responses=True))
dataset_contributions = defaultdict(int)
user_mapping = {}
for record in records:
record_dict = record.to_dict()
if "answer_1" in record_dict["responses"]:
for answer in record_dict["responses"]["answer_1"]:
if answer["user_id"]:
user_id = answer["user_id"]
dataset_contributions[user_id] += 1
if user_id not in user_mapping:
try:
user = client.users(id=user_id)
user_mapping[user_id] = user.username
except Exception as e:
print(f"Error getting username for {user_id}: {e}")
user_mapping[user_id] = f"User-{user_id[:8]}"
for user_id, count in dataset_contributions.items():
username = user_mapping.get(user_id, f"User-{user_id[:8]}")
data.append({
"source": "blend-es",
"username": username,
"count": count
})
except Exception as e:
print(f"Error processing dataset {dataset_name}: {e}")
return data
def get_include_data():
data = []
try:
if os.path.exists("include.csv"):
include_df = pd.read_csv("include.csv")
if "Nombre en Discord / username" in include_df.columns and "Número de preguntas / number of questions" in include_df.columns:
discord_users = defaultdict(int)
for _, row in include_df.iterrows():
username = row["Nombre en Discord / username"][1:]
questions = row["Número de preguntas / number of questions"]
if pd.notna(username) and pd.notna(questions):
discord_users[username.lower()] += int(questions)
for username, count in discord_users.items():
data.append({
"source": "include",
"username": username,
"count": count
})
except Exception as e:
print(f"Error loading include.csv: {e}")
return data
def get_mail_to_username_mapping():
mail_to_discord = {}
try:
if os.path.exists("mail_to_username.csv"):
mapping_df = pd.read_csv("mail_to_username.csv")
if "gmail" in mapping_df.columns and "discord" in mapping_df.columns:
for _, row in mapping_df.iterrows():
mail = row["gmail"]
discord = row["discord"]
if pd.notna(mail) and pd.notna(discord):
mail_to_discord[mail.lower()] = discord.lower()
except Exception as e:
print(f"Error loading mail_to_username.csv: {e}")
return mail_to_discord
def get_estereotipos_data():
data = []
mail_to_discord = get_mail_to_username_mapping()
try:
if os.path.exists("token_id_counts.csv"):
counts_df = pd.read_csv("token_id_counts.csv")
if "token_id" in counts_df.columns and "count" in counts_df.columns:
mail_counts = defaultdict(int)
for _, row in counts_df.iterrows():
mail = row["token_id"]
count = row["count"]
if pd.notna(mail) and pd.notna(count):
mail_counts[mail.lower()] += int(count)
for mail, count in mail_counts.items():
username = mail_to_discord.get(mail.lower(), "")
if not username:
username = mail.split('@')[0] if '@' in mail else mail
data.append({
"source": "estereotipos",
"username": username,
"count": count
})
except Exception as e:
print(f"Error loading estereotipos data: {e}")
return data
def get_arena_data():
data = []
mail_to_discord = get_mail_to_username_mapping()
try:
if os.path.exists("arena.json"):
import json
with open("arena.json", "r", encoding="utf-8") as f:
arena_data = json.load(f)
mail_counts = defaultdict(int)
for country, conversations in arena_data.items():
for conversation in conversations:
if "username" in conversation:
mail = conversation["username"]
if mail:
mail_counts[mail.lower()] += 1
for mail, count in mail_counts.items():
username = mail_to_discord.get(mail.lower(), "")
if not username:
username = mail.split('@')[0] if '@' in mail else mail
data.append({
"source": "arena",
"username": username,
"count": count
})
except Exception as e:
print(f"Error loading arena data: {e}")
return data
@lru_cache(maxsize=32)
def get_user_contributions_cached(cache_buster: int):
return consolidate_all_data()
def consolidate_all_data():
all_data = []
all_data.extend(get_blend_es_data())
all_data.extend(get_include_data())
all_data.extend(get_estereotipos_data())
all_data.extend(get_arena_data())
user_contributions = defaultdict(lambda: {"username": "", "blend_es": 0, "include": 0, "estereotipos": 0, "arena": 0})
for item in all_data:
source = item["source"]
username = item["username"]
count = item["count"]
user_key = username.lower()
if not user_contributions[user_key]["username"]:
user_contributions[user_key]["username"] = username
if source == "blend-es":
user_contributions[user_key]["blend_es"] += count
elif source == "include":
user_contributions[user_key]["include"] += count
elif source == "estereotipos":
user_contributions[user_key]["estereotipos"] += count
elif source == "arena":
user_contributions[user_key]["arena"] += count
rows = []
for _, data in user_contributions.items():
total = data["blend_es"] + data["include"] + data["estereotipos"] + data["arena"]
row = {
"Username": data["username"],
"Total": total,
"Blend-es": data["blend_es"],
"INCLUDE": data["include"],
"Estereotipos": data["estereotipos"],
"Arena": data["arena"]
}
rows.append(row)
df = pd.DataFrame(rows)
if not df.empty:
df = df.sort_values("Total", ascending=False)
return df
app = FastAPI()
last_update_time = 0
cached_data = None
def create_leaderboard_ui():
global cached_data, last_update_time
current_time = time.time()
if cached_data is not None and current_time - last_update_time < 300:
df = cached_data
else:
cache_buster = int(current_time)
df = get_user_contributions_cached(cache_buster)
cached_data = df
last_update_time = current_time
if not df.empty:
df = df.reset_index(drop=True)
df.index = df.index + 1
df = df.rename_axis("Rank")
df = df.reset_index()
df_html = df.to_html(classes="leaderboard-table", border=0, index=False)
styled_html = f"""
<div style="margin: 20px 0;">
<p>Última Actualización: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(last_update_time))}</p>
<style>
.leaderboard-table {{
width: 100%;
border-collapse: collapse;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
border-radius: 8px;
overflow: hidden;
}}
.leaderboard-table th {{
background-color: #1a1a2e;
color: white;
font-weight: bold;
text-align: left;
padding: 14px;
border-bottom: 2px solid #16213e;
}}
.leaderboard-table td {{
padding: 12px 14px;
border-bottom: 1px solid #333;
background-color: #222;
color: #fff;
}}
.leaderboard-table tr:hover td {{
background-color: #2a2a3a;
}}
.leaderboard-table tr:nth-child(1) td:first-child {{
background-color: #ffd700;
color: #333;
font-weight: bold;
text-align: center;
border-right: 1px solid #333;
}}
.leaderboard-table tr:nth-child(2) td:first-child {{
background-color: #c0c0c0;
color: #333;
font-weight: bold;
text-align: center;
border-right: 1px solid #333;
}}
.leaderboard-table tr:nth-child(3) td:first-child {{
background-color: #cd7f32;
color: #333;
font-weight: bold;
text-align: center;
border-right: 1px solid #333;
}}
.leaderboard-table tr:nth-child(1) td:nth-child(2) {{
font-weight: bold;
color: #ffd700;
}}
.leaderboard-table tr:nth-child(2) td:nth-child(2) {{
font-weight: bold;
color: #c0c0c0;
}}
.leaderboard-table tr:nth-child(3) td:nth-child(2) {{
font-weight: bold;
color: #cd7f32;
}}
</style>
{df_html}
</div>
"""
return styled_html
def refresh_data():
global cached_data, last_update_time
cached_data = None
last_update_time = 0
return create_leaderboard_ui()
with gr.Blocks(theme=gr.themes.Default()) as demo:
with gr.Column(scale=1):
gr.Markdown("""# 🏆 Hackaton Leaderboard""")
leaderboard_html = gr.HTML(create_leaderboard_ui)
refresh_btn = gr.Button("🔄 Actualizar Datos", variant="primary")
refresh_btn.click(fn=refresh_data, outputs=leaderboard_html)
gr.mount_gradio_app(app, demo, path="/")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860)