// ===== State =====
let allResults = [];
let activeFilter = 'all';
let searchQuery = '';
// ===== DOM Elements =====
const searchInput = document.getElementById('searchInput');
const filterButtons = document.querySelectorAll('.filter-btn');
const resultsContainer = document.getElementById('resultsContainer');
const resultsInfo = document.getElementById('resultsInfo');
// ===== Init =====
document.addEventListener('DOMContentLoaded', () => {
loadBenchmarkData();
loadSubtitle();
bindEvents();
});
function bindEvents() {
searchInput.addEventListener('input', (e) => {
searchQuery = e.target.value.toLowerCase().trim();
render();
});
filterButtons.forEach(btn => {
btn.addEventListener('click', () => {
setActiveFilter(btn.dataset.filter);
});
});
// Stat card shortcuts
document.querySelectorAll('.stat-card[data-filter]').forEach(card => {
card.addEventListener('click', () => {
setActiveFilter(card.dataset.filter);
});
});
}
function setActiveFilter(filter) {
activeFilter = filter;
filterButtons.forEach(b => {
b.classList.toggle('active', b.dataset.filter === filter);
});
render();
}
// ===== Subtitle =====
async function loadSubtitle() {
const el = document.getElementById('subtitleText');
try {
const res = await fetch('data/subtitle.md');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const text = await res.text();
el.innerHTML = renderLightMd(text.trim()) || 'Compare model performance across tests';
} catch {
el.textContent = 'Compare model performance across tests';
}
}
function renderLightMd(md) {
return md
.split(/\n\n+/)
.map(block =>
'
' + block
.replace(/\*\*(.+?)\*\*/g, '$1')
.replace(/\*(.+?)\*/g, '$1')
.replace(/ \n/g, '
')
.replace(/\n/g, '
') +
'
'
)
.join('');
}
// ===== Data Loading =====
async function loadBenchmarkData() {
try {
const response = await fetch('data/benchmark.md');
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const mdText = await response.text();
allResults = parseMarkdownTable(mdText);
updateStats();
render();
} catch (err) {
resultsContainer.innerHTML = `
Failed to load benchmark data
${escapeHtml(err.message)}
`;
}
}
// ===== MD Parser =====
function parseMarkdownTable(md) {
const lines = md.split('\n').filter(line => line.trim().startsWith('|'));
if (lines.length < 2) return [];
// Parse header
const headers = parseRow(lines[0]).map(h => h.trim().toLowerCase());
// Skip separator row (line index 1), parse data rows
const results = [];
for (let i = 2; i < lines.length; i++) {
const cells = parseRow(lines[i]);
if (cells.length === 0) continue;
const entry = {};
headers.forEach((header, idx) => {
entry[header] = (cells[idx] || '').trim();
});
// Normalize score
const rawScore = (entry.score || '').toLowerCase().trim();
if (rawScore === 'fail' || rawScore === 'failed' || rawScore === 'f') {
entry.scoreKey = 'fail';
entry.scoreLabel = 'FAIL';
entry.scoreNumeric = -1;
} else {
const num = parseInt(rawScore, 10);
if (isNaN(num)) continue; // skip invalid rows
entry.scoreKey = String(Math.min(Math.max(num, 0), 3));
entry.scoreLabel = String(num);
entry.scoreNumeric = num;
}
results.push(entry);
}
return results;
}
function parseRow(line) {
const parts = line.split('|');
if (parts.length > 1) {
parts.pop();
parts.shift();
}
return parts;
}
// ===== Stats =====
function updateStats() {
const total = allResults.length;
const scored = allResults.filter(r => r.scoreNumeric >= 0);
const avg = scored.length > 0
? (scored.reduce((sum, r) => sum + r.scoreNumeric, 0) / scored.length).toFixed(2)
: '—';
const fails = allResults.filter(r => r.scoreKey === 'fail').length;
const perfect = allResults.filter(r => r.scoreNumeric === 3).length;
const passRate = total > 0
? Math.round((scored.length / total) * 100) + '%'
: '—';
document.getElementById('statTotal').textContent = total;
document.getElementById('statAvg').textContent = avg;
document.getElementById('statPerfect').textContent = perfect;
document.getElementById('statFails').textContent = fails;
document.getElementById('statPass').textContent = passRate;
}
// ===== Filtering =====
function getFilteredResults() {
return allResults.filter(entry => {
// Score filter
if (activeFilter !== 'all' && entry.scoreKey !== activeFilter) return false;
// Search filter
if (searchQuery) {
const haystack = [
entry.model || '',
entry.notes || '',
entry.scoreLabel || ''
].join(' ').toLowerCase();
if (!haystack.includes(searchQuery)) return false;
}
return true;
});
}
// ===== Rendering =====
function render() {
const filtered = getFilteredResults();
// Update results info
resultsInfo.textContent = `Showing ${filtered.length} of ${allResults.length} models`;
if (filtered.length === 0) {
resultsContainer.innerHTML = `
No results match your filters
`;
return;
}
const html = `${filtered.map(renderRow).join('')}
`;
resultsContainer.innerHTML = html;
}
function renderRow(entry) {
const scoreClass = entry.scoreKey === 'fail' ? 'score-fail' : `score-${entry.scoreKey}`;
const scoreLabel = entry.scoreKey === 'fail' ? 'FAIL' : entry.scoreLabel;
const notes = entry.notes ? escapeHtml(entry.notes) : '';
const nameDisplay = notes
? `${escapeHtml(entry.model || 'Unknown')} (${notes})`
: escapeHtml(entry.model || 'Unknown');
return `
${scoreLabel}
${nameDisplay}
`;
}
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}