Skip to content

Instantly share code, notes, and snippets.

@Sietesoles
Last active August 29, 2015 14:06
Show Gist options
  • Save Sietesoles/42bbf4bd0089e29f86c6 to your computer and use it in GitHub Desktop.
Save Sietesoles/42bbf4bd0089e29f86c6 to your computer and use it in GitHub Desktop.
Graph of world cities - Implements Dijkstra's Algo
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();
}
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;
}
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();
}
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();
}
}
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