mirror of
https://github.com/multipleof4/lynchmark.git
synced 2026-01-14 08:37:56 +00:00
Docs: Update benchmark for minimax/minimax-m2
This commit is contained in:
142
tests/7_scheduler/outputs/minimax_minimax-m2.js
Normal file
142
tests/7_scheduler/outputs/minimax_minimax-m2.js
Normal file
@@ -0,0 +1,142 @@
|
||||
'use strict';
|
||||
|
||||
export async function findAvailableSlots(busyA, busyB, constraints) {
|
||||
const {
|
||||
addMinutes,
|
||||
compareAsc,
|
||||
eachMinuteOfInterval,
|
||||
isBefore,
|
||||
isEqual,
|
||||
isValid,
|
||||
parseISO,
|
||||
startOfDay,
|
||||
} = await import('https://cdn.skypack.dev/date-fns@2.30.0');
|
||||
|
||||
const c = constraints || {};
|
||||
const durationMinutes = (c && c.durationMinutes) || 30;
|
||||
if (!Number.isInteger(durationMinutes) || durationMinutes <= 0) throw new Error('durationMinutes must be a positive integer');
|
||||
const range = c && c.searchRange || {};
|
||||
const rangeStart = parseISO(range.start);
|
||||
const rangeEnd = parseISO(range.end);
|
||||
if (!isValid(rangeStart) || !isValid(rangeEnd) || !isBefore(rangeStart, rangeEnd)) throw new Error('Invalid searchRange');
|
||||
const wh = c && c.workHours || {};
|
||||
const [whStartH, whStartM] = String(wh.start || '09:00').split(':').map(n => parseInt(n, 10));
|
||||
const [whEndH, whEndM] = String(wh.end || '17:00').split(':').split(':').map(n => parseInt(n, 10));
|
||||
const WH_ST = whStartH * 60 + (isNaN(whStartM) ? 0 : whStartM);
|
||||
const WH_ET = whEndH * 60 + (isNaN(whEndM) ? 0 : whEndM);
|
||||
if (!(0 <= WH_ST && WH_ST < WH_ET && WH_ET <= 1440)) throw new Error('Invalid workHours');
|
||||
|
||||
const toEpoch = d => d.getTime();
|
||||
const fmtTime = d => {
|
||||
const t = d.getUTCHours().toString().padStart(2, '0') + ':' + d.getUTCMinutes().toString().padStart(2, '0');
|
||||
return t;
|
||||
};
|
||||
|
||||
const parseBusy = slot => {
|
||||
const s = parseISO(slot.start);
|
||||
const e = parseISO(slot.end);
|
||||
if (!isValid(s) || !isValid(e) || !isBefore(s, e) && !isEqual(s, e)) throw new Error('Invalid busy slot');
|
||||
return { s, e };
|
||||
};
|
||||
|
||||
const busy = [...busyA, ...busyB].map(parseBusy)
|
||||
.filter(({ s, e }) => isBefore(rangeStart, e) && !isBefore(s, rangeEnd))
|
||||
.map(({ s, e }) => ({ s: isBefore(s, rangeStart) ? rangeStart : s, e: isBefore(rangeEnd, e) ? rangeEnd : e }))
|
||||
.sort((a, b) => compareAsc(a.s, b.s));
|
||||
|
||||
const merged = [];
|
||||
for (const cur of busy) {
|
||||
if (merged.length === 0) {
|
||||
merged.push({ ...cur });
|
||||
continue;
|
||||
}
|
||||
const last = merged[merged.length - 1];
|
||||
if (isBefore(last.e, cur.s) || isEqual(last.e, cur.s)) {
|
||||
merged.push({ ...cur });
|
||||
} else {
|
||||
if (isBefore(cur.e, last.e)) continue;
|
||||
last.e = cur.e;
|
||||
}
|
||||
}
|
||||
|
||||
const findNext = (t, arr, lo, hi) => {
|
||||
while (lo <= hi) {
|
||||
const mid = (lo + hi) >> 1;
|
||||
if (isBefore(arr[mid].e, t) || isEqual(arr[mid].e, t)) lo = mid + 1;
|
||||
else hi = mid - 1;
|
||||
}
|
||||
return lo < arr.length ? lo : -1;
|
||||
};
|
||||
|
||||
const available = [];
|
||||
let cursor = rangeStart;
|
||||
let idx = 0;
|
||||
while (idx < merged.length && !isBefore(rangeEnd, merged[idx].s)) {
|
||||
const blockStart = merged[idx].s;
|
||||
const blockEnd = merged[idx].e;
|
||||
if (isBefore(cursor, blockStart)) {
|
||||
available.push({ start: cursor, end: blockStart });
|
||||
}
|
||||
if (isBefore(blockEnd, cursor)) {
|
||||
idx = findNext(cursor, merged, idx + 1, merged.length - 1);
|
||||
if (idx === -1) break;
|
||||
continue;
|
||||
}
|
||||
cursor = blockEnd;
|
||||
idx = idx + 1;
|
||||
}
|
||||
if (isBefore(cursor, rangeEnd)) available.push({ start: cursor, end: rangeEnd });
|
||||
|
||||
const isSameUTCDay = (a, b) =>
|
||||
a.getUTCFullYear() === b.getUTCFullYear() &&
|
||||
a.getUTCMonth() === b.getUTCMonth() &&
|
||||
a.getUTCDate() === b.getUTCDate();
|
||||
|
||||
const startOfNextDayUTC = d => addMinutes(startOfDay(d), 24 * 60);
|
||||
|
||||
const clipSegmentToWorkHours = (segStart, segEnd) => {
|
||||
const out = [];
|
||||
let day = startOfDay(segStart);
|
||||
while (isBefore(day, segEnd)) {
|
||||
const dayStart = isBefore(day, segStart) ? segStart : day;
|
||||
const dayNext = startOfNextDayUTC(day);
|
||||
const dayEnd = isBefore(segEnd, dayNext) ? segEnd : dayNext;
|
||||
const segST = (dayStart.getUTCHours() * 60 + dayStart.getUTCMinutes()) | 0;
|
||||
const segET = (dayEnd.getUTCHours() * 60 + dayEnd.getUTCMinutes()) | 0;
|
||||
const st = Math.max(segST, WH_ST);
|
||||
const et = Math.min(segET, WH_ET);
|
||||
if (st < et) {
|
||||
const clipStart = addMinutes(day, st);
|
||||
const clipEnd = addMinutes(day, et);
|
||||
out.push({ start: clipStart, end: clipEnd });
|
||||
}
|
||||
day = dayNext;
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
const slots = [];
|
||||
for (const seg of available) {
|
||||
const clips = clipSegmentToWorkHours(seg.start, seg.end);
|
||||
for (const clip of clips) {
|
||||
const clipLen = Math.floor((toEpoch(clip.end) - toEpoch(clip.start)) / 60000);
|
||||
const count = Math.floor(clipLen / durationMinutes);
|
||||
if (count <= 0) continue;
|
||||
let cur = clip.start;
|
||||
for (let i = 0; i < count; i++) {
|
||||
const s = cur;
|
||||
const e = addMinutes(s, durationMinutes);
|
||||
if (isBefore(e, clip.end) || isEqual(e, clip.end)) {
|
||||
if (isBefore(rangeStart, s) && !isBefore(rangeEnd, e)) {
|
||||
slots.push({ start: s.toISOString(), end: e.toISOString() });
|
||||
}
|
||||
}
|
||||
cur = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
return slots;
|
||||
}
|
||||
export default findAvailableSlots;
|
||||
// Generation time: 36.069s
|
||||
// Result: FAIL
|
||||
Reference in New Issue
Block a user