Add Google Map of voters
[selectricity-live] / vendor / plugins / ym4r_gm / lib / gm_plugin / geocoding.rb
diff --git a/vendor/plugins/ym4r_gm/lib/gm_plugin/geocoding.rb b/vendor/plugins/ym4r_gm/lib/gm_plugin/geocoding.rb
new file mode 100644 (file)
index 0000000..ea015eb
--- /dev/null
@@ -0,0 +1,116 @@
+require 'open-uri'\r
+require 'rexml/document'\r
+\r
+module Ym4r\r
+  module GmPlugin\r
+    module Geocoding\r
+\r
+      GEO_SUCCESS = 200\r
+      GEO_MISSING_ADDRESS = 601\r
+      GEO_UNKNOWN_ADDRESS = 602\r
+      GEO_UNAVAILABLE_ADDRESS = 603\r
+      GEO_BAD_KEY = 610\r
+      GEO_TOO_MANY_QUERIES = 620\r
+      GEO_SERVER_ERROR = 500\r
+      \r
+      #Gets placemarks by querying the Google Maps Geocoding service with the +request+ string. Options can either an explicity GMaps API key (<tt>:key</tt>) or a host, (<tt>:host</tt>). \r
+      def self.get(request,options = {})\r
+        api_key = ApiKey.get(options)\r
+        output =  options[:output] || "kml"\r
+        url = "http://maps.google.com/maps/geo?q=#{URI.encode(request)}&key=#{api_key}&output=#{output}"\r
+\r
+        res = open(url).read\r
+\r
+        case output.to_sym\r
+          when :json\r
+          res = eval(res.gsub(":","=>")) #!!!EVAL EVAL EVAL EVAL!!! hopefully we can trust google...\r
+          placemarks = Placemarks.new(res['name'],res['Status']['code'])\r
+          if res['Placemark']\r
+            placemark = res['Placemark']\r
+   \r
+            placemark.each do |data|\r
+              \r
+              data_country = data['Country']['CountryNameCode'] rescue ""\r
+              data_administrative = data['Country']['AdministrativeArea']['AdministrativeAreaName'] rescue ""\r
+              data_sub_administrative = data['Country']['AdministrativeArea']['SubAdministrativeArea']['SubAdministrativeAreaName'] rescue ""\r
+              data_locality = data['Country']['AdministrativeArea']['SubAdministrativeArea']['Locality']['LocalityName'] rescue ""\r
+              data_dependent_locality = data['Country']['AdministrativeArea']['SubAdministrativeArea']['Locality']['DependentLocality']['DependentLocalityName'] rescue ""\r
+              data_thoroughfare = data['Country']['AdministrativeArea']['SubAdministrativeArea']['Locality']['DependentLocality']['Thoroughfare']['ThoroughfareName'] rescue ""\r
+              data_postal_code = data['Country']['AdministrativeArea']['SubAdministrativeArea']['Locality']['DependentLocality']['Thoroughfare']['PostalCode']['PostalCodeNumber'] rescue ""\r
+              lon, lat = data['Point']['coordinates'][0,2]\r
+              data_accuracy = data['Accuracy']\r
+              unless data_accuracy.nil?\r
+                data_accuracy = data_accuracy.to_i\r
+              end\r
+        \r
+              placemarks << Geocoding::Placemark.new(data['address'],\r
+                                                     data_country,\r
+                                                     data_administrative,\r
+                                                     data_sub_administrative,\r
+                                                     data_locality,\r
+                                                     data_dependent_locality,\r
+                                                     data_thoroughfare,\r
+                                                     data_postal_code,\r
+                                                     lon, lat, data_accuracy)\r
+                                                     \r
+            end\r
+          end\r
+          when :kml, :xml\r
+          \r
+          doc = REXML::Document.new(res) \r
+\r
+          response = doc.elements['//Response']\r
+          placemarks = Placemarks.new(response.elements['name'].text,response.elements['Status/code'].text.to_i)\r
+          response.elements.each(".//Placemark") do |placemark|\r
+            data = placemark.elements\r
+            data_country = data['.//CountryNameCode']\r
+            data_administrative = data['.//AdministrativeAreaName']\r
+            data_sub_administrative = data['.//SubAdministrativeAreaName']\r
+            data_locality = data['.//LocalityName']\r
+            data_dependent_locality = data['.//DependentLocalityName']\r
+            data_thoroughfare = data['.//ThoroughfareName']\r
+            data_postal_code = data['.//PostalCodeNumber']\r
+            lon, lat = data['.//coordinates'].text.split(",")[0..1].collect {|l| l.to_f }\r
+            data_accuracy = data['.//*[local-name()="AddressDetails"]'].attributes['Accuracy']\r
+            unless data_accuracy.nil?\r
+               data_accuracy = data_accuracy.to_i\r
+             end\r
+            placemarks << Geocoding::Placemark.new(data['address'].text,\r
+                                                   data_country.nil? ? "" : data_country.text,\r
+                                                   data_administrative.nil? ? "" : data_administrative.text,\r
+                                                   data_sub_administrative.nil? ? "" : data_sub_administrative.text,\r
+                                                   data_locality.nil? ? "" : data_locality.text,\r
+                                                   data_dependent_locality.nil? ? "" : data_dependent_locality.text,\r
+                                                   data_thoroughfare.nil? ? "" : data_thoroughfare.text,\r
+                                                   data_postal_code.nil? ? "" : data_postal_code.text,\r
+                                                   lon, lat, data_accuracy )\r
+          end\r
+        end\r
+                \r
+        placemarks\r
+      end\r
+\r
+      #Group of placemarks returned by the Geocoding service. If the result is valid the +status+ attribute should be equal to <tt>Geocoding::GE0_SUCCESS</tt>\r
+      class Placemarks < Array\r
+        attr_accessor :name,:status\r
+\r
+        def initialize(name,status)\r
+          super(0)\r
+          @name = name\r
+          @status = status\r
+        end\r
+      end\r
+\r
+      #A result from the Geocoding service.\r
+      class Placemark < Struct.new(:address,:country_code,:administrative_area,:sub_administrative_area,:locality,:dependent_locality,:thoroughfare,:postal_code,:longitude,:latitude,:accuracy)\r
+        def lonlat\r
+          [longitude,latitude]\r
+        end\r
+\r
+        def latlon\r
+          [latitude,longitude]\r
+        end\r
+      end\r
+    end\r
+  end\r
+end\r

Benjamin Mako Hill || Want to submit a patch?