Leaderboard / app.js
liukqchoco04's picture
Upload 5 files
0e47d41 verified
Raw
History Blame Contribute Delete
19.1 kB
const state = {
data: null,
track: "shared",
category: "quality",
sortMetric: "va",
sortDirection: "desc",
query: "",
paradigm: "all",
access: "all"
};
const elements = {
trackTabs: document.querySelector("#track-tabs"),
trackDescription: document.querySelector("#track-description"),
categoryTabs: document.querySelector("#category-tabs"),
categoryTitle: document.querySelector("#category-title"),
categoryDescription: document.querySelector("#category-description"),
tablePanel: document.querySelector(".table-panel"),
tableKicker: document.querySelector("#table-kicker"),
rankingLabel: document.querySelector("#ranking-label"),
table: document.querySelector("#leaderboard-table"),
tableStatus: document.querySelector("#table-status"),
contextCopy: document.querySelector("#context-copy"),
search: document.querySelector("#model-search"),
metricSelect: document.querySelector("#metric-select"),
paradigm: document.querySelector("#paradigm-filter"),
access: document.querySelector("#access-filter"),
reset: document.querySelector("#reset-filters"),
download: document.querySelector("#download-csv"),
metricGuide: document.querySelector("#metric-guide"),
error: document.querySelector("#data-error")
};
const directionFor = (metric) => metric.direction === "higher" ? "desc" : "asc";
const escapeHtml = (value) => String(value)
.replaceAll("&", "&")
.replaceAll("<", "&lt;")
.replaceAll(">", "&gt;")
.replaceAll('"', "&quot;")
.replaceAll("'", "&#039;");
function formatScore(value) {
if (value === null || value === undefined) return "—";
return Number(value).toFixed(state.data.meta.publishedPrecision);
}
function sourceLabel(access) {
if (access === "Open") return "Open-source";
if (access === "Web") return "Closed-source";
return access;
}
function currentCategory() {
return state.data.categories.find((category) => category.id === state.category);
}
function currentMetric() {
return state.data.metrics[state.sortMetric];
}
function applyLink(id, url, readyLabel, pendingLabel) {
const link = document.querySelector(`#${id}`);
if (!link) return;
if (url) {
link.href = url;
link.target = "_blank";
link.rel = "noopener noreferrer";
link.classList.remove("is-disabled");
link.removeAttribute("aria-disabled");
const status = link.querySelector("[data-link-status]");
if (status) status.textContent = readyLabel;
} else {
link.removeAttribute("href");
link.classList.add("is-disabled");
link.setAttribute("aria-disabled", "true");
const status = link.querySelector("[data-link-status]");
if (status) status.textContent = pendingLabel;
}
}
function renderMeta() {
const { meta } = state.data;
document.title = meta.title;
document.querySelector("#hero-tagline").textContent = meta.tagline;
document.querySelector("#hero-description").textContent = meta.description;
document.querySelector("#stat-systems").textContent = meta.systemCount;
document.querySelector("#stat-metrics").textContent = meta.metricCount;
document.querySelector("#stat-scenarios").textContent = meta.scenarioCount;
document.querySelector("#stat-duration").textContent = `${meta.durationSeconds}s`;
applyLink("project-link", meta.links.project, "Project page", "Coming soon");
applyLink("code-link", meta.links.code, "Code repository", "Coming soon");
applyLink("paper-link", meta.links.paper, "Read paper", "Coming soon");
applyLink("dataset-link", meta.links.dataset, "Open dataset", "Coming soon");
}
function renderTrackTabs() {
elements.trackTabs.innerHTML = state.data.tracks.map((track) => {
const active = track.id === state.track;
return `
<button
class="track-tab ${active ? "is-active" : ""}"
type="button"
role="tab"
aria-selected="${active}"
data-track="${escapeHtml(track.id)}"
>
<span>${escapeHtml(track.label)}</span>
<b>${escapeHtml(track.badge || track.count)}</b>
</button>
`;
}).join("");
const activeTrack = state.data.tracks.find((track) => track.id === state.track);
elements.trackDescription.textContent = activeTrack.description;
elements.trackTabs.querySelectorAll("[data-track]").forEach((button) => {
button.addEventListener("click", () => {
state.track = button.dataset.track;
const firstCategory = state.data.categories.find((category) => category.track === state.track);
state.category = firstCategory.id;
state.sortMetric = firstCategory.defaultMetric;
state.sortDirection = directionFor(state.data.metrics[state.sortMetric]);
render();
});
});
}
function renderCategoryTabs() {
const categories = state.data.categories.filter((category) => category.track === state.track);
elements.categoryTabs.innerHTML = categories.map((category) => {
const active = category.id === state.category;
return `
<button
class="category-tab ${active ? "is-active" : ""}"
type="button"
aria-pressed="${active}"
data-category="${escapeHtml(category.id)}"
>
${escapeHtml(category.label)}
</button>
`;
}).join("");
elements.categoryTabs.querySelectorAll("[data-category]").forEach((button) => {
button.addEventListener("click", () => {
const category = state.data.categories.find((item) => item.id === button.dataset.category);
state.category = category.id;
state.sortMetric = category.defaultMetric;
state.sortDirection = directionFor(state.data.metrics[state.sortMetric]);
render();
});
});
}
function renderMetricSelect() {
const category = currentCategory();
elements.metricSelect.innerHTML = category.metrics.map((metricKey) => {
const metric = state.data.metrics[metricKey];
const direction = metric.direction === "higher" ? "↑" : "↓";
return `<option value="${escapeHtml(metricKey)}">${escapeHtml(metric.abbr)} ${direction} · ${escapeHtml(metric.name)}</option>`;
}).join("");
elements.metricSelect.value = state.sortMetric;
}
function compareScores(a, b, metricKey, direction) {
const aValue = a.scores[metricKey];
const bValue = b.scores[metricKey];
if (aValue === null && bValue === null) return a.name.localeCompare(b.name);
if (aValue === null) return 1;
if (bValue === null) return -1;
const difference = direction === "desc" ? bValue - aValue : aValue - bValue;
return difference || a.name.localeCompare(b.name);
}
function buildRankMap(metricKey) {
const metric = state.data.metrics[metricKey];
const sortedValues = state.data.models
.map((model) => model.scores[metricKey])
.filter((value) => value !== null)
.sort((a, b) => metric.direction === "higher" ? b - a : a - b);
const ranks = new Map();
sortedValues.forEach((value, index) => {
if (!ranks.has(value)) ranks.set(value, index + 1);
});
return ranks;
}
function filteredModels() {
const query = state.query.trim().toLocaleLowerCase();
return state.data.models
.filter((model) => !query || model.name.toLocaleLowerCase().includes(query))
.filter((model) => state.paradigm === "all" || model.paradigm === state.paradigm)
.filter((model) => state.access === "all" || model.access === state.access)
.sort((a, b) => compareScores(a, b, state.sortMetric, state.sortDirection));
}
function contextForCategory(categoryId) {
const ranking = `
<p><strong>Ranking.</strong> Ranks use published three-decimal scores; ties use competition ranking (for example, 1, 1, 3). Select a metric to show the best values first, or click its active table header to reverse the display order.</p>
`;
const notes = {
streaming: `
<p><strong>Availability.</strong> NBC, FPS, and TTFC are unavailable for PixVerse R1, HappyOyster, and Odyssey-2 because their web interfaces do not expose model-native boundaries or reliable generation-time traces.</p>
`,
adherence: `
<p><strong>Endpoint drift.</strong> VID and AID are absolute changes between the first and last 30-second intervals; lower values indicate better stability.</p>
`,
stability: `
<p><strong>Reading drift.</strong> The six drift metrics favor lower endpoint change, while subject and background consistency favor higher values.</p>
`,
response: `
<p><strong>Conditional latency.</strong> PVRL and PARL are measured only for achieved targets and should be read together with PVUAR and PAUAR.</p>
`,
state: `
<p><strong>Conditional coverage.</strong> HDF is evaluated only when the required source state was established.</p>
`,
adjusted: `
<p><strong>Diagnostic status.</strong> These four adjusted diagnostics are separate from the 32 core metrics. SA-PVRL and SA-PARL assign the 30-second cap to unachieved targets; CA-HDF-A and CA-HDF-L assign zero when the required source state was not established.</p>
`
};
return `${ranking}${notes[categoryId] || ""}`;
}
function renderTable() {
const category = currentCategory();
const metric = currentMetric();
const models = filteredModels();
const rankMap = buildRankMap(state.sortMetric);
const arrow = state.sortDirection === "desc" ? "↓" : "↑";
const preferredDirection = metric.direction === "higher" ? "Higher is better" : "Lower is better";
const displayOrder = state.sortDirection === directionFor(metric) ? "Best to worst" : "Worst to best";
const isDiagnostics = state.track === "diagnostics";
elements.tablePanel.classList.toggle("is-diagnostics", isDiagnostics);
elements.tableKicker.textContent = isDiagnostics ? "Adjusted sensitivity analysis" : "Metric-wise ranking";
elements.categoryTitle.textContent = category.label;
elements.categoryDescription.textContent = category.description;
elements.rankingLabel.innerHTML = `
Ranked by <strong>${escapeHtml(metric.name)}</strong>
<span>${preferredDirection} &middot; ${displayOrder}</span>
`;
elements.contextCopy.innerHTML = contextForCategory(category.id);
const metricHeaders = category.metrics.map((metricKey) => {
const item = state.data.metrics[metricKey];
const active = metricKey === state.sortMetric;
const ariaSort = active
? (state.sortDirection === "desc" ? "descending" : "ascending")
: "none";
const title = active ? `Reverse ${item.name} order` : `Rank by ${item.name}`;
return `
<th scope="col" aria-sort="${ariaSort}" class="metric-column ${active ? "is-sorted" : ""}">
<button type="button" data-sort="${escapeHtml(metricKey)}" title="${escapeHtml(title)}">
<span>${escapeHtml(item.abbr)}</span>
<i aria-hidden="true">${active ? arrow : "↕"}</i>
<small>${item.direction === "higher" ? "higher" : "lower"}</small>
</button>
</th>
`;
}).join("");
const rows = models.map((model) => {
const sortedValue = model.scores[state.sortMetric];
const rank = sortedValue === null ? null : rankMap.get(sortedValue);
const rankClass = rank !== null && rank <= 3 ? ` rank-${rank}` : "";
const cells = category.metrics.map((metricKey) => {
const value = model.scores[metricKey];
const metricRankMap = buildMetricRankMap(metricKey);
const cellRank = value === null ? null : metricRankMap.get(value);
const rankClass = cellRank === 1 ? "is-best" : cellRank === 2 ? "is-runner-up" : "";
const sortedClass = metricKey === state.sortMetric ? "is-sorted" : "";
const metricInfo = state.data.metrics[metricKey];
const unit = value !== null && metricInfo.unit ? ` ${metricInfo.unit}` : "";
const unavailableReason = value === null
? "Unavailable because the official web interface does not expose model-native boundaries or reliable generation-time traces."
: "";
return `
<td
class="score-cell ${rankClass} ${sortedClass}"
data-label="${escapeHtml(metricInfo.abbr)}"
${unavailableReason ? `title="${escapeHtml(unavailableReason)}"` : ""}
>
${value === null
? `<span aria-hidden="true">—</span><span class="sr-only">${escapeHtml(unavailableReason)}</span>`
: `<span>${formatScore(value)}</span>${unit ? `<small>${escapeHtml(unit.trim())}</small>` : ""}`
}
</td>
`;
}).join("");
return `
<tr>
<td class="rank-cell" data-label="Rank">
${rank === null ? "—" : `<span class="rank-badge${rankClass}">${rank}</span>`}
</td>
<th scope="row" class="model-cell">
<a href="${escapeHtml(model.reference)}" target="_blank" rel="noopener noreferrer">
<span>${escapeHtml(model.name)}</span><i aria-hidden="true">↗</i>
</a>
<small>${model.paradigm === "Cascaded" ? "with HunyuanVideo-Foley" : "native audio-video"}</small>
</th>
<td class="meta-cell" data-label="Paradigm">
<span class="tag tag-${model.paradigm === "Native joint" ? "native" : "cascaded"}">${escapeHtml(model.paradigm)}</span>
</td>
<td class="meta-cell" data-label="Source">
<span class="access-dot access-${model.access.toLowerCase()}"></span>${escapeHtml(sourceLabel(model.access))}
</td>
${cells}
</tr>
`;
}).join("");
elements.table.innerHTML = `
<thead>
<tr>
<th scope="col" class="rank-heading">#</th>
<th scope="col" class="model-heading">System</th>
<th scope="col">Paradigm</th>
<th scope="col">Source</th>
${metricHeaders}
</tr>
</thead>
<tbody>
${rows || `
<tr>
<td class="empty-row" colspan="${4 + category.metrics.length}">
No systems match the current filters.
</td>
</tr>
`}
</tbody>
`;
elements.tableStatus.textContent = `${models.length} of ${state.data.models.length} systems · global ranks use published three-decimal scores`;
elements.table.querySelectorAll("[data-sort]").forEach((button) => {
button.addEventListener("click", () => {
const metricKey = button.dataset.sort;
if (state.sortMetric === metricKey) {
state.sortDirection = state.sortDirection === "desc" ? "asc" : "desc";
} else {
state.sortMetric = metricKey;
state.sortDirection = directionFor(state.data.metrics[metricKey]);
}
elements.metricSelect.value = state.sortMetric;
renderTable();
renderMetricGuide();
});
});
}
function buildMetricRankMap(metricKey) {
const item = state.data.metrics[metricKey];
const values = state.data.models
.map((model) => model.scores[metricKey])
.filter((value) => value !== null)
.sort((a, b) => item.direction === "higher" ? b - a : a - b);
return new Map([...new Set(values)].map((value, index) => [value, index + 1]));
}
function renderMetricGuide() {
const category = currentCategory();
elements.metricGuide.innerHTML = category.metrics.map((metricKey) => {
const metric = state.data.metrics[metricKey];
const active = metricKey === state.sortMetric;
return `
<article class="metric-card ${active ? "is-active" : ""}">
<button type="button" data-metric-card="${escapeHtml(metricKey)}" aria-label="Rank by ${escapeHtml(metric.name)}">
<span class="metric-abbr">${escapeHtml(metric.abbr)}</span>
<span class="direction direction-${metric.direction}">
${metric.direction === "higher" ? "↑ Higher" : "↓ Lower"}
</span>
</button>
<h3>${escapeHtml(metric.name)}</h3>
<p>${escapeHtml(metric.description)}</p>
<dl>
<div><dt>Reported as</dt><dd>${escapeHtml(metric.range)}${metric.unit ? ` · ${escapeHtml(metric.unit)}` : ""}</dd></div>
</dl>
</article>
`;
}).join("");
elements.metricGuide.querySelectorAll("[data-metric-card]").forEach((button) => {
button.addEventListener("click", () => {
state.sortMetric = button.dataset.metricCard;
state.sortDirection = directionFor(state.data.metrics[state.sortMetric]);
elements.metricSelect.value = state.sortMetric;
renderTable();
renderMetricGuide();
document.querySelector("#leaderboard").scrollIntoView({ behavior: "smooth", block: "start" });
});
});
}
function csvCell(value) {
const stringValue = value === null || value === undefined ? "" : String(value);
return `"${stringValue.replaceAll('"', '""')}"`;
}
function downloadCurrentView() {
const category = currentCategory();
const models = filteredModels();
const headers = ["System", "Paradigm", "Source", ...category.metrics.map((key) => state.data.metrics[key].abbr)];
const lines = [
headers.map(csvCell).join(","),
...models.map((model) => [
model.name,
model.paradigm,
sourceLabel(model.access),
...category.metrics.map((key) => model.scores[key])
].map(csvCell).join(","))
];
const blob = new Blob([`\uFEFF${lines.join("\n")}`], { type: "text/csv;charset=utf-8" });
const url = URL.createObjectURL(blob);
const anchor = document.createElement("a");
anchor.href = url;
anchor.download = `streamav-bench-${category.id}.csv`;
document.body.appendChild(anchor);
anchor.click();
anchor.remove();
URL.revokeObjectURL(url);
}
function resetFilters() {
state.query = "";
state.paradigm = "all";
state.access = "all";
elements.search.value = "";
elements.paradigm.value = "all";
elements.access.value = "all";
renderTable();
}
function bindControls() {
elements.search.addEventListener("input", (event) => {
state.query = event.target.value;
renderTable();
});
elements.metricSelect.addEventListener("change", (event) => {
state.sortMetric = event.target.value;
state.sortDirection = directionFor(state.data.metrics[state.sortMetric]);
renderTable();
renderMetricGuide();
});
elements.paradigm.addEventListener("change", (event) => {
state.paradigm = event.target.value;
renderTable();
});
elements.access.addEventListener("change", (event) => {
state.access = event.target.value;
renderTable();
});
elements.reset.addEventListener("click", resetFilters);
elements.download.addEventListener("click", downloadCurrentView);
}
function render() {
renderTrackTabs();
renderCategoryTabs();
renderMetricSelect();
renderTable();
renderMetricGuide();
}
async function init() {
try {
const response = await fetch("./data.json", { cache: "no-store" });
if (!response.ok) throw new Error(`Data request failed with status ${response.status}`);
state.data = await response.json();
state.sortDirection = directionFor(state.data.metrics[state.sortMetric]);
renderMeta();
bindControls();
render();
document.documentElement.classList.add("is-ready");
} catch (error) {
console.error(error);
elements.error.hidden = false;
elements.error.querySelector("p").textContent = "The leaderboard data could not be loaded. Please refresh the page or try again later.";
}
}
init();