Docs: Update benchmark results

This commit is contained in:
github-actions[bot]
2025-11-27 19:36:55 +00:00
parent e8b9dd6d0e
commit ba567f4017
109 changed files with 1138 additions and 1679 deletions

View File

@@ -5,3 +5,5 @@ async function hashPassword(p, s) {
return [...h].map(b => b.toString(16).padStart(2, '0')).join('') return [...h].map(b => b.toString(16).padStart(2, '0')).join('')
} }
export default hashPassword; export default hashPassword;
// Generation time: 2.609s
// Result: PASS

View File

@@ -1,9 +1,9 @@
async function hashPassword(password, salt) { async function hashPassword(password, salt) {
const { scrypt } = await import('https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/+esm'); const { scrypt } = await import('https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/+esm');
const encoder = new TextEncoder(); const enc = new TextEncoder();
const hash = await scrypt( const hash = await scrypt(
encoder.encode(password), enc.encode(password),
encoder.encode(salt), enc.encode(salt),
1024, 1024,
8, 8,
1, 1,
@@ -12,3 +12,5 @@ async function hashPassword(password, salt) {
return Array.from(hash, b => b.toString(16).padStart(2, '0')).join(''); return Array.from(hash, b => b.toString(16).padStart(2, '0')).join('');
} }
export default hashPassword; export default hashPassword;
// Generation time: 2.743s
// Result: PASS

View File

@@ -1,19 +0,0 @@
const hashPassword = async (password, salt) => {
const { scrypt } = await import('https://esm.sh/scrypt-js@3.0.1');
const encoder = new TextEncoder();
const hashBytes = await scrypt(
encoder.encode(password),
encoder.encode(salt),
1024,
8,
1,
32
);
return [...hashBytes]
.map(b => b.toString(16).padStart(2, '0'))
.join('');
};
export default hashPassword;

View File

@@ -2,6 +2,8 @@ const hashPassword = async (p, s) => {
const { scrypt } = await import('https://esm.sh/scrypt-js') const { scrypt } = await import('https://esm.sh/scrypt-js')
const e = new TextEncoder() const e = new TextEncoder()
const h = await scrypt(e.encode(p), e.encode(s), 1024, 8, 1, 32) 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('') return Array.from(h).map(b => b.toString(16).padStart(2, '0')).join('')
} }
export default hashPassword; export default hashPassword;
// Generation time: 18.084s
// Result: PASS

View File

@@ -1,9 +1,9 @@
async function hashPassword(password, salt) { async function hashPassword(password, salt) {
const { default: scrypt } = await import('https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/index.js'); const { scrypt } = await import('https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/dist/scrypt.min.js');
const e = new TextEncoder(); const enc = new TextEncoder();
const p = e.encode(password); const buf = await scrypt(enc.encode(password), enc.encode(salt), 1024, 8, 1, 32);
const s = e.encode(salt); return Array.from(buf, b => b.toString(16).padStart(2, '0')).join('');
const h = await scrypt(p, s, 1024, 8, 1, 32);
return [...h].map(b => b.toString(16).padStart(2, '0')).join('');
} }
export default hashPassword; export default hashPassword;
// Generation time: 39.100s
// Result: FAIL

View File

@@ -1,7 +1,9 @@
const e=new TextEncoder
const hashPassword=async(p,s)=>{ const hashPassword=async(p,s)=>{
const{ scrypt }=await import('https://cdn.skypack.dev/scrypt-js') 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) const h=await scrypt(e.encode(p),e.encode(s),1024,8,1,32)
return Array.from(h,x=>(x+256).toString(16).slice(-2)).join('') return [...h].map(b=>b.toString(16).padStart(2,'0')).join('')
} }
export default hashPassword; export default hashPassword;
// Generation time: 8.405s
// Result: PASS

View File

@@ -1,12 +0,0 @@
const hashPassword = async (password, salt) => {
const { scrypt } = await import('https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/scrypt.min.js')
const encoder = new TextEncoder()
const passwordBytes = encoder.encode(password)
const saltBytes = encoder.encode(salt)
const hashBytes = await scrypt(passwordBytes, saltBytes, 1024, 8, 1, 32)
return Array.from(hashBytes)
.map(b => b.toString(16).padStart(2, '0'))
.join('')
}
export default hashPassword;

View File

@@ -1,9 +0,0 @@
async function hashPassword(password, salt) {
const { scrypt } = await import('https://cdn.skypack.dev/scrypt-js');
const e = new TextEncoder();
const pw = e.encode(password);
const s = e.encode(salt);
const h = await scrypt(pw, s, 1024, 8, 1, 32);
return Array.from(h).map(b=>b.toString(16).padStart(2,'0')).join('');
}
export default hashPassword;

View File

@@ -1,9 +0,0 @@
async function hashPassword(password, salt) {
const { scrypt } = await import('https://cdn.skypack.dev/scrypt-js');
const encoder = new TextEncoder();
const pwBuf = encoder.encode(password);
const saltBuf = encoder.encode(salt);
const hashBuf = await scrypt(pwBuf, saltBuf, 1024, 8, 1, 32);
return Array.from(hashBuf).map(b => b.toString(16).padStart(2, '0')).join('');
}
export default hashPassword;

View File

@@ -0,0 +1,11 @@
async function hashPassword(password, salt) {
const { scrypt } = await import('https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/index.js');
const encoder = new TextEncoder();
const passwordBytes = encoder.encode(password);
const saltBytes = encoder.encode(salt);
const hashBytes = await scrypt(passwordBytes, saltBytes, 1024, 8, 1, 32);
return Array.from(hashBytes, byte => byte.toString(16).padStart(2, '0')).join('').toLowerCase();
}
export default hashPassword;
// Generation time: 12.779s
// Result: FAIL

View File

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

View File

@@ -12,3 +12,5 @@ async function analyzeGPS(readings, boundary) {
return Math.round(turf.length(line) * 100) / 100; return Math.round(turf.length(line) * 100) / 100;
} }
export default analyzeGPS; export default analyzeGPS;
// Generation time: 2.827s
// Result: PASS

View File

@@ -1,18 +0,0 @@
const analyzeGPS = async (readings, boundary) => {
const { booleanPointInPolygon, lineString, length } = await import('https://cdn.jsdelivr.net/npm/@turf/turf/+esm');
const sortedCoords = readings
.filter(({ loc }) => booleanPointInPolygon(loc, boundary, { ignoreBoundary: true }))
.sort((a, b) => a.ts - b.ts)
.map(({ loc }) => loc);
if (sortedCoords.length < 2) {
return 0;
}
const path = lineString(sortedCoords);
const dist = length(path, { units: 'kilometers' });
return Math.round(dist * 1e2) / 1e2;
};
export default analyzeGPS;

View File

@@ -1,12 +1,14 @@
const analyzeGPS = async (readings, boundary) => { const analyzeGPS = async (readings, boundary) => {
const turf = await import('https://cdn.jsdelivr.net/npm/@turf/turf/+esm'); const t = await import('https://cdn.jsdelivr.net/npm/@turf/turf/+esm');
const pts = readings const pts = readings
.filter(({ loc }) => turf.booleanPointInPolygon(turf.point(loc), boundary)) .filter(r => t.booleanPointInPolygon(t.point(r.loc), boundary, { ignoreBoundary: true }))
.sort((a, b) => a.ts - b.ts) .sort((a, b) => a.ts - b.ts)
.map(r => r.loc); .map(r => r.loc);
return pts.length < 2 ? 0 : return pts.length < 2 ? 0
+turf.length(turf.lineString(pts), { units: 'kilometers' }).toFixed(2); : +t.length(t.lineString(pts), { units: 'kilometers' }).toFixed(2);
}; };
export default analyzeGPS; export default analyzeGPS;
// Generation time: 41.986s
// Result: PASS

View File

@@ -1,11 +1,18 @@
export async function analyzeGPS(readings, boundary) { async function analyzeGPS(readings, boundary) {
const { booleanPointInPolygon, lineString, length } = await import('https://cdn.skypack.dev/@turf/turf'); 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 pts = readings const turf = await import('https://cdn.skypack.dev/@turf/turf').catch(() => null);
.filter(r => booleanPointInPolygon(r.loc, boundary)) if (!turf) return 0;
const points = valid
.filter(r => turf.booleanPointInPolygon(r.loc, boundary))
.sort((a, b) => a.ts - b.ts) .sort((a, b) => a.ts - b.ts)
.map(r => r.loc); .map(r => r.loc);
return pts.length < 2 ? 0 : +length(lineString(pts)).toFixed(2); return points.length < 2 ? 0 : Math.round(turf.length(turf.lineString(points), {units: 'kilometers'}) * 100) / 100;
} }
export default analyzeGPS; export default analyzeGPS;
// Generation time: 48.580s
// Result: PASS

View File

@@ -1,13 +1,12 @@
let turf$; let turfReady
const useTurf = () => turf$ ??= import('https://cdn.skypack.dev/@turf/turf?min'); const loadTurf=()=>turfReady||(turfReady=import('https://cdn.jsdelivr.net/npm/@turf/turf@6.5.0/+esm'))
async function analyzeGPS(readings,boundary){
async function analyzeGPS(readings, boundary) { const {point,lineString,length,booleanPointInPolygon}=await loadTurf()
const t = await useTurf(); const inBounds=readings.filter(r=>booleanPointInPolygon(point(r.loc),boundary,{ignoreBoundary:true})).sort((a,b)=>a.ts-b.ts)
const pts = readings if(inBounds.length<2)return 0
.filter(r => t.booleanPointInPolygon(t.point(r.loc), boundary)) const km=length(lineString(inBounds.map(r=>r.loc)),{units:'kilometers'})
.sort((a, b) => a.ts - b.ts); return +km.toFixed(2)
if (pts.length < 2) return 0;
const km = t.length(t.lineString(pts.map(r => r.loc)), { units: 'kilometers' });
return Math.round(km * 100) / 100;
} }
export default analyzeGPS; export default analyzeGPS;
// Generation time: 8.791s
// Result: PASS

View File

@@ -1,16 +0,0 @@
export const analyzeGPS = async (readings, boundary) => {
const { default: turf } = await import('https://unpkg.com/@turf/turf@6/turf.min.js')
const inside = readings.filter(({ loc }) =>
turf.booleanPointInPolygon(turf.point(loc), boundary, { ignoreBoundary: false })
)
if (inside.length < 2) return 0
const sorted = inside.sort((a, b) => a.ts - b.ts)
const line = turf.lineString(sorted.map(({ loc }) => loc))
const length = turf.length(line, { units: 'kilometers' })
return Math.round(length * 100) / 100
}
export default analyzeGPS;

View File

@@ -1,8 +0,0 @@
async function analyzeGPS(readings,boundary){
const{booleanPointInPolygon,lineString,length}=await import('https://cdn.skypack.dev/@turf/turf');
const valid=readings
.filter(r=>booleanPointInPolygon({type:'Point',coordinates:r.loc},boundary,{ignoreBoundary:true}))
.sort((a,b)=>a.ts-b.ts);
return valid.length<2?0:+length(lineString(valid.map(r=>r.loc)),{units:'kilometers'}).toFixed(2);
}
export default analyzeGPS;

View File

@@ -1,6 +0,0 @@
async function analyzeGPS(readings, boundary) {
const { point: p, booleanPointInPolygon: i, lineString: s, length: l } = await import('https://esm.sh/@turf/turf@6');
const v = readings.filter(r => i(p(r.loc), boundary)).sort((a, b) => a.ts - b.ts);
return v.length < 2 ? 0 : +l(s(v.map(r => r.loc))).toFixed(2);
}
export default analyzeGPS;

View File

@@ -0,0 +1,13 @@
async function analyzeGPS(readings, boundary) {
const turf = await import('https://cdn.jsdelivr.net/npm/@turf/turf@6/turf.min.js');
const valid = readings
.filter(r => turf.booleanPointInPolygon(turf.point(r.loc), boundary))
.sort((a, b) => a.ts - b.ts);
if (valid.length < 2) return 0;
const line = { type: 'LineString', coordinates: valid.map(r => r.loc) };
const length = turf.length(line, { units: 'kilometers' });
return Math.round(length * 100) / 100;
}
export default analyzeGPS;
// Generation time: 17.976s
// Result: FAIL

View File

