require 'net/http' require 'rexml/document' BEGIN { $server = 'weather.yahooapis.com' $query = '/forecastrss?p=' $welcome = 'Welcome to the weather demonstration application.' $prompt = 'Please enter a five digit ZIP code or press the pound key to quit.' $regrets = 'We are sorry but we had trouble determining the weather for your ZIP code. ' + 'If the ZIP code is valid you can try again later.' $states = { 'AL' => 'Alabama' , 'AK' => 'Alaska' , 'AZ' => 'Arizona' , 'AR' => 'Arkansas' , 'CA' => 'California' , 'CO' => 'Colorado' , 'CT' => 'Connecticut' , 'DE' => 'Delaware' , 'DC' => 'D C' , 'FL' => 'Florida' , 'GA' => 'Georgia' , 'HI' => 'Hawaii' , 'ID' => 'Idaho' , 'IL' => 'Illinois' , 'IN' => 'Indiana' , 'IA' => 'Iowa' , 'KS' => 'Kansas' , 'KY' => 'Kentucky' , 'LA' => 'Louisiana' , 'ME' => 'Maine' , 'MD' => 'Maryland' , 'MA' => 'Massachusetts' , 'MI' => 'Michigan' , 'MN' => 'Minnesota' , 'MS' => 'Mississippi' , 'MO' => 'Missouri' , 'MT' => 'Montana' , 'NE' => 'Nebraska' , 'NV' => 'Nevada' , 'NH' => 'New Hampshire' , 'NJ' => 'New Jersey' , 'NM' => 'New Mexico' , 'NY' => 'New York' , 'NC' => 'North Carolina' , 'ND' => 'North Dakota' , 'OH' => 'Ohio' , 'OK' => 'Oklahoma' , 'OR' => 'Oregon' , 'PA' => 'Pennsylvania' , 'PR' => 'Puerto Rico' , 'RI' => 'Rhode Island' , 'SC' => 'South Carolina' , 'SD' => 'South Dakota' , 'TN' => 'Tennessee' , 'TX' => 'Texas' , 'UT' => 'Utah' , 'VT' => 'Vermont' , 'VA' => 'Virginia' , 'WA' => 'Washington' , 'WV' => 'West Virginia' , 'WI' => 'Wisconsin' , 'WY' => 'Wyoming' } } #-------------------------------------------------------------------------------------- # The voice user interface is here - Ask the caller for a 5 digit ZIP code #-------------------------------------------------------------------------------------- def Answer(kall) # Get an instance of the synthesizer and greet the caller syn = kall.getSynthesizer() syn.speak($welcome) syn.wait(-1) # Repeat indefinitely while true # Ask the user for a ZIP code syn.speak($prompt) syn.wait(-1) # Wait for 5 keystrokes or a terminator but not more than 20 seconds ok = kall.inputWait1(5, '#', 20000) # If the time out elapses or the caller hangs up we are done break if !ok # We have no patience if he gave us less than 5 digits break if kall.inputAvailable() < 5 # Build a string from the key strokes zip = ' ' for i in 0..4 zip[i] = kall.getChar() end # If there is a terminator in there we are done break if zip.index('#') # Tell the caller to wait syn.speak('Please wait ...') # Amuse him with "music on hold" kall.loopMessage('strumming') # Get his forecast forecast = DoRequest(zip) # Stop playing and put a delay between the music and the speech kall.stopPlaying() kall.wait(500) # Speak the forecast syn.speak(forecast) puts forecast # Log the input and output to the call detail records table kall.cdrStatusMessage(0, zip) kall.cdrStatusMessage(1, forecast) # Let him hear the forecast before we ask if he wants to go again syn.wait(-1) end # Ta-ta for now if !kall.isDisconnected() syn.speak('Good bye.') syn.wait(-1) end end #-------------------------------------------------------------------------------------- # Request the weather from the web service #-------------------------------------------------------------------------------------- def DoRequest(zip) conx = Net::HTTP.new($server, 80) resp, data = conx.get($query + zip, nil) if resp.code != '200' forecast = $regrets puts 'The web service fails us: ' + resp.message + ' (' + resp.code + ')' else forecast = ParseXML(data) end return forecast end #-------------------------------------------------------------------------------------- # Parse the XML document returned #-------------------------------------------------------------------------------------- def ParseXML(xml) begin doc = REXML::Document.new(xml) city = GetCity(doc) wind = GetWind(doc) temp = GetTemperature(doc) outlook = GetOutlook(doc) forecast = 'In ' + city + ' the weather is ' + outlook + ' with a temperature of ' + temp + '. The winds are ' + wind + '.' rescue Exception => e forecast = $regrets puts "\n" puts e.message() puts e.backtrace.join("\n") puts "\n" end return forecast end # ----------------------------------------------------------------------------------------------- # Extract the city and state from the XML document # ----------------------------------------------------------------------------------------------- def GetCity(doc) temp1 = doc.root.elements["channel/yweather:location"].attributes["city"] temp2 = doc.root.elements["channel/yweather:location"].attributes["region"] if $states[temp2] city = temp1 + ' ' + $states[temp2] else city = temp1 + ' ' + temp2 end return city end # ----------------------------------------------------------------------------------------------- # Extract the forecast from the XML document # ----------------------------------------------------------------------------------------------- def GetWind(doc) temp1 = doc.root.elements["channel/yweather:wind"].attributes["direction"] temp2 = doc.root.elements["channel/yweather:wind"].attributes["speed"] wind = 'from the ' + Direction( temp1.to_i() ) + ' at ' + temp2 + ' miles per hour' return wind end # ----------------------------------------------------------------------------------------------- # Extract the temperature from the XML document # ----------------------------------------------------------------------------------------------- def GetTemperature(doc) temp = doc.root.elements["channel/item/yweather:condition"].attributes["temp"] temp = temp + ' degrees Fahrenheit' return temp end # ----------------------------------------------------------------------------------------------- # Extract the forecast from the XML document # ----------------------------------------------------------------------------------------------- def GetOutlook(doc) outlook = doc.root.elements["channel/item/yweather:condition"].attributes["text"] return outlook end #-------------------------------------------------------------------------------------- # Translate wind direction in degress to text #-------------------------------------------------------------------------------------- def Direction(degrees) if degrees <= 11 dir = 'north' elsif degrees <= 33 dir = 'north northeast' elsif degrees <= 56 dir = 'northeast' elsif degrees <= 78 dir = 'east northeast' elsif degrees <= 101 dir = 'east' elsif degrees <= 123 dir = 'east southeast' elsif degrees <= 146 dir = 'southeast' elsif degrees <= 168 dir = 'south southeast' elsif degrees <= 191 dir = 'south' elsif degrees <= 213 dir = 'south southwest' elsif degrees <= 236 dir = 'southwest' elsif degrees <= 258 dir = 'west southwest' elsif degrees <= 281 dir = 'west' elsif degrees <= 303 dir = 'west northwest' elsif degrees <= 326 dir = 'northwest' elsif degrees <= 348 dir = 'north northwest' else dir = 'north' end return dir end