Java tutorial
/* * Copyright (c) <2013> <Jim Johnson jimj@jimj.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package net.jimj.automaton.commands; import com.fasterxml.jackson.databind.JsonNode; import net.jimj.automaton.events.BehaviorEvent; import net.jimj.automaton.events.ReplyEvent; import net.jimj.automaton.model.User; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.utils.URIBuilder; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.URI; public class WeatherCommand extends Command { private static final Logger LOGGER = LoggerFactory.getLogger(WeatherCommand.class); private static final double SECONDS_PER_HOUR = 3600d; private static final double METERS_PER_MILE = 1609.34d; private static final String[] RANDOM_LOCATIONS = { "hooker,ok", "crapstone", "timbuktu", "blowhard", "condom" }; //Version 2.5 //http://bugs.openweathermap.org/projects/api/wiki/Weather_Data private static final String WEATHER_API_URL = "http://api.openweathermap.org/data/2.5/weather"; @Override public String getCommandName() { return "weather"; } @Override public void execute(User user, String args) { String weatherLocation = args; if (StringUtils.isEmpty(weatherLocation)) { weatherLocation = user.getFirstPreference("city", "location"); if (StringUtils.isEmpty(weatherLocation)) { addEvent(new ReplyEvent(user, "You don't have a preference set so I'll pick a location for you.")); weatherLocation = RANDOM_LOCATIONS[RANDOM.nextInt(RANDOM_LOCATIONS.length)]; } } HttpGet getWeatherMethod = null; try { URI getWeatherURI = new URIBuilder(WEATHER_API_URL).addParameter("q", weatherLocation).build(); getWeatherMethod = new HttpGet(getWeatherURI); HttpResponse response = HTTP_CLIENT.execute(getWeatherMethod); if (response.getStatusLine().getStatusCode() != 200) { throw new IOException("Got status code " + response.getStatusLine().getStatusCode()); } String body = EntityUtils.toString(response.getEntity()); System.out.println(body); JsonNode parentNode = OBJECT_MAPPER.readTree(body); String locationName = parentNode.get("name").asText(); //Toplevel node has temp, wind node, 'weather' node (conditions) JsonNode mainNode = parentNode.get("main"); double tempK = mainNode.get("temp").asDouble(); double tempC = tempK - 273.15d; double tempF = tempC * 1.8d + 32; StringBuilder weatherString = new StringBuilder(locationName).append(": "); weatherString.append(String.format("Temperature %.1f F (%.1f C)", tempF, tempC)); JsonNode windNode = parentNode.get("wind"); double windSpeedMPS = windNode.get("speed").asDouble(); //mps * 60 seconds * 60 minutes / 1 mile in meters double windSpeedMPH = windSpeedMPS * SECONDS_PER_HOUR / METERS_PER_MILE; weatherString.append(" | ").append(String.format("Wind Speed %.2f mph", windSpeedMPH)); JsonNode gustNode = windNode.get("gust"); if (gustNode != null) { double windGustMPS = gustNode.asDouble(); double windGustMPH = windGustMPS * SECONDS_PER_HOUR / METERS_PER_MILE; weatherString.append(" | ").append(String.format("Wind Gust %.2f mph", windGustMPH)); } JsonNode weatherNode = parentNode.get("weather"); if (weatherNode != null && weatherNode.size() > 0) { weatherString.append(" | Conditions "); for (int i = 0; i < weatherNode.size(); i++) { if (i != 0) { weatherString.append(", "); } weatherString.append(weatherNode.get(i).get("description").asText()); } } addEvent(new ReplyEvent(user, weatherString.toString())); } catch (Exception e) { LOGGER.error("Error getting weather for " + weatherLocation, e); addEvent(new BehaviorEvent(user, BehaviorEvent.Behavior.SORRY)); } finally { if (getWeatherMethod != null) { getWeatherMethod.releaseConnection(); } } } @Override public void help(User user) { addEvent(new ReplyEvent(user, "weather [location] - gets the weather at the location specified, based on your preference")); addEvent(new ReplyEvent(user, "If no location is provided, I will look for the first preference with a value " + "in the set: {city, location} and use that value for the lookup. It works best if you set the value to " + "city name,state code. Zip codes work very poorly. See the 'pref' command for more details on setting preferences.")); } }