// 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);
  }
  // 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);
  }