@@ -1,12 +1,10 @@
async function findShortestPath(graph, start, end) { async function findShortestPath(graph, start, end) {
const { default: PriorityQueue } = await import("https://esm.run/js-priority-queue"); const { default: PriorityQueue } = await import('https://cdn.jsdelivr.net/npm/js-priority-queue@0.4.1/+esm');
const dist = {}, visited = new Set();
for (let n in graph) dist[n] = Infinity;
dist[start] = 0;
const dist = { [start]: 0 };
const visited = new Set();
const pq = new PriorityQueue({ comparator: (a, b) => a[1] - b[1] }); const pq = new PriorityQueue({ comparator: (a, b) => a[1] - b[1] });
pq.queue([start, 0]); pq.queue([start, 0]);
while (pq.length) { while (pq.length) {
@@ -17,16 +15,17 @@ async function findShortestPath(graph, start, end) {
if (node === end) return d; if (node === end) return d;
for (let neighbor in graph[node] || {}) { for (const [neighbor, weight] of Object.entries(graph[node] || {})) {
if (visited.has(neighbor)) continue; const newDist = d + weight;
const newDist = d + graph[node][neighbor]; if (newDist < (dist[neighbor] ?? Infinity)) {
if (newDist < dist[neighbor]) {
dist[neighbor] = newDist; dist[neighbor] = newDist;
pq.queue([neighbor, newDist]); pq.queue([neighbor, newDist]);
} }
} }
} }
return dist[end] ?? Infinity; return Infinity;
} }
export default findShortestPath; export default findShortestPath;
// Generation time: 4.850s
// Result: FAIL

View File

@@ -1,31 +1,35 @@
async function findShortestPath(graph, start, end) { async function findShortestPath(graph, start, end) {
const { default: PriorityQueue } = await import('https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.5/+esm'); const { default: PriorityQueue } = await import('https://cdn.skypack.dev/js-priority-queue');
const distances = Object.keys(graph).reduce((acc, node) => ({ ...acc, [node]: Infinity }), {});
distances[start] = 0;
const distances = {};
const visited = new Set();
const pq = new PriorityQueue({ comparator: (a, b) => a.dist - b.dist }); const pq = new PriorityQueue({ comparator: (a, b) => a.dist - b.dist });
for (const node in graph) distances[node] = Infinity;
distances[start] = 0;
pq.queue({ node: start, dist: 0 }); pq.queue({ node: start, dist: 0 });
const visited = new Set(); while (pq.length > 0) {
while (pq.length) {
const { node, dist } = pq.dequeue(); const { node, dist } = pq.dequeue();
if (visited.has(node)) continue; if (visited.has(node)) continue;
visited.add(node);
if (node === end) return dist; if (node === end) return dist;
for (const [neighbor, weight] of Object.entries(graph[node] || {})) { visited.add(node);
const newDist = dist + weight;
for (const neighbor in graph[node]) {
if (!visited.has(neighbor)) {
const newDist = dist + graph[node][neighbor];
if (newDist < distances[neighbor]) { if (newDist < distances[neighbor]) {
distances[neighbor] = newDist; distances[neighbor] = newDist;
pq.queue({ node: neighbor, dist: newDist }); pq.queue({ node: neighbor, dist: newDist });
} }
} }
} }
}
return distances[end]; return Infinity;
} }
export default findShortestPath; export default findShortestPath;
// Generation time: 4.029s
// Result: PASS

View File

@@ -1,40 +0,0 @@
async function findShortestPath(graph, startNode, endNode) {
const { default: PriorityQueue } = await import(
'https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.5/priority-queue.min.js'
);
const distances = {};
const pq = new PriorityQueue({ comparator: (a, b) => a.priority - b.priority });
for (const node in graph) {
distances[node] = Infinity;
}
distances[startNode] = 0;
pq.queue({ node: startNode, priority: 0 });
while (pq.length) {
const { node: currentNode, priority: currentPriority } = pq.dequeue();
if (currentPriority > distances[currentNode]) {
continue;
}
if (currentNode === endNode) {
return currentPriority;
}
for (const neighbor in graph[currentNode]) {
const weight = graph[currentNode][neighbor];
const newDistance = currentPriority + weight;
if (newDistance < distances[neighbor]) {
distances[neighbor] = newDistance;
pq.queue({ node: neighbor, priority: newDistance });
}
}
}
return Infinity;
}
export default findShortestPath;

View File

@@ -1,7 +1,8 @@
const findShortestPath = async (g, s, e) => { const findShortestPath = async (g, s, e) => {
const { default: Q } = await import('https://esm.sh/js-priority-queue') const { default: PQ } = await import('https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.5/+esm')
const q = new Q({ comparator: (a, b) => a.w - b.w }) const q = new PQ({ comparator: (a, b) => a.w - b.w })
const d = { [s]: 0 } const d = { [s]: 0 }
q.queue({ n: s, w: 0 }) q.queue({ n: s, w: 0 })
while (q.length) { while (q.length) {
@@ -9,14 +10,17 @@ const findShortestPath = async (g, s, e) => {
if (n === e) return w if (n === e) return w
if (w > (d[n] ?? Infinity)) continue if (w > (d[n] ?? Infinity)) continue
for (const v in g[n]) { for (const k in g[n] || {}) {
const k = w + g[n][v] const t = w + g[n][k]
if (k < (d[v] ?? Infinity)) { if (t < (d[k] ?? Infinity)) {
d[v] = k d[k] = t
q.queue({ n: v, w: k }) q.queue({ n: k, w: t })
} }
} }
} }
return Infinity return Infinity
} }
export default findShortestPath; export default findShortestPath;
// Generation time: 30.290s
// Result: PASS

View File

@@ -1,28 +1,27 @@
export async function findShortestPath(graph, start, end) { let PQ;
const { default: PriorityQueue } = await import('https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.5/index.min.js'); export async function findShortestPath(g, s, e) {
if (!(s in g) || !(e in g)) return Infinity;
if (!graph[start] || !graph[end]) return Infinity; if (!PQ) ({ default: PQ } = await import('https://cdn.skypack.dev/js-priority-queue@0.1.5'));
if (start === end) return 0; const d = new Map([[s, 0]]);
const q = new PQ({ comparator: (a, b) => a[1] - b[1] });
const dist = { [start]: 0 }; const v = new Set();
const pq = new PriorityQueue({ comparator: (a, b) => a[0] - b[0] }); q.queue([s, 0]);
pq.queue([0, start]); while (q.length) {
const [n, c] = q.dequeue();
while (pq.length) { if (n === e) return c;
const [d, node] = pq.dequeue(); if (v.has(n)) continue;
v.add(n);
if (node === end) return d; if (c > (d.get(n) ?? Infinity)) continue;
if (d > (dist[node] ?? Infinity)) continue; for (const [p, w] of Object.entries(g[n] || {})) {
const t = c + w;
for (const [n, w] of Object.entries(graph[node] || {})) { if (t < (d.get(p) ?? Infinity)) {
const nd = d + w; d.set(p, t);
if (nd < (dist[n] ?? Infinity)) { q.queue([p, t]);
dist[n] = nd;
pq.queue([nd, n]);
} }
} }
} }
return d.get(e) ?? Infinity;
return Infinity;
} }
export default findShortestPath; export default findShortestPath;
// Generation time: 95.484s
// Result: PASS

View File

@@ -1,30 +1,24 @@
let pqPromise export const findShortestPath=async(g,s,e)=>{
const getPQ=()=>pqPromise??=import('https://cdn.jsdelivr.net/npm/js-priority-queue@latest/+esm') 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]})
async function findShortestPath(g,s,t){ for(const k in g)d[k]=Infinity
if(!g||!(s in g)||!(t in g)) return Infinity d[s]=0
if(s===t) return 0 q.queue([s,0])
const {default:PriorityQueue}=await getPQ() while(q.length){
const d={[s]:0} const[n,w]=q.dequeue()
const seen=new Set if(v.has(n))continue
const q=new PriorityQueue({comparator:(a,b)=>a[0]-b[0]}) if(n===e)return w
q.queue([0,s]) v.add(n)
while(q.length){ for(const[nb,c]of Object.entries(g[n]||{})){
const [w,n]=q.dequeue() const nw=w+c
if(seen.has(n)) continue if(nw<d[nb]){
seen.add(n) d[nb]=nw
if(n===t) return w q.queue([nb,nw])
const edges=g[n] }
if(!edges) continue }
for(const k in edges){ }
if(seen.has(k)) continue return Infinity
const nw=w+edges[k]
if(nw<(d[k]??Infinity)){
d[k]=nw
q.queue([nw,k])
}
}
}
return Infinity
} }
export default findShortestPath; export default findShortestPath;
// Generation time: 9.436s
// Result: PASS

View File

@@ -1,37 +0,0 @@
const findShortestPath = async (graph, start, end) => {
const { default: PriorityQueue } = await import('https://cdn.jsdelivr.net/npm/js-priority-queue@1.0.0/+esm')
if (!graph[start] || !graph[end]) return Infinity
const distances = Object.keys(graph).reduce((acc, node) => {
acc[node] = node === start ? 0 : Infinity
return acc
}, {})
const pq = new PriorityQueue({ comparator: (a, b) => a.distance - b.distance })
pq.queue({ node: start, distance: 0 })
const visited = new Set()
while (pq.length) {
const { node, distance } = pq.dequeue()
if (node === end) return distance
if (visited.has(node)) continue
visited.add(node)
Object.entries(graph[node]).forEach(([neighbor, weight]) => {
if (visited.has(neighbor)) return
const newDistance = distance + weight
if (newDistance < distances[neighbor]) {
distances[neighbor] = newDistance
pq.queue({ node: neighbor, distance: newDistance })
}
})
}
return Infinity
}
export default findShortestPath;

View File

@@ -1,24 +0,0 @@
async function findShortestPath(graph,start,end){
const {PriorityQueue}=await import('https://cdn.skypack.dev/js-priority-queue');
if(start===end)return 0;
const dist={};
dist[start]=0;
const pq=new PriorityQueue({comparator:(a,b)=>a.dist-b.dist});
pq.queue({node:start,dist:0});
while(!pq.isEmpty()){
const u=pq.dequeue();
if(u.dist>dist[u.node])continue;
const neighbors=graph[u.node];
if(!neighbors)continue;
for(const v in neighbors){
const w=neighbors[v];
const alt=dist[u.node]+w;
if(alt<(dist[v]??Infinity)){
dist[v]=alt;
pq.queue({node:v,dist:alt});
}
}
}
return dist[end]??Infinity;
}
export default findShortestPath;

View File

@@ -1,21 +0,0 @@
async function findShortestPath(graph, start, end) {
const { PriorityQueue } = await import('https://cdn.skypack.dev/js-priority-queue');
const pq = new PriorityQueue({ comparator: (a, b) => a.d - b.d });
const dist = {};
dist[start] = 0;
pq.queue({ node: start, d: 0 });
while (!pq.isEmpty()) {
const { node, d } = pq.dequeue();
if (d > dist[node]) continue;
if (node === end) return d;
for (const [nei, w] of Object.entries(graph[node] || {})) {
const alt = d + w;
if (alt < (dist[nei] ?? Infinity)) {
dist[nei] = alt;
pq.queue({ node: nei, d: alt });
}
}
}
return Infinity;
}
export default findShortestPath;

View File

@@ -0,0 +1,22 @@
async function findShortestPath(graph, start, end) {
const PQ = (await import('https://unpkg.com/js-priority-queue@0.1.5')).default;
const D = {};
D[start] = 0;
const q = new PQ({comparator: (a, b) => a.d - b.d});
q.queue({n: start, d: 0});
while (q.length) {
let {n: u, d} = q.dequeue();
if (d > D[u]) continue;
for (let v in graph[u]) {
let a = d + graph[u][v];
if (a < (D[v] ?? Infinity)) {
D[v] = a;
q.queue({n: v, d: a});
}
}
}
return D[end] ?? Infinity;
}
export default findShortestPath;
// Generation time: 82.003s
// Result: FAIL

View File

@@ -1,4 +1,4 @@
const findConvexHull = async (points) => { async function findConvexHull(points) {
const _ = (await import("https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.min.js")).default; const _ = (await import("https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.min.js")).default;
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x); const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
@@ -22,6 +22,11 @@ const findConvexHull = async (points) => {
upper.push(p); upper.push(p);
} }
return [...lower.slice(0, -1), ...upper.slice(0, -1)]; lower.pop();
}; upper.pop();
return [...lower, ...upper];
}
export default findConvexHull; export default findConvexHull;
// Generation time: 5.506s
// Result: PASS

