Files
lynchmark/tests/7_scheduler/outputs_gemini/gemini-3-pro-preview TEMP_0.1.js
2025-11-18 22:04:41 +00:00

59 lines
1.8 KiB
JavaScript

const findAvailableSlots = async (calA, calB, { durationMinutes: dur, searchRange: range, workHours: wh }) => {
const { parseISO } = await import('https://esm.sh/date-fns@2.30.0');
const toMs = (t) => parseISO(t).getTime();
const getMins = (t) => { const [h, m] = t.split(':'); return h * 60 + +m; };
const [whStart, whEnd] = [getMins(wh.start), getMins(wh.end)];
const [rStart, rEnd] = [toMs(range.start), toMs(range.end)];
const durMs = dur * 60000;
const busy = [...calA, ...calB]
.map(s => ({ s: toMs(s.start), e: toMs(s.end) }))
.sort((a, b) => a.s - b.s);
const merged = [];
if (busy.length) {
let curr = busy[0];
for (let i = 1; i < busy.length; i++) {
if (busy[i].s < curr.e) curr.e = Math.max(curr.e, busy[i].e);
else { merged.push(curr); curr = busy[i]; }
}
merged.push(curr);
}
const gaps = [];
let ptr = rStart;
const relBusy = [...merged.filter(b => b.e > rStart && b.s < rEnd), { s: rEnd, e: rEnd }];
for (const b of relBusy) {
const s = Math.max(ptr, rStart), e = Math.min(b.s, rEnd);
if (e - s >= durMs) gaps.push({ s, e });
ptr = Math.max(ptr, b.e);
}
const slots = [];
for (const g of gaps) {
let t = g.s;
while (t + durMs <= g.e) {
const d = new Date(t);
const curM = d.getUTCHours() * 60 + d.getUTCMinutes();
if (curM >= whStart && curM + dur <= whEnd) {
slots.push({ start: d.toISOString(), end: new Date(t + durMs).toISOString() });
t += durMs;
} else {
if (curM < whStart) {
d.setUTCHours(0, whStart, 0, 0);
} else {
d.setUTCDate(d.getUTCDate() + 1);
d.setUTCHours(0, whStart, 0, 0);
}
t = Math.max(t, d.getTime());
}
}
}
return slots;
};
export default findAvailableSlots;