import pandas as pd from typing import List, Optional from .data_loader import DataLoader class Leaderboard: def __init__(self, data_loader: DataLoader): self.data_loader = data_loader def update_leaderboard(self, metric: str = "Average", top_k: int = 25, model_filter: str = "", open_source_filter: str = "All", year_filter: str = "All", category_filter: str = "All", sort_mode: str = "Auto", selected_metrics: Optional[List[str]] = None) -> pd.DataFrame: df = self.data_loader.filter_data(model_filter, open_source_filter, year_filter, category_filter) if df.empty: return pd.DataFrame() if sort_mode == "Auto": ascending = False elif sort_mode == "Ascending (low → high)": ascending = True else: ascending = False if metric in df.columns: df = df.sort_values(by=metric, ascending=ascending) df = df.head(top_k).reset_index(drop=True) df.insert(0, "Rank", range(1, len(df) + 1)) base_cols = ["Rank", "Model", "Category"] if selected_metrics is None: selected_metrics = ["Average"] display_cols = base_cols.copy() for m in selected_metrics: if m in df.columns and m not in display_cols: display_cols.append(m) # Add optional link columns if they exist link_cols = [] if "Paper" in df.columns: link_cols.append("Paper") if "Code" in df.columns: link_cols.append("Code") display_cols.extend(link_cols) result_df = df[display_cols].copy() # Format numeric values for col in result_df.columns: if col not in ["Rank", "Model", "Category", "Paper", "Code", "Open Source", "Year"]: result_df[col] = result_df[col].apply( lambda x: f"{x:.4f}" if pd.notna(x) and isinstance(x, (int, float)) else "-" ) # Do NOT generate HTML links; keep as plain text # (If you want links, you can add them here, but for sorting they are fine as text) return result_df