mirror of
https://github.com/multipleof4/lynchmark.git
synced 2026-01-14 00:27:55 +00:00
55 lines
1.4 KiB
JavaScript
55 lines
1.4 KiB
JavaScript
export async function createStreamVisualizer(stream, opts = {}) {
|
|
const {
|
|
maxPoints = 1000,
|
|
alpha = 0.2,
|
|
width = 800,
|
|
height = 300,
|
|
yDomain = [-1, 1]
|
|
} = opts;
|
|
|
|
if (alpha <= 0 || alpha >= 1 || !Number.isFinite(alpha))
|
|
throw new Error('alpha must be in (0,1)');
|
|
if (!Array.isArray(yDomain) || yDomain.length !== 2 || !yDomain.every(Number.isFinite))
|
|
throw new Error('yDomain must be a [min, max] pair of numbers');
|
|
|
|
const d3 = await import('https://cdn.jsdelivr.net/npm/d3@7/+esm');
|
|
|
|
const buf = [];
|
|
let prevEma = undefined;
|
|
|
|
for await (const p of stream) {
|
|
if (!p || !('timestamp' in p) || !('value' in p)) continue;
|
|
const v = Number(p.value);
|
|
if (!Number.isFinite(v)) continue;
|
|
|
|
if (prevEma === undefined) prevEma = v;
|
|
else prevEma = alpha * v + (1 - alpha) * prevEma;
|
|
|
|
buf.push({ timestamp: p.timestamp, value: v, ema: prevEma });
|
|
if (buf.length > maxPoints) buf.shift();
|
|
}
|
|
|
|
const data = buf;
|
|
let path = '';
|
|
|
|
if (data.length) {
|
|
const xs = d3.scaleLinear()
|
|
.domain([data[0].timestamp, data[data.length - 1].timestamp])
|
|
.range([0, width]);
|
|
|
|
const ys = d3.scaleLinear()
|
|
.domain(yDomain)
|
|
.range([height, 0]);
|
|
|
|
const line = d3.line()
|
|
.x(d => xs(d.timestamp))
|
|
.y(d => ys(d.ema));
|
|
|
|
path = line(data) || '';
|
|
}
|
|
|
|
return { data, path };
|
|
}
|
|
export default createStreamVisualizer;
|
|
// Generation time: 14.769s
|
|
// Result: PASS
|