View File

@@ -1,34 +1,28 @@
async function findConvexHull(points) { const findConvexHull = async (points) => {
const { sortBy, uniqWith } = await import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.js'); const { sortBy, uniqWith, isEqual } = await import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.js');
if (points.length < 3) return points; if (points.length < 3) return points;
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x); const sorted = sortBy(uniqWith(points, isEqual), ['x', 'y']);
const sorted = sortBy(uniqWith(points, (a, b) => a.x === b.x && a.y === b.y), ['x', 'y']);
if (sorted.length < 3) return sorted; if (sorted.length < 3) return sorted;
const lower = []; const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
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 = []; const buildHalf = (pts) => {
for (let i = sorted.length - 1; i >= 0; i--) { const hull = [];
const p = sorted[i]; for (const p of pts) {
while (upper.length >= 2 && cross(upper[upper.length - 2], upper[upper.length - 1], p) <= 0) { while (hull.length >= 2 && cross(hull[hull.length - 2], hull[hull.length - 1], p) <= 0) {
upper.pop(); hull.pop();
} }
upper.push(p); hull.push(p);
} }
hull.pop();
return hull;
};
lower.pop(); return [...buildHalf(sorted), ...buildHalf([...sorted].reverse())];
upper.pop(); };
return lower.concat(upper);
}
export default findConvexHull; export default findConvexHull;
// Generation time: 4.808s
// Result: PASS

View File

@@ -1,29 +0,0 @@
async const findConvexHull = async (points) => {
const { sortBy, uniqWith, isEqual } = await import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.min.js');
const cross = (p1, p2, p3) =>
(p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x);
const sortedPoints = sortBy(uniqWith(points, isEqual), ['x', 'y']);
if (sortedPoints.length <= 3) {
return sortedPoints;
}
const buildHull = (pointSet) => {
const hull = [];
for (const p of pointSet) {
while (hull.length >= 2 && cross(hull[hull.length - 2], hull[hull.length - 1], p) <= 0) {
hull.pop();
}
hull.push(p);
}
return hull;
};
const lower = buildHull(sortedPoints);
const upper = buildHull([...sortedPoints].reverse());
return [...lower.slice(0, -1), ...upper.slice(0, -1)];
};
export default findConvexHull;

View File

@@ -1,20 +1,20 @@
const findConvexHull = async (pts) => { const findConvexHull = async (pts) => {
const { sortBy: S, uniqWith: U, isEqual: E } = await import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/+esm') const { default: _ } = await import('https://cdn.jsdelivr.net/npm/lodash@4.17.21/+esm')
const p = S(U(pts, E), ['x', 'y']) const s = _.sortBy(_.uniqWith(pts, _.isEqual), ['x', 'y'])
if (p.length < 3) return p if (s.length < 3) return s
const X = (a, b, o) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x)
const B = (list) => { const cp = (a, b, c) => (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)
const h = [] const walk = (h, p) => {
for (const pt of list) { while (h.length >= 2 && cp(h[h.length - 2], h[h.length - 1], p) <= 0) h.pop()
while (h.length >= 2 && X(h[h.length - 1], pt, h[h.length - 2]) <= 0) h.pop() h.push(p)
h.push(pt)
}
return h return h
} }
const l = B(p)
const u = B(p.reverse()) const l = s.reduce(walk, [])
l.pop() const u = s.reduceRight(walk, [])
u.pop()
return l.concat(u) return [...l.slice(0, -1), ...u.slice(0, -1)]
} }
export default findConvexHull; export default findConvexHull;
// Generation time: 33.416s
// Result: PASS

View File

@@ -1,18 +1,23 @@
async function findConvexHull(pts) { async function findConvexHull(p) {
if (!Array.isArray(pts)) return []; const { default: _ } = await import('https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js'),
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);
const points = _.sortBy(_.uniqWith(pts, (a, b) => a.x === b.x && a.y === b.y), ['x', 'y']); if (u.length < 3) return u;
if (points.length < 3) return points;
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x); const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x),
const build = (h, p) => { build = (pts) => {
while (h.length >= 2 && cross(h[h.length - 2], h[h.length - 1], p) <= 0) h.pop(); const h = [];
h.push(p); 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 lower = [], upper = [];
for (const p of points) build(lower, p); const l = build(u),
for (let i = points.length; i--; ) build(upper, points[i]); r = build([...u].reverse());
lower.pop();
upper.pop(); return [...l.slice(0, -1), ...r.slice(0, -1)];
return lower.concat(upper);
} }
export default findConvexHull; export default findConvexHull;
// Generation time: 147.393s
// Result: FAIL

View File

@@ -1,19 +1,19 @@
async function findConvexHull(points) { export async function findConvexHull(pts){
const { uniqWith, isEqual, sortBy } = await import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.js') const {default:_}=await import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.js');
const pts = sortBy(uniqWith(points, isEqual), ['x', 'y']) const p=_.orderBy(_.uniqWith(pts,(a,b)=>a.x===b.x&&a.y===b.y),['x','y']);
if (pts.length < 3) return pts if(p.length<3)return p;
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x) const c=(o,a,b)=>(a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x);
const scan = (src, acc = []) => { const l=[],u=[];
src.forEach(p => { for(const v of p){
while (acc.length > 1 && cross(acc.at(-2), acc.at(-1), p) <= 0) acc.pop() while(l.length>1&&c(l[l.length-2],l[l.length-1],v)<=0)l.pop();
acc.push(p) l.push(v);
})
return acc
} }
const lower = scan(pts) for(const v of [...p].reverse()){
const upper = scan([...pts].reverse()) while(u.length>1&&c(u[u.length-2],u[u.length-1],v)<=0)u.pop();
lower.pop() u.push(v);
upper.pop() }
return lower.concat(upper) return l.slice(0,-1).concat(u.slice(0,-1));
} }
export default findConvexHull; export default findConvexHull;
// Generation time: 10.565s
// Result: PASS

View File

@@ -1,38 +0,0 @@
const findConvexHull = async points => {
const { sortBy, uniqWith, isEqual } = await import('https://cdn.skypack.dev/lodash')
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x)
const preparePoints = pts => {
const unique = uniqWith(pts, isEqual)
return sortBy(unique, ['x', 'y'])
}
const buildHull = pts => {
const hull = []
for (const p of pts) {
while (hull.length >= 2 && cross(hull[hull.length - 2], hull[hull.length - 1], p) <= 0) {
hull.pop()
}
hull.push(p)
}
const lowerHullSize = hull.length + 1
for (let i = pts.length - 1; i >= 0; i--) {
const p = pts[i]
while (hull.length >= lowerHullSize && cross(hull[hull.length - 2], hull[hull.length - 1], p) <= 0) {
hull.pop()
}
hull.push(p)
}
hull.pop()
return hull
}
if (points.length < 3) return [...points]
const prepared = preparePoints(points)
return buildHull(prepared)
}
export default findConvexHull;

View File

@@ -1,12 +0,0 @@
async function findConvexHull(pts){
const{ sortBy:s,uniqBy:u }=await import('https://cdn.skypack.dev/lodash');
if(!pts?.length)return[];
const p=u(s(pts,['x','y']),t=>`${t.x},${t.y}`);
if(p.length<2)return p;
const c=(o,a,b)=>(a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x);
let l=[];for(let t of p){while(l.length>1&&c(l[l.length-2],l[l.length-1],t)<=0)l.pop();l.push(t)}
let r=[];for(let i=p.length-1;i>=0;i--){const t=p[i];while(r.length>1&&c(r[r.length-2],r[r.length-1],t)<=0)r.pop();r.push(t)}
l.pop();r.pop();
return[...l,...r];
}
export default findConvexHull;

View File

@@ -1,19 +0,0 @@
async function findConvexHull(pts) {
const { sortBy, uniqBy } = await import('https://cdn.skypack.dev/lodash-es');
const ps = uniqBy(pts, p => `${p.x},${p.y}`);
if (ps.length < 2) return ps;
const sorted = sortBy(ps, ['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 = (pnts) => {
const h = [];
for (let p of pnts) {
while (h.length > 1 && cross(h[h.length - 2], h.at(-1), p) <= 0) h.pop();
h.push(p);
}
return h;
};
const lower = build(sorted);
const upper = build([...sorted].reverse());
return [...lower.slice(0, -1), ...upper.slice(0, -1)];
}
export default findConvexHull;

View File

@@ -0,0 +1,28 @@
async function findConvexHull(points) {
const _ = await import('https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js');
if (points.length <= 1) return points.slice();
let pts = _.sortBy(_.uniqWith(points, (a, b) => a.x === b.x && a.y === b.y), ['x', 'y']);
if (pts.length <= 1) return pts;
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
let lower = [];
for (let p of pts) {
while (lower.length >= 2 && cross(lower[lower.length - 2], lower[lower.length - 1], p) <= 0) {
lower.pop();
}
lower.push(p);
}
let upper = [];
for (let i = pts.length - 1; i >= 0; i--) {
let p = pts[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: 60.720s
// Result: FAIL

View File

@@ -1,11 +1,13 @@
async function findLISLength(a) { async function findLISLength(nums) {
if (!a?.length) return 0; if (!nums?.length) return 0;
const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm'); const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm');
const t = []; const tails = [];
for (const n of a) { for (const n of nums) {
const i = bisectLeft(t, n); const i = bisectLeft(tails, n);
i < t.length ? t[i] = n : t.push(n); i < tails.length ? tails[i] = n : tails.push(n);
} }
return t.length; return tails.length;
} }
export default findLISLength; export default findLISLength;
// Generation time: 3.101s
// Result: PASS

View File

@@ -1,4 +1,4 @@
const findLISLength = async (arr) => { async function findLISLength(arr) {
const { bisectLeft } = await import('https://cdn.skypack.dev/d3-array'); const { bisectLeft } = await import('https://cdn.skypack.dev/d3-array');
if (!arr?.length) return 0; if (!arr?.length) return 0;
@@ -11,5 +11,7 @@ const findLISLength = async (arr) => {
} }
return tails.length; return tails.length;
}; }
export default findLISLength; export default findLISLength;
// Generation time: 2.177s
// Result: PASS

View File

@@ -1,16 +0,0 @@
const findLISLength = async (nums) => {
if (!nums?.length) {
return 0;
}
const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array/+esm');
const tails = [];
nums.forEach((num) => {
tails[bisectLeft(tails, num)] = num;
});
return tails.length;
};
export default findLISLength;

View File

@@ -1,9 +1,13 @@
const findLISLength = async (nums) => { const findLISLength = async nums => {
const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm'); const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array/+esm')
const tails = []; const tails = []
for (const n of nums) { for (const n of nums) {
tails[bisectLeft(tails, n)] = n; tails[bisectLeft(tails, n)] = n
} }
return tails.length;
}; return tails.length
}
export default findLISLength; export default findLISLength;
// Generation time: 25.399s
// Result: PASS

View File

@@ -1,14 +1,10 @@
export async function findLISLength(nums) { export async function findLISLength(a){
if (!Array.isArray(nums) || nums.length === 0) return 0; const{bisectLeft}=await import('https://esm.sh/d3-array');
if(!Array.isArray(a))return 0;
const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm'); const t=[];
const tails = []; for(const v of a){const i=bisectLeft(t,v);i===t.length?t.push(v):t[i]=v;}
return t.length;
for (const num of nums) {
const idx = bisectLeft(tails, num);
idx === tails.length ? tails.push(num) : tails[idx] = num;
}
return tails.length;
} }
export default findLISLength; export default findLISLength;
// Generation time: 39.477s
// Result: PASS

View File

@@ -1,10 +1,12 @@
async function findLISLength(a) { async function findLISLength(a){
const {bisectLeft} = await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm') const{bisectLeft}=await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm')
const t=[] const t=[]
for (const x of a||[]) { for(const x of a){
const i = bisectLeft(t,x) const i=bisectLeft(t,x)
t[i]=x t[i]=x
} }
return t.length return t.length
} }
export default findLISLength; export default findLISLength;
// Generation time: 6.704s
// Result: PASS

View File

@@ -1,14 +0,0 @@
const findLISLength = async (nums) => {
if (!nums.length) return 0
const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm')
const tails = []
for (const num of nums) {
const i = bisectLeft(tails, num)
tails[i] = num
}
return tails.length
}
export default findLISLength;

