Kearm commited on
Commit
f878a0f
·
verified ·
1 Parent(s): 1f7e62f

Upload benchmark-chart.js with huggingface_hub

Browse files
Files changed (1) hide show
  1. benchmark-chart.js +18 -2
benchmark-chart.js CHANGED
@@ -9,7 +9,8 @@ class ResmpBenchmarkChart extends HTMLElement {
9
  render() {
10
  const cfg = this._config;
11
  if (!cfg) return;
12
- const all = cfg.groups.flatMap(g => g.panels.flatMap(p => Object.values(p.values)));
 
13
  const min = Math.min(0, ...all), max = Math.max(1, ...all);
14
  this.innerHTML = `<section class="resmp-chart">
15
  <header class="chart-head">
@@ -33,13 +34,28 @@ class ResmpBenchmarkChart extends HTMLElement {
33
  const gap = 7, barW = Math.min(36, (width-left-right-gap*(series.length-1))/series.length);
34
  const total = series.length * barW + (series.length - 1) * gap, start = (width - total) / 2;
35
  const bars = series.map((s, i) => {
36
- const v = Number(panel.values[s.id] ?? 0), yv = top + ((max - v) / (max - min)) * plotH;
 
 
 
 
 
37
  const y = Math.min(yv, zeroY), h = Math.max(1, Math.abs(zeroY - yv)), x = start + i * (barW + gap);
38
  const labelY = v >= 0 ? y - 5 : y + h + 11;
39
  return `<g><rect x="${x}" y="${y}" width="${barW}" height="${h}" fill="${this.escape(s.color)}"/><text x="${x+barW/2}" y="${labelY}" text-anchor="middle" class="value">${v.toFixed(2)}</text><text x="${x+barW/2}" y="${Math.min(y+h-7, zeroY-7)}" text-anchor="middle" class="series-code">${this.escape(s.id.slice(0,2).toUpperCase())}</text></g>`;
40
  }).join('');
41
  return `<figure><svg viewBox="0 0 ${width} ${height}" role="img" aria-label="${this.escape(panel.name)} benchmark"><line x1="${left}" y1="${zeroY}" x2="${width-right}" y2="${zeroY}" class="baseline"/>${bars}<text x="${width/2}" y="${height-8}" text-anchor="middle" class="panel-name">${this.escape(panel.name)}</text></svg></figure>`;
42
  }
 
 
 
 
 
 
 
 
 
 
43
  exportSvg() {
44
  const chart = this.querySelector('.resmp-chart').cloneNode(true); chart.querySelector('.chart-actions')?.remove();
45
  const css = [...document.styleSheets].flatMap(s => { try { return [...s.cssRules].map(r=>r.cssText) } catch { return [] } }).join('\n');
 
9
  render() {
10
  const cfg = this._config;
11
  if (!cfg) return;
12
+ this.validate(cfg);
13
+ const all = cfg.groups.flatMap(g => g.panels.flatMap(p => Object.values(p.values))).filter(Number.isFinite);
14
  const min = Math.min(0, ...all), max = Math.max(1, ...all);
15
  this.innerHTML = `<section class="resmp-chart">
16
  <header class="chart-head">
 
34
  const gap = 7, barW = Math.min(36, (width-left-right-gap*(series.length-1))/series.length);
35
  const total = series.length * barW + (series.length - 1) * gap, start = (width - total) / 2;
36
  const bars = series.map((s, i) => {
37
+ const raw = panel.values[s.id];
38
+ if (raw === null || raw === undefined || !Number.isFinite(Number(raw))) {
39
+ const x = start + i * (barW + gap);
40
+ return `<g><rect x="${x}" y="${top}" width="${barW}" height="${plotH}" fill="none" stroke="${this.escape(s.color)}" stroke-dasharray="3 3" opacity=".35"/><text x="${x+barW/2}" y="${zeroY-6}" text-anchor="middle" class="value">N/A</text></g>`;
41
+ }
42
+ const v = Number(raw), yv = top + ((max - v) / (max - min)) * plotH;
43
  const y = Math.min(yv, zeroY), h = Math.max(1, Math.abs(zeroY - yv)), x = start + i * (barW + gap);
44
  const labelY = v >= 0 ? y - 5 : y + h + 11;
45
  return `<g><rect x="${x}" y="${y}" width="${barW}" height="${h}" fill="${this.escape(s.color)}"/><text x="${x+barW/2}" y="${labelY}" text-anchor="middle" class="value">${v.toFixed(2)}</text><text x="${x+barW/2}" y="${Math.min(y+h-7, zeroY-7)}" text-anchor="middle" class="series-code">${this.escape(s.id.slice(0,2).toUpperCase())}</text></g>`;
46
  }).join('');
47
  return `<figure><svg viewBox="0 0 ${width} ${height}" role="img" aria-label="${this.escape(panel.name)} benchmark"><line x1="${left}" y1="${zeroY}" x2="${width-right}" y2="${zeroY}" class="baseline"/>${bars}<text x="${width/2}" y="${height-8}" text-anchor="middle" class="panel-name">${this.escape(panel.name)}</text></svg></figure>`;
48
  }
49
+ validate(cfg) {
50
+ if (!cfg || typeof cfg !== 'object') throw new TypeError('Benchmark config must be an object.');
51
+ if (!Array.isArray(cfg.series) || cfg.series.length < 1) throw new TypeError('Benchmark config requires at least one series.');
52
+ if (!Array.isArray(cfg.groups) || cfg.groups.length < 1) throw new TypeError('Benchmark config requires at least one group.');
53
+ const ids = cfg.series.map(s => s.id);
54
+ if (new Set(ids).size !== ids.length) throw new TypeError('Series IDs must be unique.');
55
+ for (const group of cfg.groups) {
56
+ if (!Array.isArray(group.panels) || group.panels.length < 1) throw new TypeError(`Group ${group.name || '(unnamed)'} requires panels.`);
57
+ }
58
+ }
59
  exportSvg() {
60
  const chart = this.querySelector('.resmp-chart').cloneNode(true); chart.querySelector('.chart-actions')?.remove();
61
  const css = [...document.styleSheets].flatMap(s => { try { return [...s.cssRules].map(r=>r.cssText) } catch { return [] } }).join('\n');