@Override
    protected void appendTasksAfterDropoff(Schedule<TaxiTask> schedule) {
      if (rankmode) {
        TaxiDropoffTask dropoffStayTask = (TaxiDropoffTask) Schedules.getLastTask(schedule);

        Link link = dropoffStayTask.getLink();
        Link startLink = schedule.getVehicle().getStartLink();

        if (link != startLink) {
          double t5 = dropoffStayTask.getEndTime();
          VrpPathWithTravelData path = calcPath(link, startLink, t5);
          schedule.addTask(new TaxiDriveTask(path));
        }
      }

      appendStayTask(schedule);
    }
  private void sendIdlingTaxisHome(double time) {
    int homeboundthishour = 0;
    for (Vehicle veh : optimConfig.context.getVrpData().getVehicles().values()) {
      if (time + 3600 < veh.getT1()) continue;
      if (!optimConfig.scheduler.isIdle(veh)) continue;
      if (veh.getSchedule().getStatus() != ScheduleStatus.STARTED) continue;
      if (!(Schedules.getLastTask(veh.getSchedule()).getTaskIdx()
          == veh.getSchedule().getCurrentTask().getTaskIdx())) continue;

      if (veh.getSchedule().getCurrentTask().getType().equals(TaskType.STAY)) {

        rankModeTaxiScheduler.scheduleRankReturn(veh, time, false, true);
        homeboundthishour++;
      }
    }
    log.info(
        time % 3600 + " hrs: " + homeboundthishour + " sent home" + this.homebound + " total.");
  }
  public void sendIdlingTaxisBackToRank(double time) {
    for (Vehicle veh : optimConfig.context.getVrpData().getVehicles().values()) {
      if (!optimConfig.scheduler.isIdle(veh)) continue;
      if (veh.getSchedule().getStatus() != ScheduleStatus.STARTED) continue;
      if (!(Schedules.getLastTask(veh.getSchedule()).getTaskIdx()
          == veh.getSchedule().getCurrentTask().getTaskIdx())) continue;

      if (veh.getSchedule().getCurrentTask().getType().equals(TaskType.STAY)) {

        TaxiStayTask twst = (TaxiStayTask) veh.getSchedule().getCurrentTask();
        if (!this.rankHandler.isRankLocation(twst.getLink().getId())) {
          if (time - twst.getBeginTime() > 60.) {
            rankModeTaxiScheduler.scheduleRankReturn(veh, time, false, false);
          }
        }
      }
    }
  }
  private void checkWaitingVehiclesBatteryState(double time) {

    for (Vehicle veh : optimConfig.context.getVrpData().getVehicles().values()) {

      if (!optimConfig.scheduler.isIdle(veh)) continue;
      if (veh.getSchedule().getStatus() != ScheduleStatus.STARTED) continue;
      if (!(Schedules.getLastTask(veh.getSchedule()).getTaskIdx()
          == veh.getSchedule().getCurrentTask().getTaskIdx())) continue;

      if (veh.getSchedule().getCurrentTask().getType().equals(TaskType.STAY)) {

        TaxiStayTask twst = (TaxiStayTask) veh.getSchedule().getCurrentTask();

        if (!this.ecabhandler.isAtCharger(twst.getLink().getId())) {
          if (this.needsToCharge(veh.getId())) {
            log.info("veh" + veh.getId() + " to charge");
            rankModeTaxiScheduler.scheduleRankReturn(veh, time, true, false);
          }
        }
      }
    }
  }
    protected void scheduleRankReturn(Vehicle veh, double time, boolean charge, boolean home) {
      @SuppressWarnings("unchecked")
      Schedule<Task> sched = (Schedule<Task>) veh.getSchedule();
      TaxiStayTask last = (TaxiStayTask) Schedules.getLastTask(veh.getSchedule());
      if (last.getStatus() != TaskStatus.STARTED) throw new IllegalStateException();

      last.setEndTime(time);
      Link currentLink = last.getLink();
      Link nearestRank;
      if (charge) {
        nearestRank = optimizer.getNearestFreeCharger(currentLink.getId());
        log.info("veh" + veh.getId() + " to charge");
      } else if (home) {
        nearestRank = veh.getStartLink();
        //        log.info("start" + veh.getId()+ " at " + time + " t1 " + veh.getT1());
        optimizer.homebound++;
      } else nearestRank = optimizer.getNearestFreeRank(currentLink.getId());

      VrpPathWithTravelData path = calcPath(currentLink, nearestRank, time);
      if (path.getArrivalTime() > veh.getT1())
        return; // no rank return if vehicle is going out of service anyway
      sched.addTask(new TaxiDriveTask(path));
      sched.addTask(new TaxiStayTask(path.getArrivalTime(), veh.getT1(), nearestRank));
    }