View File

@@ -1,2 +0,0 @@
async function findLISLength(a){const{bisectLeft}=await import('https://cdn.skypack.dev/d3-array');let t=[];for(let n of a){let i=bisectLeft(t,n);i===t.length?t.push(n):t[i]=n}return t.length}
export default findLISLength;

View File

@@ -1,11 +0,0 @@
async function findLISLength(arr) {
const {bisectLeft} = await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm');
let tails = [];
for (let num of arr) {
let i = bisectLeft(tails, num);
if (i === tails.length) tails.push(num);
else tails[i] = num;
}
return tails.length;
}
export default findLISLength;

View File

@@ -0,0 +1,16 @@
async function findLISLength(arr) {
const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array@3');
let tails = [];
for (let num of arr) {
let pos = bisectLeft(tails, num);
if (pos === tails.length) {
tails.push(num);
} else {
tails[pos] = num;
}
}
return tails.length;
}
export default findLISLength;
// Generation time: 47.415s
// Result: FAIL

View File

@@ -3,3 +3,5 @@ async function renderTemplate(template, data) {
return Handlebars.compile(template)(data); return Handlebars.compile(template)(data);
} }
export default renderTemplate; export default renderTemplate;
// Generation time: 2.930s
// Result: PASS

View File

@@ -1,9 +1,7 @@
async function renderTemplate(templateString, data) { async function renderTemplate(template, data) {
const { default: Handlebars } = await import( const { default: Handlebars } = await import('https://cdn.jsdelivr.net/npm/handlebars@4.7.8/dist/handlebars.min.js');
'https://cdn.jsdelivr.net/npm/handlebars@4.7.8/dist/handlebars.min.js' return Handlebars.compile(template)(data);
);
const template = Handlebars.compile(templateString);
return template(data);
} }
export default renderTemplate; export default renderTemplate;
// Generation time: 2.224s
// Result: FAIL

View File

@@ -1,5 +0,0 @@
const renderTemplate = async (templateString, data) => {
const { default: Handlebars } = await import('https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.min.js');
return Handlebars.compile(templateString)(data);
};
export default renderTemplate;

View File

@@ -1,5 +1,6 @@
const renderTemplate = async (tmpl, data) => { const renderTemplate = async (t, d) =>
const { default: H } = await import('https://cdn.jsdelivr.net/npm/handlebars@latest/+esm') (await import('https://esm.sh/handlebars'))
return H.compile(tmpl)(data) .default.compile(t)(d)
}
export default renderTemplate; export default renderTemplate;
// Generation time: 29.656s
// Result: PASS

View File

@@ -1,7 +1,12 @@
let h, c = new Map(); let hb;
const renderTemplate = async (t, d) => { export const renderTemplate=async(t,d)=>{
h ||= (await import('https://cdn.jsdelivr.net/npm/handlebars@4.7.8/dist/handlebars.min.js')).default; try{
c.has(t) || c.set(t, h.compile(t)); hb??=(await import('https://cdn.jsdelivr.net/npm/handlebars@4.7.8/dist/handlebars.mjs')).default;
return c.get(t)(d); return hb.compile(t)(d);
}catch(e){
throw new Error(`Render failed: ${e.message}`);
}
}; };
export default renderTemplate; export default renderTemplate;
// Generation time: 50.722s
// Result: FAIL

View File

@@ -1,5 +1,7 @@
async function renderTemplate(t,d){ async function renderTemplate(tpl, data) {
const {default:h}=await import('https://cdn.jsdelivr.net/npm/handlebars@latest/+esm') const { default: h } = await import('https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.esm.js')
return h.compile(t)(d) return h.compile(tpl)(data)
} }
export default renderTemplate; export default renderTemplate;
// Generation time: 2.868s
// Result: FAIL

View File

@@ -1,6 +0,0 @@
const renderTemplate = async (template, data) => {
const { default: Handlebars } = await import('https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.min.js')
const compiled = Handlebars.compile(template)
return compiled(data)
}
export default renderTemplate;

View File

@@ -1,8 +0,0 @@
const getHandlebars=(async()=>(await import('https://esm.sh/handlebars@4.7.8')).default)();
async function renderTemplate(template,data){
const Handlebars=await getHandlebars;
const fn=Handlebars.compile(template);
return fn(data);
}
export default renderTemplate;

View File

@@ -0,0 +1,8 @@
async function renderTemplate(template, data) {
const { default: Handlebars } = await import('https://esm.sh/handlebars');
const compiled = Handlebars.compile(template);
return compiled(data);
}
export default renderTemplate;
// Generation time: 22.419s
// Result: PASS

View File

@@ -1,5 +1,7 @@
async function parseMarkdown(t) { async function parseMarkdown(md) {
const { marked } = await import("https://esm.sh/marked@12.0.0"); const { marked } = await import('https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js');
return marked.parse(t); return marked.parse(md);
} }
export default parseMarkdown; export default parseMarkdown;
// Generation time: 2.905s
// Result: PASS

View File

@@ -3,3 +3,5 @@ async function parseMarkdown(md) {
return marked.parse(md); return marked.parse(md);
} }
export default parseMarkdown; export default parseMarkdown;
// Generation time: 1.766s
// Result: PASS

View File

@@ -1,24 +0,0 @@
const parseMarkdown = async (md) => {
try {
const [
{ marked },
{ default: DOMPurify }
] = await Promise.all([
import('https://cdn.jsdelivr.net/npm/marked@13.0.0/lib/marked.esm.js'),
import('https://cdn.jsdelivr.net/npm/dompurify@3.1.5/dist/purify.es.mjs')
]);
const rawHtml = marked.parse(md || '', {
gfm: true,
breaks: true,
});
return DOMPurify.sanitize(rawHtml);
} catch (err) {
console.error('Failed to parse markdown:', err);
const el = document.createElement('div');
el.textContent = md || '';
return el.innerHTML;
}
};
export default parseMarkdown;

View File

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

View File

@@ -1,15 +1,13 @@
async function parseMarkdown(md) { let p;
if (!md?.trim()) return '';
try { export const parseMarkdown = async (s) => {
const [{ marked }, { default: DOMPurify }] = await Promise.all([ p ||= Promise.all([
import('https://esm.sh/marked@9'), import('https://esm.sh/marked@7.0.4').then(r => r.marked),
import('https://esm.sh/dompurify@3') import('https://esm.sh/dompurify@3.0.5').then(r => r.default)
]); ]);
marked.setOptions({ gfm: true, breaks: true }); const [m, d] = await p;
return DOMPurify.sanitize(marked.parse(md)); return d.sanitize(m.parse(s));
} catch (e) { };
console.error('Markdown parse error:', e);
return '';
}
}
export default parseMarkdown; export default parseMarkdown;
// Generation time: 550.549s
// Result: PASS

View File

