Spaces:
Sleeping
Sleeping
File size: 7,849 Bytes
b0697fd e81469a b0697fd e81469a b0697fd e81469a b0697fd e81469a b0697fd | 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 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | """Dash callbacks for g-Harmony tournament."""
import uuid
import logging
import dash
from dash import ALL, Input, Output, State, ctx
from dash.exceptions import PreventUpdate
from src import elo
from src.hf_logging import log_query_event
from src.galaxy_profiles import TOTAL_PAIRS
from src.components import create_arena, create_leaderboard_rows, create_compact_showcase
logger = logging.getLogger(__name__)
def register_callbacks(app):
"""Register all Dash callbacks."""
# Initial load: populate the arena with the first champion vs challenger
@app.callback(
[
Output("arena-container", "children"),
Output("current-pair", "data"),
Output("current-champion", "data"),
Output("leaderboard-body", "children"),
Output("session-id", "data"),
],
Input("arena-container", "id"),
)
def initial_load(_):
session_id = uuid.uuid4().hex
# Select random starting champion
from src.galaxy_profiles import GALAXY_IDS
import random
champion_id = random.choice(GALAXY_IDS)
# Find first challenger
pair = elo.select_pair(set(), champion_id=champion_id)
arena = create_arena(pair[0], pair[1], champion_id=None) # No crown until first win
leaderboard = create_leaderboard_rows(elo.get_leaderboard())
return (
arena,
[pair[0], pair[1]],
champion_id,
leaderboard,
session_id,
)
# Card click: pick a winner, update ELO, load next pair
@app.callback(
[
Output("arena-container", "children", allow_duplicate=True),
Output("current-pair", "data", allow_duplicate=True),
Output("current-champion", "data", allow_duplicate=True),
Output("seen-pairs", "data", allow_duplicate=True),
Output("comparison-count", "data", allow_duplicate=True),
Output("leaderboard-body", "children", allow_duplicate=True),
],
[
Input("left-card-btn", "n_clicks"),
Input("right-card-btn", "n_clicks"),
],
[
State("current-pair", "data"),
State("current-champion", "data"),
State("seen-pairs", "data"),
State("comparison-count", "data"),
State("session-id", "data"),
],
prevent_initial_call=True,
)
def handle_card_click(left_clicks, right_clicks, current_pair, current_champion, seen_pairs, comp_count, session_id):
if not ctx.triggered_id:
raise PreventUpdate
if current_pair is None:
raise PreventUpdate
if seen_pairs is None:
seen_pairs = []
if comp_count is None:
comp_count = 0
# Determine winner based on which button was clicked
triggered = ctx.triggered_id
if triggered == "left-card-btn":
winner_side = "left"
elif triggered == "right-card-btn":
winner_side = "right"
else:
raise PreventUpdate
left_id = current_pair[0]
right_id = current_pair[1]
if winner_side == "left":
winner_id, loser_id = left_id, right_id
else:
winner_id, loser_id = right_id, left_id
# Record comparison
result = elo.record_comparison(winner_id, loser_id)
# Log to HF
log_query_event({
"log_type": "comparison",
"session_id": session_id,
"galaxy_left": left_id,
"galaxy_right": right_id,
"winner": winner_id,
"elo_left_before": result["winner_elo_before"] if winner_side == "left" else result["loser_elo_before"],
"elo_right_before": result["loser_elo_before"] if winner_side == "left" else result["winner_elo_before"],
"elo_left_after": result["winner_elo_after"] if winner_side == "left" else result["loser_elo_after"],
"elo_right_after": result["loser_elo_after"] if winner_side == "left" else result["winner_elo_after"],
})
# Update seen pairs and count
seen_pairs.append([left_id, right_id])
comp_count += 1
# Update champion: winner becomes/stays champion
new_champion = winner_id
# Select next pair with champion logic
seen_set = set()
for p in seen_pairs:
seen_set.add((p[0], p[1]))
seen_set.add((p[1], p[0]))
pair = elo.select_pair(seen_set, champion_id=new_champion)
if pair is None:
arena = create_arena(None, None, champion_id=new_champion)
current_pair_data = None
else:
arena = create_arena(pair[0], pair[1], champion_id=new_champion)
current_pair_data = [pair[0], pair[1]]
counter_text = "" # Remove comparison counter
leaderboard = create_leaderboard_rows(elo.get_leaderboard())
return (
arena,
current_pair_data,
new_champion,
seen_pairs,
comp_count,
leaderboard,
)
# Leaderboard toggle
@app.callback(
[
Output("leaderboard-body", "style"),
Output("leaderboard-arrow", "style"),
],
Input("leaderboard-toggle", "n_clicks"),
State("leaderboard-body", "style"),
prevent_initial_call=True,
)
def toggle_leaderboard(n_clicks, current_style):
if current_style and current_style.get("display") == "none":
return (
{
"display": "block",
"animation": "fadeSlideUp 0.3s ease",
"maxHeight": "52vh",
"overflowY": "auto",
"overscrollBehavior": "contain",
},
{"transition": "transform 0.3s", "fontSize": "0.65rem", "transform": "rotate(180deg)"},
)
return (
{"display": "none"},
{"transition": "transform 0.3s", "fontSize": "0.65rem", "transform": "rotate(0deg)"},
)
# Leaderboard row click: show selected galaxy preview in all-done card
@app.callback(
Output("leaderboard-showcase", "children"),
Input({"type": "leaderboard-row", "index": ALL}, "n_clicks"),
State("current-pair", "data"),
prevent_initial_call=True,
)
def show_leaderboard_selection(row_clicks, current_pair):
if current_pair is not None:
raise PreventUpdate
if not ctx.triggered_id or not isinstance(ctx.triggered_id, dict):
raise PreventUpdate
selected_id = ctx.triggered_id.get("index")
if not selected_id:
raise PreventUpdate
return create_compact_showcase(selected_id)
# Reset session
@app.callback(
[
Output("arena-container", "children", allow_duplicate=True),
Output("current-pair", "data", allow_duplicate=True),
Output("seen-pairs", "data", allow_duplicate=True),
Output("comparison-count", "data", allow_duplicate=True),
Output("comparison-counter", "children", allow_duplicate=True),
Output("leaderboard-body", "children", allow_duplicate=True),
],
Input("reset-session", "n_clicks"),
prevent_initial_call=True,
)
def reset_session(n_clicks):
if not n_clicks:
raise PreventUpdate
pair = elo.select_pair(set())
arena = create_arena(pair[0], pair[1])
leaderboard = create_leaderboard_rows(elo.get_leaderboard())
return (
arena,
[pair[0], pair[1]],
[],
0,
f"0 / {TOTAL_PAIRS} comparisons",
leaderboard,
)
|