|
function getStartTime(schedules, duration) { |
|
//console.log('schedules:', schedules, '| duration:', duration); |
|
let spareTime = []; |
|
schedules.forEach((schedule, index) => { |
|
//console.log('index:', index); |
|
spareTime.push([]); |
|
if (schedule.length > 0) { // if a whole day is free schedule.length === 0 |
|
//console.log('schedule[0]:', schedule[0]); |
|
if ((parseInt(schedule[0][0].split(':')[0]) > 9 && parseInt(schedule[0][0].split(':')[1]) >= 0) || (parseInt(schedule[0][0].split(':')[0]) >= 9 && parseInt(schedule[0][0].split(':')[1]) > 0)) { |
|
//console.log('extra time in the morning, checking duration:', schedule[0][0]); |
|
const diff = (parseInt(schedule[0][0].split(':')[0]) - 9) * 60 + parseInt(schedule[0][0].split(':')[1]); |
|
//console.log('diff:', diff); |
|
if (diff >= duration) { spareTime[index].push(['09:00', schedule[0][0]]); } |
|
//console.log('spareTime:', spareTime); |
|
} |
|
|
|
for (let i = 1, max = schedule.length; i < max; i++) { |
|
const previous = schedule[i - 1]; |
|
const current = schedule[i]; |
|
const diff = (parseInt(current[0].split(':')[0]) - parseInt(previous[1].split(':')[0])) * 60 + parseInt(current[0].split(':')[1]) - parseInt(previous[1].split(':')[1]); |
|
//console.log('diff:', diff); |
|
if (diff >= duration) { spareTime[index].push([previous[1], current[0]]); } |
|
} |
|
const lastIndex = schedule.length - 1; |
|
if (parseInt(schedule[lastIndex][1].split(':')[0]) < 19) { |
|
//console.log('extra time in the evening, checking duration:', schedule[lastIndex][1]); |
|
const diff = (19 - parseInt(schedule[lastIndex][0].split(':')[0])) * 60 + 60 - parseInt(schedule[lastIndex][0].split(':')[1]); |
|
//console.log('diff:', diff); |
|
if (diff >= duration) { spareTime[index].push([schedule[lastIndex][1], '19:00']); } |
|
} |
|
} else { |
|
spareTime[index].push('09:00', '19:00'); |
|
} |
|
}); |
|
console.log('spareTime:', spareTime); |
|
const noSpareTime = spareTime.filter((schedule) => schedule.length === 0); |
|
if (noSpareTime.length > 0) { |
|
//console.log('noSpareTime:', noSpareTime); |
|
return null; |
|
} |
|
const mostAvailable = spareTime.reduce((a, b) => { return (a.length < b.length) ? b : a; }); |
|
//console.log('mostAvailable:', mostAvailable); |
|
spareTime.splice(spareTime.indexOf(mostAvailable), 1); |
|
//console.log('spareTime:', spareTime); |
|
let matches = 0; |
|
let matchesDetails = []; |
|
let time = null; |
|
root: |
|
for (let k = 0, kMax = mostAvailable.length; k < kMax; k++) { |
|
const sch0 = mostAvailable[k]; |
|
//console.log('sch0:', sch0); |
|
let sch0Start = parseInt(sch0[0].split(':')[0]) * 60 + parseInt(sch0[0].split(':')[1]); |
|
if (matchesDetails.length > 0) { |
|
sch0Start = (matchesDetails[matchesDetails.length - 1].time && time > sch0Start) ? matchesDetails[matchesDetails.length - 1].time : sch0Start; |
|
} |
|
const sch0End = parseInt(sch0[1].split(':')[0]) * 60 + parseInt(sch0[1].split(':')[1]); |
|
//console.log('sch0:', sch0Start, sch0End); |
|
matches = 0; |
|
time = null; |
|
child1: |
|
for (let j = 0, jMax = spareTime.length; j < jMax; j++) { |
|
const schedule = spareTime[j]; |
|
//console.log('NEXT SCHEDULE:', schedule); |
|
child2: |
|
for (let i = 0, max = schedule.length; i < max; i++) { |
|
const start = parseInt(schedule[i][0].split(':')[0]) * 60 + parseInt(schedule[i][0].split(':')[1]); |
|
const end = parseInt(schedule[i][1].split(':')[0]) * 60 + parseInt(schedule[i][1].split(':')[1]); |
|
//console.log('schedule time in minutes', start, end); |
|
if (sch0Start <= start && sch0End >= end) { |
|
matches++; |
|
time = (time < start) ? start : time; |
|
matchesDetails.push({ time: time, gaps: [start, end] }); |
|
//console.log('break child2 1, time', time); |
|
break child2; |
|
} else if (sch0Start > start && sch0End >= end && end > sch0Start && end - sch0Start >= duration) { |
|
matches++; |
|
time = (time < sch0Start) ? sch0Start : time; |
|
matchesDetails.push({ time: time, gaps: [start, end] }); |
|
/* |
|
console.log('break child2 2, time', time); |
|
console.log('diff', end - sch0Start); |
|
console.log('schedule 0:', sch0Start, sch0End, '|', duration); |
|
console.log('schedule '+i+':', start, end, '|', duration); |
|
*/ |
|
break child2; |
|
} else if (sch0Start > start && sch0End < end && end - sch0Start >= duration && sch0End - start >= duration) { |
|
matches++; |
|
time = (time < sch0Start) ? sch0Start : time; |
|
matchesDetails.push({ time: time, gaps: [start, end] }); |
|
/* |
|
console.log('break child2 3, time', time); |
|
console.log('diff', sch0End - start); |
|
console.log('schedule 0:', sch0Start, sch0End, '|', duration); |
|
console.log('schedule '+i+':', start, end, '|', duration); |
|
*/ |
|
break child2; |
|
} else if (sch0Start <= start && start < sch0End && sch0End < end && sch0End - start >= duration) { |
|
matches++; |
|
time = (time < start) ? start : time; |
|
matchesDetails.push({ time: time, gaps: [start, end] }); |
|
/* |
|
console.log('break child2 3, time', time); |
|
console.log('diff', sch0End - start); |
|
console.log('schedule 0:', sch0Start, sch0End, '|', duration); |
|
console.log('schedule '+i+':', start, end, '|', duration); |
|
*/ |
|
break child2; |
|
} else { |
|
console.log('ignore'); |
|
/* |
|
console.log('schedule 0:', sch0Start, sch0End, '|', duration); |
|
console.log('schedule '+i+':', start, end, '|', duration); |
|
*/ |
|
} |
|
} |
|
//console.log('matches:', matches, '| schedules.length:', schedules.length); |
|
//console.log('==='); |
|
if (schedules.length - 1 === matches && sch0End - time >= duration) { |
|
//console.log('break root, time', time); |
|
//console.log('schedule 0:', sch0Start, sch0End, '|', duration); |
|
matches++; |
|
break root; |
|
} |
|
} |
|
} |
|
//console.log('matchesDetails:', matchesDetails, 'time:', time); |
|
// recalculate suitable matches after finding earlies starting time possible |
|
matches = 1; |
|
matchesDetails.forEach((match) => { |
|
if (match.gaps[1] - time >= duration) { matches++; } |
|
}); |
|
if (schedules.length !== matches) { time = null; } |
|
// convert result to format hh:mm |
|
let hours = Math.floor(time / 60); |
|
hours = (hours < 10) ? '0' + hours : hours; |
|
let minutes = time % 60; |
|
minutes = (minutes < 10) ? '0' + minutes : minutes; |
|
return (time) ? hours + ':' + minutes : time; |
|
} |
|
|
|
let schedules = [ |
|
[['09:10', '11:30'], ['12:30', '16:30'], ['17:30', '19:15']], |
|
[['09:15', '12:10'], ['14:10', '16:20']] |
|
], |
|
duration = 120; |
|
getStartTime(schedules, duration); // null |