/*
* This file is part of the TimeFinder project.
* Visit http://www.timefinder.de for more information.
* Copyright (c) 2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.timefinder.algo.roomassignment;
import de.timefinder.algo.constraint.EventOrderConstraint;
import de.timefinder.algo.util.TimeFinder2Tester;
import de.timefinder.data.Feature;
import de.timefinder.data.Location;
import de.timefinder.data.algo.Assignment;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
/**
* @author Peter Karich, peat_hal 'at' users 'dot' sourceforge 'dot' net
*/
public class AssignmentManagerTest extends TimeFinder2Tester {
private AssignmentManager aManager;
private Location loc1;
private List<Location> allLocations;
@Before
@Override
public void setUp() {
super.setUp();
loc1 = newLocation("loc1", 10);
allLocations = new ArrayList<Location>();
allLocations.add(loc1);
aManager = new AssignmentManager(0, allLocations);
aManager.setAlgorithm(new HungarianAlgorithm());
}
@Test
public void testAssignedTIs() {
int ass[][] = {{3, 0}, {0, 1}, {2, 2}, {1, 3}};
assertEquals(4, aManager.countValid(ass));
}
@Test
public void testAssignEvents() {
Assignment event1 = newAssignment(0, 1);
assertNotNull(aManager.assign(event1));
assertEquals(loc1, event1.getLocation());
assertEquals(1, aManager.getAll().size());
Feature loc1Feature = newFeature("special");
loc1.addFeature(loc1Feature);
Location locForEvent1 = newLocation("loc2", 5);
allLocations.add(locForEvent1);
aManager = new AssignmentManager(0, allLocations);
aManager.setAlgorithm(new HungarianAlgorithm());
Assignment event2 = newAssignment(0, 1);
event2.getEvent().addFeature(loc1Feature);
assertNotNull(aManager.assign(event1));
assertEquals(1, aManager.getAll().size());
assertEquals(loc1, event1.getLocation());
assertNotNull(aManager.assign(event2));
assertEquals(2, aManager.getAll().size());
assertEquals(loc1, event2.getLocation());
assertEquals(locForEvent1, event1.getLocation());
}
@Test
public void testGetLocation() {
Assignment event1 = newAssignment(0, 1);
assertEquals(loc1, aManager.calculateLocation(event1));
}
@Test
public void testAssignToLocation() {
Location loc2 = newLocation("loc2", 5);
allLocations.add(loc2);
aManager = new AssignmentManager(0, allLocations);
Assignment event1 = newAssignment(0, 1);
assertNotNull(aManager.forceAssignment(event1, loc1));
assertEquals(loc1, event1.getLocation());
// TODO reassignment not possible at the moment
Assignment event2 = newAssignment(0, 1);
assertNull(aManager.forceAssignment(event2, loc1));
assertEquals(loc1, event1.getLocation());
assertEquals(null, event2.getLocation());
}
@Test
public void testTestAssignToLocation() {
Location loc2 = newLocation("loc2", 5);
allLocations.add(loc2);
aManager = new AssignmentManager(0, allLocations);
Assignment event1 = newAssignment(0, 1);
assertEquals(true, aManager.isForcedAssignmentPossible(event1, loc1));
assertEquals(true, aManager.isForcedAssignmentPossible(event1, loc2));
// with reassignment
Assignment event2 = newAssignment(0, 1);
assertNotNull(aManager.assign(event1));
assertEquals(true, aManager.isForcedAssignmentPossible(event2, loc1));
assertEquals(true, aManager.isForcedAssignmentPossible(event2, loc2));
}
@Test
public void testTestAssignmentWithBiggerDuration() {
Location loc2 = newLocation("loc2", 5);
allLocations.add(loc2);
aManager = new AssignmentManager(0, allLocations);
// we can only reassign events which will be 'consumed'
Assignment ass1 = newAssignment(0, 2);
assertNotNull(aManager.assign(ass1));
assertEquals(loc1, ass1.getLocation());
Assignment ass2 = newAssignment(0, 2);
assertEquals(true, aManager.isForcedAssignmentPossible(ass2, loc2));
assertEquals(true, aManager.isForcedAssignmentPossible(ass2, loc1));
// if one assignment exists with end < ass2.end
ass2.getEvent().setDuration(1);
assertEquals(true, aManager.isForcedAssignmentPossible(ass2, loc2));
assertEquals(true, aManager.isForcedAssignmentPossible(ass2, loc1));
}
@Test
public void testTestAssignmentWithSpecialEvent() {
Location loc2 = newLocation("loc2", 5);
allLocations.add(loc2);
aManager = new AssignmentManager(0, allLocations);
Feature special = newFeature("special");
loc1.addFeature(special);
Assignment ass1 = newAssignment("1", 0, 1);
ass1.getEvent().addFeature(special);
Assignment ass2 = newAssignment("2", 0, 1);
ass2.getEvent().addFeature(special);
assertEquals(true, aManager.isForcedAssignmentPossible(ass1, loc1));
assertEquals(true, aManager.isForcedAssignmentPossible(ass2, loc1));
assertNotNull(aManager.assign(ass1));
assertEquals(loc1, ass1.getLocation());
assertEquals(false, aManager.isForcedAssignmentPossible(ass2, loc1));
assertNull(aManager.assign(ass2));
}
@Test
public void testReassignWhileCollidingEventIsNotAssigned() {
Location loc2 = newLocation("loc2", 5);
allLocations.add(loc2);
aManager = new AssignmentManager(0, allLocations);
Assignment ass1 = newAssignment("1", 0, 1);
Assignment ass2 = newAssignment("2", 0, 1);
Object undoAddData1 = aManager.forceAssignment(ass1, loc1);
assertEquals(1, aManager.getAvailableLocations().size());
assertNotNull(undoAddData1);
// try to inject ass2 => ass1 is one of the colliding => remove
Object undoRmData1 = aManager.remove(ass1);
assertEquals(2, aManager.getAvailableLocations().size());
assertNotNull(undoRmData1);
assertNull(ass2.getLocation());
Object undoAddData2 = aManager.forceAssignment(ass2, loc1);
assertEquals(loc1, ass2.getLocation());
assertEquals(1, aManager.getAvailableLocations().size());
assertNotNull(undoAddData2);
// inject fails => rollback move of ass2 and ass1
aManager.rollbackAssign(ass2, undoAddData2);
// assertNull(ass2.getLocation());
// ass2 was not assigned before assign so no rollbackRemove necessary
assertEquals(0, aManager.getAll().size());
assertEquals(2, aManager.getAvailableLocations().size());
aManager.rollbackRemove(ass1, undoRmData1);
assertEquals(1, aManager.getAll().size());
assertEquals(1, aManager.getAvailableLocations().size());
}
@Test
public void testAssignedLocationAfterRollback() {
Location loc2 = newLocation("loc2", 5);
allLocations.add(loc2);
aManager = new AssignmentManager(0, allLocations);
Assignment ass1 = newAssignment("1", 0, 1);
Assignment ass2 = newAssignment("2", 0, 1);
aManager.forceAssignment(ass1, loc1);
// try to inject ass2 => assume ass1 is one of the colliding => remove
Object undoRmData1 = aManager.remove(ass1);
Object undoAddData2 = aManager.forceAssignment(ass2, loc1);
// now force ass1 into another location in a deeper "Period.inject depth"
Object undoAddData1Deeper = aManager.forceAssignment(ass1, loc2);
// inject fails => rollback move of ass2 and deeper-ass1
aManager.rollbackAssign(ass1, undoAddData1Deeper);
aManager.rollbackAssign(ass2, undoAddData2);
assertEquals(0, aManager.getAll().size());
assertEquals(2, aManager.getAvailableLocations().size());
aManager.rollbackRemove(ass1, undoRmData1);
assertEquals(loc1, ass1.getLocation());
assertEquals(1, aManager.getAll().size());
assertEquals(1, aManager.getAvailableLocations().size());
}
@Test
public void testOrder() {
Location loc2 = newLocation("loc2", 5);
allLocations.add(loc2);
Feature special = newFeature("loc1");
loc1.addFeature(special);
aManager = new AssignmentManager(0, allLocations);
Assignment ass1 = newAssignment("1", 0, 1);
Assignment ass2 = newAssignment("2", 0, 1);
EventOrderConstraint oc1 = new EventOrderConstraint(ass1.getEvent());
EventOrderConstraint oc2 = new EventOrderConstraint(ass2.getEvent());
oc2.addFollow(newEvent("ev3"));
ass1.getEvent().putConstraint(oc1);
ass2.getEvent().putConstraint(oc2);
ass2.getEvent().addFeature(special);
Object rollbackAssData = aManager.assign(ass1);
assertNotNull(rollbackAssData);
assertEquals(loc1, ass1.getLocation());
assertNotNull(aManager.assign(ass2));
assertEquals(loc1, ass2.getLocation());
assertEquals(loc2, ass1.getLocation());
Object rollbackRmData = aManager.remove(ass1);
assertNotNull(rollbackRmData);
assertNotNull(aManager.remove(ass2));
aManager.rollbackRemove(ass1, rollbackRmData);
aManager.rollbackAssign(ass1, rollbackAssData);
aManager.assign(ass1);
assertNotNull(aManager.remove(ass1));
}
@Test
public void testAssignedLocationAfterRollback2() {
Location loc2 = newLocation("loc2", 5);
allLocations.add(loc2);
Feature special = newFeature("loc1");
loc1.addFeature(special);
aManager = new AssignmentManager(0, allLocations);
Assignment ass1 = newAssignment("1", 0, 1);
Assignment ass2 = newAssignment("2", 0, 1);
ass2.getEvent().addFeature(special);
aManager.assign(ass1);
assertEquals(loc1, ass1.getLocation());
Object undoAddData2 = aManager.assign(ass2);
assertEquals(loc1, ass2.getLocation());
assertEquals(loc2, ass1.getLocation());
// rollback move of ass2 should also rollback others location assignments!
aManager.rollbackAssign(ass2, undoAddData2);
assertEquals(1, aManager.getAll().size());
assertEquals(1, aManager.getAvailableLocations().size());
assertEquals(loc1, ass1.getLocation());
}
@Test
public void testTestReassignmentDifferentDuration() {
// two rooms
Location loc2 = newLocation("loc2", 5);
allLocations.add(loc2);
aManager = new AssignmentManager(0, allLocations);
AssignmentManager aManagerForSlot2 = new AssignmentManager(0, allLocations);
Assignment ass1 = newAssignment("1", 0, 2);
Assignment ass2 = newAssignment("2", 0, 4);
Location loc = aManagerForSlot2.calculateLocation(ass1);
assertNotNull(loc);
// force assignment, so that only one matrix entry is possible
assertNotNull(aManager.forceAssignment(ass1, loc));
// slot1 slot2
// loc1 | - | - | - | - |
// loc2 | ass1 | ass1 | - | - |
assertEquals(true, aManagerForSlot2.isForcedAssignmentPossible(ass2, loc));
assertEquals(false, aManager.isForcedAssignmentPossible(ass2, loc));
}
}