public JsonVehicleRoutingSolution convertToJsonVehicleRoutingSolution(
     VehicleRoutingSolution solution) {
   JsonVehicleRoutingSolution jsonSolution = new JsonVehicleRoutingSolution();
   jsonSolution.setName(solution.getName());
   List<JsonCustomer> jsonCustomerList =
       new ArrayList<JsonCustomer>(solution.getCustomerList().size());
   for (Customer customer : solution.getCustomerList()) {
     Location customerLocation = customer.getLocation();
     jsonCustomerList.add(
         new JsonCustomer(
             customerLocation.getId(),
             customerLocation.getName(),
             customerLocation.getLatitude(),
             customerLocation.getLongitude(),
             customer.getDemand()));
   }
   jsonSolution.setCustomerList(jsonCustomerList);
   List<JsonVehicleRoute> jsonVehicleRouteList =
       new ArrayList<JsonVehicleRoute>(solution.getVehicleList().size());
   TangoColorFactory tangoColorFactory = new TangoColorFactory();
   for (Vehicle vehicle : solution.getVehicleList()) {
     JsonVehicleRoute jsonVehicleRoute = new JsonVehicleRoute();
     Location depotLocation = vehicle.getDepot().getLocation();
     jsonVehicleRoute.setId(vehicle.getId());
     jsonVehicleRoute.setDepotLocationName(depotLocation.getName());
     jsonVehicleRoute.setDepotLatitude(depotLocation.getLatitude());
     jsonVehicleRoute.setDepotLongitude(depotLocation.getLongitude());
     jsonVehicleRoute.setCapacity(vehicle.getCapacity());
     Color color = tangoColorFactory.pickColor(vehicle);
     jsonVehicleRoute.setHexColor(
         String.format("#%02x%02x%02x", color.getRed(), color.getGreen(), color.getBlue()));
     Customer customer = vehicle.getNextCustomer();
     int demandTotal = 0;
     List<JsonCustomer> jsonVehicleCustomerList = new ArrayList<JsonCustomer>();
     while (customer != null) {
       Location customerLocation = customer.getLocation();
       demandTotal += customer.getDemand();
       jsonVehicleCustomerList.add(
           new JsonCustomer(
               customerLocation.getId(),
               customerLocation.getName(),
               customerLocation.getLatitude(),
               customerLocation.getLongitude(),
               customer.getDemand()));
       customer = customer.getNextCustomer();
     }
     jsonVehicleRoute.setDemandTotal(demandTotal);
     jsonVehicleRoute.setCustomerList(jsonVehicleCustomerList);
     jsonVehicleRouteList.add(jsonVehicleRoute);
   }
   jsonSolution.setVehicleRouteList(jsonVehicleRouteList);
   HardSoftLongScore score = solution.getScore();
   jsonSolution.setFeasible(score != null && score.isFeasible());
   jsonSolution.setDistance(solution.getDistanceString(NUMBER_FORMAT));
   return jsonSolution;
 }
  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);
 }