Compare commits

...

4 Commits

Author SHA1 Message Date
github-actions[bot]
c263572691 Docs: Update benchmark for moonshotai/kimi-k2.7-code 2026-06-19 23:28:58 +00:00
49dadb5155 Feat: Add OpenRouter leaderboard headers
Co-authored-by: gemini-3.5-flash <gemini@google.com>
2026-06-19 16:14:45 -07:00
github-actions[bot]
d4ae079fea Docs: Update benchmark for z-ai/glm-5.2 2026-06-19 23:14:20 +00:00
3cd4fa5ca6 Update README 2026-06-19 16:05:26 -07:00
26 changed files with 711 additions and 1 deletions

2
README
View File

@@ -9,6 +9,8 @@ SHARED_PROMPT: "Provide production-ready and maintainable JavaScript code. Apply
The following models are included in the benchmark run. The following models are included in the benchmark run.
<!-- MODELS_START --> <!-- MODELS_START -->
z-ai/glm-5.2
moonshotai/kimi-k2.7-code
anthropic/claude-fable-5 anthropic/claude-fable-5
anthropic/claude-opus-4.8 EFF:medium anthropic/claude-opus-4.8 EFF:medium
google/gemini-3.5-flash google/gemini-3.5-flash

View File

@@ -26,7 +26,13 @@ const apiCall = async (prompt, model, temp, effort) => {
...(temp !== undefined && { temperature: temp }), ...(temp !== undefined && { temperature: temp }),
...(effort && { reasoning: { effort } }) ...(effort && { reasoning: { effort } })
}, },
{ headers: { Authorization: `Bearer ${process.env.OPENROUTER_KEY}` } } {
headers: {
Authorization: `Bearer ${process.env.OPENROUTER_KEY}`,
'HTTP-Referer': 'https://lynchmark.com',
'X-Title': 'Lynchmark'
}
}
); );
if (!res.data.choices || !res.data.choices[0]) { if (!res.data.choices || !res.data.choices[0]) {
console.error('API Response:', JSON.stringify(res.data, null, 2)); console.error('API Response:', JSON.stringify(res.data, null, 2));

View File

@@ -0,0 +1,9 @@
const hashPassword = async (password, salt) => {
const { default: scrypt } = await import('https://esm.sh/scrypt-js');
const enc = new TextEncoder();
const hash = await scrypt(enc.encode(password), enc.encode(salt), 1024, 8, 1, 32);
return Array.from(hash, b => b.toString(16).padStart(2, '0')).join('');
};
export default hashPassword;
// Generation time: 16.829s
// Result: FAIL

View File

@@ -0,0 +1,9 @@
const hashPassword = async (password, salt) => {
const scrypt = (await import('https://esm.sh/scrypt-js')).default;
const enc = new TextEncoder();
const hash = await scrypt(enc.encode(password), enc.encode(salt), 1024, 8, 1, 32);
return [...hash].map(b => b.toString(16).padStart(2, '0')).join('');
};
export default hashPassword;
// Generation time: 21.621s
// Result: FAIL

View File

@@ -0,0 +1,17 @@
const analyzeGPS = async (readings, boundary) => {
const turf = await import('https://esm.sh/@turf/turf@7.2.0');
const valid = readings
.filter(r => turf.booleanPointInPolygon(r.loc, boundary, { ignoreBoundary: true }))
.sort((a, b) => a.ts - b.ts);
if (valid.length < 2) return 0;
const path = turf.lineString(valid.map(r => r.loc));
const km = turf.length(path, { units: 'kilometers' });
return Math.round(km * 100) / 100;
};
export default analyzeGPS;
// Generation time: 18.408s
// Result: PASS

View File

@@ -0,0 +1,18 @@
async function analyzeGPS(readings, boundary) {
const turf = await import('https://esm.sh/@turf/turf');
const valid = readings
.filter(r => turf.booleanPointInPolygon(turf.point(r.loc), boundary, { ignoreBoundary: true }))
.sort((a, b) => a.ts - b.ts);
if (valid.length < 2) return 0;
const len = turf.length(
turf.lineString(valid.map(r => r.loc)),
{ units: 'kilometers' }
);
return Math.round(len * 100) / 100;
}
export default analyzeGPS;
// Generation time: 28.608s
// Result: PASS

View File

@@ -0,0 +1,48 @@
const computeMST = async (toml) => {
const [{ parse }, { Heap }, { default: table }] = await Promise.all([
import("https://esm.sh/smol-toml"),
import("https://esm.sh/mnemonist"),
import("https://esm.sh/text-table")
]);
const { edges = [] } = parse(toml);
const nodes = [...new Set(edges.flatMap((e) => [e.from, e.to]))];
const parent = Object.fromEntries(nodes.map((n) => [n, n]));
const rank = Object.fromEntries(nodes.map((n) => [n, 0]));
const find = (x) => (parent[x] === x ? x : (parent[x] = find(parent[x])));
const union = (a, b) => {
let ra = find(a);
let rb = find(b);
if (ra === rb) return false;
if (rank[ra] < rank[rb]) [ra, rb] = [rb, ra];
parent[rb] = ra;
if (rank[ra] === rank[rb]) rank[ra]++;
return true;
};
const heap = new Heap((a, b) => a.weight - b.weight);
for (const e of edges) heap.push(e);
const mst = [];
let totalWeight = 0;
while (heap.size && mst.length < nodes.length - 1) {
const e = heap.pop();
if (union(e.from, e.to)) {
mst.push([e.from, e.to, String(e.weight)]);
totalWeight += e.weight;
}
}
return {
table: table([["From", "To", "Weight"], ...mst]),
totalWeight
};
};
self.computeMST = computeMST;
export default computeMST;
// Generation time: 37.889s
// Result: PASS

View File

@@ -0,0 +1,53 @@
const computeMST = async (tomlStr) => {
const { parse } = await import('https://esm.sh/smol-toml');
const { Heap } = await import('https://esm.sh/mnemonist');
const textTable = (await import('https://esm.sh/text-table')).default;
const config = parse(tomlStr);
const edges = config.edges || [];
class UnionFind {
constructor() { this.p = {}; this.r = {}; }
add(n) { if (!(n in this.p)) { this.p[n] = n; this.r[n] = 0; } }
find(n) { return this.p[n] === n ? n : (this.p[n] = this.find(this.p[n])); }
union(a, b) {
const ra = this.find(a), rb = this.find(b);
if (ra === rb) return false;
if (this.r[ra] < this.r[rb]) this.p[ra] = rb;
else if (this.r[ra] > this.r[rb]) this.p[rb] = ra;
else { this.p[rb] = ra; this.r[ra]++; }
return true;
}
}
const uf = new UnionFind();
const heap = new Heap((a, b) => a.weight - b.weight);
const nodes = new Set();
for (const e of edges) {
nodes.add(e.from);
nodes.add(e.to);
uf.add(e.from);
uf.add(e.to);
heap.push(e);
}
const mst = [];
let totalWeight = 0;
while (heap.size && mst.length < nodes.size - 1) {
const e = heap.pop();
if (uf.union(e.from, e.to)) {
mst.push([e.from, e.to, String(e.weight)]);
totalWeight += e.weight;
}
}
return {
table: textTable([['From', 'To', 'Weight'], ...mst]),
totalWeight
};
};
export default computeMST;
// Generation time: 22.055s
// Result: PASS

View File

@@ -0,0 +1,22 @@
const findShortestPath = async (graph, start, end) => {
const {default: PQ} = await import('https://esm.sh/js-priority-queue');
const dist = new Map([[start, 0]]);
const pq = new PQ({comparator: (a, b) => a[1] - b[1]});
pq.queue([start, 0]);
while (pq.length) {
const [u, d] = pq.dequeue();
if (u === end) return d;
if (d > (dist.get(u) ?? Infinity)) continue;
for (const [v, w] of Object.entries(graph[u] || {})) {
const nd = d + w;
if (nd < (dist.get(v) ?? Infinity)) {
dist.set(v, nd);
pq.queue([v, nd]);
}
}
}
return Infinity;
};
export default findShortestPath;
// Generation time: 42.886s
// Result: PASS

View File

@@ -0,0 +1,24 @@
async function findShortestPath(g, s, e) {
const { default: PQ } = await import('https://esm.sh/js-priority-queue');
const d = { [s]: 0 };
const q = new PQ({ comparator: (a, b) => a.p - b.p });
q.queue({ n: s, p: 0 });
while (q.length) {
const { n, p } = q.dequeue();
if (n === e) return p;
if (p > (d[n] ?? Infinity)) continue;
for (const m in g[n]) {
const w = p + g[n][m];
if (w < (d[m] ?? Infinity)) {
d[m] = w;
q.queue({ n: m, p: w });
}
}
}
return Infinity;
}
export default findShortestPath;
// Generation time: 45.601s
// Result: PASS

View File

@@ -0,0 +1,29 @@
let l;
export const findConvexHull = async p => {
if (!Array.isArray(p)) throw new TypeError("points must be an array");
if (p.length < 2) return [...p];
l = l || import("https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/+esm");
const { sortBy: m, uniqWith: u } = await l;
const q = u(m(p, [o => o.x, o => o.y]), (a, b) => a.x === b.x && a.y === b.y);
const n = q.length;
if (n < 4) return q;
const c = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
const h = [];
for (let i = 0; i < n; h.push(q[i++]))
while (h.length > 1 && c(h[h.length - 2], h[h.length - 1], q[i]) <= 0) h.pop();
const t = h.length + 1;
for (let i = n - 1; i >= 0; h.push(q[i--]))
while (h.length > t && c(h[h.length - 2], h[h.length - 1], q[i]) <= 0) h.pop();
h.pop();
return h;
};
export default findConvexHull;
// Generation time: 26.432s
// Result: FAIL

View File

@@ -0,0 +1,24 @@
async function findConvexHull(points) {
const _ = await import('https://esm.sh/lodash');
if (points.length < 3) return _.uniqWith(points, _.isEqual);
const pts = _.sortBy(points, ['x', 'y']);
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
const build = (arr) => {
const h = [];
for (const p of arr) {
while (h.length >= 2 && cross(h[h.length - 2], h[h.length - 1], p) <= 0) h.pop();
h.push(p);
}
return h;
};
const lower = build(pts);
const upper = build([...pts].reverse());
return _.uniqWith([...lower, ...upper], _.isEqual);
}
export default findConvexHull;
// Generation time: 54.184s
// Result: PASS

View File

@@ -0,0 +1,46 @@
const analyzeSignal = async (yamlString) => {
const [yaml, mathMod, ndarrayMod, fftMod, domMod] = await Promise.all([
import('https://esm.sh/js-yaml@4.1.0'),
import('https://esm.sh/mathjs@11.11.0'),
import('https://esm.sh/ndarray'),
import('https://esm.sh/ndarray-fft'),
import('https://esm.sh/dompurify@3.0.3')
]);
const math = mathMod.default;
const ndarray = ndarrayMod.default;
const fft = fftMod.default;
const DOMPurify = domMod.default(window);
const { sampleRate, duration, components } = yaml.load(yamlString);
const N = sampleRate * duration;
const half = N / 2;
const signal = new Array(N);
for (let i = 0; i < N; i++) {
const t = i / sampleRate;
let s = 0;
for (const { frequency, amplitude } of components) {
s += amplitude * math.sin(2 * math.pi * frequency * t);
}
signal[i] = s;
}
const real = ndarray(new Float64Array(signal));
const imag = ndarray(new Float64Array(N));
fft(1, real, imag);
const magnitude = [];
for (let k = 0; k <= half; k++) {
magnitude[k] = math.sqrt(real.get(k) ** 2 + imag.get(k) ** 2) / half;
}
const peaks = magnitude
.map((m, k) => ({
frequencyHz: Math.round(k * sampleRate / N),
magnitude: Math.round(m * 100) / 100
}))
.filter(p => p.magnitude > 0.1)
.sort((a, b) => b.magnitude - a.magnitude);
const html = `<table><tr><th>Frequency (Hz)</th><th>Magnitude</th></tr>${peaks
.map(p => `<tr><td>${p.frequencyHz}</td><td>${p.magnitude}</td></tr>`)
.join('')}</table>`;
return { peaks, html: DOMPurify.sanitize(html), signalLength: N };
};
export default analyzeSignal;
// Generation time: 83.104s
// Result: FAIL

View File

@@ -0,0 +1,43 @@
async function analyzeSignal(yamlStr) {
const [{ default: yaml }, { default: math }, { default: ndarray }, { default: fft }, { default: DOMPurify }] = await Promise.all([
import('https://esm.sh/js-yaml'),
import('https://esm.sh/mathjs'),
import('https://esm.sh/ndarray'),
import('https://esm.sh/ndarray-fft'),
import('https://esm.sh/dompurify')
]);
const { sampleRate, duration, components } = yaml.load(yamlStr);
const N = sampleRate * duration;
const signal = new Float64Array(N);
for (let i = 0; i < N; i++) {
const t = i / sampleRate;
signal[i] = components.reduce((s, c) => s + c.amplitude * math.sin(2 * math.pi * c.frequency * t), 0);
}
const real = ndarray(signal, [N]);
const imag = ndarray(new Float64Array(N), [N]);
fft(1, real, imag);
const peaks = [];
for (let k = 0; k <= N / 2; k++) {
const mag = math.sqrt(real.get(k) ** 2 + imag.get(k) ** 2) / (N / 2);
if (mag > 0.1) {
peaks.push({
frequencyHz: Math.round(k * sampleRate / N),
magnitude: parseFloat(mag.toFixed(2))
});
}
}
peaks.sort((a, b) => b.magnitude - a.magnitude);
const rows = peaks.map(p => `<tr><td>${p.frequencyHz}</td><td>${p.magnitude}</td></tr>`).join('');
const html = `<table><tr><th>Frequency (Hz)</th><th>Magnitude</th></tr>${rows}</table>`;
return { peaks, html: DOMPurify.sanitize(html), signalLength: N };
}
export default analyzeSignal;
// Generation time: 34.195s
// Result: FAIL

View File

@@ -0,0 +1,58 @@
const hexchain = async (toml) => {
const [tm, sd, ss, am, tt, pm] = await Promise.all([
import('https://esm.sh/smol-toml'),
import('https://esm.sh/seedrandom'),
import('https://esm.sh/simple-statistics'),
import('https://esm.sh/ajv'),
import('https://esm.sh/text-table'),
import('https://esm.sh/dompurify')
]);
const parse = tm.parse;
const seedrandom = sd.default;
const Ajv = am.default;
const table = tt.default;
const DOMPurify = pm.default;
const config = parse(toml);
const schema = {
type: 'object',
required: ['seed', 'count', 'label'],
properties: {
seed: { type: 'string' },
count: { type: 'integer', minimum: 1, maximum: 10000 },
label: { type: 'string', minLength: 1 }
}
};
const ajv = new Ajv();
if (!ajv.validate(schema, config)) return { valid: false, errors: ajv.errorsText() };
const rng = seedrandom(config.seed);
const nums = Array.from({ length: config.count }, rng);
const round = (x) => Math.round(x * 1e6) / 1e6;
const mean = round(ss.mean(nums));
const stddev = round(ss.standardDeviation(nums));
const median = round(ss.median(nums));
const tbl = table([
['Stat', 'Value'],
['mean', String(mean)],
['stddev', String(stddev)],
['median', String(median)]
]);
const clean = DOMPurify.sanitize('<pre class="stats">' + tbl + '</pre>');
return {
valid: true,
label: config.label,
stats: { mean, stddev, median },
table: clean,
count: config.count
};
};
export default hexchain;
// Generation time: 69.982s
// Result: PASS

View File

@@ -0,0 +1,25 @@
const hexchain = async (t) => {
const [{ parse }, { default: R }, S, { default: A }, { default: T }, { default: D }] = await Promise.all([
import('https://esm.run/smol-toml'),
import('https://esm.run/seedrandom'),
import('https://esm.run/simple-statistics'),
import('https://esm.run/ajv'),
import('https://esm.run/text-table'),
import('https://esm.run/dompurify')
]);
const c = parse(t);
const s = { type:'object', required:['seed','count','label'], properties:{ seed:{type:'string'}, count:{type:'integer',minimum:1,maximum:10000}, label:{type:'string',minLength:1} } };
const a = new A();
if (!a.validate(s, c)) return { valid:false, errors: a.errorsText() };
const r = R(c.seed);
const n = Array.from({ length: c.count }, r);
const m = +S.mean(n).toFixed(6);
const d = +S.standardDeviation(n).toFixed(6);
const e = +S.median(n).toFixed(6);
const tb = T([['Stat','Value'],['mean',m.toFixed(6)],['stddev',d.toFixed(6)],['median',e.toFixed(6)]]);
const h = D.sanitize(`<pre class="stats">${tb}</pre>`);
return { valid:true, label:c.label, stats:{ mean:m, stddev:d, median:e }, table:h, count:c.count };
};
export default hexchain;
// Generation time: 76.627s
// Result: PASS

View File

@@ -0,0 +1,7 @@
const parseMarkdown = async (md) => {
const { default: MarkdownIt } = await import('https://cdn.jsdelivr.net/npm/markdown-it@14.1.0/+esm');
return MarkdownIt({ html: false, linkify: true }).render(md);
};
export default parseMarkdown;
// Generation time: 18.711s
// Result: PASS

View File

@@ -0,0 +1,7 @@
const parseMarkdown = async (md) => {
const { marked } = await import('https://esm.sh/marked');
return marked.parse(md);
};
export default parseMarkdown;
// Generation time: 17.682s
// Result: PASS

View File

@@ -0,0 +1,36 @@
const processCSV = async (csv, {
filterColumn: f,
filterValue: v,
groupBy: g,
aggregateColumn: a,
operation: o
}) => {
const [{ default: P }, { groupBy: G }] = await Promise.all([
import('https://cdn.jsdelivr.net/npm/papaparse@5.4.1/+esm'),
import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/+esm')
]);
const N = x => {
const y = Number(x);
return Number.isFinite(y) ? y : 0;
};
const rows = P.parse(csv, { header: true, skipEmptyLines: true }).data;
const groups = G(rows.filter(r => r[f] == v), r => r[g]);
return Object.entries(groups).map(([k, list]) => {
let result = 0;
if (o === 'count') {
result = list.length;
} else {
const total = list.reduce((s, r) => s + N(r[a]), 0);
result = o === 'avg' ? total / list.length : total;
}
return { [g]: k, result };
});
};
export default processCSV;
// Generation time: 38.066s
// Result: PASS

View File

@@ -0,0 +1,21 @@
const processCSV = async (csv, c) => {
const Papa = (await import('https://esm.run/papaparse@5')).default;
const { data } = Papa.parse(csv, { header: true });
return Object.values(
data.reduce((acc, r) => {
if (r[c.filterColumn] != c.filterValue) return acc;
const k = r[c.groupBy];
acc[k] ??= { [c.groupBy]: k, sum: 0, count: 0 };
acc[k].sum += Number(r[c.aggregateColumn]) || 0;
acc[k].count++;
return acc;
}, {})
).map(g => ({
[c.groupBy]: g[c.groupBy],
result: c.operation === 'count' ? g.count : c.operation === 'sum' ? g.sum : g.sum / g.count
}));
};
export default processCSV;
// Generation time: 31.429s
// Result: PASS

View File

@@ -0,0 +1,54 @@
const luxonP = import('https://esm.sh/luxon@3.4.4');
const findAvailableSlots = async (a, b, c) => {
const { DateTime, Duration } = await luxonP;
if (c.durationMinutes <= 0) return [];
const u = s => DateTime.fromISO(s, { zone: 'utc' });
const hm = s => { const [h, m] = s.split(':'); return +h * 60 + +m; };
const D = Duration.fromObject({ days: 1 });
const z = Duration.fromObject({ minutes: c.durationMinutes });
const w0 = hm(c.workHours.start);
const w1 = hm(c.workHours.end);
const rng = { s: u(c.searchRange.start), e: u(c.searchRange.end) };
const busy = [...a, ...b]
.map(x => ({ s: u(x.start), e: u(x.end) }))
.filter(x => +x.s < +x.e)
.sort((x, y) => +x.s - +y.s || +x.e - +y.e);
const mrg = [];
for (const x of busy) {
const l = mrg[mrg.length - 1];
if (l && +x.s <= +l.e) l.e = DateTime.max(l.e, x.e);
else mrg.push({ s: x.s, e: x.e });
}
const free = [];
let cur = rng.s;
for (const x of mrg) {
if (x.s > cur) free.push({ s: DateTime.max(cur, rng.s), e: DateTime.min(x.s, rng.e) });
cur = DateTime.max(cur, x.e);
if (cur >= rng.e) break;
}
if (cur < rng.e) free.push({ s: cur, e: rng.e });
const slots = [];
for (const x of free) {
if (x.s >= x.e) continue;
for (let d = x.s.startOf('day'); d <= x.e; d = d.plus(D)) {
const i = DateTime.max(x.s, d.plus({ minutes: w0 }), rng.s);
const j = DateTime.min(x.e, d.plus({ minutes: w1 }), rng.e);
for (let t = i; j >= t.plus(z); t = t.plus(z)) {
const v = t.plus(z);
slots.push({ start: t.toJSDate().toISOString(), end: v.toJSDate().toISOString() });
}
}
}
return slots;
};
export default findAvailableSlots;
// Generation time: 173.316s
// Result: PASS

View File

@@ -0,0 +1,62 @@
async function findAvailableSlots(cal1, cal2, c) {
const { DateTime } = await import('https://esm.sh/luxon@3');
const s = DateTime.fromISO(c.searchRange.start, { zone: 'utc' });
const e = DateTime.fromISO(c.searchRange.end, { zone: 'utc' });
let work = [];
let cur = s;
const [wSH, wSM] = c.workHours.start.split(':').map(Number);
const [wEH, wEM] = c.workHours.end.split(':').map(Number);
while (cur < e) {
const ws = cur.set({ hour: wSH, minute: wSM, second: 0, millisecond: 0 });
const we = cur.set({ hour: wEH, minute: wEM, second: 0, millisecond: 0 });
if (we > ws) work.push({ start: ws, end: we });
cur = cur.plus({ days: 1 }).set({ hour: 0, minute: 0, second: 0, millisecond: 0 });
}
const busy = [...cal1, ...cal2]
.map(b => ({
start: DateTime.fromISO(b.start, { zone: 'utc' }),
end: DateTime.fromISO(b.end, { zone: 'utc' })
}))
.filter(b => b.start < b.end)
.sort((a, b) => a.start - b.start);
let merged = [];
for (const b of busy) {
const last = merged[merged.length - 1];
if (merged.length && b.start <= last.end) last.end = DateTime.max(last.end, b.end);
else merged.push({ ...b });
}
let free = [];
for (const w of work) {
let cs = w.start;
for (const b of merged) {
if (b.end <= cs) continue;
if (b.start >= w.end) break;
if (b.start > cs) free.push({ start: cs, end: b.start });
cs = DateTime.max(cs, b.end);
if (cs >= w.end) break;
}
if (cs < w.end) free.push({ start: cs, end: w.end });
}
const d = c.durationMinutes;
const slots = [];
for (const f of free) {
let ss = f.start;
while (ss.plus({ minutes: d }) <= f.end) {
slots.push({
start: ss.toISO({ suppressMilliseconds: true }),
end: ss.plus({ minutes: d }).toISO({ suppressMilliseconds: true })
});
ss = ss.plus({ minutes: d });
}
}
return slots;
}
export default findAvailableSlots;
// Generation time: 59.287s
// Result: PASS

View File

@@ -0,0 +1,21 @@
let ajv;
const validateJSON = async (data, schema) => {
try {
if (!ajv) {
const Ajv = (await import('https://esm.sh/ajv@8.17.1')).default;
ajv = new Ajv({ allErrors: true, strict: false });
}
const validate = ajv.compile(schema);
const valid = validate(data);
return {
valid,
errors: valid ? [] : validate.errors.map(e => `${e.instancePath || '/'}: ${e.message}`)
};
} catch (err) {
return { valid: false, errors: [err.message] };
}
};
export default validateJSON;
// Generation time: 45.178s
// Result: PASS

View File

@@ -0,0 +1,9 @@
async function validateJSON(data, schema) {
const { default: Ajv } = await import('https://esm.sh/ajv@8');
const ajv = new Ajv({ allErrors: true });
const valid = ajv.validate(schema, data);
return { valid, errors: valid ? [] : ajv.errors.map(e => e.message) };
}
export default validateJSON;
// Generation time: 31.005s
// Result: PASS

View File

@@ -0,0 +1,34 @@
const createStreamVisualizer = async (stream, options) => {
const { maxPoints, alpha, width, height, yDomain } = options;
const mod = await import('https://cdn.jsdelivr.net/npm/d3@7/+esm');
const { scaleLinear, line } = mod.default || mod;
const data = [];
let prev;
for await (const { timestamp, value } of stream) {
const ema = prev === undefined ? value : alpha * value + (1 - alpha) * prev;
prev = ema;
data.push({ timestamp, value, ema });
if (data.length > maxPoints) data.shift();
}
if (!data.length) return { data, path: '' };
const x = scaleLinear()
.domain([data[0].timestamp, data[data.length - 1].timestamp])
.range([0, width]);
const y = scaleLinear()
.domain(yDomain)
.range([height, 0]);
const path = line()
.x(d => x(d.timestamp))
.y(d => y(d.ema))(data) || '';
return { data, path };
};
export default createStreamVisualizer;
// Generation time: 48.885s
// Result: PASS

View File

@@ -0,0 +1,26 @@
async function createStreamVisualizer(asyncIterable, { maxPoints: max, alpha, width: w, height: h, yDomain }) {
const d3 = await import('d3');
const data = [];
let prev;
for await (const { timestamp: t, value: v } of asyncIterable) {
const ema = prev === undefined ? v : alpha * v + (1 - alpha) * prev;
prev = ema;
data.push({ timestamp: t, value: v, ema });
if (data.length > max) data.shift();
}
if (!data.length) return { data, path: null };
const x = d3.scaleLinear([data[0].timestamp, data[data.length - 1].timestamp], [0, w]);
const y = d3.scaleLinear(yDomain, [h, 0]);
const path = d3.line()
.x(d => x(d.timestamp))
.y(d => y(d.ema))(data);
return { data, path };
}
export default createStreamVisualizer;
// Generation time: 17.130s
// Result: FAIL