-
Notifications
You must be signed in to change notification settings - Fork 0
/
DisasterRelief.java 1.2
246 lines (203 loc) · 10.5 KB
/
DisasterRelief.java 1.2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
/*
CSC-346 Data Exchange Technologies Assignment 02 Disaster Relief Simulation
The agency needs a program that takes a 5-digit zip code and a distance in miles. The program should produce a list
of places within the given distance of the specified zip code along with the total population and the total number of
housing units.
For example, if given a zip code of 64507 and a distance of 300, the program would give a list of all places within
300 miles of St. Joseph. Each place should be listed only once, even if it has several zip codes. For each place be
sure to list the place name, state, the total population, and the total number of housing units. It should also list
the distance from the source in both kilometers and miles.
If there are several zip codes for a place, use any of the distances you calculated. Obviously this program is going
to miss places outside the US if you give a latitude and longitude near a US border. We can't help that at this point.
Also, you may find that at the borders a place may be partially in or partially out. Don't sweat that too much.
It is just fine if you only calculate the parts that are within the specified distance.
In practice during most disasters the borders of the affected areas are always a bit fuzzy. Here are a couple of
resources you can try using. I think all the information you need is within them.
When you are doing places, make sure you don't combine two cities in different states. If you search for cities
with 200 miles of St. Louis you should have both Springfield, MO and Springfield, IL listed as different places.
*/
import java.sql.*;
import java.util.*;
public class DET_02_DisasterRelief {
static Connection connection;
static ResultSet rsSet;
static Statement statement;
public static void main(String[] args) {
//create scanner for user input of zip code and miles
Scanner scan = new Scanner(System.in);
//input for zipcode
System.out.print("Please enter 5-digit zip code: ");
String zipCode = scan.next();
//loop to ensure zipCode is correct
while (!zipCode.matches("[0-9]+") || zipCode.length() != 5) {
if (!zipCode.matches("[0-9]+")) {
System.out.print("An alphabetical letter was used. Please enter 5-digit zip code: ");
zipCode = scan.next();
} else if (zipCode.length() < 5) {
System.out.print("Too few digits used. Please enter 5-digit zip code: ");
zipCode = scan.next();
} else {
System.out.print("Too many digits used. Please enter 5-digit zip code: ");
zipCode = scan.next();
}
}
//input for distance
System.out.print("Please enter miles from disaster wanted: ");
double distInMiles = scan.nextDouble() * 1.60934;
//loop to ensure distance isn't negative
while (distInMiles <= 0) {
System.out.println("It appears a negative number was entered. Please use positive numbers for distance.");
System.out.print("Please enter miles from disaster wanted: ");
distInMiles = scan.nextDouble();
}
//credentials to use to access the database
String host = "jdbc:mysql://turing.cs.missouriwestern.edu:3306/misc";
String user = "csc254";
String password = "age126";
//strings to be fed into the database queries
String queryStringAll = "SELECT zips.city, zips2.state, zips2.locationtype, zips.population, zips.housingunits, "+
"zips2.zipcode, zips.lat, zips.lon FROM zips inner join zips2 on zip_code=zipcode WHERE NOT state = 'PR' "+
"AND locationtype = 'PRIMARY' ORDER BY zipcode ASC";
String queryStringForZip = "SELECT zipcode, lat, `long` FROM zips2 where locationtype = 'PRIMARY' AND zipcode = " + zipCode;
try {
//create a connection to the database
connection = DriverManager.getConnection(host, user, password);
//temporary variables to start latitude and longitude
double startLat = 0.0;
double startLong = 0.0;
//query to find latitude and longitude for initial zipCode
statement = connection.createStatement();
rsSet = statement.executeQuery(queryStringForZip);
while (rsSet.next()) {
startLat = rsSet.getDouble("lat");
startLong = rsSet.getDouble("long");
}
//create arraylist to hold cities, states and other info
ArrayList<Place> disasterCities = new ArrayList<>();
//create a statement, set it to be the above queryStringAll
statement = connection.createStatement();
rsSet = statement.executeQuery(queryStringAll);
//looking through the database for the specified info
while (rsSet.next()) {
//set city, state, and other variables to use in Place
String city = rsSet.getString("city");
String state = rsSet.getString("state");
String locationType = rsSet.getString("locationtype");
int population = rsSet.getInt("population");
int houses = rsSet.getInt("housingunits");
String zipcode = rsSet.getString("zipcode");
double lat = rsSet.getDouble("lat");
double lon = rsSet.getDouble("lon");
//create new place
Place place = new Place(city, state, locationType, population, houses, zipcode, lat, lon);
//find distance of place from origin and store it
place.setDistFromOrigin(haversine.totDistance(startLat, startLong, lat, lon));
//if it is within the user specified distance, put it into the array
if(place.getDistFromOrigin()<distInMiles){
disasterCities.add(place);
}
}
//iterate through the array, adding population and houses to first occurance of a city, then removing other occurances of that place
for(int i = 0; i<disasterCities.size(); i++) {
for (int j = 0; j < disasterCities.size(); j++) {
if (i == j) {
continue;
}
else if(disasterCities.get(i).getCity().equals(disasterCities.get(j).getCity())&&disasterCities.get(i).getState().equals(disasterCities.get(j).getState()) || disasterCities.get(i).getZipCode().equals(disasterCities.get(j).getZipCode())){
disasterCities.get(i).setPopulation(disasterCities.get(i).getPopulation()+disasterCities.get(j).getPopulation());
disasterCities.get(i).setHouses(disasterCities.get(i).getHouses()+disasterCities.get(j).getHouses());
disasterCities.remove(j);
j=-1;
}
}
}
//Currently prints out the array to the console
for(int i = 0; i<disasterCities.size(); i++){
if(disasterCities.get(i).getPopulation()>0){
System.out.printf("%-25s,\t%-2s\t%-5s,\tpopulation = %8d,\thousing units = %8d\n",
disasterCities.get(i).getCity(), disasterCities.get(i).getState(), disasterCities.get(i).getZipCode(),
disasterCities.get(i).getPopulation(), disasterCities.get(i).getHouses());
}
}
//close connection to the database
connection.close();
}
catch(SQLException e){
System.out.println("Trouble accessing information in the database");
System.exit(1);
}
}
}
//creating the class Place to later create place objects and store information like zipcode and population
class Place {
private String city;
private String state;
String locationType;
private String zipCode;
double latitude;
double longitude;
private double distFromOrigin;
private int houses;
private int population;
//constructor for Place
public Place(String city, String state, String locationType, int population, int houses, String zipCode, double latitude, double longitude) {
this.city = city;
this.state = state;
this.locationType = locationType;
this.zipCode = zipCode;
this.houses = houses;
this.population = population;
this.latitude = latitude;
this.longitude = longitude;
this.distFromOrigin = 0.0;
}
public String getCity() {
return city;
}
public String getState() {
return state;
}
public int getPopulation() {
return population;
}
public void setPopulation(int population) {
this.population = population;
}
public int getHouses() {
return houses;
}
public void setHouses(int houses) {
this.houses = houses;
}
public String getZipCode() {
return zipCode;
}
public double getDistFromOrigin() {
return distFromOrigin;
}
public void setDistFromOrigin(double distFromOrigin) {
this.distFromOrigin = distFromOrigin;
}
public double getLatitude(){
return latitude;
}
public double getLongitude(){
return longitude;
}
}
//creation of class haversine
class haversine {
//constant Earth's Radius
private final static double eRadiusKm = 6371.0;
//creation of haversine's constructor
public static double totDistance(double startLat, double startLong, double endLat, double endLong){
double deltaLat = Math.toRadians(endLat-startLat);
double deltaLong = Math.toRadians(endLong-startLong);
startLat = Math.toRadians(startLat);
endLat = Math.toRadians(endLat);
double tempA = Math.pow(Math.sin(deltaLat/2.0), 2.0)+Math.cos(startLat)*Math.cos(endLat)*Math.pow(Math.sin(deltaLong/2.0), 2.0);
double tempC = 2.0*Math.atan2(Math.sqrt(tempA),Math.sqrt(1.0-tempA));
double distance = Math.round((eRadiusKm * tempC *.621371)* 10000.0) / 10000.0;
return distance;
}//credit to Jason Winn, http://jasonwinn.org, Created July 10, 2013, with a few tweaks made by me (rounding)
}