Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>BenchHub Leaderboards β reproducible, apples-to-apples ML benchmarks</title> | |
| <meta name="description" content="Reproducible ML leaderboards β LLM (MMLU, HellaSwag, ARC, GSM8K), vision, and audio. Every model scored on the same data with the same metric in a sandbox, not self-reported. Browse standings and submit your model free."> | |
| <meta name="keywords" content="ML leaderboard, model evaluation, reproducible benchmark, MMLU leaderboard, HellaSwag, ARC-Challenge, GSM8K, LLM benchmark, apples-to-apples, object detection, depth estimation, stereo, speech recognition"> | |
| <link rel="canonical" href="https://runbenchhub-leaderboards.static.hf.space/"> | |
| <meta property="og:type" content="website"> | |
| <meta property="og:title" content="BenchHub Leaderboards β reproducible, apples-to-apples ML benchmarks"> | |
| <meta property="og:description" content="Reproducible LLM, vision & audio leaderboards. Same data, same metric, sandboxed β not self-reported. Submit your model free."> | |
| <meta property="og:url" content="https://runbenchhub-leaderboards.static.hf.space/"> | |
| <meta name="twitter:card" content="summary_large_image"> | |
| <meta name="twitter:title" content="BenchHub Leaderboards β reproducible, apples-to-apples ML benchmarks"> | |
| <meta name="twitter:description" content="Reproducible LLM, vision & audio leaderboards. Same data, same metric, sandboxed β not self-reported. Submit free."> | |
| <meta name="theme-color" content="#7c3aed"> | |
| <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>π</text></svg>"> | |
| <script type="application/ld+json"> | |
| {"@context":"https://schema.org","@type":"WebSite","name":"BenchHub Leaderboards","url":"https://runbenchhub.com","description":"Reproducible, apples-to-apples ML benchmarking β LLM, vision, and audio leaderboards scored on the same data with the same metric in a sandbox.","keywords":"reproducible ML leaderboard, LLM benchmark, MMLU, HellaSwag, ARC, GSM8K, model evaluation, apples-to-apples","about":[{"@type":"Thing","name":"Large language model evaluation"},{"@type":"Thing","name":"Computer vision benchmarks"},{"@type":"Thing","name":"Reproducible model evaluation"}]} | |
| </script> | |
| <style> | |
| :root{ | |
| --violet:#7c3aed; --violet-2:#a78bfa; | |
| --bg:#fcf9f4; --card:#fffdf8; --card-2:#f5efe2; --border:#e8dfc8; | |
| --text:#3a2614; --text-2:#6b5b43; --muted:#9a8c73; | |
| --shadow:0 4px 18px rgba(60,38,20,.08); | |
| --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; | |
| } | |
| body.dark{ | |
| --bg:#0f1117; --card:#171a21; --card-2:#1e222b; --border:#2b313c; | |
| --text:#e7e3da; --text-2:#a7adba; --muted:#7c8595; | |
| --shadow:0 4px 22px rgba(0,0,0,.45); | |
| } | |
| *{box-sizing:border-box} | |
| body{margin:0;background:var(--bg);color:var(--text); | |
| font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif; | |
| line-height:1.45;-webkit-font-smoothing:antialiased;transition:background .2s,color .2s;} | |
| a{color:var(--violet);text-decoration:none} | |
| a:hover{text-decoration:underline} | |
| .wrap{max-width:1140px;margin:0 auto;padding:0 18px 60px} | |
| /* Top bar */ | |
| .topbar{display:flex;align-items:center;gap:14px;flex-wrap:wrap; | |
| padding:16px 18px;max-width:1140px;margin:0 auto;} | |
| .brand{font-weight:800;font-size:1.15rem;letter-spacing:-.01em;display:flex;align-items:center;gap:8px} | |
| .brand .dot{color:var(--violet)} | |
| .topbar .spacer{flex:1} | |
| .btn{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--border); | |
| background:var(--card);color:var(--text);border-radius:9px;padding:7px 13px; | |
| font-size:.82rem;font-weight:600;cursor:pointer;transition:all .15s;white-space:nowrap} | |
| .btn:hover{border-color:var(--violet);color:var(--violet);text-decoration:none;transform:translateY(-1px)} | |
| .btn-primary{background:var(--violet);color:#fff;border-color:var(--violet)} | |
| .btn-primary:hover{background:#6d28d9;color:#fff;border-color:#6d28d9} | |
| /* Hero */ | |
| .hero{text-align:center;padding:26px 0 8px} | |
| .hero h1{font-size:2rem;margin:.1em 0 .15em;letter-spacing:-.02em} | |
| .hero p{color:var(--text-2);max-width:680px;margin:.2em auto 1.1em;font-size:1.02rem} | |
| .stats{display:flex;justify-content:center;gap:12px;flex-wrap:wrap;margin:10px 0 4px} | |
| .stat{background:var(--card);border:1px solid var(--border);border-top:3px solid var(--violet); | |
| border-radius:12px;padding:12px 20px;min-width:120px;box-shadow:var(--shadow)} | |
| .stat .n{font-size:1.7rem;font-weight:800;font-family:var(--mono);color:var(--violet);line-height:1} | |
| .stat .l{font-size:.72rem;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin-top:5px} | |
| /* Trust strip */ | |
| .trust{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin:18px 0 4px} | |
| .trust-item{display:flex;gap:10px;align-items:flex-start;background:var(--card);border:1px solid var(--border); | |
| border-radius:12px;padding:13px 15px;font-size:.84rem;color:var(--text-2);line-height:1.35} | |
| .trust-item span{font-size:1.25rem;line-height:1} | |
| .trust-item b{color:var(--text)} | |
| @media(max-width:720px){.trust{grid-template-columns:1fr}} | |
| /* Controls */ | |
| .controls{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin:22px 0 10px} | |
| .subcontrols{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin:0 0 16px; | |
| padding-left:2px;animation:fade .15s ease} | |
| @keyframes fade{from{opacity:0;transform:translateY(-3px)}to{opacity:1}} | |
| .sublabel{font-size:.76rem;color:var(--muted);font-weight:700;text-transform:uppercase;letter-spacing:.04em} | |
| .subpills .pill{font-size:.76rem;padding:5px 11px;background:var(--card-2)} | |
| .subpills .pill.on{background:var(--violet);color:#fff} | |
| #search{flex:1;min-width:220px;border:1px solid var(--border);background:var(--card);color:var(--text); | |
| border-radius:10px;padding:10px 14px;font-size:.95rem} | |
| #search:focus{outline:none;border-color:var(--violet);box-shadow:0 0 0 3px rgba(124,58,237,.15)} | |
| .pills{display:flex;gap:6px;flex-wrap:wrap} | |
| .pill{border:1px solid var(--border);background:var(--card);color:var(--text-2);border-radius:999px; | |
| padding:6px 13px;font-size:.8rem;font-weight:600;cursor:pointer;transition:all .12s} | |
| .pill:hover{border-color:var(--violet-2)} | |
| .pill.on{background:var(--violet);color:#fff;border-color:var(--violet)} | |
| /* Card grid */ | |
| .grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(290px,1fr));gap:14px} | |
| .card{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:15px 16px; | |
| box-shadow:var(--shadow);cursor:pointer;transition:transform .14s,border-color .14s; | |
| display:flex;flex-direction:column;gap:9px} | |
| .card:hover{transform:translateY(-3px);border-color:var(--violet)} | |
| .card .cat{font-size:.7rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em; | |
| color:var(--violet);background:rgba(124,58,237,.1);align-self:flex-start;border-radius:6px;padding:2px 8px} | |
| .card h3{margin:0;font-size:1.04rem;letter-spacing:-.01em;word-break:break-word} | |
| .card .lead{font-size:.85rem;color:var(--text-2);display:flex;align-items:center;gap:6px;min-height:1.2em} | |
| .card .lead b{color:var(--text);font-weight:700} | |
| .card .lead .score{font-family:var(--mono);color:#16a34a;font-weight:700} | |
| .card .meta{display:flex;justify-content:space-between;align-items:center;margin-top:auto;padding-top:6px; | |
| border-top:1px solid var(--border);font-size:.78rem;color:var(--muted)} | |
| .card .meta .subs b{color:var(--text);font-family:var(--mono)} | |
| .card .go{color:var(--violet);font-weight:700} | |
| /* Drill-down: area section headers + sub-category cards */ | |
| .cat-head{font-size:.78rem;text-transform:uppercase;letter-spacing:.05em;color:var(--text-2); | |
| font-weight:800;margin:24px 0 11px;display:flex;align-items:center;gap:8px} | |
| .cat-head:first-child{margin-top:4px} | |
| .cat-head .n{color:var(--muted);font-weight:600} | |
| .grid + .cat-head{margin-top:26px} | |
| .catcard h3{font-size:1.1rem} | |
| #backBar{margin:4px 0 16px} | |
| #backBar .crumb{margin-left:12px;color:var(--text-2);font-weight:700;font-size:.92rem} | |
| #backBar .crumb .area{color:var(--violet)} | |
| /* Board detail */ | |
| #board{display:none} | |
| .back{cursor:pointer;color:var(--text-2);font-weight:600;font-size:.88rem;margin-bottom:10px;display:inline-flex;gap:6px} | |
| .back:hover{color:var(--violet)} | |
| .board-head{display:flex;flex-wrap:wrap;align-items:center;gap:10px 16px;margin-bottom:6px} | |
| .board-head h2{margin:0;font-size:1.5rem;letter-spacing:-.01em} | |
| .board-sub{color:var(--text-2);font-size:.9rem;margin:2px 0 16px} | |
| table{border-collapse:collapse;width:100%;font-size:.9rem;background:var(--card); | |
| border:1px solid var(--border);border-radius:12px;overflow:hidden} | |
| thead th{background:var(--card-2);text-align:left;padding:10px 12px;font-size:.74rem; | |
| text-transform:uppercase;letter-spacing:.04em;color:var(--text-2);position:sticky;top:0} | |
| tbody td{padding:9px 12px;border-top:1px solid var(--border);vertical-align:middle} | |
| tbody tr:hover{background:var(--card-2)} | |
| td.num{font-family:var(--mono);text-align:right;font-weight:600} | |
| td.rank{font-family:var(--mono);color:var(--muted);width:42px;text-align:center} | |
| .medal{font-size:1.05em} | |
| /* Model rankings (inline, shown when a sub-category is selected) */ | |
| .rk-card{background:var(--card);border:1px solid var(--border);border-radius:14px; | |
| padding:16px 18px;box-shadow:var(--shadow);margin-bottom:18px} | |
| .rk-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:5px} | |
| .rk-head h3{margin:0;font-size:1.18rem;letter-spacing:-.01em} | |
| .rk-meta{color:var(--muted);font-size:.8rem} | |
| .rk-bar{height:8px;border-radius:5px;background:var(--card-2);overflow:hidden;min-width:70px;flex:1} | |
| .rk-bar > i{display:block;height:100%;background:var(--violet)} | |
| /* Clickable per-board chips β open that board's standings */ | |
| .rk-chips{display:flex;flex-wrap:wrap;gap:5px;margin-top:6px} | |
| .rk-bchip{display:inline-flex;align-items:center;gap:5px;font-size:.72rem;line-height:1.1; | |
| padding:2px 8px;border:1px solid var(--border);border-left-width:3px;border-radius:999px; | |
| background:var(--card-2);color:var(--text-2);cursor:pointer;max-width:15rem; | |
| transition:background .12s,color .12s,box-shadow .12s} | |
| .rk-bchip:hover{background:var(--violet);color:#fff;box-shadow:var(--shadow)} | |
| .rk-bchip b{font-family:var(--mono);font-weight:700} | |
| .rk-bchip-name{max-width:11rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} | |
| /* Top-3 by default; rk-extra rows reveal when the tbody is expanded. */ | |
| tbody:not(.rk-expanded) tr.rk-extra{display:none} | |
| .rk-more{border:1px solid var(--border);background:var(--card);color:var(--violet); | |
| border-radius:999px;padding:6px 16px;font-size:.82rem;font-weight:700;cursor:pointer;transition:all .14s} | |
| .rk-more:hover{border-color:var(--violet);background:var(--violet);color:#fff} | |
| /* Collapsible per-board chip list (default collapsed). */ | |
| .rk-boards-d{margin-top:6px} | |
| .rk-boards-d > summary{display:inline-flex;align-items:center;gap:4px;cursor:pointer;list-style:none; | |
| font-size:.74rem;color:var(--violet);width:max-content} | |
| .rk-boards-d > summary::-webkit-details-marker{display:none} | |
| .rk-boards-d > summary::before{content:"βΈ";font-size:.66rem;transition:transform .12s} | |
| .rk-boards-d[open] > summary::before{transform:rotate(90deg)} | |
| .rk-boards-d > summary:hover{text-decoration:underline} | |
| .rk-boards-d .rk-chips{margin-top:5px} | |
| .cov{font-family:var(--mono);font-size:.78rem;border-radius:6px;padding:2px 8px;border:1px solid;white-space:nowrap} | |
| .cov.full{background:rgba(22,163,74,.12);color:#16a34a;border-color:rgba(22,163,74,.32)} | |
| .cov.part{background:rgba(202,138,4,.13);color:#b45309;border-color:rgba(202,138,4,.32)} | |
| body.dark .cov.part{color:#fbbf24} | |
| .empty{text-align:center;color:var(--muted);padding:48px 0} | |
| footer{text-align:center;color:var(--muted);font-size:.82rem;margin-top:40px;padding-top:20px;border-top:1px solid var(--border)} | |
| .spin{display:inline-block;width:18px;height:18px;border:2px solid var(--border);border-top-color:var(--violet); | |
| border-radius:50%;animation:sp .7s linear infinite;vertical-align:middle} | |
| @keyframes sp{to{transform:rotate(360deg)}} | |
| @media(max-width:560px){.hero h1{font-size:1.55rem}.stat{min-width:90px;padding:10px 14px}} | |
| </style> | |
| </head> | |
| <body> | |
| <div class="topbar"> | |
| <div class="brand"><span>π</span> BenchHub <span class="dot">Leaderboards</span></div> | |
| <div class="spacer"></div> | |
| <button class="btn" id="darkBtn" onclick="toggleDark()">π Dark</button> | |
| <a class="btn btn-primary" id="ctaTop" target="_blank" rel="noopener">Open BenchHub β</a> | |
| </div> | |
| <div class="wrap"> | |
| <div class="hero"> | |
| <h1>Open, π-to-π ML benchmarks</h1> | |
| <p>Every model scored on the <b>same data</b>, the <b>same metric</b>, in a reproducible sandbox β | |
| across LLM, vision, and audio. Browse the standings here; run your model and submit free on BenchHub.</p> | |
| <div class="stats" id="stats"></div> | |
| </div> | |
| <!-- Trust strip: why these numbers are reliable (the conversion hook). --> | |
| <div class="trust" id="trust"> | |
| <div class="trust-item"><span>π―</span><div><b>Same data & metric</b><br>Every model on a board runs the identical eval set and scorer.</div></div> | |
| <div class="trust-item"><span>π</span><div><b>Pinned protocol</b><br>LLM boards bake one exact prompt β zero-shot, exact-match, no per-model tuning.</div></div> | |
| <div class="trust-item"><span>π¦</span><div><b>Sandboxed, not self-reported</b><br>Predictions are scored server-side in a container β reproducible, not paper numbers.</div></div> | |
| </div> | |
| <div class="controls"> | |
| <input id="search" type="search" placeholder="π Search benchmarks by name or domainβ¦" oninput="onSearch(this.value)"> | |
| </div> | |
| <!-- Domain filter for the sub-category cards (shown only in the cards view). --> | |
| <div class="subcontrols" id="domainFilter" style="display:none"> | |
| <span class="sublabel">Domain</span> | |
| <div class="pills" id="domainPills"></div> | |
| </div> | |
| <!-- Drill-down back link + breadcrumb, shown when inside a sub-category. --> | |
| <div id="backBar" style="display:none"></div> | |
| <!-- Inline meta-ranking: appears when a specific sub-category is selected. --> | |
| <div id="subRanking"></div> | |
| <!-- Holds either sub-category cards (default) or a sub-category's board cards. --> | |
| <div id="grid"><div class="empty"><span class="spin"></span> Loadingβ¦</div></div> | |
| <div id="board"> | |
| <span class="back" onclick="closeBoard()">β Back</span> | |
| <div class="board-head"><h2 id="bName"></h2></div> | |
| <div class="board-sub" id="bSub"></div> | |
| <div id="bTable"></div> | |
| </div> | |
| <footer> | |
| Read-only mirror of public standings from | |
| <a id="ctaFoot" target="_blank" rel="noopener">runbenchhub.com</a>. | |
| No ground-truth data, no submissions here β the interactive explorer, per-sample comparison, | |
| and submission live on BenchHub. <span id="synced"></span> | |
| </footer> | |
| </div> | |
| <script> | |
| const DATA = "https://huggingface.co/datasets/runbenchhub/leaderboards/resolve/main"; | |
| const SITE = "https://runbenchhub.com"; | |
| const UTM = "utm_source=hf_space&utm_medium=mirror"; | |
| const ALL = "All"; | |
| let ENTRIES = [], AREA = ALL, SUB = ALL, QUERY = ""; | |
| let AGG = []; // sub-category meta-rankings from aggregates.json | |
| function utm(url){ if(!url) return url; return url + (url.includes("?")?"&":"?") + UTM; } | |
| function esc(s){ return String(s==null?"":s).replace(/[&<>"]/g,c=>({"&":"&","<":"<",">":">",'"':"""}[c])); } | |
| function area(cat){ return (cat||"Uncategorized").split("/")[0]; } | |
| function subarea(cat){ const p=(cat||"").split("/"); return p.length>1?p.slice(1).join("/").trim():""; } | |
| function fmtNum(v){ if(v==null||isNaN(v)) return "β"; const n=+v; return Number.isInteger(n)?String(n):n.toFixed(4).replace(/0+$/,"").replace(/\.$/,""); } | |
| async function getJSON(path){ | |
| const r = await fetch(DATA+path, {cache:"no-cache"}); | |
| if(!r.ok) throw new Error(r.status); | |
| return r.json(); | |
| } | |
| /* ---------- init ---------- */ | |
| (async function init(){ | |
| document.getElementById("ctaTop").href = utm(SITE); | |
| document.getElementById("ctaFoot").href = utm(SITE); | |
| if(localStorage.getItem("bh-dark")==="1") document.body.classList.add("dark"), setDarkLabel(); | |
| try{ | |
| const idx = await getJSON("/index.json"); | |
| ENTRIES = (idx.leaderboards||[]).filter(e => (e.n_verified||0) > 0); | |
| // Load the sub-category meta-rankings up front (best-effort) so they're | |
| // ready the moment a sub-category pill is clicked. | |
| try{ const ag = await getJSON("/aggregates.json"); AGG = ag.scopes || []; }catch(_){ AGG = []; } | |
| renderStats(idx); | |
| applyNav(parseHash()); // restore view from the URL hash (deep link / refresh) | |
| replaceNav(); // seed the history entry for this view | |
| const g = idx.generated_at; | |
| if(g) document.getElementById("synced").textContent = "Last synced "+new Date(g).toLocaleDateString(undefined,{year:"numeric",month:"short",day:"numeric"})+"."; | |
| }catch(e){ | |
| document.getElementById("grid").innerHTML = '<div class="empty">Couldnβt load standings right now. <a href="'+utm(SITE)+'" target="_blank" rel="noopener">Open BenchHub β</a></div>'; | |
| } | |
| })(); | |
| function renderStats(idx){ | |
| const subs = ENTRIES.reduce((a,e)=>a+(e.n_verified||0),0); | |
| // Distinct sub-categories (full "Area/Sub" category strings) β reflects the | |
| // breadth of the catalog better than the handful of top-level domains. | |
| const subcats = new Set(ENTRIES.map(e=>e.category||"Uncategorized")).size; | |
| const el = document.getElementById("stats"); | |
| const cards = [["Benchmarks",ENTRIES.length],["Submissions",subs],["Sub-categories",subcats]]; | |
| el.innerHTML = cards.map(c=>`<div class="stat"><div class="n" data-to="${c[1]}">0</div><div class="l">${c[0]}</div></div>`).join(""); | |
| el.querySelectorAll(".n").forEach(countUp); | |
| } | |
| function countUp(node){ | |
| const to=+node.dataset.to||0, dur=900, t0=performance.now(); | |
| function step(t){ const p=Math.min(1,(t-t0)/dur); node.textContent=Math.round(to*(1-Math.pow(1-p,3))); if(p<1)requestAnimationFrame(step); } | |
| requestAnimationFrame(step); | |
| } | |
| const jsstr = s => String(s).replace(/\\/g,"\\\\").replace(/'/g,"\\'"); | |
| // Two-level browse: sub-category cards (default) -> a sub-category's boards. | |
| // AREA/SUB === ALL means "browsing categories"; both set means "inside a sub". | |
| let BOARD = null; // open board id, or null | |
| // --- History API: browser Back/Forward mirror the in-app drill-down --- | |
| function hashFor(){ | |
| if(BOARD!=null) return "#b/"+BOARD; | |
| if(QUERY) return "#q/"+encodeURIComponent(QUERY); | |
| if(AREA!==ALL && SUB!==ALL) return "#c/"+encodeURIComponent(AREA)+"/"+encodeURIComponent(SUB); | |
| if(AREA!==ALL) return "#d/"+encodeURIComponent(AREA); | |
| return "#"; | |
| } | |
| function navState(){ return {area:AREA, sub:SUB, query:QUERY, board:BOARD}; } | |
| function pushNav(){ try{ history.pushState(navState(), "", hashFor()); }catch(e){} } | |
| function replaceNav(){ try{ history.replaceState(navState(), "", hashFor()); }catch(e){} } | |
| function parseHash(){ | |
| const h=decodeURIComponent(location.hash||""); let m; | |
| if(m=h.match(/^#b\/(\d+)/)) return {board:+m[1]}; | |
| if(m=h.match(/^#q\/(.+)/)) return {query:m[1].toLowerCase()}; | |
| if(m=h.match(/^#c\/([^/]+)\/(.+)/)) return {area:m[1], sub:m[2]}; | |
| if(m=h.match(/^#d\/(.+)/)) return {area:m[1]}; | |
| return {}; | |
| } | |
| function applyNav(s){ // set state from a popped/parsed entry; no new push | |
| s=s||{}; | |
| AREA=s.area||ALL; SUB=s.sub||ALL; QUERY=s.query||""; BOARD=(s.board!=null?s.board:null); | |
| const i=document.getElementById("search"); if(i) i.value=QUERY; | |
| if(BOARD!=null) openBoard(BOARD, true); else render(); | |
| } | |
| window.addEventListener("popstate", function(e){ applyNav(e.state || parseHash()); window.scrollTo({top:0}); }); | |
| function onSearch(v){ const had=!!QUERY; QUERY=(v||"").trim().toLowerCase(); BOARD=null; render(); if(QUERY&&!had) pushNav(); else replaceNav(); } | |
| function enterSub(a,s){ AREA=a; SUB=s; QUERY=""; BOARD=null; const i=document.getElementById("search"); if(i) i.value=""; pushNav(); render(); window.scrollTo({top:0,behavior:"smooth"}); } | |
| function backToCats(){ history.back(); } // in-app back == browser back | |
| // Master view dispatcher. | |
| function render(){ | |
| const bb=document.getElementById("backBar"), sr=document.getElementById("subRanking"), | |
| df=document.getElementById("domainFilter"), tr=document.getElementById("trust"); | |
| document.getElementById("board").style.display="none"; | |
| document.querySelector(".controls").style.display=""; | |
| document.getElementById("grid").style.display=""; | |
| if(QUERY){ // search: flat board cards across all | |
| tr.style.display="none"; df.style.display="none"; bb.style.display="none"; sr.innerHTML=""; renderBoardCards(searchList()); | |
| } else if(AREA!==ALL && SUB!==ALL){ // inside a sub-category | |
| tr.style.display="none"; df.style.display="none"; bb.style.display=""; | |
| bb.innerHTML=`<span class="back" onclick="backToCats()">β All categories</span>`+ | |
| `<span class="crumb"><span class="area">${esc(AREA)}</span> Β· ${esc(SUB)}</span>`; | |
| renderSubRanking(); | |
| renderBoardCards(subList()); | |
| } else { // main page: sub-category cards (+ domain filter + trust strip) | |
| bb.style.display="none"; sr.innerHTML=""; | |
| tr.style.display=""; df.style.display="flex"; renderDomainPills(); renderCatCards(); | |
| } | |
| } | |
| // Domain (top-level area) filter for the cards view β narrows which | |
| // sub-category cards show. AREA===ALL shows every domain. | |
| function renderDomainPills(){ | |
| const areas=catGroups().map(g=>g[0]); // ordered by board count desc | |
| document.getElementById("domainPills").innerHTML = | |
| [ALL,...areas].map(a=>`<span class="pill ${a===AREA?'on':''}" onclick="setDomain('${jsstr(a)}')">${esc(a)}</span>`).join(""); | |
| } | |
| function setDomain(a){ AREA=a; SUB=ALL; QUERY=""; BOARD=null; const i=document.getElementById("search"); if(i) i.value=""; pushNav(); render(); } | |
| function searchList(){ | |
| return ENTRIES.filter(e=>(e.name+" "+(e.category||"")).toLowerCase().includes(QUERY)) | |
| .sort((a,b)=>(b.n_verified||0)-(a.n_verified||0)); | |
| } | |
| function subList(){ | |
| return ENTRIES.filter(e=>area(e.category)===AREA && (subarea(e.category)||"General")===SUB) | |
| .sort((a,b)=>(b.n_verified||0)-(a.n_verified||0)); | |
| } | |
| // area -> [[sub, count], ...] desc by count, for the default card view. | |
| function catGroups(){ | |
| const m={}; | |
| ENTRIES.forEach(e=>{ const a=area(e.category), s=subarea(e.category)||"General"; | |
| (m[a]=m[a]||{}); m[a][s]=(m[a][s]||0)+1; }); | |
| return Object.keys(m).sort((x,y)=>{ | |
| const cx=Object.values(m[x]).reduce((p,c)=>p+c,0), cy=Object.values(m[y]).reduce((p,c)=>p+c,0); | |
| return cy-cx || x.localeCompare(y); | |
| }).map(a=>[a, Object.entries(m[a]).sort((p,q)=>q[1]-p[1])]); | |
| } | |
| function renderCatCards(){ | |
| let groups=catGroups(); | |
| if(AREA!==ALL) groups=groups.filter(([a])=>a===AREA); // domain filter | |
| if(!groups.length){ document.getElementById("grid").innerHTML='<div class="empty">No benchmarks yet.</div>'; return; } | |
| document.getElementById("grid").innerHTML = groups.map(([a,subs])=>{ | |
| const total=subs.reduce((p,[,c])=>p+c,0); | |
| const cards=subs.map(([s,c])=> | |
| `<div class="card catcard" onclick="enterSub('${jsstr(a)}','${jsstr(s)}')"> | |
| <span class="cat">${esc(a)}</span> | |
| <h3>${esc(s)}</h3> | |
| <div class="meta"><span class="subs"><b>${c}</b> board${c===1?"":"s"}</span><span class="go">Browse β</span></div> | |
| </div>`).join(""); | |
| return `<div class="cat-head">${esc(a)} <span class="n">${total}</span></div><div class="grid">${cards}</div>`; | |
| }).join(""); | |
| } | |
| function renderBoardCards(list){ | |
| const wrap=document.getElementById("grid"); | |
| if(!list.length){ wrap.innerHTML='<div class="empty">No benchmarks match.</div>'; return; } | |
| wrap.innerHTML = '<div class="grid">'+list.map(e=>{ | |
| const sa = subarea(e.category); | |
| const top = e.top; | |
| const lead = top && top.name | |
| ? `π₯ <b>${esc(top.name)}</b>${top.score!=null?` <span class="score">${fmtNum(top.score)}</span>`:""}` | |
| : `<span style="color:var(--muted)">${e.n_verified} ranked model${e.n_verified===1?"":"s"}</span>`; | |
| return `<div class="card" onclick="openBoard(${e.id})"> | |
| <span class="cat">${esc(area(e.category))}${sa?" Β· "+esc(sa):""}</span> | |
| <h3>${esc(e.name)}</h3> | |
| <div class="lead">${lead}</div> | |
| <div class="meta"> | |
| <span class="subs"><b>${e.n_verified}</b> submission${e.n_verified===1?"":"s"}</span> | |
| <span class="go">Standings β</span> | |
| </div> | |
| </div>`; | |
| }).join("")+'</div>'; | |
| } | |
| // Sub-category meta-ranking, shown inline above the board cards inside a sub. | |
| function renderSubRanking(){ | |
| const box=document.getElementById("subRanking"); | |
| if(AREA===ALL || SUB===ALL){ box.innerHTML=""; return; } | |
| const scope=(AGG||[]).find(s=>s.scope===AREA+"/"+SUB); | |
| box.innerHTML = scope ? renderScope(scope) : ""; | |
| } | |
| /* ---------- board detail ---------- */ | |
| function aggRanks(verified, cols){ | |
| const n=verified.length; if(!n||!cols.length) return {}; | |
| const tot=Array(n).fill(0), cnt=Array(n).fill(0); | |
| for(const c of cols){ | |
| const mid=String(c.metric_id), higher=(c.sort_direction||"higher_is_better")!=="lower_is_better"; | |
| const scored=[], missing=[]; | |
| verified.forEach((r,i)=>{ const v=(r.scores||{})[mid]; (typeof v==="number"?scored:missing).push([i,v]); }); | |
| if(!scored.length) continue; | |
| scored.sort((a,b)=>higher?b[1]-a[1]:a[1]-b[1]); | |
| let k=0; | |
| while(k<scored.length){ let j=k; while(j+1<scored.length && scored[j+1][1]===scored[k][1]) j++; | |
| const avg=(k+j)/2+1; for(let t=k;t<=j;t++){ tot[scored[t][0]]+=avg; cnt[scored[t][0]]++; } k=j+1; } | |
| for(const [i] of missing){ tot[i]+=n; cnt[i]++; } | |
| } | |
| const out={}; for(let i=0;i<n;i++) if(cnt[i]) out[i]=tot[i]/cnt[i]; | |
| return out; | |
| } | |
| function greenStyle(v, lo, hi, higher){ | |
| if(v==null||isNaN(v)) return ""; | |
| const rng=(hi-lo)||1; let norm=(v-lo)/rng; if(!higher) norm=1-norm; | |
| return `background-color:hsl(120,68%,${(90-norm*47).toFixed(0)}%);color:#0b3d0b;`; | |
| } | |
| async function openBoard(id, fromPop){ | |
| BOARD=id; if(!fromPop) pushNav(); | |
| document.getElementById("trust").style.display="none"; | |
| document.getElementById("grid").style.display="none"; | |
| document.querySelector(".controls").style.display="none"; | |
| document.getElementById("backBar").style.display="none"; | |
| document.getElementById("subRanking").innerHTML=""; | |
| const b=document.getElementById("board"); b.style.display="block"; | |
| document.getElementById("bName").textContent="Loadingβ¦"; | |
| document.getElementById("bSub").innerHTML=""; | |
| document.getElementById("bTable").innerHTML='<div class="empty"><span class="spin"></span></div>'; | |
| window.scrollTo({top:0,behavior:"smooth"}); | |
| let d; try{ d=await getJSON("/leaderboards/"+id+".json"); } | |
| catch(e){ document.getElementById("bTable").innerHTML='<div class="empty">Couldnβt load this board.</div>'; return; } | |
| const cols=d.columns||[], verified=d.verified||[]; | |
| document.getElementById("bName").textContent=d.name||""; | |
| const view=utm(d.url||`${SITE}/leaderboard/${id}`), submit=utm(d.submit_url||`${SITE}/leaderboard/${id}`); | |
| document.getElementById("bSub").innerHTML = | |
| `<span style="color:var(--violet);font-weight:700">${esc(d.category||"Uncategorized")}</span> Β· `+ | |
| `${verified.length} submission${verified.length===1?"":"s"} `+ | |
| `<a class="btn btn-primary" href="${submit}" target="_blank" rel="noopener" style="padding:5px 12px">π Submit your model</a> `+ | |
| `<a class="btn" href="${view}" target="_blank" rel="noopener" style="padding:5px 12px">Full board β</a>`; | |
| if(!verified.length){ document.getElementById("bTable").innerHTML='<div class="empty">No ranked submissions yet.</div>'; return; } | |
| const multi=cols.length>1; | |
| const agg=aggRanks(verified,cols); | |
| const order=verified.map((_,i)=>i).sort((a,b)=>(agg[a]??1e9)-(agg[b]??1e9)); | |
| // column ranges for the heatmap | |
| const ranges=cols.map(c=>{ const mid=String(c.metric_id); | |
| const nums=verified.map(r=>(r.scores||{})[mid]).filter(v=>typeof v==="number"); | |
| return {lo:Math.min(...nums), hi:Math.max(...nums), higher:(c.sort_direction||"higher_is_better")!=="lower_is_better"}; }); | |
| const aggNums=Object.values(agg); const aggLo=Math.min(...aggNums), aggHi=Math.max(...aggNums); | |
| let head="<tr><th>#</th><th>Submission</th><th>Author</th>"; | |
| if(multi) head+="<th>Agg. rank</th>"; | |
| head+=cols.map(c=>`<th style="text-align:right">${esc(c.label)}</th>`).join("")+"</tr>"; | |
| const medals=["π₯","π₯","π₯"]; | |
| let body=""; | |
| order.forEach((i,pos)=>{ | |
| const r=verified[i], rk=pos+1; | |
| const name=esc(r.name||""); | |
| const sub=r.link?`<a href="${utm(esc(r.link))}" target="_blank" rel="noopener">${name}</a>`:name; | |
| const author=r.author_url?`<a href="${esc(r.author_url)}" target="_blank" rel="noopener">${esc(r.author||"")}</a>`:esc(r.author||""); | |
| let row=`<tr><td class="rank">${pos<3?`<span class="medal">${medals[pos]}</span>`:rk}</td>`+ | |
| `<td>${sub}</td><td style="color:var(--text-2)">${author||"β"}</td>`; | |
| if(multi){ const a=agg[i]; row+=`<td class="num" style="${greenStyle(a,aggLo,aggHi,false)}">${a!=null?a.toFixed(2):"β"}</td>`; } | |
| cols.forEach((c,ci)=>{ const v=(r.scores||{})[String(c.metric_id)]; | |
| row+=`<td class="num" style="${greenStyle(typeof v==="number"?v:null,ranges[ci].lo,ranges[ci].hi,ranges[ci].higher)}">${fmtNum(v)}</td>`; }); | |
| body+=row+"</tr>"; | |
| }); | |
| document.getElementById("bTable").innerHTML=`<table>${head}${body}</table>`; | |
| } | |
| function closeBoard(){ history.back(); } // in-app back == browser back (popstate restores the view) | |
| /* ---------- model rankings ---------- */ | |
| // 0..1 β violet ramp, matching the site's hsl(258,70%,...) per-board bars | |
| function miniColor(nv){ return `hsl(258,70%,${Math.round(88 - nv*48)}%)`; } | |
| function renderScope(s){ | |
| const medals=["π₯","π₯","π₯"]; | |
| const list=(s.models||[]).slice(0,50); | |
| const rows = list.map((m,i)=>{ | |
| const rk=i+1; | |
| const name = m.link ? `<a href="${utm(esc(m.link))}" target="_blank" rel="noopener">${esc(m.model)}</a>` : esc(m.model); | |
| // Clickable per-board chips: each opens that board's standings, tinted by | |
| // the model's normalized score there. | |
| const chips = Object.entries(m.per_board||{}).map(([bn,info])=>{ | |
| const nv=+info.norm; | |
| return `<span class="rk-bchip" title="See this model on β${esc(bn)}β β normalized ${nv.toFixed(2)}"`+ | |
| ` style="border-left-color:${miniColor(nv)}" onclick="event.stopPropagation();openBoard(${info.lb_id})">`+ | |
| `<span class="rk-bchip-name">${esc(bn)}</span><b>${nv.toFixed(2)}</b></span>`; | |
| }).join(""); | |
| const full = m.coverage===s.n_boards; | |
| // Per-board chips collapsed by default (native <details>). | |
| const boards = `<details class="rk-boards-d"><summary>${m.coverage} board${m.coverage===1?"":"s"}</summary><div class="rk-chips">${chips}</div></details>`; | |
| return `<tr class="${i>=3?"rk-extra":""}"> | |
| <td class="rank">${rk<=3?`<span class="medal">${medals[rk-1]}</span>`:rk}</td> | |
| <td><div style="font-weight:600;word-break:break-word">${name}</div>${boards}</td> | |
| <td><div style="display:flex;align-items:center;gap:8px"> | |
| <div class="rk-bar"><i style="width:${Math.round((+m.score)*100)}%"></i></div> | |
| <span class="num" style="font-weight:700">${(+m.score).toFixed(3)}</span> | |
| </div></td> | |
| <td style="text-align:center"><span class="cov ${full?"full":"part"}">${m.coverage}/${s.n_boards}</span></td> | |
| </tr>`; | |
| }).join(""); | |
| const shown=list.length; | |
| // Top 3 by default; "Show all" reveals the rest (rk-extra rows). | |
| const toggle = shown>3 ? `<div style="text-align:center;margin-top:10px"><button class="rk-more" data-more="Show all ${shown} models" data-less="Show top 3" onclick="rkToggle(this)">Show all ${shown} models</button></div>` : ""; | |
| const more = s.n_models>50 ? `<div class="rk-meta" style="margin-top:7px;text-align:center">Top 50 of ${s.n_models} models.</div>` : ""; | |
| return `<div class="rk-card"> | |
| <div class="rk-head"> | |
| <h3>π Model ranking</h3> | |
| <span class="rk-meta">Β· combined across ${s.n_boards} boards Β· ${s.n_models} models</span> | |
| </div> | |
| <table><thead><tr><th>#</th><th>Model</th><th>Score</th><th style="text-align:center">Coverage</th></tr></thead> | |
| <tbody>${rows}</tbody></table> | |
| ${toggle}${more} | |
| </div>`; | |
| } | |
| // Expand/collapse the ranking table (top 3 β all). | |
| function rkToggle(btn){ | |
| const tb=btn.closest(".rk-card").querySelector("tbody"); | |
| const exp=tb.classList.toggle("rk-expanded"); | |
| btn.textContent = exp ? btn.dataset.less : btn.dataset.more; | |
| } | |
| /* ---------- dark mode ---------- */ | |
| function setDarkLabel(){ document.getElementById("darkBtn").textContent=document.body.classList.contains("dark")?"βοΈ Light":"π Dark"; } | |
| function toggleDark(){ document.body.classList.toggle("dark"); localStorage.setItem("bh-dark",document.body.classList.contains("dark")?"1":"0"); setDarkLabel(); } | |
| </script> | |
| </body> | |
| </html> | |