// test overnight activities with first and last activity of different types
  @Test
  public final void test0c() {

    PlanCalcScoreConfigGroup plansCalcScoreConfigGroup = new PlanCalcScoreConfigGroup();

    ActivityParams activityParams1 = new ActivityParams("firstActivityType");
    activityParams1.setTypicalDuration(12 * 3600.);

    ActivityParams activityParams2 = new ActivityParams("lastActivityType");
    activityParams2.setTypicalDuration(12 * 3600.);

    plansCalcScoreConfigGroup.addActivityParams(activityParams1);
    plansCalcScoreConfigGroup.addActivityParams(activityParams2);

    plansCalcScoreConfigGroup.setEarlyDeparture_utils_hr(0.);
    plansCalcScoreConfigGroup.setLateArrival_utils_hr(0.);
    plansCalcScoreConfigGroup.setMarginalUtlOfWaiting_utils_hr(0.);
    plansCalcScoreConfigGroup.setPerforming_utils_hr(6.);

    ScenarioConfigGroup scenarioConfig = new ScenarioConfigGroup();
    CharyparNagelScoringParameters params =
        new CharyparNagelScoringParameters.Builder(
                plansCalcScoreConfigGroup,
                plansCalcScoreConfigGroup.getScoringParameters(null),
                scenarioConfig)
            .build();

    MarginalSumScoringFunction marginaSumScoringFunction = new MarginalSumScoringFunction(params);

    Id<Link> linkId = null;

    ActivityImpl activity1 = new ActivityImpl("firstActivityType", linkId);
    activity1.setEndTime(7 * 3600.);
    ActivityImpl activity2 = new ActivityImpl("lastActivityType", linkId);
    activity2.setStartTime(18 * 3600.);

    // test if zero delay results in zero activity delay disutility
    double delay1 = 0 * 3600.;
    double activityDelayDisutility1 =
        marginaSumScoringFunction.getOvernightActivityDelayDisutility(activity1, activity2, delay1);
    // 6 --> 10.0934029996839 utils + 7 --> 21.1922519472465 utils = 31.285654946930 utils
    // 6 --> 10.0934029996839 utils + 7 --> 21.1922519472465 utils = 31.285654946930 utils
    Assert.assertEquals(
        "Wrong disutility from starting an activity with a delay (arriving later at the activity location).",
        0.,
        activityDelayDisutility1,
        MatsimTestUtils.EPSILON);

    // test if a delay results in the right activity delay disutility
    double delay2 = 1 * 3600.;
    double activityDelayDisutility2 =
        marginaSumScoringFunction.getOvernightActivityDelayDisutility(activity1, activity2, delay2);
    // 6 --> 10.0934029996839 utils + 7 --> 21.1922519472465 utils = 31.285654946930 utils
    // 7 --> 21.1922519472465 utils + 7 --> 21.1922519472465 utils = 42.3845038944931 utils
    Assert.assertEquals(
        "Wrong disutility from starting an activity with a delay (arriving later at the activity location).",
        11.0988489475631,
        activityDelayDisutility2,
        MatsimTestUtils.EPSILON);
  }
    public Fixture() {
      firstLegStartTime = 7 * 3600;
      firstLegTravelTime = 30 * 60;
      thirdLegTravelTime = 30 * 60;
      secondLegStartTime = 10 * 3600;
      secondLegTravelTime = 15 * 60;
      thirdLegStartTime = 13 * 3600;
      fourthLegStartTime = 16 * 3600;
      fourthLegTravelTime = 15 * 60;
      // home act end 7am
      // work 7:30 to 10:00
      // work 10:15 to 13:00
      // work 13:30 to 16:00
      // home 15:15 to ...

      this.config = ConfigUtils.createConfig();
      PlanCalcScoreConfigGroup scoring = this.config.planCalcScore();
      scoring.setBrainExpBeta(2.0);

      scoring.setConstantCar(0.0);
      scoring.setConstantPt(0.0);
      scoring.setConstantWalk(0.0);
      scoring.setConstantBike(0.0);

      scoring.setEarlyDeparture_utils_hr(0.0);
      scoring.setLateArrival_utils_hr(0.0);
      scoring.setMarginalUtlOfWaiting_utils_hr(0.0);
      scoring.setPerforming_utils_hr(0.0);
      scoring.setTraveling_utils_hr(0.0);
      scoring.setTravelingPt_utils_hr(0.0);
      scoring.setTravelingWalk_utils_hr(0.0);
      scoring.setTravelingBike_utils_hr(0.0);

      scoring.setMarginalUtilityOfMoney(1.);
      scoring.setMonetaryDistanceCostRateCar(0.0);
      scoring.setMonetaryDistanceCostRatePt(0.0);

      // setup activity types h and w for scoring
      PlanCalcScoreConfigGroup.ActivityParams params =
          new PlanCalcScoreConfigGroup.ActivityParams("h");
      params.setTypicalDuration(15 * 3600);
      scoring.addActivityParams(params);

      params = new PlanCalcScoreConfigGroup.ActivityParams("w");
      params.setTypicalDuration(3 * 3600);
      scoring.addActivityParams(params);

      this.scenario = ScenarioUtils.createScenario(config);
      this.network = (NetworkImpl) this.scenario.getNetwork();
      Node node1 =
          this.network.createAndAddNode(Id.create("1", Node.class), new CoordImpl(0.0, 0.0));
      Node node2 =
          this.network.createAndAddNode(Id.create("2", Node.class), new CoordImpl(500.0, 0.0));
      Node node3 =
          this.network.createAndAddNode(Id.create("3", Node.class), new CoordImpl(5500.0, 0.0));
      Node node4 =
          this.network.createAndAddNode(Id.create("4", Node.class), new CoordImpl(6000.0, 0.0));
      Node node5 =
          this.network.createAndAddNode(Id.create("5", Node.class), new CoordImpl(11000.0, 0.0));
      Node node6 =
          this.network.createAndAddNode(Id.create("6", Node.class), new CoordImpl(11500.0, 0.0));
      Node node7 =
          this.network.createAndAddNode(Id.create("7", Node.class), new CoordImpl(16500.0, 0.0));
      Node node8 =
          this.network.createAndAddNode(Id.create("8", Node.class), new CoordImpl(17000.0, 0.0));
      Node node9 =
          this.network.createAndAddNode(Id.create("9", Node.class), new CoordImpl(22000.0, 0.0));
      Node node10 =
          this.network.createAndAddNode(Id.create("10", Node.class), new CoordImpl(22500.0, 0.0));

      Link link1 =
          this.network.createAndAddLink(Id.create("1", Link.class), node1, node2, 500, 25, 3600, 1);
      Link link2 =
          this.network.createAndAddLink(
              Id.create("2", Link.class), node2, node3, 25000, 50, 3600, 1);
      Link link3 =
          this.network.createAndAddLink(Id.create("3", Link.class), node3, node4, 500, 25, 3600, 1);
      this.network.createAndAddLink(Id.create("4", Link.class), node4, node5, 5000, 50, 3600, 1);
      Link link5 =
          this.network.createAndAddLink(Id.create("5", Link.class), node5, node6, 500, 25, 3600, 1);
      this.network.createAndAddLink(Id.create("6", Link.class), node6, node7, 5000, 50, 3600, 1);
      Link link7 =
          this.network.createAndAddLink(Id.create("7", Link.class), node7, node8, 500, 25, 3600, 1);
      this.network.createAndAddLink(Id.create("8", Link.class), node8, node9, 5000, 50, 3600, 1);
      Link link9 =
          this.network.createAndAddLink(
              Id.create("9", Link.class), node9, node10, 500, 25, 3600, 1);

      this.person = new PersonImpl(Id.create("1", Person.class));
      this.plan = this.person.createAndAddPlan(true);

      ActivityImpl firstActivity = this.plan.createAndAddActivity("h", link1.getId());
      firstActivity.setEndTime(firstLegStartTime);

      Leg leg = this.plan.createAndAddLeg(TransportMode.car);
      leg.setDepartureTime(firstLegStartTime);
      leg.setTravelTime(firstLegTravelTime);
      NetworkRoute route1 = new LinkNetworkRouteImpl(link1.getId(), link3.getId());
      route1.setLinkIds(link1.getId(), Arrays.asList(link2.getId()), link3.getId());
      route1.setTravelTime(firstLegTravelTime);
      route1.setDistance(RouteUtils.calcDistance(route1, this.network));
      leg.setRoute(route1);

      ActivityImpl secondActivity = this.plan.createAndAddActivity("w", link3.getId());
      secondActivity.setStartTime(firstLegStartTime + firstLegTravelTime);
      secondActivity.setEndTime(secondLegStartTime);
      leg = this.plan.createAndAddLeg(TransportMode.pt);
      leg.setDepartureTime(secondLegStartTime);
      leg.setTravelTime(secondLegTravelTime);
      Route route2 = new GenericRouteImpl(link3.getId(), link5.getId());
      route2.setTravelTime(secondLegTravelTime);
      route2.setDistance(20000.0);
      leg.setRoute(route2);

      ActivityImpl thirdActivity = this.plan.createAndAddActivity("w", link5.getId());
      thirdActivity.setStartTime(secondLegStartTime + secondLegTravelTime);
      thirdActivity.setEndTime(thirdLegStartTime);
      leg = this.plan.createAndAddLeg(TransportMode.walk);
      leg.setDepartureTime(thirdLegStartTime);
      leg.setTravelTime(thirdLegTravelTime);
      Route route3 = new GenericRouteImpl(link5.getId(), link7.getId());
      route3.setTravelTime(thirdLegTravelTime);
      route3.setDistance(CoordUtils.calcDistance(link5.getCoord(), link7.getCoord()));
      leg.setRoute(route3);

      ActivityImpl fourthActivity = this.plan.createAndAddActivity("w", link7.getId());
      fourthActivity.setStartTime(thirdLegStartTime + thirdLegTravelTime);
      fourthActivity.setEndTime(fourthLegStartTime);
      leg = this.plan.createAndAddLeg(TransportMode.bike);
      leg.setDepartureTime(fourthLegStartTime);
      leg.setTravelTime(fourthLegTravelTime);
      Route route4 = new GenericRouteImpl(link7.getId(), link9.getId());
      route4.setTravelTime(fourthLegTravelTime);
      route4.setDistance(CoordUtils.calcDistance(link7.getCoord(), link9.getCoord()));
      leg.setRoute(route4);

      ActivityImpl fifthActivity = this.plan.createAndAddActivity("h", link9.getId());
      fifthActivity.setStartTime(fourthLegStartTime + fourthLegTravelTime);
      this.scenario.getPopulation().addPerson(this.person);
    }
  public void run() {

    new MatsimNetworkReader(scenario).readFile(scenario.getConfig().network().getInputFile());
    new TransitScheduleReaderV1(scenario)
        .readFile(this.scenario.getConfig().transit().getTransitScheduleFile());
    Logger.getLogger(this.getClass())
        .fatal(
            "cannot say if the following should be vehicles or transit vehicles; aborting ... .  kai, feb'15");
    System.exit(-1);
    new VehicleReaderV1((scenario).getTransitVehicles())
        .readFile(this.scenario.getConfig().transit().getVehiclesFile());

    Controler controler = new Controler(this.scenario);
    controler
        .getConfig()
        .controler()
        .setOverwriteFileSetting(
            OutputDirectoryHierarchy.OverwriteFileSetting.overwriteExistingFiles);
    controler.addOverridingModule(new OTFVisFileWriterModule());
    controler.addControlerListener(
        new OptControlerListener(
            this.fare,
            this.scenario,
            this.calculate_inVehicleTimeDelayEffects,
            this.calculate_waitingTimeDelayEffects,
            this.calculate_capacityDelayEffects,
            this.marginalCostPricingPt,
            this.calculate_carCongestionEffects,
            this.marginalCostPricingCar));

    ControlerConfigGroup controlerConfGroup = controler.getConfig().controler();
    if (controlerConfGroup.getLastIteration() == 0) {
      controlerConfGroup.setWriteEventsInterval(1);
      controlerConfGroup.setWritePlansInterval(1);
    } else {
      controlerConfGroup.setWriteEventsInterval(controlerConfGroup.getLastIteration());
      controlerConfGroup.setWritePlansInterval(controlerConfGroup.getLastIteration());
    }

    PlanCalcScoreConfigGroup planCalcScoreConfigGroup = controler.getConfig().planCalcScore();
    planCalcScoreConfigGroup.setMarginalUtilityOfMoney(MARGINAL_UTILITY_OF_MONEY);
    planCalcScoreConfigGroup.setPerforming_utils_hr(PERFORMING);

    planCalcScoreConfigGroup.getModes().get(TransportMode.car).setConstant(CONSTANT_CAR);
    planCalcScoreConfigGroup
        .getModes()
        .get(TransportMode.car)
        .setMarginalUtilityOfTraveling(TRAVEL_CAR);
    planCalcScoreConfigGroup
        .getModes()
        .get(TransportMode.car)
        .setMonetaryDistanceRate(MONETARY_DISTANCE_COST_RATE_CAR);

    planCalcScoreConfigGroup.getModes().get(TransportMode.walk).setConstant(CONSTANT_WALK);
    planCalcScoreConfigGroup
        .getModes()
        .get(TransportMode.walk)
        .setMarginalUtilityOfTraveling(TRAVEL_WALK);
    planCalcScoreConfigGroup
        .getModes()
        .get(TransportMode.pt)
        .setMonetaryDistanceRate(MONETARY_DISTANCE_COST_RATE_PT);

    planCalcScoreConfigGroup.getModes().get(TransportMode.pt).setConstant(CONSTANT_PT);
    planCalcScoreConfigGroup
        .getModes()
        .get(TransportMode.pt)
        .setMarginalUtilityOfTraveling(TRAVEL_PT_IN_VEHICLE);
    planCalcScoreConfigGroup.setMarginalUtlOfWaitingPt_utils_hr(TRAVEL_PT_WAITING);
    planCalcScoreConfigGroup.setUtilityOfLineSwitch(LINE_SWITCH);

    planCalcScoreConfigGroup.setLateArrival_utils_hr(LATE_ARRIVAL);
    planCalcScoreConfigGroup.setEarlyDeparture_utils_hr(EARLY_DEPARTURE);
    planCalcScoreConfigGroup.setMarginalUtlOfWaiting_utils_hr(WAITING);

    OptimizationScoringFunctionFactory scoringfactory =
        new OptimizationScoringFunctionFactory(scenario, STUCK_SCORE);

    controler.setScoringFunctionFactory(scoringfactory);

    controler.getConfig().controler().setCreateGraphs(false);
    controler.run();
  }
  // test normal activities
  @Test
  public final void test0a() {

    PlanCalcScoreConfigGroup plansCalcScoreConfigGroup = new PlanCalcScoreConfigGroup();
    ActivityParams activityParams = new ActivityParams("work");
    activityParams.setTypicalDuration(6 * 3600.);
    activityParams.setOpeningTime(7 * 3600.);
    activityParams.setClosingTime(18 * 3600.);

    plansCalcScoreConfigGroup.addActivityParams(activityParams);
    plansCalcScoreConfigGroup.setEarlyDeparture_utils_hr(0.);
    plansCalcScoreConfigGroup.setLateArrival_utils_hr(0.);
    plansCalcScoreConfigGroup.setMarginalUtlOfWaiting_utils_hr(0.);
    plansCalcScoreConfigGroup.setPerforming_utils_hr(6.);

    ScenarioConfigGroup scenarioConfig = new ScenarioConfigGroup();

    CharyparNagelScoringParameters params =
        new CharyparNagelScoringParameters.Builder(
                plansCalcScoreConfigGroup,
                plansCalcScoreConfigGroup.getScoringParameters(null),
                scenarioConfig)
            .build();

    MarginalSumScoringFunction marginaSumScoringFunction = new MarginalSumScoringFunction(params);

    Id<Link> linkId = null;

    // test if zero delay results in zero activity delay disutility
    ActivityImpl activity1 = new ActivityImpl("work", linkId);
    activity1.setStartTime(10 * 3600.);
    activity1.setEndTime(16 * 3600.);
    double delay1 = 0 * 3600.;
    double activityDelayDisutility1 =
        marginaSumScoringFunction.getNormalActivityDelayDisutility(activity1, delay1);
    Assert.assertEquals(
        "Wrong disutility from starting an activity with a delay (arriving later at the activity location).",
        0.,
        activityDelayDisutility1,
        MatsimTestUtils.EPSILON);

    // test if a delay results in zero activity delay disutility if the agent would have arrived to
    // late at the activity location anyway
    ActivityImpl activity2 = new ActivityImpl("work", linkId);
    activity2.setStartTime(19 * 3600.);
    activity2.setEndTime(20 * 3600.);
    double delay2 = 0.5 * 3600.;
    double activityDelayDisutility2 =
        marginaSumScoringFunction.getNormalActivityDelayDisutility(activity2, delay2);
    Assert.assertEquals(
        "Wrong disutility from starting an activity with a delay (arriving later at the activity location).",
        0.,
        activityDelayDisutility2,
        MatsimTestUtils.EPSILON);

    // test if a delay results in zero activity delay disutility if the agent would have arrived to
    // early at the activity location anyway
    ActivityImpl activity3 = new ActivityImpl("work", linkId);
    activity3.setStartTime(4 * 3600.);
    activity3.setEndTime(5 * 3600.);
    double delay3 = 0.5 * 3600.;
    double activityDelayDisutility3 =
        marginaSumScoringFunction.getNormalActivityDelayDisutility(activity3, delay3);
    Assert.assertEquals(
        "Wrong disutility from starting an activity with a delay (arriving later at the activity location).",
        0.,
        activityDelayDisutility3,
        MatsimTestUtils.EPSILON);

    // test if a delay results in the right activity delay disutility if the agent would have had
    // more time to perform the activity
    ActivityImpl activity4 = new ActivityImpl("work", linkId);
    activity4.setStartTime(10 * 3600.);
    activity4.setEndTime(16 * 3600.);
    double delay4 = 1 * 3600.;
    double activityDelayDisutility4 =
        marginaSumScoringFunction.getNormalActivityDelayDisutility(activity4, delay4);
    // 6 hours --> 65.549424473781 utils
    // 5 hours --> 60 utils
    Assert.assertEquals(
        "Wrong disutility from starting an activity with a delay (arriving later at the activity location).",
        5.549424473781310,
        activityDelayDisutility4,
        MatsimTestUtils.EPSILON);

    // repeat the previous test: test if a delay results in the right activity delay disutility if
    // the agent would have had more time to perform the activity
    double activityDelayDisutility4b =
        marginaSumScoringFunction.getNormalActivityDelayDisutility(activity4, delay4);
    // 6 hours --> 65.549424473781 utils
    // 5 hours --> 60 utils
    Assert.assertEquals(
        "Wrong disutility from starting an activity with a delay (arriving later at the activity location).",
        5.549424473781310,
        activityDelayDisutility4b,
        MatsimTestUtils.EPSILON);
  }
  // test overnight activities with first and last activity of the same type
  @Test
  public final void test0b() {

    PlanCalcScoreConfigGroup plansCalcScoreConfigGroup = new PlanCalcScoreConfigGroup();
    ActivityParams activityParams = new ActivityParams("overnightActivity");
    activityParams.setTypicalDuration(12 * 3600.);

    plansCalcScoreConfigGroup.addActivityParams(activityParams);
    plansCalcScoreConfigGroup.setEarlyDeparture_utils_hr(0.);
    plansCalcScoreConfigGroup.setLateArrival_utils_hr(0.);
    plansCalcScoreConfigGroup.setMarginalUtlOfWaiting_utils_hr(0.);
    plansCalcScoreConfigGroup.setPerforming_utils_hr(6.);

    ScenarioConfigGroup scenarioConfig = new ScenarioConfigGroup();

    CharyparNagelScoringParameters params =
        new CharyparNagelScoringParameters.Builder(
                plansCalcScoreConfigGroup,
                plansCalcScoreConfigGroup.getScoringParameters(null),
                scenarioConfig)
            .build();

    MarginalSumScoringFunction marginaSumScoringFunction = new MarginalSumScoringFunction(params);

    Id<Link> linkId = null;

    ActivityImpl activity1 = new ActivityImpl("overnightActivity", linkId);
    activity1.setEndTime(7 * 3600.);
    ActivityImpl activity2 = new ActivityImpl("overnightActivity", linkId);
    activity2.setStartTime(18 * 3600.);

    // test if zero delay results in zero activity delay disutility
    double delay1 = 0 * 3600.;
    double activityDelayDisutility1 =
        marginaSumScoringFunction.getOvernightActivityDelayDisutility(activity1, activity2, delay1);
    // 6 + 7 hours --> 65.763074952494600 utils
    // 6 + 7 hours --> 65.763074952494600 utils
    Assert.assertEquals(
        "Wrong disutility from starting an activity with a delay (arriving later at the activity location).",
        0.,
        activityDelayDisutility1,
        MatsimTestUtils.EPSILON);

    // test if a delay results in the right activity delay disutility
    double delay2 = 1 * 3600.;
    double activityDelayDisutility2 =
        marginaSumScoringFunction.getOvernightActivityDelayDisutility(activity1, activity2, delay2);
    // 6 + 7 hours --> 65.763074952494600 utils
    // 7 + 7 hours --> 71.098848947562600 utils
    Assert.assertEquals(
        "Wrong disutility from starting an activity with a delay (arriving later at the activity location).",
        5.335773995067980,
        activityDelayDisutility2,
        MatsimTestUtils.EPSILON);

    // repeat the previous test: test if a delay results in the right activity delay disutility
    double activityDelayDisutility2b =
        marginaSumScoringFunction.getOvernightActivityDelayDisutility(activity1, activity2, delay2);
    // 6 + 7 hours --> 65.763074952494600 utils
    // 7 + 7 hours --> 71.098848947562600 utils
    Assert.assertEquals(
        "Wrong disutility from starting an activity with a delay (arriving later at the activity location).",
        5.335773995067980,
        activityDelayDisutility2b,
        MatsimTestUtils.EPSILON);
  }