Java tutorial
/* * Copyright (c) 2015 Washington State Department of Transportation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> * */ package main.java.gov.wa.wsdot.candidate.evaluation; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.Collections; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.JSONValue; /** * @author Logan Sims * * App for the WSDOT ITS3 evaluation Nov 23, 2015. * * Given a latitude, longitude, and radius this app display all highway * cameras within given radius of the given latitude and longitude * location. * */ public class App { private final static String URL = "http://www.wsdot.wa.gov/Traffic/api/HighwayCameras/HighwayCamerasREST.svc/GetCamerasAsJson?AccessCode={2b4ac199-3738-4849-98ba-b6e355e8b45a}"; private final static int R = 3959; private double latitude; private double longitude; private int distance; public static void main(String[] args) { System.out.println("Hello WSDOT ITS 3 Candidate!"); System.out.println("Hello WSDOT ITS 3 Interviewers!"); if (args.length != 3) { System.out.println("Parameters: latitude longitude radius\n"); } else { App app = new App(Double.parseDouble(args[0]), Double.parseDouble(args[1]), Integer.parseInt(args[2])); try { app.run(); } catch (Exception e) { e.printStackTrace(); System.exit(0); } } } /** * Constructor * * @param la user latitude * @param lo user longitude * @param dist search distance from user */ public App(double la, double lo, int dist) { this.latitude = la; this.longitude = lo; this.distance = dist; } /** * Starts processing logic. * * @throws Exception */ public void run() throws Exception { ArrayList<Camera> cameras; cameras = scanCameras(generateJSON(getAllCameras()), latitude, longitude, distance); Collections.sort(cameras); printCameras(cameras); } /** * Reads in WSDOT highway camera data from Traveler Information API URL * using the StringBuilder Class. * * @return JSON string read from Traveler Information API. * @throws Exception */ private String getAllCameras() throws Exception { StringBuilder sb = new StringBuilder(); URL url = new URL(URL); URLConnection connection = url.openConnection(); BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); int cp; while ((cp = in.read()) != -1) { sb.append((char) cp); } in.close(); return sb.toString(); } /** * Using methods from org.json.simple to create a JSONArray object from a * JSON string. * * @param jsonString a string representation of a JSON object * @return JSONArray object with camera data */ private JSONArray generateJSON(String jsonString) { return (JSONArray) JSONValue.parse(jsonString); } /** * Returns an ArrayList of Camera objects that are within a given radius of * users location. * * @param jArray JSONArray with WSDOT camera data * @param userLat users current latitude * @param userLong users current longitude * @param radius max distance to look for cameras * @return ArrayList of cameras within max distance of users location */ private ArrayList<Camera> scanCameras(JSONArray jArray, double userLat, double userLong, int radius) { JSONObject jObj1; JSONObject jObj2; double camLat; double camLong; double dist; ArrayList<Camera> cameras = new ArrayList<Camera>(); for (int i = 0; i < jArray.size(); i++) { jObj1 = (JSONObject) jArray.get(i); jObj2 = (JSONObject) jObj1.get("CameraLocation"); camLat = (double) jObj2.get("Latitude"); camLong = (double) jObj2.get("Longitude"); dist = getDistance(userLat, userLong, camLat, camLong); if (dist < radius) { cameras.add(new Camera(jObj1.get("Title").toString(), dist)); } } return cameras; } /** * This method prints the ID and distance of cameras in the input ArrayList. * * @param cameras sorted ArrayList of cameras within set max distance of users * location */ private void printCameras(ArrayList<Camera> cameras) { for (int i = 0; i < cameras.size(); i++) { System.out.printf("%s\n", cameras.get(i).title); } } /** * Using the Haversine formula this method calculates the distance in miles * between two latitude and longitude points. * * Formula from: https://en.wikipedia.org/wiki/Haversine_formula * * @param lat1 latitude of point 1 (user) * @param long1 longitude of point 1 (user) * @param lat2 latitude of point 2 (camera) * @param long2 longitude of point 2 (camera) * @return distance in miles between two points given */ private double getDistance(double lat1, double long1, double lat2, double long2) { double deltaLong; double deltaLat; double hav2; double hav1; lat1 = Math.toRadians(lat1); lat2 = Math.toRadians(lat2); long1 = Math.toRadians(long1); long2 = Math.toRadians(long2); deltaLong = Math.toRadians(long2 - long1); deltaLat = Math.toRadians(lat2 - lat1); hav1 = (Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2)); hav2 = (Math.sin(deltaLong / 2) * Math.sin(deltaLong / 2)); return Math.toDegrees(2 * R * Math.asin(Math.sqrt(hav1 + Math.cos(lat1) * Math.cos(lat2) * hav2))); } }