private VaccinationSlot findAvailableVaccinationSlot()

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;
    }