diff --git a/tests/10_scrypt_hash/outputs/openai_gpt-5.6-luna EFF_high.js b/tests/10_scrypt_hash/outputs/openai_gpt-5.6-luna EFF_high.js new file mode 100644 index 0000000..66fc1f6 --- /dev/null +++ b/tests/10_scrypt_hash/outputs/openai_gpt-5.6-luna EFF_high.js @@ -0,0 +1,15 @@ +async function hashPassword(password, salt) { + const scryptModule = await import( + "https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/+esm" + ); + const scrypt = scryptModule.default ?? scryptModule.scrypt; + + const passwordBytes = new TextEncoder().encode(password); + const saltBytes = new TextEncoder().encode(salt); + const hash = await scrypt(passwordBytes, saltBytes, 1024, 8, 1, 32); + + return Array.from(hash, byte => byte.toString(16).padStart(2, "0")).join(""); +} +export default hashPassword; +// Generation time: 8.694s +// Result: FAIL \ No newline at end of file diff --git a/tests/11_geospatial/outputs/openai_gpt-5.6-luna EFF_high.js b/tests/11_geospatial/outputs/openai_gpt-5.6-luna EFF_high.js new file mode 100644 index 0000000..96459e1 --- /dev/null +++ b/tests/11_geospatial/outputs/openai_gpt-5.6-luna EFF_high.js @@ -0,0 +1,27 @@ +let turfModule; + +async function analyzeGPS(readings, boundary) { + turfModule ||= import("https://cdn.jsdelivr.net/npm/@turf/turf@7.2.0/+esm"); + + const { + point, + lineString, + length: pathLength, + booleanPointInPolygon + } = await turfModule; + + const valid = readings + .filter(({ loc }) => + booleanPointInPolygon(point(loc), boundary, { ignoreBoundary: true }) + ) + .sort((a, b) => a.ts - b.ts); + + if (valid.length < 2) return 0; + + const path = lineString(valid.map(({ loc }) => loc)); + + return Number(pathLength(path).toFixed(2)); +} +export default analyzeGPS; +// Generation time: 12.391s +// Result: PASS \ No newline at end of file diff --git a/tests/12_mst_pipeline/outputs/openai_gpt-5.6-luna EFF_high.js b/tests/12_mst_pipeline/outputs/openai_gpt-5.6-luna EFF_high.js new file mode 100644 index 0000000..7469c1b --- /dev/null +++ b/tests/12_mst_pipeline/outputs/openai_gpt-5.6-luna EFF_high.js @@ -0,0 +1,105 @@ +async function computeMST(toml) { + const [tomlModule, heapModule, tableModule] = await Promise.all([ + import("https://esm.sh/smol-toml@1.3.1"), + import("https://esm.sh/mnemonist@0.40.3/heap"), + import("https://esm.sh/text-table@0.2.0") + ]); + + const parse = tomlModule.parse ?? tomlModule.default?.parse; + const Heap = heapModule.default ?? heapModule.Heap; + const textTable = tableModule.default ?? tableModule; + + if (typeof parse !== "function" || typeof Heap !== "function" || + typeof textTable !== "function") { + throw new Error("Failed to load required libraries"); + } + + const config = parse(toml); + const edges = config?.edges; + + if (!Array.isArray(edges)) { + throw new TypeError("TOML must contain an edges array"); + } + + const nodes = new Set(); + const heap = new Heap((a, b) => a.weight - b.weight); + + for (const edge of edges) { + const { from, to, weight } = edge ?? {}; + + if (typeof from !== "string" || typeof to !== "string" || + !from || !to || typeof weight !== "number" || + !Number.isFinite(weight)) { + throw new TypeError("Each edge must have valid from, to, and weight fields"); + } + + nodes.add(from); + nodes.add(to); + heap.push({ from, to, weight }); + } + + const parent = new Map(); + const rank = new Map(); + + for (const node of nodes) { + parent.set(node, node); + rank.set(node, 0); + } + + const find = node => { + let root = node; + + while (parent.get(root) !== root) { + root = parent.get(root); + } + + while (parent.get(node) !== node) { + const next = parent.get(node); + parent.set(node, root); + node = next; + } + + return root; + }; + + const union = (left, right) => { + let leftRoot = find(left); + let rightRoot = find(right); + + if (leftRoot === rightRoot) { + return false; + } + + if (rank.get(leftRoot) < rank.get(rightRoot)) { + [leftRoot, rightRoot] = [rightRoot, leftRoot]; + } + + parent.set(rightRoot, leftRoot); + + if (rank.get(leftRoot) === rank.get(rightRoot)) { + rank.set(leftRoot, rank.get(leftRoot) + 1); + } + + return true; + }; + + const mst = []; + let totalWeight = 0; + + while (heap.size && mst.length < nodes.size - 1) { + const edge = heap.pop(); + + if (union(edge.from, edge.to)) { + mst.push([edge.from, edge.to, String(edge.weight)]); + totalWeight += edge.weight; + } + } + + return { + table: textTable([["From", "To", "Weight"], ...mst]), + totalWeight + }; +} +export default computeMST; +// Generation time: 11.402s +// Result: PASS \ No newline at end of file diff --git a/tests/1_dijkstra/outputs/openai_gpt-5.6-luna EFF_high.js b/tests/1_dijkstra/outputs/openai_gpt-5.6-luna EFF_high.js new file mode 100644 index 0000000..0d5e2dc --- /dev/null +++ b/tests/1_dijkstra/outputs/openai_gpt-5.6-luna EFF_high.js @@ -0,0 +1,57 @@ +let priorityQueueModule; + +async function findShortestPath(graph, start, end) { + if (!graph || typeof graph !== "object" || Array.isArray(graph)) { + throw new TypeError("graph must be an object"); + } + + priorityQueueModule ??= import( + "https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.5/+esm" + ); + + const module = await priorityQueueModule; + const PriorityQueue = module.default ?? module.PriorityQueue; + + if (typeof PriorityQueue !== "function") { + throw new TypeError("PriorityQueue could not be loaded"); + } + + const queue = new PriorityQueue({ + comparator: (a, b) => a.distance - b.distance + }); + const distances = new Map([[start, 0]]); + + queue.queue({ node: start, distance: 0 }); + + while (queue.length) { + const { node, distance } = queue.dequeue(); + + if (distance !== distances.get(node)) continue; + if (node === end) return distance; + + const edges = Object.hasOwn(graph, node) ? graph[node] : undefined; + if (edges === undefined) continue; + + if (!edges || typeof edges !== "object" || Array.isArray(edges)) { + throw new TypeError(`Invalid edges for node: ${node}`); + } + + for (const [neighbor, weight] of Object.entries(edges)) { + if (!Number.isFinite(weight) || weight < 0) { + throw new RangeError("Edge weights must be finite and non-negative"); + } + + const nextDistance = distance + weight; + + if (nextDistance < (distances.get(neighbor) ?? Infinity)) { + distances.set(neighbor, nextDistance); + queue.queue({ node: neighbor, distance: nextDistance }); + } + } + } + + return Infinity; +} +export default findShortestPath; +// Generation time: 30.835s +// Result: PASS \ No newline at end of file diff --git a/tests/2_convex_hull/outputs/openai_gpt-5.6-luna EFF_high.js b/tests/2_convex_hull/outputs/openai_gpt-5.6-luna EFF_high.js new file mode 100644 index 0000000..d5746cc --- /dev/null +++ b/tests/2_convex_hull/outputs/openai_gpt-5.6-luna EFF_high.js @@ -0,0 +1,56 @@ +async function findConvexHull(points) { + if (!Array.isArray(points)) { + throw new TypeError("Points must be an array"); + } + + if (points.some(point => + !point || + typeof point !== "object" || + !Number.isFinite(point.x) || + !Number.isFinite(point.y) + )) { + throw new TypeError("Each point must contain finite numeric x and y values"); + } + + const { sortBy, uniqBy } = await import( + "https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.js" + ); + + const sorted = sortBy( + uniqBy(points, ({ x, y }) => `${x}\0${y}`), + ["x", "y"] + ); + + if (sorted.length < 3) { + return sorted; + } + + const cross = (a, b, c) => + (b.x - a.x) * (c.y - a.y) - + (b.y - a.y) * (c.x - a.x); + + const buildHalf = sequence => { + const half = []; + + for (const point of sequence) { + while ( + half.length > 1 && + cross(half[half.length - 2], half[half.length - 1], point) <= 0 + ) { + half.pop(); + } + + half.push(point); + } + + return half; + }; + + const lower = buildHalf(sorted); + const upper = buildHalf(sorted.slice().reverse()); + + return lower.slice(0, -1).concat(upper.slice(0, -1)); +} +export default findConvexHull; +// Generation time: 21.094s +// Result: PASS \ No newline at end of file diff --git a/tests/3_signal_pipeline/outputs/openai_gpt-5.6-luna EFF_high.js b/tests/3_signal_pipeline/outputs/openai_gpt-5.6-luna EFF_high.js new file mode 100644 index 0000000..0784f5a --- /dev/null +++ b/tests/3_signal_pipeline/outputs/openai_gpt-5.6-luna EFF_high.js @@ -0,0 +1,132 @@ +async function analyzeSignal(yamlString) { + const [ + yamlModule, + mathModule, + ndarrayModule, + fftModule, + purifierModule + ] = await Promise.all([ + import('https://esm.sh/js-yaml@4.1.0'), + import('https://esm.sh/mathjs@13.2.0'), + import('https://esm.sh/ndarray@1.0.19'), + import('https://esm.sh/ndarray-fft@1.0.0'), + import('https://esm.sh/dompurify@3.2.4') + ]); + + if (typeof yamlString !== 'string') { + throw new TypeError('yamlString must be a string'); + } + + const yaml = yamlModule.default ?? yamlModule; + const ndarray = ndarrayModule.default ?? ndarrayModule.ndarray ?? ndarrayModule; + const fft = fftModule.default ?? fftModule.fft ?? fftModule; + const DOMPurify = purifierModule.default ?? + purifierModule.DOMPurify ?? + purifierModule; + + const math = mathModule.default?.sin + ? mathModule.default + : typeof mathModule.create === 'function' && mathModule.all + ? mathModule.create(mathModule.all) + : mathModule; + + const config = yaml.load(yamlString); + + if ( + !config || + Array.isArray(config) || + typeof config !== 'object' + ) { + throw new TypeError('YAML must describe an object'); + } + + const { sampleRate, duration, components } = config; + + if (!Number.isFinite(sampleRate) || sampleRate <= 0) { + throw new RangeError('sampleRate must be a positive number'); + } + + if (!Number.isFinite(duration) || duration <= 0) { + throw new RangeError('duration must be a positive number'); + } + + if (!Array.isArray(components)) { + throw new TypeError('components must be an array'); + } + + const N = sampleRate * duration; + + if (!Number.isSafeInteger(N) || N < 2) { + throw new RangeError('sampleRate * duration must be an integer of at least 2'); + } + + const signalComponents = components.map(component => { + if (!component || typeof component !== 'object') { + throw new TypeError('Each component must be an object'); + } + + const { frequency, amplitude } = component; + + if (!Number.isFinite(frequency) || !Number.isFinite(amplitude)) { + throw new TypeError('Component frequency and amplitude must be numbers'); + } + + return { frequency, amplitude }; + }); + + const signal = new Float64Array(N); + + for (let i = 0; i < N; i++) { + const t = i / sampleRate; + + for (const { frequency, amplitude } of signalComponents) { + signal[i] += amplitude * + math.sin(2 * math.pi * frequency * t); + } + } + + const real = ndarray(signal, [N]); + const imag = ndarray(new Float64Array(N), [N]); + + fft(1, real, imag); + + const ranked = []; + + for (let k = 0; k <= N / 2; k++) { + const magnitude = + math.sqrt(real.get(k) ** 2 + imag.get(k) ** 2) / (N / 2); + + if (magnitude > 0.1) { + ranked.push({ + frequencyHz: k * sampleRate / N, + magnitude + }); + } + } + + ranked.sort((a, b) => b.magnitude - a.magnitude); + + const peaks = ranked.map(({ frequencyHz, magnitude }) => ({ + frequencyHz: Math.round(frequencyHz), + magnitude: Math.round(magnitude * 100) / 100 + })); + + const rows = peaks + .map(({ frequencyHz, magnitude }) => + `
| Frequency (Hz) | Magnitude |
|---|
${tableString}`
+ );
+
+ return {
+ valid: true,
+ label: config.label,
+ stats,
+ table,
+ count: config.count
+ };
+}
+export default hexchain;
+// Generation time: 13.622s
+// Result: PASS
\ No newline at end of file
diff --git a/tests/5_markdown_parser/outputs/openai_gpt-5.6-luna EFF_high.js b/tests/5_markdown_parser/outputs/openai_gpt-5.6-luna EFF_high.js
new file mode 100644
index 0000000..b2fe924
--- /dev/null
+++ b/tests/5_markdown_parser/outputs/openai_gpt-5.6-luna EFF_high.js
@@ -0,0 +1,21 @@
+let dependencies;
+
+const loadDependencies = () =>
+ dependencies ??= Promise.all([
+ import("https://esm.sh/marked@15.0.12"),
+ import("https://esm.sh/dompurify@3.2.6")
+ ]);
+
+async function parseMarkdown(markdown) {
+ if (typeof markdown !== "string") {
+ throw new TypeError("Markdown must be a string");
+ }
+
+ const [{ marked }, { default: DOMPurify }] = await loadDependencies();
+ const html = marked.parse(markdown, { gfm: true });
+
+ return DOMPurify.sanitize(html);
+}
+export default parseMarkdown;
+// Generation time: 13.055s
+// Result: PASS
\ No newline at end of file
diff --git a/tests/6_csv_processor/outputs/openai_gpt-5.6-luna EFF_high.js b/tests/6_csv_processor/outputs/openai_gpt-5.6-luna EFF_high.js
new file mode 100644
index 0000000..8a236bb
--- /dev/null
+++ b/tests/6_csv_processor/outputs/openai_gpt-5.6-luna EFF_high.js
@@ -0,0 +1,73 @@
+const dependencies = Promise.all([
+ import("https://cdn.jsdelivr.net/npm/papaparse@5.4.3/+esm"),
+ import("https://cdn.jsdelivr.net/npm/lodash@4.17.21/+esm")
+]);
+
+async function processCSV(csv, config) {
+ if (typeof csv !== "string") throw new TypeError("csv must be a string");
+ if (!config || typeof config !== "object") {
+ throw new TypeError("config must be an object");
+ }
+
+ const {
+ filterColumn,
+ filterValue,
+ groupBy,
+ aggregateColumn,
+ operation
+ } = config;
+
+ if (![filterColumn, groupBy, aggregateColumn].every(
+ value => typeof value === "string"
+ )) {
+ throw new TypeError("Column names must be strings");
+ }
+
+ if (!["sum", "avg", "count"].includes(operation)) {
+ throw new RangeError("operation must be sum, avg, or count");
+ }
+
+ const [parserModule, utilityModule] = await dependencies;
+ const Papa = parserModule.default ?? parserModule;
+ const _ = utilityModule.default ?? utilityModule;
+
+ const parsed = Papa.parse(csv, {
+ header: true,
+ skipEmptyLines: true
+ });
+
+ if (parsed.errors.length) {
+ throw new Error(
+ parsed.errors.map(error => error.message).join("; ")
+ );
+ }
+
+ const rows = _.filter(
+ parsed.data,
+ row => row[filterColumn] == filterValue
+ );
+
+ const groups = _.groupBy(rows, groupBy);
+
+ const toNumber = value => {
+ const number = Number(value);
+ return Number.isFinite(number) ? number : 0;
+ };
+
+ return Object.values(groups).map(group => {
+ const total = operation === "count"
+ ? group.length
+ : group.reduce(
+ (sum, row) => sum + toNumber(row[aggregateColumn]),
+ 0
+ );
+
+ return {
+ [groupBy]: group[0][groupBy],
+ result: operation === "avg" ? total / group.length : total
+ };
+ });
+}
+export default processCSV;
+// Generation time: 22.212s
+// Result: FAIL
\ No newline at end of file
diff --git a/tests/7_scheduler/outputs/openai_gpt-5.6-luna EFF_high.js b/tests/7_scheduler/outputs/openai_gpt-5.6-luna EFF_high.js
new file mode 100644
index 0000000..9891817
--- /dev/null
+++ b/tests/7_scheduler/outputs/openai_gpt-5.6-luna EFF_high.js
@@ -0,0 +1,194 @@
+async function findAvailableSlots(calendarA, calendarB, constraints) {
+ const { parseISO, isValid } = await import(
+ "https://cdn.jsdelivr.net/npm/date-fns@4.1.0/+esm"
+ );
+
+ const minute = 60000;
+ const day = 1440 * minute;
+
+ const instant = (value, label) => {
+ if (typeof value !== "string") {
+ throw new TypeError(`${label} must be an ISO date string`);
+ }
+
+ const dateOnly = /^\d{4}-\d{2}-\d{2}$/.test(value);
+ const hasZone = /(?:Z|[+-]\d{2}:?\d{2})$/i.test(value);
+ const normalized = dateOnly
+ ? `${value}T00:00:00Z`
+ : hasZone
+ ? value
+ : `${value}Z`;
+ const date = parseISO(normalized);
+
+ if (!isValid(date)) {
+ throw new RangeError(`${label} is not a valid ISO date string`);
+ }
+
+ return date.getTime();
+ };
+
+ const clock = (value, label) => {
+ if (value === "24:00") return day;
+
+ const match = typeof value === "string"
+ ? /^(\d{2}):(\d{2})$/.exec(value)
+ : null;
+
+ if (
+ !match ||
+ Number(match[1]) > 23 ||
+ Number(match[2]) > 59
+ ) {
+ throw new RangeError(`${label} must use HH:mm format`);
+ }
+
+ return (Number(match[1]) * 60 + Number(match[2])) * minute;
+ };
+
+ if (!constraints || typeof constraints !== "object") {
+ throw new TypeError("constraints must be an object");
+ }
+
+ const { durationMinutes, searchRange, workHours } = constraints;
+
+ if (!Number.isFinite(durationMinutes) || durationMinutes <= 0) {
+ throw new RangeError("durationMinutes must be a positive number");
+ }
+
+ const duration = durationMinutes * minute;
+
+ if (!Number.isSafeInteger(duration)) {
+ throw new RangeError("durationMinutes must resolve to whole milliseconds");
+ }
+
+ if (!searchRange || typeof searchRange !== "object") {
+ throw new TypeError("searchRange must be an object");
+ }
+
+ if (!workHours || typeof workHours !== "object") {
+ throw new TypeError("workHours must be an object");
+ }
+
+ const range = {
+ start: instant(searchRange.start, "searchRange.start"),
+ end: instant(searchRange.end, "searchRange.end")
+ };
+
+ if (range.start >= range.end) {
+ throw new RangeError("searchRange.start must be before searchRange.end");
+ }
+
+ const workStart = clock(workHours.start, "workHours.start");
+ const workEnd = clock(workHours.end, "workHours.end");
+
+ if (workStart >= workEnd) {
+ throw new RangeError("workHours.start must be before workHours.end");
+ }
+
+ const readCalendar = (calendar, label) => {
+ if (!Array.isArray(calendar)) {
+ throw new TypeError(`${label} must be an array`);
+ }
+
+ return calendar
+ .map((slot, index) => {
+ if (!slot || typeof slot !== "object") {
+ throw new TypeError(`${label}[${index}] must be an object`);
+ }
+
+ const start = instant(slot.start, `${label}[${index}].start`);
+ const end = instant(slot.end, `${label}[${index}].end`);
+
+ if (start >= end) {
+ throw new RangeError(
+ `${label}[${index}].start must be before ${label}[${index}].end`
+ );
+ }
+
+ return {
+ start: Math.max(start, range.start),
+ end: Math.min(end, range.end)
+ };
+ })
+ .filter(slot => slot.start < slot.end);
+ };
+
+ const busy = [
+ ...readCalendar(calendarA, "calendarA"),
+ ...readCalendar(calendarB, "calendarB")
+ ].sort((a, b) => a.start - b.start || a.end - b.end);
+
+ const merged = [];
+
+ for (const slot of busy) {
+ const last = merged[merged.length - 1];
+
+ if (!last || slot.start > last.end) {
+ merged.push({ ...slot });
+ } else {
+ last.end = Math.max(last.end, slot.end);
+ }
+ }
+
+ const result = [];
+ const addSlots = (start, end) => {
+ for (
+ let cursor = start;
+ cursor + duration <= end;
+ cursor += duration
+ ) {
+ result.push({
+ start: new Date(cursor).toISOString(),
+ end: new Date(cursor + duration).toISOString()
+ });
+ }
+ };
+
+ const firstDay = new Date(range.start);
+ firstDay.setUTCHours(0, 0, 0, 0);
+
+ let busyIndex = 0;
+
+ for (
+ let dayStart = firstDay.getTime();
+ dayStart < range.end;
+ dayStart += day
+ ) {
+ const windowStart = Math.max(range.start, dayStart + workStart);
+ const windowEnd = Math.min(range.end, dayStart + workEnd);
+
+ if (windowStart >= windowEnd) continue;
+
+ while (
+ busyIndex < merged.length &&
+ merged[busyIndex].end <= windowStart
+ ) {
+ busyIndex++;
+ }
+
+ let cursor = windowStart;
+
+ for (
+ let index = busyIndex;
+ index < merged.length && merged[index].start < windowEnd;
+ index++
+ ) {
+ const blocked = merged[index];
+
+ if (blocked.start > cursor) {
+ addSlots(cursor, Math.min(blocked.start, windowEnd));
+ }
+
+ cursor = Math.max(cursor, blocked.end);
+
+ if (cursor >= windowEnd) break;
+ }
+
+ addSlots(cursor, windowEnd);
+ }
+
+ return result;
+}
+export default findAvailableSlots;
+// Generation time: 80.821s
+// Result: PASS
\ No newline at end of file
diff --git a/tests/8_json_validator/outputs/openai_gpt-5.6-luna EFF_high.js b/tests/8_json_validator/outputs/openai_gpt-5.6-luna EFF_high.js
new file mode 100644
index 0000000..9664a8d
--- /dev/null
+++ b/tests/8_json_validator/outputs/openai_gpt-5.6-luna EFF_high.js
@@ -0,0 +1,42 @@
+let ajvPromise;
+
+const getAjv = () => {
+ if (ajvPromise) return ajvPromise;
+
+ ajvPromise = import("https://esm.sh/ajv@8.17.1")
+ .then(({ default: Ajv }) => Ajv)
+ .catch(error => {
+ ajvPromise = null;
+ throw error;
+ });
+
+ return ajvPromise;
+};
+
+const formatError = ({ instancePath, message }) =>
+ `${instancePath || "$"} ${message}`;
+
+async function validateJSON(value, schema) {
+ try {
+ const Ajv = await getAjv();
+ const validate = new Ajv({
+ allErrors: true,
+ strict: false
+ }).compile(schema);
+
+ const valid = validate(value);
+
+ return {
+ valid,
+ errors: valid ? [] : (validate.errors || []).map(formatError)
+ };
+ } catch (error) {
+ return {
+ valid: false,
+ errors: [error instanceof Error ? error.message : String(error)]
+ };
+ }
+}
+export default validateJSON;
+// Generation time: 15.651s
+// Result: PASS
\ No newline at end of file
diff --git a/tests/9_stream_visualizer/outputs/openai_gpt-5.6-luna EFF_high.js b/tests/9_stream_visualizer/outputs/openai_gpt-5.6-luna EFF_high.js
new file mode 100644
index 0000000..f5a6b31
--- /dev/null
+++ b/tests/9_stream_visualizer/outputs/openai_gpt-5.6-luna EFF_high.js
@@ -0,0 +1,97 @@
+async function createStreamVisualizer(asyncIterable, options = {}) {
+ const {
+ maxPoints = 1000,
+ alpha = 0.2,
+ width = 800,
+ height = 400,
+ yDomain = [0, 1]
+ } = options;
+
+ if (
+ !asyncIterable ||
+ typeof asyncIterable[Symbol.asyncIterator] !== "function"
+ ) {
+ throw new TypeError("asyncIterable must be an async iterable");
+ }
+
+ if (!Number.isSafeInteger(maxPoints) || maxPoints < 1) {
+ throw new RangeError("maxPoints must be a positive integer");
+ }
+
+ if (!Number.isFinite(alpha) || alpha < 0 || alpha > 1) {
+ throw new RangeError("alpha must be between 0 and 1");
+ }
+
+ if (
+ !Number.isFinite(width) ||
+ width < 0 ||
+ !Number.isFinite(height) ||
+ height < 0
+ ) {
+ throw new RangeError("width and height must be non-negative numbers");
+ }
+
+ const [yMin, yMax] = Array.isArray(yDomain) ? yDomain : [];
+
+ if (
+ !Number.isFinite(yMin) ||
+ !Number.isFinite(yMax) ||
+ yMin >= yMax
+ ) {
+ throw new RangeError("yDomain must contain two ascending finite numbers");
+ }
+
+ const { scaleLinear, line } = await import(
+ "https://cdn.jsdelivr.net/npm/d3@7/+esm"
+ );
+
+ const data = [];
+ let ema;
+
+ for await (const point of asyncIterable) {
+ if (!point || typeof point !== "object") {
+ throw new TypeError("Each stream item must be an object");
+ }
+
+ const { timestamp, value } = point;
+
+ if (!Number.isFinite(Number(timestamp))) {
+ throw new TypeError("Each timestamp must be numeric or date-like");
+ }
+
+ if (!Number.isFinite(value)) {
+ throw new TypeError("Each value must be a finite number");
+ }
+
+ ema = ema === undefined
+ ? value
+ : alpha * value + (1 - alpha) * 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([yMin, yMax])
+ .range([height, 0]);
+
+ const path = line()
+ .x(point => x(point.timestamp))
+ .y(point => y(point.ema))(data);
+
+ return { data, path };
+}
+export default createStreamVisualizer;
+// Generation time: 27.431s
+// Result: PASS
\ No newline at end of file