Spaces:
Running
Running
| custom_css = """ | |
| /* Info icon for column tooltips */ | |
| .info-icon { | |
| color: #b0b0b0; | |
| font-size: 15px; | |
| margin-left: 4px; | |
| vertical-align: middle; | |
| font-family: Arial, sans-serif; | |
| font-style: normal; | |
| font-weight: bold; | |
| user-select: none; | |
| } | |
| .info-icon:hover { | |
| color: #888; | |
| } | |
| /* Model Name link hover effect */ | |
| .pretty-leaderboard-table a:hover { | |
| text-decoration: underline; | |
| color: #1098F7; | |
| cursor: pointer; | |
| } | |
| /* INTRO FEATURE CARDS (for about page) */ | |
| .intro-feature-row { | |
| display: flex; | |
| flex-wrap: wrap; | |
| justify-content: center; | |
| gap: 24px; | |
| margin: 18px 0 !important; | |
| } | |
| .intro-feature-box { | |
| background: linear-gradient(135deg, #f8fafc 60%, #e3e6f3 100%); | |
| border-radius: 18px; | |
| box-shadow: 0 4px 16px rgba(44,62,80,0.08); | |
| padding: 32px 28px; | |
| width: 380px; | |
| min-width: 260px; | |
| max-width: 420px; | |
| text-align: left; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: flex-start; | |
| transition: box-shadow 0.2s; | |
| } | |
| .intro-feature-title { | |
| font-weight: 900; | |
| font-size: 1.45em; | |
| margin-bottom: 12px; | |
| color: #23244a; | |
| } | |
| .intro-feature-desc { | |
| font-size: 1.18em; | |
| color: #444; | |
| margin-bottom: 7px; | |
| } | |
| .intro-feature-icon { | |
| font-size: 2.3em; | |
| margin-bottom: 16px; | |
| color: #1098F7; | |
| } | |
| .intro-feature-box:hover { | |
| box-shadow: 0 0 24px #a5a1ff55, 0 4px 16px rgba(0,0,0,0.18); | |
| transform: translateY(-4px) scale(1.025); | |
| transition: box-shadow 0.2s, transform 0.2s; | |
| cursor: default; | |
| } | |
| @media (prefers-color-scheme: dark) { | |
| .intro-feature-box { | |
| background: linear-gradient(135deg, #23244a 0%, #2a1859 100%) !important; | |
| color: #f5f6f7 !important; | |
| } | |
| .intro-feature-title, .intro-feature-desc { | |
| color: #f5f6f7 !important; | |
| } | |
| } | |
| /* Dataset Sample Button (below feature cards) */ | |
| .intro-dataset-btn { | |
| display: inline-block; | |
| background: #1098F7; | |
| color: #fff !important; | |
| border: none; | |
| border-radius: 12px; | |
| font-weight: 700; | |
| font-size: 1.18em; | |
| padding: 16px 36px; | |
| margin: 32px auto 0 auto; | |
| text-align: center; | |
| text-decoration: none; | |
| box-shadow: 0 2px 8px #1098f733; | |
| transition: background 0.18s, color 0.18s, box-shadow 0.18s; | |
| cursor: pointer; | |
| outline: none; | |
| } | |
| .intro-dataset-btn:hover, .intro-dataset-btn:focus { | |
| background: #0a6dc2; | |
| color: #fff !important; | |
| box-shadow: 0 4px 16px #1098f755; | |
| text-decoration: none; | |
| } | |
| @media (prefers-color-scheme: dark) { | |
| .intro-dataset-btn { | |
| background: #1a4b7a; | |
| color: #fff !important; | |
| } | |
| .intro-dataset-btn:hover, .intro-dataset-btn:focus { | |
| background: #1098F7; | |
| color: #fff !important; | |
| } | |
| } | |
| .radar-chart, .plot-container { | |
| display: block; | |
| margin-left: auto; | |
| margin-right: auto; | |
| width: fit-content; | |
| max-width: 100%; | |
| } | |
| /* Ensure injected HTML/Markdown blocks are transparent and text is visible in all color schemes */ | |
| .gr-html, .gr-markdown, .gr-html * { | |
| background: transparent !important; | |
| color: inherit !important; | |
| } | |
| .gr-html div, .gr-html body, .gr-markdown div, .gr-markdown body { | |
| background: transparent !important; | |
| color: inherit !important; | |
| } | |
| @media (prefers-color-scheme: dark) { | |
| .gr-html, .gr-markdown, .gr-html *, .gr-markdown * { | |
| color: #f5f6f7 !important; | |
| } | |
| } | |
| @media (prefers-color-scheme: light) { | |
| .gr-html, .gr-markdown, .gr-html *, .gr-markdown * { | |
| color: #23244a !important; | |
| } | |
| } | |
| /* Custom radio styles for category selector */ | |
| .cat-btn-radio label { | |
| border-radius: 18px !important; | |
| border: 1.5px solid #d1d5db !important; | |
| background: #f8fafc !important; | |
| color: #222 !important; | |
| font-weight: 600 !important; | |
| cursor: pointer !important; | |
| padding: 8px 20px !important; | |
| box-shadow: 0 2px 8px #e5e7eb88 !important; | |
| margin: 0 !important; | |
| font-size: 1.08rem !important; | |
| transition: background 0.2s, color 0.2s, box-shadow 0.2s, border 0.2s !important; | |
| display: inline-block !important; | |
| } | |
| .cat-btn-radio input[type="radio"] { | |
| display: none !important; | |
| } | |
| .cat-btn-radio input[type="radio"]:checked + label, | |
| .cat-btn-radio label.selected { | |
| background: #1098F7 !important; | |
| color: #fff !important; | |
| border: 1.5px solid #1098F7 !important; | |
| box-shadow: 0 4px 16px #1098f755, 0 2px 8px #e5e7eb88 !important; | |
| } | |
| .cat-btn-radio label:hover { | |
| border: 1.5px solid #1098F7 !important; | |
| box-shadow: 0 4px 16px #1098f733, 0 2px 8px #e5e7eb88 !important; | |
| } | |
| /* Gradio tab content: Space-themed background */ | |
| .gr-tabitem { | |
| background: linear-gradient(135deg, #e3e6f3 60%, #f5f6fa 100%); | |
| background-image: | |
| radial-gradient(rgba(255,255,255,0.10) 1.2px, transparent 1.2px), | |
| radial-gradient(rgba(255,255,255,0.06) 1px, transparent 1px); | |
| background-size: 40px 40px, 80px 80px; | |
| background-position: 0 0, 20px 20px; | |
| } | |
| @media (prefers-color-scheme: dark) { | |
| .gr-tabitem { | |
| background: linear-gradient(135deg, #181c3a 0%, #2a1859 100%) !important; | |
| background-image: | |
| radial-gradient(rgba(255,255,255,0.10) 1.2px, transparent 1.2px), | |
| radial-gradient(rgba(255,255,255,0.06) 1px, transparent 1px); | |
| background-size: 40px 40px, 80px 80px; | |
| background-position: 0 0, 20px 20px; | |
| } | |
| } | |
| @media (prefers-color-scheme: light) { | |
| .gr-tabitem { | |
| background: linear-gradient(135deg, #e3e6f3 60%, #f5f6fa 100%) !important; | |
| background-image: | |
| radial-gradient(rgba(255,255,255,0.10) 1.2px, transparent 1.2px), | |
| radial-gradient(rgba(255,255,255,0.06) 1px, transparent 1px); | |
| background-size: 40px 40px, 80px 80px; | |
| background-position: 0 0, 20px 20px; | |
| } | |
| h3 a, h3 a:visited { | |
| color: #222 !important; | |
| } | |
| } | |
| /* Sort arrow/button styles */ | |
| .sort-arrow, .sort-btn { | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| background: #23244a; | |
| color: #ffd700 !important; /* Always yellow */ | |
| border: 1.5px solid #ffd700; /* Gold border */ | |
| border-radius: 6px; | |
| font-size: 15px; | |
| font-weight: 700; | |
| margin-left: 6px; | |
| margin-right: 2px; | |
| padding: 2px 8px 2px 6px; | |
| cursor: pointer; | |
| transition: background 0.2s, color 0.2s, border 0.2s; | |
| min-width: 28px; | |
| min-height: 28px; | |
| outline: none; | |
| } | |
| .sort-arrow.active, .sort-btn.active { | |
| color: #ffd700 !important; /* Gold */ | |
| border-color: #ffd700; | |
| background: #1a237e; | |
| } | |
| .sort-arrow:hover, .sort-btn:hover { | |
| background: #ffd700; | |
| color: #23244a !important; | |
| border-color: #ffd700; | |
| } | |
| .sort-arrow svg, .sort-btn svg { | |
| margin-left: 2px; | |
| margin-right: 0; | |
| width: 1em; | |
| height: 1em; | |
| vertical-align: middle; | |
| } | |
| /* Enhanced leaderboard table styles */ | |
| .pretty-leaderboard-table { | |
| width: 100%; | |
| border-collapse: separate; | |
| border-spacing: 0; | |
| background: rgba(30, 34, 54, 0.98); | |
| /* border-radius: 16px; 테이블 자체에는 radius 제거 */ | |
| box-shadow: 0 4px 24px 0 rgba(16, 152, 247, 0.10), 0 1.5px 6px 0 rgba(227, 84, 84, 0.08); | |
| margin-bottom: 24px; | |
| } | |
| .pretty-leaderboard-table thead { | |
| border-radius: 16px 16px 0 0; | |
| overflow: hidden; | |
| background: #23244a; | |
| } | |
| /* Sticky first and second columns */ | |
| /* Sticky first and second columns - header(th) */ | |
| .pretty-leaderboard-table th:nth-child(1) { | |
| position: sticky; | |
| left: 0; | |
| top: 0; | |
| z-index: 5; | |
| background: #23244a; | |
| min-width: 60px; | |
| max-width: 60px; | |
| width: 60px; | |
| } | |
| .pretty-leaderboard-table th:nth-child(2) { | |
| position: sticky; | |
| left: 60px; | |
| top: 0; | |
| z-index: 5; | |
| background: #23244a; | |
| min-width: 220px; | |
| max-width: 400px; | |
| width: 220px; | |
| } | |
| /* Sticky first and second columns - body(td) with CSS variable for background */ | |
| .pretty-leaderboard-table td:nth-child(1) { | |
| position: sticky; | |
| left: 0; | |
| z-index: 4; | |
| background: var(--row-bg) !important; | |
| min-width: 60px; | |
| max-width: 60px; | |
| width: 60px; | |
| } | |
| .pretty-leaderboard-table td:nth-child(2) { | |
| position: sticky; | |
| left: 60px; | |
| z-index: 4; | |
| background: var(--row-bg) !important; | |
| min-width: 220px; | |
| max-width: 400px; | |
| width: 220px; | |
| } | |
| /* Set --row-bg variable for each row type */ | |
| .pretty-leaderboard-table tr { | |
| --row-bg: #1e2236; | |
| } | |
| .pretty-leaderboard-table tr:nth-child(even) { | |
| --row-bg: #23253a; | |
| } | |
| .pretty-leaderboard-table tr:hover { | |
| --row-bg: #2066a0; | |
| } | |
| .pretty-leaderboard-table th { | |
| z-index: 4; | |
| } | |
| .pretty-leaderboard-table th, .pretty-leaderboard-table td { | |
| padding: 12px 16px; | |
| text-align: left; | |
| border-bottom: 1px solid #23244a; | |
| font-size: 16px; | |
| } | |
| .pretty-leaderboard-table th { | |
| background: #23244a; | |
| color: #fff; | |
| font-weight: 800; | |
| letter-spacing: 0.5px; | |
| border-bottom: 2px solid #1098F7; | |
| text-shadow: 0 1px 8px #0006; | |
| transition: background 0.2s, color 0.2s; | |
| position: sticky; | |
| top: 0; | |
| z-index: 2; | |
| border-radius: 0 !important; | |
| } | |
| .pretty-leaderboard-table th:hover, .pretty-leaderboard-table th:focus { | |
| background: #273a8a; | |
| color: #fff; | |
| } | |
| .pretty-leaderboard-table td { | |
| color: #F5F6F7; | |
| vertical-align: middle; | |
| background: var(--row-bg); | |
| } | |
| .pretty-leaderboard-table tr:last-child td { | |
| border-bottom: none; | |
| } | |
| /* th/td의 border-radius는 모두 제거, 둥근 효과는 thead에만 */ | |
| /* Enhanced score bar styles */ | |
| .score-bar { | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| width: 100%; | |
| } | |
| .score-bar-track { | |
| flex-grow: 1; | |
| height: 10px; | |
| background: rgba(245, 246, 247, 0.12); | |
| border-radius: 5px; | |
| overflow: hidden; | |
| max-width: 220px; | |
| box-shadow: 0 1px 4px 0 rgba(16, 152, 247, 0.10); | |
| } | |
| .score-bar-fill { | |
| height: 100%; | |
| background: linear-gradient(90deg, #a259f7 0%, #6d28d9 100%); | |
| border-radius: 5px; | |
| transition: width 0.3s cubic-bezier(0.4,0,0.2,1); | |
| } | |
| .score-bar-value { | |
| font-family: 'SF Mono', monospace; | |
| font-weight: 600; | |
| color: #F5F6F7; | |
| min-width: 60px; | |
| font-size: 14px; | |
| } | |
| body { | |
| min-height: 100vh; | |
| } | |
| /* 전체 배경색은 브라우저 기본값을 따름. gradio-container도 마찬가지로 별도 배경 없음 */ | |
| .markdown-text { | |
| font-size: 16px !important; | |
| } | |
| #citation-button span { | |
| font-size: 16px !important; | |
| } | |
| #citation-button textarea { | |
| font-size: 16px !important; | |
| } | |
| #citation-button > label > button { | |
| margin: 6px; | |
| transform: scale(1.3); | |
| } | |
| .leaderboard-table-container { | |
| margin-top: 15px; | |
| /* Space-themed background */ | |
| background: linear-gradient(135deg, #e3e6f3 60%, #f5f6fa 100%); | |
| position: relative; | |
| background-image: | |
| radial-gradient(rgba(255,255,255,0.15) 1.2px, transparent 1.2px), | |
| radial-gradient(rgba(255,255,255,0.10) 1px, transparent 1px); | |
| background-size: 40px 40px, 80px 80px; | |
| background-position: 0 0, 20px 20px; | |
| } | |
| @media (prefers-color-scheme: dark) { | |
| .leaderboard-table-container { | |
| background: linear-gradient(135deg, #1a237e 0%, #311b92 100%) !important; | |
| background-image: | |
| radial-gradient(rgba(255,255,255,0.15) 1.2px, transparent 1.2px), | |
| radial-gradient(rgba(255,255,255,0.10) 1px, transparent 1px); | |
| background-size: 40px 40px, 80px 80px; | |
| background-position: 0 0, 20px 20px; | |
| } | |
| } | |
| @media (prefers-color-scheme: light) { | |
| .leaderboard-table-container { | |
| background: linear-gradient(135deg, #e3e6f3 60%, #f5f6fa 100%) !important; | |
| background-image: | |
| radial-gradient(rgba(255,255,255,0.15) 1.2px, transparent 1.2px), | |
| radial-gradient(rgba(255,255,255,0.10) 1px, transparent 1px); | |
| background-size: 40px 40px, 80px 80px; | |
| background-position: 0 0, 20px 20px; | |
| } | |
| } | |
| /* Limit the width of the first column so that names don't expand too much */ | |
| .leaderboard-table-container td:nth-child(2), | |
| .leaderboard-table-container th:nth-child(2) { | |
| max-width: 400px; | |
| overflow: auto; | |
| white-space: nowrap; | |
| } | |
| .tab-buttons button { | |
| font-size: 20px; | |
| } | |
| /* Model type and think badge styles */ | |
| .badge { | |
| display: inline-block; | |
| border-radius: 12px; | |
| padding: 2px 10px; | |
| font-size: 0.85em; | |
| font-weight: 700; | |
| margin-left: 6px; | |
| box-shadow: 0 1px 4px rgba(0,0,0,0.10); | |
| vertical-align: middle; | |
| } | |
| .badge-think-on { | |
| background: #A7C7E7; | |
| color: #234567; | |
| border: 1.5px solid #A7C7E7; | |
| } | |
| .badge-think-off { | |
| background: #E0E0E0; | |
| color: #555; | |
| border: 1.5px solid #E0E0E0; | |
| } | |
| /* Model Type badge styles */ | |
| .badge-modeltype-instruct { | |
| background: #B2F2E9; | |
| color: #22796A; | |
| border: 1.5px solid #B2F2E9; | |
| } | |
| .badge-modeltype-think { | |
| background: #D6C8F7; | |
| color: #5B4B8A; | |
| border: 1.5px solid #D6C8F7; | |
| } | |
| .badge-modeltype-hybrid { | |
| background: #FFE0B2; | |
| color: #A67C52; | |
| border: 1.5px solid #FFE0B2; | |
| } | |
| /* Type badge Open/Proprietary styles */ | |
| .badge-type-open { | |
| background: #A8E6A3; | |
| color: #225522; | |
| border: 1.5px solid #A8E6A3; | |
| } | |
| .badge-type-proprietary { | |
| background: #F7B2B7; | |
| color: #7A2F34; | |
| border: 1.5px solid #F7B2B7; | |
| } | |
| /* Sort button styles */ | |
| .sort-btn { | |
| background: #23244a; | |
| color: #F5F6F7; | |
| border: 1px solid #1098F7; | |
| border-radius: 6px; | |
| font-size: 13px; | |
| font-weight: 700; | |
| margin-left: 4px; | |
| margin-right: 2px; | |
| padding: 2px 7px; | |
| cursor: pointer; | |
| transition: background 0.2s, color 0.2s; | |
| } | |
| .sort-btn:hover { | |
| background: #1098F7; | |
| color: #fff; | |
| } | |
| /* Custom CheckboxGroup and Dropdown styles for table theme */ | |
| .gr-checkbox-group, .gr-checkbox, .gr-checkbox-group label, .gr-checkbox input[type="checkbox"] { | |
| background: #23244a !important; | |
| color: #F5F6F7 !important; | |
| border: 1.5px solid #1098F7 !important; | |
| border-radius: 6px !important; | |
| } | |
| .gr-checkbox input[type="checkbox"]:checked { | |
| background: #1a237e !important; | |
| border-color: #ffd700 !important; | |
| } | |
| .gr-dropdown, .gr-input, select { | |
| background: #23244a !important; | |
| color: #F5F6F7 !important; | |
| border: 1.5px solid #1098F7 !important; | |
| border-radius: 6px !important; | |
| } | |
| /* Custom style for radar chart model selector's selected tags (only the tag area, not the dropdown list) */ | |
| .custom-dropdown .multiselect__tag { | |
| background: #1098F7 !important; | |
| color: #fff !important; | |
| border: 1.5px solid #1098F7 !important; | |
| box-shadow: 0 4px 16px #1098f755, 0 2px 8px #e5e7eb88 !important; | |
| border-radius: 18px !important; | |
| font-weight: 600 !important; | |
| padding: 8px 20px !important; | |
| margin: 2px 4px !important; | |
| font-size: 1.08rem !important; | |
| display: inline-block !important; | |
| transition: background 0.2s, color 0.2s, box-shadow 0.2s, border 0.2s !important; | |
| } | |
| .gr-dropdown:focus, .gr-input:focus, select:focus { | |
| border-color: #ffd700 !important; | |
| outline: none !important; | |
| } | |
| @media (prefers-color-scheme: dark) { | |
| .category-box, | |
| .space-info-box, | |
| .pretty-leaderboard-table, | |
| .dark-container { | |
| background: linear-gradient(135deg, #23244a 0%, #2a1859 100%) !important; | |
| color: #f5f6f7 !important; | |
| } | |
| .space-info-box, .space-info-box * { | |
| color: #f5f6f7 !important; | |
| } | |
| h3 a, h3 a:visited { | |
| color: #f5f6f7 !important; | |
| } | |
| } | |
| """ | |
| # requirements_textbox and adaptor_class_textbox scroll/height control | |
| custom_css += """ | |
| #requirements-textbox textarea { | |
| overflow-y: auto !important; | |
| resize: vertical; | |
| height: 480px; | |
| max-height: 480px; | |
| } | |
| #yml-textbox textarea { | |
| overflow-y: auto !important; | |
| resize: vertical; | |
| height: 240px; | |
| max-height: 240px; | |
| } | |
| /* No border textbox style for file upload status */ | |
| .no-border-textbox textarea { | |
| border: none !important; | |
| box-shadow: none !important; | |
| background: transparent !important; | |
| padding: 0 !important; | |
| margin: 0 !important; | |
| outline: none !important; | |
| resize: none !important; | |
| overflow: hidden !important; | |
| } | |
| .no-border-textbox .wrap { | |
| background: transparent !important; | |
| border: none !important; | |
| box-shadow: none !important; | |
| padding: 0 !important; | |
| margin: 0 !important; | |
| outline: none !important; | |
| } | |
| .no-border-textbox .prose { | |
| background: transparent !important; | |
| border: none !important; | |
| box-shadow: none !important; | |
| padding: 0 !important; | |
| margin: 0 !important; | |
| } | |
| .no-border-textbox label { | |
| display: none !important; | |
| } | |
| .no-border-textbox .gr-textbox { | |
| border: none !important; | |
| box-shadow: none !important; | |
| background: transparent !important; | |
| padding: 0 !important; | |
| margin: 0 !important; | |
| } | |
| .no-border-textbox .gr-textbox > div { | |
| border: none !important; | |
| box-shadow: none !important; | |
| background: transparent !important; | |
| padding: 0 !important; | |
| margin: 0 !important; | |
| } | |
| .no-border-textbox .gr-textbox > div > div { | |
| border: none !important; | |
| box-shadow: none !important; | |
| background: transparent !important; | |
| padding: 0 !important; | |
| margin: 0 !important; | |
| } | |
| /* Ensure model name tooltips are hoverable */ | |
| .pretty-leaderboard-table td span[title] { | |
| pointer-events: auto; | |
| } | |
| /* Tall file upload container to match lines=25 textbox height */ | |
| .tall-file-upload .file-upload-container { | |
| min-height: 283px !important; | |
| height: 283px !important; | |
| } | |
| .tall-file-upload .gr-file { | |
| min-height: 283px !important; | |
| height: 283px !important; | |
| } | |
| """ | |
| def get_rank_badge(rank: int) -> str: | |
| """ | |
| Returns emoji for 1st, 2nd, 3rd, otherwise just the number. | |
| """ | |
| if rank == 1: | |
| return '<span style="font-size:1.5em;" title="1st">🥇</span>' | |
| elif rank == 2: | |
| return '<span style="font-size:1.5em;" title="2nd">🥈</span>' | |
| elif rank == 3: | |
| return '<span style="font-size:1.5em;" title="3rd">🥉</span>' | |
| else: | |
| return f'<span style="font-size:1.2em;color:#a1a1aa;font-weight:500;">{rank}</span>' | |
| def get_score_gauge(score: float) -> str: | |
| """ | |
| Returns HTML for an overall score gauge (progress bar style). | |
| Robustly normalizes score to 0~100% regardless of input range (0~1 or 0~100). | |
| """ | |
| # Handle None/NaN | |
| try: | |
| score = float(score) | |
| except (TypeError, ValueError): | |
| score = 0.0 | |
| # Normalize: if score is 0~1, treat as normalized and scale to 0~100 | |
| if score is None or score != score: # NaN check | |
| percent = 0.0 | |
| display_score = 0.0 | |
| elif score <= 1.0: | |
| percent = score * 100 | |
| display_score = percent | |
| else: | |
| percent = score | |
| display_score = score | |
| # For scores above 95, adjust to 98~100% so the bar appears almost full | |
| if percent >= 95: | |
| percent = 98 + (min(percent, 100) - 95) * 0.4 # 95=98%, 100=100% | |
| # Clip to 0~100 | |
| percent = min(max(percent, 0), 100) | |
| display_score = min(max(display_score, 0), 100) | |
| return f''' | |
| <div class="score-bar" style="margin: 0.5em 0;"> | |
| <div class="score-bar-track"> | |
| <div class="score-bar-fill" style="width: {percent}%;"></div> | |
| </div> | |
| <span class="score-bar-value">{display_score:.3f}</span> | |
| </div> | |
| ''' | |
| from src.display.formatting import get_score_stars | |
| def get_leaderboard_table_html(df, key="Category") -> str: | |
| """ | |
| Returns HTML for a pretty leaderboard table using badge and gauge. | |
| Displays all columns in df, applying format_leaderboard_cell to each cell as needed. | |
| key: "Category" or "Language" (default: "Category") | |
| """ | |
| import pandas as pd | |
| from src.display.formatting import get_score_stars, get_type_badge, get_model_type_badge, get_output_badge, format_leaderboard_cell, get_display_model_name | |
| # Build table header | |
| html = ['<table class="pretty-leaderboard-table">'] | |
| html.append("<thead><tr>") | |
| for col in df.columns: | |
| html.append(f"<th>{col}</th>") | |
| html.append("</tr></thead>") | |
| html.append("<tbody>") | |
| for idx, row in df.iterrows(): | |
| html.append("<tr>") | |
| for col in df.columns: | |
| cell = row[col] | |
| # Special cell handling | |
| if col == "Rank": | |
| badge = get_rank_badge(cell) | |
| html.append(f"<td>{badge}</td>") | |
| elif col == "Model Name": | |
| # Highlight top 1~3 | |
| rank = row.get("Rank", None) | |
| highlight_style = "" | |
| if rank == 1 or rank == "1": | |
| highlight_style = "color: #ffd700; font-weight: bold; text-shadow: 0 0 4px #fff2;" | |
| elif rank == 2 or rank == "2": | |
| highlight_style = "color: #b0b0b0; font-weight: bold;" | |
| elif rank == 3 or rank == "3": | |
| highlight_style = "color: #cd7f32; font-weight: bold;" | |
| else: | |
| highlight_style = "color: #fff; font-weight: 600;" | |
| display_name = get_display_model_name(str(cell)) | |
| link_value = row["Link"] if "Link" in row and pd.notna(row["Link"]) and str(row["Link"]).strip() != "" else None | |
| if link_value: | |
| clickable_name = f'<a href="{link_value}" target="_blank" style="color:inherit;">{display_name}</a>' | |
| else: | |
| clickable_name = display_name | |
| html.append(f'<td><span style="{highlight_style}">{clickable_name}</span></td>') | |
| elif col == "Model Type": | |
| html.append(f"<td>{get_model_type_badge(row.get('Model Type', ''))}</td>") | |
| elif col == "Type": | |
| html.append(f"<td>{get_type_badge(row.get('Type', ''))}</td>") | |
| elif col == "Think": | |
| html.append(f"<td>{get_output_badge(row.get('Think', ''))}</td>") | |
| elif col == "Overall": | |
| # 별점 | |
| try: | |
| unique_id = row.get("Model Name", None) | |
| unique_id = unique_id.replace(" ", "_").replace("-", "_").replace("(", "_").replace(")", "_") | |
| cell_html = get_score_stars(float(cell), unique_id=unique_id) | |
| except Exception: | |
| cell_html = str(cell) | |
| html.append(f"<td>{cell_html}</td>") | |
| else: | |
| html.append(f"<td>{format_leaderboard_cell(cell, col, key)}</td>") | |
| html.append("</tr>") | |
| html.append("</tbody></table>") | |
| table_html = "\n".join(html) | |
| # Wrap in scrollable div for sticky header | |
| return f'<div class="leaderboard-table-container" style="max-height:900px;overflow-y:auto;">{table_html}</div>' | |