package heufybot.modules; import heufybot.utils.StringUtils; import heufybot.utils.URLUtils; import org.apache.commons.lang3.text.WordUtils; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; public class WeatherInterface { private final static String WEATHER_ADDRESS = "http://api.openweathermap.org/data/2.5/weather?"; private final static String FORECAST_ADDRESS = "http://api.openweathermap.org/data/2.5/forecast/daily?"; public String getWeather(float latitude, float longitude) throws ParseException { StringBuilder builder = new StringBuilder(); builder.append(WEATHER_ADDRESS); builder.append("lat=" + latitude); builder.append("&lon=" + longitude); JSONObject object = this.getJSON(builder.toString()); String parsedJSON = this.parseJSONForWeather(object); if (parsedJSON == null) { return null; } return parsedJSON; } public String getForecast(float latitude, float longitude) throws ParseException { StringBuilder builder = new StringBuilder(); builder.append(FORECAST_ADDRESS); builder.append("lat=" + latitude); builder.append("&lon=" + longitude); builder.append("&cnt=4"); JSONObject object = this.getJSON(builder.toString()); if (object == null) { return "OpenWeatherMap seems to be down right now. Try again later."; } String parsedJSON = this.parseJSONForForecast(object); if (parsedJSON == null) { return null; } return parsedJSON; } private String parseJSONForWeather(JSONObject object) { if (!object.get("cod").toString().equals("200")) { return null; } JSONObject main = (JSONObject) object.get("main"); JSONObject wind = (JSONObject) object.get("wind"); JSONObject weather = (JSONObject) ((JSONArray) object.get("weather")).get(0); double tempK = StringUtils.tryParseDouble(main.get("temp").toString()); double tempC = round((tempK - 273.15), 1); double tempF = round((tempK - 273.15) * 9 / 5 + 32, 1); int humidity = StringUtils.tryParseInt(main.get("humidity").toString()); double windspeed = StringUtils.tryParseDouble(wind.get("speed").toString()); double windspeedMiles = round(windspeed, 1); double windspeedKmph = round(windspeed * 1.60934, 1); String windDir = convertWindDirToCardinal(StringUtils.tryParseDouble(wind.get("deg").toString())); String description = WordUtils.capitalizeFully(weather.get("description").toString()); long unixTime = System.currentTimeMillis() / 1000L; long latestUpdate = (unixTime - StringUtils.tryParseLong(object.get("dt").toString())) / 60; String latestUpdateString = "just now"; if (latestUpdate > 0) { latestUpdateString = String.format("%s minute(s) ago", latestUpdate); } return String .format("Temp: %s°C / %s°F | Weather: %s | Humidity: %s%c | Wind Speed: %s kmph / %s mph | Wind " + "Direction: %s | Latest Update: %s.", tempC, tempF, description, humidity, '%', windspeedKmph, windspeedMiles, windDir, latestUpdateString); } private String parseJSONForForecast(JSONObject object) { if (!object.get("cod").toString().equals("200")) { return null; } JSONArray list = (JSONArray) object.get("list"); DateFormat format2 = new SimpleDateFormat("EEEEEEEE", Locale.US); List<String> days = new ArrayList<String>(); for (int i = 0; i < list.size(); i++) { JSONObject day = (JSONObject) list.get(i); JSONObject temp = (JSONObject) day.get("temp"); JSONObject weather = (JSONObject) ((JSONArray) day.get("weather")).get(0); Date date = new Date(StringUtils.tryParseLong(day.get("dt").toString()) * 1000); String dayOfWeek = format2.format(date); double minK = StringUtils.tryParseDouble(temp.get("min").toString()); double maxK = StringUtils.tryParseDouble(temp.get("max").toString()); double minC = round((minK - 273.15), 1); double minF = round((minK - 273.15) * 9 / 5 + 32, 1); double maxC = round((maxK - 273.15), 1); double maxF = round((maxK - 273.15) * 9 / 5 + 32, 1); String description = WordUtils.capitalizeFully(weather.get("description").toString()); days.add(String.format("%s: %s - %s°C, %s - %s°F, %s", dayOfWeek, minC, maxC, minF, maxF, description)); } return StringUtils.join(days, " | "); } private JSONObject getJSON(String urlString) throws ParseException { String weather = URLUtils.grab(urlString); if (weather != null) { return (JSONObject) new JSONParser().parse(weather); } return null; } private String convertWindDirToCardinal(double degrees) { String directions[] = { "N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW" }; int i = (int) ((degrees + 11.25) / 22.5); return directions[i % 16]; } private double round(double value, int places) { if (places < 0) { return 0.0; } BigDecimal bd = new BigDecimal(value); bd = bd.setScale(places, RoundingMode.HALF_UP); return bd.doubleValue(); } }