Download leaderboard-history.js from AxiomicLabs/Open_SLM_Leaderboard: direct link, hf CLI and curl.
- Browser
- Download file 25.3 kB
-
https://huggingface.co/spaces/AxiomicLabs/Open_SLM_Leaderboard/resolve/main/leaderboard-history.js
- Command line
-
hf download hf://spaces/AxiomicLabs/Open_SLM_Leaderboard/leaderboard-history.js
-
curl -L -o leaderboard-history.js https://huggingface.co/spaces/AxiomicLabs/Open_SLM_Leaderboard/resolve/main/leaderboard-history.js
25.3 kB
| /* Charts are reconstructed from current model scores and stored addition dates. */ | |
| (() => { | |
| 'use strict'; | |
| const escapeHtml = value => String(value).replace(/[&<>"']/g, char => ({ | |
| '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' | |
| })[char]); | |
| const calendarTime = value => Date.parse(`${value}T00:00:00Z`); | |
| const dayLength = 86400000; | |
| const formatDate = (value, year = false) => new Intl.DateTimeFormat('en-AU', { | |
| day: 'numeric', month: 'short', ...(year ? { year: 'numeric' } : {}), timeZone: 'UTC' | |
| }).format(new Date(calendarTime(value))); | |
| const lastIncluded = value => new Date(calendarTime(value) - dayLength).toISOString().slice(0, 10); | |
| const lab = key => ORGS[key] || { name: key, chartBorder: '#c2b6ff', url: null }; | |
| function dateAxis(history, wrapperClass = '') { | |
| const start = calendarTime(history.start); | |
| const span = calendarTime(history.endExclusive) - start; | |
| const ticks = [{ value: history.start, label: formatDate(history.start) }]; | |
| const cursor = new Date(start); | |
| cursor.setUTCDate(1); | |
| cursor.setUTCMonth(cursor.getUTCMonth() + 1); | |
| while (cursor.getTime() < calendarTime(history.asOf)) { | |
| const fraction = (cursor.getTime() - start) / span; | |
| if (fraction > .12 && fraction < .88) { | |
| ticks.push({ value: cursor.toISOString().slice(0, 10), label: new Intl.DateTimeFormat('en-AU', { month: 'short', timeZone: 'UTC' }).format(cursor) }); | |
| } | |
| cursor.setUTCMonth(cursor.getUTCMonth() + 1); | |
| } | |
| ticks.push({ value: history.endExclusive, label: formatDate(history.asOf) }); | |
| return `<div class="history-date-axis ${wrapperClass}" aria-hidden="true">${ticks.map(tick => | |
| `<span class="history-tick" style="left:${(calendarTime(tick.value) - start) / span * 100}%">${escapeHtml(tick.label)}</span>` | |
| ).join('')}</div>`; | |
| } | |
| function categoryLegend(classes) { | |
| return `<div class="legend-bar history-legend" aria-label="Size category colors">${classes.map(category => | |
| `<span class="legend-item history-legend-item"><span class="legend-dot history-swatch" style="background:${category.color}"></span>${escapeHtml(category.key)}</span>` | |
| ).join('')}</div>`; | |
| } | |
| function organizationLegend(keys) { | |
| return `<div class="legend-bar history-legend" aria-label="Organization colors">${[...new Set(keys)].map(key => { | |
| const organization = lab(key); | |
| return `<span class="legend-item history-legend-item"><span class="legend-dot history-swatch" style="background:${escapeHtml(organization.chartBorder)}"></span>${escapeHtml(organization.name)}</span>`; | |
| }).join('')}</div>`; | |
| } | |
| function buildHistory() { | |
| const classes = [ | |
| { key: '<150M', limit: 150000000, color: '#2b65bd' }, | |
| { key: '<100M', limit: 100000000, color: '#f5d657' }, | |
| { key: '<50M', limit: 50000000, color: '#e984bf' }, | |
| { key: '<10M', limit: 10000000, color: '#4bc4ba' }, | |
| { key: '<3M', limit: 3000000, color: '#70d18b' } | |
| ]; | |
| const excluded = new Set(['facebook', 'huggingface', 'openai', 'google', 'microsoft']); | |
| const parts = new Intl.DateTimeFormat('en-AU', { | |
| timeZone: 'Australia/Sydney', year: 'numeric', month: '2-digit', day: '2-digit' | |
| }).formatToParts(new Date()); | |
| const today = Object.fromEntries(parts.map(part => [part.type, part.value])); | |
| const asOf = `${today.year}-${today.month}-${today.day}`; | |
| const endExclusive = new Date(calendarTime(asOf) + dayLength).toISOString().slice(0, 10); | |
| const entries = getModelEntries().map(model => ({ ...model, score: getIntelligenceIndex(model) })) | |
| .filter(model => !excluded.has(model.org) && Number.isFinite(model.score) && model.params > 0 && model.params < 150000000 | |
| && /^\d{4}-\d{2}-\d{2}$/.test(model.addedDate || '') && Number.isFinite(calendarTime(model.addedDate)) && model.addedDate <= asOf); | |
| const additionDates = [...new Set(entries.map(model => model.addedDate))].sort(); | |
| const reigns = []; | |
| const finish = (active, end) => { | |
| if (!active) return; | |
| active.endExclusive = end; | |
| active.days = Math.round((calendarTime(end) - calendarTime(active.start)) / dayLength); | |
| if (active.days > 0) reigns.push(active); | |
| }; | |
| classes.forEach(category => { | |
| let active = null; | |
| additionDates.forEach(day => { | |
| let winner = null, best = -Infinity; | |
| for (const model of entries) { | |
| if (model.params < category.limit && model.addedDate <= day && model.score > best) { | |
| winner = model; | |
| best = model.score; | |
| } | |
| } | |
| if (!winner) return; | |
| const identity = winner.links.card; | |
| if (active?.modelId === identity) return; | |
| finish(active, day); | |
| active = { modelId: identity, model: winner.name, org: winner.org, card: winner.links.card, | |
| params: winner.params, category: category.key, start: day }; | |
| }); | |
| finish(active, endExclusive); | |
| }); | |
| const totals = new Map(); | |
| reigns.forEach(reign => { | |
| if (!totals.has(reign.org)) totals.set(reign.org, { org: reign.org, categories: {}, days: 0 }); | |
| const row = totals.get(reign.org); | |
| row.categories[reign.category] = (row.categories[reign.category] || 0) + reign.days; | |
| row.days += reign.days; | |
| }); | |
| return { start: additionDates[0] || asOf, asOf, endExclusive, classes, reigns, | |
| labs: [...totals.values()].sort((a, b) => b.days - a.days || a.org.localeCompare(b.org)) }; | |
| } | |
| function currentModel(model) { | |
| const entries = getModelEntries(); | |
| const exact = entries.find(entry => entry.links?.card === model.card || (entry.org === model.org && entry.name === model.model)); | |
| if (exact) return exact; | |
| const sameName = entries.filter(entry => entry.name === model.model); | |
| return sameName.length === 1 ? sameName[0] : null; | |
| } | |
| function modelTotals(history) { | |
| const groups = new Map(); | |
| history.reigns.forEach(reign => { | |
| const identity = reign.modelId || reign.card; | |
| if (!groups.has(identity)) groups.set(identity, { model: reign.model, card: reign.card, org: reign.org, params: reign.params, categories: {}, reigns: [], days: 0 }); | |
| const group = groups.get(identity); | |
| group.categories[reign.category] = (group.categories[reign.category] || 0) + reign.days; | |
| group.days += reign.days; | |
| group.reigns.push(reign); | |
| }); | |
| for (const group of groups.values()) { | |
| group.longest = 0; | |
| history.classes.forEach(category => { | |
| const reigns = group.reigns.filter(reign => reign.category === category.key).sort((a, b) => a.start.localeCompare(b.start)); | |
| let streak = 0, end = null; | |
| reigns.forEach(reign => { | |
| streak = end === reign.start ? streak + reign.days : reign.days; | |
| end = reign.endExclusive; | |
| group.longest = Math.max(group.longest, streak); | |
| }); | |
| }); | |
| } | |
| return [...groups.values()].sort((a, b) => b.days - a.days || a.model.localeCompare(b.model)); | |
| } | |
| function renderFrontier(history) { | |
| const container = document.getElementById('history-frontier'); | |
| if (!container) return; | |
| if (typeof Chart === 'undefined') { | |
| container.innerHTML = '<p class="history-empty">The chart library could not load. Reload the page to view the frontier.</p>'; | |
| return; | |
| } | |
| const start = calendarTime(history.start); | |
| const offset = value => (calendarTime(value) - start) / dayLength; | |
| const end = offset(history.endExclusive); | |
| const datasets = history.classes.map((category, index) => { | |
| const reigns = history.reigns.filter(reign => reign.category === category.key) | |
| .sort((a, b) => a.start.localeCompare(b.start)); | |
| const data = []; | |
| reigns.forEach(reign => { | |
| const entry = currentModel(reign); | |
| const score = entry ? getIntelligenceIndex(entry) : null; | |
| if (!Number.isFinite(score)) return; | |
| const x = offset(reign.start); | |
| // Repeat the arrival's x coordinate to draw a vertical jump on that date. | |
| if (data.length) data.push({ ...data[data.length - 1], x, record: false }); | |
| data.push({ x, y: score, record: true, reign }); | |
| }); | |
| if (data.length) data.push({ ...data[data.length - 1], x: end, record: false }); | |
| return { | |
| label: category.key, data, borderColor: category.color, backgroundColor: category.color, | |
| borderWidth: 4, order: history.classes.length - index, | |
| borderJoinStyle: 'round', fill: false, tension: 0, | |
| segment: { | |
| borderColor: context => { | |
| const left = data[context.p0DataIndex]; | |
| const right = data[context.p1DataIndex]; | |
| // Plateaus belong to the preceding model; jumps to the new record. | |
| const owner = left.x === right.x ? right : left; | |
| return lab(owner.reign.org).chartBorder; | |
| } | |
| }, | |
| pointBackgroundColor: context => context.raw?.reign ? lab(context.raw.reign.org).chartBorder : category.color, | |
| pointRadius: context => context.raw?.record ? 6 : 0, | |
| pointHoverRadius: context => context.raw?.record ? 9 : 0, | |
| pointHitRadius: 10, pointBorderWidth: 1.5, | |
| pointBorderColor: getComputedStyle(container).getPropertyValue('--surface').trim() || '#141416' | |
| }; | |
| }); | |
| const summaries = datasets.filter(dataset => dataset.data.length).map(dataset => | |
| `${dataset.label}: ${dataset.data[dataset.data.length - 1].y.toFixed(2)} II` | |
| ).join('; '); | |
| container.innerHTML = `<div class="filter-group"><span class="filter-label">Size category</span><div class="filter-bar" aria-label="Show or hide frontier categories">${history.classes.map((category, index) => | |
| `<button type="button" class="filter-btn active history-frontier-toggle" data-frontier-category="${index}" aria-pressed="true" aria-label="${escapeHtml(category.key)} frontier">${escapeHtml(category.key)}</button>` | |
| ).join('')}</div></div>${organizationLegend(history.reigns.map(reign => reign.org))} | |
| <div class="history-frontier-plot"><canvas aria-label="Intelligence Index frontier by category, ${escapeHtml(formatDate(history.start, true))} to ${escapeHtml(formatDate(history.asOf, true))}. ${escapeHtml(summaries)}" role="img" aria-describedby="history-frontier-note">${escapeHtml(summaries)}</canvas></div>`; | |
| const styles = getComputedStyle(container); | |
| const muted = styles.getPropertyValue('--text-muted').trim(); | |
| const chart = new Chart(container.querySelector('canvas'), { | |
| type: 'line', data: { datasets }, | |
| options: { | |
| responsive: true, maintainAspectRatio: false, animation: false, | |
| interaction: { mode: 'nearest', intersect: true }, | |
| layout: { padding: { top: 12, right: 12 } }, | |
| plugins: { | |
| legend: { display: false }, | |
| tooltip: { | |
| ...getChartTooltipOptions(), | |
| filter: item => item.raw.record, | |
| callbacks: { | |
| title: items => items[0]?.raw.reign?.model || '', | |
| label: item => { | |
| const reign = item.raw.reign; | |
| return [ | |
| `${lab(reign.org).name} · ${reign.category}`, | |
| `Intelligence Index: ${item.raw.y.toFixed(2)}`, | |
| `Lead began: ${formatDate(reign.start, true)}`, | |
| `Time at #1: ${reign.days} ${reign.days === 1 ? 'day' : 'days'}`, | |
| `Parameters: ${new Intl.NumberFormat('en-AU', { maximumFractionDigits: 2 }).format(reign.params / 1e6)}M` | |
| ]; | |
| } | |
| } | |
| } | |
| }, | |
| scales: { | |
| x: { | |
| type: 'linear', min: 0, max: end, | |
| afterBuildTicks: scale => { | |
| const ticks = [{ value: 0 }]; | |
| const cursor = new Date(start); | |
| cursor.setUTCDate(1); | |
| cursor.setUTCMonth(cursor.getUTCMonth() + 1); | |
| while (cursor.getTime() < calendarTime(history.asOf)) { | |
| const value = (cursor.getTime() - start) / dayLength; | |
| if (value > end * .12 && value < end * .88) ticks.push({ value }); | |
| cursor.setUTCMonth(cursor.getUTCMonth() + 1); | |
| } | |
| ticks.push({ value: end }); | |
| scale.ticks = ticks; | |
| }, | |
| ticks: { | |
| color: muted, maxRotation: 0, autoSkip: true, maxTicksLimit: 7, | |
| font: { family: "'Space Mono', monospace", size: 10 }, | |
| callback: value => { | |
| if (value === 0) return formatDate(history.start); | |
| if (value === end) return formatDate(history.asOf); | |
| return new Intl.DateTimeFormat('en-AU', { month: 'short', timeZone: 'UTC' }).format(new Date(start + value * dayLength)); | |
| } | |
| }, | |
| grid: { display: false }, border: { display: false } | |
| }, | |
| y: { | |
| grace: '8%', | |
| title: { display: true, text: 'Intelligence Index', color: muted, font: { family: "'Space Mono', monospace", size: 10 } }, | |
| ticks: { color: muted, maxTicksLimit: 6, font: { family: "'Space Mono', monospace", size: 10 } }, | |
| grid: { color: 'rgba(255,255,255,0.03)' }, border: { display: false } | |
| } | |
| } | |
| } | |
| }); | |
| container.addEventListener('click', event => { | |
| const button = event.target.closest('[data-frontier-category]'); | |
| if (!button) return; | |
| const visible = button.getAttribute('aria-pressed') !== 'true'; | |
| chart.data.datasets[Number(button.dataset.frontierCategory)].hidden = !visible; | |
| button.setAttribute('aria-pressed', String(visible)); | |
| button.classList.toggle('active', visible); | |
| chart.update(); | |
| }); | |
| } | |
| function installHistoryTooltip(section, history, models) { | |
| const tooltip = document.createElement('div'); | |
| tooltip.id = 'history-tooltip'; | |
| tooltip.className = 'history-tooltip'; | |
| tooltip.setAttribute('role', 'tooltip'); | |
| tooltip.hidden = true; | |
| document.body.append(tooltip); | |
| let active = null; | |
| const selector = '[data-history-reign], [data-history-model], [data-history-lab]'; | |
| const targetFor = element => element?.closest?.(selector); | |
| const number = value => new Intl.NumberFormat('en-AU', { maximumFractionDigits: 2 }).format(value); | |
| const parameters = value => value >= 1e6 ? `${number(value / 1e6)}M` : value >= 1e3 ? `${number(value / 1e3)}K` : number(value); | |
| const detailRows = rows => `<dl>${rows.filter(([, value]) => value !== null && value !== undefined).map(([name, value]) => `<dt>${escapeHtml(name)}</dt><dd>${escapeHtml(value)}</dd>`).join('')}</dl>`; | |
| const currentII = model => { | |
| const entry = currentModel(model); | |
| const score = entry ? getIntelligenceIndex(entry) : null; | |
| return Number.isFinite(score) ? score.toFixed(2) : null; | |
| }; | |
| function content(target) { | |
| if (target.dataset.historyReign !== undefined) { | |
| const reign = history.reigns[Number(target.dataset.historyReign)]; | |
| if (!reign) return ''; | |
| return `<strong class="history-tooltip-name">${escapeHtml(reign.model)}</strong><span class="history-tooltip-sub">${escapeHtml(lab(reign.org).name)} · ${escapeHtml(reign.category)}</span>${detailRows([ | |
| ['Time at #1', `${reign.days} ${reign.days === 1 ? 'day' : 'days'}`], | |
| ['Reign', `${formatDate(reign.start)} – ${formatDate(lastIncluded(reign.endExclusive), true)}`], | |
| ['Parameters', Number.isFinite(reign.params) ? parameters(reign.params) : null], | |
| ['Current II', currentII(reign)] | |
| ])}`; | |
| } | |
| if (target.dataset.historyModel !== undefined) { | |
| const model = models[Number(target.dataset.historyModel)]; | |
| if (!model) return ''; | |
| const category = target.dataset.historyCategory; | |
| const organizationNames = [...new Set(model.reigns.map(reign => lab(reign.org).name))].join(' / '); | |
| const entry = currentModel(model); | |
| const params = entry?.params ?? model.params; | |
| return `<strong class="history-tooltip-name">${escapeHtml(model.model)}</strong><span class="history-tooltip-sub">${escapeHtml(organizationNames)}</span>${detailRows([ | |
| ['Total #1 time', `${model.days} class-days`], | |
| ['Longest streak', `${model.longest} days`], | |
| ...(category ? [[category, `${model.categories[category]} days`]] : history.classes.filter(item => model.categories[item.key]).map(item => [item.key, `${model.categories[item.key]} days`])), | |
| ['Parameters', Number.isFinite(params) ? parameters(params) : null], | |
| ['Current II', currentII(model)] | |
| ])}`; | |
| } | |
| const organization = target.dataset.historyLab; | |
| const row = history.labs.find(item => item.org === organization); | |
| if (!row) return ''; | |
| const category = target.dataset.historyCategory; | |
| return `<strong class="history-tooltip-name">${escapeHtml(lab(organization).name)}</strong><span class="history-tooltip-sub">Time at #1 across size categories</span>${detailRows([ | |
| ['Total #1 time', `${row.days} class-days`], | |
| ...(category ? [[category, `${row.categories[category]} days`]] : history.classes.filter(item => row.categories[item.key]).map(item => [item.key, `${row.categories[item.key]} days`])) | |
| ])}`; | |
| } | |
| function position(target, event) { | |
| const bounds = target.getBoundingClientRect(); | |
| const pointer = event && Number.isFinite(event.clientX); | |
| const x = pointer ? event.clientX : bounds.left + Math.min(bounds.width / 2, 100); | |
| const y = pointer ? event.clientY : bounds.bottom; | |
| const width = tooltip.offsetWidth, height = tooltip.offsetHeight; | |
| const left = Math.max(12, Math.min(x + 16, window.innerWidth - width - 12)); | |
| let top = y + 16; | |
| if (top + height > window.innerHeight - 12) top = y - height - 16; | |
| tooltip.style.left = `${left}px`; | |
| tooltip.style.top = `${Math.max(12, top)}px`; | |
| } | |
| function hide() { | |
| active?.removeAttribute('aria-describedby'); | |
| active = null; | |
| tooltip.hidden = true; | |
| } | |
| function show(target, event) { | |
| if (active !== target) { | |
| const markup = content(target); | |
| if (!markup) return; | |
| active?.removeAttribute('aria-describedby'); | |
| active = target; | |
| tooltip.innerHTML = markup; | |
| target.setAttribute('aria-describedby', tooltip.id); | |
| tooltip.hidden = false; | |
| } | |
| position(target, event); | |
| } | |
| section.addEventListener('pointerover', event => { | |
| const target = targetFor(event.target); | |
| if (target) show(target, event); | |
| }); | |
| section.addEventListener('pointermove', event => { | |
| if (active && active.contains(event.target)) position(active, event); | |
| }); | |
| section.addEventListener('pointerout', event => { | |
| const target = targetFor(event.target); | |
| if (target && target === active && !target.contains(event.relatedTarget) && !target.contains(document.activeElement)) hide(); | |
| }); | |
| section.addEventListener('focusin', event => { | |
| const target = targetFor(event.target); | |
| if (target) show(target); | |
| }); | |
| section.addEventListener('focusout', event => { | |
| if (active && !active.contains(event.relatedTarget) && !active.matches(':hover')) hide(); | |
| }); | |
| document.addEventListener('keydown', event => { if (event.key === 'Escape') hide(); }); | |
| document.addEventListener('scroll', hide, true); | |
| window.addEventListener('resize', hide); | |
| } | |
| function renderHistory() { | |
| const section = document.getElementById('org-performance'); | |
| const history = buildHistory(); | |
| if (!section) return; | |
| if (!history || !history.reigns.length) { | |
| document.getElementById('history-dominance').innerHTML = '<p class="history-empty">History data is unavailable.</p>'; | |
| return; | |
| } | |
| document.getElementById('history-period').textContent = | |
| `Indie model leads across five size categories, ${formatDate(history.start, true)} – ${formatDate(history.asOf, true)}.`; | |
| renderFrontier(history); | |
| const start = calendarTime(history.start); | |
| const span = calendarTime(history.endExclusive) - start; | |
| const position = reign => ({ | |
| left: (calendarTime(reign.start) - start) / span * 100, | |
| width: (calendarTime(reign.endExclusive) - calendarTime(reign.start)) / span * 100 | |
| }); | |
| const reignTitle = reign => `${reign.model} · ${lab(reign.org).name} · ${reign.category}: ${reign.days} ${reign.days === 1 ? 'day' : 'days'}, ${formatDate(reign.start, true)} – ${formatDate(lastIncluded(reign.endExclusive), true)}`; | |
| const dominance = history.classes.map(category => { | |
| const reigns = history.reigns.filter(reign => reign.category === category.key); | |
| return `<div class="history-dominance-row"> | |
| <span class="history-category-label">${escapeHtml(category.key)}</span> | |
| <div class="history-dominance-track" role="group" aria-label="${escapeHtml(category.key)} leadership over time">${reigns.map(reign => { | |
| const { left, width } = position(reign); | |
| const organization = lab(reign.org); | |
| const description = escapeHtml(reignTitle(reign)); | |
| return `<a class="history-dominance-segment${width >= 8 ? ' has-label' : ''}" data-history-reign="${history.reigns.indexOf(reign)}" href="${escapeHtml(reign.card)}" target="_blank" rel="noopener noreferrer" aria-label="${description}" style="left:${left}%;width:max(1px, calc(${width}% - 1px));--org-color:${escapeHtml(organization.chartBorder)}"> | |
| ${width >= 8 ? `<span class="history-segment-model">${escapeHtml(reign.model)}</span>` : ''} | |
| </a>`; | |
| }).join('')}</div> | |
| </div>`; | |
| }).join(''); | |
| const labLegend = organizationLegend(history.labs.slice(0, 10).map(row => row.org)); | |
| document.getElementById('history-dominance').innerHTML = `<div class="history-dominance-rows">${dominance}</div>` + dateAxis(history, 'history-timeline-axis') + labLegend; | |
| const labs = history.labs.slice(0, 10); | |
| const maxDays = Math.ceil(labs[0].days / 50) * 50; | |
| const labChart = labs.map(row => { | |
| const organization = lab(row.org); | |
| return `<div class="history-lab-row"> | |
| ${organization.url ? `<a class="history-lab-label" data-history-lab="${escapeHtml(row.org)}" href="${escapeHtml(organization.url)}" target="_blank" rel="noopener noreferrer">${escapeHtml(organization.name)}</a>` : `<span class="history-lab-label" data-history-lab="${escapeHtml(row.org)}">${escapeHtml(organization.name)}</span>`} | |
| <div class="history-lab-track" role="group" aria-label="${escapeHtml(organization.name)}: ${row.days} class-days">${history.classes.map(category => { | |
| const days = row.categories[category.key] || 0; | |
| if (!days) return ''; | |
| const description = `${organization.name} · ${category.key}: ${days} days`; | |
| return `<span class="history-lab-segment" data-history-lab="${escapeHtml(row.org)}" data-history-category="${escapeHtml(category.key)}" tabindex="0" role="img" aria-label="${escapeHtml(description)}" style="width:${days / maxDays * 100}%;--history-bar-color:${category.color}"></span>`; | |
| }).join('')}<span class="history-day-total history-lab-total" style="left:${row.days / maxDays * 100}%">${row.days}d</span></div> | |
| </div>`; | |
| }).join(''); | |
| const labAxis = `<div class="history-date-axis history-lab-axis" aria-hidden="true">${[0, .2, .4, .6, .8, 1].map(fraction => | |
| `<span class="history-tick" style="left:${fraction * 100}%">${Math.round(maxDays * fraction)}</span>` | |
| ).join('')}</div>`; | |
| document.getElementById('history-labs').innerHTML = labChart + labAxis + categoryLegend(history.classes); | |
| const models = modelTotals(history).slice(0, 10); | |
| const maxModelDays = Math.ceil(models[0].days / 10) * 10; | |
| const modelChart = models.map((model, index) => { | |
| const entry = currentModel(model); | |
| return `<div class="history-model-row"> | |
| <a class="history-model-label" data-history-model="${index}" href="${escapeHtml(entry?.links.card || model.card)}" target="_blank" rel="noopener noreferrer">${escapeHtml(model.model)}</a> | |
| <div class="history-model-bar-row"><div class="history-model-track" role="group" aria-label="${escapeHtml(model.model)}: ${model.days} class-days"><span class="history-model-segment" data-history-model="${index}" tabindex="0" role="img" aria-label="${escapeHtml(model.model)}: ${model.days} class-days" style="width:${model.days / maxModelDays * 100}%;--history-bar-color:${escapeHtml(lab(model.org).chartBorder)}"></span><span class="history-day-total history-lab-total" style="left:${model.days / maxModelDays * 100}%">${model.days}d</span></div></div> | |
| </div>`; | |
| }).join(''); | |
| const modelAxis = `<div class="history-date-axis history-model-axis" aria-hidden="true">${[0, .2, .4, .6, .8, 1].map(fraction => `<span class="history-tick" style="left:${fraction * 100}%">${Math.round(maxModelDays * fraction)}</span>`).join('')}</div>`; | |
| document.getElementById('history-models').innerHTML = modelChart + modelAxis + organizationLegend(models.map(model => model.org)); | |
| installHistoryTooltip(section, history, models); | |
| } | |
| if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', renderHistory); | |
| else renderHistory(); | |
| })(); | |