diff --git a/src/edu/caltech/cs2/datastructures/BeaverMapsGraph.java b/src/edu/caltech/cs2/datastructures/BeaverMapsGraph.java index d824b986c827fd3e491b7de6595de8b9d6050bda..f3372faaad7cc0f140853e9aac3b3ad524414322 100644 --- a/src/edu/caltech/cs2/datastructures/BeaverMapsGraph.java +++ b/src/edu/caltech/cs2/datastructures/BeaverMapsGraph.java @@ -2,18 +2,13 @@ package edu.caltech.cs2.datastructures; import com.google.gson.JsonElement; import com.google.gson.JsonParser; -import edu.caltech.cs2.interfaces.IDeque; -import edu.caltech.cs2.interfaces.IDictionary; -import edu.caltech.cs2.interfaces.ISet; +import edu.caltech.cs2.interfaces.*; -import java.io.File; import java.io.FileReader; import java.io.IOException; public class BeaverMapsGraph extends Graph<Long, Double> { - private static JsonParser JSON_PARSER = new JsonParser(); - private IDictionary<Long, Location> ids; private ISet<Location> buildings; @@ -117,12 +112,8 @@ public class BeaverMapsGraph extends Graph<Long, Double> { * @return the JSON data from filename */ private static JsonElement fromFile(String filename) { - try { - return JSON_PARSER.parse( - new FileReader( - new File(filename) - ) - ); + try (FileReader reader = new FileReader(filename)) { + return JsonParser.parseReader(reader); } catch (IOException e) { return null; } diff --git a/src/edu/caltech/cs2/datastructures/Graph.java b/src/edu/caltech/cs2/datastructures/Graph.java index da8d0920e1ca413fc2c47219fec8466042cad804..223b49cdbcdc4c0142f8c803b8b4925b70f2d95a 100644 --- a/src/edu/caltech/cs2/datastructures/Graph.java +++ b/src/edu/caltech/cs2/datastructures/Graph.java @@ -2,7 +2,7 @@ package edu.caltech.cs2.datastructures; import edu.caltech.cs2.interfaces.*; -public class Graph<V, E> extends IGraph<V, E> { +public class Graph<V, E> implements IGraph<V, E> { @Override public boolean addVertex(V vertex) { diff --git a/src/edu/caltech/cs2/interfaces/IDictionary.java b/src/edu/caltech/cs2/interfaces/IDictionary.java index 588ec4304d6833ddc7fbc6154a28dfff01035c9d..04c3f7928c10a4be8ec0e66d3dc8d5e49d09f3ac 100644 --- a/src/edu/caltech/cs2/interfaces/IDictionary.java +++ b/src/edu/caltech/cs2/interfaces/IDictionary.java @@ -1,5 +1,7 @@ package edu.caltech.cs2.interfaces; +import edu.caltech.cs2.datastructures.LinkedDeque; + public interface IDictionary<K, V> extends Iterable<K> { public static class Entry<K, V> { diff --git a/src/edu/caltech/cs2/interfaces/IGraph.java b/src/edu/caltech/cs2/interfaces/IGraph.java index 6e0e757be7b798ae4a6072aa22231854d72448e7..24a47c8824c9822a28f0bc4af13a84f51d093206 100644 --- a/src/edu/caltech/cs2/interfaces/IGraph.java +++ b/src/edu/caltech/cs2/interfaces/IGraph.java @@ -1,32 +1,32 @@ package edu.caltech.cs2.interfaces; -public abstract class IGraph<V, E> { +public interface IGraph<V, E> { /** * Add a vertex to the graph. * @param vertex The vertex to add * @return true if vertex was not present already. */ - public abstract boolean addVertex(V vertex); + public boolean addVertex(V vertex); /** * Adds edge e to the graph. * * @param e The edge to add. * @throws IllegalArgumentException - * If e is not a valid edge (eg. refers to vertices not in the graph). - * @return true If e was not already present; false if it was (in which case the graph is still updated). + * If src and dest are not valid vertices (eg. refers to vertices not in the graph). + * @return true If src and dest were not already present; false if it was (in which case the graph is still updated). */ - public abstract boolean addEdge(V src, V dest, E e); + public boolean addEdge(V src, V dest, E e); /** * Adds edge e to the graph in both directionns. * * @param e The edge to add. * @throws IllegalArgumentException - * If e is not a valid edge (eg. refers to vertices not in the graph). - * @return true If e was not already present in either direction; false if it was (in which case the graph is still updated). + * If src and dest are not valid vertices (eg. refers to vertices not in the graph). + * @return true If src and dest were not already present in either direction; false if it was (in which case the graph is still updated). */ - public abstract boolean addUndirectedEdge(V src, V dest, E e); + public boolean addUndirectedEdge(V src, V dest, E e); /** * Remove an edge from src to dest from the graph. @@ -34,13 +34,13 @@ public abstract class IGraph<V, E> { * @throws IllegalArgumentException if src or dest is not in the graph. * @return true if an edge from src to dest edge was present. */ - public abstract boolean removeEdge(V src, V dest); + public boolean removeEdge(V src, V dest); /** * Returns the set of vertices in the graph. * @return The set of all vertices in the graph. */ - public abstract ISet<V> vertices(); + public ISet<V> vertices(); /** * Tests if vertices i and j are adjacent, returning the edge between @@ -50,7 +50,7 @@ public abstract class IGraph<V, E> { * @return The edge from i to j if it exists in the graph; * null otherwise. */ - public abstract E adjacent(V i, V j); + public E adjacent(V i, V j); /** * Return the neighbours of a given vertex when this graph is treated as @@ -60,5 +60,5 @@ public abstract class IGraph<V, E> { * @throws IllegalArgumentException if vertex is not in the graph. * @return The set of neighbors of vertex. */ - public abstract ISet<V> neighbors(V vertex); + public ISet<V> neighbors(V vertex); } \ No newline at end of file diff --git a/src/edu/caltech/cs2/project08/BeaverMaps.java b/src/edu/caltech/cs2/project08/BeaverMaps.java index 3acb98eac1fa32ba8de6e531022a0aa55e9130c4..e11e8d17019b16246547d1cf1b91d314fd37c631 100644 --- a/src/edu/caltech/cs2/project08/BeaverMaps.java +++ b/src/edu/caltech/cs2/project08/BeaverMaps.java @@ -5,6 +5,7 @@ import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; import edu.caltech.cs2.datastructures.BeaverMapsGraph; +import edu.caltech.cs2.datastructures.LinkedDeque; import edu.caltech.cs2.datastructures.Location; import edu.caltech.cs2.interfaces.IDeque; import edu.caltech.cs2.interfaces.ISet; diff --git a/src/edu/caltech/cs2/project08/MapsAutoCompleter.java b/src/edu/caltech/cs2/project08/MapsAutoCompleter.java index db88dfa6cee44519458593f32219555ee29c45d2..7be91f5278ba1940417237729496148958caa315 100644 --- a/src/edu/caltech/cs2/project08/MapsAutoCompleter.java +++ b/src/edu/caltech/cs2/project08/MapsAutoCompleter.java @@ -1,6 +1,8 @@ package edu.caltech.cs2.project08; +import edu.caltech.cs2.datastructures.LinkedDeque; import edu.caltech.cs2.datastructures.Location; +import edu.caltech.cs2.datastructures.TrieMap; import edu.caltech.cs2.interfaces.IDeque; import edu.caltech.cs2.interfaces.ISet; import edu.caltech.cs2.interfaces.ITrieMap; diff --git a/tests/edu/caltech/cs2/project08/BeavermapTests.java b/tests/edu/caltech/cs2/project08/BeavermapTests.java index bc4fddf7db0509d2b3ab66dae07aecf7d467eead..50c73274a7d8eda85df59d0c5db9d2e080e9732a 100644 --- a/tests/edu/caltech/cs2/project08/BeavermapTests.java +++ b/tests/edu/caltech/cs2/project08/BeavermapTests.java @@ -9,7 +9,6 @@ import edu.caltech.cs2.datastructures.Location; import edu.caltech.cs2.helpers.Inspection; import edu.caltech.cs2.helpers.Reflection; -import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; @@ -22,7 +21,7 @@ import edu.caltech.cs2.interfaces.ISet; import org.hamcrest.MatcherAssert; import org.hamcrest.collection.IsIterableContainingInAnyOrder; import org.hamcrest.collection.IsIterableContainingInOrder; -import org.hamcrest.core.IsCollectionContaining; +import org.hamcrest.core.IsIterableContaining; import org.junit.jupiter.api.*; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.TestMethodOrder; @@ -34,16 +33,12 @@ import static org.junit.jupiter.api.Assertions.*; @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class BeavermapTests { private static String BEAVERMAP_GRAPH_SOURCE = "src/edu/caltech/cs2/datastructures/BeaverMapsGraph.java"; - private static JsonParser JSON_PARSER = new JsonParser(); private static JsonElement fromFile(String filename) { - try { - return JSON_PARSER.parse( - new FileReader( - new File(filename) - ) - ); - } catch (IOException e) { + try (FileReader reader = new FileReader(filename)) { + return JsonParser.parseReader(reader); + } + catch (IOException e) { return null; } } @@ -130,6 +125,22 @@ public class BeavermapTests { } } + @Tag("C") + @DisplayName("Test addVertex() updates BeaverMapsGraph properly") + @Test + public void testAddVertexBeaverMapsGraph() { + BeaverMapsGraph bmg = new BeaverMapsGraph( + "data/caltech/caltech.buildings.json", + "data/caltech/caltech.waypoints.json", + "data/caltech/caltech.roads.json"); + JsonElement bs = fromFile("data/pasadena/pasadena.buildings.json"); + for (JsonElement b : bs.getAsJsonArray()) { + Location loc = new Location(b.getAsJsonObject()); + bmg.addVertex(loc); + assertNotNull(bmg.getLocationByID(loc.id), "Location id " + loc.id + " not found by id"); + } + } + @Tag("C") @DisplayName("BeaverMapsGraph implements required public methods") @Test @@ -143,7 +154,7 @@ public class BeavermapTests { .map(x -> x.getName()) .collect(Collectors.toList())); MatcherAssert.assertThat(new ArrayList<>(actual), - IsCollectionContaining.hasItems((expected.toArray()))); + IsIterableContaining.hasItems((expected.toArray()))); } @@ -226,6 +237,33 @@ public class BeavermapTests { } } + @Tag("A") + @DisplayName("Test buildings are ignored in dijkstra path") + @Test + public void testDijkstraIgnoreBuildings() { + BeaverMapsGraph bmg = new BeaverMapsGraph( + "data/caltech/caltech.buildings.json", + "data/caltech/caltech.waypoints.json", + "data/caltech/caltech.roads.json"); + JsonElement s = fromFile("data/caltech/caltech.paths_trace.json"); + for (JsonElement b : s.getAsJsonArray()) { + JsonObject curr = b.getAsJsonObject(); + Location start = bmg.getLocationByID(curr.get("start").getAsLong()); + Location target = bmg.getLocationByID(curr.get("target").getAsLong()); + + IDeque<Location> actualPath = bmg.dijkstra(start, target); + if (actualPath == null) { + continue; + } + for (Location loc : actualPath){ + if (loc.id == start.id || loc.id == target.id) { + continue; + } + ISet<Location> buildings = Reflection.getFieldValue(BeaverMapsGraph.class, "buildings", bmg); + assertFalse(buildings.contains(loc), "Location " + loc.id + " in path is a building"); + } + } + } @Tag("A") @DisplayName("Test Dijkstra") diff --git a/tests/edu/caltech/cs2/project08/DijkstraTest.java b/tests/edu/caltech/cs2/project08/DijkstraTest.java index 10701000cfa3ec1eb97118fb3bff6531fe65b48e..e8ad31e80ff3e653fd61695851a696d0c6caf7e6 100644 --- a/tests/edu/caltech/cs2/project08/DijkstraTest.java +++ b/tests/edu/caltech/cs2/project08/DijkstraTest.java @@ -77,10 +77,12 @@ public class DijkstraTest { Scanner s = new Scanner(new File("data/dijkstra/" + traceFile)); - if (res == null) { - assertEquals(s.nextLine(), "null", "Path exists but was not found"); + String line = s.nextLine(); + if (line.equals("null")) { + assertNull(res, "Path does not exist but was found"); } else { + assertNotNull(res, "Path exists but was not found"); for (Location l : res) { if (prev != null) { pathLen += bmg.adjacent(prev.id, l.id); @@ -88,7 +90,7 @@ public class DijkstraTest { prev = l; } - double expectedLen = s.nextDouble(); + double expectedLen = Double.parseDouble(line); assertEquals(expectedLen, pathLen, "Path lengths are not equivalent"); } @@ -97,7 +99,7 @@ public class DijkstraTest { @Order(3) @DisplayName("Tests Dijkstra on random graph and paths") @Test - public void dijkstraStressTest() throws FileNotFoundException{ + public void dijkstraStressTest() throws FileNotFoundException { final int num_tests = 1000; IGraph<Integer, Integer> refg = new Graph<Integer, Integer>(); @@ -131,10 +133,12 @@ public class DijkstraTest { BeaverMapsGraph bmg = GraphMaker.transformToLocations(refg); IDeque<Location> res = bmg.dijkstra(new Location(startvertex), new Location(endvertex)); - if (res == null) { - assertEquals(s.nextLine(), "null", "Path exists but was not found"); + String line = s.nextLine(); + if (line.equals("null")) { + assertNull(res, "Path does not exist but was found"); } else { + assertNotNull(res, "Path exists but was not found"); double pathLen = 0; Location prev = null; for (Location l : res) { @@ -144,8 +148,7 @@ public class DijkstraTest { prev = l; } - double expectedLen = s.nextDouble(); - s.nextLine(); + double expectedLen = Double.parseDouble(line); assertEquals(expectedLen, pathLen, "Path lengths are not equivalent"); } } diff --git a/tests/edu/caltech/cs2/project08/GraphTests.java b/tests/edu/caltech/cs2/project08/GraphTests.java index c38df58c0cdd768d72c706f8c117d6512ebd7fcd..c15c08cd80c63c12b815f1fb6e853395423b1c96 100644 --- a/tests/edu/caltech/cs2/project08/GraphTests.java +++ b/tests/edu/caltech/cs2/project08/GraphTests.java @@ -187,6 +187,38 @@ public class GraphTests { }); } + @Test + public void undirectedEdgeTest() { + assertTimeout(Duration.ofMillis(SIMPLE_OP_TIMEOUT_MS), () -> { + IGraph<String, Integer> g = new Graph<>(); + + assertTrue(g.addVertex("1"), "Should be able to add a vertex"); + assertEquals(1, g.vertices().size(), "Should have correct number of vertices"); + assertTrue(g.addVertex("2"), "Should be able to add a vertex"); + assertEquals(2, g.vertices().size(), "Should have correct number of vertices"); + assertTrue(g.addVertex("3"), "Should be able to add a vertex"); + assertEquals(3, g.vertices().size(), "Should have correct number of vertices"); + + assertTrue(g.addUndirectedEdge("1", "2", 1), "Should be able to add new edge"); + assertFalse(g.addEdge("1", "2", 1), "Should not be able to add new edge"); + assertFalse(g.addEdge("1", "2", 2), "Should not be able to add new edge"); + assertFalse(g.addEdge("2", "1", 1), "Should not be able to add new edge"); + assertFalse(g.addEdge("2", "1", 2), "Should not be able to add new edge"); + + assertTrue(g.addUndirectedEdge("1", "3", 1), "Should be able to add new edge"); + assertFalse(g.addEdge("1", "3", 1), "Should not be able to add new edge"); + assertFalse(g.addEdge("1", "3", 2), "Should not be able to add new edge"); + assertFalse(g.addEdge("3", "1", 1), "Should not be able to add new edge"); + assertFalse(g.addEdge("3", "1", 2), "Should not be able to add new edge"); + + assertTrue(g.addUndirectedEdge("2", "3", 1), "Should be able to add new edge"); + assertFalse(g.addEdge("2", "3", 1), "Should not be able to add new edge"); + assertFalse(g.addEdge("2", "3", 2), "Should not be able to add new edge"); + assertFalse(g.addEdge("3", "2", 1), "Should not be able to add new edge"); + assertFalse(g.addEdge("3", "2", 2), "Should not be able to add new edge"); + }); + } + @Test public void stringEdgeTest() { assertTimeout(Duration.ofMillis(SIMPLE_OP_TIMEOUT_MS), () -> {