Spaces:
Running
Running
Yuxuan-Zhang-Dexter
commited on
Commit
·
c998efb
1
Parent(s):
68f8427
update bar chart
Browse files- app.py +160 -7
- data_visualization.py +23 -5
app.py
CHANGED
|
@@ -118,17 +118,41 @@ def prepare_dataframe_for_display(df, for_game=None):
|
|
| 118 |
# Filter out models that didn't participate
|
| 119 |
display_df = display_df[~display_df[score_col].isna()]
|
| 120 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 121 |
return display_df
|
| 122 |
|
| 123 |
# Helper function to ensure leaderboard updates maintain consistent height
|
| 124 |
def update_df_with_height(df):
|
| 125 |
"""Update DataFrame with consistent height parameter."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
return gr.update(value=df,
|
| 127 |
show_row_numbers=True,
|
| 128 |
show_fullscreen_button=True,
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
|
|
|
| 132 |
|
| 133 |
def update_leaderboard(mario_overall, mario_details,
|
| 134 |
sokoban_overall, sokoban_details,
|
|
@@ -472,6 +496,32 @@ def create_timeline_slider():
|
|
| 472 |
|
| 473 |
def build_app():
|
| 474 |
with gr.Blocks(css="""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 475 |
.visualization-container .js-plotly-plot {
|
| 476 |
margin-left: auto !important;
|
| 477 |
margin-right: auto !important;
|
|
@@ -595,6 +645,53 @@ def build_app():
|
|
| 595 |
width: 100%;
|
| 596 |
border-collapse: separate;
|
| 597 |
border-spacing: 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 598 |
}
|
| 599 |
|
| 600 |
/* Make headers sticky */
|
|
@@ -604,13 +701,19 @@ def build_app():
|
|
| 604 |
background-color: #f8f9fa !important;
|
| 605 |
z-index: 10 !important;
|
| 606 |
font-weight: bold;
|
| 607 |
-
padding:
|
| 608 |
border-bottom: 2px solid #e9ecef;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 609 |
}
|
| 610 |
|
| 611 |
/* Simple cell styling */
|
| 612 |
.table-container td {
|
| 613 |
-
padding:
|
| 614 |
border-bottom: 1px solid #e9ecef;
|
| 615 |
}
|
| 616 |
|
|
@@ -630,6 +733,41 @@ def build_app():
|
|
| 630 |
overflow: visible !important;
|
| 631 |
margin-bottom: 20px;
|
| 632 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 633 |
""") as demo:
|
| 634 |
gr.Markdown("# 🎮 Game Arena: Gaming Agent 🎲")
|
| 635 |
|
|
@@ -719,6 +857,14 @@ def build_app():
|
|
| 719 |
# Format the DataFrame for display
|
| 720 |
initial_display_df = prepare_dataframe_for_display(initial_df)
|
| 721 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 722 |
# Create a standard DataFrame component with enhanced styling
|
| 723 |
with gr.Row():
|
| 724 |
leaderboard_df = gr.DataFrame(
|
|
@@ -731,7 +877,8 @@ def build_app():
|
|
| 731 |
show_fullscreen_button=True,
|
| 732 |
line_breaks=True,
|
| 733 |
max_height=700,
|
| 734 |
-
show_search="search"
|
|
|
|
| 735 |
)
|
| 736 |
|
| 737 |
# Add the score note below the table
|
|
@@ -815,4 +962,10 @@ def build_app():
|
|
| 815 |
if __name__ == "__main__":
|
| 816 |
demo_app = build_app()
|
| 817 |
# Add file serving configuration
|
| 818 |
-
demo_app.launch(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 118 |
# Filter out models that didn't participate
|
| 119 |
display_df = display_df[~display_df[score_col].isna()]
|
| 120 |
|
| 121 |
+
# Add line breaks to column headers
|
| 122 |
+
new_columns = {}
|
| 123 |
+
for col in display_df.columns:
|
| 124 |
+
if col.endswith(' Score'):
|
| 125 |
+
# Replace 'Game Name Score' with 'Game Name\nScore'
|
| 126 |
+
game_name = col.replace(' Score', '')
|
| 127 |
+
new_col = f"{game_name}\nScore"
|
| 128 |
+
new_columns[col] = new_col
|
| 129 |
+
elif col == 'Organization':
|
| 130 |
+
new_columns[col] = 'Organi-\nzation'
|
| 131 |
+
|
| 132 |
+
# Rename columns with new line breaks
|
| 133 |
+
if new_columns:
|
| 134 |
+
display_df = display_df.rename(columns=new_columns)
|
| 135 |
+
|
| 136 |
return display_df
|
| 137 |
|
| 138 |
# Helper function to ensure leaderboard updates maintain consistent height
|
| 139 |
def update_df_with_height(df):
|
| 140 |
"""Update DataFrame with consistent height parameter."""
|
| 141 |
+
# Create column widths array
|
| 142 |
+
col_widths = ["40px"] # Row number column width
|
| 143 |
+
col_widths.append("230px") # Player column - reduced by 20px
|
| 144 |
+
col_widths.append("120px") # Organization column
|
| 145 |
+
# Add game score columns
|
| 146 |
+
for _ in range(len(df.columns) - 2):
|
| 147 |
+
col_widths.append("120px")
|
| 148 |
+
|
| 149 |
return gr.update(value=df,
|
| 150 |
show_row_numbers=True,
|
| 151 |
show_fullscreen_button=True,
|
| 152 |
+
line_breaks=True,
|
| 153 |
+
show_search="search",
|
| 154 |
+
max_height=700,
|
| 155 |
+
column_widths=col_widths)
|
| 156 |
|
| 157 |
def update_leaderboard(mario_overall, mario_details,
|
| 158 |
sokoban_overall, sokoban_details,
|
|
|
|
| 496 |
|
| 497 |
def build_app():
|
| 498 |
with gr.Blocks(css="""
|
| 499 |
+
/* Fix for disappearing scrollbar */
|
| 500 |
+
html, body {
|
| 501 |
+
overflow-y: scroll !important;
|
| 502 |
+
height: 100% !important;
|
| 503 |
+
min-height: 100vh !important;
|
| 504 |
+
}
|
| 505 |
+
|
| 506 |
+
/* Prevent content from shrinking to center */
|
| 507 |
+
.gradio-container {
|
| 508 |
+
width: 100% !important;
|
| 509 |
+
max-width: 1200px !important;
|
| 510 |
+
margin-left: auto !important;
|
| 511 |
+
margin-right: auto !important;
|
| 512 |
+
min-height: 100vh !important;
|
| 513 |
+
}
|
| 514 |
+
|
| 515 |
+
/* Force table to maintain width */
|
| 516 |
+
.table-container {
|
| 517 |
+
width: 100% !important;
|
| 518 |
+
min-width: 100% !important;
|
| 519 |
+
}
|
| 520 |
+
|
| 521 |
+
.table-container table {
|
| 522 |
+
width: 100% !important;
|
| 523 |
+
}
|
| 524 |
+
|
| 525 |
.visualization-container .js-plotly-plot {
|
| 526 |
margin-left: auto !important;
|
| 527 |
margin-right: auto !important;
|
|
|
|
| 645 |
width: 100%;
|
| 646 |
border-collapse: separate;
|
| 647 |
border-spacing: 0;
|
| 648 |
+
table-layout: fixed !important;
|
| 649 |
+
}
|
| 650 |
+
|
| 651 |
+
/* Targeting row number column directly */
|
| 652 |
+
table th[role="cell"][aria-colindex="1"],
|
| 653 |
+
table td[role="cell"][aria-colindex="1"],
|
| 654 |
+
table col[data-col-index="0"],
|
| 655 |
+
.table-container tr > *:first-child[aria-colindex="1"],
|
| 656 |
+
th[scope="row"],
|
| 657 |
+
th[aria-sort],
|
| 658 |
+
td[data-index],
|
| 659 |
+
th[data-row-header] {
|
| 660 |
+
width: 30px !important;
|
| 661 |
+
min-width: 30px !important;
|
| 662 |
+
max-width: 30px !important;
|
| 663 |
+
padding: 2px 4px !important;
|
| 664 |
+
font-size: 0.85em !important;
|
| 665 |
+
text-align: center !important;
|
| 666 |
+
overflow: hidden !important;
|
| 667 |
+
text-overflow: ellipsis !important;
|
| 668 |
+
white-space: nowrap !important;
|
| 669 |
+
}
|
| 670 |
+
|
| 671 |
+
/* Column width customization - adjust for row numbers being first column */
|
| 672 |
+
.table-container th:nth-child(2),
|
| 673 |
+
.table-container td:nth-child(2) {
|
| 674 |
+
width: 230px !important;
|
| 675 |
+
min-width: 200px !important;
|
| 676 |
+
max-width: 280px !important;
|
| 677 |
+
padding-left: 8px !important;
|
| 678 |
+
padding-right: 8px !important;
|
| 679 |
+
}
|
| 680 |
+
|
| 681 |
+
.table-container th:nth-child(3),
|
| 682 |
+
.table-container td:nth-child(3) {
|
| 683 |
+
width: 120px !important;
|
| 684 |
+
min-width: 100px !important;
|
| 685 |
+
max-width: 140px !important;
|
| 686 |
+
}
|
| 687 |
+
|
| 688 |
+
/* Game score columns */
|
| 689 |
+
.table-container th:nth-child(n+4),
|
| 690 |
+
.table-container td:nth-child(n+4) {
|
| 691 |
+
width: 120px !important;
|
| 692 |
+
min-width: 100px !important;
|
| 693 |
+
max-width: 140px !important;
|
| 694 |
+
text-align: center !important;
|
| 695 |
}
|
| 696 |
|
| 697 |
/* Make headers sticky */
|
|
|
|
| 701 |
background-color: #f8f9fa !important;
|
| 702 |
z-index: 10 !important;
|
| 703 |
font-weight: bold;
|
| 704 |
+
padding: 16px 10px !important;
|
| 705 |
border-bottom: 2px solid #e9ecef;
|
| 706 |
+
white-space: pre-wrap !important;
|
| 707 |
+
word-wrap: break-word !important;
|
| 708 |
+
line-height: 1.2 !important;
|
| 709 |
+
height: auto !important;
|
| 710 |
+
min-height: 60px !important;
|
| 711 |
+
vertical-align: middle !important;
|
| 712 |
}
|
| 713 |
|
| 714 |
/* Simple cell styling */
|
| 715 |
.table-container td {
|
| 716 |
+
padding: 8px 8px;
|
| 717 |
border-bottom: 1px solid #e9ecef;
|
| 718 |
}
|
| 719 |
|
|
|
|
| 733 |
overflow: visible !important;
|
| 734 |
margin-bottom: 20px;
|
| 735 |
}
|
| 736 |
+
|
| 737 |
+
/* Additional specific selectors for row numbers */
|
| 738 |
+
.gradio-dataframe thead tr th[id="0"],
|
| 739 |
+
.gradio-dataframe tbody tr td:nth-child(1),
|
| 740 |
+
[data-testid="dataframe"] thead tr th[id="0"],
|
| 741 |
+
[data-testid="dataframe"] tbody tr td:nth-child(1),
|
| 742 |
+
.svelte-1gfkn6j thead tr th:first-child,
|
| 743 |
+
.svelte-1gfkn6j tbody tr td:first-child {
|
| 744 |
+
width: 40px !important;
|
| 745 |
+
min-width: 40px !important;
|
| 746 |
+
max-width: 40px !important;
|
| 747 |
+
padding: 4px !important;
|
| 748 |
+
text-align: center !important;
|
| 749 |
+
font-size: 0.85em !important;
|
| 750 |
+
}
|
| 751 |
+
|
| 752 |
+
/* Fix overflow issues */
|
| 753 |
+
.table-container {
|
| 754 |
+
overflow: auto !important;
|
| 755 |
+
max-height: 700px !important;
|
| 756 |
+
}
|
| 757 |
+
|
| 758 |
+
body, html {
|
| 759 |
+
overflow-x: hidden !important;
|
| 760 |
+
overflow-y: auto !important;
|
| 761 |
+
height: 100% !important;
|
| 762 |
+
width: 100% !important;
|
| 763 |
+
margin: 0 !important;
|
| 764 |
+
padding: 0 !important;
|
| 765 |
+
}
|
| 766 |
+
|
| 767 |
+
.gradio-container {
|
| 768 |
+
overflow: visible !important;
|
| 769 |
+
max-height: none !important;
|
| 770 |
+
}
|
| 771 |
""") as demo:
|
| 772 |
gr.Markdown("# 🎮 Game Arena: Gaming Agent 🎲")
|
| 773 |
|
|
|
|
| 857 |
# Format the DataFrame for display
|
| 858 |
initial_display_df = prepare_dataframe_for_display(initial_df)
|
| 859 |
|
| 860 |
+
# Custom column widths including row numbers
|
| 861 |
+
col_widths = ["40px"] # Row number column width
|
| 862 |
+
col_widths.append("230px") # Player column - reduced by 20px
|
| 863 |
+
col_widths.append("120px") # Organization column
|
| 864 |
+
# Add game score columns
|
| 865 |
+
for _ in range(len(initial_display_df.columns) - 2):
|
| 866 |
+
col_widths.append("120px")
|
| 867 |
+
|
| 868 |
# Create a standard DataFrame component with enhanced styling
|
| 869 |
with gr.Row():
|
| 870 |
leaderboard_df = gr.DataFrame(
|
|
|
|
| 877 |
show_fullscreen_button=True,
|
| 878 |
line_breaks=True,
|
| 879 |
max_height=700,
|
| 880 |
+
show_search="search",
|
| 881 |
+
column_widths=col_widths
|
| 882 |
)
|
| 883 |
|
| 884 |
# Add the score note below the table
|
|
|
|
| 962 |
if __name__ == "__main__":
|
| 963 |
demo_app = build_app()
|
| 964 |
# Add file serving configuration
|
| 965 |
+
demo_app.launch(
|
| 966 |
+
debug=True,
|
| 967 |
+
show_error=True,
|
| 968 |
+
share=True,
|
| 969 |
+
height="100%",
|
| 970 |
+
width="100%"
|
| 971 |
+
)
|
data_visualization.py
CHANGED
|
@@ -203,7 +203,21 @@ def create_group_bar_chart(df):
|
|
| 203 |
|
| 204 |
# Build consistent game order (X-axis)
|
| 205 |
sorted_games = [game for game in GAME_ORDER if f"norm_{game} Score" in df.columns]
|
| 206 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 207 |
# Group models by prefix, then sort alphabetically
|
| 208 |
model_groups = {}
|
| 209 |
for player in df["Player"].unique():
|
|
@@ -233,13 +247,13 @@ def create_group_bar_chart(df):
|
|
| 233 |
|
| 234 |
if not has_data:
|
| 235 |
continue
|
| 236 |
-
|
| 237 |
fig.add_trace(go.Bar(
|
| 238 |
name=simplify_model_name(player),
|
| 239 |
-
x=sorted_games,
|
| 240 |
y=y_vals,
|
| 241 |
marker_color=MODEL_COLORS.get(player, '#808080'),
|
| 242 |
-
hovertemplate="
|
| 243 |
))
|
| 244 |
|
| 245 |
fig.update_layout(
|
|
@@ -252,9 +266,13 @@ def create_group_bar_chart(df):
|
|
| 252 |
yaxis_title="Normalized Score",
|
| 253 |
xaxis=dict(
|
| 254 |
categoryorder='array',
|
| 255 |
-
categoryarray=sorted_games
|
|
|
|
| 256 |
),
|
| 257 |
barmode='group',
|
|
|
|
|
|
|
|
|
|
| 258 |
legend=dict(
|
| 259 |
font=dict(size=9),
|
| 260 |
itemsizing='trace',
|
|
|
|
| 203 |
|
| 204 |
# Build consistent game order (X-axis)
|
| 205 |
sorted_games = [game for game in GAME_ORDER if f"norm_{game} Score" in df.columns]
|
| 206 |
+
|
| 207 |
+
# Format game names with line breaks
|
| 208 |
+
formatted_games = []
|
| 209 |
+
for game in sorted_games:
|
| 210 |
+
if len(game) > 10 and ' ' in game:
|
| 211 |
+
parts = game.split(' ')
|
| 212 |
+
midpoint = len(parts) // 2
|
| 213 |
+
formatted_name = ' '.join(parts[:midpoint]) + '<br>' + ' '.join(parts[midpoint:])
|
| 214 |
+
formatted_games.append(formatted_name)
|
| 215 |
+
else:
|
| 216 |
+
formatted_games.append(game)
|
| 217 |
+
|
| 218 |
+
# Create mapping from original to formatted names
|
| 219 |
+
game_display_map = dict(zip(sorted_games, formatted_games))
|
| 220 |
+
|
| 221 |
# Group models by prefix, then sort alphabetically
|
| 222 |
model_groups = {}
|
| 223 |
for player in df["Player"].unique():
|
|
|
|
| 247 |
|
| 248 |
if not has_data:
|
| 249 |
continue
|
| 250 |
+
|
| 251 |
fig.add_trace(go.Bar(
|
| 252 |
name=simplify_model_name(player),
|
| 253 |
+
x=[game_display_map[game] for game in sorted_games],
|
| 254 |
y=y_vals,
|
| 255 |
marker_color=MODEL_COLORS.get(player, '#808080'),
|
| 256 |
+
hovertemplate="<b>%{fullData.name}</b><br>Score: %{y:.1f}<extra></extra>"
|
| 257 |
))
|
| 258 |
|
| 259 |
fig.update_layout(
|
|
|
|
| 266 |
yaxis_title="Normalized Score",
|
| 267 |
xaxis=dict(
|
| 268 |
categoryorder='array',
|
| 269 |
+
categoryarray=[game_display_map[g] for g in sorted_games],
|
| 270 |
+
tickangle=0 # Keep text horizontal since we're using line breaks
|
| 271 |
),
|
| 272 |
barmode='group',
|
| 273 |
+
bargap=0.2, # Gap between game categories
|
| 274 |
+
bargroupgap=0.05, # Gap between bars in a group
|
| 275 |
+
uniformtext=dict(mode='hide', minsize=8), # Hide text that doesn't fit
|
| 276 |
legend=dict(
|
| 277 |
font=dict(size=9),
|
| 278 |
itemsizing='trace',
|