private void setRandomTripMode(final Trip trip, final Plan plan, boolean ffcard, boolean owcard) {

    // carsharing is the new trip
    if (possibleModes.length == 2) {
      if (rng.nextBoolean()) {
        if (owcard)
          TripRouter.insertTrip(
              plan,
              trip.getOriginActivity(),
              Collections.singletonList(new LegImpl("onewaycarsharing")),
              trip.getDestinationActivity());
      } else {
        if (ffcard)
          TripRouter.insertTrip(
              plan,
              trip.getOriginActivity(),
              Collections.singletonList(new LegImpl("freefloating")),
              trip.getDestinationActivity());
      }
    } else if (possibleModes.length == 1 && possibleModes[0] != null) {
      if ((possibleModes[0].equals("freefloating") && ffcard)
          || (possibleModes[0].equals("onewaycarsharing") && owcard))
        TripRouter.insertTrip(
            plan,
            trip.getOriginActivity(),
            Collections.singletonList(new LegImpl(possibleModes[0])),
            trip.getDestinationActivity());
    } else
      TripRouter.insertTrip(
          plan, trip.getOriginActivity(), trip.getTripElements(), trip.getDestinationActivity());
  }
  @Override
  public TripRouter instantiateAndConfigureTripRouter(RoutingContext routingContext) {

    TripRouter instance = this.delegateFactory.instantiateAndConfigureTripRouter(routingContext);

    Network network = this.scenario.getNetwork();
    PopulationFactory populationFactory = this.scenario.getPopulation().getFactory();
    ModeRouteFactory modeRouteFactory =
        ((PopulationFactoryImpl) populationFactory).getModeRouteFactory();

    MultiModalConfigGroup multiModalConfigGroup =
        (MultiModalConfigGroup) scenario.getConfig().getModule(MultiModalConfigGroup.GROUP_NAME);
    Set<String> simulatedModes =
        CollectionUtils.stringToSet(multiModalConfigGroup.getSimulatedModes());
    for (String mode : simulatedModes) {

      if (instance.getRegisteredModes().contains(mode)) {
        log.warn("A routing algorithm for " + mode + " is already registered. It is replaced!");
      }

      TravelTime travelTime = this.multimodalTravelTimes.get(mode);
      if (travelTime == null) {
        throw new RuntimeException(
            "No travel time object was found for mode " + mode + "! Aborting.");
      }

      Network subNetwork = multimodalSubNetworks.get(mode);
      if (subNetwork == null) {
        subNetwork = NetworkImpl.createNetwork();
        Set<String> restrictions = new HashSet<>();
        restrictions.add(mode);
        TransportModeNetworkFilter networkFilter = new TransportModeNetworkFilter(network);
        networkFilter.filter(subNetwork, restrictions);
        this.multimodalSubNetworks.put(mode, subNetwork);
      }

      /*
       * We cannot use the travel disutility object from the routingContext since it
       * has not been created for the modes used here.
       */
      TravelDisutility travelDisutility =
          this.travelDisutilityFactory.createTravelDisutility(
              travelTime, scenario.getConfig().planCalcScore());
      LeastCostPathCalculator routeAlgo =
          this.leastCostPathCalculatorFactory.createPathCalculator(
              subNetwork, travelDisutility, travelTime);
      RoutingModule legRouterWrapper =
          DefaultRoutingModules.createNetworkRouter(mode, populationFactory, subNetwork, routeAlgo);
      instance.setRoutingModule(mode, legRouterWrapper);
    }

    return instance;
  }
  @Override
  public PlanAlgorithm getPlanAlgoInstance() {
    final TripRouter tripRouter = tripRouterProvider.get();
    ChooseActivityToInsert algo =
        new ChooseActivityToInsert(
            MatsimRandom.getLocalInstance(),
            tripRouter.getStageActivityTypes(),
            this.scenario,
            shopFacilityQuadTree,
            leisureFacilityQuadTree);

    return algo;
  }
  @Override
  public TripRouter instantiateAndConfigureTripRouter(RoutingContext routingContext) {
    // TODO Auto-generated method stub

    final TripRouter router = delegate.instantiateAndConfigureTripRouter(routingContext);

    // add our module to the instance
    router.setRoutingModule("movingpathways", new AAMRoutingModule(this.scenario));

    /*
    router.setRoutingModule(TransportMode.pt,
    		new TransitMultiModalAccessRoutingModule(
    				scenario,
    				new InitialNodeRouter(
    					router.getRoutingModule( "movingpathways" ),
    					scenario.getConfig().transitRouter().getSearchRadius(),
    					1,
    					scoringParams )

    				) );

    */
    final MainModeIdentifier defaultModeIdentifier = router.getMainModeIdentifier();
    router.setMainModeIdentifier(
        new MainModeIdentifier() {
          @Override
          public String identifyMainMode(final List<? extends PlanElement> tripElements) {
            boolean hadMovingPathway = false;
            for (PlanElement pe : tripElements) {
              if (pe instanceof Leg) {
                final Leg l = (Leg) pe;
                if (l.getMode().equals("movingpathways")) {
                  hadMovingPathway = true;
                }
                if (l.getMode().equals(TransportMode.transit_walk)) {
                  return TransportMode.pt;
                }
              }
            }

            if (hadMovingPathway) {
              // there were bike sharing legs but no transit walk
              return "movingpathways";
            }

            return defaultModeIdentifier.identifyMainMode(tripElements);
          }
        });

    return router;
  }
  // package protected for tests
  final void removePassengerTrip(final JointTrip toRemove, final JointPlan jointPlan) {
    final Plan passengerPlan = jointPlan.getIndividualPlan(toRemove.getPassengerId());

    final Trip tripWithLeg =
        getTripWithLeg(passengerPlan, toRemove.getPassengerLeg(), stagesWithJointTypes);

    TripRouter.insertTrip(
        passengerPlan,
        tripWithLeg.getOriginActivity(),
        Collections.singletonList(PopulationUtils.createLeg(TransportMode.pt)),
        tripWithLeg.getDestinationActivity());
  }
  private Alternative<ModeNests> calcAlternative(
      final int i,
      final String mode,
      final ActivityFacility origin,
      final ActivityFacility destination,
      final Person person) {
    final Trip trip =
        new Trip(
            origin, router.calcRoute(mode, origin, destination, 12 * 3600, person), destination);

    return new Alternative<>(
        ModeNests.valueOf(mode), Id.create(i + "_" + mode, Alternative.class), trip);
  }
  @Override
  public TripRouter get() {
    final TripRouter tripRouter = defaultFactory.get();

    final TransitRouterWrapper routingModule =
        new TransitRouterWrapper(
            transitRouterFactory.get(),
            scenario.getTransitSchedule(),
            scenario.getNetwork(), // use a walk router in case no PT path is found
            DefaultRoutingModules.createTeleportationRouter(
                TransportMode.transit_walk,
                scenario.getPopulation().getFactory(),
                scenario
                    .getConfig()
                    .plansCalcRoute()
                    .getModeRoutingParams()
                    .get(TransportMode.walk)));

    tripRouter.setRoutingModule(TransportMode.pt, routingModule);

    return tripRouter;
  }
  private void repareDriverTrips(final JointTrip toRemove, final JointPlan plan) {
    final List<TripStructureUtils.Trip> subtrips =
        getDriverTrip(toRemove, plan.getIndividualPlan(toRemove.getDriverId()));
    final List<PlanElement> newTrip = new ArrayList<PlanElement>();
    newTrip.add(PopulationUtils.createLeg(TransportMode.car));

    // "state" variables, changed in the loop:
    // - keeps track of the passengers currently in the vehicle.
    //   Pick-up or drop-offs are created at each change
    Set<Id> currentPassengers = Collections.<Id>emptySet();
    for (TripStructureUtils.Trip subtrip : subtrips) {
      final Leg leg = getDriverLegIfItIs(subtrip);
      final Route route = leg == null ? null : leg.getRoute();

      final Set<Id> newPassengers =
          route != null
              ? new HashSet<Id>(((DriverRoute) route).getPassengersIds())
              : Collections.<Id>emptySet();
      // note that no check of the mode is done...
      if (!newPassengers.equals(currentPassengers)) {
        newTrip.add(
            PopulationUtils.createActivityFromLinkId(
                JointActingTypes.INTERACTION,
                route != null ? route.getStartLinkId() : subtrip.getOriginActivity().getLinkId()));

        // as the spatial structure of the trip is modified, it is possible
        // that some pre-existing subtours are removed. Thus, a driver that may
        // have walked to a pick up (because at the same location as its departure)
        // may then have to drive to pick up the second passenger directly if
        // the first passenger was removed. Setting all non-driver legs
        // to car ensures to have a consistent mode chain.
        // XXX It could be done in a smarter way, so that if no subtour is removed, no modification
        // is done
        // For instance, when removing an "intern" trip, first PU and last DO are
        // left untouched, and thus access and egress leg need not be touched.
        newTrip.add(leg != null ? leg : PopulationUtils.createLeg(TransportMode.car));
        currentPassengers = newPassengers;
      }
    }

    TripRouter.insertTrip(
        plan.getIndividualPlan(toRemove.getDriverId()),
        subtrips.get(0).getOriginActivity(),
        newTrip,
        subtrips.get(subtrips.size() - 1).getDestinationActivity());
  }
  private boolean microRouteCurrentLegRoute(
      Leg leg,
      Person person,
      int currentLinkIndex,
      double time,
      Network network,
      TripRouter tripRouter,
      Random random,
      Plan plan) {

    Route route = leg.getRoute();

    // if the route type is not supported (e.g., because it is a walking agent)
    if (!(route instanceof NetworkRoute)) return false;

    if (random.nextFloat() > 0.3) return false; // only 30% replanners

    PersonImpl p = (PersonImpl) person;
    int legnr = plan.getPlanElements().indexOf(leg);

    //	logger.warn(legnr);

    if (p.getAge() == legnr) {
      //		logger.error("agent already replanned");
      //		return false; // agent has been replanned already
    } else {
      //		p.setAge(legnr);
    }

    NetworkRoute oldRoute = (NetworkRoute) route;

    /*
     *  Get the Id of the current Link.
     *  Create a List that contains all links of a route, including the Start- and EndLinks.
     */
    List<Id<Link>> allLinkIds = getRouteLinkIds(oldRoute); //

    int links2go = allLinkIds.size() - (currentLinkIndex + 1); //

    if (links2go >= 3) {
      Id<Link> startLink = allLinkIds.get(0);
      Id<Link> endLink = allLinkIds.get(allLinkIds.size() - 1);

      // The linkIds of the new Route ---------------------------
      List<Id<Link>> linkIds = new ArrayList<Id<Link>>();
      // start of the old route
      linkIds.addAll(allLinkIds.subList(1, currentLinkIndex)); // currentLinkIndex exclusive

      // micro-reroute part of route ---------------------------
      Id<Link> currentLinkId = allLinkIds.get(currentLinkIndex); // link 1, currentLinkIndex = 1
      Link fromLink = network.getLinks().get(currentLinkId);

      int jump = random.nextInt(links2go - 2) + 2; // start with 2
      int toLinkIndex = (currentLinkIndex + jump); // jump over one link //
      Id<Link> toLinkId = allLinkIds.get(toLinkIndex); //
      Link toLink = network.getLinks().get(toLinkId); //

      Facility<ActivityFacility> fromFacility = new LinkWrapperFacility(fromLink);
      Facility<ActivityFacility> toFacility = new LinkWrapperFacility(toLink);

      List<? extends PlanElement> planElements =
          tripRouter.calcRoute(leg.getMode(), fromFacility, toFacility, time, person); //

      if (planElements.size() != 1) {
        throw new RuntimeException(
            "Expected a list of PlanElements containing exactly one element, "
                + "but the returned list contained "
                + planElements.size()
                + " elements.");
      }
      Leg newLeg = (Leg) planElements.get(0);
      Route newRoute = newLeg.getRoute();
      linkIds.addAll(getRouteLinkIds(newRoute)); // currentLinkIndex => startLink

      // remainder of the old route ---------------------------
      if (toLinkIndex + 1 < allLinkIds.size() - 1) { // if route is not yet finished:
        linkIds.addAll(allLinkIds.subList(toLinkIndex + 1, allLinkIds.size() - 1));
      }

      // Overwrite old Route
      if (linkIds.size() > 2 && toLinkId.compareTo(fromLink.getId()) != 0) {
        List<Id<Link>> middleLinks = linkIds.subList(0, linkIds.size()); // to is exclusive

        //				String str = oldRoute.toString();
        //				int lo = oldRoute.getLinkIds().size();

        oldRoute.setLinkIds(startLink, middleLinks, endLink);

        //				if (oldRoute.getLinkIds().size() != lo) {
        //					logger.info(person.getId() + " :" + str + "\n" +
        //							oldRoute.toString());
        //				}
      } // else do not replace route
    }
    return true;
  }
  private void initializeFreeFLoatingParkingCarLeg(double now) {
    this.state = MobsimAgent.State.LEG;

    PlanElement pe = this.getCurrentPlanElement();

    Leg leg = (Leg) pe;
    Route route = leg.getRoute();

    // create route for the car part of the freefloating trip
    parkingSpot =
        parkingModule.parkFreeFloatingVehicle(
            Id.create(vehID, Vehicle.class),
            this.scenario.getNetwork().getLinks().get(route.getEndLinkId()).getCoord(),
            this.person.getId(),
            now);

    double travelTime = 0.0;
    List<Id<Link>> ids = new ArrayList<Id<Link>>();

    Provider<TripRouter> tripRouterFactory = controler.getTripRouterProvider();

    TripRouter tripRouter = tripRouterFactory.get();

    Coord coordStart =
        new Coord(
            scenario.getNetwork().getLinks().get(route.getEndLinkId()).getCoord().getX(),
            scenario.getNetwork().getLinks().get(route.getEndLinkId()).getCoord().getY());

    TwoWayCSFacility startFacility =
        new TwoWayCSFacilityImpl(
            Id.create("1000000000", TwoWayCSFacility.class), coordStart, route.getEndLinkId());

    Coord coordEnd =
        new Coord(
            scenario.getNetwork().getLinks().get(parkingSpot.getLinkId()).getCoord().getX(),
            scenario.getNetwork().getLinks().get(parkingSpot.getLinkId()).getCoord().getY());
    TwoWayCSFacility endFacility =
        new TwoWayCSFacilityImpl(
            Id.create("1000000001", TwoWayCSFacility.class), coordEnd, parkingSpot.getLinkId());

    for (PlanElement pe1 : tripRouter.calcRoute("car", startFacility, endFacility, now, person)) {

      if (pe1 instanceof Leg) {
        ids = ((NetworkRoute) ((Leg) pe1).getRoute()).getLinkIds();
        travelTime += ((Leg) pe1).getTravelTime();
      }
    }

    LegImpl carLeg = new LegImpl("freefloatingparking");

    carLeg.setTravelTime(travelTime);
    NetworkRoute route1 =
        ((PopulationFactoryImpl) scenario.getPopulation().getFactory())
            .getModeRouteFactory()
            .createRoute(NetworkRoute.class, route.getEndLinkId(), parkingSpot.getLinkId());
    route1.setLinkIds(route.getEndLinkId(), ids, parkingSpot.getLinkId());
    route1.setTravelTime(travelTime);
    // route1.setVehicleId(new IdImpl("FF_" + (vehID)));
    carLeg.setRoute(route1);
    this.cachedDestinationLinkId = parkingSpot.getLinkId();

    // set the route according to the next leg
    this.currentLeg = carLeg;
    this.cachedRouteLinkIds = null;
    this.currentLinkIdIndex = 0;
    this.cachedNextLinkId = null;

    return;
  }