/**
   * By applying a routing algorithm (e.g. shortest path or OSM-extraction) route from station to
   * station for each pt-line.
   *
   * <p>Writes the resulting schedule into this.schedule.
   */
  protected void createPTRoutes() {
    log.info("Creating pt routes...");

    Counter counter = new Counter("route # ");
    this.router = new PTLRFastAStarLandmarksSimpleRouting(this.network);
    for (TransitLine line : this.schedule.getTransitLines().values()) {
      for (TransitRoute route : line.getRoutes().values()) {
        counter.incCounter();
        assignRoute(route);
      }
    }
    counter.printCounter();

    log.info("  Add artificial links and nodes...");
    for (ArtificiallyConnectedStopFacility newFacility :
        artificiallyConnectedStopFacilities.values()) {
      this.network.addNode(newFacility.myNode);
    }
    for (ArtificiallyConnectedStopFacility newFacility :
        artificiallyConnectedStopFacilities.values()) {
      this.network.addLink(newFacility.myLink);
      for (Link newLink : newFacility.getLinks()) {
        this.network.addLink(newLink);
      }
    }
    for (Link newLink : artificiallyAddedLinks.values()) {
      this.network.addLink(newLink);
    }
    log.info("  Add artificial links and nodes... done.");

    log.info("Creating pt routes... done.");
  }
 private void cleanSchedule() {
   for (TransitLine line : this.schedule.getTransitLines().values()) {
     Set<TransitRoute> toRemove = new HashSet<>();
     for (TransitRoute transitRoute : line.getRoutes().values()) {
       boolean removeRoute = false;
       NetworkRoute networkRoute = transitRoute.getRoute();
       if (networkRoute.getStartLinkId() == null || networkRoute.getEndLinkId() == null) {
         removeRoute = true;
       }
       for (Id<Link> linkId : transitRoute.getRoute().getLinkIds()) {
         if (linkId == null) {
           removeRoute = true;
         }
       }
       if (removeRoute) {
         log.error(
             "NetworkRoute for " + transitRoute.getId().toString() + " incomplete. Remove route.");
         toRemove.add(transitRoute);
       }
     }
     if (!toRemove.isEmpty()) {
       for (TransitRoute transitRoute : toRemove) {
         line.removeRoute(transitRoute);
       }
     }
   }
 }
 public WaitTimeCalculatorSerializable(
     final TransitSchedule transitSchedule, final int timeSlot, final int totalTime) {
   this.timeSlot = timeSlot;
   for (TransitLine line : transitSchedule.getTransitLines().values())
     for (TransitRoute route : line.getRoutes().values()) {
       double[] sortedDepartures = new double[route.getDepartures().size()];
       int d = 0;
       for (Departure departure : route.getDepartures().values())
         sortedDepartures[d++] = departure.getDepartureTime();
       Arrays.sort(sortedDepartures);
       Map<String, WaitTimeData> stopsMap = new HashMap<String, WaitTimeData>(100);
       Map<String, double[]> stopsScheduledMap = new HashMap<String, double[]>(100);
       for (TransitRouteStop stop : route.getStops()) {
         stopsMap.put(
             stop.getStopFacility().getId().toString(),
             new WaitTimeDataArray((int) (totalTime / timeSlot) + 1));
         double[] cacheWaitTimes = new double[(int) (totalTime / timeSlot) + 1];
         for (int i = 0; i < cacheWaitTimes.length; i++) {
           double endTime = timeSlot * (i + 1);
           if (endTime > 24 * 3600) endTime -= 24 * 3600;
           cacheWaitTimes[i] = Time.UNDEFINED_TIME;
           SORTED_DEPARTURES:
           for (double departure : sortedDepartures) {
             double arrivalTime =
                 departure
                     + (stop.getArrivalOffset() != Time.UNDEFINED_TIME
                         ? stop.getArrivalOffset()
                         : stop.getDepartureOffset());
             if (arrivalTime >= endTime) {
               cacheWaitTimes[i] = arrivalTime - endTime;
               break SORTED_DEPARTURES;
             }
           }
           if (cacheWaitTimes[i] == Time.UNDEFINED_TIME)
             cacheWaitTimes[i] =
                 sortedDepartures[0]
                     + 24 * 3600
                     + (stop.getArrivalOffset() != Time.UNDEFINED_TIME
                         ? stop.getArrivalOffset()
                         : stop.getDepartureOffset())
                     - endTime;
         }
         stopsScheduledMap.put(stop.getStopFacility().getId().toString(), cacheWaitTimes);
       }
       Tuple<String, String> key =
           new Tuple<String, String>(line.getId().toString(), route.getId().toString());
       waitTimes.put(key, stopsMap);
       scheduledWaitTimes.put(key, stopsScheduledMap);
     }
 }
 private void removeNonUsedStopFacilities() {
   // Collect all used stop facilities:
   Set<Id<TransitStopFacility>> usedStopFacilities = new HashSet<>();
   for (TransitLine line : this.schedule.getTransitLines().values()) {
     for (TransitRoute route : line.getRoutes().values()) {
       for (TransitRouteStop stop : route.getStops()) {
         usedStopFacilities.add(stop.getStopFacility().getId());
       }
     }
   }
   // Check all stop facilities if not used:
   Set<TransitStopFacility> unusedStopFacilites = new HashSet<>();
   for (Id<TransitStopFacility> facilityId : this.schedule.getFacilities().keySet()) {
     if (!usedStopFacilities.contains(facilityId)) {
       unusedStopFacilites.add(this.schedule.getFacilities().get(facilityId));
     }
   }
   // Remove all stop facilities not used:
   for (TransitStopFacility facility : unusedStopFacilites) {
     this.schedule.removeStopFacility(facility);
   }
 }
 /**
  * Add to any link that is passed by any route a "pt" in the modes, if it hasn't already one...
  */
 private void prepareNetwork() {
   Map<Id<Link>, ? extends Link> networkLinks = network.getLinks();
   Set<Id<Link>> transitLinks = new HashSet<>();
   for (TransitLine line : this.schedule.getTransitLines().values()) {
     for (TransitRoute transitRoute : line.getRoutes().values()) {
       NetworkRoute networkRoute = transitRoute.getRoute();
       transitLinks.add(networkRoute.getStartLinkId());
       for (Id<Link> linkId : transitRoute.getRoute().getLinkIds()) {
         transitLinks.add(linkId);
       }
       transitLinks.add(networkRoute.getEndLinkId());
     }
   }
   for (Id<Link> transitLinkId : transitLinks) {
     Link transitLink = networkLinks.get(transitLinkId);
     if (!transitLink.getAllowedModes().contains(TransportMode.pt)) {
       Set<String> modes = new HashSet<>();
       modes.addAll(transitLink.getAllowedModes());
       modes.add(TransportMode.pt);
       transitLink.setAllowedModes(modes);
     }
   }
 }