public VaccinationSolution()

in use-cases/vaccination-scheduling/src/main/java/org/acme/vaccinationscheduler/domain/solver/VaccinationSolution.java [94:164]


    public VaccinationSolution(VaccinationSchedule schedule, DistanceCalculator distanceCalculator) {
        this.vaccineTypeList = schedule.getVaccineTypeList();
        this.vaccinationCenterList = schedule.getVaccinationCenterList();
        this.appointmentList = schedule.getAppointmentList();

        Function<Appointment, Triple<VaccinationCenter, LocalDateTime, VaccineType>> tripleFunction
                = (appointment) -> Triple.of(
                        appointment.getVaccinationCenter(),
                        appointment.getDateTime().truncatedTo(ChronoUnit.HOURS),
                        appointment.getVaccineType());
        Set<Appointment> scheduledAppointmentSet = schedule.getPersonList().stream()
                .map(Person::getAppointment)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        Map<Triple<VaccinationCenter, LocalDateTime, VaccineType>, List<Appointment>> appointmentListMap
                = schedule.getAppointmentList().stream()
                .collect(groupingBy(tripleFunction, LinkedHashMap::new, Collectors.collectingAndThen(
                        Collectors.toList(), subAppointmentList -> subAppointmentList.stream().sorted(
                                Comparator.comparing(Appointment::getDateTime).thenComparing(Appointment::getBoothId))
                                .collect(Collectors.toList()))));
        vaccinationSlotList = new ArrayList<>(appointmentListMap.size());
        Map<Triple<VaccinationCenter, LocalDateTime, VaccineType>, VaccinationSlot> vaccinationSlotMap = new HashMap<>(appointmentListMap.size());
        long nextVaccinationSlotId = 0;
        for (Map.Entry<Triple<VaccinationCenter, LocalDateTime, VaccineType>, List<Appointment>> entry : appointmentListMap.entrySet()) {
            Triple<VaccinationCenter, LocalDateTime, VaccineType> triple = entry.getKey();
            List<Appointment> appointmentList = entry.getValue();
            VaccinationCenter vaccinationCenter = triple.getLeft();
            LocalDateTime startDateTime = triple.getMiddle();
            VaccineType vaccineType = triple.getRight();
            List<Appointment> unscheduledAppointmentList = appointmentList.stream()
                    .filter(appointment -> !scheduledAppointmentSet.contains(appointment))
                    .collect(Collectors.toList());
            int capacity = appointmentList.size();
            VaccinationSlot vaccinationSlot = new VaccinationSlot(nextVaccinationSlotId++, vaccinationCenter,
                    startDateTime, vaccineType, unscheduledAppointmentList, capacity);
            vaccinationSlotList.add(vaccinationSlot);
            vaccinationSlotMap.put(triple, vaccinationSlot);
        }

        List<Person> personList = schedule.getPersonList();
        personAssignmentList = new ArrayList<>(personList.size());

        Location[] fromLocations = personList.stream().map(Person::getHomeLocation).toArray(Location[]::new);
        Location[] toLocations = vaccinationCenterList.stream().map(VaccinationCenter::getLocation).toArray(Location[]::new);
        // One single call to enable bulk mapping optimizations
        long[][] distanceMatrix = distanceCalculator.calculateBulkDistance(fromLocations, toLocations);
        for (int personIndex = 0; personIndex < personList.size(); personIndex++) {
            Person person = personList.get(personIndex);
            Map<VaccinationCenter, Long> distanceMap = new HashMap<>(vaccinationCenterList.size());
            for (int vaccinationCenterIndex = 0; vaccinationCenterIndex < vaccinationCenterList.size(); vaccinationCenterIndex++) {
                VaccinationCenter vaccinationCenter = vaccinationCenterList.get(vaccinationCenterIndex);
                long distance = distanceMatrix[personIndex][vaccinationCenterIndex];
                distanceMap.put(vaccinationCenter, distance);
            }
            PersonAssignment personAssignment = new PersonAssignment(person, distanceMap);
            Appointment appointment = person.getAppointment();
            // Person.appointment is non-null with pinned persons but maybe also with non-pinned persons from draft runs
            if (appointment != null) {
                VaccinationSlot vaccinationSlot = vaccinationSlotMap.get(tripleFunction.apply(appointment));
                if (vaccinationSlot == null) {
                    throw new IllegalStateException("The person (" + person
                            + ") has a pre-set appointment (" + appointment
                            + ") that is not part of the schedule's appointmentList with size ("
                            + schedule.getAppointmentList().size() + ")");
                }
                personAssignment.setVaccinationSlot(vaccinationSlot);
            }
            personAssignmentList.add(personAssignment);
        }
        this.score = schedule.getScore();
    }