feat(algo): skip day when candidates < slotsPerDay
This commit is contained in:
1 parent
625f9c7037
commit
3d314e84fd
2 files changed
+39
-3
No files matched your search
+6
-3
@@ -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 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.');
|
||||||
Reference in new issue
Block a user