mirror of
https://github.com/multipleof4/lynchmark.git
synced 2026-01-14 00:27:55 +00:00
Docs: Update benchmark results
This commit is contained in:
@@ -1,55 +1,40 @@
|
||||
let df
|
||||
async function findAvailableSlots(a,b,c){
|
||||
df??=await import('https://cdn.jsdelivr.net/npm/date-fns@3.6.0/+esm')
|
||||
const {parseISO:pi,formatISO:fi,eachDayOfInterval:ed,set:st}=df
|
||||
const sr=pi(c.searchRange.start),er=pi(c.searchRange.end),srT=+sr,erT=+er
|
||||
const [hs,ms]=c.workHours.start.split(':').map(Number)
|
||||
const [he,me]=c.workHours.end.split(':').map(Number)
|
||||
const step=c.durationMinutes*6e4
|
||||
const norm=u=>{
|
||||
const arr=u.map(v=>({s:+pi(v.start),e:+pi(v.end)})).filter(v=>v.e>srT&&v.s<erT).map(v=>({s:Math.max(v.s,srT),e:Math.min(v.e,erT)})).filter(v=>v.e>v.s).sort((x,y)=>x.s-y.s)
|
||||
const out=[]
|
||||
arr.forEach(v=>{
|
||||
const w=out[out.length-1]
|
||||
if(!w||v.s>w.e)out.push({s:v.s,e:v.e})
|
||||
else w.e=Math.max(w.e,v.e)
|
||||
})
|
||||
return out
|
||||
let cache
|
||||
const load=()=>cache||(cache=import('https://cdn.skypack.dev/date-fns@2.30.0?min'))
|
||||
async function findAvailableSlots(calA,calB,rules){
|
||||
const {parseISO:iso,addMinutes:plus,differenceInMinutes:gap,eachDayOfInterval:days,set:setTime,max:maxDate,min:minDate}=await load()
|
||||
const parseCal=c=>c.map(({start,end})=>({start:iso(start),end:iso(end)}))
|
||||
const [sh,sm]=rules.workHours.start.split(':').map(Number)
|
||||
const [eh,em]=rules.workHours.end.split(':').map(Number)
|
||||
const rangeStart=iso(rules.searchRange.start),rangeEnd=iso(rules.searchRange.end)
|
||||
const entries=[...parseCal(calA),...parseCal(calB)].filter(b=>b.end>rangeStart&&b.start<rangeEnd).sort((a,b)=>a.start-b.start)
|
||||
const slots=[]
|
||||
const addFree=(s,e)=>{
|
||||
let cursor=s
|
||||
while(gap(e,cursor)>=rules.durationMinutes){
|
||||
const stop=plus(cursor,rules.durationMinutes)
|
||||
slots.push({start:cursor.toISOString(),end:stop.toISOString()})
|
||||
cursor=stop
|
||||
}
|
||||
const free=u=>{
|
||||
const busy=norm(u),days=ed({start:sr,end:er}),out=[]
|
||||
let i=0
|
||||
for(const day of days){
|
||||
const d0=Math.max(+st(day,{hours:hs,minutes:ms,seconds:0,milliseconds:0}),srT)
|
||||
const d1=Math.min(+st(day,{hours:he,minutes:me,seconds:0,milliseconds:0}),erT)
|
||||
if(d0>=d1)continue
|
||||
while(i<busy.length&&busy[i].e<=d0)i++
|
||||
let cur=d0,j=i
|
||||
while(j<busy.length&&busy[j].s<d1){
|
||||
if(busy[j].s>cur)out.push({s:cur,e:Math.min(busy[j].s,d1)})
|
||||
cur=Math.max(cur,busy[j].e)
|
||||
if(cur>=d1)break
|
||||
j++
|
||||
}
|
||||
if(cur<d1)out.push({s:cur,e:d1})
|
||||
i=j
|
||||
}
|
||||
return out
|
||||
}
|
||||
for(const day of days({start:rangeStart,end:rangeEnd})){
|
||||
const workStart=setTime(day,{hours:sh,minutes:sm,seconds:0,milliseconds:0})
|
||||
const workEnd=setTime(day,{hours:eh,minutes:em,seconds:0,milliseconds:0})
|
||||
let spanStart=maxDate([workStart,rangeStart]),spanEnd=minDate([workEnd,rangeEnd])
|
||||
if(spanStart>=spanEnd)continue
|
||||
const busy=entries.filter(b=>b.end>spanStart&&b.start<spanEnd).map(b=>({start:maxDate([b.start,spanStart]),end:minDate([b.end,spanEnd])})).sort((a,b)=>a.start-b.start)
|
||||
const merged=[]
|
||||
for(const block of busy){
|
||||
const last=merged[merged.length-1]
|
||||
if(!last||block.start>last.end)merged.push({start:block.start,end:block.end})
|
||||
else if(block.end>last.end)last.end=block.end
|
||||
}
|
||||
const x=free(a),y=free(b),res=[]
|
||||
let i=0,j=0
|
||||
while(i<x.length&&j<y.length){
|
||||
const s=Math.max(x[i].s,y[j].s)
|
||||
const e=Math.min(x[i].e,y[j].e)
|
||||
if(e-s>=step){
|
||||
const k=Math.floor((e-s)/step)
|
||||
for(let n=0;n<k;n++){
|
||||
const start=s+n*step,end=start+step
|
||||
res.push({start:fi(new Date(start)),end:fi(new Date(end))})
|
||||
}
|
||||
}
|
||||
x[i].e<y[j].e?i++:x[i].e>y[j].e?j++:(i++,j++)
|
||||
let cursor=spanStart
|
||||
for(const block of merged){
|
||||
if(block.start>cursor)addFree(cursor,block.start)
|
||||
if(block.end>cursor)cursor=block.end
|
||||
}
|
||||
return res
|
||||
if(cursor<spanEnd)addFree(cursor,spanEnd)
|
||||
}
|
||||
return slots
|
||||
}
|
||||
export default findAvailableSlots;
|
||||
Reference in New Issue
Block a user