@Test
  public void testNumberOfSelectedJointPlans() throws Exception {
    final JointPlans jointPlans = new JointPlans();
    final GroupPlanStrategy strategy =
        new GroupPlanStrategy(
            new HighestScoreSumSelector(new EmptyIncompatiblePlansIdentifierFactory()));
    strategy.addStrategyModule(new JointStructureInvertingModule(jointPlans.getFactory()));

    final ReplanningGroup group = createTestGroup(jointPlans);
    strategy.run(createContext(), jointPlans, Arrays.asList(group));

    int countSelectedJoint = 0;
    int countSelectedIndiv = 0;
    for (Person person : group.getPersons()) {
      for (Plan plan : person.getPlans()) {
        if (plan.isSelected() && jointPlans.getJointPlan(plan) != null) {
          countSelectedJoint++;
        }
        if (plan.isSelected() && jointPlans.getJointPlan(plan) == null) {
          countSelectedIndiv++;
        }
      }
    }

    assertEquals(
        "wrong number of selected plans in joint plans",
        N_INITIALLY_INDIV_PLANS,
        countSelectedJoint);
    assertEquals(
        "wrong number of selected plans in individual plans",
        N_INITIALLY_JOINT_PLANS,
        countSelectedIndiv);
  }
  @Test
  public void testNewPlanIsSelected() throws Exception {
    final JointPlans jointPlans = new JointPlans();
    final GroupPlanStrategy strategy =
        new GroupPlanStrategy(
            new HighestScoreSumSelector(new EmptyIncompatiblePlansIdentifierFactory()));
    strategy.addStrategyModule(new JointStructureInvertingModule(jointPlans.getFactory()));

    final List<Plan> selectedPlans = new ArrayList<Plan>();
    final ReplanningGroup group = createTestGroup(jointPlans);
    for (Person p : group.getPersons()) {
      selectedPlans.add(p.getSelectedPlan());
    }

    strategy.run(createContext(), jointPlans, Arrays.asList(group));
    for (Person person : group.getPersons()) {
      for (Plan plan : person.getPlans()) {
        if (plan.isSelected()) {
          // new plan: selection status inverted
          assertFalse("old plan still selected", selectedPlans.contains(plan));
        } else {
          assertTrue("old plan still selected", selectedPlans.contains(plan));
        }
      }
    }
  }
  @Test
  public void testNumberOfPlans() throws Exception {
    final JointPlans jointPlans = new JointPlans();
    final GroupPlanStrategy strategy =
        new GroupPlanStrategy(
            new HighestScoreSumSelector(new EmptyIncompatiblePlansIdentifierFactory()));
    strategy.addStrategyModule(new JointStructureInvertingModule(jointPlans.getFactory()));

    final ReplanningGroup group = createTestGroup(jointPlans);
    final int groupSize = group.getPersons().size();
    strategy.run(createContext(), jointPlans, Arrays.asList(group));

    assertEquals("group size changed by strategy!", groupSize, group.getPersons().size());
  }
  private ReplanningGroup createTestGroup(final JointPlans jointPlans) {
    final ReplanningGroup group = new ReplanningGroup();

    final Map<Id<Person>, Plan> jointPlan = new LinkedHashMap<>();

    int i = 0;
    for (int j = 0; j < N_INITIALLY_JOINT_PLANS; j++) {
      group.addPerson(createPerson(i++, true, jointPlan));
    }

    for (int j = 0; j < N_INITIALLY_INDIV_PLANS; j++) {
      group.addPerson(createPerson(i++, false, jointPlan));
    }

    if (jointPlan.size() != N_INITIALLY_JOINT_PLANS) {
      // this is basically an assertion, but I want an error,
      // not a failure in this case (it indicates a bug in the test)
      throw new RuntimeException();
    }

    jointPlans.addJointPlan(jointPlans.getFactory().createJointPlan(jointPlan));

    return group;
  }
  @Test
  public void testPruneSmallestJointPlan() {
    final JointPlans jointPlans = new JointPlans();
    final Map<Id<Person>, Plan> smallJp = new HashMap<>();
    final Map<Id<Person>, Plan> bigJp = new HashMap<>();

    final ReplanningGroup group = new ReplanningGroup();

    Id<Person> id = Id.createPersonId(1);
    {
      final Person person = PopulationUtils.createPerson(id);
      group.addPerson(person);
      {
        final Plan plan = jointPlans.getFactory().createIndividualPlan(person);
        plan.setScore(1d);
        person.addPlan(plan);
        bigJp.put(id, plan);
      }
      {
        final Plan plan = jointPlans.getFactory().createIndividualPlan(person);
        plan.setScore(0d);
        person.addPlan(plan);
        smallJp.put(id, plan);
      }
    }

    id = Id.createPersonId(2);
    {
      final Person person = PopulationUtils.createPerson(id);
      group.addPerson(person);
      {
        final Plan plan = jointPlans.getFactory().createIndividualPlan(person);
        plan.setScore(0d);
        person.addPlan(plan);
        bigJp.put(id, plan);
      }
      {
        final Plan plan = jointPlans.getFactory().createIndividualPlan(person);
        plan.setScore(1d);
        person.addPlan(plan);
        smallJp.put(id, plan);
      }
    }

    id = Id.createPersonId(3);
    {
      final Person person = PopulationUtils.createPerson(id);
      group.addPerson(person);
      {
        final Plan plan = jointPlans.getFactory().createIndividualPlan(person);
        plan.setScore(1d);
        person.addPlan(plan);
        bigJp.put(id, plan);
      }
      {
        final Plan plan = jointPlans.getFactory().createIndividualPlan(person);
        plan.setScore(0d);
        person.addPlan(plan);
      }
    }

    jointPlans.addJointPlan(jointPlans.getFactory().createJointPlan(bigJp));
    jointPlans.addJointPlan(jointPlans.getFactory().createJointPlan(smallJp));

    test(new ConflictSolverTestsFixture(jointPlans, group, smallJp.values()));
  }