@@ -1,12 +1,17 @@
const parseMarkdown=(()=>{ const loadLibs=(()=>{let cache;return async()=>cache||(cache=Promise.all([
let m,r import('https://cdn.jsdelivr.net/npm/marked@11.1.0/lib/marked.esm.js'),
return async t=>{ import('https://cdn.jsdelivr.net/npm/dompurify@3.0.6/dist/purify.es.mjs')
if(!r){ ]).then(([{marked},purifyMod])=>{
({marked:m}=await import('https://cdn.jsdelivr.net/npm/marked@11.1.1/+esm')) const purify=(purifyMod.default||purifyMod)(window);
m.setOptions({gfm:1,mangle:0,headerIds:0}) marked.setOptions({gfm:true,headerIds:true,mangle:false});
r=1 return {marked,purify};
} }));})();
return m.parse(t)
} 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; export default parseMarkdown;
// Generation time: 15.618s
// Result: FAIL

View File

@@ -1,15 +0,0 @@
const parseMarkdown = async (markdown) => {
const { default: marked } = await import('https://cdn.jsdelivr.net/npm/marked@4.0.12/lib/marked.esm.js')
const { default: DOMPurify } = await import('https://cdn.jsdelivr.net/npm/dompurify@3.0.5/dist/purify.es.mjs')
marked.setOptions({
gfm: true,
breaks: true,
headerIds: false,
mangle: false
})
const html = marked.parse(markdown)
return DOMPurify.sanitize(html)
}
export default parseMarkdown;

View File

@@ -1,6 +0,0 @@
async function parseMarkdown(md){
const{marked}=await import('https://esm.sh/marked');
const{DOMPurify}=await import('https://esm.sh/dompurify');
return DOMPurify.sanitize(marked.parse(md));
}
export default parseMarkdown;

View File

@@ -1,5 +0,0 @@
async function parseMarkdown(md) {
const { marked } = await import('https://cdn.skypack.dev/marked');
return marked.parse(md);
}
export default parseMarkdown;

View File

@@ -0,0 +1,7 @@
async function parseMarkdown(markdown) {
const { marked } = await import('https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js');
return marked(markdown);
}
export default parseMarkdown;
// Generation time: 16.386s
// Result: PASS

View File

@@ -1,32 +1,24 @@
async function processCSV(csv, config) { async function processCSV(csv, config) {
const { parse } = await import('https://cdn.jsdelivr.net/npm/papaparse@5/+esm');
const { filterColumn, filterValue, groupBy, aggregateColumn, operation } = config; const { filterColumn, filterValue, groupBy, aggregateColumn, operation } = config;
const { default: Papa } = await import('https://cdn.jsdelivr.net/npm/papaparse@5/+esm'); const { data } = parse(csv, { header: true, skipEmptyLines: true });
const { data } = Papa.parse(csv, { header: true, skipEmptyLines: true });
const filtered = data.filter(row => row[filterColumn] == filterValue); const filtered = data.filter(row => row[filterColumn] == filterValue);
const groups = {}; const groups = {};
for (const row of filtered) { for (const row of filtered) {
const key = row[groupBy]; const key = row[groupBy];
(groups[key] ??= []).push(row); (groups[key] ??= []).push(+row[aggregateColumn] || 0);
} }
const toNum = v => { return Object.entries(groups).map(([key, vals]) => ({
const n = Number(v); [groupBy]: key,
return isNaN(n) ? 0 : n; result: operation === 'count' ? vals.length :
}; operation === 'sum' ? vals.reduce((a, b) => a + b, 0) :
vals.reduce((a, b) => a + b, 0) / vals.length
const ops = {
sum: rows => rows.reduce((s, r) => s + toNum(r[aggregateColumn]), 0),
avg: rows => rows.length ? ops.sum(rows) / rows.length : 0,
count: rows => rows.length
};
return Object.entries(groups).map(([k, v]) => ({
[groupBy]: k,
result: ops[operation](v)
})); }));
} }
export default processCSV; export default processCSV;
// Generation time: 4.406s
// Result: FAIL

View File

@@ -1,27 +1,28 @@
const processCSV = async (csv, { filterColumn, filterValue, groupBy, aggregateColumn, operation }) => { async function processCSV(csv, config) {
const [{ default: Papa }] = await Promise.all([ const { parse } = await import('https://cdn.jsdelivr.net/npm/papaparse@5.4.1/+esm');
import('https://cdn.jsdelivr.net/npm/papaparse@5.4.1/+esm')
]);
const { data } = Papa.parse(csv, { header: true, skipEmptyLines: true }); const { data } = parse(csv, { header: true, skipEmptyLines: true });
const filtered = data.filter(row => row[filterColumn] == filterValue); const filtered = data.filter(row => row[config.filterColumn] == config.filterValue);
const groups = filtered.reduce((acc, row) => { const groups = filtered.reduce((acc, row) => {
const key = row[groupBy]; const key = row[config.groupBy];
if (!acc[key]) acc[key] = []; (acc[key] ??= []).push(row);
acc[key].push(row);
return acc; return acc;
}, {}); }, {});
return Object.entries(groups).map(([key, rows]) => { return Object.entries(groups).map(([key, rows]) => {
const values = rows.map(r => Number(r[aggregateColumn]) || 0); const values = rows.map(r => Number(r[config.aggregateColumn]) || 0);
const sum = values.reduce((a, b) => a + b, 0); const sum = values.reduce((a, b) => a + b, 0);
return { return {
[groupBy]: key, [config.groupBy]: key,
result: operation === 'sum' ? sum : operation === 'avg' ? sum / values.length : values.length result: config.operation === 'sum' ? sum :
config.operation === 'avg' ? sum / values.length :
values.length
}; };
}); });
}; }
export default processCSV; export default processCSV;
// Generation time: 4.238s
// Result: FAIL

View File

@@ -1,34 +0,0 @@
async function processCSV(csvString, config) {
const {
filterColumn: fc,
filterValue: fv,
groupBy: gb,
aggregateColumn: ac,
operation: op
} = config;
const { default: Papa } = await import('https://cdn.jsdelivr.net/npm/papaparse@5.3.2/papaparse.min.js');
const { data } = Papa.parse(csvString, {
header: true,
skipEmptyLines: true
});
const groups = data.reduce((acc, row) => {
if (row[fc] == fv) {
const key = row[gb];
const val = Number(row[ac]) || 0;
acc[key] = acc[key] || { sum: 0, count: 0 };
acc[key].sum += val;
acc[key].count++;
}
return acc;
}, {});
return Object.entries(groups).map(([key, { sum, count }]) => ({
[gb]: key,
result: op === 'avg' ? sum / count : op === 'sum' ? sum : count,
}));
}
export default processCSV;

View File

@@ -1,19 +1,16 @@
export const processCSV = async (csvString, { filterColumn, filterValue, groupBy, aggregateColumn, operation }) => { const processCSV = async (str, { filterColumn: fc, filterValue: fv, groupBy: gb, aggregateColumn: ac, operation: op }) => {
const [{ csvParse }, { rollup, sum, mean }] = await Promise.all([ const { csvParse, rollups, sum } = await import('https://esm.sh/d3@7');
import('https://esm.sh/d3-dsv'), const num = v => +v || 0;
import('https://esm.sh/d3-array') return rollups(
]); csvParse(str).filter(d => d[fc] == fv),
g => {
const getValue = d => +(d[aggregateColumn]) || 0; if (op === 'count') return g.length;
const t = sum(g, d => num(d[ac]));
const grouped = rollup( return op === 'sum' ? t : t / g.length;
csvParse(csvString).filter(row => row[filterColumn] == filterValue), },
group => operation === 'count' d => d[gb]
? group.length ).map(([k, v]) => ({ [gb]: k, result: v }));
: (operation === 'sum' ? sum : mean)(group, getValue),
row => row[groupBy]
);
return Array.from(grouped, ([key, result]) => ({ [groupBy]: key, result }));
}; };
export default processCSV; export default processCSV;
// Generation time: 40.784s
// Result: PASS

View File

@@ -1,2 +1,17 @@
async function processCSV(csv,{filterColumn:f,filterValue:v,groupBy:g,aggregateColumn:a,operation:o}){const{default:P}=await import('https://cdn.jsdelivr.net/npm/papaparse@5.4.1/+esm');const{data}=P.parse(csv,{header:true});const grouped=data.filter(r=>r[f]==v).reduce((c,r)=>{const k=r[g],n=Number(r[a])||0;c[k]||=(c[k]={s:0,c:0});c[k].s+=n;c[k].c++;return c},{});return Object.entries(grouped).map(([k,{s,c}])=>({[g]:k,result:o=='sum'?s:o=='avg'?s/c:c}))} 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; export default processCSV;
// Generation time: 66.769s
// Result: PASS

View File

@@ -1,21 +1,16 @@
const libCache={},load=u=>libCache[u]??=import(u); 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,cfg){ async function processCSV(csv,opt){
const [{csvParse},{groupBy}]=await Promise.all([ const [{Papa},{groupBy:gb}] = await Promise.all([load(csvLib),load(dataLib)]);
load('https://cdn.jsdelivr.net/npm/d3-dsv@3.0.1/+esm'), const {filterColumn:f,filterValue:v,groupBy:g,aggregateColumn:a,operation:o}=opt;
load('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/+esm') const rows=Papa.parse(csv,{header:true,skipEmptyLines:true}).data.filter(r=>r&&r[f]==v);
]); const grouped=gb(rows,r=>r[g]);
const {filterColumn:f,filterValue:v,groupBy:k,aggregateColumn:a,operation:o}=cfg; return Object.entries(grouped).map(([k,items])=>{
const rows=csvParse(csv).filter(r=>r[f]==v); const total=items.reduce((s,r)=>s+toNum(r[a]),0);
const grouped=groupBy(rows,r=>r[k]); const result=o==='count'?items.length:o==='sum'?total:items.length?total/items.length:0;
return Object.entries(grouped).map(([g,list])=>{ return {[g]:k,result};
const nums=list.map(r=>{
const n=+r[a];
return Number.isFinite(n)?n:0;
});
const sum=nums.reduce((s,n)=>s+n,0);
const result=o==='count'?list.length:o==='sum'?sum:list.length?sum/list.length:0;
return {[k]:g,result};
}); });
} }
export default processCSV; export default processCSV;
// Generation time: 29.916s
// Result: FAIL

View File

@@ -1,25 +0,0 @@
const processCSV = async (csvData, config) => {
const { parse } = await import('https://cdn.skypack.dev/papaparse@5.3.0')
const { filterColumn, filterValue, groupBy, aggregateColumn, operation } = config
const { data } = parse(csvData, { header: true })
const filtered = data.filter(row => row[filterColumn] == filterValue)
const groups = filtered.reduce((acc, row) => {
const key = row[groupBy]
if (!acc[key]) acc[key] = []
acc[key].push(row)
return acc
}, {})
return Object.entries(groups).map(([groupValue, rows]) => {
const numbers = rows.map(row => +row[aggregateColumn] || 0)
let result
if (operation === 'sum') result = numbers.reduce((a, b) => a + b, 0)
if (operation === 'avg') result = numbers.reduce((a, b) => a + b, 0) / numbers.length
if (operation === 'count') result = numbers.length
return { [groupBy]: groupValue, result }
})
}
export default processCSV;

View File

@@ -1,17 +0,0 @@
async function processCSV(csv,config){
const Papa=(await import('https://cdn.skypack.dev/papaparse')).default;
const parsed=Papa.parse(csv,{header:!0}).data;
const{filterColumn:fc,filterValue:fv,groupBy:gb,aggregateColumn:ac,operation:op}=config;
const filtered=parsed.filter(r=>r[fc]==fv);
const groups=new Map;
for(const r of filtered){
const gv=r[gb];
const v=Number(r[ac])||0;
const g=groups.get(gv)||{sum:0,count:0};
g.sum+=v;
g.count++;
groups.set(gv,g);
}
return Array.from(groups,(g,gv)=>(({[gb]:gv,result:op==='sum'?g.sum:op==='count'?g.count:g.sum/g.count})));
}
export default processCSV;

View File

@@ -1,15 +0,0 @@
async function processCSV(csv, config) {
const [{ default: Papa }, { aq, sum, mean, count }] = await Promise.all([
import('https://cdn.skypack.dev/papaparse'),
import('https://cdn.skypack.dev/arquero')
]);
const data = Papa.parse(csv, { header: true, skipEmptyLines: true }).data;
const { filterColumn, filterValue, groupBy, aggregateColumn, operation } = config;
let table = aq.from(data).filter(d => d[filterColumn] == filterValue);
if (operation !== 'count') {
table = table.derive({ [aggregateColumn]: d => Number(d[aggregateColumn]) || 0 });
}
const makeAgg = operation === 'count' ? count() : { sum: sum, avg: mean }[operation](aggregateColumn);
return table.groupby(groupBy).rollup({ result: makeAgg }).objects();
}
export default processCSV;

View File

@@ -0,0 +1,20 @@
async function processCSV(csvString, config) {
const d3 = await import('https://unpkg.com/d3?module');
const data = d3.csvParse(csvString);
const filtered = data.filter(row => row[config.filterColumn] == config.filterValue);
const grouped = d3.group(filtered, d => d[config.groupBy]);
return [...grouped].map(([key, group]) => {
const col = config.aggregateColumn;
const vals = group.map(r => Number(r[col]) || 0);
let result;
switch (config.operation) {
case 'sum': result = vals.reduce((a, b) => a + b, 0); break;
case 'avg': result = vals.reduce((a, b) => a + b, 0) / vals.length; break;
case 'count': result = group.length; break;
}
return { [config.groupBy]: key, result };
});
}
export default processCSV;
// Generation time: 34.010s
// Result: PASS

View File

@@ -7,71 +7,70 @@ async function findAvailableSlots(calendar1, calendar2, constraints) {
const [whStartH, whStartM] = workHours.start.split(':').map(Number); const [whStartH, whStartM] = workHours.start.split(':').map(Number);
const [whEndH, whEndM] = workHours.end.split(':').map(Number); const [whEndH, whEndM] = workHours.end.split(':').map(Number);
const busyIntervals = [...calendar1, ...calendar2] const allBusy = [...calendar1, ...calendar2]
.map(b => Interval.fromDateTimes( .map(b => ({
DateTime.fromISO(b.start, { zone: 'utc' }), start: DateTime.fromISO(b.start, { zone: 'utc' }),
DateTime.fromISO(b.end, { zone: 'utc' }) end: DateTime.fromISO(b.end, { zone: 'utc' })
)) }))
.filter(i => i.isValid) .filter(b => b.end > rangeStart && b.start < rangeEnd)
.sort((a, b) => a.start - b.start); .sort((a, b) => a.start - b.start);
const merged = []; const merged = [];
for (const interval of busyIntervals) { for (const b of allBusy) {
if (!merged.length || merged[merged.length - 1].end < interval.start) { if (!merged.length || b.start > merged[merged.length - 1].end) {
merged.push(interval); merged.push({ start: b.start, end: b.end });
} else { } else {
const last = merged.pop(); merged[merged.length - 1].end = DateTime.max(merged[merged.length - 1].end, b.end);
merged.push(Interval.fromDateTimes(
last.start,
last.end > interval.end ? last.end : interval.end
));
} }
} }
const freeIntervals = []; const free = [];
let cursor = rangeStart; let cursor = rangeStart;
for (const busy of merged) { for (const b of merged) {
if (busy.start > cursor && busy.start <= rangeEnd) { if (b.start > cursor) {
freeIntervals.push(Interval.fromDateTimes(cursor, busy.start < rangeEnd ? busy.start : rangeEnd)); free.push({ start: cursor, end: b.start });
} }
cursor = busy.end > cursor ? busy.end : cursor; cursor = DateTime.max(cursor, b.end);
} }
if (cursor < rangeEnd) { if (cursor < rangeEnd) {
freeIntervals.push(Interval.fromDateTimes(cursor, rangeEnd)); free.push({ start: cursor, end: rangeEnd });
} }
const getWorkInterval = day => { const getWorkWindow = (day) => {
const start = day.set({ hour: whStartH, minute: whStartM, second: 0, millisecond: 0 }); const ws = day.set({ hour: whStartH, minute: whStartM, second: 0, millisecond: 0 });
const end = day.set({ hour: whEndH, minute: whEndM, second: 0, millisecond: 0 }); const we = day.set({ hour: whEndH, minute: whEndM, second: 0, millisecond: 0 });
return start < end ? Interval.fromDateTimes(start, end) : null; return { start: ws, end: we };
}; };
const slots = []; const slots = [];
for (const free of freeIntervals) { for (const f of free) {
let day = free.start.startOf('day'); let day = f.start.startOf('day');
const endDay = free.end.startOf('day'); const lastDay = f.end.startOf('day');
while (day <= endDay) { while (day <= lastDay) {
const workInt = getWorkInterval(day); const ww = getWorkWindow(day);
if (workInt) { const effStart = DateTime.max(f.start, ww.start, rangeStart);
const intersection = free.intersection(workInt); const effEnd = DateTime.min(f.end, ww.end, rangeEnd);
if (intersection && intersection.length('minutes') >= durationMinutes) {
let slotStart = intersection.start; if (effStart < effEnd) {
while (slotStart.plus({ minutes: durationMinutes }) <= intersection.end) { let slotStart = effStart;
while (true) {
const slotEnd = slotStart.plus({ minutes: durationMinutes }); const slotEnd = slotStart.plus({ minutes: durationMinutes });
if (slotEnd > effEnd) break;
slots.push({ slots.push({
start: slotStart.toISO({ suppressMilliseconds: true }), start: slotStart.toISO(),
end: slotEnd.toISO({ suppressMilliseconds: true }) end: slotEnd.toISO()
}); });
slotStart = slotEnd; slotStart = slotEnd;
} }
} }
}
day = day.plus({ days: 1 }); day = day.plus({ days: 1 });
} }
} }
return slots.sort((a, b) => a.start.localeCompare(b.start)); return slots;
} }
export default findAvailableSlots; export default findAvailableSlots;
// Generation time: 12.726s
// Result: PASS

