package nl.tudelft.bw4t.server.model.robots;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Queue;
import nl.tudelft.bw4t.server.model.zone.Room;
import nl.tudelft.bw4t.server.model.zone.Zone;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import repast.simphony.space.continuous.NdPoint;
public class NavigatingRobotPathPlanningTest {
private static List<Zone> graph = new ArrayList<>(3 * 3);
private static Zone[][] zones = new Zone[3][3];
/**
* We create a 3x3 Grid of Zones with a room in the center that connects to the top.
*/
@BeforeClass
public static void setupNavigationGrid() {
for (int row = 0; row < zones.length; row++) {
for (int col = 0; col < zones[row].length; col++) {
Zone zone = mock(Zone.class);
if(col == 1 && row == 1) {
zone = mock(Room.class);
}
when(zone.getLocation()).thenReturn(new NdPoint((row + 1) * 5, (col + 1) * 5));
zones[row][col] = zone;
graph.add(zone);
}
}
}
@Before
public void setupConnections() {
when(zones[0][0].getNeighbours()).thenReturn(new HashSet<>(Arrays.asList(zones[0][1], zones[1][0])));
when(zones[0][1].getNeighbours()).thenReturn(
new HashSet<>(Arrays.asList(zones[0][2], zones[1][1], zones[0][0])));
when(zones[0][2].getNeighbours()).thenReturn(new HashSet<>(Arrays.asList(zones[1][2], zones[0][1])));
when(zones[1][0].getNeighbours()).thenReturn(new HashSet<>(Arrays.asList(zones[0][0], zones[2][0])));
when(zones[1][1].getNeighbours()).thenReturn(new HashSet<>(Arrays.asList(zones[0][1])));
when(zones[1][2].getNeighbours()).thenReturn(new HashSet<>(Arrays.asList(zones[0][2], zones[2][2])));
when(zones[2][0].getNeighbours()).thenReturn(new HashSet<>(Arrays.asList(zones[1][0], zones[2][1])));
when(zones[2][1].getNeighbours()).thenReturn(new HashSet<>(Arrays.asList(zones[2][2], zones[2][0])));
when(zones[2][2].getNeighbours()).thenReturn(new HashSet<>(Arrays.asList(zones[1][2], zones[2][1])));
}
public static void assertEqual(Queue<NdPoint> expected, Queue<NdPoint> actual) {
String error = String.format("expected: %s but was: %s", expected, actual);
assertEquals(error, expected.size(), actual.size());
Iterator<NdPoint> iexpect = expected.iterator();
Iterator<NdPoint> iactual = actual.iterator();
while (iexpect.hasNext()) {
NdPoint e = iexpect.next();
NdPoint a = iactual.next();
assertTrue(error, e.equals(a));
}
}
@Test
public void testSameZone() {
final Zone zone = zones[0][0];
final NdPoint zLocation = zone.getLocation();
NdPoint begin = new NdPoint(zLocation.getX() + 2, zLocation.getY() + 1);
NdPoint end = new NdPoint(zLocation.getX() + 3, zLocation.getY() - 4);
Queue<NdPoint> expected = new ArrayDeque<>();
expected.add(end);
Queue<NdPoint> actual = NavigatingRobot.planPath(begin, end, zone, zone, graph);
assertEqual(expected, actual);
}
@Test
public void testNextDirectZone() {
NdPoint begin = new NdPoint(zones[0][0].getLocation().getX(), zones[0][0].getLocation().getY());
NdPoint end = new NdPoint(zones[0][1].getLocation().getX() + 3, zones[0][1].getLocation().getY() - 4);
Queue<NdPoint> expected = new ArrayDeque<>();
expected.add(end);
Queue<NdPoint> actual = NavigatingRobot.planPath(begin, end, zones[0][0], zones[0][1], graph);
assertEqual(expected, actual);
}
@Test
public void testNextNextZone() {
NdPoint begin = new NdPoint(zones[0][0].getLocation().getX(), zones[0][0].getLocation().getY());
NdPoint end = new NdPoint(zones[1][1].getLocation().getX() + 1, zones[1][1].getLocation().getY() - 1);
Queue<NdPoint> expected = new ArrayDeque<>();
expected.add(zones[0][1].getLocation());
expected.add(zones[1][1].getLocation());
expected.add(end);
Queue<NdPoint> actual = NavigatingRobot.planPath(begin, end, zones[0][0], zones[1][1], graph);
assertEqual(expected, actual);
}
@Test
public void testRoundZone() {
final Zone bzone = zones[2][0];
final Zone ezone = zones[1][1];
NdPoint begin = new NdPoint(bzone.getLocation().getX(), bzone.getLocation().getY());
NdPoint end = new NdPoint(ezone.getLocation().getX() + 1, ezone.getLocation().getY() - 1);
Queue<NdPoint> expected = new ArrayDeque<>();
expected.add(zones[1][0].getLocation());
expected.add(zones[0][0].getLocation());
expected.add(zones[0][1].getLocation());
expected.add(ezone.getLocation());
expected.add(end);
Queue<NdPoint> actual = NavigatingRobot.planPath(begin, end, bzone, ezone, graph);
assertEqual(expected, actual);
}
@Test(expected = IllegalArgumentException.class)
public void testNoConnectionZone() {
final Zone bzone = zones[2][0];
final Zone ezone = zones[1][1];
NdPoint begin = new NdPoint(bzone.getLocation().getX(), bzone.getLocation().getY());
NdPoint end = new NdPoint(ezone.getLocation().getX() + 1, ezone.getLocation().getY() - 1);
// disconnect the middle zone
when(zones[0][1].getNeighbours()).thenReturn(new HashSet<Zone>(Arrays.asList(zones[0][2], zones[0][0])));
when(ezone.getNeighbours()).thenReturn(new HashSet<Zone>());
NavigatingRobot.planPath(begin, end, bzone, ezone, graph);
}
@Test
public void testBreakRoom() {
final Zone bzone = zones[1][1];
final Zone ezone = zones[0][1];
NdPoint begin = new NdPoint(bzone.getLocation().getX() - 1, bzone.getLocation().getY() + 3);
NdPoint end = new NdPoint(ezone.getLocation().getX() + 1, ezone.getLocation().getY() - 1);
assertTrue(bzone instanceof Room);
Queue<NdPoint> expected = new ArrayDeque<>();
expected.add(bzone.getLocation());
expected.add(ezone.getLocation());
expected.add(end);
Queue<NdPoint> actual = NavigatingRobot.planPath(begin, end, bzone, ezone, graph);
assertEqual(expected, actual);
}
}