Spaces:
Running
Running
Codex commited on
Commit ยท
f032aa0
1
Parent(s): ff5e7c3
Add overview K rank display switch
Browse files- app.js +37 -8
- index.html +8 -0
- style.css +41 -0
app.js
CHANGED
|
@@ -28,6 +28,7 @@ const state = {
|
|
| 28 |
collapsedFilters: new Set(),
|
| 29 |
recordsReady: false,
|
| 30 |
view: "overview",
|
|
|
|
| 31 |
sort: { key: "overall", asc: true },
|
| 32 |
metric: { tier: "tier1", key: null, detail: "__all__", frequency: "__all__", sort: { key: "rank", asc: true } },
|
| 33 |
strength: { tier: "tier1", mode: "k" }
|
|
@@ -185,12 +186,22 @@ function tierStats(records = includedRecords()) {
|
|
| 185 |
return [...stats.values()].map((row) => ({ ...row, overall: row.pointwise + row.ic + row.portfolio }));
|
| 186 |
}
|
| 187 |
function sortedOverview() {
|
| 188 |
-
const rows = state.recordsReady ? tierStats() : [...(state.data?.overall || [])]
|
|
|
|
|
|
|
|
|
|
| 189 |
const s = state.sort;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 190 |
rows.sort((a, b) => {
|
| 191 |
if (s.key === "model") return s.asc ? a.model.localeCompare(b.model) : b.model.localeCompare(a.model);
|
| 192 |
-
const av =
|
| 193 |
-
const bv =
|
| 194 |
return s.asc ? av - bv : bv - av;
|
| 195 |
});
|
| 196 |
return rows;
|
|
@@ -457,21 +468,35 @@ function fillHowtoFrequencies() {
|
|
| 457 |
}
|
| 458 |
function renderOverview() {
|
| 459 |
const rows = sortedOverview();
|
| 460 |
-
const
|
|
|
|
| 461 |
const leader = [...(state.recordsReady ? tierStats() : (state.data?.overall || []))]
|
| 462 |
.sort((a, b) => a.overall - b.overall || a.model.localeCompare(b.model))[0];
|
| 463 |
const strip = $("winner-strip");
|
| 464 |
if (strip && leader) {
|
| 465 |
strip.innerHTML = `<span>Overall #1</span><b>${isExaone(leader.model) ? "โ
" : ""}${displayName(leader.model)}</b><strong>Rank sum ${fmt(leader.overall, leader.overall % 1 ? 1 : 0)}</strong>`;
|
| 466 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 467 |
$("overview-body").innerHTML = rows.map((row, index) => `
|
| 468 |
<tr class="model-row ${isExaone(row.model) ? "exaone-row" : ""}">
|
| 469 |
<td class="num">${rankBadge(index + 1)}</td>
|
| 470 |
<td class="model-name" data-model="${row.model}">${isExaone(row.model) ? "โ
" : ""}${displayName(row.model)}</td>
|
| 471 |
-
|
| 472 |
-
|
| 473 |
-
|
| 474 |
-
|
| 475 |
<td class="num"><small>${row.count.toLocaleString()}</small></td>
|
| 476 |
</tr>
|
| 477 |
`).join("");
|
|
@@ -738,6 +763,10 @@ async function boot() {
|
|
| 738 |
$("detail-close").onclick = closeDrawer;
|
| 739 |
$("detail2-close").onclick = closeDrawer2;
|
| 740 |
$("drawer-scrim").onclick = closeDrawer;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 741 |
setupTabs();
|
| 742 |
setupCollapsibles();
|
| 743 |
buildSpecToggles();
|
|
|
|
| 28 |
collapsedFilters: new Set(),
|
| 29 |
recordsReady: false,
|
| 30 |
view: "overview",
|
| 31 |
+
overviewMode: "rank",
|
| 32 |
sort: { key: "overall", asc: true },
|
| 33 |
metric: { tier: "tier1", key: null, detail: "__all__", frequency: "__all__", sort: { key: "rank", asc: true } },
|
| 34 |
strength: { tier: "tier1", mode: "k" }
|
|
|
|
| 186 |
return [...stats.values()].map((row) => ({ ...row, overall: row.pointwise + row.ic + row.portfolio }));
|
| 187 |
}
|
| 188 |
function sortedOverview() {
|
| 189 |
+
const rows = (state.recordsReady ? tierStats() : [...(state.data?.overall || [])]).map((row) => ({
|
| 190 |
+
...row,
|
| 191 |
+
overall_k: geometricMean([row.pointwise_k, row.ic_k, row.portfolio_k])
|
| 192 |
+
}));
|
| 193 |
const s = state.sort;
|
| 194 |
+
const valueForSort = (row, key) => {
|
| 195 |
+
if (key === "pos" || key === "overall") return state.overviewMode === "k" ? row.overall_k : row.overall;
|
| 196 |
+
if (state.overviewMode === "k" && key === "pointwise") return row.pointwise_k;
|
| 197 |
+
if (state.overviewMode === "k" && key === "ic") return row.ic_k;
|
| 198 |
+
if (state.overviewMode === "k" && key === "portfolio") return row.portfolio_k;
|
| 199 |
+
return row[key];
|
| 200 |
+
};
|
| 201 |
rows.sort((a, b) => {
|
| 202 |
if (s.key === "model") return s.asc ? a.model.localeCompare(b.model) : b.model.localeCompare(a.model);
|
| 203 |
+
const av = valueForSort(a, s.key);
|
| 204 |
+
const bv = valueForSort(b, s.key);
|
| 205 |
return s.asc ? av - bv : bv - av;
|
| 206 |
});
|
| 207 |
return rows;
|
|
|
|
| 468 |
}
|
| 469 |
function renderOverview() {
|
| 470 |
const rows = sortedOverview();
|
| 471 |
+
const isKMode = state.overviewMode === "k";
|
| 472 |
+
const best = Math.min(...rows.map((r) => isKMode ? r.overall_k : r.overall).filter(finite));
|
| 473 |
const leader = [...(state.recordsReady ? tierStats() : (state.data?.overall || []))]
|
| 474 |
.sort((a, b) => a.overall - b.overall || a.model.localeCompare(b.model))[0];
|
| 475 |
const strip = $("winner-strip");
|
| 476 |
if (strip && leader) {
|
| 477 |
strip.innerHTML = `<span>Overall #1</span><b>${isExaone(leader.model) ? "โ
" : ""}${displayName(leader.model)}</b><strong>Rank sum ${fmt(leader.overall, leader.overall % 1 ? 1 : 0)}</strong>`;
|
| 478 |
}
|
| 479 |
+
$("overview-mode-toggle").checked = !isKMode;
|
| 480 |
+
document.querySelector('#overview-table th[data-sort="pointwise"]').textContent = isKMode ? "Point K โ" : "Point rank";
|
| 481 |
+
document.querySelector('#overview-table th[data-sort="ic"]').textContent = isKMode ? "Ranking K โ" : "Ranking rank";
|
| 482 |
+
document.querySelector('#overview-table th[data-sort="portfolio"]').textContent = isKMode ? "Decision K โ" : "Decision rank";
|
| 483 |
+
document.querySelector('#overview-table th[data-sort="overall"]').textContent = isKMode ? "Overall K โ" : "Rank sum โ";
|
| 484 |
+
const tierCell = (row, tier, value) => finite(value)
|
| 485 |
+
? `<td class="num tier-rank" data-model="${row.model}" data-tier="${tier}">${isKMode ? fmt(value) : rankBadge(value)}</td>`
|
| 486 |
+
: `<td class="num">${fmt(value)}</td>`;
|
| 487 |
+
const overallCell = (row) => {
|
| 488 |
+
const value = isKMode ? row.overall_k : row.overall;
|
| 489 |
+
const text = isKMode ? fmt(value) : fmt(value, value % 1 ? 1 : 0);
|
| 490 |
+
return `<td class="num ${value === best ? "val-best" : ""}"><b>${text}</b></td>`;
|
| 491 |
+
};
|
| 492 |
$("overview-body").innerHTML = rows.map((row, index) => `
|
| 493 |
<tr class="model-row ${isExaone(row.model) ? "exaone-row" : ""}">
|
| 494 |
<td class="num">${rankBadge(index + 1)}</td>
|
| 495 |
<td class="model-name" data-model="${row.model}">${isExaone(row.model) ? "โ
" : ""}${displayName(row.model)}</td>
|
| 496 |
+
${tierCell(row, "tier1", isKMode ? row.pointwise_k : row.pointwise)}
|
| 497 |
+
${tierCell(row, "tier2", isKMode ? row.ic_k : row.ic)}
|
| 498 |
+
${tierCell(row, "tier3", isKMode ? row.portfolio_k : row.portfolio)}
|
| 499 |
+
${overallCell(row)}
|
| 500 |
<td class="num"><small>${row.count.toLocaleString()}</small></td>
|
| 501 |
</tr>
|
| 502 |
`).join("");
|
|
|
|
| 763 |
$("detail-close").onclick = closeDrawer;
|
| 764 |
$("detail2-close").onclick = closeDrawer2;
|
| 765 |
$("drawer-scrim").onclick = closeDrawer;
|
| 766 |
+
$("overview-mode-toggle").onchange = (event) => {
|
| 767 |
+
state.overviewMode = event.target.checked ? "rank" : "k";
|
| 768 |
+
renderOverview();
|
| 769 |
+
};
|
| 770 |
setupTabs();
|
| 771 |
setupCollapsibles();
|
| 772 |
buildSpecToggles();
|
index.html
CHANGED
|
@@ -74,6 +74,14 @@
|
|
| 74 |
<b>Rank sum์ด ๋ฎ์์๋ก ์ฐ์</b>ํฉ๋๋ค.
|
| 75 |
</p>
|
| 76 |
<div id="winner-strip" class="winner-strip"></div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
<div class="table-wrap">
|
| 78 |
<table id="overview-table" class="board">
|
| 79 |
<thead>
|
|
|
|
| 74 |
<b>Rank sum์ด ๋ฎ์์๋ก ์ฐ์</b>ํฉ๋๋ค.
|
| 75 |
</p>
|
| 76 |
<div id="winner-strip" class="winner-strip"></div>
|
| 77 |
+
<div class="overview-toolbar">
|
| 78 |
+
<label class="mode-switch" title="Overview table display mode">
|
| 79 |
+
<span>K</span>
|
| 80 |
+
<input id="overview-mode-toggle" type="checkbox" checked />
|
| 81 |
+
<i aria-hidden="true"></i>
|
| 82 |
+
<span>Rank</span>
|
| 83 |
+
</label>
|
| 84 |
+
</div>
|
| 85 |
<div class="table-wrap">
|
| 86 |
<table id="overview-table" class="board">
|
| 87 |
<thead>
|
style.css
CHANGED
|
@@ -125,6 +125,47 @@ main { flex: 1 1 auto; min-width: 0; padding: 22px 32px 60px; }
|
|
| 125 |
}
|
| 126 |
.hint code, code { background: #fff; padding: 1px 5px; border-radius: 5px; font-size: 12px; }
|
| 127 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 128 |
.specbar, .filters, .table-wrap {
|
| 129 |
background: var(--card);
|
| 130 |
border: 1px solid var(--line);
|
|
|
|
| 125 |
}
|
| 126 |
.hint code, code { background: #fff; padding: 1px 5px; border-radius: 5px; font-size: 12px; }
|
| 127 |
|
| 128 |
+
.overview-toolbar {
|
| 129 |
+
display: flex;
|
| 130 |
+
justify-content: flex-end;
|
| 131 |
+
margin: -4px 0 10px;
|
| 132 |
+
}
|
| 133 |
+
.mode-switch {
|
| 134 |
+
display: inline-flex;
|
| 135 |
+
align-items: center;
|
| 136 |
+
gap: 8px;
|
| 137 |
+
color: var(--ink-soft);
|
| 138 |
+
font-size: 12px;
|
| 139 |
+
font-weight: 700;
|
| 140 |
+
}
|
| 141 |
+
.mode-switch input { position: absolute; opacity: 0; pointer-events: none; }
|
| 142 |
+
.mode-switch i {
|
| 143 |
+
position: relative;
|
| 144 |
+
width: 48px;
|
| 145 |
+
height: 24px;
|
| 146 |
+
border-radius: 999px;
|
| 147 |
+
background: var(--line);
|
| 148 |
+
border: 1px solid #d4dae5;
|
| 149 |
+
transition: background .15s ease, border-color .15s ease;
|
| 150 |
+
}
|
| 151 |
+
.mode-switch i::after {
|
| 152 |
+
content: "";
|
| 153 |
+
position: absolute;
|
| 154 |
+
top: 3px;
|
| 155 |
+
left: 3px;
|
| 156 |
+
width: 16px;
|
| 157 |
+
height: 16px;
|
| 158 |
+
border-radius: 50%;
|
| 159 |
+
background: #fff;
|
| 160 |
+
box-shadow: 0 1px 3px rgba(20, 30, 60, .22);
|
| 161 |
+
transition: transform .15s ease;
|
| 162 |
+
}
|
| 163 |
+
.mode-switch input:checked + i {
|
| 164 |
+
background: var(--accent);
|
| 165 |
+
border-color: var(--accent);
|
| 166 |
+
}
|
| 167 |
+
.mode-switch input:checked + i::after { transform: translateX(24px); }
|
| 168 |
+
|
| 169 |
.specbar, .filters, .table-wrap {
|
| 170 |
background: var(--card);
|
| 171 |
border: 1px solid var(--line);
|