""" Create animated bar chart race showing leaderboard evolution over time """ import pandas as pd import numpy as np from typing import List, Tuple import json import os def prepare_animation_data(history_df: pd.DataFrame, top_n: int = 15) -> dict: """ Prepare data for D3.js bar chart race animation. Args: history_df: DataFrame with columns: date, model, rating, rank top_n: Number of top models to show at each time point Returns: Dictionary with animation data """ # Convert date column to Timestamp to support ISO date strings and date objects if history_df is not None and len(history_df) > 0 and 'date' in history_df.columns: history_df = history_df.copy() history_df['date'] = pd.to_datetime(history_df['date']) # Get all unique dates dates = sorted(history_df['date'].unique()) if len(dates) == 0: return { 'frames': [], 'total_frames': 0, 'top_n': top_n, 'start_date': None, 'end_date': None, } # For each date, get top N models frames = [] for date in dates: date_data = history_df[history_df['date'] == date].nlargest(top_n, 'rating') frame = { 'date': date.strftime('%Y-%m-%d'), 'timestamp': int(date.timestamp()), 'models': [] } for rank, row in enumerate(date_data.itertuples(), 1): frame['models'].append({ 'rank': rank, 'name': row.model, 'rating': float(row.rating), 'matches': int(row.matches), 'wins': float(row.wins) }) frames.append(frame) animation_data = { 'frames': frames, 'total_frames': len(frames), 'top_n': top_n, 'start_date': dates[0].strftime('%Y-%m-%d'), 'end_date': dates[-1].strftime('%Y-%m-%d') } return animation_data def generate_html_animation(animation_data: dict, output_path: str = "leaderboard_animation.html"): """ Generate standalone HTML file with D3.js bar chart race animation. Args: animation_data: Dictionary from prepare_animation_data output_path: Path to save HTML file """ html_template = """