in use-cases/vaccination-scheduling/src/main/java/org/acme/vaccinationscheduler/solver/optional/VaccinationCustomConstructionHeuristic.java [81:144]
private VaccinationSlot findAvailableVaccinationSlot(ScoreDirector<VaccinationSolution> scoreDirector,
Map<VaccinationCenter, Map<VaccineType, Map<LocalDate, Map<VaccinationSlot, Integer>>>> vaccinationCenterToSlotMap,
PersonAssignment person) {
// Iterate the nearest VaccinationCenters to the person first.
List<VaccinationCenter> vaccinationCenterList = vaccinationCenterToSlotMap.keySet().stream()
.sorted(Comparator
.comparing((VaccinationCenter vaccinationCenter) -> person.getRequiredVaccinationCenter() != vaccinationCenter)
.thenComparing((VaccinationCenter vaccinationCenter) -> person.getPreferredVaccinationCenter() != vaccinationCenter)
.thenComparing(person::getDistanceTo))
.collect(Collectors.toList());
for (VaccinationCenter vaccinationCenter : vaccinationCenterList) {
Map<VaccineType, Map<LocalDate, Map<VaccinationSlot, Integer>>> vaccineTypeToSlotMap
= vaccinationCenterToSlotMap.get(vaccinationCenter);
for (Map.Entry<VaccineType, Map<LocalDate, Map<VaccinationSlot, Integer>>> vaccineTypeEntry : vaccineTypeToSlotMap.entrySet()) {
VaccineType vaccineType = vaccineTypeEntry.getKey();
// Skip all slots with the wrong vaccineType
if (person.getRequiredVaccineType() != null && person.getRequiredVaccineType() != vaccineType) {
if (person.getRequiredVaccineType().getName().equals(vaccineType.getName())) {
throw new IllegalStateException("Don't have 2 VaccineType with the same name ("
+ vaccineType.getName() + ") instances in your input data.");
}
continue;
}
Map<LocalDate, Map<VaccinationSlot, Integer>> dateToSlotMap = vaccineTypeEntry.getValue();
List<LocalDate> dateList = dateToSlotMap.keySet().stream()
.filter(date -> {
// Skip all slots with an invalid date
long age = YEARS.between(person.getBirthdate(), date);
if (vaccineType.getMinimumAge() != null && age < vaccineType.getMinimumAge()) {
return false;
}
if (vaccineType.getMaximumAge() != null && age > vaccineType.getMaximumAge()) {
return false;
}
if (person.getReadyDate() != null && date.compareTo(person.getReadyDate()) < 0) {
return false;
}
if (person.getDueDate() != null && date.compareTo(person.getDueDate()) > 0) {
return false;
}
return true;
})
.sorted(person.getIdealDate() == null ? Comparator.naturalOrder()
: Comparator.<LocalDate, Long>comparing(date ->
Math.abs(DAYS.between(person.getIdealDate(), date))))
.collect(Collectors.toList());
for (LocalDate date : dateList) {
Map<VaccinationSlot, Integer> slotToAvailabilityMap = dateToSlotMap.get(date);
for (Map.Entry<VaccinationSlot, Integer> slotEntry : slotToAvailabilityMap.entrySet()) {
VaccinationSlot vaccinationSlot = slotEntry.getKey();
int availability = slotEntry.getValue();
reduceAvailability(vaccinationCenterToSlotMap, vaccinationCenter,
vaccineTypeToSlotMap, vaccineType,
dateToSlotMap, date,
slotToAvailabilityMap, vaccinationSlot,
availability);
return vaccinationSlot;
}
}
}
}
return null;
}