mirror of
https://github.com/multipleof4/lynchmark.git
synced 2026-03-17 03:11:01 +00:00
Refactor: Remove stale benchmark outputs
This commit is contained in:
@@ -1,11 +0,0 @@
|
|||||||
async function hashPassword(password, salt) {
|
|
||||||
const { scrypt } = await import("https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/+esm");
|
|
||||||
const enc = new TextEncoder();
|
|
||||||
const passwordBytes = enc.encode(password);
|
|
||||||
const saltBytes = enc.encode(salt);
|
|
||||||
const hash = await scrypt(passwordBytes, saltBytes, 1024, 8, 1, 32);
|
|
||||||
return Array.from(hash, b => b.toString(16).padStart(2, "0")).join("");
|
|
||||||
}
|
|
||||||
export default hashPassword;
|
|
||||||
// Generation time: 3.538s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
async function hashPassword(password, salt) {
|
|
||||||
const { scrypt } = await import("https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/+esm");
|
|
||||||
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: 2.342s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
const hashPassword = async (password, salt) => {
|
|
||||||
const { scrypt } = await import('https://cdn.jsdelivr.net/npm/scrypt-js@3.1.7/+esm');
|
|
||||||
const encoder = new TextEncoder();
|
|
||||||
|
|
||||||
const derivedKey = await scrypt(
|
|
||||||
encoder.encode(password),
|
|
||||||
encoder.encode(salt),
|
|
||||||
1024,
|
|
||||||
8,
|
|
||||||
1,
|
|
||||||
32
|
|
||||||
);
|
|
||||||
|
|
||||||
return Array.from(derivedKey, byte => byte.toString(16).padStart(2, '0')).join('');
|
|
||||||
};
|
|
||||||
export default hashPassword;
|
|
||||||
// Generation time: 9.228s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
async function hashPassword(password, salt) {
|
|
||||||
const scrypt = (await import("https://cdnjs.cloudflare.com/ajax/libs/scrypt-js/0.0.2/index.js")).scrypt;
|
|
||||||
const encoder = new TextEncoder();
|
|
||||||
const passwordBytes = encoder.encode(password);
|
|
||||||
const saltBytes = encoder.encode(salt);
|
|
||||||
const derivedKey = await scrypt(passwordBytes, saltBytes, 1024, 8, 1, 32);
|
|
||||||
return Array.from(derivedKey)
|
|
||||||
.map(b => b.toString(16).padStart(2, '0'))
|
|
||||||
.join('');
|
|
||||||
}
|
|
||||||
export default hashPassword;
|
|
||||||
// Generation time: 3.507s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
let _scrypt;
|
|
||||||
|
|
||||||
export async function hashPassword(password, salt) {
|
|
||||||
if (!_scrypt) {
|
|
||||||
const mod = await import('https://cdn.skypack.dev/scrypt-js');
|
|
||||||
_scrypt = mod.default || mod.scrypt;
|
|
||||||
}
|
|
||||||
const hash = await _scrypt(new TextEncoder().encode(password), new TextEncoder().encode(salt), {
|
|
||||||
N: 1024,
|
|
||||||
r: 8,
|
|
||||||
p: 1,
|
|
||||||
dkLen: 32
|
|
||||||
});
|
|
||||||
return [...hash].map(b => b.toString(16).padStart(2, '0')).join('');
|
|
||||||
}
|
|
||||||
export default hashPassword;
|
|
||||||
// Generation time: 17.866s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
async function hashPassword(password, salt) {
|
|
||||||
const { scrypt } = await import('https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/dist/scrypt.min.js');
|
|
||||||
const enc = new TextEncoder();
|
|
||||||
const buf = await scrypt(enc.encode(password), enc.encode(salt), 1024, 8, 1, 32);
|
|
||||||
return Array.from(buf, b => b.toString(16).padStart(2, '0')).join('');
|
|
||||||
}
|
|
||||||
export default hashPassword;
|
|
||||||
// Generation time: 39.100s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
const enc=new TextEncoder()
|
|
||||||
async function hashPassword(p,s){
|
|
||||||
const{default:scrypt}=await import('https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/+esm')
|
|
||||||
const u=await scrypt(enc.encode(p),enc.encode(s),1024,8,1,32)
|
|
||||||
return[...u].map(x=>x.toString(16).padStart(2,'0')).join('')
|
|
||||||
}
|
|
||||||
export default hashPassword;
|
|
||||||
// Generation time: 12.207s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
const hashPassword=async(p,s)=>{
|
|
||||||
const {scrypt}=await import('https://cdn.skypack.dev/scrypt-js')
|
|
||||||
const e=new TextEncoder
|
|
||||||
const h=await scrypt(e.encode(p),e.encode(s),1024,8,1,32)
|
|
||||||
return [...h].map(b=>b.toString(16).padStart(2,'0')).join('')
|
|
||||||
}
|
|
||||||
export default hashPassword;
|
|
||||||
// Generation time: 8.405s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
const scryptUrl = "https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/+esm";
|
|
||||||
const te = new TextEncoder();
|
|
||||||
const N = 1024, r = 8, p = 1, dkLen = 32;
|
|
||||||
let scryptP;
|
|
||||||
|
|
||||||
const getScrypt = () =>
|
|
||||||
scryptP ??= import(scryptUrl).then(m => {
|
|
||||||
const f = m.scrypt || m.default?.scrypt || m.default;
|
|
||||||
if (typeof f != "function") throw Error("scrypt-js: missing scrypt export");
|
|
||||||
return f;
|
|
||||||
});
|
|
||||||
|
|
||||||
const toHex = u8 =>
|
|
||||||
Array.from(u8, b => b.toString(16).padStart(2, "0")).join("");
|
|
||||||
|
|
||||||
async function hashPassword(password, salt) {
|
|
||||||
if (typeof password != "string" || typeof salt != "string") throw TypeError("Expected (string, string)");
|
|
||||||
const scrypt = await getScrypt();
|
|
||||||
const key = await scrypt(te.encode(password), te.encode(salt), N, r, p, dkLen);
|
|
||||||
return toHex(key);
|
|
||||||
}
|
|
||||||
export default hashPassword;
|
|
||||||
// Generation time: 101.462s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
async function analyzeGPS(readings, boundary) {
|
|
||||||
const turf = await import("https://cdn.jsdelivr.net/npm/@turf/turf@7/+esm");
|
|
||||||
|
|
||||||
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 line = turf.lineString(valid.map(r => r.loc));
|
|
||||||
const len = turf.length(line, { units: "kilometers" });
|
|
||||||
|
|
||||||
return Math.round(len * 100) / 100;
|
|
||||||
}
|
|
||||||
export default analyzeGPS;
|
|
||||||
// Generation time: 3.692s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
async function analyzeGPS(readings, boundary) {
|
|
||||||
const turf = await import("https://cdn.jsdelivr.net/npm/@turf/turf@7/+esm");
|
|
||||||
|
|
||||||
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 line = turf.lineString(valid.map(r => r.loc));
|
|
||||||
const len = turf.length(line, { units: "kilometers" });
|
|
||||||
|
|
||||||
return Math.round(len * 100) / 100;
|
|
||||||
}
|
|
||||||
export default analyzeGPS;
|
|
||||||
// Generation time: 3.774s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
export async function analyzeGPS(readings, boundary) {
|
|
||||||
const T = await import('https://cdn.jsdelivr.net/npm/@turf/turf/+esm');
|
|
||||||
|
|
||||||
const pts = readings
|
|
||||||
.filter(({ loc }) => T.booleanPointInPolygon(loc, boundary))
|
|
||||||
.sort((a, b) => a.ts - b.ts)
|
|
||||||
.map(({ loc }) => loc);
|
|
||||||
|
|
||||||
if (pts.length < 2) return 0;
|
|
||||||
|
|
||||||
const len = T.length(T.lineString(pts), { units: 'kilometers' });
|
|
||||||
|
|
||||||
return Math.round(len * 100) / 100;
|
|
||||||
}
|
|
||||||
export default analyzeGPS;
|
|
||||||
// Generation time: 9.884s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
async function analyzeGPS(readings, boundary) {
|
|
||||||
if (!readings?.length) return 0;
|
|
||||||
const turf = await import('https://cdn.skypack.dev/@turf/turf');
|
|
||||||
const valid = readings.filter(r => turf.booleanPointInPolygon(r.loc, boundary));
|
|
||||||
valid.sort((a, b) => a.ts - b.ts);
|
|
||||||
if (valid.length < 2) return 0;
|
|
||||||
const line = turf.lineString(valid.map(r => r.loc));
|
|
||||||
return Math.round(turf.length(line, { units: 'kilometers' }) * 100) / 100;
|
|
||||||
}
|
|
||||||
export default analyzeGPS;
|
|
||||||
// Generation time: 6.167s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
export async function analyzeGPS(readings, boundary) {
|
|
||||||
const t = await import('https://cdn.skypack.dev/@turf/turf')
|
|
||||||
const v = readings.filter(r => t.booleanPointInPolygon(r.loc, boundary)).sort((a,b) => a.ts-b.ts)
|
|
||||||
if(v.length < 2) return 0
|
|
||||||
const coords = v.map(r => r.loc)
|
|
||||||
const line = t.lineString(coords)
|
|
||||||
return Math.round(t.length(line, {units:'kilometers'})*100)/100
|
|
||||||
}
|
|
||||||
export default analyzeGPS;
|
|
||||||
// Generation time: 11.219s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
async function analyzeGPS(readings, boundary) {
|
|
||||||
const isValid = r => r?.ts != null && Array.isArray(r?.loc) && r.loc.length === 2;
|
|
||||||
const valid = readings?.filter(isValid) || [];
|
|
||||||
if (valid.length < 2) return 0;
|
|
||||||
|
|
||||||
const turf = await import('https://cdn.skypack.dev/@turf/turf').catch(() => null);
|
|
||||||
if (!turf) return 0;
|
|
||||||
|
|
||||||
const points = valid
|
|
||||||
.filter(r => turf.booleanPointInPolygon(r.loc, boundary))
|
|
||||||
.sort((a, b) => a.ts - b.ts)
|
|
||||||
.map(r => r.loc);
|
|
||||||
|
|
||||||
return points.length < 2 ? 0 : Math.round(turf.length(turf.lineString(points), {units: 'kilometers'}) * 100) / 100;
|
|
||||||
}
|
|
||||||
export default analyzeGPS;
|
|
||||||
// Generation time: 48.580s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
async function analyzeGPS(readings, boundary) {
|
|
||||||
const { point, booleanPointInPolygon, lineString, length } = await import('https://cdn.skypack.dev/@turf/turf')
|
|
||||||
const v = readings.filter(r => booleanPointInPolygon(point(r.loc), boundary, { ignoreBoundary: true })).sort((a, b) => a.ts - b.ts)
|
|
||||||
if (v.length < 2) return 0
|
|
||||||
const l = lineString(v.map(r => r.loc))
|
|
||||||
return +length(l, { units: 'kilometers' }).toFixed(2)
|
|
||||||
}
|
|
||||||
export default analyzeGPS;
|
|
||||||
// Generation time: 10.671s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
let turfReady
|
|
||||||
const loadTurf=()=>turfReady||(turfReady=import('https://cdn.jsdelivr.net/npm/@turf/turf@6.5.0/+esm'))
|
|
||||||
async function analyzeGPS(readings,boundary){
|
|
||||||
const {point,lineString,length,booleanPointInPolygon}=await loadTurf()
|
|
||||||
const inBounds=readings.filter(r=>booleanPointInPolygon(point(r.loc),boundary,{ignoreBoundary:true})).sort((a,b)=>a.ts-b.ts)
|
|
||||||
if(inBounds.length<2)return 0
|
|
||||||
const km=length(lineString(inBounds.map(r=>r.loc)),{units:'kilometers'})
|
|
||||||
return +km.toFixed(2)
|
|
||||||
}
|
|
||||||
export default analyzeGPS;
|
|
||||||
// Generation time: 8.791s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
const TURF_SRC = "https://cdn.jsdelivr.net/npm/@turf/turf@6.5.0/+esm"
|
|
||||||
let turfP
|
|
||||||
const turf = () => turfP || (turfP = import(TURF_SRC))
|
|
||||||
|
|
||||||
async function analyzeGPS(readings, boundary) {
|
|
||||||
if (!Array.isArray(readings) || !boundary) return 0
|
|
||||||
|
|
||||||
const {
|
|
||||||
point: pt,
|
|
||||||
booleanPointInPolygon: inPoly,
|
|
||||||
lineString: ls,
|
|
||||||
length: len
|
|
||||||
} = await turf()
|
|
||||||
|
|
||||||
const ok = []
|
|
||||||
for (const r of readings) {
|
|
||||||
const ts = +r?.ts
|
|
||||||
const loc = [+r?.loc?.[0], +r?.loc?.[1]]
|
|
||||||
if (!Number.isFinite(ts) || loc.some(n => !Number.isFinite(n))) continue
|
|
||||||
if (inPoly(pt(loc), boundary, { ignoreBoundary: true })) ok.push({ ts, loc })
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ok.length < 2) return 0
|
|
||||||
ok.sort((a, b) => a.ts - b.ts)
|
|
||||||
|
|
||||||
const km = len(ls(ok.map(r => r.loc)), { units: "kilometers" })
|
|
||||||
return Number.isFinite(km) ? +km.toFixed(2) : 0
|
|
||||||
}
|
|
||||||
export default analyzeGPS;
|
|
||||||
// Generation time: 113.549s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
async function findShortestPath(graph, start, end) {
|
|
||||||
const { default: PriorityQueue } = await import(
|
|
||||||
"https://cdn.jsdelivr.net/npm/js-priority-queue@0.4.1/+esm"
|
|
||||||
);
|
|
||||||
|
|
||||||
const dist = {};
|
|
||||||
for (const node in graph) dist[node] = Infinity;
|
|
||||||
dist[start] = 0;
|
|
||||||
|
|
||||||
const pq = new PriorityQueue({ comparator: (a, b) => a[1] - b[1] });
|
|
||||||
pq.queue([start, 0]);
|
|
||||||
|
|
||||||
const visited = new Set();
|
|
||||||
|
|
||||||
while (pq.length > 0) {
|
|
||||||
const [node, d] = pq.dequeue();
|
|
||||||
|
|
||||||
if (visited.has(node)) continue;
|
|
||||||
visited.add(node);
|
|
||||||
|
|
||||||
if (node === end) return d;
|
|
||||||
|
|
||||||
const neighbors = graph[node] || {};
|
|
||||||
for (const neighbor in neighbors) {
|
|
||||||
if (visited.has(neighbor)) continue;
|
|
||||||
const newDist = d + neighbors[neighbor];
|
|
||||||
if (newDist < dist[neighbor]) {
|
|
||||||
dist[neighbor] = newDist;
|
|
||||||
pq.queue([neighbor, newDist]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dist[end] ?? Infinity;
|
|
||||||
}
|
|
||||||
export default findShortestPath;
|
|
||||||
// Generation time: 5.576s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
async function findShortestPath(graph, start, end) {
|
|
||||||
const { default: PriorityQueue } = await import(
|
|
||||||
"https://cdn.jsdelivr.net/npm/js-priority-queue@0.4.1/+esm"
|
|
||||||
);
|
|
||||||
|
|
||||||
const dist = {};
|
|
||||||
for (const node in graph) dist[node] = Infinity;
|
|
||||||
dist[start] = 0;
|
|
||||||
|
|
||||||
const pq = new PriorityQueue({ comparator: (a, b) => a[1] - b[1] });
|
|
||||||
pq.queue([start, 0]);
|
|
||||||
|
|
||||||
const visited = new Set();
|
|
||||||
|
|
||||||
while (pq.length > 0) {
|
|
||||||
const [node, d] = pq.dequeue();
|
|
||||||
|
|
||||||
if (node === end) return d;
|
|
||||||
if (visited.has(node)) continue;
|
|
||||||
visited.add(node);
|
|
||||||
|
|
||||||
if (!graph[node]) continue;
|
|
||||||
|
|
||||||
for (const [neighbor, weight] of Object.entries(graph[node])) {
|
|
||||||
const newDist = d + weight;
|
|
||||||
if (newDist < (dist[neighbor] ?? Infinity)) {
|
|
||||||
dist[neighbor] = newDist;
|
|
||||||
pq.queue([neighbor, newDist]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dist[end] ?? Infinity;
|
|
||||||
}
|
|
||||||
export default findShortestPath;
|
|
||||||
// Generation time: 5.349s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
export const findShortestPath = async (graph, start, end) => {
|
|
||||||
const { default: PQ } = await import('https://cdn.skypack.dev/js-priority-queue');
|
|
||||||
|
|
||||||
const dists = { [start]: 0 };
|
|
||||||
const pq = new PQ({ comparator: (a, b) => a.w - b.w });
|
|
||||||
|
|
||||||
pq.queue({ n: start, w: 0 });
|
|
||||||
|
|
||||||
while (pq.length) {
|
|
||||||
const { n, w } = pq.dequeue();
|
|
||||||
|
|
||||||
if (n === end) return w;
|
|
||||||
if (w > (dists[n] ?? Infinity)) continue;
|
|
||||||
|
|
||||||
for (const [neighbor, weight] of Object.entries(graph[n] ?? {})) {
|
|
||||||
const total = w + weight;
|
|
||||||
if (total < (dists[neighbor] ?? Infinity)) {
|
|
||||||
dists[neighbor] = total;
|
|
||||||
pq.queue({ n: neighbor, w: total });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Infinity;
|
|
||||||
};
|
|
||||||
export default findShortestPath;
|
|
||||||
// Generation time: 12.594s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
export async function findShortestPath(graph, start, end) {
|
|
||||||
const { PriorityQueue } = await import("https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.15/+esm");
|
|
||||||
|
|
||||||
const distances = {};
|
|
||||||
const visited = new Set();
|
|
||||||
const queue = new PriorityQueue({ comparator: (a, b) => a.distance - b.distance });
|
|
||||||
|
|
||||||
for (const node in graph) {
|
|
||||||
distances[node] = Infinity;
|
|
||||||
}
|
|
||||||
distances[start] = 0;
|
|
||||||
queue.enqueue({ node: start, distance: 0 });
|
|
||||||
|
|
||||||
while (queue.length > 0) {
|
|
||||||
const { node: current, distance } = queue.dequeue();
|
|
||||||
|
|
||||||
if (current === end) return distance;
|
|
||||||
if (visited.has(current)) continue;
|
|
||||||
visited.add(current);
|
|
||||||
|
|
||||||
for (const [neighbor, weight] of Object.entries(graph[current] || {})) {
|
|
||||||
const newDistance = distance + weight;
|
|
||||||
if (newDistance < distances[neighbor]) {
|
|
||||||
distances[neighbor] = newDistance;
|
|
||||||
queue.enqueue({ node: neighbor, distance: newDistance });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Infinity;
|
|
||||||
}
|
|
||||||
export default findShortestPath;
|
|
||||||
// Generation time: 4.700s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
export async function findShortestPath(graph, start, end) {
|
|
||||||
if (start === end) return 0;
|
|
||||||
if (!graph || !graph[start] || !graph[end]) return Infinity;
|
|
||||||
|
|
||||||
const { default: PQ } = await import('https://cdn.skypack.dev/js-priority-queue@0.2.0?min') ||
|
|
||||||
(await import('https://unpkg.com/js-priority-queue@0.2.0/dist/js-priority-queue.min.js')) ||
|
|
||||||
{ default: self.PriorityQueue };
|
|
||||||
const pq = new PQ({ comparator: (a, b) => a.d - b.d });
|
|
||||||
|
|
||||||
const dist = Object.create(null);
|
|
||||||
const q = new Set(Object.keys(graph));
|
|
||||||
|
|
||||||
for (const k of q) dist[k] = Infinity;
|
|
||||||
dist[start] = 0;
|
|
||||||
pq.enqueue({ n: start, d: 0 });
|
|
||||||
|
|
||||||
while (pq.length) {
|
|
||||||
const { n: u, d: du } = pq.dequeue();
|
|
||||||
if (du !== dist[u]) continue;
|
|
||||||
if (u === end) return du;
|
|
||||||
const nb = graph[u] || {};
|
|
||||||
for (const v in nb) {
|
|
||||||
if (!q.has(v)) continue;
|
|
||||||
const w = +nb[v];
|
|
||||||
if (!isFinite(w)) continue;
|
|
||||||
const nd = du + w;
|
|
||||||
if (nd < dist[v]) {
|
|
||||||
dist[v] = nd;
|
|
||||||
pq.enqueue({ n: v, d: nd });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Infinity;
|
|
||||||
}
|
|
||||||
export default findShortestPath;
|
|
||||||
// Generation time: 18.720s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
let PQ;
|
|
||||||
export async function findShortestPath(g, s, e) {
|
|
||||||
if (!(s in g) || !(e in g)) return Infinity;
|
|
||||||
if (!PQ) ({ default: PQ } = await import('https://cdn.skypack.dev/js-priority-queue@0.1.5'));
|
|
||||||
const d = new Map([[s, 0]]);
|
|
||||||
const q = new PQ({ comparator: (a, b) => a[1] - b[1] });
|
|
||||||
const v = new Set();
|
|
||||||
q.queue([s, 0]);
|
|
||||||
while (q.length) {
|
|
||||||
const [n, c] = q.dequeue();
|
|
||||||
if (n === e) return c;
|
|
||||||
if (v.has(n)) continue;
|
|
||||||
v.add(n);
|
|
||||||
if (c > (d.get(n) ?? Infinity)) continue;
|
|
||||||
for (const [p, w] of Object.entries(g[n] || {})) {
|
|
||||||
const t = c + w;
|
|
||||||
if (t < (d.get(p) ?? Infinity)) {
|
|
||||||
d.set(p, t);
|
|
||||||
q.queue([p, t]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return d.get(e) ?? Infinity;
|
|
||||||
}
|
|
||||||
export default findShortestPath;
|
|
||||||
// Generation time: 95.484s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
async function findShortestPath(g,s,t){
|
|
||||||
let {default:P}=await import('https://cdn.skypack.dev/js-priority-queue')
|
|
||||||
if(!(s in g)||!(t in g))return Infinity
|
|
||||||
let d={},u=new Set,q=new P({comparator:(a,b)=>a[0]-b[0]})
|
|
||||||
Object.keys(g).forEach(k=>d[k]=Infinity)
|
|
||||||
d[s]=0
|
|
||||||
q.queue([0,s])
|
|
||||||
while(q.length){
|
|
||||||
let [w,n]=q.dequeue()
|
|
||||||
if(u.has(n))continue
|
|
||||||
if(n===t)return w
|
|
||||||
u.add(n)
|
|
||||||
for(let m in g[n]){
|
|
||||||
let nw=w+g[n][m]
|
|
||||||
if(nw<d[m])d[m]=nw,q.queue([nw,m])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Infinity
|
|
||||||
}
|
|
||||||
export default findShortestPath;
|
|
||||||
// Generation time: 15.370s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
export const findShortestPath=async(g,s,e)=>{
|
|
||||||
const{default:Q}=await import('https://esm.sh/js-priority-queue')
|
|
||||||
const d={},v=new Set(),q=new Q({comparator:(a,b)=>a[1]-b[1]})
|
|
||||||
for(const k in g)d[k]=Infinity
|
|
||||||
d[s]=0
|
|
||||||
q.queue([s,0])
|
|
||||||
while(q.length){
|
|
||||||
const[n,w]=q.dequeue()
|
|
||||||
if(v.has(n))continue
|
|
||||||
if(n===e)return w
|
|
||||||
v.add(n)
|
|
||||||
for(const[nb,c]of Object.entries(g[n]||{})){
|
|
||||||
const nw=w+c
|
|
||||||
if(nw<d[nb]){
|
|
||||||
d[nb]=nw
|
|
||||||
q.queue([nb,nw])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Infinity
|
|
||||||
}
|
|
||||||
export default findShortestPath;
|
|
||||||
// Generation time: 9.436s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
let _pqP;
|
|
||||||
const _loadPQ = () =>
|
|
||||||
_pqP || (_pqP = import("https://esm.sh/js-priority-queue@0.1.5"));
|
|
||||||
|
|
||||||
async function findShortestPath(graph, start, end) {
|
|
||||||
if (start === end) return 0;
|
|
||||||
if (!graph) return Infinity;
|
|
||||||
|
|
||||||
const { default: PriorityQueue } = await _loadPQ();
|
|
||||||
const dist = Object.create(null);
|
|
||||||
const pq = new PriorityQueue({ comparator: (a, b) => a[0] - b[0] });
|
|
||||||
|
|
||||||
dist[start] = 0;
|
|
||||||
pq.queue([0, start]);
|
|
||||||
|
|
||||||
while (pq.length) {
|
|
||||||
const [d, u] = pq.dequeue();
|
|
||||||
if (d !== dist[u]) continue;
|
|
||||||
if (u === end) return d;
|
|
||||||
|
|
||||||
for (const [v, w] of Object.entries(graph[u] || {})) {
|
|
||||||
const nd = d + +w;
|
|
||||||
if (nd < (dist[v] ?? Infinity)) {
|
|
||||||
dist[v] = nd;
|
|
||||||
pq.queue([nd, v]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Infinity;
|
|
||||||
}
|
|
||||||
export default findShortestPath;
|
|
||||||
// Generation time: 91.630s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
async function findConvexHull(points) {
|
|
||||||
const _ = (await import("https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.min.js")).default
|
|
||||||
|| await import("https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.min.js");
|
|
||||||
|
|
||||||
const unique = _.uniqWith(points, _.isEqual);
|
|
||||||
const sorted = _.sortBy(unique, ["x", "y"]);
|
|
||||||
|
|
||||||
if (sorted.length <= 1) 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 (const p of sorted) {
|
|
||||||
while (lower.length >= 2 && cross(lower[lower.length - 2], lower[lower.length - 1], p) <= 0)
|
|
||||||
lower.pop();
|
|
||||||
lower.push(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
const upper = [];
|
|
||||||
for (let i = sorted.length - 1; i >= 0; i--) {
|
|
||||||
const p = sorted[i];
|
|
||||||
while (upper.length >= 2 && cross(upper[upper.length - 2], upper[upper.length - 1], p) <= 0)
|
|
||||||
upper.pop();
|
|
||||||
upper.push(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
lower.pop();
|
|
||||||
upper.pop();
|
|
||||||
|
|
||||||
return lower.concat(upper);
|
|
||||||
}
|
|
||||||
export default findConvexHull;
|
|
||||||
// Generation time: 5.615s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
async function findConvexHull(points) {
|
|
||||||
const _ = (await import("https://cdn.jsdelivr.net/npm/lodash-es/lodash.js")).default;
|
|
||||||
|
|
||||||
const unique = _.uniqWith(points, _.isEqual);
|
|
||||||
const sorted = _.sortBy(unique, ["x", "y"]);
|
|
||||||
|
|
||||||
if (sorted.length <= 1) 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 (const p of sorted) {
|
|
||||||
while (lower.length >= 2 && cross(lower[lower.length - 2], lower[lower.length - 1], p) <= 0)
|
|
||||||
lower.pop();
|
|
||||||
lower.push(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
const upper = [];
|
|
||||||
for (const p of _.reverse([...sorted])) {
|
|
||||||
while (upper.length >= 2 && cross(upper[upper.length - 2], upper[upper.length - 1], p) <= 0)
|
|
||||||
upper.pop();
|
|
||||||
upper.push(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
lower.pop();
|
|
||||||
upper.pop();
|
|
||||||
|
|
||||||
return [...lower, ...upper];
|
|
||||||
}
|
|
||||||
export default findConvexHull;
|
|
||||||
// Generation time: 5.094s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
export const findConvexHull = async (points) => {
|
|
||||||
const _ = (await import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/+esm')).default;
|
|
||||||
const sorted = _.sortBy(_.uniqWith(points, _.isEqual), ['x', 'y']);
|
|
||||||
|
|
||||||
if (sorted.length < 3) return sorted;
|
|
||||||
|
|
||||||
const crossProduct = (a, b, c) => (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
|
|
||||||
|
|
||||||
const buildChain = (arr) => {
|
|
||||||
const chain = [];
|
|
||||||
for (const p of arr) {
|
|
||||||
while (chain.length >= 2 && crossProduct(chain[chain.length - 2], chain[chain.length - 1], p) <= 0) {
|
|
||||||
chain.pop();
|
|
||||||
}
|
|
||||||
chain.push(p);
|
|
||||||
}
|
|
||||||
return chain;
|
|
||||||
};
|
|
||||||
|
|
||||||
const lower = buildChain(sorted);
|
|
||||||
const upper = buildChain([...sorted].reverse());
|
|
||||||
|
|
||||||
return [...lower.slice(0, -1), ...upper.slice(0, -1)];
|
|
||||||
};
|
|
||||||
export default findConvexHull;
|
|
||||||
// Generation time: 12.985s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
async function findConvexHull(points) {
|
|
||||||
const _ = await import("https://cdn.jsdelivr.net/npm/lodash@4.17.21/+esm");
|
|
||||||
|
|
||||||
const sortedPoints = _.sortBy([...points], ["x", "y"]);
|
|
||||||
const uniquePoints = _.uniqWith(sortedPoints, (a, b) => a.x === b.x && a.y === b.y);
|
|
||||||
|
|
||||||
if (uniquePoints.length <= 2) return uniquePoints;
|
|
||||||
|
|
||||||
const crossProduct = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
|
|
||||||
|
|
||||||
const lower = [];
|
|
||||||
for (const point of uniquePoints) {
|
|
||||||
while (lower.length >= 2 && crossProduct(lower[lower.length - 2], lower[lower.length - 1], point) <= 0) {
|
|
||||||
lower.pop();
|
|
||||||
}
|
|
||||||
lower.push(point);
|
|
||||||
}
|
|
||||||
|
|
||||||
const upper = [];
|
|
||||||
for (let i = uniquePoints.length - 1; i >= 0; i--) {
|
|
||||||
const point = uniquePoints[i];
|
|
||||||
while (upper.length >= 2 && crossProduct(upper[upper.length - 2], upper[upper.length - 1], point) <= 0) {
|
|
||||||
upper.pop();
|
|
||||||
}
|
|
||||||
upper.push(point);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [...lower.slice(0, -1), ...upper.slice(0, -1)];
|
|
||||||
}
|
|
||||||
export default findConvexHull;
|
|
||||||
// Generation time: 11.859s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
export async function findConvexHull(points) {
|
|
||||||
const _ = await import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/+esm');
|
|
||||||
if (!Array.isArray(points)) points = [];
|
|
||||||
const uniq = _.uniqWith(points, (a, b) => a.x === b.x && a.y === b.y);
|
|
||||||
const pts = _.sortBy(uniq, p => [p.x, p.y]);
|
|
||||||
if (pts.length <= 1) return pts.slice();
|
|
||||||
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
|
|
||||||
const lower = [];
|
|
||||||
for (const p of pts) {
|
|
||||||
while (lower.length > 1 && cross(lower[lower.length - 2], lower[lower.length - 1], p) <= 0) lower.pop();
|
|
||||||
lower.push(p);
|
|
||||||
}
|
|
||||||
const upper = [];
|
|
||||||
for (let i = pts.length - 1; i >= 0; i--) {
|
|
||||||
const p = pts[i];
|
|
||||||
while (upper.length > 1 && cross(upper[upper.length - 2], upper[upper.length - 1], p) <= 0) upper.pop();
|
|
||||||
upper.push(p);
|
|
||||||
}
|
|
||||||
upper.pop();
|
|
||||||
lower.pop();
|
|
||||||
return lower.concat(upper);
|
|
||||||
}
|
|
||||||
export default findConvexHull;
|
|
||||||
// Generation time: 14.502s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
async function findConvexHull(p) {
|
|
||||||
const { default: _ } = await import('https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js'),
|
|
||||||
u = _.uniqWith(_.sortBy(p, 'x', 'y'), (a, b) => a.x === b.x && a.y === b.y);
|
|
||||||
if (u.length < 3) return u;
|
|
||||||
|
|
||||||
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x),
|
|
||||||
build = (pts) => {
|
|
||||||
const h = [];
|
|
||||||
for (const q of pts) {
|
|
||||||
while (h.length > 1 && cross(h[h.length - 2], h[h.length - 1], q) <= 0) h.pop();
|
|
||||||
h.push(q);
|
|
||||||
}
|
|
||||||
return h;
|
|
||||||
};
|
|
||||||
|
|
||||||
const l = build(u),
|
|
||||||
r = build([...u].reverse());
|
|
||||||
|
|
||||||
return [...l.slice(0, -1), ...r.slice(0, -1)];
|
|
||||||
}
|
|
||||||
export default findConvexHull;
|
|
||||||
// Generation time: 147.393s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
async function findConvexHull(a) {
|
|
||||||
const { sortBy, uniqWith, isEqual } = await import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.js');
|
|
||||||
a = uniqWith(a, isEqual);
|
|
||||||
if (a.length < 4) return a;
|
|
||||||
const b = sortBy(a, [v => v.x, v => v.y]);
|
|
||||||
const c = (o, p, q) => (p.x - o.x) * (q.y - o.y) - (p.y - o.y) * (q.x - o.x);
|
|
||||||
const d = [];
|
|
||||||
for (const p of b) {
|
|
||||||
while (d.length > 1 && c(d[d.length - 2], d[d.length - 1], p) <= 0) d.pop();
|
|
||||||
d.push(p);
|
|
||||||
}
|
|
||||||
const e = [];
|
|
||||||
for (let i = b.length; i--;) {
|
|
||||||
const p = b[i];
|
|
||||||
while (e.length > 1 && c(e[e.length - 2], e[e.length - 1], p) <= 0) e.pop();
|
|
||||||
e.push(p);
|
|
||||||
}
|
|
||||||
return uniqWith([...d, ...e], isEqual);
|
|
||||||
}
|
|
||||||
export default findConvexHull;
|
|
||||||
// Generation time: 16.314s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
export async function findConvexHull(pts){
|
|
||||||
const {default:_}=await import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.js');
|
|
||||||
const p=_.orderBy(_.uniqWith(pts,(a,b)=>a.x===b.x&&a.y===b.y),['x','y']);
|
|
||||||
if(p.length<3)return p;
|
|
||||||
const c=(o,a,b)=>(a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x);
|
|
||||||
const l=[],u=[];
|
|
||||||
for(const v of p){
|
|
||||||
while(l.length>1&&c(l[l.length-2],l[l.length-1],v)<=0)l.pop();
|
|
||||||
l.push(v);
|
|
||||||
}
|
|
||||||
for(const v of [...p].reverse()){
|
|
||||||
while(u.length>1&&c(u[u.length-2],u[u.length-1],v)<=0)u.pop();
|
|
||||||
u.push(v);
|
|
||||||
}
|
|
||||||
return l.slice(0,-1).concat(u.slice(0,-1));
|
|
||||||
}
|
|
||||||
export default findConvexHull;
|
|
||||||
// Generation time: 10.565s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
const loadLodash = (() => {
|
|
||||||
let p;
|
|
||||||
return () =>
|
|
||||||
p || (p = import("https://cdn.jsdelivr.net/npm/lodash@4.17.21/+esm")
|
|
||||||
.then(m => m.default || m)
|
|
||||||
.catch(e => (p = null, Promise.reject(e))));
|
|
||||||
})();
|
|
||||||
|
|
||||||
async function findConvexHull(points) {
|
|
||||||
const _ = await loadLodash();
|
|
||||||
if (!Array.isArray(points)) throw new TypeError("Expected an array of points");
|
|
||||||
|
|
||||||
const pts = _.uniqBy(
|
|
||||||
points.filter(p => p && Number.isFinite(p.x) && Number.isFinite(p.y)),
|
|
||||||
p => `${p.x}|${p.y}`
|
|
||||||
);
|
|
||||||
|
|
||||||
if (pts.length < 2) return pts.slice();
|
|
||||||
|
|
||||||
const s = _.sortBy(pts, ["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 > 1 && cross(h[h.length - 2], h[h.length - 1], p) <= 0) h.pop();
|
|
||||||
h.push(p);
|
|
||||||
}
|
|
||||||
return h;
|
|
||||||
};
|
|
||||||
|
|
||||||
const lo = build(s);
|
|
||||||
const up = build(s.slice().reverse());
|
|
||||||
lo.pop();
|
|
||||||
up.pop();
|
|
||||||
return lo.concat(up);
|
|
||||||
}
|
|
||||||
export default findConvexHull;
|
|
||||||
// Generation time: 134.929s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
async function findLISLength(nums) {
|
|
||||||
const { bisectLeft } = await import("https://cdn.jsdelivr.net/npm/d3-array/+esm");
|
|
||||||
const tails = [];
|
|
||||||
for (const n of nums) {
|
|
||||||
const i = bisectLeft(tails, n);
|
|
||||||
i < tails.length ? tails[i] = n : tails.push(n);
|
|
||||||
}
|
|
||||||
return tails.length;
|
|
||||||
}
|
|
||||||
export default findLISLength;
|
|
||||||
// Generation time: 3.321s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
async function findLISLength(nums) {
|
|
||||||
const { bisectLeft } = await import("https://cdn.jsdelivr.net/npm/d3-array/+esm");
|
|
||||||
const tails = [];
|
|
||||||
for (const n of nums) {
|
|
||||||
const i = bisectLeft(tails, n);
|
|
||||||
if (i === tails.length) tails.push(n);
|
|
||||||
else tails[i] = n;
|
|
||||||
}
|
|
||||||
return tails.length;
|
|
||||||
}
|
|
||||||
export default findLISLength;
|
|
||||||
// Generation time: 2.405s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
const findLISLength = async (nums) => {
|
|
||||||
const { bisectLeft } = await import('https://cdn.skypack.dev/d3-array@3');
|
|
||||||
const tails = [];
|
|
||||||
|
|
||||||
for (const x of nums) {
|
|
||||||
const i = bisectLeft(tails, x);
|
|
||||||
tails[i] = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
return tails.length;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export default findLISLength;
|
|
||||||
// Generation time: 13.472s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
async function findLISLength(arr) {
|
|
||||||
const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm');
|
|
||||||
const tails = [];
|
|
||||||
for (const num of arr) {
|
|
||||||
const idx = bisectLeft(tails, num);
|
|
||||||
if (idx === tails.length) tails.push(num);
|
|
||||||
else tails[idx] = num;
|
|
||||||
}
|
|
||||||
return tails.length;
|
|
||||||
}
|
|
||||||
export default findLISLength;
|
|
||||||
// Generation time: 4.847s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
|
|
||||||
export default findLISLength;
|
|
||||||
// Generation time: 10.991s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
export async function findLISLength(a){
|
|
||||||
const{bisectLeft}=await import('https://esm.sh/d3-array');
|
|
||||||
if(!Array.isArray(a))return 0;
|
|
||||||
const t=[];
|
|
||||||
for(const v of a){const i=bisectLeft(t,v);i===t.length?t.push(v):t[i]=v;}
|
|
||||||
return t.length;
|
|
||||||
}
|
|
||||||
export default findLISLength;
|
|
||||||
// Generation time: 39.477s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
async function findLISLength(a){
|
|
||||||
let {bisectLeft}=await import('https://cdn.jsdelivr.net/npm/d3-array@3')
|
|
||||||
let t=[]
|
|
||||||
for(let x of a){
|
|
||||||
let i=bisectLeft(t,x)
|
|
||||||
t[i]=x
|
|
||||||
}
|
|
||||||
return t.length
|
|
||||||
}
|
|
||||||
export default findLISLength;
|
|
||||||
// Generation time: 8.286s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
async function findLISLength(a){
|
|
||||||
const{bisectLeft}=await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm')
|
|
||||||
const t=[]
|
|
||||||
for(const x of a){
|
|
||||||
const i=bisectLeft(t,x)
|
|
||||||
t[i]=x
|
|
||||||
}
|
|
||||||
return t.length
|
|
||||||
}
|
|
||||||
export default findLISLength;
|
|
||||||
// Generation time: 6.704s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
const d3ArrayUrl = 'https://cdn.jsdelivr.net/npm/d3-array@3/+esm'
|
|
||||||
const err = 'Expected an array of numbers'
|
|
||||||
let d3Array
|
|
||||||
|
|
||||||
async function findLISLength(nums) {
|
|
||||||
if (!Array.isArray(nums)) throw TypeError(err)
|
|
||||||
|
|
||||||
d3Array ||= import(d3ArrayUrl)
|
|
||||||
let { bisectLeft } = await d3Array
|
|
||||||
|
|
||||||
let tails = []
|
|
||||||
for (let x of nums) {
|
|
||||||
if (typeof x != 'number' || x != x) throw TypeError(err)
|
|
||||||
tails[bisectLeft(tails, x)] = x
|
|
||||||
}
|
|
||||||
return tails.length
|
|
||||||
}
|
|
||||||
export default findLISLength;
|
|
||||||
// Generation time: 227.924s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
async function renderTemplate(template, data) {
|
|
||||||
const { default: Handlebars } = await import("https://cdn.jsdelivr.net/npm/handlebars@4.7.8/+esm");
|
|
||||||
return Handlebars.compile(template)(data);
|
|
||||||
}
|
|
||||||
export default renderTemplate;
|
|
||||||
// Generation time: 1.747s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
async function renderTemplate(template, data) {
|
|
||||||
const { default: Handlebars } = await import("https://cdn.jsdelivr.net/npm/handlebars@4.7.8/+esm");
|
|
||||||
return Handlebars.compile(template)(data);
|
|
||||||
}
|
|
||||||
export default renderTemplate;
|
|
||||||
// Generation time: 2.282s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
const renderTemplate = async (template, data) => {
|
|
||||||
const { default: hb } = await import('https://esm.sh/handlebars');
|
|
||||||
return hb.compile(template)(data);
|
|
||||||
};
|
|
||||||
export default renderTemplate;
|
|
||||||
// Generation time: 14.517s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
async function renderTemplate(template, data) {
|
|
||||||
window.Handlebars || await import('https://cdn.jsdelivr.net/npm/handlebars@4.7.7/dist/handlebars.min.js');
|
|
||||||
return window.Handlebars.compile(template)(data);
|
|
||||||
}
|
|
||||||
export default renderTemplate;
|
|
||||||
// Generation time: 42.558s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
export async function renderTemplate(template, data) {
|
|
||||||
const load = async () => {
|
|
||||||
try {
|
|
||||||
const src = 'https://cdn.jsdelivr.net/npm/handlebars@4.7.7/dist/handlebars.min.js'
|
|
||||||
const mod = await import(src)
|
|
||||||
return mod.default || mod.Handlebars || mod
|
|
||||||
} catch (e) {
|
|
||||||
const alt = 'https://unpkg.com/handlebars@4.7.7/dist/handlebars.min.js'
|
|
||||||
const mod2 = await import(alt)
|
|
||||||
return mod2.default || mod2.Handlebars || mod2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const hbs = await load()
|
|
||||||
const s = String(template)
|
|
||||||
const f = hbs.compile(s, { noEscape: false })
|
|
||||||
return f(data)
|
|
||||||
}
|
|
||||||
export default renderTemplate;
|
|
||||||
// Generation time: 13.350s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
let hb;
|
|
||||||
export const renderTemplate=async(t,d)=>{
|
|
||||||
try{
|
|
||||||
hb??=(await import('https://cdn.jsdelivr.net/npm/handlebars@4.7.8/dist/handlebars.mjs')).default;
|
|
||||||
return hb.compile(t)(d);
|
|
||||||
}catch(e){
|
|
||||||
throw new Error(`Render failed: ${e.message}`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
export default renderTemplate;
|
|
||||||
// Generation time: 50.722s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
export const renderTemplate=async(template,data)=>{
|
|
||||||
const {default:Handlebars}=await import('https://cdn.jsdelivr.net/npm/handlebars@latest/+esm')
|
|
||||||
return Handlebars.compile(template)(data)
|
|
||||||
}
|
|
||||||
export default renderTemplate;
|
|
||||||
// Generation time: 4.362s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
async function renderTemplate(tpl, data) {
|
|
||||||
const { default: h } = await import('https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.esm.js')
|
|
||||||
return h.compile(tpl)(data)
|
|
||||||
}
|
|
||||||
export default renderTemplate;
|
|
||||||
// Generation time: 2.868s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
const HANDLEBARS_CDN = "https://cdn.jsdelivr.net/npm/handlebars@4.7.8/+esm"
|
|
||||||
|
|
||||||
let hbP
|
|
||||||
const tplCache = new Map()
|
|
||||||
|
|
||||||
const loadHB = () => hbP ??= import(HANDLEBARS_CDN).then(m => m.default ?? m)
|
|
||||||
|
|
||||||
async function renderTemplate(template, data = {}) {
|
|
||||||
if (typeof template != "string") throw new TypeError("Template must be a string")
|
|
||||||
const HB = await loadHB()
|
|
||||||
let fn = tplCache.get(template)
|
|
||||||
fn || tplCache.set(template, fn = HB.compile(template))
|
|
||||||
return fn(data ?? {})
|
|
||||||
}
|
|
||||||
export default renderTemplate;
|
|
||||||
// Generation time: 77.305s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
async function parseMarkdown(md) {
|
|
||||||
const { marked } = await import("https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js");
|
|
||||||
return marked.parse(md);
|
|
||||||
}
|
|
||||||
export default parseMarkdown;
|
|
||||||
// Generation time: 2.382s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
async function parseMarkdown(md) {
|
|
||||||
const { marked } = await import("https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js");
|
|
||||||
return marked.parse(md);
|
|
||||||
}
|
|
||||||
export default parseMarkdown;
|
|
||||||
// Generation time: 2.445s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
const parseMarkdown = async (md) => {
|
|
||||||
const [{ marked }, { default: sanitize }] = await Promise.all([
|
|
||||||
import('https://esm.sh/marked'),
|
|
||||||
import('https://esm.sh/dompurify')
|
|
||||||
]);
|
|
||||||
|
|
||||||
return sanitize.sanitize(marked.parse(md));
|
|
||||||
};
|
|
||||||
export default parseMarkdown;
|
|
||||||
// Generation time: 7.966s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
async function parseMarkdown(markdown) {
|
|
||||||
try {
|
|
||||||
const { marked } = await import('https://cdn.jsdelivr.net/npm/marked@5.1.0/lib/marked.esm.min.js');
|
|
||||||
return marked.parse(markdown);
|
|
||||||
} catch (error) {
|
|
||||||
return `<p>Error parsing markdown: ${error.message}</p>`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export default parseMarkdown;
|
|
||||||
// Generation time: 10.685s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
const parseMarkdown=async e=>(await import("https://cdn.jsdelivr.net/npm/markdown-it@13.0.2/dist/markdown-it.min.js")).default().render(e)
|
|
||||||
export default parseMarkdown;
|
|
||||||
// Generation time: 9.601s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
let p;
|
|
||||||
|
|
||||||
export const parseMarkdown = async (s) => {
|
|
||||||
p ||= Promise.all([
|
|
||||||
import('https://esm.sh/marked@7.0.4').then(r => r.marked),
|
|
||||||
import('https://esm.sh/dompurify@3.0.5').then(r => r.default)
|
|
||||||
]);
|
|
||||||
const [m, d] = await p;
|
|
||||||
return d.sanitize(m.parse(s));
|
|
||||||
};
|
|
||||||
export default parseMarkdown;
|
|
||||||
// Generation time: 550.549s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
let md
|
|
||||||
const parseMarkdown = async s => {
|
|
||||||
md ||= (await import('https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js')).marked
|
|
||||||
return md.parse(s)
|
|
||||||
}
|
|
||||||
export default parseMarkdown;
|
|
||||||
// Generation time: 8.679s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
const loadLibs=(()=>{let cache;return async()=>cache||(cache=Promise.all([
|
|
||||||
import('https://cdn.jsdelivr.net/npm/marked@11.1.0/lib/marked.esm.js'),
|
|
||||||
import('https://cdn.jsdelivr.net/npm/dompurify@3.0.6/dist/purify.es.mjs')
|
|
||||||
]).then(([{marked},purifyMod])=>{
|
|
||||||
const purify=(purifyMod.default||purifyMod)(window);
|
|
||||||
marked.setOptions({gfm:true,headerIds:true,mangle:false});
|
|
||||||
return {marked,purify};
|
|
||||||
}));})();
|
|
||||||
|
|
||||||
const parseMarkdown=async input=>{
|
|
||||||
const {marked,purify}=await loadLibs();
|
|
||||||
const html=marked.parse(typeof input==='string'?input:`${input??''}`);
|
|
||||||
return purify.sanitize(html,{USE_PROFILES:{html:true}});
|
|
||||||
};
|
|
||||||
export default parseMarkdown;
|
|
||||||
// Generation time: 15.618s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
let p, md, purify;
|
|
||||||
|
|
||||||
const load = () =>
|
|
||||||
p ??= Promise.all([
|
|
||||||
import("https://cdn.jsdelivr.net/npm/markdown-it@14/dist/markdown-it.esm.js"),
|
|
||||||
import("https://cdn.jsdelivr.net/npm/dompurify@3/dist/purify.es.mjs")
|
|
||||||
]).then(([{ default: MarkdownIt }, { default: DOMPurify }]) => {
|
|
||||||
md ||= new MarkdownIt({ html: true, linkify: true });
|
|
||||||
purify ||= DOMPurify;
|
|
||||||
}).catch(e => {
|
|
||||||
p = 0;
|
|
||||||
throw e;
|
|
||||||
});
|
|
||||||
|
|
||||||
async function parseMarkdown(src) {
|
|
||||||
await load();
|
|
||||||
return purify.sanitize(md.render(`${src ?? ""}`), { USE_PROFILES: { html: true } });
|
|
||||||
}
|
|
||||||
export default parseMarkdown;
|
|
||||||
// Generation time: 136.807s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
async function processCSV(csv, config) {
|
|
||||||
const { filterColumn, filterValue, groupBy, aggregateColumn, operation } = config;
|
|
||||||
|
|
||||||
const { default: Papa } = await import("https://cdn.jsdelivr.net/npm/papaparse@5.4.1/+esm");
|
|
||||||
|
|
||||||
const parsed = Papa.parse(csv.trim(), { header: true, skipEmptyLines: true });
|
|
||||||
const rows = parsed.data;
|
|
||||||
|
|
||||||
const filtered = rows.filter(r => r[filterColumn] == filterValue);
|
|
||||||
|
|
||||||
const groups = {};
|
|
||||||
for (const row of filtered) {
|
|
||||||
const key = row[groupBy];
|
|
||||||
if (!groups[key]) groups[key] = [];
|
|
||||||
groups[key].push(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Object.entries(groups).map(([groupValue, groupRows]) => {
|
|
||||||
let result;
|
|
||||||
if (operation === "count") {
|
|
||||||
result = groupRows.length;
|
|
||||||
} else {
|
|
||||||
const vals = groupRows.map(r => {
|
|
||||||
const n = Number(r[aggregateColumn]);
|
|
||||||
return isNaN(n) ? 0 : n;
|
|
||||||
});
|
|
||||||
const sum = vals.reduce((a, b) => a + b, 0);
|
|
||||||
result = operation === "avg" ? sum / groupRows.length : sum;
|
|
||||||
}
|
|
||||||
return { [groupBy]: groupValue, result };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
export default processCSV;
|
|
||||||
// Generation time: 4.670s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
async function processCSV(csv, config) {
|
|
||||||
const { filterColumn, filterValue, groupBy, aggregateColumn, operation } = config;
|
|
||||||
|
|
||||||
const { default: Papa } = await import("https://cdn.jsdelivr.net/npm/papaparse@5/+esm");
|
|
||||||
|
|
||||||
const parsed = Papa.parse(csv.trim(), { header: true, skipEmptyLines: true });
|
|
||||||
const rows = parsed.data;
|
|
||||||
|
|
||||||
const filtered = rows.filter(r => r[filterColumn] == filterValue);
|
|
||||||
|
|
||||||
const groups = new Map();
|
|
||||||
for (const row of filtered) {
|
|
||||||
const key = row[groupBy];
|
|
||||||
if (!groups.has(key)) groups.set(key, []);
|
|
||||||
groups.get(key).push(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
const toNum = v => {
|
|
||||||
const n = Number(v);
|
|
||||||
return Number.isFinite(n) ? n : 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
return [...groups.entries()].map(([groupValue, rows]) => {
|
|
||||||
let result;
|
|
||||||
if (operation === "count") {
|
|
||||||
result = rows.length;
|
|
||||||
} else {
|
|
||||||
const sum = rows.reduce((acc, r) => acc + toNum(r[aggregateColumn]), 0);
|
|
||||||
result = operation === "avg" ? sum / rows.length : sum;
|
|
||||||
}
|
|
||||||
return { [groupBy]: groupValue, result };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
export default processCSV;
|
|
||||||
// Generation time: 6.543s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
export const processCSV = async (csv, { filterColumn, filterValue, groupBy, aggregateColumn, operation }) => {
|
|
||||||
const [{ parse }, { groupBy: group, sum: total }] = 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 { data } = parse(csv, {
|
|
||||||
header: true,
|
|
||||||
skipEmptyLines: true
|
|
||||||
});
|
|
||||||
|
|
||||||
const filtered = data.filter(r => r[filterColumn] == filterValue);
|
|
||||||
const collections = group(filtered, groupBy);
|
|
||||||
|
|
||||||
return Object.entries(collections).map(([key, rows]) => {
|
|
||||||
const values = rows.map(r => +r[aggregateColumn] || 0);
|
|
||||||
const s = total(values);
|
|
||||||
const n = values.length;
|
|
||||||
|
|
||||||
const calculations = {
|
|
||||||
sum: s,
|
|
||||||
avg: s / n,
|
|
||||||
count: n
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
[groupBy]: key,
|
|
||||||
result: calculations[operation]
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
export default processCSV;
|
|
||||||
// Generation time: 41.061s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
export async function processCSV(csvData, config) {
|
|
||||||
const { Papa } = await import('https://cdn.skypack.dev/papaparse@5.3.2');
|
|
||||||
const { filterColumn, filterValue, groupBy, aggregateColumn, operation } = config;
|
|
||||||
|
|
||||||
const { data } = Papa.parse(csvData, { header: true, skipEmptyLines: true });
|
|
||||||
|
|
||||||
const groups = data.reduce((acc, row) => {
|
|
||||||
if (row[filterColumn] != filterValue) return acc;
|
|
||||||
const key = row[groupBy];
|
|
||||||
if (!acc[key]) acc[key] = [];
|
|
||||||
acc[key].push(row);
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
return Object.entries(groups).map(([key, rows]) => {
|
|
||||||
let result;
|
|
||||||
if (operation === 'count') {
|
|
||||||
result = rows.length;
|
|
||||||
} else {
|
|
||||||
const values = rows.map(r => parseFloat(r[aggregateColumn]) || 0);
|
|
||||||
if (operation === 'sum') {
|
|
||||||
result = values.reduce((a, b) => a + b, 0);
|
|
||||||
} else if (operation === 'avg') {
|
|
||||||
const sum = values.reduce((a, b) => a + b, 0);
|
|
||||||
result = sum / values.length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return { [groupBy]: key, result };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
export default processCSV;
|
|
||||||
// Generation time: 4.238s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
async function processCSV(csvString, config) {
|
|
||||||
const [{ default: Papa }, { groupBy, sumBy, meanBy }] = 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 data = Papa.parse(csvString, { header: true }).data.filter(row =>
|
|
||||||
row[config.filterColumn] == config.filterValue
|
|
||||||
);
|
|
||||||
|
|
||||||
const grouped = groupBy(data, config.groupBy);
|
|
||||||
|
|
||||||
return Object.entries(grouped).map(([key, rows]) => {
|
|
||||||
let result;
|
|
||||||
const numRows = rows.map(r => parseFloat(r[config.aggregateColumn]) || 0);
|
|
||||||
|
|
||||||
switch(config.operation) {
|
|
||||||
case 'sum': result = numRows.reduce((a, b) => a + b, 0); break;
|
|
||||||
case 'avg': result = numRows.reduce((a, b) => a + b, 0) / numRows.length; break;
|
|
||||||
case 'count': result = numRows.length; break;
|
|
||||||
}
|
|
||||||
return { [config.groupBy]: key, result };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
export default processCSV;
|
|
||||||
// Generation time: 5.258s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
async function processCSV(csv, { filterColumn: fc, filterValue: fv, groupBy: gb, aggregateColumn: ac, operation: op }) {
|
|
||||||
const { default: Papa } = await import('https://cdn.jsdelivr.net/npm/papaparse@5.4.1/+esm');
|
|
||||||
const groups = {};
|
|
||||||
|
|
||||||
Papa.parse(csv, { header: true }).data
|
|
||||||
.filter(r => r[fc] == fv)
|
|
||||||
.forEach(r => {
|
|
||||||
const key = r[gb], g = groups[key] || (groups[key] = { c: 0, s: 0 });
|
|
||||||
g.c++;
|
|
||||||
g.s += +r[ac] || 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
return Object.entries(groups).map(([k, { c, s }]) => ({ [gb]: k, result: op === 'count' ? c : op === 'avg' ? s / c : s }));
|
|
||||||
}
|
|
||||||
export default processCSV;
|
|
||||||
// Generation time: 66.769s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
async function processCSV(csv, o) {
|
|
||||||
const { csvParse } = await import('https://cdn.skypack.dev/d3-dsv');
|
|
||||||
const { filterColumn, filterValue, groupBy, aggregateColumn, operation } = o;
|
|
||||||
const rows = csvParse(csv);
|
|
||||||
const m = new Map();
|
|
||||||
for (const r of rows) {
|
|
||||||
if (r[filterColumn] == filterValue) {
|
|
||||||
const g = r[groupBy];
|
|
||||||
let a = +r[aggregateColumn];
|
|
||||||
if (isNaN(a)) a = 0;
|
|
||||||
const v = m.get(g) || { c: 0, s: 0 };
|
|
||||||
v.c++;
|
|
||||||
v.s += a;
|
|
||||||
m.set(g, v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const out = [];
|
|
||||||
for (const [k, v] of m) {
|
|
||||||
const result = operation === 'sum' ? v.s : operation === 'count' ? v.c : v.s / v.c;
|
|
||||||
out.push({ [groupBy]: k, result });
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
export default processCSV;
|
|
||||||
// Generation time: 11.354s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
const store={},load=u=>store[u]??=import(u),csvLib='https://cdn.jsdelivr.net/npm/papaparse@5.4.1/+esm',dataLib='https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/+esm',toNum=v=>{const n=Number(v);return Number.isFinite(n)?n:0};
|
|
||||||
|
|
||||||
async function processCSV(csv,opt){
|
|
||||||
const [{Papa},{groupBy:gb}] = await Promise.all([load(csvLib),load(dataLib)]);
|
|
||||||
const {filterColumn:f,filterValue:v,groupBy:g,aggregateColumn:a,operation:o}=opt;
|
|
||||||
const rows=Papa.parse(csv,{header:true,skipEmptyLines:true}).data.filter(r=>r&&r[f]==v);
|
|
||||||
const grouped=gb(rows,r=>r[g]);
|
|
||||||
return Object.entries(grouped).map(([k,items])=>{
|
|
||||||
const total=items.reduce((s,r)=>s+toNum(r[a]),0);
|
|
||||||
const result=o==='count'?items.length:o==='sum'?total:items.length?total/items.length:0;
|
|
||||||
return {[g]:k,result};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
export default processCSV;
|
|
||||||
// Generation time: 29.916s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
const _csvLibs = (() => {
|
|
||||||
let p
|
|
||||||
return () =>
|
|
||||||
p ??= Promise.all([
|
|
||||||
import("https://cdn.jsdelivr.net/npm/d3-dsv@3/+esm"),
|
|
||||||
import("https://cdn.jsdelivr.net/npm/d3-array@3/+esm")
|
|
||||||
]).then(([dsv, arr]) => ({ csvParse: dsv.csvParse, group: arr.group }))
|
|
||||||
})()
|
|
||||||
|
|
||||||
async function processCSV(csv, cfg = {}) {
|
|
||||||
if (typeof csv != "string") throw new TypeError("csv must be a string")
|
|
||||||
|
|
||||||
const { filterColumn, filterValue, groupBy, aggregateColumn, operation } = cfg
|
|
||||||
if (typeof filterColumn != "string" || !filterColumn) throw new TypeError("filterColumn required")
|
|
||||||
if (typeof groupBy != "string" || !groupBy) throw new TypeError("groupBy required")
|
|
||||||
if (!["sum", "avg", "count"].includes(operation)) throw new TypeError("operation must be sum|avg|count")
|
|
||||||
if (operation != "count" && (typeof aggregateColumn != "string" || !aggregateColumn))
|
|
||||||
throw new TypeError("aggregateColumn required for sum/avg")
|
|
||||||
|
|
||||||
const { csvParse, group } = await _csvLibs()
|
|
||||||
const rows = csvParse(csv)
|
|
||||||
const filtered = rows.filter(r => r[filterColumn] == filterValue)
|
|
||||||
const groups = group(filtered, r => r[groupBy])
|
|
||||||
|
|
||||||
const num = v => +v || 0
|
|
||||||
const calc = rs => {
|
|
||||||
const c = rs.length
|
|
||||||
if (operation == "count") return c
|
|
||||||
const s = rs.reduce((a, r) => a + num(r[aggregateColumn]), 0)
|
|
||||||
return operation == "avg" ? s / c : s
|
|
||||||
}
|
|
||||||
|
|
||||||
return Array.from(groups, ([k, rs]) => ({ [groupBy]: k, result: calc(rs) }))
|
|
||||||
}
|
|
||||||
export default processCSV;
|
|
||||||
// Generation time: 136.946s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
async function findAvailableSlots(calendar1, calendar2, constraints) {
|
|
||||||
const { DateTime, Interval } = await import("https://cdn.jsdelivr.net/npm/luxon@3/+esm");
|
|
||||||
|
|
||||||
const { durationMinutes, searchRange, workHours } = constraints;
|
|
||||||
const dur = durationMinutes;
|
|
||||||
|
|
||||||
const rangeStart = DateTime.fromISO(searchRange.start, { zone: "utc" });
|
|
||||||
const rangeEnd = DateTime.fromISO(searchRange.end, { zone: "utc" });
|
|
||||||
|
|
||||||
const [whStartH, whStartM] = workHours.start.split(":").map(Number);
|
|
||||||
const [whEndH, whEndM] = workHours.end.split(":").map(Number);
|
|
||||||
|
|
||||||
const allBusy = [...calendar1, ...calendar2]
|
|
||||||
.map(b => ({
|
|
||||||
s: DateTime.fromISO(b.start, { zone: "utc" }),
|
|
||||||
e: DateTime.fromISO(b.end, { zone: "utc" })
|
|
||||||
}))
|
|
||||||
.sort((a, b) => a.s - b.s);
|
|
||||||
|
|
||||||
const merged = [];
|
|
||||||
for (const slot of allBusy) {
|
|
||||||
if (merged.length && slot.s <= merged[merged.length - 1].e) {
|
|
||||||
merged[merged.length - 1].e = DateTime.max(merged[merged.length - 1].e, slot.e);
|
|
||||||
} else {
|
|
||||||
merged.push({ s: slot.s, e: slot.e });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const freePeriods = [];
|
|
||||||
let cursor = rangeStart;
|
|
||||||
|
|
||||||
for (const busy of merged) {
|
|
||||||
if (busy.s > cursor) {
|
|
||||||
freePeriods.push({ s: cursor, e: DateTime.min(busy.s, rangeEnd) });
|
|
||||||
}
|
|
||||||
cursor = DateTime.max(cursor, busy.e);
|
|
||||||
if (cursor >= rangeEnd) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cursor < rangeEnd) {
|
|
||||||
freePeriods.push({ s: cursor, e: rangeEnd });
|
|
||||||
}
|
|
||||||
|
|
||||||
const workConstrained = [];
|
|
||||||
|
|
||||||
for (const free of freePeriods) {
|
|
||||||
let day = free.s.startOf("day");
|
|
||||||
const lastDay = free.e.startOf("day");
|
|
||||||
|
|
||||||
while (day <= lastDay) {
|
|
||||||
const whS = day.set({ hour: whStartH, minute: whStartM, second: 0, millisecond: 0 });
|
|
||||||
const whE = day.set({ hour: whEndH, minute: whEndM, second: 0, millisecond: 0 });
|
|
||||||
|
|
||||||
const overlapStart = DateTime.max(free.s, whS, rangeStart);
|
|
||||||
const overlapEnd = DateTime.min(free.e, whE, rangeEnd);
|
|
||||||
|
|
||||||
if (overlapStart < overlapEnd) {
|
|
||||||
workConstrained.push({ s: overlapStart, e: overlapEnd });
|
|
||||||
}
|
|
||||||
|
|
||||||
day = day.plus({ days: 1 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const results = [];
|
|
||||||
|
|
||||||
for (const period of workConstrained) {
|
|
||||||
let slotStart = period.s;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
const slotEnd = slotStart.plus({ minutes: dur });
|
|
||||||
if (slotEnd > period.e) break;
|
|
||||||
results.push({
|
|
||||||
start: slotStart.toISO(),
|
|
||||||
end: slotEnd.toISO()
|
|
||||||
});
|
|
||||||
slotStart = slotEnd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
results.sort((a, b) => a.start.localeCompare(b.start));
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
export default findAvailableSlots;
|
|
||||||
// Generation time: 11.229s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
async function findAvailableSlots(calendar1, calendar2, constraints) {
|
|
||||||
const { DateTime, Interval } = await import("https://cdn.jsdelivr.net/npm/luxon@3/+esm");
|
|
||||||
|
|
||||||
const { durationMinutes, searchRange, workHours } = constraints;
|
|
||||||
const rangeStart = DateTime.fromISO(searchRange.start, { zone: "utc" });
|
|
||||||
const rangeEnd = DateTime.fromISO(searchRange.end, { zone: "utc" });
|
|
||||||
const [whStartH, whStartM] = workHours.start.split(":").map(Number);
|
|
||||||
const [whEndH, whEndM] = workHours.end.split(":").map(Number);
|
|
||||||
|
|
||||||
const allBusy = [...calendar1, ...calendar2]
|
|
||||||
.map(b => ({
|
|
||||||
s: DateTime.fromISO(b.start, { zone: "utc" }),
|
|
||||||
e: DateTime.fromISO(b.end, { zone: "utc" })
|
|
||||||
}))
|
|
||||||
.sort((a, b) => a.s - b.s);
|
|
||||||
|
|
||||||
const merged = [];
|
|
||||||
for (const slot of allBusy) {
|
|
||||||
if (merged.length && slot.s <= merged[merged.length - 1].e) {
|
|
||||||
merged[merged.length - 1].e = DateTime.max(merged[merged.length - 1].e, slot.e);
|
|
||||||
} else {
|
|
||||||
merged.push({ s: slot.s, e: slot.e });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const freePeriods = [];
|
|
||||||
let cursor = rangeStart;
|
|
||||||
for (const busy of merged) {
|
|
||||||
if (busy.s > cursor) {
|
|
||||||
freePeriods.push({ s: cursor, e: DateTime.min(busy.s, rangeEnd) });
|
|
||||||
}
|
|
||||||
cursor = DateTime.max(cursor, busy.e);
|
|
||||||
}
|
|
||||||
if (cursor < rangeEnd) {
|
|
||||||
freePeriods.push({ s: cursor, e: rangeEnd });
|
|
||||||
}
|
|
||||||
|
|
||||||
const workWindows = [];
|
|
||||||
let day = rangeStart.startOf("day");
|
|
||||||
const lastDay = rangeEnd.startOf("day").plus({ days: 1 });
|
|
||||||
|
|
||||||
while (day < lastDay) {
|
|
||||||
const ws = day.set({ hour: whStartH, minute: whStartM, second: 0, millisecond: 0 });
|
|
||||||
const we = day.set({ hour: whEndH, minute: whEndM, second: 0, millisecond: 0 });
|
|
||||||
if (we > ws) {
|
|
||||||
const clampedStart = DateTime.max(ws, rangeStart);
|
|
||||||
const clampedEnd = DateTime.min(we, rangeEnd);
|
|
||||||
if (clampedStart < clampedEnd) {
|
|
||||||
workWindows.push({ s: clampedStart, e: clampedEnd });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
day = day.plus({ days: 1 });
|
|
||||||
}
|
|
||||||
|
|
||||||
const effectiveFree = [];
|
|
||||||
for (const free of freePeriods) {
|
|
||||||
for (const ww of workWindows) {
|
|
||||||
const s = DateTime.max(free.s, ww.s);
|
|
||||||
const e = DateTime.min(free.e, ww.e);
|
|
||||||
if (s < e) {
|
|
||||||
effectiveFree.push({ s, e });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
effectiveFree.sort((a, b) => a.s - b.s);
|
|
||||||
|
|
||||||
const results = [];
|
|
||||||
const dur = { minutes: durationMinutes };
|
|
||||||
|
|
||||||
for (const period of effectiveFree) {
|
|
||||||
let slotStart = period.s;
|
|
||||||
while (true) {
|
|
||||||
const slotEnd = slotStart.plus(dur);
|
|
||||||
if (slotEnd > period.e) break;
|
|
||||||
results.push({
|
|
||||||
start: slotStart.toISO(),
|
|
||||||
end: slotEnd.toISO()
|
|
||||||
});
|
|
||||||
slotStart = slotEnd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
export default findAvailableSlots;
|
|
||||||
// Generation time: 12.695s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
export async function findAvailableSlots(cal1, cal2, { durationMinutes, searchRange, workHours }) {
|
|
||||||
const dayjs = (await import('https://cdn.skypack.dev/dayjs')).default;
|
|
||||||
const utc = (await import('https://cdn.skypack.dev/dayjs/plugin/utc')).default;
|
|
||||||
dayjs.extend(utc);
|
|
||||||
|
|
||||||
const u = (v) => dayjs.utc(v);
|
|
||||||
const sR = u(searchRange.start);
|
|
||||||
const eR = u(searchRange.end);
|
|
||||||
const [sh, sm] = workHours.start.split(':');
|
|
||||||
const [eh, em] = workHours.end.split(':');
|
|
||||||
|
|
||||||
let blocked = [...cal1, ...cal2].map((b) => ({
|
|
||||||
s: u(b.start),
|
|
||||||
e: u(b.end)
|
|
||||||
}));
|
|
||||||
|
|
||||||
for (let c = sR.startOf('d'); c <= eR; c = c.add(1, 'd')) {
|
|
||||||
blocked.push(
|
|
||||||
{ s: c, e: c.set('h', sh).set('m', sm) },
|
|
||||||
{ s: c.set('h', eh).set('m', em), e: c.add(1, 'd') }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const merged = blocked
|
|
||||||
.map((b) => ({
|
|
||||||
s: b.s < sR ? sR : b.s,
|
|
||||||
e: b.e > eR ? eR : b.e
|
|
||||||
}))
|
|
||||||
.filter((b) => b.s < b.e)
|
|
||||||
.sort((a, b) => a.s - b.s)
|
|
||||||
.reduce((acc, b) => {
|
|
||||||
const p = acc[acc.length - 1];
|
|
||||||
p && b.s <= p.e ? (p.e = b.e > p.e ? b.e : p.e) : acc.push(b);
|
|
||||||
return acc;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const avail = [];
|
|
||||||
let cursor = sR;
|
|
||||||
|
|
||||||
[...merged, { s: eR, e: eR }].forEach((b) => {
|
|
||||||
while (cursor.add(durationMinutes, 'm') <= b.s) {
|
|
||||||
const next = cursor.add(durationMinutes, 'm');
|
|
||||||
avail.push({
|
|
||||||
start: cursor.toISOString(),
|
|
||||||
end: next.toISOString()
|
|
||||||
});
|
|
||||||
cursor = next;
|
|
||||||
}
|
|
||||||
if (b.e > cursor) cursor = b.e;
|
|
||||||
});
|
|
||||||
|
|
||||||
return avail;
|
|
||||||
}
|
|
||||||
export default findAvailableSlots;
|
|
||||||
// Generation time: 35.904s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
export async function findAvailableSlots(calendarA, calendarB, constraints) {
|
|
||||||
const { durationMinutes, searchRange, workHours } = constraints;
|
|
||||||
const { parseISO, addMinutes, differenceInMinutes, min, max, formatISO, isAfter, isBefore, isEqual, parse } = await import('https://cdn.jsdelivr.net/npm/date-fns@3.6.0/+esm');
|
|
||||||
|
|
||||||
const searchStart = parseISO(searchRange.start);
|
|
||||||
const searchEnd = parseISO(searchRange.end);
|
|
||||||
const workStart = parse(workHours.start, 'HH:mm', searchStart);
|
|
||||||
const workEnd = parse(workHours.end, 'HH:mm', searchStart);
|
|
||||||
|
|
||||||
const allBusy = [...calendarA, ...calendarB].map(slot => ({
|
|
||||||
start: parseISO(slot.start),
|
|
||||||
end: parseISO(slot.end)
|
|
||||||
})).sort((a, b) => a.start - b.start);
|
|
||||||
|
|
||||||
const mergedBusy = [];
|
|
||||||
for (const slot of allBusy) {
|
|
||||||
if (!mergedBusy.length || isAfter(slot.start, mergedBusy[mergedBusy.length - 1].end)) {
|
|
||||||
mergedBusy.push({ start: slot.start, end: slot.end });
|
|
||||||
} else {
|
|
||||||
mergedBusy[mergedBusy.length - 1].end = max([mergedBusy[mergedBusy.length - 1].end, slot.end]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const freePeriods = [];
|
|
||||||
let currentStart = searchStart;
|
|
||||||
|
|
||||||
for (const busy of mergedBusy) {
|
|
||||||
if (isBefore(currentStart, busy.start)) {
|
|
||||||
freePeriods.push({ start: currentStart, end: busy.start });
|
|
||||||
}
|
|
||||||
currentStart = max([currentStart, busy.end]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isBefore(currentStart, searchEnd)) {
|
|
||||||
freePeriods.push({ start: currentStart, end: searchEnd });
|
|
||||||
}
|
|
||||||
|
|
||||||
const slots = [];
|
|
||||||
|
|
||||||
for (const period of freePeriods) {
|
|
||||||
const periodStart = max([period.start, searchStart]);
|
|
||||||
const periodEnd = min([period.end, searchEnd]);
|
|
||||||
|
|
||||||
let slotStart = periodStart;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
const slotEnd = addMinutes(slotStart, durationMinutes);
|
|
||||||
|
|
||||||
if (isAfter(slotEnd, periodEnd) || isAfter(slotEnd, searchEnd)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const slotWorkStart = new Date(slotStart);
|
|
||||||
const slotWorkEnd = new Date(slotStart);
|
|
||||||
slotWorkStart.setUTCHours(workStart.getUTCHours(), workStart.getUTCMinutes(), 0, 0);
|
|
||||||
slotWorkEnd.setUTCHours(workEnd.getUTCHours(), workEnd.getUTCMinutes(), 0, 0);
|
|
||||||
|
|
||||||
const adjustedSlotStart = max([slotStart, slotWorkStart]);
|
|
||||||
|
|
||||||
if (differenceInMinutes(slotEnd, adjustedSlotStart) >= durationMinutes) {
|
|
||||||
const finalSlotStart = adjustedSlotStart;
|
|
||||||
const finalSlotEnd = addMinutes(finalSlotStart, durationMinutes);
|
|
||||||
|
|
||||||
if (!isAfter(finalSlotEnd, periodEnd) && !isAfter(finalSlotEnd, searchEnd) && !isAfter(finalSlotEnd, slotWorkEnd)) {
|
|
||||||
slots.push({ start: formatISO(finalSlotStart), end: formatISO(finalSlotEnd) });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
slotStart = addMinutes(slotStart, durationMinutes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const sortedSlots = slots.sort((a, b) => parseISO(a.start) - parseISO(b.start));
|
|
||||||
|
|
||||||
const nonOverlappingSlots = [];
|
|
||||||
let lastEnd = null;
|
|
||||||
|
|
||||||
for (const slot of sortedSlots) {
|
|
||||||
const slotStart = parseISO(slot.start);
|
|
||||||
const slotEnd = parseISO(slot.end);
|
|
||||||
|
|
||||||
if (!lastEnd || !isBefore(slotStart, lastEnd)) {
|
|
||||||
if (!lastEnd || isAfter(slotStart, lastEnd)) {
|
|
||||||
nonOverlappingSlots.push(slot);
|
|
||||||
lastEnd = slotEnd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nonOverlappingSlots;
|
|
||||||
}
|
|
||||||
export default findAvailableSlots;
|
|
||||||
// Generation time: 14.885s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
export async function findAvailableSlots(busyA, busyB, constraints) {
|
|
||||||
const {
|
|
||||||
addMinutes,
|
|
||||||
compareAsc,
|
|
||||||
eachMinuteOfInterval,
|
|
||||||
isBefore,
|
|
||||||
isEqual,
|
|
||||||
isValid,
|
|
||||||
parseISO,
|
|
||||||
startOfDay,
|
|
||||||
} = await import('https://cdn.skypack.dev/date-fns@2.30.0');
|
|
||||||
|
|
||||||
const c = constraints || {};
|
|
||||||
const durationMinutes = (c && c.durationMinutes) || 30;
|
|
||||||
if (!Number.isInteger(durationMinutes) || durationMinutes <= 0) throw new Error('durationMinutes must be a positive integer');
|
|
||||||
const range = c && c.searchRange || {};
|
|
||||||
const rangeStart = parseISO(range.start);
|
|
||||||
const rangeEnd = parseISO(range.end);
|
|
||||||
if (!isValid(rangeStart) || !isValid(rangeEnd) || !isBefore(rangeStart, rangeEnd)) throw new Error('Invalid searchRange');
|
|
||||||
const wh = c && c.workHours || {};
|
|
||||||
const [whStartH, whStartM] = String(wh.start || '09:00').split(':').map(n => parseInt(n, 10));
|
|
||||||
const [whEndH, whEndM] = String(wh.end || '17:00').split(':').split(':').map(n => parseInt(n, 10));
|
|
||||||
const WH_ST = whStartH * 60 + (isNaN(whStartM) ? 0 : whStartM);
|
|
||||||
const WH_ET = whEndH * 60 + (isNaN(whEndM) ? 0 : whEndM);
|
|
||||||
if (!(0 <= WH_ST && WH_ST < WH_ET && WH_ET <= 1440)) throw new Error('Invalid workHours');
|
|
||||||
|
|
||||||
const toEpoch = d => d.getTime();
|
|
||||||
const fmtTime = d => {
|
|
||||||
const t = d.getUTCHours().toString().padStart(2, '0') + ':' + d.getUTCMinutes().toString().padStart(2, '0');
|
|
||||||
return t;
|
|
||||||
};
|
|
||||||
|
|
||||||
const parseBusy = slot => {
|
|
||||||
const s = parseISO(slot.start);
|
|
||||||
const e = parseISO(slot.end);
|
|
||||||
if (!isValid(s) || !isValid(e) || !isBefore(s, e) && !isEqual(s, e)) throw new Error('Invalid busy slot');
|
|
||||||
return { s, e };
|
|
||||||
};
|
|
||||||
|
|
||||||
const busy = [...busyA, ...busyB].map(parseBusy)
|
|
||||||
.filter(({ s, e }) => isBefore(rangeStart, e) && !isBefore(s, rangeEnd))
|
|
||||||
.map(({ s, e }) => ({ s: isBefore(s, rangeStart) ? rangeStart : s, e: isBefore(rangeEnd, e) ? rangeEnd : e }))
|
|
||||||
.sort((a, b) => compareAsc(a.s, b.s));
|
|
||||||
|
|
||||||
const merged = [];
|
|
||||||
for (const cur of busy) {
|
|
||||||
if (merged.length === 0) {
|
|
||||||
merged.push({ ...cur });
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const last = merged[merged.length - 1];
|
|
||||||
if (isBefore(last.e, cur.s) || isEqual(last.e, cur.s)) {
|
|
||||||
merged.push({ ...cur });
|
|
||||||
} else {
|
|
||||||
if (isBefore(cur.e, last.e)) continue;
|
|
||||||
last.e = cur.e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const findNext = (t, arr, lo, hi) => {
|
|
||||||
while (lo <= hi) {
|
|
||||||
const mid = (lo + hi) >> 1;
|
|
||||||
if (isBefore(arr[mid].e, t) || isEqual(arr[mid].e, t)) lo = mid + 1;
|
|
||||||
else hi = mid - 1;
|
|
||||||
}
|
|
||||||
return lo < arr.length ? lo : -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
const available = [];
|
|
||||||
let cursor = rangeStart;
|
|
||||||
let idx = 0;
|
|
||||||
while (idx < merged.length && !isBefore(rangeEnd, merged[idx].s)) {
|
|
||||||
const blockStart = merged[idx].s;
|
|
||||||
const blockEnd = merged[idx].e;
|
|
||||||
if (isBefore(cursor, blockStart)) {
|
|
||||||
available.push({ start: cursor, end: blockStart });
|
|
||||||
}
|
|
||||||
if (isBefore(blockEnd, cursor)) {
|
|
||||||
idx = findNext(cursor, merged, idx + 1, merged.length - 1);
|
|
||||||
if (idx === -1) break;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cursor = blockEnd;
|
|
||||||
idx = idx + 1;
|
|
||||||
}
|
|
||||||
if (isBefore(cursor, rangeEnd)) available.push({ start: cursor, end: rangeEnd });
|
|
||||||
|
|
||||||
const isSameUTCDay = (a, b) =>
|
|
||||||
a.getUTCFullYear() === b.getUTCFullYear() &&
|
|
||||||
a.getUTCMonth() === b.getUTCMonth() &&
|
|
||||||
a.getUTCDate() === b.getUTCDate();
|
|
||||||
|
|
||||||
const startOfNextDayUTC = d => addMinutes(startOfDay(d), 24 * 60);
|
|
||||||
|
|
||||||
const clipSegmentToWorkHours = (segStart, segEnd) => {
|
|
||||||
const out = [];
|
|
||||||
let day = startOfDay(segStart);
|
|
||||||
while (isBefore(day, segEnd)) {
|
|
||||||
const dayStart = isBefore(day, segStart) ? segStart : day;
|
|
||||||
const dayNext = startOfNextDayUTC(day);
|
|
||||||
const dayEnd = isBefore(segEnd, dayNext) ? segEnd : dayNext;
|
|
||||||
const segST = (dayStart.getUTCHours() * 60 + dayStart.getUTCMinutes()) | 0;
|
|
||||||
const segET = (dayEnd.getUTCHours() * 60 + dayEnd.getUTCMinutes()) | 0;
|
|
||||||
const st = Math.max(segST, WH_ST);
|
|
||||||
const et = Math.min(segET, WH_ET);
|
|
||||||
if (st < et) {
|
|
||||||
const clipStart = addMinutes(day, st);
|
|
||||||
const clipEnd = addMinutes(day, et);
|
|
||||||
out.push({ start: clipStart, end: clipEnd });
|
|
||||||
}
|
|
||||||
day = dayNext;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
};
|
|
||||||
|
|
||||||
const slots = [];
|
|
||||||
for (const seg of available) {
|
|
||||||
const clips = clipSegmentToWorkHours(seg.start, seg.end);
|
|
||||||
for (const clip of clips) {
|
|
||||||
const clipLen = Math.floor((toEpoch(clip.end) - toEpoch(clip.start)) / 60000);
|
|
||||||
const count = Math.floor(clipLen / durationMinutes);
|
|
||||||
if (count <= 0) continue;
|
|
||||||
let cur = clip.start;
|
|
||||||
for (let i = 0; i < count; i++) {
|
|
||||||
const s = cur;
|
|
||||||
const e = addMinutes(s, durationMinutes);
|
|
||||||
if (isBefore(e, clip.end) || isEqual(e, clip.end)) {
|
|
||||||
if (isBefore(rangeStart, s) && !isBefore(rangeEnd, e)) {
|
|
||||||
slots.push({ start: s.toISOString(), end: e.toISOString() });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cur = e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return slots;
|
|
||||||
}
|
|
||||||
export default findAvailableSlots;
|
|
||||||
// Generation time: 36.069s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
export async function findAvailableSlots(cal1, cal2, { durationMinutes, searchRange, workHours }) {
|
|
||||||
const { parseISO, compareAsc, addMinutes } = await import('https://cdn.skypack.dev/date-fns');
|
|
||||||
|
|
||||||
const s = parseISO(searchRange.start);
|
|
||||||
const e = parseISO(searchRange.end);
|
|
||||||
|
|
||||||
const [whS, whE] = [workHours.start, workHours.end].map(t => {
|
|
||||||
const [h, m] = t.split(':').map(Number);
|
|
||||||
return h * 60 + m;
|
|
||||||
});
|
|
||||||
|
|
||||||
const inWH = (d, de) => {
|
|
||||||
const g = t => t.getUTCHours() * 60 + t.getUTCMinutes();
|
|
||||||
return g(d) >= whS && g(de) <= whE;
|
|
||||||
};
|
|
||||||
|
|
||||||
const busy = [...cal1, ...cal2]
|
|
||||||
.map(({ start, end }) => ({ s: parseISO(start), e: parseISO(end) }))
|
|
||||||
.filter(({ s: bs, e: be }) => compareAsc(be, s) > 0 && compareAsc(bs, e) < 0)
|
|
||||||
.map(({ s: bs, e: be }) => ({
|
|
||||||
s: compareAsc(bs, s) < 0 ? s : bs,
|
|
||||||
e: compareAsc(be, e) > 0 ? e : be
|
|
||||||
}))
|
|
||||||
.sort((a, b) => compareAsc(a.s, b.s));
|
|
||||||
|
|
||||||
const merged = [];
|
|
||||||
for (const { s: bs, e: be } of busy) {
|
|
||||||
const last = merged[merged.length - 1];
|
|
||||||
if (!last || compareAsc(bs, last.e) >= 0) merged.push({ s: bs, e: be });
|
|
||||||
else if (compareAsc(be, last.e) > 0) last.e = be;
|
|
||||||
}
|
|
||||||
|
|
||||||
const free = [];
|
|
||||||
let cur = s;
|
|
||||||
for (const { s: ms, e: me } of merged) {
|
|
||||||
if (compareAsc(cur, ms) < 0) free.push({ s: cur, e: ms });
|
|
||||||
cur = compareAsc(me, cur) > 0 ? me : cur;
|
|
||||||
}
|
|
||||||
if (compareAsc(cur, e) < 0) free.push({ s: cur, e });
|
|
||||||
|
|
||||||
const slots = [];
|
|
||||||
for (const { s: fs, e: fe } of free) {
|
|
||||||
let cs = fs;
|
|
||||||
while (true) {
|
|
||||||
const ce = addMinutes(cs, durationMinutes);
|
|
||||||
if (compareAsc(ce, fe) > 0) break;
|
|
||||||
if (inWH(cs, ce)) slots.push({ start: cs.toISOString(), end: ce.toISOString() });
|
|
||||||
cs = addMinutes(cs, durationMinutes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return slots;
|
|
||||||
}
|
|
||||||
export default findAvailableSlots;
|
|
||||||
// Generation time: 289.823s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
async function findAvailableSlots(a,b,o){
|
|
||||||
const {default:d}=await import('https://cdn.jsdelivr.net/npm/dayjs@1.11.10/esm/index.js')
|
|
||||||
const {default:u}=await import('https://cdn.jsdelivr.net/npm/dayjs@1.11.10/esm/plugin/utc.js')
|
|
||||||
d.extend(u)
|
|
||||||
const s=d.utc(o.searchRange.start),e=d.utc(o.searchRange.end)
|
|
||||||
const S=s.valueOf(),E=e.valueOf(),t=o.durationMinutes*6e4
|
|
||||||
const busy=[...a,...b].map(v=>[d.utc(v.start).valueOf(),d.utc(v.end).valueOf()]).filter(v=>v[1]>S&&v[0]<E).sort((i,j)=>i[0]-j[0])
|
|
||||||
const m=[]
|
|
||||||
for(const [b0,b1]of busy){
|
|
||||||
const x=Math.max(b0,S),y=Math.min(b1,E)
|
|
||||||
if(!m.length||x>m[m.length-1][1])m.push([x,y])
|
|
||||||
else m[m.length-1][1]=Math.max(m[m.length-1][1],y)
|
|
||||||
}
|
|
||||||
const r=[],ws=o.workHours.start,we=o.workHours.end
|
|
||||||
let j=0
|
|
||||||
for(let day=s.startOf('day');day.isBefore(e);day=day.add(1,'day')){
|
|
||||||
let w0=d.utc(`${day.format('YYYY-MM-DD')}T${ws}Z`).valueOf(),w1=d.utc(`${day.format('YYYY-MM-DD')}T${we}Z`).valueOf()
|
|
||||||
if(w1<=S||w0>=E)continue
|
|
||||||
if(w0<S)w0=S
|
|
||||||
if(w1>E)w1=E
|
|
||||||
if(w0>=w1)continue
|
|
||||||
while(j<m.length&&m[j][1]<=w0)j++
|
|
||||||
let p=w0
|
|
||||||
for(let k=j;k<m.length&&m[k][0]<w1;k++){
|
|
||||||
if(m[k][0]>p){
|
|
||||||
for(let a=p;a+t<=Math.min(m[k][0],w1);a+=t)r.push({start:new Date(a).toISOString(),end:new Date(a+t).toISOString()})
|
|
||||||
}
|
|
||||||
p=Math.max(p,m[k][1])
|
|
||||||
}
|
|
||||||
if(p<w1){
|
|
||||||
for(let a=p;a+t<=w1;a+=t)r.push({start:new Date(a).toISOString(),end:new Date(a+t).toISOString()})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
export default findAvailableSlots;
|
|
||||||
// Generation time: 62.189s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
const loadDay = (() => {
|
|
||||||
let memo
|
|
||||||
return () => memo ?? (memo = (async () => {
|
|
||||||
const [core, utc] = await Promise.all([
|
|
||||||
import('https://esm.sh/dayjs@1.11.13?target=esnext'),
|
|
||||||
import('https://esm.sh/dayjs@1.11.13/plugin/utc?target=esnext')
|
|
||||||
])
|
|
||||||
const d = core.default
|
|
||||||
d.extend(utc.default)
|
|
||||||
return d
|
|
||||||
})())
|
|
||||||
})()
|
|
||||||
|
|
||||||
const findAvailableSlots = async (c1 = [], c2 = [], cfg = {}) => {
|
|
||||||
const d = await loadDay()
|
|
||||||
const u = v => d.utc(v)
|
|
||||||
const {
|
|
||||||
durationMinutes: dm,
|
|
||||||
searchRange: sr = {},
|
|
||||||
workHours: wh = {}
|
|
||||||
} = cfg
|
|
||||||
const dur = Number(dm)
|
|
||||||
if(!Number.isFinite(dur) || dur <= 0 || !sr.start || !sr.end || !wh.start || !wh.end) return []
|
|
||||||
const s = u(sr.start)
|
|
||||||
const e = u(sr.end)
|
|
||||||
if(!s.isValid() || !e.isValid() || !s.isBefore(e)) return []
|
|
||||||
const toMin = v => {
|
|
||||||
const [h, m = 0] = String(v).split(':').map(Number)
|
|
||||||
if(!Number.isFinite(h) || !Number.isFinite(m)) return null
|
|
||||||
if(h < 0 || h > 24 || m < 0 || m > 59) return null
|
|
||||||
if(h === 24 && m > 0) return null
|
|
||||||
return h * 60 + m
|
|
||||||
}
|
|
||||||
const ws = toMin(wh.start)
|
|
||||||
const we = toMin(wh.end)
|
|
||||||
if(ws == null || we == null || ws >= we) return []
|
|
||||||
const list = [
|
|
||||||
...(Array.isArray(c1) ? c1 : []),
|
|
||||||
...(Array.isArray(c2) ? c2 : [])
|
|
||||||
]
|
|
||||||
const busy = list.map(v => {
|
|
||||||
if(!v?.start || !v?.end) return null
|
|
||||||
const st = u(v.start)
|
|
||||||
const en = u(v.end)
|
|
||||||
if(!st.isValid() || !en.isValid() || !st.isBefore(en)) return null
|
|
||||||
if(!en.isAfter(s) || !st.isBefore(e)) return null
|
|
||||||
return {
|
|
||||||
start: st.isBefore(s) ? s : st,
|
|
||||||
end: en.isAfter(e) ? e : en
|
|
||||||
}
|
|
||||||
}).filter(Boolean).sort((a, b) => a.start.valueOf() - b.start.valueOf())
|
|
||||||
const merged = []
|
|
||||||
for(const slot of busy){
|
|
||||||
if(!merged.length){
|
|
||||||
merged.push({...slot})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
const last = merged[merged.length - 1]
|
|
||||||
if(slot.start.isAfter(last.end)) merged.push({...slot})
|
|
||||||
else if(slot.end.isAfter(last.end)) last.end = slot.end
|
|
||||||
}
|
|
||||||
const free = []
|
|
||||||
let cur = s
|
|
||||||
for(const slot of merged){
|
|
||||||
if(slot.start.isAfter(cur)) free.push({start: cur, end: slot.start})
|
|
||||||
if(slot.end.isAfter(cur)) cur = slot.end
|
|
||||||
}
|
|
||||||
if(cur.isBefore(e)) free.push({start: cur, end: e})
|
|
||||||
if(!free.length) return []
|
|
||||||
const step = dur * 60000
|
|
||||||
if(!Number.isFinite(step) || step <= 0) return []
|
|
||||||
const out = []
|
|
||||||
for(const seg of free){
|
|
||||||
for(let day = seg.start.startOf('day'); day.isBefore(seg.end); day = day.add(1, 'day')){
|
|
||||||
const wsStart = day.add(ws, 'minute')
|
|
||||||
const wsEnd = day.add(we, 'minute')
|
|
||||||
const start = wsStart.isAfter(seg.start) ? wsStart : seg.start
|
|
||||||
const end = wsEnd.isBefore(seg.end) ? wsEnd : seg.end
|
|
||||||
if(!start.isBefore(end)) continue
|
|
||||||
const limit = end.valueOf()
|
|
||||||
for(let t = start.valueOf(); t + step <= limit; t += step){
|
|
||||||
out.push({
|
|
||||||
start: d.utc(t).toISOString(),
|
|
||||||
end: d.utc(t + step).toISOString()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
export default findAvailableSlots;
|
|
||||||
// Generation time: 211.798s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
let _lx;
|
|
||||||
const _loadLuxon = () =>
|
|
||||||
_lx || (_lx = import("https://cdn.jsdelivr.net/npm/luxon@3.4.4/build/es6/luxon.js"));
|
|
||||||
|
|
||||||
async function findAvailableSlots(calendarA, calendarB, constraints) {
|
|
||||||
const { DateTime } = await _loadLuxon();
|
|
||||||
const M = 6e4, DAY = 1440, Z = { zone: "utc" };
|
|
||||||
|
|
||||||
const a = Array.isArray(calendarA) ? calendarA : [];
|
|
||||||
const b = Array.isArray(calendarB) ? calendarB : [];
|
|
||||||
const o = constraints && typeof constraints === "object" ? constraints : {};
|
|
||||||
|
|
||||||
const durMin = Number(o.durationMinutes);
|
|
||||||
if (!(durMin > 0)) return [];
|
|
||||||
const dur = durMin * M;
|
|
||||||
|
|
||||||
const sr = o.searchRange || {};
|
|
||||||
const rs = DateTime.fromISO(sr.start || "", Z);
|
|
||||||
const re = DateTime.fromISO(sr.end || "", Z);
|
|
||||||
if (!rs.isValid || !re.isValid) return [];
|
|
||||||
const r0 = rs.toMillis(), r1 = re.toMillis();
|
|
||||||
if (r0 >= r1) return [];
|
|
||||||
|
|
||||||
const wh = o.workHours || {};
|
|
||||||
const toMin = t => {
|
|
||||||
const [h, m] = String(t).split(":").map(Number);
|
|
||||||
if (!Number.isFinite(h) || !Number.isFinite(m)) return NaN;
|
|
||||||
if (h === 24 && m === 0) return DAY;
|
|
||||||
if (h < 0 || h > 23 || m < 0 || m > 59) return NaN;
|
|
||||||
return h * 60 + m;
|
|
||||||
};
|
|
||||||
const ws = toMin(wh.start), we = toMin(wh.end);
|
|
||||||
if (!Number.isFinite(ws) || !Number.isFinite(we)) return [];
|
|
||||||
|
|
||||||
const clamp = (s, e) => {
|
|
||||||
s = Math.max(s, r0);
|
|
||||||
e = Math.min(e, r1);
|
|
||||||
return s < e ? [s, e] : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const busy = [];
|
|
||||||
const add = (s, e) => {
|
|
||||||
const c = clamp(s, e);
|
|
||||||
if (c) busy.push(c);
|
|
||||||
};
|
|
||||||
|
|
||||||
const addEvent = ev => {
|
|
||||||
const s = DateTime.fromISO(ev?.start || "", Z);
|
|
||||||
const e = DateTime.fromISO(ev?.end || "", Z);
|
|
||||||
if (!s.isValid || !e.isValid) return;
|
|
||||||
const x = s.toMillis(), y = e.toMillis();
|
|
||||||
if (x < y) add(x, y);
|
|
||||||
};
|
|
||||||
|
|
||||||
a.forEach(addEvent);
|
|
||||||
b.forEach(addEvent);
|
|
||||||
|
|
||||||
for (let d = rs.startOf("day"); d.toMillis() < r1; d = d.plus({ days: 1 })) {
|
|
||||||
const base = d.toMillis();
|
|
||||||
const off = (x, y) => add(base + x * M, base + y * M);
|
|
||||||
|
|
||||||
if (ws === we) off(0, DAY);
|
|
||||||
else if (ws < we) {
|
|
||||||
if (ws) off(0, ws);
|
|
||||||
if (we < DAY) off(we, DAY);
|
|
||||||
} else off(we, ws);
|
|
||||||
}
|
|
||||||
|
|
||||||
busy.sort((x, y) => x[0] - y[0] || x[1] - y[1]);
|
|
||||||
|
|
||||||
const merged = [];
|
|
||||||
for (const [s, e] of busy) {
|
|
||||||
const last = merged[merged.length - 1];
|
|
||||||
if (!last || s > last[1]) merged.push([s, e]);
|
|
||||||
else last[1] = Math.max(last[1], e);
|
|
||||||
}
|
|
||||||
|
|
||||||
const out = [];
|
|
||||||
const iso = ms => new Date(ms).toISOString();
|
|
||||||
const pushSlot = (s, e) => out.push({ start: iso(s), end: iso(e) });
|
|
||||||
|
|
||||||
let cur = r0;
|
|
||||||
for (const [s, e] of merged) {
|
|
||||||
if (cur < s) {
|
|
||||||
for (let t = cur; t + dur <= s; t += dur) pushSlot(t, t + dur);
|
|
||||||
}
|
|
||||||
if (e > cur) cur = e;
|
|
||||||
if (cur >= r1) return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let t = cur; t + dur <= r1; t += dur) pushSlot(t, t + dur);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
export default findAvailableSlots;
|
|
||||||
// Generation time: 822.838s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
async function validateJSON(json, schema) {
|
|
||||||
const { default: Ajv } = await import("https://esm.sh/ajv@8");
|
|
||||||
const ajv = new Ajv({ allErrors: true });
|
|
||||||
const valid = ajv.validate(schema, json);
|
|
||||||
return {
|
|
||||||
valid,
|
|
||||||
errors: valid ? [] : ajv.errors.map(e => `${e.instancePath || "/"} ${e.message}`)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
export default validateJSON;
|
|
||||||
// Generation time: 3.592s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
async function validateJSON(json, schema) {
|
|
||||||
const Ajv = (await import("https://esm.sh/ajv@8")).default;
|
|
||||||
const ajv = new Ajv({ allErrors: true });
|
|
||||||
const validate = ajv.compile(schema);
|
|
||||||
const valid = validate(json);
|
|
||||||
return {
|
|
||||||
valid: !!valid,
|
|
||||||
errors: valid ? [] : validate.errors.map(e =>
|
|
||||||
`${e.instancePath ? e.instancePath + " " : ""}${e.message}`
|
|
||||||
)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
export default validateJSON;
|
|
||||||
// Generation time: 4.304s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
export const validateJSON = async (data, schema) => {
|
|
||||||
const { default: Ajv } = await import('https://cdn.jsdelivr.net/npm/ajv@8.12.0/+esm');
|
|
||||||
const ajv = new Ajv({ allErrors: true, strict: false });
|
|
||||||
const validate = ajv.compile(schema);
|
|
||||||
const isValid = validate(data);
|
|
||||||
|
|
||||||
return {
|
|
||||||
valid: isValid,
|
|
||||||
errors: isValid ? [] : validate.errors.map(({ instancePath, message }) =>
|
|
||||||
`${instancePath || 'root'} ${message}`.trim()
|
|
||||||
)
|
|
||||||
};
|
|
||||||
};
|
|
||||||
export default validateJSON;
|
|
||||||
// Generation time: 6.123s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
async function validateJSON(data, schema) {
|
|
||||||
const Ajv = (await import('https://cdn.jsdelivr.net/npm/ajv@8.12.0/dist/ajv2019.min.js')).default;
|
|
||||||
|
|
||||||
const ajv = new Ajv({ allErrors: true, strict: false });
|
|
||||||
const validate = ajv.compile(schema);
|
|
||||||
const valid = validate(data);
|
|
||||||
|
|
||||||
if (valid) {
|
|
||||||
return { valid: true, errors: [] };
|
|
||||||
}
|
|
||||||
|
|
||||||
const errors = validate.errors.map(error => {
|
|
||||||
const message = `${error.instancePath} ${error.message}`;
|
|
||||||
return error.params && error.params.allowedValues
|
|
||||||
? `${message} (allowed: ${error.params.allowedValues.join(', ')})`
|
|
||||||
: message;
|
|
||||||
});
|
|
||||||
|
|
||||||
return { valid: false, errors };
|
|
||||||
}
|
|
||||||
export default validateJSON;
|
|
||||||
// Generation time: 6.888s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
export async function validateJSON(data, schema) {
|
|
||||||
try {
|
|
||||||
const AjvMod = await import('https://esm.sh/ajv@8.17.1');
|
|
||||||
const FormatsMod = await import('https://esm.sh/ajv-formats@3.0.1?deps=ajv@8.17.1');
|
|
||||||
const Ajv = AjvMod.default;
|
|
||||||
const addFormats = FormatsMod.default;
|
|
||||||
|
|
||||||
const ajv = new Ajv({ allErrors: true, strict: false, allowUnionTypes: true });
|
|
||||||
addFormats(ajv);
|
|
||||||
|
|
||||||
if (schema && typeof schema === 'object' && schema.$schema && typeof schema.$schema === 'string') {
|
|
||||||
try { ajv.addMetaSchema(JSON.parse(schema.$schema)); } catch {}
|
|
||||||
}
|
|
||||||
|
|
||||||
const validate = ajv.compile(schema);
|
|
||||||
const valid = validate(data);
|
|
||||||
|
|
||||||
if (valid) return { valid: true, errors: [] };
|
|
||||||
|
|
||||||
const errors = validate.errors.map(err => {
|
|
||||||
const path = err.instancePath || '';
|
|
||||||
const loc = path.replace(/\//g, '.').replace(/^\./, '') || 'root';
|
|
||||||
let msg = `${loc} ${err.message}`;
|
|
||||||
if (err.params) {
|
|
||||||
const params = Object.assign({}, err.params);
|
|
||||||
if (params.limit !== undefined) msg += ` (limit=${params.limit})`;
|
|
||||||
if (params.type) msg += ` (type=${params.type})`;
|
|
||||||
if (params.format) msg += ` (format=${params.format})`;
|
|
||||||
if (params.pattern) msg += ` (pattern=${params.pattern})`;
|
|
||||||
if (params.missingProperty) msg += ` (missingProperty=${params.missingProperty})`;
|
|
||||||
if (params.additionalProperty) msg += ` (additionalProperty=${params.additionalProperty})`;
|
|
||||||
if (params.existingCount !== undefined && params.allowedLength !== undefined) msg += ` (count=${params.existingCount}/${params.allowedLength})`;
|
|
||||||
}
|
|
||||||
return msg;
|
|
||||||
});
|
|
||||||
|
|
||||||
return { valid: false, errors };
|
|
||||||
} catch (e) {
|
|
||||||
return { valid: false, errors: [String(e && e.message || e)] };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export default validateJSON;
|
|
||||||
// Generation time: 22.759s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
let a, c;
|
|
||||||
|
|
||||||
export const validateJSON = async (d, s) => {
|
|
||||||
try {
|
|
||||||
if (!a) {
|
|
||||||
const { default: Ajv } = await import('https://esm.sh/ajv?bundle');
|
|
||||||
a = new Ajv({ allErrors: true });
|
|
||||||
c = new Map();
|
|
||||||
}
|
|
||||||
const k = JSON.stringify(s);
|
|
||||||
if (!c.has(k)) c.set(k, a.compile(s));
|
|
||||||
const v = c.get(k);
|
|
||||||
const valid = v(d);
|
|
||||||
return {
|
|
||||||
valid,
|
|
||||||
errors: valid ? [] : v.errors.map(e => `${e.instancePath || 'root'} ${e.message}`)
|
|
||||||
};
|
|
||||||
} catch (e) {
|
|
||||||
return { valid: false, errors: [e.message] };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
export default validateJSON;
|
|
||||||
// Generation time: 19.566s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
async function validateJSON(d,s){
|
|
||||||
const{default:A}=await import('https://cdn.skypack.dev/ajv@8.12.0')
|
|
||||||
const a=new A
|
|
||||||
const v=a.compile(s)
|
|
||||||
const ok=v(d)
|
|
||||||
return ok?{valid:!0,errors:[]}:{valid:!1,errors:v.errors.map(e=>(e.instancePath||'root')+' '+e.message)}
|
|
||||||
}
|
|
||||||
export default validateJSON;
|
|
||||||
// Generation time: 4.189s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
const loadAjv = (() => {
|
|
||||||
let ajv
|
|
||||||
return async () => {
|
|
||||||
if (!ajv) {
|
|
||||||
const { default: Ajv } = await import('https://cdn.jsdelivr.net/npm/ajv@8.12.0/dist/ajv.js')
|
|
||||||
ajv = new Ajv({ allErrors: true, strict: false })
|
|
||||||
}
|
|
||||||
return ajv
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
|
|
||||||
export const validateJSON = async (data, schema) => {
|
|
||||||
const ajv = await loadAjv()
|
|
||||||
const validate = ajv.compile(schema)
|
|
||||||
const valid = validate(data)
|
|
||||||
const errors = valid ? [] : validate.errors.map(e => `${e.instancePath || '/'} ${e.message}`)
|
|
||||||
return { valid, errors }
|
|
||||||
}
|
|
||||||
export default validateJSON;
|
|
||||||
// Generation time: 6.678s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
let _ajvP
|
|
||||||
|
|
||||||
const _ajv = async () => {
|
|
||||||
if (_ajvP) return _ajvP
|
|
||||||
_ajvP = (async () => {
|
|
||||||
const [{ default: Ajv }, { default: addFormats }] = await Promise.all([
|
|
||||||
import("https://esm.sh/ajv@8.12.0"),
|
|
||||||
import("https://esm.sh/ajv-formats@2.1.1")
|
|
||||||
])
|
|
||||||
const ajv = new Ajv({ allErrors: true, strict: false, allowUnionTypes: true })
|
|
||||||
addFormats(ajv)
|
|
||||||
return ajv
|
|
||||||
})()
|
|
||||||
return _ajvP
|
|
||||||
}
|
|
||||||
|
|
||||||
const _err = e => {
|
|
||||||
let p = e.instancePath || ""
|
|
||||||
let m = e.message || "is invalid"
|
|
||||||
if (e.keyword === "required" && e.params?.missingProperty) {
|
|
||||||
p += `/${e.params.missingProperty}`
|
|
||||||
m = "is required"
|
|
||||||
} else if (e.keyword === "additionalProperties" && e.params?.additionalProperty) {
|
|
||||||
p += `/${e.params.additionalProperty}`
|
|
||||||
m = "is not allowed"
|
|
||||||
}
|
|
||||||
return `${p || "/"} ${m}`.trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
async function validateJSON(json, schema) {
|
|
||||||
let ajv, v
|
|
||||||
try { ajv = await _ajv() } catch (e) { return { valid: false, errors: [String(e?.message || e)] } }
|
|
||||||
try { v = ajv.compile(schema) } catch (e) { return { valid: false, errors: [String(e?.message || e)] } }
|
|
||||||
|
|
||||||
const valid = !!v(json)
|
|
||||||
return { valid, errors: valid ? [] : (v.errors || []).map(_err) }
|
|
||||||
}
|
|
||||||
export default validateJSON;
|
|
||||||
// Generation time: 95.873s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
async function createStreamVisualizer(asyncIterable, options) {
|
|
||||||
const { maxPoints, alpha, width, height, yDomain } = options;
|
|
||||||
|
|
||||||
const d3 = await import("https://cdn.jsdelivr.net/npm/d3@7/+esm");
|
|
||||||
|
|
||||||
const data = [];
|
|
||||||
let prevEma = null;
|
|
||||||
|
|
||||||
for await (const { timestamp, value } of asyncIterable) {
|
|
||||||
const ema = prevEma === null
|
|
||||||
? value
|
|
||||||
: alpha * value + (1 - alpha) * prevEma;
|
|
||||||
prevEma = ema;
|
|
||||||
data.push({ timestamp, value, ema });
|
|
||||||
if (data.length > maxPoints) data.shift();
|
|
||||||
}
|
|
||||||
|
|
||||||
const xScale = d3.scaleLinear()
|
|
||||||
.domain([data[0].timestamp, data[data.length - 1].timestamp])
|
|
||||||
.range([0, width]);
|
|
||||||
|
|
||||||
const yScale = d3.scaleLinear()
|
|
||||||
.domain(yDomain)
|
|
||||||
.range([height, 0]);
|
|
||||||
|
|
||||||
const lineGen = d3.line()
|
|
||||||
.x(d => xScale(d.timestamp))
|
|
||||||
.y(d => yScale(d.ema));
|
|
||||||
|
|
||||||
const path = lineGen(data);
|
|
||||||
|
|
||||||
return { data, path };
|
|
||||||
}
|
|
||||||
export default createStreamVisualizer;
|
|
||||||
// Generation time: 4.923s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
async function createStreamVisualizer(asyncIterable, options) {
|
|
||||||
const { maxPoints, alpha, width, height, yDomain } = options;
|
|
||||||
|
|
||||||
const d3 = await import("https://cdn.jsdelivr.net/npm/d3@7/+esm");
|
|
||||||
|
|
||||||
const data = [];
|
|
||||||
let prevEma = null;
|
|
||||||
|
|
||||||
for await (const { timestamp, value } of asyncIterable) {
|
|
||||||
const ema = prevEma === null
|
|
||||||
? value
|
|
||||||
: alpha * value + (1 - alpha) * prevEma;
|
|
||||||
prevEma = ema;
|
|
||||||
data.push({ timestamp, value, ema });
|
|
||||||
if (data.length > maxPoints) data.shift();
|
|
||||||
}
|
|
||||||
|
|
||||||
const xScale = d3.scaleLinear()
|
|
||||||
.domain([data[0].timestamp, data[data.length - 1].timestamp])
|
|
||||||
.range([0, width]);
|
|
||||||
|
|
||||||
const yScale = d3.scaleLinear()
|
|
||||||
.domain(yDomain)
|
|
||||||
.range([height, 0]);
|
|
||||||
|
|
||||||
const lineGen = d3.line()
|
|
||||||
.x(d => xScale(d.timestamp))
|
|
||||||
.y(d => yScale(d.ema));
|
|
||||||
|
|
||||||
const path = lineGen(data);
|
|
||||||
|
|
||||||
return { data, path };
|
|
||||||
}
|
|
||||||
export default createStreamVisualizer;
|
|
||||||
// Generation time: 5.157s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
export async function createStreamVisualizer(asyncIterable, { maxPoints, alpha, width, height, yDomain }) {
|
|
||||||
const d3 = await import("https://cdn.skypack.dev/d3@7");
|
|
||||||
let data = [];
|
|
||||||
let ema = null;
|
|
||||||
|
|
||||||
for await (const { timestamp, value } of asyncIterable) {
|
|
||||||
ema = (ema === null) ? 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 = d3.scaleLinear()
|
|
||||||
.domain([data[0].timestamp, data.at(-1).timestamp])
|
|
||||||
.range([0, width]);
|
|
||||||
|
|
||||||
const y = d3.scaleLinear()
|
|
||||||
.domain(yDomain)
|
|
||||||
.range([height, 0]);
|
|
||||||
|
|
||||||
const lineGenerator = d3.line()
|
|
||||||
.x(d => x(d.timestamp))
|
|
||||||
.y(d => y(d.ema));
|
|
||||||
|
|
||||||
return {
|
|
||||||
data,
|
|
||||||
path: lineGenerator(data)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
export default createStreamVisualizer;
|
|
||||||
// Generation time: 11.081s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
export async function createStreamVisualizer(asyncIterable, options) {
|
|
||||||
const { maxPoints, alpha, width, height, yDomain } = options;
|
|
||||||
const d3 = await import('https://cdn.jsdelivr.net/npm/d3@7/+esm');
|
|
||||||
|
|
||||||
const data = [];
|
|
||||||
let prevEma = null;
|
|
||||||
|
|
||||||
for await (const point of asyncIterable) {
|
|
||||||
const { timestamp, value } = point;
|
|
||||||
const ema = prevEma === null
|
|
||||||
? value
|
|
||||||
: alpha * value + (1 - alpha) * prevEma;
|
|
||||||
prevEma = ema;
|
|
||||||
|
|
||||||
data.push({ timestamp, value, ema });
|
|
||||||
if (data.length > maxPoints) {
|
|
||||||
data.shift();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.length === 0) {
|
|
||||||
return { data: [], path: '' };
|
|
||||||
}
|
|
||||||
|
|
||||||
const [first, last] = [data[0], data[data.length - 1]];
|
|
||||||
const xScale = d3.scaleLinear()
|
|
||||||
.domain([first.timestamp, last.timestamp])
|
|
||||||
.range([0, width]);
|
|
||||||
|
|
||||||
const yScale = d3.scaleLinear()
|
|
||||||
.domain(yDomain)
|
|
||||||
.range([height, 0]);
|
|
||||||
|
|
||||||
const path = d3.line()
|
|
||||||
.x(d => xScale(d.timestamp))
|
|
||||||
.y(d => yScale(d.ema))
|
|
||||||
.curve(d3.curveLinear)(data);
|
|
||||||
|
|
||||||
return { data, path };
|
|
||||||
}
|
|
||||||
export default createStreamVisualizer;
|
|
||||||
// Generation time: 20.632s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
async function createStreamVisualizer(asyncIterable, { maxPoints, alpha, width, height, yDomain }) {
|
|
||||||
const d3 = await import('d3'), data = [];
|
|
||||||
let pe;
|
|
||||||
|
|
||||||
for await (const { timestamp: t, value: v } of asyncIterable) {
|
|
||||||
const ema = pe === undefined ? v : alpha * v + (1 - alpha) * pe;
|
|
||||||
pe = ema;
|
|
||||||
data.push({ timestamp: t, value: v, ema });
|
|
||||||
data.length > maxPoints && data.shift();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!data.length) return { data: [], path: '' };
|
|
||||||
|
|
||||||
const x = d3.scaleLinear().domain([data[0].timestamp, data.at(-1).timestamp]).range([0, width]);
|
|
||||||
const y = d3.scaleLinear().domain(yDomain).range([height, 0]);
|
|
||||||
|
|
||||||
return { data, path: d3.line().x(d => x(d.timestamp)).y(d => y(d.ema))(data) };
|
|
||||||
}
|
|
||||||
export default createStreamVisualizer;
|
|
||||||
// Generation time: 81.116s
|
|
||||||
// Result: FAIL
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
async function createStreamVisualizer(it,o={}){
|
|
||||||
let{maxPoints=100,alpha=.3,width=300,height=150,yDomain:[y0,y1]=[0,1]}=o
|
|
||||||
let{scaleLinear,line}=await import('https://cdn.jsdelivr.net/npm/d3@7/+esm')
|
|
||||||
let d=[],e
|
|
||||||
for await(let{timestamp:t,value:v}of it){
|
|
||||||
e=e==null?v:alpha*v+(1-alpha)*e
|
|
||||||
d.push({timestamp:+t,value:v,ema:e})
|
|
||||||
d.length>maxPoints&&d.shift()
|
|
||||||
}
|
|
||||||
let p=''
|
|
||||||
if(d.length){
|
|
||||||
let x=scaleLinear().domain([d[0].timestamp,d.at(-1).timestamp]).range([0,width])
|
|
||||||
let y=scaleLinear().domain([y0,y1]).range([height,0])
|
|
||||||
p=line().x(a=>x(a.timestamp)).y(a=>y(a.ema))(d)||''
|
|
||||||
}
|
|
||||||
return{data:d,path:p}
|
|
||||||
}
|
|
||||||
export default createStreamVisualizer;
|
|
||||||
// Generation time: 25.168s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
async function createStreamVisualizer(iterable,options={}){
|
|
||||||
const{maxPoints=100,alpha=.3,width=640,height=320,yDomain=[0,1]}=options
|
|
||||||
const{scaleLinear,line}=await import('https://cdn.jsdelivr.net/npm/d3@7/+esm')
|
|
||||||
const data=[]
|
|
||||||
let ema
|
|
||||||
for await(const{timestamp,value}of iterable){
|
|
||||||
ema=ema==null?value:alpha*value+(1-alpha)*ema
|
|
||||||
data.push({timestamp,value,ema})
|
|
||||||
data.length>maxPoints&&data.shift()
|
|
||||||
}
|
|
||||||
let path=''
|
|
||||||
if(data.length){
|
|
||||||
const x=scaleLinear().domain([data[0].timestamp,data.at(-1).timestamp]).range([0,width])
|
|
||||||
const y=scaleLinear().domain(yDomain).range([height,0])
|
|
||||||
path=line().x(d=>x(d.timestamp)).y(d=>y(d.ema))(data)||''
|
|
||||||
}
|
|
||||||
return{data,path}
|
|
||||||
}
|
|
||||||
export default createStreamVisualizer;
|
|
||||||
// Generation time: 10.093s
|
|
||||||
// Result: PASS
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
const d3Url = "https://cdn.jsdelivr.net/npm/d3@7/+esm";
|
|
||||||
let d3p;
|
|
||||||
|
|
||||||
const loadD3 = () => d3p || (d3p = import(d3Url));
|
|
||||||
const toNum = v => (typeof v == "string" && !v.trim() ? NaN : +v);
|
|
||||||
const toTime = t => (t instanceof Date ? +t : typeof t == "string" && isNaN(+t) ? Date.parse(t) : +t);
|
|
||||||
|
|
||||||
const asPoint = p => {
|
|
||||||
if (p == null) return {};
|
|
||||||
if (typeof p == "number") return { timestamp: Date.now(), value: p };
|
|
||||||
if (Array.isArray(p)) return { timestamp: toTime(p[0]), value: toNum(p[1]) };
|
|
||||||
if (typeof p == "object")
|
|
||||||
return {
|
|
||||||
timestamp: toTime(p.timestamp ?? p.time ?? p.t),
|
|
||||||
value: toNum(p.value ?? p.v ?? p.y)
|
|
||||||
};
|
|
||||||
return {};
|
|
||||||
};
|
|
||||||
|
|
||||||
async function createStreamVisualizer(asyncIterable, o = {}) {
|
|
||||||
const { scaleLinear, line } = await loadD3();
|
|
||||||
|
|
||||||
let {
|
|
||||||
maxPoints = 500,
|
|
||||||
alpha = 0.2,
|
|
||||||
width = 600,
|
|
||||||
height = 200,
|
|
||||||
yDomain = [0, 1]
|
|
||||||
} = o;
|
|
||||||
|
|
||||||
maxPoints =
|
|
||||||
maxPoints === Infinity
|
|
||||||
? Infinity
|
|
||||||
: Number.isFinite(+maxPoints)
|
|
||||||
? Math.max(1, Math.floor(+maxPoints))
|
|
||||||
: 500;
|
|
||||||
|
|
||||||
alpha = Number.isFinite(+alpha) ? Math.min(1, Math.max(0, +alpha)) : 0.2;
|
|
||||||
width = Math.max(0, +width || 0);
|
|
||||||
height = Math.max(0, +height || 0);
|
|
||||||
|
|
||||||
const data = [];
|
|
||||||
let ema, seeded = false;
|
|
||||||
|
|
||||||
for await (const item of asyncIterable) {
|
|
||||||
const { timestamp, value } = asPoint(item);
|
|
||||||
if (!Number.isFinite(timestamp) || !Number.isFinite(value)) continue;
|
|
||||||
|
|
||||||
ema = seeded ? alpha * value + (1 - alpha) * ema : (seeded = true, value);
|
|
||||||
data.push({ timestamp, value, ema });
|
|
||||||
if (data.length > maxPoints) data.splice(0, data.length - maxPoints);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!data.length) return { data, path: "" };
|
|
||||||
|
|
||||||
let t0 = data[0].timestamp,
|
|
||||||
t1 = data[data.length - 1].timestamp;
|
|
||||||
if (t0 === t1) t1 = t0 + 1;
|
|
||||||
|
|
||||||
let [y0, y1] = Array.isArray(yDomain) ? yDomain : [0, 1];
|
|
||||||
y0 = toNum(y0);
|
|
||||||
y1 = toNum(y1);
|
|
||||||
if (!Number.isFinite(y0) || !Number.isFinite(y1)) (y0 = 0), (y1 = 1);
|
|
||||||
if (y0 === y1) y1 = y0 + 1;
|
|
||||||
|
|
||||||
const x = scaleLinear().domain([t0, t1]).range([0, width]);
|
|
||||||
const y = scaleLinear().domain([y0, y1]).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: 140.623s
|
|
||||||
// Result: PASS
|
|
||||||
Reference in New Issue
Block a user