Spaces:
Running
Running
thibaud frere
commited on
Commit
·
03cd478
1
Parent(s):
cb92d91
update
Browse files
app/src/components/ThemeToggle.astro
CHANGED
@@ -1,18 +1,16 @@
|
|
1 |
<button id="theme-toggle" aria-label="Toggle color theme">
|
2 |
-
<svg class="icon light" width="20" height="20" viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">
|
3 |
-
<circle cx="12" cy="12" r="5"
|
4 |
-
<
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
<line x1="17.66" y1="6.34" x2="19.78" y2="4.22"/>
|
13 |
-
</g>
|
14 |
</svg>
|
15 |
-
<svg class="icon dark" width="20" height="20" viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">
|
16 |
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
|
17 |
</svg>
|
18 |
<script>
|
@@ -35,11 +33,13 @@
|
|
35 |
else if (media.addListener) media.addListener(syncWithSystem);
|
36 |
}
|
37 |
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
|
|
|
|
43 |
</script>
|
44 |
</button>
|
45 |
|
|
|
1 |
<button id="theme-toggle" aria-label="Toggle color theme">
|
2 |
+
<svg class="icon light" width="20" height="20" viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
3 |
+
<circle cx="12" cy="12" r="5"></circle>
|
4 |
+
<line x1="12" y1="1" x2="12" y2="4"></line>
|
5 |
+
<line x1="12" y1="20" x2="12" y2="23"></line>
|
6 |
+
<line x1="1" y1="12" x2="4" y2="12"></line>
|
7 |
+
<line x1="20" y1="12" x2="23" y2="12"></line>
|
8 |
+
<line x1="4.22" y1="4.22" x2="6.34" y2="6.34"></line>
|
9 |
+
<line x1="17.66" y1="17.66" x2="19.78" y2="19.78"></line>
|
10 |
+
<line x1="4.22" y1="19.78" x2="6.34" y2="17.66"></line>
|
11 |
+
<line x1="17.66" y1="6.34" x2="19.78" y2="4.22"></line>
|
|
|
|
|
12 |
</svg>
|
13 |
+
<svg class="icon dark" width="20" height="20" viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
14 |
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
|
15 |
</svg>
|
16 |
<script>
|
|
|
33 |
else if (media.addListener) media.addListener(syncWithSystem);
|
34 |
}
|
35 |
|
36 |
+
if (btn) {
|
37 |
+
btn.addEventListener('click', () => {
|
38 |
+
const next = (document.documentElement.dataset.theme === 'dark') ? 'light' : 'dark';
|
39 |
+
localStorage.setItem('theme', next);
|
40 |
+
apply(next);
|
41 |
+
});
|
42 |
+
}
|
43 |
</script>
|
44 |
</button>
|
45 |
|
app/src/content/assets/data/against_baselines.csv
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
-
size
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:85f900011d0ea9cd2e0326e2d5bf40b74e90e696901b8fd9283dd802aa0bdbe1
|
3 |
+
size 37017
|
app/src/content/embeds/d3-line.html
CHANGED
@@ -156,6 +156,7 @@
|
|
156 |
const gGrid = gRoot.append('g').attr('class', 'grid');
|
157 |
const gAxes = gRoot.append('g').attr('class', 'axes');
|
158 |
const gLines = gRoot.append('g').attr('class', 'lines');
|
|
|
159 |
const gHover = gRoot.append('g').attr('class', 'hover');
|
160 |
const gLegend = gRoot.append('foreignObject').attr('class', 'legend');
|
161 |
|
@@ -197,11 +198,15 @@
|
|
197 |
let xScale = d3.scaleLinear();
|
198 |
let yScale = d3.scaleLinear();
|
199 |
|
200 |
-
// Line
|
201 |
-
const
|
202 |
.curve(d3.curveCatmullRom.alpha(0.05))
|
203 |
.x((d) => xScale(d.step))
|
204 |
.y((d) => yScale(d.value));
|
|
|
|
|
|
|
|
|
205 |
|
206 |
// Hover elements
|
207 |
const hoverLine = gHover.append('line').attr('stroke-width', 1);
|
@@ -327,15 +332,33 @@
|
|
327 |
// Bind lines
|
328 |
const series = runs.map((r, i) => ({ run: r, color: pool[i % pool.length], values: (map[r]||[]).slice().sort((a,b)=>a.step-b.step) }));
|
329 |
const paths = gLines.selectAll('path.run-line').data(series, d=>d.run);
|
|
|
330 |
paths.enter().append('path').attr('class','run-line').attr('fill','none').attr('stroke-width',2)
|
331 |
.attr('stroke', d=>d.color).attr('opacity',0.9)
|
332 |
-
.attr('d', d=>
|
333 |
.merge(paths)
|
334 |
.transition().duration(200)
|
335 |
.attr('stroke', d=>d.color)
|
336 |
-
.attr('d', d=>
|
337 |
paths.exit().remove();
|
338 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
339 |
// Inline legend content (row, right side) compact
|
340 |
legendInline.innerHTML = series.map(s => `<span style="display:inline-flex;align-items:center;gap:6px;white-space:nowrap;"><span style="width:18px;height:10px;background:${s.color};border-radius:3px;display:inline-block"></span><span>${s.run}</span></span>`).join('');
|
341 |
|
@@ -353,7 +376,10 @@
|
|
353 |
series.forEach(s=>{
|
354 |
const m = new Map(s.values.map(v=>[v.step, v.value]));
|
355 |
const val = m.has(nearest) ? m.get(nearest) : null;
|
356 |
-
if (val != null)
|
|
|
|
|
|
|
357 |
});
|
358 |
tipInner.innerHTML = html;
|
359 |
const offsetX = 12, offsetY = 12;
|
|
|
156 |
const gGrid = gRoot.append('g').attr('class', 'grid');
|
157 |
const gAxes = gRoot.append('g').attr('class', 'axes');
|
158 |
const gLines = gRoot.append('g').attr('class', 'lines');
|
159 |
+
const gPoints = gRoot.append('g').attr('class', 'points');
|
160 |
const gHover = gRoot.append('g').attr('class', 'hover');
|
161 |
const gLegend = gRoot.append('foreignObject').attr('class', 'legend');
|
162 |
|
|
|
198 |
let xScale = d3.scaleLinear();
|
199 |
let yScale = d3.scaleLinear();
|
200 |
|
201 |
+
// Line generators
|
202 |
+
const lineGenSmooth = d3.line()
|
203 |
.curve(d3.curveCatmullRom.alpha(0.05))
|
204 |
.x((d) => xScale(d.step))
|
205 |
.y((d) => yScale(d.value));
|
206 |
+
const lineGenStep = d3.line()
|
207 |
+
.curve(d3.curveStepAfter)
|
208 |
+
.x((d) => xScale(d.step))
|
209 |
+
.y((d) => yScale(d.value));
|
210 |
|
211 |
// Hover elements
|
212 |
const hoverLine = gHover.append('line').attr('stroke-width', 1);
|
|
|
332 |
// Bind lines
|
333 |
const series = runs.map((r, i) => ({ run: r, color: pool[i % pool.length], values: (map[r]||[]).slice().sort((a,b)=>a.step-b.step) }));
|
334 |
const paths = gLines.selectAll('path.run-line').data(series, d=>d.run);
|
335 |
+
const gen = isRank ? lineGenStep : lineGenSmooth;
|
336 |
paths.enter().append('path').attr('class','run-line').attr('fill','none').attr('stroke-width',2)
|
337 |
.attr('stroke', d=>d.color).attr('opacity',0.9)
|
338 |
+
.attr('d', d=>gen(d.values))
|
339 |
.merge(paths)
|
340 |
.transition().duration(200)
|
341 |
.attr('stroke', d=>d.color)
|
342 |
+
.attr('d', d=>gen(d.values));
|
343 |
paths.exit().remove();
|
344 |
|
345 |
+
// Points for rank metrics (discrete steps)
|
346 |
+
if (isRank) {
|
347 |
+
const pointData = series.flatMap(s => s.values.map(v => ({ run: s.run, color: s.color, step: v.step, value: v.value })));
|
348 |
+
const circles = gPoints.selectAll('circle.point').data(pointData, d => d.run + '-' + d.step);
|
349 |
+
circles.enter().append('circle').attr('class', 'point')
|
350 |
+
.attr('r', 2.5)
|
351 |
+
.attr('fill', d => d.color)
|
352 |
+
.attr('cx', d => xScale(d.step))
|
353 |
+
.attr('cy', d => yScale(d.value))
|
354 |
+
.merge(circles)
|
355 |
+
.attr('cx', d => xScale(d.step))
|
356 |
+
.attr('cy', d => yScale(d.value));
|
357 |
+
circles.exit().remove();
|
358 |
+
} else {
|
359 |
+
gPoints.selectAll('*').remove();
|
360 |
+
}
|
361 |
+
|
362 |
// Inline legend content (row, right side) compact
|
363 |
legendInline.innerHTML = series.map(s => `<span style="display:inline-flex;align-items:center;gap:6px;white-space:nowrap;"><span style="width:18px;height:10px;background:${s.color};border-radius:3px;display:inline-block"></span><span>${s.run}</span></span>`).join('');
|
364 |
|
|
|
376 |
series.forEach(s=>{
|
377 |
const m = new Map(s.values.map(v=>[v.step, v.value]));
|
378 |
const val = m.has(nearest) ? m.get(nearest) : null;
|
379 |
+
if (val != null) {
|
380 |
+
const formatVal = (vv) => (isRank ? d3.format('d')(vv) : (+vv).toFixed(4));
|
381 |
+
html += `<div><span style=\"display:inline-block;width:10px;height:10px;background:${s.color};border-radius:50%;margin-right:6px;\"></span><strong>${s.run}</strong> ${formatVal(val)}</div>`;
|
382 |
+
}
|
383 |
});
|
384 |
tipInner.innerHTML = html;
|
385 |
const offsetX = 12, offsetY = 12;
|
app/src/content/embeds/d3-pie.html
CHANGED
@@ -6,7 +6,7 @@
|
|
6 |
.d3-pie .legend .swatch { width:14px; height:14px; border-radius:3px; display:inline-block; border: 1px solid var(--border-color); }
|
7 |
.d3-pie .caption { font-size: 14px; font-weight: 800; fill: var(--text-color); }
|
8 |
.d3-pie .nodata { font-size: 12px; fill: var(--muted-color); }
|
9 |
-
.d3-pie .slice-label { font-size: 11px; font-weight: 700; fill: var(--text-color); paint-order: stroke; stroke: rgba(255,255,255,0.
|
10 |
</style>
|
11 |
<script>
|
12 |
(() => {
|
|
|
6 |
.d3-pie .legend .swatch { width:14px; height:14px; border-radius:3px; display:inline-block; border: 1px solid var(--border-color); }
|
7 |
.d3-pie .caption { font-size: 14px; font-weight: 800; fill: var(--text-color); }
|
8 |
.d3-pie .nodata { font-size: 12px; fill: var(--muted-color); }
|
9 |
+
.d3-pie .slice-label { font-size: 11px; font-weight: 700; fill: var(--text-color); paint-order: stroke; stroke: rgba(255,255,255,0.2); stroke-width: 3px; }
|
10 |
</style>
|
11 |
<script>
|
12 |
(() => {
|