delete generated code

This commit is contained in:
Dobromir Popov
2024-06-26 10:13:53 +03:00
parent 19a8963a2e
commit 2cd50bd34f
2 changed files with 5 additions and 228 deletions

View File

@ -46,7 +46,8 @@ const ProtectedRoute = ({ children, allowedRoles, deniedMessage, bypass = false,
<div className="flex items-center justify-center min-h-screen">
<div className="text-center">
<h1 className="text-2xl font-bold mb-4 text-blue-500">{session?.user?.email},</h1>
<p className="mb-6">{`Нямате достъп до тази страница. Ако мислите, че това е грешка, моля, свържете се с администраторите`}</p>
<p className="mb-6">{`Нямате достъп до тази страница.`}</p>
<p className="mb-6">{`Ако мислите, че това е грешка, моля, свържете се с администраторите`}</p>
</div>
</div>
</>);

View File

@ -871,230 +871,6 @@ async function ImportShiftsFromDocx(axios: Axios) {
}
async function GenerateOptimalSchedule(axios, date, copyFromPreviousMonth = false, autoFill = false, forDay) {
const prisma = common.getPrismaClient();
try {
const monthInfo = common.getMonthDatesInfo(new Date(date));
const lastMonthInfo = common.getMonthDatesInfo(new Date(monthInfo.date.getFullYear(), monthInfo.date.getMonth() - 1, 1));
if (forDay) {
await DeleteShiftsForDay(monthInfo.date);
} else {
await DeleteShiftsForMonth(monthInfo);
}
const events = await prisma.cartEvent.findMany({
where: {
isActive: true
}
});
let shiftsLastMonth = await getShiftsFromLastMonth(lastMonthInfo);
let publishers = await data.getAllPublishersWithStatisticsMonth(date, false, false);
let day = new Date(monthInfo.firstMonday);
let endDate = monthInfo.lastSunday;
let weekNr = 1;
if (forDay) {
day = monthInfo.date;
endDate = new Date(monthInfo.date.getTime() + 86400000); // +1 day
weekNr = common.getWeekNumber(monthInfo.date);
}
let allShifts = [];
// First pass: Generate shifts and copy assignments from the previous month
while (day < endDate) {
let dayShifts = await generateShiftsForDay(day, events, shiftsLastMonth, weekNr, copyFromPreviousMonth);
allShifts = [...allShifts, ...dayShifts];
day.setDate(day.getDate() + 1);
if (common.DaysOfWeekArray[day.getDayEuropean()] === DayOfWeek.Sunday) {
weekNr++;
}
if (forDay) break;
}
// Second pass: Optimize assignments
allShifts = await optimizeAssignments(allShifts, publishers, events);
// Save optimized shifts to the database
for (let shift of allShifts) {
await saveShiftToDB(shift);
}
return {};
} catch (error) {
console.log(error);
return { error: error };
}
}
async function generateShiftsForDay(day, events, shiftsLastMonth, weekNr, copyFromPreviousMonth) {
const prisma = common.getPrismaClient();
let dayShifts = [];
let dayOfWeekEnum = common.getDayOfWeekNameEnEnumForDate(day);
let dayName = common.DaysOfWeekArray[day.getDayEuropean()];
const event = events.find((event) => event.dayofweek == dayName && (event.dayOfMonth == null || event.dayOfMonth == day.getDate()));
if (!event) return dayShifts;
let startTime = new Date(day);
startTime.setHours(event.startTime.getHours(), event.startTime.getMinutes());
let endTime = new Date(day);
endTime.setHours(event.endTime.getHours(), event.endTime.getMinutes());
let shiftStart = new Date(startTime);
let shiftEnd = new Date(startTime);
shiftEnd.setMinutes(shiftStart.getMinutes() + event.shiftDuration);
let shiftNr = 0;
while (shiftEnd <= endTime) {
shiftNr++;
let isTransportRequired = shiftNr == 1 || shiftEnd.getTime() == endTime.getTime();
let shift = {
startTime: new Date(shiftStart),
endTime: new Date(shiftEnd),
name: `${event.dayofweek} ${shiftStart.toLocaleTimeString()} - ${shiftEnd.toLocaleTimeString()}`,
requiresTransport: isTransportRequired,
cartEventId: event.id,
assignments: [],
};
if (copyFromPreviousMonth) {
const shiftLastMonthSameDay = findTheSameShiftFromLastMonth(shiftsLastMonth, day, weekNr, shiftNr);
if (shiftLastMonthSameDay) {
shift.assignments = shiftLastMonthSameDay.assignments
.map(a => ({
publisherId: a.publisher.id,
isConfirmed: true,
isWithTransport: a.isWithTransport
}));
}
}
dayShifts.push(shift);
shiftStart = new Date(shiftEnd);
shiftEnd.setMinutes(shiftStart.getMinutes() + event.shiftDuration);
}
return dayShifts;
}
async function optimizeAssignments(allShifts, publishers, events) {
let scheduledPubsPerDayAndWeek = {};
for (let shift of allShifts) {
const event = events.find(e => e.id === shift.cartEventId);
const day = new Date(shift.startTime);
const weekNr = common.getWeekNumber(day);
let availablePubs = await getAvailablePublishersForShiftNew(shift.startTime, shift.endTime, publishers, []);
availablePubs = filterPublishersForShift(availablePubs, shift, scheduledPubsPerDayAndWeek, day, weekNr);
while (shift.assignments.length < event.numberOfPublishers && availablePubs.length > 0) {
const rankedPubs = rankPublishersForShift(availablePubs, scheduledPubsPerDayAndWeek, day, weekNr);
const selectedPub = rankedPubs[0];
shift.assignments.push({
publisherId: selectedPub.id,
isConfirmed: true,
isWithTransport: shift.requiresTransport && (selectedPub.isWithTransportIn || selectedPub.isWithTransportOut)
});
updateRegistry(selectedPub.id, day, weekNr, scheduledPubsPerDayAndWeek);
selectedPub.currentMonthAssignments++;
availablePubs = availablePubs.filter(p => p.id !== selectedPub.id);
}
}
return allShifts;
}
function filterPublishersForShift(publishers, shift, scheduledPubsPerDayAndWeek, day, weekNr) {
const dayKey = common.getISODateOnly(day);
return publishers.filter(p => {
const isNotAssigned = !shift.assignments.some(a => a.publisherId === p.id);
const isNotAssignedToday = !flattenRegistry(scheduledPubsPerDayAndWeek[dayKey]).includes(p.id);
const isNotOverAssigned = p.currentMonthAssignments < p.desiredShiftsPerMonth;
const isNotAssignedThisWeek = !Object.keys(scheduledPubsPerDayAndWeek)
.filter(key => common.getWeekNumber(new Date(key)) === weekNr)
.some(key => flattenRegistry(scheduledPubsPerDayAndWeek[key]).includes(p.id));
return isNotAssigned && isNotAssignedToday && isNotOverAssigned && isNotAssignedThisWeek;
});
}
function rankPublishersForShift(publishers, scheduledPubsPerDayAndWeek, currentDay, currentWeekNr) {
const weights = {
gender: 2,
desiredCompletion: 3,
availability: 2,
lastMonthCompletion: 3,
currentAssignments: 1
};
const totalWeight = Object.values(weights).reduce((acc, val) => acc + val, 0);
Object.keys(weights).forEach(key => {
weights[key] /= totalWeight;
});
publishers.forEach(p => {
p.score = calculatePublisherScore(p, weights, scheduledPubsPerDayAndWeek, currentDay, currentWeekNr);
});
return publishers.sort((a, b) => b.score - a.score);
}
function calculatePublisherScore(publisher, weights, scheduledPubsPerDayAndWeek, currentDay, currentWeekNr) {
let score = (publisher.isMale ? weights.gender : 0) -
((publisher.currentMonthAssignments / publisher.desiredShiftsPerMonth) * weights.desiredCompletion) +
((1 - publisher.currentMonthAvailabilityHoursCount / 24) * weights.availability) +
((publisher.previousMonthAssignments / publisher.currentMonthAssignments) * weights.lastMonthCompletion) -
(publisher.currentMonthAssignments * weights.currentAssignments);
// Apply penalties for nearby assignments
for (let i = 1; i <= 6; i++) {
const previousDayKey = 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];
if (flattenRegistry(scheduledPubsPerDayAndWeek[previousDayKey]).includes(publisher.id) ||
flattenRegistry(scheduledPubsPerDayAndWeek[nextDayKey]).includes(publisher.id)) {
score *= penalty;
}
}
return score;
}
async function saveShiftToDB(shift) {
const prisma = common.getPrismaClient();
await prisma.shift.create({
data: {
startTime: shift.startTime,
endTime: shift.endTime,
name: shift.name,
requiresTransport: shift.requiresTransport,
cartEvent: {
connect: {
id: shift.cartEventId,
},
},
assignments: {
create: shift.assignments.map(a => ({
publisher: {
connect: { id: a.publisherId }
},
isWithTransport: a.isWithTransport,
isConfirmed: a.isConfirmed,
isBySystem: true,
})),
},
},
});
}
// *********************************************************************************************************************
//region helpers
// *********************************************************************************************************************