feat(algo): skip day when candidates < slotsPerDay

This commit is contained in:
ferdi2go committed 2026-04-28 10:07:22 +00:00
1 parent 625f9c7037
commit 3d314e84fd
2 files changed
+39 -3

No files matched your search

+6 -3
View File
@@ -86,14 +86,17 @@ export function generatePlan(workdays, employees, history, randomFn = Math.rando
const candidates = employees.filter(e => const candidates = employees.filter(e =>
isEligible(e, date, monthAssignments, history) isEligible(e, date, monthAssignments, history)
); );
if (candidates.length === 0) continue;
if (candidates.length < slotsPerDay) {
skippedDates.push(date);
continue;
}
const scored = candidates const scored = candidates
.map(e => ({ employee: e, score: scoreCandidate(e, date, history, randomFn) })) .map(e => ({ employee: e, score: scoreCandidate(e, date, history, randomFn) }))
.sort((a, b) => b.score - a.score); .sort((a, b) => b.score - a.score);
const take = Math.min(slotsPerDay, scored.length); for (let i = 0; i < slotsPerDay; i++) {
for (let i = 0; i < take; i++) {
monthAssignments.push({ date, employeeId: scored[i].employee.id, manual: false }); monthAssignments.push({ date, employeeId: scored[i].employee.id, manual: false });
} }
} }
+33
View File
@@ -154,4 +154,37 @@ function emp(id, constraints = {}) {
} }
} }
// slotsPerDay=2 with only 1 eligible employee → day skipped, listed in skippedDates
{
const employees = [emp('alice')];
const result = generatePlan(['2026-04-01'], employees, [], fixed, 2);
assert.equal(result.assignments.length, 0, 'no assignments when candidates < slotsPerDay');
assert.deepEqual(result.skippedDates, ['2026-04-01'], 'date listed in skippedDates');
}
// slotsPerDay=1 with 0 candidates → still skipped, listed
{
// 2026-04-01 = Wednesday (3), only employee blocks Wednesday
const employees = [emp('alice', { neverDays: [3] })];
const result = generatePlan(['2026-04-01'], employees, [], fixed, 1);
assert.equal(result.assignments.length, 0, 'no assignments when 0 candidates');
assert.deepEqual(result.skippedDates, ['2026-04-01'], 'date listed in skippedDates');
}
// Mixed: some days fully assigned, some skipped
{
// 2026-04-01 = Wed, 2026-04-02 = Thu
// alice can only Wed, bob can always work
const employees = [
emp('alice', { onlyDays: [3] }),
emp('bob')
];
const result = generatePlan(['2026-04-01','2026-04-02'], employees, [], fixed, 2);
// 2026-04-01: 2 candidates → 2 entries
assert.equal(result.assignments.filter(a => a.date === '2026-04-01').length, 2, 'Wed has 2 entries');
// 2026-04-02: only bob → skipped
assert.equal(result.assignments.filter(a => a.date === '2026-04-02').length, 0, 'Thu skipped');
assert.deepEqual(result.skippedDates, ['2026-04-02'], 'Thu in skippedDates');
}
console.log('All algorithm tests passed.'); console.log('All algorithm tests passed.');