mirror of
https://github.com/multipleof4/lynchmark.git
synced 2026-03-17 03:11:01 +00:00
Docs: Update benchmark for openrouter/hunter-alpha
This commit is contained in:
9
tests/10_scrypt_hash/outputs/openrouter_hunter-alpha.js
Normal file
9
tests/10_scrypt_hash/outputs/openrouter_hunter-alpha.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
async function hashPassword(password, salt) {
|
||||||
|
const { scrypt } = await import('https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/+esm');
|
||||||
|
const encode = str => new TextEncoder().encode(str);
|
||||||
|
const hash = await scrypt(encode(password), encode(salt), 1024, 8, 1, 32);
|
||||||
|
return Array.from(hash, b => b.toString(16).padStart(2, '0')).join('');
|
||||||
|
}
|
||||||
|
export default hashPassword;
|
||||||
|
// Generation time: 7.014s
|
||||||
|
// Result: PASS
|
||||||
15
tests/11_geospatial/outputs/openrouter_hunter-alpha.js
Normal file
15
tests/11_geospatial/outputs/openrouter_hunter-alpha.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
```javascript
|
||||||
|
const analyzeGPS = async (readings, boundary) => {
|
||||||
|
const turf = await import('https://unpkg.com/@turf/turf@6/turf.min.js');
|
||||||
|
const boundaryPolygon = turf.polygon(boundary.coordinates);
|
||||||
|
const validReadings = readings.filter(r =>
|
||||||
|
turf.booleanPointInPolygon(turf.point(r.loc), boundaryPolygon)
|
||||||
|
);
|
||||||
|
const sorted = validReadings.sort((a, b) => a.ts - b.ts);
|
||||||
|
if (sorted.length < 2) return 0;
|
||||||
|
const line = turf.lineString(sorted.map(r => r.loc));
|
||||||
|
return Math.round(turf.length(line, {units: 'kilometers'}) * 100) / 100;
|
||||||
|
};
|
||||||
|
export default analyzeGPS;
|
||||||
|
// Generation time: 56.302s
|
||||||
|
// Result: FAIL
|
||||||
48
tests/12_mst_pipeline/outputs/openrouter_hunter-alpha.js
Normal file
48
tests/12_mst_pipeline/outputs/openrouter_hunter-alpha.js
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
async function computeMST(tomlStr) {
|
||||||
|
const [tomlMod, heapMod, tableMod] = await Promise.all([
|
||||||
|
import('https://esm.sh/smol-toml'),
|
||||||
|
import('https://esm.sh/mnemonist/heap'),
|
||||||
|
import('https://esm.sh/text-table')
|
||||||
|
]);
|
||||||
|
const {parse} = tomlMod;
|
||||||
|
const {default: Heap} = heapMod;
|
||||||
|
const {default: textTable} = tableMod;
|
||||||
|
|
||||||
|
const edges = parse(tomlStr).edges;
|
||||||
|
const nodes = new Set();
|
||||||
|
for (const e of edges) { nodes.add(e.from); nodes.add(e.to); }
|
||||||
|
|
||||||
|
const heap = new Heap((a, b) => a.weight - b.weight);
|
||||||
|
edges.forEach(e => heap.push(e));
|
||||||
|
|
||||||
|
const p = {}, r = {};
|
||||||
|
function find(x) { return p[x] === x ? x : (p[x] = find(p[x])); }
|
||||||
|
function union(a, b) {
|
||||||
|
a = find(a); b = find(b);
|
||||||
|
if (a === b) return false;
|
||||||
|
if (r[a] < r[b]) [a, b] = [b, a];
|
||||||
|
p[b] = a;
|
||||||
|
if (r[a] === r[b]) r[a]++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
nodes.forEach(n => { p[n] = n; r[n] = 0; });
|
||||||
|
|
||||||
|
const mst = [];
|
||||||
|
let total = 0;
|
||||||
|
const needed = nodes.size - 1;
|
||||||
|
while (heap.size > 0 && mst.length < needed) {
|
||||||
|
const e = heap.pop();
|
||||||
|
if (union(e.from, e.to)) {
|
||||||
|
mst.push([e.from, e.to, String(e.weight)]);
|
||||||
|
total += e.weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
table: textTable([['From', 'To', 'Weight'], ...mst]),
|
||||||
|
totalWeight: total
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export default computeMST;
|
||||||
|
// Generation time: 23.699s
|
||||||
|
// Result: PASS
|
||||||
25
tests/1_dijkstra/outputs/openrouter_hunter-alpha.js
Normal file
25
tests/1_dijkstra/outputs/openrouter_hunter-alpha.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
async function findShortestPath(graph, start, end) {
|
||||||
|
const PriorityQueue = (await import('https://esm.sh/js-priority-queue@0.1.5')).default
|
||||||
|
const dist = Object.fromEntries(Object.keys(graph).map(n => [n, Infinity]))
|
||||||
|
const pq = new PriorityQueue({ comparator: (a, b) => a[1] - b[1] })
|
||||||
|
dist[start] = 0
|
||||||
|
pq.queue([start, 0])
|
||||||
|
|
||||||
|
while (pq.length) {
|
||||||
|
const [node, d] = pq.dequeue()
|
||||||
|
if (node === end) return d
|
||||||
|
if (d > dist[node]) continue
|
||||||
|
|
||||||
|
for (const [neigh, w] of Object.entries(graph[node])) {
|
||||||
|
const nd = d + w
|
||||||
|
if (nd < dist[neigh]) {
|
||||||
|
dist[neigh] = nd
|
||||||
|
pq.queue([neigh, nd])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Infinity
|
||||||
|
}
|
||||||
|
export default findShortestPath;
|
||||||
|
// Generation time: 35.807s
|
||||||
|
// Result: PASS
|
||||||
30
tests/2_convex_hull/outputs/openrouter_hunter-alpha.js
Normal file
30
tests/2_convex_hull/outputs/openrouter_hunter-alpha.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
const findConvexHull = async points => {
|
||||||
|
const _ = await import('https://unpkg.com/lodash@4.17.21/lodash.js');
|
||||||
|
const sorted = _.uniqWith(_.sortBy(points, ['x', 'y']), _.isEqual);
|
||||||
|
if (sorted.length <= 2) return sorted;
|
||||||
|
|
||||||
|
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
|
||||||
|
|
||||||
|
const lower = [];
|
||||||
|
for (let i = 0; i < sorted.length; i++) {
|
||||||
|
while (lower.length >= 2 && cross(lower[lower.length - 2], lower[lower.length - 1], sorted[i]) <= 0) {
|
||||||
|
lower.pop();
|
||||||
|
}
|
||||||
|
lower.push(sorted[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const upper = [];
|
||||||
|
for (let i = sorted.length - 1; i >= 0; i--) {
|
||||||
|
while (upper.length >= 2 && cross(upper[upper.length - 2], upper[upper.length - 1], sorted[i]) <= 0) {
|
||||||
|
upper.pop();
|
||||||
|
}
|
||||||
|
upper.push(sorted[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
lower.pop();
|
||||||
|
upper.pop();
|
||||||
|
return [...lower, ...upper];
|
||||||
|
};
|
||||||
|
export default findConvexHull;
|
||||||
|
// Generation time: 17.814s
|
||||||
|
// Result: FAIL
|
||||||
49
tests/3_signal_pipeline/outputs/openrouter_hunter-alpha.js
Normal file
49
tests/3_signal_pipeline/outputs/openrouter_hunter-alpha.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
const analyzeSignal = async yamlStr => {
|
||||||
|
const [{default: yaml}, {default: math}, {default: ndarray}, {default: fft}, {default: DOMPurify}] = await Promise.all([
|
||||||
|
import('https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs'),
|
||||||
|
import('https://cdn.jsdelivr.net/npm/mathjs@11.11.0/lib/browser/math.js'),
|
||||||
|
import('https://cdn.skypack.dev/ndarray@1.0.19'),
|
||||||
|
import('https://cdn.skypack.dev/ndarray-fft@1.0.3'),
|
||||||
|
import('https://cdn.jsdelivr.net/npm/dompurify@3.0.6/dist/purify.min.js'),
|
||||||
|
])
|
||||||
|
|
||||||
|
const config = yaml.load(yamlStr)
|
||||||
|
const N = config.sampleRate * config.duration
|
||||||
|
|
||||||
|
const signal = Array.from({length: N}, (_, i) => {
|
||||||
|
const t = i / config.sampleRate
|
||||||
|
return config.components.reduce((sum, {frequency, amplitude}) =>
|
||||||
|
sum + amplitude * math.sin(2 * math.pi * frequency * t), 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
const real = ndarray(signal)
|
||||||
|
const imag = ndarray(Array(N).fill(0))
|
||||||
|
|
||||||
|
fft(1, real, imag)
|
||||||
|
|
||||||
|
const magnitudes = Array.from({length: Math.floor(N / 2) + 1}, (_, k) => ({
|
||||||
|
magnitude: math.sqrt(real.get(k) ** 2 + imag.get(k) ** 2) / (N / 2),
|
||||||
|
frequencyHz: Math.round(k * config.sampleRate / N)
|
||||||
|
}))
|
||||||
|
|
||||||
|
const peaks = magnitudes
|
||||||
|
.filter(({magnitude}) => magnitude > 0.1)
|
||||||
|
.map(({frequencyHz, magnitude}) => ({
|
||||||
|
frequencyHz,
|
||||||
|
magnitude: Math.round(magnitude * 100) / 100
|
||||||
|
}))
|
||||||
|
.sort((a, b) => b.magnitude - a.magnitude)
|
||||||
|
|
||||||
|
const html = DOMPurify.sanitize(`
|
||||||
|
<table>
|
||||||
|
<tr><th>Frequency (Hz)</th><th>Magnitude</th></tr>
|
||||||
|
${peaks.map(({frequencyHz, magnitude}) =>
|
||||||
|
`<tr><td>${frequencyHz}</td><td>${magnitude}</td></tr>`).join('')}
|
||||||
|
</table>
|
||||||
|
`)
|
||||||
|
|
||||||
|
return {peaks, html, signalLength: N}
|
||||||
|
}
|
||||||
|
export default analyzeSignal;
|
||||||
|
// Generation time: 22.772s
|
||||||
|
// Result: FAIL
|
||||||
55
tests/4_hexchain_pipeline/outputs/openrouter_hunter-alpha.js
Normal file
55
tests/4_hexchain_pipeline/outputs/openrouter_hunter-alpha.js
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
const hexchain = async (toml) => {
|
||||||
|
const [smolToml, seedrandom, ss, Ajv, textTable, DOMPurify] = await Promise.all([
|
||||||
|
import('https://unpkg.com/smol-toml@1.0.0/index.js'),
|
||||||
|
import('https://unpkg.com/seedrandom@3.0.5/lib/alea.js'),
|
||||||
|
import('https://unpkg.com/simple-statistics@7.8.7/dist/simple-statistics.js'),
|
||||||
|
import('https://unpkg.com/ajv@8.12.0/dist/ajv7.min.js'),
|
||||||
|
import('https://unpkg.com/text-table@0.2.0/index.js'),
|
||||||
|
import('https://unpkg.com/dompurify@3.0.8/dist/purify.js')
|
||||||
|
]);
|
||||||
|
|
||||||
|
const config = smolToml.parse(toml);
|
||||||
|
const ajv = new Ajv.default();
|
||||||
|
const valid = ajv.validate({
|
||||||
|
type: 'object',
|
||||||
|
required: ['seed', 'count', 'label'],
|
||||||
|
properties: {
|
||||||
|
seed: { type: 'string' },
|
||||||
|
count: { type: 'integer', minimum: 1, maximum: 10000 },
|
||||||
|
label: { type: 'string', minLength: 1 }
|
||||||
|
}
|
||||||
|
}, config);
|
||||||
|
|
||||||
|
if (!valid) return { valid: false, errors: ajv.errorsText() };
|
||||||
|
|
||||||
|
const rng = seedrandom(config.seed);
|
||||||
|
const numbers = Array.from({ length: config.count }, () => rng());
|
||||||
|
|
||||||
|
const [mean, stddev, median] = [
|
||||||
|
ss.mean(numbers),
|
||||||
|
ss.standardDeviation(numbers),
|
||||||
|
ss.median(numbers)
|
||||||
|
].map(v => parseFloat(v.toFixed(6)));
|
||||||
|
|
||||||
|
const table = textTable.default([
|
||||||
|
['Stat', 'Value'],
|
||||||
|
['mean', String(mean)],
|
||||||
|
['stddev', String(stddev)],
|
||||||
|
['median', String(median)]
|
||||||
|
]);
|
||||||
|
|
||||||
|
const sanitized = DOMPurify.sanitize(
|
||||||
|
'<pre class="stats">' + table + '</pre>'
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
valid: true,
|
||||||
|
label: config.label,
|
||||||
|
stats: { mean, stddev, median },
|
||||||
|
table: sanitized,
|
||||||
|
count: config.count
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export default hexchain;
|
||||||
|
// Generation time: 19.496s
|
||||||
|
// Result: FAIL
|
||||||
29
tests/5_markdown_parser/outputs/openrouter_hunter-alpha.js
Normal file
29
tests/5_markdown_parser/outputs/openrouter_hunter-alpha.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
const parseMarkdown = async (md) => {
|
||||||
|
const { marked } = await import('https://esm.sh/marked@15.0.7');
|
||||||
|
const { default: DOMPurify } = await import('https://esm.sh/dompurify@3.2.3');
|
||||||
|
|
||||||
|
const renderer = new marked.Renderer();
|
||||||
|
const rules = {
|
||||||
|
heading: (text, level) => `<h${level}>${text}</h${level}>`,
|
||||||
|
paragraph: (text) => `<p>${text}</p>`,
|
||||||
|
strong: (text) => `<strong>${text}</strong>`,
|
||||||
|
em: (text) => `<em>${text}</em>`,
|
||||||
|
link: (href, title, text) => `<a href="${href}"${title ? ` title="${title}"` : ''}>${text}</a>`,
|
||||||
|
code: (code) => `<pre><code>${code}</code></pre>`,
|
||||||
|
codespan: (code) => `<code>${code}</code>`,
|
||||||
|
list: (body, ordered) => ordered ? `<ol>${body}</ol>` : `<ul>${body}</ul>`,
|
||||||
|
listitem: (text) => `<li>${text}</li>`,
|
||||||
|
blockquote: (quote) => `<blockquote>${quote}</blockquote>`
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.keys(rules).forEach(rule => {
|
||||||
|
renderer[rule] = (...args) => rules[rule](...args);
|
||||||
|
});
|
||||||
|
|
||||||
|
marked.use({ renderer, breaks: true, gfm: true });
|
||||||
|
const rawHtml = marked.parse(md);
|
||||||
|
return DOMPurify.sanitize(rawHtml);
|
||||||
|
};
|
||||||
|
export default parseMarkdown;
|
||||||
|
// Generation time: 11.318s
|
||||||
|
// Result: FAIL
|
||||||
22
tests/6_csv_processor/outputs/openrouter_hunter-alpha.js
Normal file
22
tests/6_csv_processor/outputs/openrouter_hunter-alpha.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
const processCSV = async (csv, { filterColumn, filterValue, groupBy, aggregateColumn, operation }) => {
|
||||||
|
const [{ default: Papa }, { default: _ }] = await Promise.all([
|
||||||
|
import('https://cdn.jsdelivr.net/npm/papaparse@5.4.1/papaparse.min.js'),
|
||||||
|
import('https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js')
|
||||||
|
]);
|
||||||
|
|
||||||
|
const { data } = Papa.parse(csv.trim(), { header: true, dynamicTyping: true });
|
||||||
|
const filtered = data.filter(row => row[filterColumn] == filterValue);
|
||||||
|
const groups = _.groupBy(filtered, groupBy);
|
||||||
|
|
||||||
|
return Object.entries(groups).map(([key, rows]) => {
|
||||||
|
const values = rows.map(row => Number(row[aggregateColumn]) || 0);
|
||||||
|
const result = operation === 'sum' ? values.reduce((a, b) => a + b, 0)
|
||||||
|
: operation === 'avg' ? values.reduce((a, b) => a + b, 0) / values.length
|
||||||
|
: rows.length;
|
||||||
|
|
||||||
|
return { [groupBy]: key, result };
|
||||||
|
});
|
||||||
|
};
|
||||||
|
export default processCSV;
|
||||||
|
// Generation time: 20.976s
|
||||||
|
// Result: FAIL
|
||||||
71
tests/7_scheduler/outputs/openrouter_hunter-alpha.js
Normal file
71
tests/7_scheduler/outputs/openrouter_hunter-alpha.js
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
async function findAvailableSlots(cal1, cal2, constraints) {
|
||||||
|
const { default: dayjs } = await import('https://cdn.skypack.dev/dayjs@1.11.10');
|
||||||
|
const { default: utc } = await import('https://cdn.skypack.dev/dayjs@1.11.10/plugin/utc');
|
||||||
|
dayjs.extend(utc);
|
||||||
|
|
||||||
|
const toMin = d => dayjs.utc(d).diff(dayjs.utc(constraints.searchRange.start), 'minute');
|
||||||
|
const toISO = m => dayjs.utc(constraints.searchRange.start).add(m, 'minute').toISOString();
|
||||||
|
const parseHM = s => { const [h, m] = s.split(':').map(Number); return h * 60 + m; };
|
||||||
|
const clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
||||||
|
|
||||||
|
const allBusy = [...cal1, ...cal2]
|
||||||
|
.map(({ start, end }) => [toMin(start), toMin(end)])
|
||||||
|
.filter(([s, e]) => s < e && e > 0)
|
||||||
|
.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
|
||||||
|
|
||||||
|
const merged = allBusy.reduce((acc, [s, e]) => {
|
||||||
|
if (!acc.length || s > acc[acc.length - 1][1]) acc.push([s, e]);
|
||||||
|
else acc[acc.length - 1][1] = Math.max(acc[acc.length - 1][1], e);
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const rangeStart = 0;
|
||||||
|
const rangeEnd = toMin(constraints.searchRange.end);
|
||||||
|
const workStartMin = parseHM(constraints.workHours.start);
|
||||||
|
const workEndMin = parseHM(constraints.workHours.end);
|
||||||
|
const duration = constraints.durationMinutes;
|
||||||
|
const slots = [];
|
||||||
|
|
||||||
|
const dayStart = dayjs.utc(constraints.searchRange.start).startOf('day');
|
||||||
|
let current = rangeStart;
|
||||||
|
|
||||||
|
while (current < rangeEnd) {
|
||||||
|
const dayDiff = Math.floor(current / 1440);
|
||||||
|
const dayBase = dayStart.add(dayDiff, 'day');
|
||||||
|
const dayStartMin = dayDiff * 1440;
|
||||||
|
const dayWorkStart = dayBase.add(workStartMin, 'minute');
|
||||||
|
const dayWorkEnd = dayBase.add(workEndMin, 'minute');
|
||||||
|
const dayWorkStartMin = toMin(dayWorkStart);
|
||||||
|
const dayWorkEndMin = toMin(dayWorkEnd);
|
||||||
|
|
||||||
|
if (current < dayWorkStartMin) {
|
||||||
|
current = dayWorkStartMin;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current >= dayWorkEndMin) {
|
||||||
|
current = dayStartMin + 1440;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const busyBlock = merged.find(([s]) => s > current);
|
||||||
|
const nextBusyStart = busyBlock ? busyBlock[0] : rangeEnd;
|
||||||
|
const freeEnd = Math.min(nextBusyStart, dayWorkEndMin, rangeEnd);
|
||||||
|
|
||||||
|
if (freeEnd - current >= duration) {
|
||||||
|
let slotStart = current;
|
||||||
|
while (slotStart + duration <= freeEnd) {
|
||||||
|
slots.push({ start: toISO(slotStart), end: toISO(slotStart + duration) });
|
||||||
|
slotStart += duration;
|
||||||
|
}
|
||||||
|
current = slotStart;
|
||||||
|
} else {
|
||||||
|
current = freeEnd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return slots;
|
||||||
|
}
|
||||||
|
export default findAvailableSlots;
|
||||||
|
// Generation time: 25.925s
|
||||||
|
// Result: FAIL
|
||||||
20
tests/8_json_validator/outputs/openrouter_hunter-alpha.js
Normal file
20
tests/8_json_validator/outputs/openrouter_hunter-alpha.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
async function validateJSON(data, schema) {
|
||||||
|
try {
|
||||||
|
const { default: Ajv } = await import('https://cdn.jsdelivr.net/npm/ajv@8/+esm');
|
||||||
|
const ajv = new Ajv({ allErrors: true });
|
||||||
|
const validate = ajv.compile(schema);
|
||||||
|
const valid = validate(data);
|
||||||
|
|
||||||
|
return {
|
||||||
|
valid,
|
||||||
|
errors: valid ? [] : validate.errors.map(e =>
|
||||||
|
`${e.instancePath || '/'} ${e.message}`
|
||||||
|
)
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return { valid: false, errors: [`Validation error: ${error.message}`] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default validateJSON;
|
||||||
|
// Generation time: 20.147s
|
||||||
|
// Result: PASS
|
||||||
36
tests/9_stream_visualizer/outputs/openrouter_hunter-alpha.js
Normal file
36
tests/9_stream_visualizer/outputs/openrouter_hunter-alpha.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
async function createStreamVisualizer(asyncIterable, options) {
|
||||||
|
const { maxPoints, alpha, width, height, yDomain } = options;
|
||||||
|
const data = [];
|
||||||
|
let ema;
|
||||||
|
|
||||||
|
for await (const point of asyncIterable) {
|
||||||
|
if (ema === undefined) {
|
||||||
|
ema = point.value;
|
||||||
|
} else {
|
||||||
|
ema = alpha * point.value + (1 - alpha) * ema;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.push({ timestamp: point.timestamp, value: point.value, ema });
|
||||||
|
if (data.length > maxPoints) {
|
||||||
|
data.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.length === 0) {
|
||||||
|
return { data, path: '' };
|
||||||
|
}
|
||||||
|
|
||||||
|
const d3 = await import('https://cdn.jsdelivr.net/npm/d3@7/+esm');
|
||||||
|
const xDomain = [data[0].timestamp, data[data.length - 1].timestamp];
|
||||||
|
const xScale = d3.scaleLinear().domain(xDomain).range([0, width]);
|
||||||
|
const yScale = d3.scaleLinear().domain(yDomain).range([height, 0]);
|
||||||
|
|
||||||
|
const lineGenerator = d3.line()
|
||||||
|
.x(d => xScale(d.timestamp))
|
||||||
|
.y(d => yScale(d.ema));
|
||||||
|
|
||||||
|
return { data, path: lineGenerator(data) };
|
||||||
|
}
|
||||||
|
export default createStreamVisualizer;
|
||||||
|
// Generation time: 21.308s
|
||||||
|
// Result: PASS
|
||||||
Reference in New Issue
Block a user