#!/usr/bin/env ruby # # Created by Demitrious S. Kelly on 2007-02-11. # # License: GPL Version 2, see # http://www.gnu.org/licenses/gpl.txt # (and pretend it's attached or included # in some way in/to this file) # # Release Version 0.002 # # Changelog # 0.001 - Initial Release # 0.002 - Added Routing Support # # Warranty: None, at all, whatsoever, use at your own # risk, may burn down your house and knock over your # garbage cans and return the car with the gas level # on "E" and refuse to return your lawnmower even though # it's now 7 months later and you're growing a small # rainforest out back... might fall asleep while # watching your children, forget to pay the electric # bill, and run up massive credit card debt. In other # words. You're on your own. Dont come crying to me! # # For this to work you have to first apply for a mapquest openapi key here: # http://company.mapquest.com/openapi/signup.jsp Then you must add "*" as a # referrer under "my account" for your openapi key at # https://trc.mapquest.com/?action=accountmanager # # Example usage: # # mq = Mapquest.new("foobazbazbooblah") # # ## Geocoding # myLocation = { # :address => "555 17th Street, Suite 1600" # :city => "Denver" # :state => "Colorado" # :zip => 80202 # } # puts mq.geocode(myLocation).inspect # # ## Routing # route_request = { # :addressOrigin => { # :name => "Yahoo!", # :address => "701 First Avenue", # :city => "Sunnyvale", # :stateProvince => "ca", # }, # :addressDestination => { # :name => "Google", # :address => "1600 Amphitheatre Parkway", # :city => " Mountain View", # :stateProvince => "ca", # }, # } # puts mq.route(route_request).inspect require 'rubygems' require 'hpricot' require 'open-uri' require 'cgi' class Mapquest def initialize(apikey, options = {}) @api_key = apikey if options[:api_url_base] == nil @api_url_base = "http://web.openapi.mapquest.com/oapi/transaction" else @api_url_base = options[:api_url_base] end end def geocode(info = {}) begin url = [] url << "#{@api_url_base}?transaction=geocode" url << "key=#{@api_key}" if info.key?(:ambiguities) url << "ambiguities=#{info[:ambiguities]}" else url << "ambiguities=0" end url << "address=" + CGI::escape(info[:address]) if !info[:address].nil? url << "city=" + CGI::escape(info[:city]) if !info[:city].nil? url << "county=" + CGI::escape(info[:county]) if !info[:county].nil? url << "stateProvince=" + CGI::escape(info[:stateprovince]) if !info[:stateprovince].nil? url << "postalcode=" + CGI::escape("#{info[:postalcode]}") if !info[:postalcode].nil? url << "country=" + CGI::escape(info[:country]) if !info[:country].nil? url = url.join("&") doc = Hpricot(open(url)) if doc.at("error").nil? rval={} rval[:address] = doc.at("address").innerHTML if !doc.at("address").nil? rval[:city] = doc.at("city").innerHTML if !doc.at("city").nil? rval[:state] = doc.at("stateprovince").innerHTML if !doc.at("stateprovince").nil? rval[:zip] = doc.at("postalcode").innerHTML if !doc.at("postalcode").nil? rval[:county] = doc.at("county").innerHTML if !doc.at("county").nil? rval[:longitude] = doc.at("longitude").innerHTML rval[:latitude] = doc.at("latitude").innerHTML return rval else return false end rescue return false end end def parameterize_route_address(p, a = {}) url = [] url << "#{p}a=" +CGI::escape("#{a[:address]}") if !a[:address].nil? url << "#{p}c=" +CGI::escape("#{a[:city]}") if !a[:city].nil? url << "#{p}sp=" +CGI::escape("#{a[:stateProvince]}") if !a[:stateProvince].nil? url << "#{p}cnty=" +CGI::escape("#{a[:county]}") if !a[:county].nil? url << "#{p}pc=" +CGI::escape("#{a[:postalCode]}") if !a[:postalCode].nil? url << "#{p}ctry=" +CGI::escape("#{a[:country]}") if !a[:country].nil? url << "#{p}n=" +CGI::escape("#{a[:name]}") if !a[:name].nil? return url.join("&") end def route(info = {}) url = [] url << "#{@api_url_base}?transaction=route" url << "key=#{@api_key}" url << "ambiguities=0" url << "routemaps=1" url << parameterize_route_address("o", info[:addressOrigin]) url << parameterize_route_address("d", info[:addressDestination]) url = url.join("&") ## Hack around bug described here: http://code.whytheluckystiff.net/hpricot/ticket/55?replyto=description#comment doc = "" open(url) do |f| doc=doc + f.read end doc = doc.gsub(//, "") doc = doc.gsub(/<\/text>/, "") doc = Hpricot(doc) ## Should be one line ## doc = Hpricot(open(url)) ## End hack begin st=doc.at("advantage > route")["status"].tr("\\", "").tr('""', "").to_i rval = { :maneuvers => {}, :maneuver_count => 0, :maneuver_units => "mi", :maneuver_distance => 0, :maneuver_time => 0, :overviewmap => {}, :route_status => st, } rval[:overviewmap]={ :height => doc.at("overviewmap > height").innerHTML.to_i, :width => doc.at("overviewmap > width").innerHTML.to_i, :longitude => doc.at("overviewmap > longitude").innerHTML.to_f, :latitude => doc.at("overviewmap > latitude").innerHTML.to_f, :zoom => doc.at("overviewmap > zoomlevel").innerHTML.to_i, :request => doc.at("overviewmap > request").innerHTML, } doc.search("maneuvers > maneuver").each do |move| rval[:maneuver_count] += 1 mnum=rval[:maneuver_count] rval[:maneuvers][mnum] = { :text => move.at("mtext").innerHTML, :distance => move.at("distance").innerHTML.to_i, :units => move.at("distance")["units"].tr("\\", "").tr('""', ""), :time => move.at("time").innerHTML.to_i, } rval[:maneuver_distance] += rval[:maneuvers][mnum][:distance] rval[:maneuver_time] += rval[:maneuvers][mnum][:time] rval[:maneuver_units] = rval[:maneuvers][mnum][:units] end return rval rescue return {} end end end