add option to choose between 2 algorithms for scheduling
This commit is contained in:
@ -56,7 +56,9 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
req.query.date?.toString() || common.getISODateOnly(new Date()),
|
req.query.date?.toString() || common.getISODateOnly(new Date()),
|
||||||
common.parseBool(req.query.copyFromPreviousMonth),
|
common.parseBool(req.query.copyFromPreviousMonth),
|
||||||
common.parseBool(req.query.autoFill),
|
common.parseBool(req.query.autoFill),
|
||||||
common.parseBool(req.query.forDay));
|
common.parseBool(req.query.forDay),
|
||||||
|
parseInt(req.query.type) || 0,
|
||||||
|
);
|
||||||
res.send(JSON.stringify(result?.error?.toString()));
|
res.send(JSON.stringify(result?.error?.toString()));
|
||||||
break;
|
break;
|
||||||
case "delete":
|
case "delete":
|
||||||
@ -488,7 +490,7 @@ function flattenRegistry(dayKey) {
|
|||||||
return Object.values(weekEntries).flat();
|
return Object.values(weekEntries).flat();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function GenerateSchedule(axios, date, copyFromPreviousMonth = false, autoFill = false, forDay) {
|
async function GenerateSchedule(axios, date, copyFromPreviousMonth = false, autoFill = false, forDay, algType = 0) {
|
||||||
|
|
||||||
let missingPublishers = [];
|
let missingPublishers = [];
|
||||||
let publishersWithChangedPref = [];
|
let publishersWithChangedPref = [];
|
||||||
@ -649,6 +651,7 @@ async function GenerateSchedule(axios, date, copyFromPreviousMonth = false, auto
|
|||||||
});
|
});
|
||||||
|
|
||||||
let publishersToday = [];
|
let publishersToday = [];
|
||||||
|
let rankedPublishers = [];
|
||||||
|
|
||||||
// Second pass - prioritize shifts with transport where it is needed
|
// Second pass - prioritize shifts with transport where it is needed
|
||||||
console.log(" second pass - fix transports " + monthInfo.monthName + " " + monthInfo.year);
|
console.log(" second pass - fix transports " + monthInfo.monthName + " " + monthInfo.year);
|
||||||
@ -703,10 +706,13 @@ async function GenerateSchedule(axios, date, copyFromPreviousMonth = false, auto
|
|||||||
|
|
||||||
return (hasTransportInAvailability || hasTransportOutAvailability);
|
return (hasTransportInAvailability || hasTransportOutAvailability);
|
||||||
});
|
});
|
||||||
|
|
||||||
availablePublishers = await FilterInappropriatePublishers([...availablePublishers], publishersToday, shift);
|
availablePublishers = await FilterInappropriatePublishers([...availablePublishers], publishersToday, shift);
|
||||||
// rank publishers based on different factors
|
if (algType == 0) {
|
||||||
// let rankedPublishersOld = await RankPublishersForShift([...availablePublishers])
|
rankedPublishers = await RankPublishersForShiftOld([...availablePublishers], scheduledPubsPerDayAndWeek, day, weekNr);
|
||||||
let rankedPublishers = await RankPublishersForShiftWeighted([...availablePublishers], scheduledPubsPerDayAndWeek, day, weekNr);
|
} else if (algType == 1) {
|
||||||
|
rankedPublishers = await RankPublishersForShiftWeighted([...availablePublishers], scheduledPubsPerDayAndWeek, day, weekNr);
|
||||||
|
}
|
||||||
if (rankedPublishers.length > 0) {
|
if (rankedPublishers.length > 0) {
|
||||||
const newAssignment = await prisma.assignment.create({
|
const newAssignment = await prisma.assignment.create({
|
||||||
data: {
|
data: {
|
||||||
@ -775,9 +781,12 @@ async function GenerateSchedule(axios, date, copyFromPreviousMonth = false, auto
|
|||||||
let availablePubsForTheShift = await data.filterPublishersNew('id,firstName,lastName,email,isActive,desiredShiftsPerMonth,lastLogin,type', shift.startTime, true, false, false, true, false);
|
let availablePubsForTheShift = await data.filterPublishersNew('id,firstName,lastName,email,isActive,desiredShiftsPerMonth,lastLogin,type', shift.startTime, true, false, false, true, false);
|
||||||
|
|
||||||
let availablePublishers = await FilterInappropriatePublishers([...availablePubsForTheShift], publishersToday, shift);
|
let availablePublishers = await FilterInappropriatePublishers([...availablePubsForTheShift], publishersToday, shift);
|
||||||
let rankedPublishers;
|
if (algType == 0) {
|
||||||
rankedPublishers = await RankPublishersForShiftOld([...availablePublishers], scheduledPubsPerDayAndWeek, day, weekNr);
|
rankedPublishers = await RankPublishersForShiftOld([...availablePublishers], scheduledPubsPerDayAndWeek, day, weekNr);
|
||||||
//rankedPublishers = await RankPublishersForShiftWeighted([...availablePublishers], scheduledPubsPerDayAndWeek, day, weekNr);
|
} else if (algType == 1) {
|
||||||
|
rankedPublishers = await RankPublishersForShiftWeighted([...availablePublishers], scheduledPubsPerDayAndWeek, day, weekNr);
|
||||||
|
}
|
||||||
|
|
||||||
if (rankedPublishers.length == 0) {
|
if (rankedPublishers.length == 0) {
|
||||||
console.log("No available publishers for shift " + shift.name);
|
console.log("No available publishers for shift " + shift.name);
|
||||||
} else if (rankedPublishers.length > 0) {
|
} else if (rankedPublishers.length > 0) {
|
||||||
@ -895,19 +904,6 @@ async function RankPublishersForShiftOld(publishers, scheduledPubsPerDayAndWeek,
|
|||||||
const nextDayKey = common.getISODateOnly(addDays(currentDay, i));
|
const nextDayKey = common.getISODateOnly(addDays(currentDay, i));
|
||||||
|
|
||||||
const penalty = [0.5, 0.7, 0.8, 0.85, 0.9, 0.95][i - 1]; // Penalties for +-1 to +-6 days
|
const penalty = [0.5, 0.7, 0.8, 0.85, 0.9, 0.95][i - 1]; // Penalties for +-1 to +-6 days
|
||||||
|
|
||||||
// if (scheduledPubsPerDayAndWeek[previousDayKey]?.some(pubId => pubId === a.id)) {
|
|
||||||
// adjustedCompletionA *= penalty;
|
|
||||||
// }
|
|
||||||
// if (scheduledPubsPerDayAndWeek[previousDayKey]?.some(pubId => pubId === b.id)) {
|
|
||||||
// adjustedCompletionB *= penalty;
|
|
||||||
// }
|
|
||||||
// if (scheduledPubsPerDayAndWeek[nextDayKey]?.some(pubId => pubId === a.id)) {
|
|
||||||
// adjustedCompletionA *= penalty;
|
|
||||||
// }
|
|
||||||
// if (scheduledPubsPerDayAndWeek[nextDayKey]?.some(pubId => pubId === b.id)) {
|
|
||||||
// adjustedCompletionB *= penalty;
|
|
||||||
// }
|
|
||||||
if (flattenRegistry(previousDayKey).includes(a.id)) {
|
if (flattenRegistry(previousDayKey).includes(a.id)) {
|
||||||
adjustedCompletionA *= penalty;
|
adjustedCompletionA *= penalty;
|
||||||
}
|
}
|
||||||
|
@ -420,10 +420,10 @@ export default function CalendarPage({ initialEvents, initialShifts }) {
|
|||||||
setActiveButton(null);
|
setActiveButton(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const generateShifts = async (buttonId, copyFromPrevious = false, autoFill = false, forDay?: Boolean | null) => {
|
const generateShifts = async (buttonId, copyFromPrevious = false, autoFill = false, forDay?: Boolean | null, type = 0) => {
|
||||||
try {
|
try {
|
||||||
setActiveButton(buttonId);
|
setActiveButton(buttonId);
|
||||||
const endpoint = `/api/shiftgenerate?action=generate&date=${common.getISODateOnly(value)}©FromPreviousMonth=${copyFromPrevious}&autoFill=${autoFill}&forDay=${forDay}`;
|
const endpoint = `/api/shiftgenerate?action=generate&date=${common.getISODateOnly(value)}©FromPreviousMonth=${copyFromPrevious}&autoFill=${autoFill}&forDay=${forDay}&type=${type}`;
|
||||||
const { shifts } = await axiosInstance.get(endpoint);
|
const { shifts } = await axiosInstance.get(endpoint);
|
||||||
toast.success('Готово!', { autoClose: 1000 });
|
toast.success('Готово!', { autoClose: 1000 });
|
||||||
setIsMenuOpen(false);
|
setIsMenuOpen(false);
|
||||||
@ -677,9 +677,12 @@ export default function CalendarPage({ initialEvents, initialShifts }) {
|
|||||||
<button className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 whitespace-nowrap" onClick={() => generateShifts("genCopy", true)}>
|
<button className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 whitespace-nowrap" onClick={() => generateShifts("genCopy", true)}>
|
||||||
{isLoading('genCopy') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fas fa-copy mr-2"></i>)}
|
{isLoading('genCopy') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fas fa-copy mr-2"></i>)}
|
||||||
копирай от миналия месец</button>
|
копирай от миналия месец</button>
|
||||||
<button className="block w-full px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 flex items-center" onClick={() => generateShifts("genDay", true, true)}>
|
<button className="block w-full px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 flex items-center" onClick={() => generateShifts("genDay", true, true, null, 0)}>
|
||||||
{isLoading('genDay') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fas fa-cogs mr-2"></i>)}
|
{isLoading('genDay') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fas fa-cogs mr-2"></i>)}
|
||||||
Генерирай смени </button>
|
Генерирай смени </button>
|
||||||
|
<button className="block w-full px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 flex items-center" onClick={() => generateShifts("genDay", true, true, null, 1)}>
|
||||||
|
{isLoading('genDay') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fas fa-cogs mr-2"></i>)}
|
||||||
|
Генерирай смени 2 </button>
|
||||||
<button className="block px-4 py-2 text-sm text-red-500 hover:bg-gray-100"
|
<button className="block px-4 py-2 text-sm text-red-500 hover:bg-gray-100"
|
||||||
onClick={() => openConfirmModal(
|
onClick={() => openConfirmModal(
|
||||||
'Сигурни ли сте че искате да изтриете ВСИЧКИ смени и назначения за месеца?',
|
'Сигурни ли сте че искате да изтриете ВСИЧКИ смени и назначения за месеца?',
|
||||||
|
Reference in New Issue
Block a user