View File

@@ -1,69 +1,103 @@
const findAvailableSlots = async (calendar1, calendar2, constraints) => { const findAvailableSlots = async (calendar1, calendar2, constraints) => {
const { startOfDay, addMinutes, parseISO, formatISO } = await import('https://cdn.jsdelivr.net/npm/date-fns@3.0.0/+esm'); const { parseISO, addMinutes, isWithinInterval, isBefore, isAfter, isEqual } = await import('https://cdn.jsdelivr.net/npm/date-fns@3.0.0/+esm');
const { durationMinutes, searchRange, workHours } = constraints; const { durationMinutes, searchRange, workHours } = constraints;
const searchStart = parseISO(searchRange.start); const searchStart = parseISO(searchRange.start);
const searchEnd = parseISO(searchRange.end); const searchEnd = parseISO(searchRange.end);
const [workStartHour, workStartMin] = workHours.start.split(':').map(Number); const parseTime = (timeStr) => {
const [workEndHour, workEndMin] = workHours.end.split(':').map(Number); const [h, m] = timeStr.split(':').map(Number);
const workStartMs = (workStartHour * 60 + workStartMin) * 60000; return h * 60 + m;
const workEndMs = (workEndHour * 60 + workEndMin) * 60000; };
const workStartMinutes = parseTime(workHours.start);
const workEndMinutes = parseTime(workHours.end);
const getUTCMinutes = (date) => date.getUTCHours() * 60 + date.getUTCMinutes();
const isInWorkHours = (date) => {
const minutes = getUTCMinutes(date);
return minutes >= workStartMinutes && minutes < workEndMinutes;
};
const setUTCTime = (date, minutes) => {
const d = new Date(date);
d.setUTCHours(Math.floor(minutes / 60), minutes % 60, 0, 0);
return d;
};
const allBusy = [...calendar1, ...calendar2] const allBusy = [...calendar1, ...calendar2]
.map(({ start, end }) => ({ start: parseISO(start), end: parseISO(end) })) .map(slot => ({ start: parseISO(slot.start), end: parseISO(slot.end) }))
.sort((a, b) => a.start - b.start); .sort((a, b) => a.start - b.start);
const merged = []; const merged = [];
for (const slot of allBusy) { for (const slot of allBusy) {
if (merged.length && slot.start <= merged[merged.length - 1].end) { if (merged.length === 0) {
merged[merged.length - 1].end = new Date(Math.max(merged[merged.length - 1].end, slot.end)); merged.push({ ...slot });
} else { } else {
merged.push({ start: slot.start, end: slot.end }); const last = merged[merged.length - 1];
if (isBefore(slot.start, last.end) || isEqual(slot.start, last.end)) {
last.end = isAfter(slot.end, last.end) ? slot.end : last.end;
} else {
merged.push({ ...slot });
}
} }
} }
const free = []; const freePeriods = [];
let current = searchStart; let currentStart = searchStart;
for (const busy of merged) { for (const busy of merged) {
if (current < busy.start) { if (isBefore(currentStart, busy.start)) {
free.push({ start: current, end: busy.start }); freePeriods.push({ start: currentStart, end: busy.start });
} }
current = new Date(Math.max(current, busy.end)); currentStart = isAfter(busy.end, currentStart) ? busy.end : currentStart;
} }
if (current < searchEnd) {
free.push({ start: current, end: searchEnd }); if (isBefore(currentStart, searchEnd)) {
freePeriods.push({ start: currentStart, end: searchEnd });
} }
const slots = []; const slots = [];
for (const period of free) {
let slotStart = period.start;
while (slotStart < period.end) { for (const period of freePeriods) {
const dayStart = startOfDay(slotStart); let current = new Date(period.start);
const slotStartMs = slotStart - dayStart; const periodEnd = period.end;
const slotEnd = addMinutes(slotStart, durationMinutes);
const slotEndMs = slotEnd - dayStart;
if (slotEnd > period.end) break; while (isBefore(current, periodEnd)) {
const currentDay = new Date(Date.UTC(current.getUTCFullYear(), current.getUTCMonth(), current.getUTCDate()));
const workStart = setUTCTime(currentDay, workStartMinutes);
const workEnd = setUTCTime(currentDay, workEndMinutes);
const endsNextDay = slotEnd - startOfDay(slotEnd) < slotEndMs % 86400000; let slotStart = isAfter(current, workStart) ? current : workStart;
if (!endsNextDay && if (!isBefore(slotStart, workEnd) || !isBefore(slotStart, periodEnd)) {
slotStartMs >= workStartMs && const nextDay = new Date(currentDay);
slotEndMs <= workEndMs && nextDay.setUTCDate(nextDay.getUTCDate() + 1);
slotStart >= searchStart && current = nextDay;
slotEnd <= searchEnd) { continue;
slots.push({
start: formatISO(slotStart),
end: formatISO(slotEnd)
});
} }
slotStart = slotEnd; const slotEnd = addMinutes(slotStart, durationMinutes);
if ((isInWorkHours(slotStart) && isInWorkHours(new Date(slotEnd.getTime() - 1))) &&
(isBefore(slotEnd, periodEnd) || isEqual(slotEnd, periodEnd)) &&
(isBefore(slotEnd, workEnd) || isEqual(slotEnd, workEnd))) {
slots.push({
start: slotStart.toISOString(),
end: slotEnd.toISOString()
});
current = slotEnd;
} else {
const nextDay = new Date(currentDay);
nextDay.setUTCDate(nextDay.getUTCDate() + 1);
current = nextDay;
}
} }
} }
return slots; return slots;
}; };
export default findAvailableSlots; export default findAvailableSlots;
// Generation time: 14.710s
// Result: PASS

View File

@@ -1,74 +0,0 @@
async function findAvailableSlots(calendar1, calendar2, constraints) {
const {
parseISO, addMinutes, addDays, max, isBefore, isAfter, startOfDay,
} = await import('https://cdn.jsdelivr.net/npm/date-fns@3.6.0/esm/index.js');
const { durationMinutes, searchRange, workHours } = constraints;
const searchStart = parseISO(searchRange.start);
const searchEnd = parseISO(searchRange.end);
const [workStartH, workStartM] = workHours.start.split(':').map(Number);
const [workEndH, workEndM] = workHours.end.split(':').map(Number);
const busySlots = [...calendar1, ...calendar2]
.map(slot => ({ start: parseISO(slot.start), end: parseISO(slot.end) }))
.sort((a, b) => a.start - b.start);
const mergedBusy = busySlots.reduce((acc, current) => {
const last = acc.at(-1);
if (last && isBefore(current.start, last.end)) {
last.end = max([last.end, current.end]);
} else {
acc.push({ ...current });
}
return acc;
}, []);
const freeIntervals = [];
let cursor = searchStart;
mergedBusy.forEach(busy => {
if (isBefore(cursor, busy.start)) {
freeIntervals.push({ start: cursor, end: busy.start });
}
cursor = max([cursor, busy.end]);
});
if (isBefore(cursor, searchEnd)) {
freeIntervals.push({ start: cursor, end: searchEnd });
}
const availableSlots = freeIntervals.flatMap(gap => {
const slotsInGap = [];
let slotCursor = gap.start;
while (isBefore(slotCursor, gap.end)) {
const day = startOfDay(slotCursor);
const workDayStart = new Date(day);
workDayStart.setUTCHours(workStartH, workStartM, 0, 0);
const workDayEnd = new Date(day);
workDayEnd.setUTCHours(workEndH, workEndM, 0, 0);
const slotStart = max([slotCursor, workDayStart]);
const slotEnd = addMinutes(slotStart, durationMinutes);
const canFit = !isAfter(slotEnd, workDayEnd) && !isAfter(slotEnd, gap.end);
if (canFit) {
slotsInGap.push({ start: slotStart, end: slotEnd });
slotCursor = slotEnd;
} else {
const nextDayStart = addDays(day, 1);
nextDayStart.setUTCHours(workStartH, workStartM, 0, 0);
slotCursor = nextDayStart;
}
}
return slotsInGap;
});
return availableSlots.map(slot => ({
start: slot.start.toISOString(),
end: slot.end.toISOString(),
}));
}
export default findAvailableSlots;

View File

@@ -1,52 +1,65 @@
const findAvailableSlots = async (cal1, cal2, { durationMinutes: dur, searchRange: range, workHours: work }) => { const findAvailableSlots = async (calA, calB, { durationMinutes, searchRange, workHours }) => {
const { parseISO } = await import('https://cdn.jsdelivr.net/npm/date-fns@3.6.0/+esm'); const { addMinutes, parseISO, formatISO } = await import('https://esm.sh/date-fns@2.30.0');
const toMs = (d) => parseISO(d).getTime(); const getMins = (t) => { const [h, m] = t.split(':'); return (+h * 60) + +m; };
const [wsH, wsM] = work.start.split(':').map(Number); const [workStart, workEnd] = [workHours.start, workHours.end].map(getMins);
const [weH, weM] = work.end.split(':').map(Number); const rangeEnd = parseISO(searchRange.end).getTime();
const rangeStart = toMs(range.start);
const rangeEnd = toMs(range.end);
const durMs = dur * 60000;
const busy = [...cal1, ...cal2] const busy = [...calA, ...calB]
.map(x => ({ s: toMs(x.start), e: toMs(x.end) })) .map(s => ({ s: parseISO(s.start).getTime(), e: parseISO(s.end).getTime() }))
.sort((a, b) => a.s - b.s); .sort((a, b) => a.s - b.s)
.reduce((acc, c) => {
const merged = []; const last = acc[acc.length - 1];
for (const b of busy) { if (last && c.s <= last.e) last.e = Math.max(last.e, c.e);
const last = merged[merged.length - 1]; else acc.push(c);
if (last && b.s < last.e) last.e = Math.max(last.e, b.e); return acc;
else merged.push(b); }, []);
}
let current = parseISO(searchRange.start).getTime();
const slots = []; const slots = [];
let currDate = parseISO(range.start);
currDate.setUTCHours(0, 0, 0, 0);
while (currDate.getTime() < rangeEnd) { while (current + durationMinutes * 60000 <= rangeEnd) {
const wStart = new Date(currDate).setUTCHours(wsH, wsM, 0, 0); const d = new Date(current);
const wEnd = new Date(currDate).setUTCHours(weH, weM, 0, 0); const curMins = d.getUTCHours() * 60 + d.getUTCMinutes();
let t = Math.max(wStart, rangeStart); if (curMins >= workEnd) {
const limit = Math.min(wEnd, rangeEnd); d.setUTCDate(d.getUTCDate() + 1);
d.setUTCHours(0, 0, 0, 0);
current = addMinutes(d, workStart).getTime();
continue;
}
while (t + durMs <= limit) { if (curMins < workStart) {
const tEnd = t + durMs; d.setUTCHours(0, 0, 0, 0);
const clash = merged.find(b => t < b.e && tEnd > b.s); current = addMinutes(d, workStart).getTime();
continue;
}
if (clash) { const end = addMinutes(current, durationMinutes).getTime();
t = clash.e; const endD = new Date(end);
const endMins = endD.getUTCHours() * 60 + endD.getUTCMinutes();
if (end > rangeEnd) break;
if (endD.getUTCDate() !== d.getUTCDate() || endMins > workEnd) {
d.setUTCDate(d.getUTCDate() + 1);
d.setUTCHours(0, 0, 0, 0);
current = addMinutes(d, workStart).getTime();
continue;
}
const conflict = busy.find(b => current < b.e && end > b.s);
if (conflict) {
current = conflict.e;
} else { } else {
slots.push({ slots.push({ start: formatISO(current), end: formatISO(end) });
start: new Date(t).toISOString(), current = end;
end: new Date(tEnd).toISOString()
});
t += durMs;
} }
} }
currDate.setUTCDate(currDate.getUTCDate() + 1);
}
return slots; return slots;
}; };
export default findAvailableSlots; export default findAvailableSlots;
// Generation time: 47.831s
// Result: PASS

View File

