import { initSite } from './site-shell.js'; const site = initSite({ onLanguageChange: render }); let snapshot = null, summary = null, failure = false; const t = (en, zh) => site.language === 'zh' ? zh : en; const number = value => value.toLocaleString('en-US'); function barChart(id, items, total) { const container = document.getElementById(id); container.replaceChildren(); for (const item of items) { const row = document.createElement('div'); row.className = 'bar-row'; const label = document.createElement('span'); label.className = 'bar-label'; label.textContent = item.label === 'Other' ? t('Other', '其他') : item.label; const count = document.createElement('span'); count.className = 'bar-count'; count.textContent = `${number(item.count)} · ${(item.count / total * 100).toFixed(1)}%`; const track = document.createElement('span'); track.className = 'bar-track'; track.setAttribute('aria-hidden', 'true'); const fill = document.createElement('span'); fill.style.width = `${item.count / total * 100}%`; track.append(fill); row.append(label, count, track); container.append(row); } } function render() { document.querySelectorAll('[data-snapshot]').forEach(el => { if (!snapshot) { if (el.dataset.snapshot === 'date' && failure) el.textContent = t('Snapshot unavailable. Open the leaderboard for details.', '快照暂不可用,请打开榜单查看。'); return; } const values = { groups: number(snapshot.groups), models: number(snapshot.models.length), date: t('Published ', '发布于 ') + snapshot.published_date }; el.textContent = values[el.dataset.snapshot]; }); if (!summary) { if (failure) document.querySelectorAll('.bar-chart').forEach(el => { el.textContent = t('Distribution unavailable. Open the dataset or download the summary JSON below.', '分布暂不可用,请打开数据集或下载下方分布 JSON。'); }); return; } barChart('method-chart', summary.methods, summary.tasks); barChart('journal-chart', summary.journals.slice(0, 5), summary.tasks); const table = document.createElement('table'); const caption = document.createElement('caption'); caption.textContent = t('Tasks by journal · n = 1,000', '按期刊统计任务 · n = 1,000'); table.append(caption); const thead = document.createElement('thead'), header = document.createElement('tr'); for (const label of [t('Journal','期刊'), t('Tasks','题数'), t('Share','比例')]) { const th = document.createElement('th'); th.scope = 'col'; th.textContent = label; header.append(th); } thead.append(header); table.append(thead); const tbody = document.createElement('tbody'); for (const item of summary.journals) { const row = document.createElement('tr'), name = document.createElement('th'), count = document.createElement('td'), percent = document.createElement('td'); name.scope = 'row'; name.textContent = item.label; count.textContent = number(item.count); percent.textContent = (item.count / summary.tasks * 100).toFixed(1) + '%'; row.append(name,count,percent); tbody.append(row); } table.append(tbody); document.getElementById('journal-table').replaceChildren(table); } async function readJSON(path) { const response = await fetch(path, { cache: 'no-cache' }); if (!response.ok) throw new Error(`HTTP ${response.status}`); return response.json(); } if (document.querySelector('[data-snapshot]')) { readJSON('./leaderboard-data.json').then(data => { if (!Array.isArray(data.models) || !Number.isInteger(data.groups) || data.records !== data.groups * data.tasks_per_group) throw new Error('Invalid snapshot'); snapshot = data; render(); }).catch(error => { console.error('Snapshot unavailable', error); failure = true; render(); }); } if (document.getElementById('method-chart')) { readJSON('./dataset-summary.json').then(data => { if (data.tasks !== 1000 || data.methods.reduce((n, x) => n + x.count, 0) !== data.tasks || data.journals.reduce((n, x) => n + x.count, 0) !== data.tasks) throw new Error('Invalid distribution summary'); summary = data; render(); }).catch(error => { console.error('Distribution unavailable', error); failure = true; render(); }); }