mirror of
https://github.com/multipleof4/lynchmark.git
synced 2026-01-13 16:17:54 +00:00
52 lines
2.2 KiB
JavaScript
52 lines
2.2 KiB
JavaScript
const findAvailableSlots = async (calendar1, calendar2, constraints) => {
|
|
const { DateTime, Interval } = await import('https://cdn.jsdelivr.net/npm/luxon@3.4.4/+esm');
|
|
|
|
const parse = s => DateTime.fromISO(s, { zone: 'utc' });
|
|
const workStart = constraints.workHours.start;
|
|
const workEnd = constraints.workHours.end;
|
|
const rangeStart = parse(constraints.searchRange.start);
|
|
const rangeEnd = parse(constraints.searchRange.end);
|
|
const duration = constraints.durationMinutes;
|
|
|
|
const allBusy = [...calendar1, ...calendar2]
|
|
.map(b => Interval.fromDateTimes(parse(b.start), parse(b.end)))
|
|
.sort((a, b) => a.s - b.s);
|
|
|
|
const merged = [];
|
|
allBusy.forEach(busy => {
|
|
const last = merged[merged.length - 1];
|
|
last && last.overlaps(busy) || last?.abutsStart(busy) ?
|
|
merged[merged.length - 1] = last.union(busy) : merged.push(busy);
|
|
});
|
|
|
|
const free = [];
|
|
let current = rangeStart;
|
|
merged.forEach(busy => {
|
|
if (current < busy.s) free.push(Interval.fromDateTimes(current, busy.s));
|
|
current = busy.e > current ? busy.e : current;
|
|
});
|
|
if (current < rangeEnd) free.push(Interval.fromDateTimes(current, rangeEnd));
|
|
|
|
const slots = [];
|
|
free.forEach(interval => {
|
|
let slotStart = interval.s;
|
|
const workStartToday = slotStart.set({ hour: workStart.slice(0, 2), minute: workStart.slice(3), second: 0, millisecond: 0 });
|
|
const workEndToday = slotStart.set({ hour: workEnd.slice(0, 2), minute: workEnd.slice(3), second: 0, millisecond: 0 });
|
|
const workInterval = Interval.fromDateTimes(workStartToday, workEndToday);
|
|
const available = interval.intersection(workInterval);
|
|
|
|
if (available) {
|
|
let start = available.s > slotStart ? available.s : slotStart;
|
|
while (start.plus({ minutes: duration }) <= available.e && start.plus({ minutes: duration }) <= rangeEnd) {
|
|
const end = start.plus({ minutes: duration });
|
|
slots.push({ start: start.toISO(), end: end.toISO() });
|
|
start = end;
|
|
}
|
|
}
|
|
});
|
|
|
|
return slots;
|
|
};
|
|
export default findAvailableSlots;
|
|
// Generation time: 19.693s
|
|
// Result: PASS
|