@@ -1,11 +1,56 @@
async function findAvailableSlots(a,b,{durationMinutes:d,searchRange:r,workHours:w}){ export async function findAvailableSlots(cal1, cal2, { durationMinutes, searchRange, workHours }) {
const{parseISO:p,formatISO:f,addMinutes:m,min:n,max:x,startOfDay:s}=await import('https://esm.sh/date-fns'); const { parseISO, compareAsc, addMinutes } = await import('https://cdn.skypack.dev/date-fns');
const busy=[...a,...b].map(({start:S,end:E})=>({s:p(S),e:p(E)})).sort((q,y)=>q.s-y.s).reduce((c,{s:S,e:E})=>{
const l=c[c.length-1];if(!l||S>l.e)c.push({s:S,e:E});else l.e=x([l.e,E]);return c; const s = parseISO(searchRange.start);
},[]); const e = parseISO(searchRange.end);
const rs=p(r.start),re=p(r.end),[ws,we]=[w.start,w.end].map(t=>{const[h,m]=t.split(':').map(Number);return h*60+m;});
const free=[];let cur=rs;for(const{s:S,e:E}of busy){S>cur&&free.push({s:cur,e:n([S,re])});cur=x([cur,E]);if(cur>=re)break;} const [whS, whE] = [workHours.start, workHours.end].map(t => {
cur<re&&free.push({s:cur,e:re});const slots=[];for(const{s:fs,e:fe}of free){let st=fs;while(m(st,d)<=fe){const en=m(st,d);const minutes=(st-s(st))/6e4;if(minutes>=ws&&minutes+d<=we)slots.push({start:f(st),end:f(en)});st=en;}} const [h, m] = t.split(':').map(Number);
return slots; 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; export default findAvailableSlots;
// Generation time: 289.823s
// Result: PASS

View File

@@ -1,66 +1,93 @@
const useDayjs=(()=>{ const loadDay = (() => {
let p let memo
return()=>p||(p=(async()=>{ return () => memo ?? (memo = (async () => {
const [{default:d},{default:u}]=await Promise.all([ const [core, utc] = await Promise.all([
import('https://cdn.jsdelivr.net/npm/dayjs@1/esm/index.js'), import('https://esm.sh/dayjs@1.11.13?target=esnext'),
import('https://cdn.jsdelivr.net/npm/dayjs@1/esm/plugin/utc/index.js') import('https://esm.sh/dayjs@1.11.13/plugin/utc?target=esnext')
]) ])
d.extend(u) const d = core.default
d.extend(utc.default)
return d return d
})()) })())
})() })()
async function findAvailableSlots(c1=[],c2=[],cfg={}){ const findAvailableSlots = async (c1 = [], c2 = [], cfg = {}) => {
const d=await useDayjs() const d = await loadDay()
const {durationMinutes:dur,searchRange:r={},workHours:w={}}=cfg const u = v => d.utc(v)
const {start:rs,end:re}=r const {
const {start:ws,end:we}=w durationMinutes: dm,
if(!dur||dur<=0||!rs||!re||!ws||!we)return [] searchRange: sr = {},
const s=d.utc(rs),e=d.utc(re) workHours: wh = {}
if(!s.isValid()||!e.isValid()||e.valueOf()<=s.valueOf())return [] } = cfg
const rangeStart=s.valueOf(),rangeEnd=e.valueOf(),min=60000 const dur = Number(dm)
const clip=v=>{ if(!Number.isFinite(dur) || dur <= 0 || !sr.start || !sr.end || !wh.start || !wh.end) return []
if(!v||!v.start||!v.end)return 0 const s = u(sr.start)
const a=d.utc(v.start),b=d.utc(v.end) const e = u(sr.end)
if(!a.isValid()||!b.isValid())return 0 if(!s.isValid() || !e.isValid() || !s.isBefore(e)) return []
const st=Math.max(rangeStart,a.valueOf()),en=Math.min(rangeEnd,b.valueOf()) const toMin = v => {
return en>st?{start:st,end:en}:0 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 busy=[...c1,...c2].map(clip).filter(Boolean).sort((x,y)=>x.start-y.start) const ws = toMin(wh.start)
const merged=[] 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){ for(const slot of busy){
const last=merged[merged.length-1] if(!merged.length){
if(!last||slot.start>last.end)merged.push({...slot}) merged.push({...slot})
else if(slot.end>last.end)last.end=slot.end continue
} }
const free=[] const last = merged[merged.length - 1]
let cur=rangeStart 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){ for(const slot of merged){
if(slot.start>cur)free.push({start:cur,end:slot.start}) if(slot.start.isAfter(cur)) free.push({start: cur, end: slot.start})
cur=Math.max(cur,slot.end) if(slot.end.isAfter(cur)) cur = slot.end
} }
if(cur<rangeEnd)free.push({start:cur,end:rangeEnd}) if(cur.isBefore(e)) free.push({start: cur, end: e})
const minutes=t=>{const [h,m]=t.split(':').map(Number);return h*60+m} if(!free.length) return []
const workStart=minutes(ws),workEnd=minutes(we) const step = dur * 60000
if(workStart>=workEnd)return [] if(!Number.isFinite(step) || step <= 0) return []
const out=[] const out = []
for(const span of free){ for(const seg of free){
let day=d.utc(span.start).startOf('day') for(let day = seg.start.startOf('day'); day.isBefore(seg.end); day = day.add(1, 'day')){
while(day.valueOf()<span.end){ const wsStart = day.add(ws, 'minute')
const dayStart=day.add(workStart,'minute'),dayEnd=day.add(workEnd,'minute') const wsEnd = day.add(we, 'minute')
const winStart=Math.max(dayStart.valueOf(),span.start),winEnd=Math.min(dayEnd.valueOf(),span.end) const start = wsStart.isAfter(seg.start) ? wsStart : seg.start
if(winEnd-winStart>=dur*min){ const end = wsEnd.isBefore(seg.end) ? wsEnd : seg.end
let slotStart=d.utc(winStart) if(!start.isBefore(end)) continue
while(true){ const limit = end.valueOf()
const slotEnd=slotStart.add(dur,'minute') for(let t = start.valueOf(); t + step <= limit; t += step){
if(slotEnd.valueOf()>winEnd)break out.push({
out.push({start:slotStart.toISOString(),end:slotEnd.toISOString()}) start: d.utc(t).toISOString(),
slotStart=slotEnd end: d.utc(t + step).toISOString()
})
} }
} }
day=day.add(1,'day')
}
} }
return out return out
} }
export default findAvailableSlots; export default findAvailableSlots;
// Generation time: 211.798s
// Result: PASS

View File

@@ -1,71 +0,0 @@
const findAvailableSlots = async (calendar1, calendar2, constraints) => {
const { DateTime, Interval } = await import('https://cdn.skypack.dev/luxon@3.0.1')
const { durationMinutes, searchRange, workHours } = constraints
const workStart = DateTime.fromISO(`${searchRange.start.split('T')[0]}T${workHours.start}:00Z`)
const workEnd = DateTime.fromISO(`${searchRange.start.split('T')[0]}T${workHours.end}:00Z`)
const searchStart = DateTime.fromISO(searchRange.start)
const searchEnd = DateTime.fromISO(searchRange.end)
const mergeCalendars = (cal1, cal2) => {
const allSlots = [...cal1, ...cal2].map(slot => ({
start: DateTime.fromISO(slot.start),
end: DateTime.fromISO(slot.end)
})).sort((a, b) => a.start - b.start)
return allSlots.reduce((merged, current) => {
if (merged.length === 0) return [current]
const last = merged[merged.length - 1]
if (current.start <= last.end) {
last.end = current.end > last.end ? current.end : last.end
return merged
}
return [...merged, current]
}, [])
}
const mergedBusy = mergeCalendars(calendar1, calendar2)
const freeIntervals = []
let currentStart = searchStart
for (const busy of mergedBusy) {
if (busy.start > currentStart) {
freeIntervals.push(Interval.fromDateTimes(currentStart, busy.start))
}
currentStart = busy.end > currentStart ? busy.end : currentStart
}
if (currentStart < searchEnd) {
freeIntervals.push(Interval.fromDateTimes(currentStart, searchEnd))
}
const availableSlots = freeIntervals.flatMap(interval => {
const slots = []
let slotStart = interval.start
while (slotStart.plus({ minutes: durationMinutes }) <= interval.end) {
const slotEnd = slotStart.plus({ minutes: durationMinutes })
const slotInterval = Interval.fromDateTimes(slotStart, slotEnd)
if (slotInterval.engulfs(workStart) && slotInterval.engulfs(workEnd)) {
slots.push({
start: slotStart.toISO(),
end: slotEnd.toISO()
})
}
slotStart = slotEnd
}
return slots
})
return availableSlots.filter(slot => {
const slotStart = DateTime.fromISO(slot.start)
const slotEnd = DateTime.fromISO(slot.end)
return slotStart >= workStart && slotEnd <= workEnd
})
}
export default findAvailableSlots;

View File

@@ -1,57 +0,0 @@
async function findAvailableSlots(cal1, cal2, {durationMinutes:dm, searchRange, workHours}) {
const {DateTime:DT, Interval, Duration} = await import('https://cdn.skypack.dev/luxon');
const dur=Duration.fromObject({minutes:dm});
const srS=DT.fromISO(searchRange.start).toUTC();
const srE=DT.fromISO(searchRange.end).toUTC();
const srI=Interval.fromDateTimes(srS,srE);
let busies=[...cal1,...cal2].map(s=>{
const a=DT.fromISO(s.start).toUTC(),b=DT.fromISO(s.end).toUTC();
return a<b?Interval.fromDateTimes(a,b).intersection(srI):null;
}).filter(Boolean);
const [ws,we]=[workHours.start,workHours.end];
const hms=+ws.slice(0,2),mms=+ws.slice(3,5),hme=+we.slice(0,2),mme=+we.slice(3,5);
let cur=srS.startOf('day');
while(cur<srE){
const dayE=cur.plus({days:1});
const dayI=Interval.fromDateTimes(cur,dayE).intersection(srI);
if(dayI.isEmpty) {cur=cur.plus({days:1});continue;}
const wsT=cur.set({hour:hms,minute:mms,second:0,millisecond:0});
const weT=cur.set({hour:hme,minute:mme,second:0,millisecond:0});
const workI=Interval.fromDateTimes(wsT,weT).intersection(dayI);
if(!workI?.isValid||workI.isEmpty){
busies.push(dayI);
}else{
if(dayI.start<workI.start)busies.push(Interval.fromDateTimes(dayI.start,workI.start));
if(workI.end<dayI.end)busies.push(Interval.fromDateTimes(workI.end,dayI.end));
}
cur=cur.plus({days:1});
}
busies.sort((a,b)=>a.start.toMillis()-b.start.toMillis());
const merged=[];
for(let iv of busies){
if(!iv?.isValid||iv.isEmpty)continue;
if(merged.length===0||merged.at(-1).end<iv.start){
merged.push(iv);
}else{
const last=merged[merged.length-1];
merged[merged.length-1]=Interval.fromDateTimes(last.start,iv.end>last.end?iv.end:last.end);
}
}
const frees=[];
let prev=srS;
for(let b of merged){
if(prev<b.start)frees.push(Interval.fromDateTimes(prev,b.start));
prev=b.end>prev?b.end:prev;
}
if(prev<srE)frees.push(Interval.fromDateTimes(prev,srE));
const slots=[];
for(let f of frees){
let c=f.start;
while(c.plus(dur)<=f.end){
slots.push({start:c.toISO(),end:c.plus(dur).toISO()});
c=c.plus(dur);
}
}
return slots;
}
export default findAvailableSlots;

View File

@@ -1,64 +0,0 @@
async function findAvailableSlots(cal1, cal2, constraints) {
const { DateTime, Interval } = await import('https://esm.sh/luxon@3');
const busySlots = [...cal1, ...cal2].map(slot => {
const s = DateTime.fromISO(slot.start, { zone: 'utc' });
const e = DateTime.fromISO(slot.end, { zone: 'utc' });
return s.isValid && e.isValid && s < e ? Interval.fromDateTimes(s, e) : null;
}).filter(Boolean);
const mergedBusies = Interval.union(busySlots);
const rangeStart = DateTime.fromISO(constraints.searchRange.start, { zone: 'utc' });
const rangeEnd = DateTime.fromISO(constraints.searchRange.end, { zone: 'utc' });
const searchInt = Interval.fromDateTimes(rangeStart, rangeEnd);
let covered = mergedBusies
.filter(b => searchInt.overlaps(b))
.map(b => searchInt.intersection(b))
.filter(i => i.isValid);
covered.sort((a, b) => a.start.toMillis() - b.start.toMillis());
const frees = [];
let current = rangeStart;
for (const busy of covered) {
if (current < busy.start) {
frees.push(Interval.fromDateTimes(current, busy.start));
}
current = DateTime.max(current, busy.end);
}
if (current < rangeEnd) {
frees.push(Interval.fromDateTimes(current, rangeEnd));
}
const [wsH, wsM] = constraints.workHours.start.split(':').map(Number);
const [weH, weM] = constraints.workHours.end.split(':').map(Number);
const durMin = constraints.durationMinutes;
let workInts = [];
let curDay = rangeStart.startOf('day');
const endDayStart = rangeEnd.startOf('day');
while (curDay <= endDayStart) {
const dayWorkS = curDay.set({ hour: wsH, minute: wsM });
const dayWorkE = curDay.set({ hour: weH, minute: weM });
if (dayWorkS < dayWorkE) {
workInts.push(Interval.fromDateTimes(dayWorkS, dayWorkE));
}
curDay = curDay.plus({ days: 1 });
}
const allowables = [];
for (const free of frees) {
for (const work of workInts) {
const inter = free.intersection(work);
if (inter.isValid) allowables.push(inter);
}
}
const mergedAllows = Interval.union(allowables);
const availableSlots = [];
for (const allow of mergedAllows) {
let slotStart = allow.start;
while (allow.contains(slotStart.plus({ minutes: durMin }))) {
const slotEnd = slotStart.plus({ minutes: durMin });
availableSlots.push({
start: slotStart.toISO(),
end: slotEnd.toISO()
});
slotStart = slotEnd;
}
}
return availableSlots;
}
export default findAvailableSlots;

View File

@@ -0,0 +1,48 @@
async function findAvailableSlots(c1, c2, con) {
const {DateTime, Interval} = await import('https://cdn.jsdelivr.net/npm/luxon@3.4.4/+esm');
const st = DateTime.fromISO(con.searchRange.start, {zone:'utc'});
const ed = DateTime.fromISO(con.searchRange.end, {zone:'utc'});
const sr = Interval.fromDateTimes(st, ed);
let bs = [...c1, ...c2].map(({start, end}) => Interval.fromDateTimes(
DateTime.fromISO(start, {zone:'utc'}),
DateTime.fromISO(end, {zone:'utc'})
));
let cur = st.startOf('day');
const [wh, wm] = con.workHours.start.split(':').map(Number);
const [eh, em] = con.workHours.end.split(':').map(Number);
while (cur <= ed) {
const ws = cur.set({hour: wh, minute: wm});
const we = cur.set({hour: eh, minute: em});
if (cur < ws) bs.push(Interval.fromDateTimes(cur, ws));
const eod = cur.endOf('day');
if (we < eod) bs.push(Interval.fromDateTimes(we, eod));
cur = cur.plus({days:1}).startOf('day');
}
let mb = Interval.merge(bs).sort((a,b) => a.start.toMillis() - b.start.toMillis());
let rb = mb.filter(i => i.overlaps(sr));
let free = [];
if (rb.length === 0) {
free.push(sr);
} else {
if (sr.start < rb[0].start) free.push(Interval.fromDateTimes(sr.start, rb[0].start));
for (let i = 0; i < rb.length - 1; i++) {
free.push(Interval.fromDateTimes(rb[i].end, rb[i + 1].start));
}
if (rb[rb.length - 1].end < sr.end) free.push(Interval.fromDateTimes(rb[rb.length - 1].end, sr.end));
}
const dur = con.durationMinutes;
let av = [];
for (let f of free) {
let cs = f.start;
while (true) {
let ce = cs.plus({minutes: dur});
if (ce > f.end) break;
av.push({start: cs.toISO(), end: ce.toISO()});
cs = ce;
}
}
return av;
}
export default findAvailableSlots;
// Generation time: 201.779s
// Result: PASS

View File

@@ -1,18 +1,43 @@
async function validateJSON(jsonObject, jsonSchema) { async function validateJSON(jsonObject, jsonSchema) {
const { default: Ajv } = await import("https://esm.sh/ajv@8"); try {
const { default: addFormats } = await import("https://esm.sh/ajv-formats@3"); const Ajv = (await import('https://cdn.jsdelivr.net/npm/ajv@8/dist/ajv.min.js')).default
|| (await import('https://esm.sh/ajv@8')).default;
const ajv = new Ajv({ allErrors: true, strict: false });
addFormats(ajv);
const ajv = new Ajv({ allErrors: true, verbose: true });
const validate = ajv.compile(jsonSchema); const validate = ajv.compile(jsonSchema);
const valid = validate(jsonObject); const valid = validate(jsonObject);
return { return {
valid, valid,
errors: valid ? [] : validate.errors.map(e => errors: valid ? [] : validate.errors.map(e =>
e.instancePath ? `${e.instancePath} ${e.message}` : e.message e.instancePath
? `${e.instancePath} ${e.message}`
: e.message
) )
}; };
} catch (e) {
try {
const { default: Ajv } = await import('https://esm.sh/ajv@8');
const ajv = new Ajv({ allErrors: true, verbose: true });
const validate = ajv.compile(jsonSchema);
const valid = validate(jsonObject);
return {
valid,
errors: valid ? [] : validate.errors.map(e =>
e.instancePath
? `${e.instancePath} ${e.message}`
: e.message
)
};
} catch (err) {
return {
valid: false,
errors: [`Schema validation failed: ${err.message}`]
};
}
}
} }
export default validateJSON; export default validateJSON;
// Generation time: 5.496s
// Result: PASS

View File

@@ -1,11 +1,18 @@
const validateJSON = async (data, schema) => { const validateJSON = async (data, schema) => {
const { default: Ajv } = await import('https://cdn.jsdelivr.net/npm/ajv@8/dist/2020.min.js'); const { default: Ajv } = await import('https://cdn.jsdelivr.net/npm/ajv@8.12.0/dist/2020.min.js');
const ajv = new Ajv({ allErrors: true, strict: false }); const ajv = new Ajv({ allErrors: true, verbose: true });
const validate = ajv.compile(schema); const validate = ajv.compile(schema);
const valid = validate(data); const valid = validate(data);
return { return {
valid, valid,
errors: valid ? [] : validate.errors.map(e => `${e.instancePath || '/'} ${e.message}`) errors: valid ? [] : validate.errors.map(e => ({
path: e.instancePath || '/',
message: e.message,
keyword: e.keyword,
params: e.params
}))
}; };
}; };
export default validateJSON; export default validateJSON;
// Generation time: 3.111s
// Result: FAIL

View File

@@ -1,24 +0,0 @@
const validateJSON = async (json, schema) => {
let ajv;
try {
const { default: Ajv } = await import('https://cdn.jsdelivr.net/npm/ajv@8.17.1/+esm');
ajv = new Ajv({ allErrors: true });
} catch (e) {
return { valid: false, errors: ["Failed to load validator: " + e.message] };
}
try {
const validate = ajv.compile(schema);
const valid = validate(json);
const errors = validate.errors?.map(
e => `${e.instancePath || 'root'} ${e.message}`.trim()
) ?? [];
return { valid, errors };
} catch (e) {
return { valid: false, errors: ["Invalid schema: " + e.message] };
}
};
export default validateJSON;

View File

@@ -1,10 +1,9 @@
const validateJSON = async (d, s) => { const validateJSON = async (data, schema) => {
const { default: A } = await import('https://esm.sh/ajv@8.17.1') const { default: Ajv } = await import('https://esm.sh/ajv@8.17.1');
const v = new A({ allErrors: true }).compile(s) const validate = new Ajv({ allErrors: true }).compile(schema);
const r = v(d) const valid = validate(data);
return { return { valid, errors: valid ? [] : validate.errors.map(e => `${e.instancePath} ${e.message}`.trim()) };
valid: r, };
errors: r ? [] : v.errors.map(e => `${e.instancePath} ${e.message}`.trim())
}
}
export default validateJSON; export default validateJSON;
// Generation time: 20.754s
// Result: PASS

View File

@@ -1,12 +1,24 @@
let Ajv; let a, c;
async function validateJSON(json, schema) {
if(!(json&&typeof json==='object')||!(schema===true||schema===false||(schema&&typeof schema==='object'))) export const validateJSON = async (d, s) => {
return{valid:false,errors:['Invalid input']}; try {
try{ if (!a) {
if(!Ajv){const m=await import('https://esm.sh/ajv@8');Ajv=m.default} const { default: Ajv } = await import('https://esm.sh/ajv?bundle');
const ajv=new Ajv({allErrors:true}),v=ajv.compile(schema); a = new Ajv({ allErrors: true });
const valid=v(json); c = new Map();
return{valid,errors:valid?[]:v.errors.map(e=>`${e.instancePath||'root'} ${e.message}`)}; }
}catch(e){return{valid:false,errors:[e.message]}} 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; export default validateJSON;
// Generation time: 19.566s
// Result: PASS

View File

@@ -1,2 +1,21 @@
const validateJSON=(()=>{let a;return async(j,s)=>{a??=(async()=>{const{default:Ajv}=await import('https://esm.run/ajv@8');return new Ajv({allErrors:1});})();const v=await a,c=v.compile(s),valid=c(j);return{valid,errors:valid?[]:(c.errors||[]).map(e=>`${e.instancePath||'/'} ${e.message}`)}}})(); 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; export default validateJSON;
// Generation time: 6.678s
// Result: FAIL

View File

@@ -1,36 +0,0 @@
const validateJSON = async (json, schema) => {
try {
const { default: Ajv } = await import('https://cdn.jsdelivr.net/npm/ajv@8.12.0/+esm')
const { default: addFormats } = await import('https://cdn.jsdelivr.net/npm/ajv-formats@2.1.1/+esm')
const ajv = new Ajv({
allErrors: true,
strict: false,
validateSchema: true
})
addFormats(ajv)
const validate = ajv.compile(schema)
const valid = validate(json)
return {
valid,
errors: valid ? [] : validate.errors.map(err => ({
message: err.message,
instancePath: err.instancePath,
schemaPath: err.schemaPath,
params: err.params
}))
}
} catch (error) {
return {
valid: false,
errors: [{
message: error.message,
stack: error.stack
}]
}
}
}
export default validateJSON;

View File

@@ -1,21 +0,0 @@
let ajvInstance;
async function validateJSON(data, schema) {
if (!ajvInstance) {
const { default: Ajv } = await import('https://cdn.skypack.dev/ajv@8');
ajvInstance = new Ajv({ allErrors: true });
}
const ajv = ajvInstance;
try {
const validate = ajv.compile(schema);
const valid = validate(data);
const errors = valid ? [] : ajv.errorsText(validate.errors, { separator: '\n' })
.split('\n')
.map(s => s.trim())
.filter(Boolean);
return { valid, errors };
} catch (e) {
return { valid: false, errors: [`Schema error: ${e.message}`] };
}
}
export default validateJSON;

View File

@@ -1,10 +0,0 @@
async function validateJSON(data,schema){
const{default:Ajv}=await import('https://esm.sh/ajv@7.13.4');
const ajv=new Ajv({allErrors:true});
const validate=ajv.compile(schema);
const valid=validate(data);
if(valid)return{valid:true,errors:[]};
const errors=validate.errors.map(e=>`${e.instancePath||''} ${e.message||'Validation error'}`.trim()).filter(Boolean);
return{valid:false,errors};
}
export default validateJSON;

View File

@@ -0,0 +1,13 @@
async function validateJSON(data, schema) {
const { default: Ajv } = await import('https://cdn.jsdelivr.net/npm/ajv@8/dist/ajv.min.js');
const ajv = new Ajv({ allErrors: true });
const validate = ajv.compile(schema);
const valid = validate(data);
return {
valid,
errors: valid ? [] : validate.errors.map(e => e.message)
};
}
export default validateJSON;
// Generation time: 16.498s
// Result: FAIL

View File

@@ -26,3 +26,5 @@ async function createStreamVisualizer(asyncIterable, options) {
return { data, path }; return { data, path };
} }
export default createStreamVisualizer; export default createStreamVisualizer;
// Generation time: 5.230s
// Result: PASS

Some files were not shown because too many files have changed in this diff Show More