mirror of
https://github.com/multipleof4/lynchmark.git
synced 2026-01-14 08:37:56 +00:00
Docs: Update benchmark results
This commit is contained in:
@@ -1,56 +1,68 @@
|
||||
async function findAvailableSlots(
|
||||
calendar1,
|
||||
calendar2,
|
||||
{ durationMinutes: dur, searchRange: sr, workHours: wh }
|
||||
) {
|
||||
const dayjs = (await import('https://cdn.skypack.dev/dayjs')).default;
|
||||
const utc = (await import('https://cdn.skypack.dev/dayjs/plugin/utc')).default;
|
||||
dayjs.extend(utc);
|
||||
async function findAvailableSlots(calendar1, calendar2, constraints) {
|
||||
const [dayjsModule, durationModule] = await Promise.all([
|
||||
import('https://cdn.jsdelivr.net/npm/dayjs@1/dayjs.min.js'),
|
||||
import('https://cdn.jsdelivr.net/npm/dayjs@1/plugin/duration.js')
|
||||
]);
|
||||
const dayjs = dayjsModule.default;
|
||||
dayjs.extend(durationModule.default);
|
||||
|
||||
const d = (s) => dayjs.utc(s);
|
||||
const rangeStart = d(sr.start);
|
||||
const rangeEnd = d(sr.end);
|
||||
const [whsH, whsM] = wh.start.split(':');
|
||||
const [wheH, wheM] = wh.end.split(':');
|
||||
const { durationMinutes: duration, searchRange, workHours } = constraints;
|
||||
const searchStart = dayjs(searchRange.start);
|
||||
const searchEnd = dayjs(searchRange.end);
|
||||
const [workStartH, workStartM] = workHours.start.split(':').map(Number);
|
||||
const [workEndH, workEndM] = workHours.end.split(':').map(Number);
|
||||
|
||||
const busySlots = [...calendar1, ...calendar2].map(({ start, end }) => ({
|
||||
start: d(start),
|
||||
end: d(end),
|
||||
}));
|
||||
const toDayjs = ({ start, end }) => ({ start: dayjs(start), end: dayjs(end) });
|
||||
const allBusy = [...calendar1, ...calendar2].map(toDayjs);
|
||||
|
||||
for (let day = rangeStart.clone().startOf('d'); day.isBefore(rangeEnd); day = day.add(1, 'd')) {
|
||||
busySlots.push({ start: day.startOf('d'), end: day.hour(whsH).minute(whsM) });
|
||||
busySlots.push({ start: day.hour(wheH).minute(wheM), end: day.endOf('d') });
|
||||
for (let day = searchStart.clone().startOf('day'); day.isBefore(searchEnd); day = day.add(1, 'day')) {
|
||||
allBusy.push({
|
||||
start: day,
|
||||
end: day.hour(workStartH).minute(workStartM)
|
||||
});
|
||||
allBusy.push({
|
||||
start: day.hour(workEndH).minute(workEndM),
|
||||
end: day.endOf('day')
|
||||
});
|
||||
}
|
||||
|
||||
const merged = busySlots
|
||||
.filter(({ start, end }) => start.isBefore(end))
|
||||
const mergedBusy = allBusy
|
||||
.sort((a, b) => a.start - b.start)
|
||||
.reduce((acc, cur) => {
|
||||
.reduce((acc, slot) => {
|
||||
const last = acc.at(-1);
|
||||
if (!last || cur.start.isAfter(last.end)) {
|
||||
acc.push(cur);
|
||||
} else if (cur.end.isAfter(last.end)) {
|
||||
last.end = cur.end;
|
||||
if (last && slot.start <= last.end) {
|
||||
if (slot.end > last.end) last.end = slot.end;
|
||||
} else {
|
||||
acc.push({ ...slot });
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
const available = [];
|
||||
let cursor = rangeStart;
|
||||
const availableSlots = [];
|
||||
let nextFreeStart = searchStart;
|
||||
|
||||
[...merged, { start: rangeEnd, end: rangeEnd }].forEach((busy) => {
|
||||
const gapEnd = busy.start;
|
||||
for (let slotStart = cursor; !slotStart.add(dur, 'm').isAfter(gapEnd); slotStart = slotStart.add(dur, 'm')) {
|
||||
const slotEnd = slotStart.add(dur, 'm');
|
||||
available.push({
|
||||
start: slotStart.toISOString(),
|
||||
end: slotEnd.toISOString(),
|
||||
});
|
||||
const findSlotsInGap = (start, end) => {
|
||||
let slotStart = start;
|
||||
while (slotStart.add(duration, 'minute') <= end) {
|
||||
const slotEnd = slotStart.add(duration, 'minute');
|
||||
availableSlots.push({ start: slotStart.toISOString(), end: slotEnd.toISOString() });
|
||||
slotStart = slotEnd;
|
||||
}
|
||||
};
|
||||
|
||||
mergedBusy.forEach(busySlot => {
|
||||
if (busySlot.start > nextFreeStart) {
|
||||
findSlotsInGap(nextFreeStart, busySlot.start);
|
||||
}
|
||||
if (busySlot.end > nextFreeStart) {
|
||||
nextFreeStart = busySlot.end;
|
||||
}
|
||||
cursor = cursor.isAfter(busy.end) ? cursor : busy.end;
|
||||
});
|
||||
|
||||
return available;
|
||||
if (searchEnd > nextFreeStart) {
|
||||
findSlotsInGap(nextFreeStart, searchEnd);
|
||||
}
|
||||
|
||||
return availableSlots;
|
||||
}
|
||||
export default findAvailableSlots;
|
||||
Reference in New Issue
Block a user