cp running successfull

This commit is contained in:
2025-10-19 21:10:03 +02:00
parent ce8182244d
commit 37f75727cc

View File

@@ -68,7 +68,7 @@ function buildSchedulingModel(model: CPModel, data: WorkerData): void {
}); });
}); });
// 4. Shift staffing constraints (RELAXED) // 4. Shift staffing constraints
shifts.forEach((shift: any) => { shifts.forEach((shift: any) => {
const assignmentVars = activeEmployees.map( const assignmentVars = activeEmployees.map(
(emp: any) => `assign_${emp.id}_${shift.id}` (emp: any) => `assign_${emp.id}_${shift.id}`
@@ -83,7 +83,7 @@ function buildSchedulingModel(model: CPModel, data: WorkerData): void {
); );
// Maximum workers // Maximum workers
const maxWorkers = shift.maxWorkers || 3; const maxWorkers = shift.maxWorkers || 2;
model.addConstraint( model.addConstraint(
`${assignmentVars.join(' + ')} <= ${maxWorkers}`, `${assignmentVars.join(' + ')} <= ${maxWorkers}`,
`Max workers for shift ${shift.id}` `Max workers for shift ${shift.id}`
@@ -122,17 +122,13 @@ function buildSchedulingModel(model: CPModel, data: WorkerData): void {
activeEmployees.forEach((employee: any) => { activeEmployees.forEach((employee: any) => {
const contractType = employee.contractType || 'large'; const contractType = employee.contractType || 'large';
// ADJUSTMENT: Make contract constraints feasible with available shifts // EXACT SHIFTS PER WEEK
let minShifts, maxShifts; let exactShifts;
if (contractType === 'small') { if (contractType === 'small') {
// Small contract: 1 shifts exactShifts = 1; // Exactly 1 shift for small contract
minShifts = 1;
maxShifts = Math.min(1, totalShifts);
} else { } else {
// Large contract: 2 shifts (2) exactShifts = 2; // Exactly 2 shifts for large contract
minShifts = 2;
maxShifts = Math.min(2, totalShifts);
} }
const shiftVars = shifts.map( const shiftVars = shifts.map(
@@ -140,18 +136,13 @@ function buildSchedulingModel(model: CPModel, data: WorkerData): void {
); );
if (shiftVars.length > 0) { if (shiftVars.length > 0) {
// Use range instead of exact number // Use EXACT constraint (== instead of range)
model.addConstraint( model.addConstraint(
`${shiftVars.join(' + ')} == ${minShifts}`, `${shiftVars.join(' + ')} == ${exactShifts}`,
`Expected shifts for ${employee.name} (${contractType} contract)` `Exact shifts for ${employee.name} (${contractType} contract)`
); );
model.addConstraint( console.log(`Employee ${employee.name}: ${exactShifts} shifts (${contractType})`);
`${shiftVars.join(' + ')} <= ${maxShifts}`,
`Max shifts for ${employee.name} (${contractType} contract)`
);
console.log(`Employee ${employee.name}: ${minShifts}-${maxShifts} shifts (${contractType})`);
} }
}); });
@@ -217,59 +208,21 @@ function extractAssignmentsFromSolution(solution: any, employees: any[], shifts:
employeeAssignments[employee.id] = 0; employeeAssignments[employee.id] = 0;
}); });
// METHOD 1: Try to use raw variables from solution // Python-parsed assignments
if (solution.variables) {
console.log('Using variable-based assignment extraction');
Object.entries(solution.variables).forEach(([varName, value]) => {
if (varName.startsWith('assign_') && value === 1) {
const parts = varName.split('_');
if (parts.length >= 3) {
const employeeId = parts[1];
const shiftId = parts.slice(2).join('_');
// Find the actual shift ID (handle generated IDs)
const actualShift = shifts.find(s =>
s.id === shiftId ||
`assign_${employeeId}_${s.id}` === varName
);
if (actualShift) {
if (!assignments[actualShift.id]) {
assignments[actualShift.id] = [];
}
assignments[actualShift.id].push(employeeId);
employeeAssignments[employeeId]++;
}
}
}
});
}
// METHOD 2: Fallback to parsed assignments from Python
if (solution.assignments && solution.assignments.length > 0) { if (solution.assignments && solution.assignments.length > 0) {
console.log('Using Python-parsed assignments'); console.log('Using Python-parsed assignments (cleaner)');
solution.assignments.forEach((assignment: any) => { solution.assignments.forEach((assignment: any) => {
const shiftId = assignment.shiftId; const shiftId = assignment.shiftId;
const employeeId = assignment.employeeId; const employeeId = assignment.employeeId;
if (shiftId && employeeId) { if (shiftId && employeeId && assignments[shiftId]) {
if (!assignments[shiftId]) { // Check if this assignment already exists to avoid duplicates
assignments[shiftId] = []; if (!assignments[shiftId].includes(employeeId)) {
}
assignments[shiftId].push(employeeId); assignments[shiftId].push(employeeId);
employeeAssignments[employeeId]++; employeeAssignments[employeeId]++;
} }
});
} }
// METHOD 3: Debug - log all variables to see what's available
if (Object.keys(assignments).length === 0 && solution.variables) {
console.log('Debug: First 10 variables from solution:');
const varNames = Object.keys(solution.variables).slice(0, 10);
varNames.forEach(varName => {
console.log(` ${varName} = ${solution.variables[varName]}`);
}); });
} }