Deux postes en même temps possibles, malus dans le solveur
ci-cd / build-backend (push) Successful in 45s
ci-cd / build-frontend (push) Successful in 24s
ci-cd / deploy (push) Successful in 27s

Le chevauchement de créneaux (SHIFT_OVERLAP) n'est plus bloquant : il
remonte en avertissement et l'affectation est enregistrée. Le solveur ne
l'exclut plus mais applique un fort malus au bénévole déjà affecté
ailleurs au même moment (proposé seulement sous l'effectif minimal, faute
de mieux) ; il n'est jamais reproposé sur un créneau où il est déjà.
Même malus dans le classement par défaut du panneau et dans le mock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
AdamThomas
2026-10-25 10:38:52 +01:00
co-authored by Claude Opus 5.5
parent d0fa1e109c
commit 0f904f5e3d
11 changed files with 114 additions and 37 deletions
+13 -1
View File
@@ -134,6 +134,17 @@ export function AssignmentPanel({
return map;
}, [volunteers.data, artistsById, shift, positionId, assigned, effectiveCompanionIds]);
// Bénévoles déjà affectés à un autre créneau qui chevauche celui-ci.
const busyElsewhereIds = useMemo(() => {
const ids = new Set<string>();
for (const a of allAssignments.data ?? []) {
if (a.shift_id === shift.shift_id) continue;
const other = shiftsById.get(a.shift_id);
if (other && windowsOverlap(shift, other)) ids.add(a.volunteer_id);
}
return ids;
}, [allAssignments.data, shiftsById, shift]);
// Score de chance de chaque candidat pour CE créneau : vœu de poste,
// conflit avec un artiste qu'il veut voir, compagnons souhaités déjà présents, charge déjà assignée — c'est ce qui classe la
// liste, pas juste « le moins chargé ».
@@ -147,12 +158,13 @@ export function AssignmentPanel({
wishesPosition: details?.wishesPosition ?? false,
conflictsWishedArtist: details?.conflictsWishedArtist ?? false,
companionMatches: details?.companionMatches ?? 0,
busyElsewhere: busyElsewhereIds.has(v.id),
assignedHours: hours.get(v.id) ?? 0,
}),
);
}
return map;
}, [volunteers.data, detailsByVolunteer, hours]);
}, [volunteers.data, detailsByVolunteer, busyElsewhereIds, hours]);
const needle = foldAccents(search.trim());