Last active
August 29, 2015 14:06
-
-
Save Sietesoles/42bbf4bd0089e29f86c6 to your computer and use it in GitHub Desktop.
Graph of world cities - Implements Dijkstra's Algo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.BufferedReader; | |
import java.io.File; | |
import java.io.FileReader; | |
import java.io.IOException; | |
import java.io.Serializable; | |
import java.text.DecimalFormat; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.LinkedList; | |
import java.util.PriorityQueue; | |
import java.util.Random; | |
import java.util.concurrent.atomic.AtomicInteger; | |
public class AGraphMap13 implements Serializable { | |
/** | |
* Adds an Edge. | |
* Returns false if either of the nodes doesn't exist or if the edge already exist. Returns true otherwise. | |
* @param a - String. Source Vertex. | |
* @param b - String. Destination Vertex | |
* @param w - Double. Weight. | |
* @return | |
*/ | |
public boolean addEdge(String a, String b, double w) { | |
//Checks if the source and destination are in place | |
if (!nodesHT.containsKey(a)) { | |
return false; | |
} else if (!nodesHT.containsKey(b)) { | |
return false; | |
} else if (nodesLL.get(a) != null && nodesLL.get(a).contains(b)) { | |
return false; | |
} | |
//Gets the vertex associated with string b. | |
Vertex destination = nodesHT.get(b); | |
//Adds the destination's name to the LL of Vertex a. | |
Object[] temp = {destination.getName(), w}; | |
nodesLL.get(a).add(temp); | |
//Updates the In and Out counter | |
nodesHT.get(b).incInCounter++; | |
nodesHT.get(a).incOutCounter++; | |
//Creates the edge and adds it to the Edge List | |
Edge edge = new Edge(nodesHT.get(a), nodesHT.get(b), w); | |
edgeList.add(edge); | |
String[] temp2 = {a, b}; | |
edgesHT.put(temp2, edge); | |
edgeSize++; | |
return true; | |
} | |
/** | |
* Adds a Vertex. | |
* @param a - String. Vertex Name. | |
* @param lat - Double. Latitude. | |
* @param lon - Double. Longitude. | |
*/ | |
public void addVertex(String city, String state, double lon, double lat, int uid) { | |
if (nodesHT.containsKey(city) && nodesHT.get(city).getState().equals(state)) | |
return; | |
nodesHT.put(city, new Vertex(city, state, lat, lon, uid)); | |
nodesLL.put(city, new LinkedList<Object[]>()); | |
vertexSize++; | |
idHT.put(uid, city); | |
} | |
/** | |
* Returns the linked list of all edges of a particular Vertex | |
* @param a - String. The vertex's name. | |
* @return Linked List | |
*/ | |
public String[] getAllEdgesFromVertex(String a) { | |
LinkedList<Object[]> llist = nodesLL.get(a); | |
String[] result = new String[llist.size()]; | |
for (int i=0; i<llist.size(); i++) { | |
String temp = (String) llist.poll()[0]; | |
result[i] = temp; | |
} | |
return result; | |
} | |
/** | |
* Finds the edge associated with both vertices. | |
* @param a - String. The name of a Vertex. | |
* @param b - String. The name of a Vertex. | |
* @return true if the edge exists. False otherwise. | |
*/ | |
public boolean findEdge(String a, String b) { | |
if (!nodesLL.get(a).contains(b)) | |
return false; | |
return true; | |
} | |
/** | |
* Gets a city from a unique id. | |
* @param id | |
* @return a city name. String. | |
*/ | |
public String getCityFromID(int id) { | |
String city = idHT.get(id); | |
return city; | |
} | |
//Returns the number of edges. | |
public int getEdgeSize() { | |
return edgeSize; | |
} | |
//Returns the number of vertices. | |
public int getVertexSize() { | |
return vertexSize; | |
} | |
/** | |
* Sets up the initial directed connections between cities. | |
* Assigns 2-8 connections with weights that range from 100-2000; | |
*/ | |
public void setConnections() { | |
for (String name : nodesHT.keySet()) { | |
int random = getRandomConnections(); | |
for (int i=0; i<random; i++) { | |
Vertex v= getRandomNode(); | |
//Checks that the destination vertex is not equal to the source | |
//And that there are no duplicate edges | |
while (v.getName() == name && nodesLL.get(v.getName()).contains(name)) | |
v = getRandomNode(); | |
int w = getRandomWeight(); | |
addEdge(name, v.getName(), w); | |
} | |
} | |
} | |
/** | |
* Loads a file into the system and creates a vertex for each city. | |
* @param file | |
* @return | |
*/ | |
public boolean LoadFile(File file) { | |
//If the file has already been entered, it returns false | |
if (files.contains(file.getName())) { | |
return false; | |
} | |
try { | |
BufferedReader buf = new BufferedReader(new FileReader(file)); | |
//Reads in the number of cities to be processed | |
NumOfCities = Integer.parseInt(buf.readLine()); | |
while (true) { | |
String name = buf.readLine(); | |
if (name == null) break; | |
String city = ""; | |
String state = ""; | |
//Checks if the string has both city and state. | |
//If not, copies the name into the state. | |
if (!name.contains(",")) { | |
city = name; | |
state = city; | |
} else { | |
String[] temp = name.split(", "); | |
city = temp[0]; | |
state = temp[1]; | |
} | |
//Gets Latitude and Longitude. | |
double lon = Double.parseDouble(buf.readLine()); | |
double lat = Double.parseDouble(buf.readLine()); | |
//Creates the id | |
int x = createId(); | |
//Creates the vertex if the vertex hasn't been added | |
addVertex(city, state, lon, lat, x); | |
} | |
buf.close(); | |
//Sets the random connections | |
setConnections(); | |
//Adds the file into the list of files | |
files.add(file.getName()); | |
return true; | |
} catch (IOException exception) { | |
exception.printStackTrace(); | |
} | |
return false; | |
} | |
/** | |
* Creates a unique identifier integer. | |
* @return an integer | |
*/ | |
public int createId() { | |
return id.incrementAndGet(); | |
} | |
/** | |
* Sets current city. | |
* @param city | |
*/ | |
public void setCurrentCity(String city) { | |
currentCityVertex = nodesHT.get(city); | |
} | |
/** | |
* Creates a random integer between 2 and 8 | |
* @return an integer | |
*/ | |
public int getRandomConnections() { | |
int result = 2 + rdg.nextInt(6) + 1; | |
return result; | |
} | |
/** | |
* Returns a random vertex. | |
* @return Vertex | |
*/ | |
public Vertex getRandomNode() { | |
Object[] cities = nodesHT.keySet().toArray(); | |
Vertex randomVertex = nodesHT.get(cities[rdg.nextInt(cities.length)]); | |
return randomVertex; | |
} | |
/** | |
* Creates a random integer between 100 and 2000 | |
* @return an integer | |
*/ | |
public int getRandomWeight() { | |
int result = 100 + rdg.nextInt(1900) + 1; | |
return result; | |
} | |
/** | |
* Returns the GPS distance between two vertices. | |
* It uses the standard formula to calculate distance. | |
* @param a - a Vertex. | |
* @param b - a Vertex. | |
* @return Distance. A double. | |
*/ | |
public double getGPSDistance(Vertex a, Vertex b) { | |
//The Haversine formula: | |
double lat1 = a.getLat(); | |
double lon1 = a.getLon(); | |
double lat2 = b.getLat(); | |
double lon2 = b.getLon(); | |
double R = 6371; | |
double dLat = Math.toRadians((lat2-lat1)); | |
double dLon = Math.toRadians((lon2-lon1)); | |
double r = Math.sin(dLat/2) * Math.sin(dLat/2) + | |
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) | |
* Math.sin(dLon/2) * Math.sin(dLon/2); | |
double c = 2 * Math.atan2(Math.sqrt(r), Math.sqrt(1-r)); | |
double distance = R*c; | |
return distance; | |
} | |
/** | |
* Finds the n closest cities by GPS from Current City. | |
* @param n - integer. The number of cities you want to return. | |
* @return a double array of cities. The first entry is the city, the second its weight. | |
*/ | |
public Object[][] findNClosestGPS(int n) { | |
Object [][] result = new Object[n][2]; | |
//Creates a Priority Queue. | |
PriorityQueue<Double> heap = new PriorityQueue<Double>(); | |
//Creates a Hash Table that links distances to cities. | |
HashMap<Double, String> tempHT = new HashMap<Double, String>(); | |
//Creates a for loop across all vertices. Takes O(V) time. | |
for (String name : nodesHT.keySet()) { | |
if (!name.equals(currentCityVertex.getName())) { | |
double distance = getGPSDistance(currentCityVertex, nodesHT.get(name)); | |
heap.add(distance); | |
tempHT.put(distance, name); | |
} | |
} | |
//Retrieves the first n elements from the P.Q. | |
DecimalFormat dFormat = new DecimalFormat("######.#"); | |
for (int i=0; i<n; i++) { | |
double x = heap.poll(); | |
result[i][0] = tempHT.get(x); | |
result[i][1] = dFormat.format(x); | |
} | |
return result; | |
} | |
/** | |
* Searches for all cities in a state. | |
* Returns an array with the name (0), the In counter (1) and Out counter (2). | |
* @param state - a String. | |
* @return an array [x][3] where x is the number of cities. | |
*/ | |
public HashMap<String, Object[]> searchForState(String state) { | |
HashMap<String, Object[]> stateList = new HashMap<String, Object[]>(); | |
for (String name : nodesHT.keySet()) { | |
if (state.equals(nodesHT.get(name).getState())) { | |
Object[] inOut = {nodesHT.get(name).getInCounter(), nodesHT.get(name).getOutCounter()}; | |
stateList.put(name, inOut); | |
} | |
} | |
return stateList; | |
} | |
/** | |
* Returns information about a city. | |
* Returns null if the city is not in the system. | |
* @param city | |
* @return | |
*/ | |
public Object[] searchForCity(String city) { | |
if (!nodesHT.keySet().contains(city)) | |
return null; | |
Vertex v = nodesHT.get(city); | |
Object[] result = new Object[6]; | |
result[0] = v.getID(); | |
result[1] = v.getState(); | |
result[2] = v.getInCounter(); | |
result[3] = v.getOutCounter(); | |
result[4] = v.getLon(); | |
result[5] = v.getLat(); | |
return result; | |
} | |
/** | |
* Runs Dijkstra's Algorithm to find shortest path to every Vertex from CurrentCityVertex | |
*/ | |
public void Dijkstras() { | |
//Marks all nodes as not visited and sets their current path to Integer.Max_Value. | |
//Creates an array of unvisited nodes. | |
ArrayList<String> notVisited = new ArrayList<String>(); | |
for (String name : nodesHT.keySet()) { | |
nodesHT.get(name).isKnown = false; | |
nodesHT.get(name).currentPath = Integer.MAX_VALUE; | |
notVisited.add(name); | |
} | |
//Set the current city's current path = 0 | |
currentCityVertex.currentPath = 0; | |
Vertex copyOfOriginal = currentCityVertex; | |
//areNodesKnown returns true if all cities are known | |
while (!notVisited.isEmpty()) { | |
//Get all adjacent cities from linked list | |
LinkedList<Object[]> neighbors = nodesLL.get(currentCityVertex.getName()); | |
//Initializes the variable next city. | |
String nextCity = ""; | |
double count = Integer.MAX_VALUE; | |
//Sets an iterator for all the cities in the adjacency list that are NOT KNOWN. | |
for (Object[] cityAndWeight : neighbors) { | |
if (!nodesHT.get(cityAndWeight[0]).isKnown) { | |
//Gets the name, vertex and weight from the adjacent city. | |
String adjacentCity = (String)cityAndWeight[0]; | |
Vertex v = nodesHT.get(adjacentCity); | |
double weight = (double) cityAndWeight[1]; | |
double newDistance = weight + currentCityVertex.currentPath; | |
//If the weight is smaller, update. | |
if (v.currentPath > newDistance) { | |
v.currentPath = newDistance; | |
} | |
//Records the closest city to current city | |
if (v.currentPath < count) { | |
count = v.currentPath; | |
nextCity = v.getName(); | |
} | |
} | |
} | |
//Update current city to known | |
currentCityVertex.isKnown = true; | |
notVisited.remove(currentCityVertex.getName()); | |
//Checks if the algorithm is at an impasse | |
if (count == Integer.MAX_VALUE) break; | |
//Sets the current city to the closest to the previous current city. | |
currentCityVertex = nodesHT.get(nextCity); | |
} | |
currentCityVertex = copyOfOriginal; | |
return; | |
} | |
/** | |
* Finds the n closest cities from current city. | |
* If no current city has been set, it chooses a random city. | |
* Essentially equal to findNClosestGPS. For details refer to that method. | |
* @param n - an integer. | |
* @return - a double array of cities. The first entry is the city, the second its weight. | |
*/ | |
public Object[][] findNClosestByEdge(int n) { | |
//Instantiates the result | |
Object[][] result = new Object[n][2]; | |
//If the current city has not been settled, a random one is chosen. | |
if (currentCityVertex == null) | |
currentCityVertex = getRandomNode(); | |
//Instantiates a Priority Queue. | |
PriorityQueue<Double> heap = new PriorityQueue<Double>(); | |
//Sets a HT that links numbers to cities. | |
HashMap<Double, String> tempHT = new HashMap<Double, String>(); | |
//Runs Dijkstra's algorithm. | |
Dijkstras(); | |
//Gets the distances generated by Dijkstra and links each with a cities | |
for (String name : nodesHT.keySet()){ | |
double distance = nodesHT.get(name).currentPath; | |
tempHT.put(distance, name); | |
} | |
//Adds the distances to the P.Q. | |
for (String name: nodesHT.keySet()) { | |
if (!name.equals(currentCityVertex.getName())) { | |
double distance = nodesHT.get(name).currentPath; | |
heap.add(distance); | |
} | |
} | |
//Retrieves the n minimum distances from the P.Q. | |
for (int i=0; i<n; i++) { | |
double x = heap.poll(); | |
result[i][0] = tempHT.get(x); | |
result[i][1] = x; | |
} | |
return result; | |
} | |
/** | |
* Finds the n closest cities by GPS from Current City in which there exists a path between them. | |
* @param n - integer. The number of cities you want to return. | |
* @return a double array of cities. The first entry is the city, te second its weight. | |
*/ | |
public Object[][] nRelatedClosestGPS(int n) { | |
Object [][] result = new Object[n][2]; | |
//Creates a Priority Queue. | |
PriorityQueue<Double> heap = new PriorityQueue<Double>(); | |
//Creates a Hash Table that links distances to cities. | |
HashMap<Double, String> tempHT = new HashMap<Double, String>(); | |
//Creates a for loop across all vertices. Takes O(V) time. | |
for (String name : nodesHT.keySet()) { | |
if (!name.equals(currentCityVertex.getName())) { | |
double distance = getGPSDistance(currentCityVertex, nodesHT.get(name)); | |
heap.add(distance); | |
tempHT.put(distance, name); | |
} | |
} | |
//Updates the current paths of all the nodes (from current node). | |
Dijkstras(); | |
//Goes through the P.Q. | |
//If the city's Curr.Path. is less than Integer.MAX_VALUE | |
//Then a path exists from the current city to that city. | |
DecimalFormat dFormat = new DecimalFormat("#####.#"); | |
int count = 0; | |
for (int i=0; i<nodesHT.size(); i++) { | |
double x = heap.poll(); | |
String city = tempHT.get(x); | |
if (nodesHT.get(city).currentPath != Integer.MAX_VALUE) { | |
result[count][0] = tempHT.get(x); | |
result[count][1] = dFormat.format(x); | |
count++; | |
} | |
if (count==n) break; | |
} | |
return result; | |
} | |
//The DS that keeps all the edges. Helps find edges rapidly. | |
private ArrayList<Edge> edgeList = new ArrayList<Edge>(); | |
//The HT that keeps all the nodes. Helps find nodes rapidly. | |
public HashMap<String, Vertex> nodesHT = new HashMap<String, Vertex>(); | |
//The HT for the adjacency list. Keys are Strings. Values are LLs. Each link is an array of size 2 containing the destination ([0]) and the weight ([1]). | |
private HashMap<String, LinkedList<Object[]>> nodesLL = new HashMap<String, LinkedList<Object[]>>(); | |
//An array containing the files entered in the system | |
ArrayList<String> files = new ArrayList<String>(); | |
//A HT that maps id numbers to cities. | |
private HashMap<Integer, String> idHT = new HashMap<Integer, String>(); | |
private static final long serialVersionUID = 1L; | |
private HashMap<String[], Edge> edgesHT = new HashMap<String[], Edge>(); | |
public int NumOfCities; | |
public Vertex currentCityVertex; | |
private int vertexSize = 0; | |
private int edgeSize = 0; | |
private Random rdg = new Random(); | |
private AtomicInteger id = new AtomicInteger(); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.Serializable; | |
public class Edge implements Serializable { | |
/** | |
* Constructor for Edge Class | |
* @param a - String - The Source | |
* @param b - String - The Destination | |
* @param w - Double - The Weight | |
*/ | |
public Edge (Vertex a, Vertex b, double w) { | |
name = b.getName(); | |
startVertex = a; | |
endVertex = b; | |
weight = w; | |
} | |
/** | |
* Getter for Name | |
* @return | |
*/ | |
public String getName() { | |
return name; | |
} | |
/** | |
* Getter for source | |
* @return | |
*/ | |
public Vertex getStartVertex() { | |
return startVertex; | |
} | |
/** | |
* Getter for destination | |
* @return | |
*/ | |
public Vertex getEndVertex() { | |
return endVertex; | |
} | |
/** | |
* Getter for weight | |
* @return | |
*/ | |
public double getWeight() { | |
return weight; | |
} | |
/** | |
* Setter for weight | |
* @param w | |
*/ | |
public void setWeight(double w){ | |
weight = w; | |
} | |
private static final long serialVersionUID = 1L; | |
private Vertex startVertex; | |
private Vertex endVertex; | |
private double weight; | |
private String name; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.awt.Color; | |
import java.awt.Dimension; | |
import java.awt.FlowLayout; | |
import java.awt.event.ActionEvent; | |
import java.awt.event.ActionListener; | |
import java.io.File; | |
import java.util.Date; | |
import java.util.HashMap; | |
import javax.swing.JButton; | |
import javax.swing.JFileChooser; | |
import javax.swing.JFrame; | |
import javax.swing.JOptionPane; | |
import javax.swing.JTextPane; | |
public class GUI implements ActionListener { | |
public void loadView() { | |
//set up frame | |
frame = new JFrame("Your favorite World Graph! (by dfr2113)"); | |
frame.setSize(500, 700); | |
frame.setMinimumSize(new Dimension(500, 500)); | |
frame.setLayout(new FlowLayout()); | |
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | |
loadFile.addActionListener(this); | |
searchState.addActionListener(this); | |
searchCity.addActionListener(this); | |
setCurrent.addActionListener(this); | |
showCurrent.addActionListener(this); | |
findGPS.addActionListener(this); | |
findEdge.addActionListener(this); | |
findShortest.addActionListener(this); | |
relatedGPS.addActionListener(this); | |
information.addActionListener(this); | |
Quit.addActionListener(this); | |
frame.add(loadFile); | |
frame.add(searchState); | |
frame.add(searchCity); | |
frame.add(setCurrent); | |
frame.add(showCurrent); | |
frame.add(findGPS); | |
frame.add(findEdge); | |
frame.add(findShortest); | |
frame.add(relatedGPS); | |
frame.add(information); | |
frame.add(Quit); | |
textDisplay.setText("Welcome to World Graph"); | |
textDisplay.setSize(new Dimension(300, 400)); | |
textDisplay.setBackground(Color.white); | |
frame.add(textDisplay); | |
frame.setVisible(true); | |
} | |
public void actionPerformed(ActionEvent e) { | |
if (e.getSource() == loadFile) { | |
textDisplay.setText("Please wait while we load your file into the system..."); | |
load(); | |
} | |
if (e.getSource() == searchState) { | |
searchForState(); | |
} | |
if (e.getSource() == searchCity) { | |
searchForCity(); | |
} | |
if (e.getSource() == setCurrent) { | |
setCurrentCity(); | |
} | |
if (e.getSource() == showCurrent) { | |
if (graph.currentCityVertex == null) { | |
textDisplay.setText("You have not yet set a current city"); | |
return; | |
} | |
Object[] result = graph.searchForCity(graph.currentCityVertex.getName()); | |
String text = ""; | |
text = "The city \"" + graph.currentCityVertex.getName() + "\" has id number: " + result[0] + ".\nIt is in the state of: " + result[1] | |
+ ".\nIt has an IN counter of " + result[2] + " and an OUT counter of " + result[3] + ".\nIts GPS coordenates are:\nLatitude: " | |
+ result[4] + "\nLongitude: " + result[5]; | |
textDisplay.setText(text); | |
} | |
if (e.getSource() == findGPS) { | |
findGPS(); | |
} | |
if (e.getSource() == findEdge) { | |
findEdge(); | |
} | |
if (e.getSource() == findShortest) { | |
findShortest(); | |
} | |
if (e.getSource() == relatedGPS) { | |
relatedClosest(); | |
} | |
if (e.getSource() == information) { | |
information(); | |
} | |
if (e.getSource() == Quit) { | |
System.exit(0); | |
} | |
} | |
/** | |
* Method for the findShortest button | |
* It runs Dijkstra's algorithm to find the shortest path | |
* to a specific city. | |
*/ | |
private void findShortest() { | |
if (graph.currentCityVertex == null) { | |
setCurrentCity(); | |
} | |
String input = JOptionPane.showInputDialog("Please enter the name or id of destination"); | |
//We try running it as if the input were an integer | |
//If not, we catch the Number Format Exception and run | |
//The method as if we were expecting a String. | |
try { | |
if (input==null) | |
return; | |
//Here we try to parse the input into an integer | |
int inputInt = Integer.parseInt(input); | |
if (graph.getCityFromID(inputInt) == null) { | |
textDisplay.setText("That id was not found"); | |
return; | |
} | |
String city = graph.getCityFromID(inputInt); | |
if (city.equals(graph.currentCityVertex.getName())) { | |
textDisplay.setText("You are already in " + city + "! It's a Festivus Miracle!"); | |
return; | |
} | |
//Runs Dijkstra's. Every city now has a projected path. | |
graph.Dijkstras(); | |
double distance = graph.nodesHT.get(city).currentPath; | |
//If the distance is equal or greater than Integer.MAX_VALUE | |
//We know that the city cannot be reached through the graph | |
if (distance >= Integer.MAX_VALUE) { | |
textDisplay.setText("You cannot get to " + input + " by following the graph's edges."); | |
return; | |
} | |
textDisplay.setText("The minimum cost of traveling to " + city + " is: " + distance + " units"); | |
return; | |
} catch (NumberFormatException exception) { | |
if (input == null) | |
return; | |
if (!graph.nodesHT.keySet().contains(input)) { | |
textDisplay.setText("That city is not in the graph"); | |
return; | |
} | |
if (input.equals(graph.currentCityVertex.getName())) { | |
textDisplay.setText("You are already in that city! It's a Festivus Miracle!"); | |
return; | |
} | |
graph.Dijkstras(); | |
double distance = graph.nodesHT.get(input).currentPath; | |
if (distance >= Integer.MAX_VALUE) { | |
textDisplay.setText("You cannot get to " + input + " by following the graph's edges."); | |
return; | |
} | |
textDisplay.setText("The minimum cost of traveling to " + input + " is: " + distance + " units"); | |
return; | |
} | |
} | |
/** | |
* Method for the findEdge button | |
* Finds the N closest cities by calling the graph's findNClosestByEdge | |
*/ | |
private void findEdge() { | |
if (graph.currentCityVertex == null) { | |
setCurrentCity(); | |
} | |
String text = ""; | |
try { | |
String input = JOptionPane.showInputDialog("Please enter a positive integer."); | |
if (input == null) | |
return; | |
int n = Integer.parseInt(input); | |
//Checks that n is not greater than the number of vertices | |
if (n > graph.getVertexSize()) { | |
textDisplay.setText("There aren't that many vertices in the graph."); | |
return; | |
} | |
//If the input is invalid we ask again for input | |
if (n<=0) { | |
findEdge(); | |
} else { | |
Object[][] result = graph.findNClosestByEdge(n); | |
text = "The " + n + " closest cities by Edge to " + graph.currentCityVertex.getName() + " are:\n"; | |
for (int i=0; i<result.length; i++) { | |
text += "\"" + result[i][0] + "\" is " + result[i][1] + " units away.\n"; | |
} | |
} | |
} catch (NumberFormatException exception) { | |
//If the input cannot be parsed into an integer, we | |
findEdge(); | |
} | |
textDisplay.setText(text); | |
} | |
/** | |
* Method for the findGPS button | |
* Finds the N closest cities by calling the graph's findNClosestGPS | |
*/ | |
private void findGPS() { | |
if (graph.currentCityVertex == null) { | |
setCurrentCity(); | |
} | |
if (graph.currentCityVertex == null) { | |
return; | |
} | |
String text = ""; | |
try { | |
String input = JOptionPane.showInputDialog("Please enter a positive integer."); | |
if (input == null) | |
return; | |
int n = Integer.parseInt(input); | |
//Checks that n is not greater than the number of vertices | |
if (n > graph.getVertexSize()) { | |
textDisplay.setText("There aren't that many vertices in the graph."); | |
return; | |
} | |
//Checks that the input is valid. If not, it calls the method again. | |
if (n<=0) { | |
findGPS(); | |
} else { | |
Object[][] result = graph.findNClosestGPS(n); | |
text = "The " + n + " closest cities by GPS to " + graph.currentCityVertex.getName() + " are:\n"; | |
for (int i=0; i<result.length; i++) { | |
text += "\"" + result[i][0] + "\": " + result[i][1] + " km away.\n"; | |
} | |
} | |
} catch (NumberFormatException exception) { | |
findGPS(); | |
} | |
textDisplay.setText(text); | |
} | |
/** | |
* Method for the relatedGPS button | |
* Find the N related closest cities by calling the graph's nRelatedClosestGPS method. | |
*/ | |
private void relatedClosest() { | |
if (graph.currentCityVertex == null) { | |
setCurrentCity(); | |
} | |
if (graph.currentCityVertex == null) { | |
return; | |
} | |
String text = ""; | |
try { | |
String input = JOptionPane.showInputDialog("Please enter a positive integer."); | |
if (input == null) | |
return; | |
int n = Integer.parseInt(input); | |
//Checks that n is not greater than the number of vertices | |
if (n > graph.getVertexSize()) { | |
textDisplay.setText("There aren't that many vertices in the graph."); | |
return; | |
} | |
//Checks that the input is valid. If not, it calls the method again. | |
if (n<=0) { | |
relatedClosest(); | |
} else { | |
Object[][] result = graph.nRelatedClosestGPS(n); | |
text = "The " + n + " closest related cities by GPS to " + graph.currentCityVertex.getName() + " are:\n"; | |
for (int i=0; i<result.length; i++) { | |
text += "\"" + result[i][0] + "\": " + result[i][1] + " km away.\n"; | |
} | |
} | |
} catch (NumberFormatException exception) { | |
relatedClosest(); | |
} | |
textDisplay.setText(text); | |
} | |
/** | |
* Sets the current city in the graph | |
*/ | |
private void setCurrentCity() { | |
String input = JOptionPane.showInputDialog("Enter the name or ID of your current city."); | |
if (input==null) | |
return; | |
try { | |
int n = Integer.parseInt(input); | |
if (graph.getCityFromID(n) == null) { | |
textDisplay.setText("That id was not found"); | |
return; | |
} | |
String city = graph.getCityFromID(n); | |
if (!graph.nodesHT.keySet().contains(city)) { | |
textDisplay.setText("That city is not in the graph."); | |
return; | |
} | |
if (graph.currentCityVertex != null && city.equals(graph.currentCityVertex.getName())) { | |
textDisplay.setText("Your current city is already " + city); | |
return; | |
} | |
graph.currentCityVertex = graph.nodesHT.get(city); | |
textDisplay.setText("Success, you have changed your current city to " + city); | |
} catch (NumberFormatException exception) { | |
String city = input; | |
if (!graph.nodesHT.keySet().contains(city)) { | |
textDisplay.setText("That city is not in the graph."); | |
return; | |
} | |
if (graph.currentCityVertex != null && city.equals(graph.currentCityVertex.getName())) { | |
textDisplay.setText("Your current city is already " + city); | |
return; | |
} | |
graph.currentCityVertex = graph.nodesHT.get(city); | |
textDisplay.setText("Success, you have changed your current city to " + city); | |
} | |
} | |
/** | |
* Search for a city in the graph. | |
* Calls the graph's searchForCity method | |
*/ | |
private void searchForCity() { | |
String input = JOptionPane.showInputDialog("Enter the name of the city you are looking for: "); | |
if (input == null) | |
return; | |
if (!graph.nodesHT.containsKey(input)) { | |
textDisplay.setText("That city is not in the graph"); | |
return; | |
} | |
Object[] result = graph.searchForCity(input); | |
String text = ""; | |
text = "The city \"" + input + "\" has id number: " + result[0] + ".\nIt is in the state of: " + result[1] | |
+ ".\nIt has an IN counter of " + result[2] + " and an OUT counter of " + result[3] + ".\nIts GPS coordinates are:\nLatitude: " | |
+ result[4] + "\nLongitude: " + result[5]; | |
textDisplay.setText(text); | |
} | |
/** | |
* Search for all the cities within a state in the graph. | |
* Calls the graph's searchForState method | |
*/ | |
private void searchForState() { | |
//displays the Option Pane | |
String input = JOptionPane.showInputDialog("Please enter the name of a State :"); | |
if (input == null) | |
return; | |
HashMap<String, Object[]> cities = graph.searchForState(input); | |
if (cities.size() == 0) { | |
textDisplay.setText("No cities were found."); | |
return; | |
} | |
String text = "The following cities are in the state of \"" + input + "\"\n" ; | |
for (String city : cities.keySet()) { | |
text += "\"" + city + "\" has " + cities.get(city)[0] + " IN counter and " + cities.get(city)[1] + " OUT counter\n"; | |
} | |
textDisplay.setText(text); | |
} | |
/** | |
* Loads a file. | |
* Prompts a user to select which file to open. | |
* Calls on the graph's LoadFile method. | |
*/ | |
private void load() { | |
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); | |
int val = chooser.showOpenDialog(loadFile); | |
if (val == JFileChooser.APPROVE_OPTION) { | |
File file = chooser.getSelectedFile(); | |
if (!graph.LoadFile(file)) { | |
textDisplay.setText("\"" + file.getName() +"\" was not loaded into the graph. You may have already loaded it before."); | |
} else { | |
textDisplay.setText("Success! You have loaded \"" + file.getName() + "\" into your system.\nThe file contained " + graph.NumOfCities + " cities."); | |
} | |
} else { | |
textDisplay.setText("Operation cancelled."); | |
} | |
} | |
/** | |
* Loads the text file containing all the information | |
* about the program | |
*/ | |
private void information(){ | |
Date date = new Date(); | |
String text = ("Author: Diego F Rincon Santana\nUNI: dfr2113\nHello \"" + System.getProperty("user.name") + "\" (if that is your real name)\nYou are using Java " + System.getProperty("java.version") | |
+ "\nIt is currently: " + date + "\nAnd you are running this on: " + System.getProperty("os.name") + | |
"\nThis program simulates a graph between cities. It allows you\nto play around with paths and GPS coordinates." + | |
"\nIf you're looking for more detailed information about how to\noperate this program please go to the ReadMe file."); | |
textDisplay.setText(text); | |
} | |
public AGraphMap13 graph = new AGraphMap13(); | |
private JFrame frame; | |
private JButton loadFile = new JButton("Load File"); | |
private JButton searchState = new JButton("Search by State"); | |
private JButton searchCity = new JButton("Search City"); | |
private JButton setCurrent = new JButton("Set Current City"); | |
private JButton showCurrent = new JButton("Show Current City"); | |
private JButton findGPS = new JButton("Find N closest cities by GPS"); | |
private JButton relatedGPS = new JButton("Find N related closest cities by GPS"); | |
private JButton findEdge = new JButton("Find N closest cities by Edge cost"); | |
private JButton findShortest = new JButton("Find shortest path to: "); | |
private JButton Quit = new JButton("Quit"); | |
private JButton information = new JButton("Information"); | |
private JFileChooser chooser = new JFileChooser(); | |
public JTextPane textDisplay = new JTextPane(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.BufferedReader; | |
import java.io.File; | |
import java.io.FileReader; | |
import java.io.IOException; | |
import java.util.HashMap; | |
public class mainfl3 { | |
/** | |
* Loads a file | |
* @param gui | |
* @param input | |
*/ | |
private static void a (GUI gui, String input) { | |
File file2 = new File(input); | |
if (!file2.exists()) { | |
System.out.println("That file doesn't exist."); | |
} else { | |
if (gui.graph.LoadFile(file2)){ | |
System.out.println("Success! You have loaded \"" + file2.getName() + "\" The file contained " + gui.graph.NumOfCities + " cities.\n"); | |
} | |
else { | |
System.out.println("Something went wrong, the file was not loaded.\n"); | |
} | |
} | |
} | |
/** | |
* Searches for state | |
* @param gui | |
* @param input | |
*/ | |
private static void b (GUI gui, String input) { | |
HashMap<String, Object[]> cities = gui.graph.searchForState(input); | |
if (cities.size() == 0) { | |
System.out.println("No cities were found.\n"); | |
return; | |
} | |
String text = "The following cities are in the state of \"" + input + "\"\n" ; | |
for (String city : cities.keySet()) { | |
text += "\"" + city + "\" has " + cities.get(city)[0] + " IN counter and " | |
+ cities.get(city)[1] + " OUT counter\n"; | |
} | |
System.out.println(text); | |
} | |
/** | |
* Searches for city | |
* @param gui | |
* @param input | |
*/ | |
private static void c (GUI gui, String input) { | |
if (!gui.graph.nodesHT.containsKey(input)) { | |
System.out.println("That city is not in the graph.\n"); | |
return; | |
} | |
Object[] result = gui.graph.searchForCity(input); | |
String text = ""; | |
text = "The city \"" + input + "\" has id number: " + result[0] + ".\nIt is in the state of: " + result[1] | |
+ ".\nIt has an IN counter of " + result[2] + " and an OUT counter of " + result[3] + ".\nIts GPS coordenates are:\nLatitude: " | |
+ result[4] + "\nLongitude: " + result[5]; | |
System.out.println(text + "\n"); | |
} | |
/** | |
* Sets the current city vertex | |
* @param gui | |
* @param input | |
*/ | |
private static void d (GUI gui, String input) { | |
try { | |
int n = Integer.parseInt(input); | |
if (gui.graph.getCityFromID(n) == null) { | |
System.out.println("That id was not found.\n"); | |
return; | |
} | |
String city = gui.graph.getCityFromID(n); | |
if (!gui.graph.nodesHT.keySet().contains(city)) { | |
System.out.println("That city is not in the graph.\n"); | |
return; | |
} | |
if (gui.graph.currentCityVertex != null && city.equals(gui.graph.currentCityVertex.getName())) { | |
System.out.println("Your current city is already \"" + city + "\"\n"); | |
return; | |
} | |
gui.graph.currentCityVertex = gui.graph.nodesHT.get(city); | |
System.out.println("Success! You have changed your current city to \"" + city + "\"\n"); | |
} catch (NumberFormatException exception) { | |
String city = input; | |
if (!gui.graph.nodesHT.keySet().contains(city)) { | |
System.out.println("That city is not in the graph."); | |
return; | |
} | |
if (gui.graph.currentCityVertex != null && city.equals(gui.graph.currentCityVertex.getName())) { | |
System.out.println("Your current city is already \"" + city + "\"\n"); | |
return; | |
} | |
gui.graph.currentCityVertex = gui.graph.nodesHT.get(city); | |
System.out.println("Success! You have changed your current city to \"" + city + "\"\n"); | |
} | |
} | |
/** | |
* Shows the current city vertex | |
* @param gui | |
* @param input | |
*/ | |
private static void e (GUI gui) { | |
if (gui.graph.currentCityVertex == null) { | |
System.out.println("You have not yet set a current city.\n"); | |
return; | |
} | |
Object[] result = gui.graph.searchForCity(gui.graph.currentCityVertex.getName()); | |
String text = ""; | |
text = "The city \"" + gui.graph.currentCityVertex.getName() + "\" has id number: " + result[0] + ".\nIt is in the state of: " + result[1] | |
+ ".\nIt has an IN counter of " + result[2] + " and an OUT counter of " + result[3] + ".\nIts GPS coordenates are:\nLatitude: " | |
+ result[4] + "\nLongitude: " + result[5]; | |
System.out.println(text + "\n"); | |
} | |
/** | |
* Finds the N closest cities by GPS | |
* @param gui | |
* @param input | |
*/ | |
private static void f (GUI gui, String input) { | |
if (gui.graph.currentCityVertex == null) { | |
System.out.println("You haven't set a current city\n"); | |
return; | |
} | |
String text = ""; | |
try { | |
int n = Integer.parseInt(input); | |
//Checks that n is not greater than the number of vertices | |
if (n > gui.graph.getVertexSize()) { | |
System.out.println("There aren't that many vertices in the graph.\n"); | |
return; | |
} | |
//Checks that the input is valid. | |
if (n<=0) { | |
System.out.println("The input was not valid.");; | |
} else { | |
Object[][] result = gui.graph.findNClosestGPS(n); | |
text = "The " + n + " closest cities by GPS to " + gui.graph.currentCityVertex.getName() + " are:\n"; | |
for (int i=0; i<result.length; i++) { | |
text += "\"" + result[i][0] + ".\": " + result[i][1] + " km away.\n"; | |
} | |
} | |
} catch (NumberFormatException exception) { | |
System.out.println("The input was not valid.\n"); | |
} | |
System.out.println(text); | |
} | |
/** | |
* Finds the N closest cities by Edge | |
* @param gui | |
* @param input | |
*/ | |
private static void g (GUI gui, String input) { | |
if (gui.graph.currentCityVertex == null) { | |
System.out.println("You haven't set a current city.\n"); | |
return; | |
} | |
String text = ""; | |
try { | |
int n = Integer.parseInt(input); | |
//Checks that n is not greater than the number of vertices | |
if (n > gui.graph.getVertexSize()) { | |
System.out.println("There aren't that many vertices in the graph.\n"); | |
return; | |
} | |
//If the input is invalid we ask again for input | |
if (n<=0) { | |
System.out.println("The input was not valid"); | |
} else { | |
Object[][] result = gui.graph.findNClosestByEdge(n); | |
text = "The " + n + " closest cities by Edge to " + gui.graph.currentCityVertex.getName() + " are:\n"; | |
for (int i=0; i<result.length; i++) { | |
text += result[i][0] + " is " + result[i][1] + " units away.\n"; | |
} | |
} | |
} catch (NumberFormatException exception) { | |
//If the input cannot be parsed into an integer, we | |
System.out.println("The input was not valid.\n"); | |
} | |
System.out.println(text); | |
} | |
/** | |
* Finds the shortest path to a specific city | |
* @param gui | |
* @param input | |
*/ | |
private static void h (GUI gui, String input) { | |
if (gui.graph.currentCityVertex == null) { | |
System.out.println("You haven't set a current city.\n"); | |
return; | |
} | |
try { | |
//Here we try to parse the input into an integer | |
int inputInt = Integer.parseInt(input); | |
if (gui.graph.getCityFromID(inputInt) == null) { | |
System.out.println("That id was not found.\n"); | |
return; | |
} | |
String city = gui.graph.getCityFromID(inputInt); | |
if (city.equals(gui.graph.currentCityVertex.getName())) { | |
System.out.println("You are already in that city! It's a Festivus Miracle!\n"); | |
return; | |
} | |
//Runs Dijkstra's. Every city now has a projected path. | |
gui.graph.Dijkstras(); | |
double distance = gui.graph.nodesHT.get(city).currentPath; | |
//If the distance is equal or greater than Integer.MAX_VALUE | |
//We know that the city cannot be reached through the graph | |
if (distance >= Integer.MAX_VALUE) { | |
System.out.println("You cannot get to " + input + " by following the graph's edges.\n"); | |
return; | |
} | |
System.out.println("The minimum cost of traveling to " + city + " is: " + distance + " units.\n"); | |
return; | |
} catch (NumberFormatException exception) { | |
if (!gui.graph.nodesHT.keySet().contains(input)) { | |
System.out.println("That city is not in the graph.\n"); | |
return; | |
} | |
if (input.equals(gui.graph.currentCityVertex.getName())) { | |
System.out.println("You are already in that city! It's a Festivus Miracle!\n"); | |
return; | |
} | |
gui.graph.Dijkstras(); | |
double distance = gui.graph.nodesHT.get(input).currentPath; | |
if (distance >= Integer.MAX_VALUE) { | |
System.out.println("You cannot get to " + input + " by following the graph's edges.\n"); | |
return; | |
} | |
System.out.println("The minimum cost of traveling to " + input + " is: " + distance + " units.\n"); | |
return; | |
} | |
} | |
/** | |
* Finds the N closest related cities by GPS | |
* @param gui | |
* @param input | |
*/ | |
private static void i (GUI gui, String input) { | |
if (gui.graph.currentCityVertex == null) { | |
System.out.println("You haven't set a current city\n"); | |
return; | |
} | |
String text = ""; | |
try { | |
int n = Integer.parseInt(input); | |
//Checks that n is not greater than the number of vertices | |
if (n > gui.graph.getVertexSize()) { | |
System.out.println("There aren't that many vertices in the graph.\n"); | |
return; | |
} | |
//Checks that the input is valid. If not, it calls the method again. | |
if (n<=0) { | |
System.out.println("The input was not valid.");; | |
} else { | |
Object[][] result = gui.graph.nRelatedClosestGPS(n); | |
text = "The " + n + " closest related cities by GPS to " + gui.graph.currentCityVertex.getName() + " are:\n"; | |
for (int i=0; i<result.length; i++) { | |
text += "\"" + result[i][0] + ".\": " + result[i][1] + " km away.\n"; | |
} | |
} | |
} catch (NumberFormatException exception) { | |
System.out.println("The input was not valid.\n"); | |
} | |
System.out.println(text); | |
} | |
public static void main(String[] args) { | |
//Initializes the GUI | |
GUI gui = new GUI(); | |
if (args.length == 1) { | |
try { | |
File file = new File(args[0]); | |
BufferedReader buf = new BufferedReader(new FileReader(file)); | |
while (true) { | |
String menuOption = buf.readLine(); | |
if (menuOption==null) break; | |
//Checks if the option is "e" (Show current city) | |
//This is the only method that doesn't require any input | |
//For this reason we must consider this case as special | |
if (!menuOption.equals("e")) { | |
String input = buf.readLine(); | |
if (input==null) break; | |
if (menuOption.equals("a")) { | |
a(gui, input); | |
} | |
if (menuOption.equals("b")) { | |
b(gui, input); | |
} | |
if (menuOption.equals("c")) { | |
c(gui, input); | |
} | |
if (menuOption.equals("d")) { | |
d(gui, input); | |
} | |
if (menuOption.equals("f")) { | |
f(gui, input); | |
} | |
if (menuOption.equals("g")) { | |
g(gui, input); | |
} | |
if (menuOption.equals("h")) { | |
h(gui, input); | |
} | |
if (menuOption.equals("i")) { | |
i(gui, input); | |
} | |
} | |
if (menuOption.equals("e")) { | |
e(gui); | |
} | |
} | |
buf.close(); | |
} catch (IOException exception) { | |
System.out.println("No file found."); | |
} | |
} | |
//Loads the GUI | |
gui.loadView(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.Serializable; | |
public class Vertex implements Serializable { | |
/** | |
* Constructor for the Vertex Class. If State is null, it assigns the name of the city as the state. | |
* @param city - String | |
* @param st - String | |
* @param lat - Double | |
* @param lon - Double | |
* @param uid - Integer | |
*/ | |
public Vertex(String city, String st, double lon, double lat, int uid) { | |
name = city; | |
state = st; | |
latitude = lat; | |
longitude = lon; | |
UID = uid; | |
isVisited = false; | |
currentPath = Integer.MAX_VALUE; | |
isKnown = false; | |
} | |
/** | |
* Getter for name | |
* @return | |
*/ | |
public String getName() { | |
return name; | |
} | |
/** | |
* Getter for Latitude | |
* @return | |
*/ | |
public double getLat() { | |
return latitude; | |
} | |
/** | |
* Getter for Longitude | |
* @return | |
*/ | |
public double getLon() { | |
return longitude; | |
} | |
/** | |
* Getter for State | |
* @return | |
*/ | |
public String getState() { | |
return state; | |
} | |
/** | |
* Getter for the Out Counter | |
* @return | |
*/ | |
public int getOutCounter() { | |
return incOutCounter; | |
} | |
/** | |
* Getter for the IN Counter | |
* @return | |
*/ | |
public int getInCounter() { | |
return incInCounter; | |
} | |
/** | |
* Setter for Latitude | |
* @param lat | |
*/ | |
public void setLatitude(double lat) { | |
latitude = lat; | |
} | |
/** | |
* Setter for Longitude | |
* @param lon | |
*/ | |
public void setLongitude(double lon) { | |
longitude = lon; | |
} | |
/** | |
* Getter for ID | |
* @return | |
*/ | |
public int getID() { | |
return UID; | |
} | |
private static final long serialVersionUID = 1L; | |
private String name; | |
public int incOutCounter; | |
public int incInCounter; | |
private double latitude; | |
private double longitude; | |
private String state; | |
private int UID; | |
public boolean isVisited; | |
public boolean isKnown; | |
public double currentPath; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment