private void applyVariables(
      VehicleRoutingSolution inputSolution, VehicleRoutingSolution varSolution) {
    List<Vehicle> inputVehicleList = inputSolution.getVehicleList();
    Map<Long, Vehicle> inputVehicleMap = new LinkedHashMap<Long, Vehicle>(inputVehicleList.size());
    for (Vehicle vehicle : inputVehicleList) {
      inputVehicleMap.put(vehicle.getId(), vehicle);
    }
    List<Customer> inputCustomerList = inputSolution.getCustomerList();
    Map<Long, Customer> inputCustomerMap =
        new LinkedHashMap<Long, Customer>(inputCustomerList.size());
    for (Customer customer : inputCustomerList) {
      inputCustomerMap.put(customer.getId(), customer);
    }

    for (Vehicle varVehicle : varSolution.getVehicleList()) {
      Vehicle inputVehicle = inputVehicleMap.get(varVehicle.getId());
      Customer varNext = varVehicle.getNextCustomer();
      inputVehicle.setNextCustomer(varNext == null ? null : inputCustomerMap.get(varNext.getId()));
    }
    for (Customer varCustomer : varSolution.getCustomerList()) {
      Customer inputCustomer = inputCustomerMap.get(varCustomer.getId());
      Standstill varPrevious = varCustomer.getPreviousStandstill();
      inputCustomer.setPreviousStandstill(
          varPrevious == null
              ? null
              : varPrevious instanceof Vehicle
                  ? inputVehicleMap.get(((Vehicle) varPrevious).getId())
                  : inputCustomerMap.get(((Customer) varPrevious).getId()));
      Customer varNext = varCustomer.getNextCustomer();
      inputCustomer.setNextCustomer(varNext == null ? null : inputCustomerMap.get(varNext.getId()));
    }
    ScoreDirector scoreDirector = scoreDirectorFactory.buildScoreDirector();
    scoreDirector.setWorkingSolution(inputSolution);
    scoreDirector.calculateScore();
  }
 @Override
 public HardSoftLongScore calculateScore(VehicleRoutingSolution solution, int initScore) {
   boolean timeWindowed = solution instanceof TimeWindowedVehicleRoutingSolution;
   List<Customer> customerList = solution.getCustomerList();
   List<Vehicle> vehicleList = solution.getVehicleList();
   Map<Vehicle, Integer> vehicleDemandMap = new HashMap<>(vehicleList.size());
   for (Vehicle vehicle : vehicleList) {
     vehicleDemandMap.put(vehicle, 0);
   }
   long hardScore = 0L;
   long softScore = 0L;
   for (Customer customer : customerList) {
     Standstill previousStandstill = customer.getPreviousStandstill();
     if (previousStandstill != null) {
       Vehicle vehicle = customer.getVehicle();
       vehicleDemandMap.put(vehicle, vehicleDemandMap.get(vehicle) + customer.getDemand());
       // Score constraint distanceToPreviousStandstill
       softScore -= customer.getDistanceFromPreviousStandstill();
       if (customer.getNextCustomer() == null) {
         // Score constraint distanceFromLastCustomerToDepot
         softScore -= customer.getLocation().getDistanceTo(vehicle.getLocation());
       }
       if (timeWindowed) {
         TimeWindowedCustomer timeWindowedCustomer = (TimeWindowedCustomer) customer;
         long dueTime = timeWindowedCustomer.getDueTime();
         Long arrivalTime = timeWindowedCustomer.getArrivalTime();
         if (dueTime < arrivalTime) {
           // Score constraint arrivalAfterDueTime
           hardScore -= (arrivalTime - dueTime);
         }
       }
     }
   }
   for (Map.Entry<Vehicle, Integer> entry : vehicleDemandMap.entrySet()) {
     int capacity = entry.getKey().getCapacity();
     int demand = entry.getValue();
     if (demand > capacity) {
       // Score constraint vehicleCapacity
       hardScore -= (demand - capacity);
     }
   }
   // Score constraint arrivalAfterDueTimeAtDepot is a build-in hard constraint in
   // VehicleRoutingImporter
   return HardSoftLongScore.valueOf(initScore, hardScore, softScore);
 }