reverse geocodingとau携帯の簡易位置情報取得のテストしてみた(2009/3/8にgithubにforkしたf2pを上げました)
f2p@githubのコードをいじってます。
PCからテストするには /f2p/entry/new?lat=35.19.30.0&lon=139.20.35.25 とかいう風にURLを入力する。(経度、緯度は分、秒、100分の1秒の単位らしい(あ、計算まちごうとった、ので直した)
実装の問題点
- calc_geo : 度、分、秒のデータを変換するルーチンの置き場所として適当なところがわからない
- au以外の端末に対して、どうやって対処するか。
- 現状はsettingsにはuse GPS infoのチェックボックスがあるだけだが、それをキャリアごとにするか?それともUserAgentを自動判別するか
- 簡易位置情報を利用してのpostのリンクをworld_addのアイコンで表示しているが、そこに張られるリンクはキャリアによって異なる。これはどこで判断させるか。settingsにキャリアの種別があればそれを使うが、app/helpers/application_helper.rb の中でUserAgentを見て云々というのはしたくない。
- app/helpers/application_helper.rbのwrite_with_geocode_linkがとてもhard codingで哀しい。とはいえ、どうやって device:location?url=... とかいうリンクを作れっちゅうねん→ link_to
2009/3/8にgithubにf2pをforkしたものをあげました
kgbu/f2p · GitHub
でも、jpmobileとかを使ってないので、大幅に書き換えるかもしれません。
記事投稿時点での状況など
とりあえず現状のgit statuやgit diff(config/environment.rbは関係ないkeyのところとかを消してます)
(2009/3/5 10:22現在、通常のgeocodingについてはGeocodingJPのサービスを使うように戻しました。よって app/controllers/entry_controller.rbのdiffの中身も替えてます)
まずgit statusの中から
# On branch master # Changed but not updated: # (use "git add..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # modified: app/controllers/entry_controller.rb # modified: app/controllers/setting_controller.rb # modified: app/helpers/application_helper.rb # modified: app/models/setting.rb # modified: app/views/entry/new.html.erb # modified: app/views/layouts/entry.html.erb # modified: app/views/setting/index.html.erb # modified: config/environment.rb # modified: config/environments/development.rb # modified: config/environments/production.rb # modified: lib/google_maps.rb
そしてgit diff
diff --git a/app/controllers/entry_controller.rb b/app/controllers/entry_controller.rb index 1786721..a57261d 100644 --- a/app/controllers/entry_controller.rb +++ b/app/controllers/entry_controller.rb @@ -257,11 +257,39 @@ class EntryController < ApplicationController @link = param(:link) @with_form = param(:with_form) @title = param(:title) + @lon = param(:lon) @lat = param(:lat) - @long = param(:long) + + def calc_geo(m_s_sss) + sign = "" + if /([-])?(\d{1,3})\.(\d{1,2})\.(\d{1,2})\.(\d{1,3})/ =~ m_s_sss then + sign = $1 + m_s_sss = (((($5.to_f/100) + $4.to_f)/60 + $3.to_f)/60 + $2.to_f) + if sign == "-" then + (m_s_sss * -1 ).to_s + else + m_s_sss.to_s + end + else + m_s_sss + end + end + + @lon = calc_geo(@lon) + @lat = calc_geo(@lat) + + @long = param(:long) || @lon @address = param(:address) @placemark = nil - if @title + if @lon + geocoder = GoogleMaps::GoogleGeocoder.new(http_client, F2P::Config.google_maps_api_key) + @placemark = geocoder.reversesearch(@lat, @lon) +p @lon +p @lat + if @placemark and !@placemark.ambiguous? + @address = @placemark.address + end + elsif @title geocoder = GoogleMaps::GeocodingJpGeocoder.new(http_client) @placemark = geocoder.search(@title) if @placemark and !@placemark.ambiguous? @@ -314,6 +342,7 @@ class EntryController < ApplicationController file = param(:file) @lat = param(:lat) @long = param(:long) + @lon = param(:lon) @title = param(:title) @address = param(:address) opt = create_opt(:room => @ctx.room) diff --git a/app/controllers/setting_controller.rb b/app/controllers/setting_controller.rb index d172715..b0b8e5f 100644 --- a/app/controllers/setting_controller.rb +++ b/app/controllers/setting_controller.rb @@ -15,12 +15,13 @@ class SettingController < ApplicationController @list_view_media_rendering = param(:list_view_media_rendering) || @setting.list_view_media_rendering @link_open_new_window = param(:link_open_new_window) || @setting.link_open_new_window @link_type = param(:link_type) || @setting.link_type + @use_gps_info = param(:use_gps_info) || @setting.use_gps_info end def update updated = false original_value = {} - [:font_size, :entries_in_page, :entries_in_thread, :text_folding_size, :list_view_media_rendering, :link_open_new_window, :link_type].each do |key| + [:font_size, :entries_in_page, :entries_in_thread, :text_folding_size, :list_view_media_rendering, :link_open_new_window, :link_type, :use_gps_info].each do |key| original_value[key] = @setting.send(key) end # int settings @@ -37,6 +38,7 @@ class SettingController < ApplicationController if param(:link_type_gwt) == 'checked' @setting.link_type = 'gwt' end + @setting.use_gps_info = (param(:use_gps_info) == 'checked') if errors = @setting.validate original_value.each do |key, value| @setting.send(key.to_s + '=', value) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 551bf29..8b9d1f8 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -33,6 +33,7 @@ module ApplicationHelper 'pin' => 'anchor.png', 'bottom' => 'arrow_down.png', 'top' => 'arrow_up.png', + 'world_add' => 'world_add.png', } def icon_url(name) @@ -61,6 +62,12 @@ module ApplicationHelper link_to(icon_tag(:logout), :controller => 'login', :action => 'clear') end + def write_with_geocode_link + if setting.use_gps_info + '<a href="device:location?url=new"><img alt="world add" height="16" src="/images/icons/world_add.png" title="world add" width="16" /></a>' + end + end + def u(arg) if arg super(arg) diff --git a/app/models/setting.rb b/app/models/setting.rb index f302bd9..02a6759 100644 --- a/app/models/setting.rb +++ b/app/models/setting.rb @@ -5,6 +5,7 @@ class Setting attr_accessor :text_folding_size attr_accessor :link_open_new_window attr_accessor :link_type + attr_accessor :use_gps_info attr_accessor :list_view_media_rendering def initialize @@ -15,6 +16,7 @@ class Setting @text_folding_size = F2P::Config.text_folding_size @link_open_new_window = F2P::Config.link_open_new_window @link_type = F2P::Config.link_type + @use_gps_info = F2P::Config.use_gps_info @list_view_media_rendering = F2P::Config.list_view_media_rendering end diff --git a/app/views/entry/new.html.erb b/app/views/entry/new.html.erb index 2f1cd71..d778e8d 100644 --- a/app/views/entry/new.html.erb +++ b/app/views/entry/new.html.erb @@ -11,6 +11,7 @@ <%- end -%> <%= hidden_field_tag('lat', @lat) %> <%= hidden_field_tag('long', @long) %> + <%= hidden_field_tag('lon', @lon) %> <%= hidden_field_tag('title', @title) %> <%= hidden_field_tag('address', @address) %> <%= submit_tag 'post' %> diff --git a/app/views/layouts/entry.html.erb b/app/views/layouts/entry.html.erb index 73ee3a9..8908281 100644 --- a/app/views/layouts/entry.html.erb +++ b/app/views/layouts/entry.html.erb @@ -31,7 +31,7 @@ </style> </head> <body> - <h1><%= link_to(h(appname), :controller => 'entry', :action => 'list') %> <%= h(viewname) %> at <a name="top"><%= date(Time.now) %></a> <%= write_new_link %> <%= search_link %> <%= settings_link %> <%= logout_link %></h1> + <h1><%= link_to(h(appname), :controller => 'entry', :action => 'list') %> <%= h(viewname) %> at <a name="top"><%= date(Time.now) %></a> <%= write_new_link %> <%= write_with_geocode_link %> <%= search_link %> <%= settings_link %> <%= logout_link %></h1> <%= yield %> </body> </html> diff --git a/app/views/setting/index.html.erb b/app/views/setting/index.html.erb index 78d3487..7d045e3 100644 --- a/app/views/setting/index.html.erb +++ b/app/views/setting/index.html.erb @@ -11,6 +11,7 @@ show medias in list view: <%= check_box_tag('list_view_media_rendering', 'checked', @list_view_media_rendering) %><br/> open links in new window: <%= check_box_tag('link_open_new_window', 'checked', @link_open_new_window) %><br/> open links via mobile proxy(gwt): <%= check_box_tag('link_type_gwt', 'checked', @link_type == 'gwt') %><br/> + use mobile phone's GPS info: <%= check_box_tag('use_gps_info', 'checked', @use_gps_info) %><br/> <%= submit_tag 'update' %> </p> <%- end -%> diff --git a/config/environment.rb b/config/environment.rb index f9a38ff..ddded84 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -32,6 +32,7 @@ module F2P attr_accessor :service_grouping_threashold attr_accessor :link_open_new_window attr_accessor :link_type # nil or 'gwt' + attr_accessor :use_gps_info attr_accessor :updated_expiration attr_accessor :list_view_media_rendering end @@ -106,15 +107,15 @@ Rails::Initializer.run do |config| F2P::Config.cipher_algorithm = 'AES-256-CBC' F2P::Config.cipher_block_size = 16 # must match with above alg. F2P::Config.encryption_key = "xxxx" - F2P::Config.google_maps_api_key = '' + F2P::Config.google_maps_api_key = 'xxxx' F2P::Config.icon_url_base = '/images/icons/' F2P::Config.google_maps_maptype = 'mobile' - F2P::Config.google_maps_zoom = 13 + F2P::Config.google_maps_zoom = 12 F2P::Config.google_maps_width = 160 F2P::Config.google_maps_height = 80 - F2P::Config.font_size = 9 + F2P::Config.font_size = 11 F2P::Config.entries_in_page = 20 F2P::Config.text_folding_size = 140 F2P::Config.entries_in_thread = 4 @@ -122,6 +123,7 @@ Rails::Initializer.run do |config| F2P::Config.service_grouping_threashold = 5400 F2P::Config.link_open_new_window = false F2P::Config.link_type = 'gwt' + F2P::Config.use_gps_info = false F2P::Config.updated_expiration = 5400 F2P::Config.list_view_media_rendering = true end diff --git a/config/environments/development.rb b/config/environments/development.rb index 85c9a60..b18ad27 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -14,4 +14,8 @@ config.action_view.debug_rjs = true config.action_controller.perform_caching = false # Don't care if the mailer can't send -config.action_mailer.raise_delivery_errors = false \ No newline at end of file +config.action_mailer.raise_delivery_errors = false + +# SyslogLogger +require 'syslog_logger' +RAILS_DEFAULT_LOGGER = SyslogLogger.new 'f2p' diff --git a/config/environments/production.rb b/config/environments/production.rb index ec5b7bc..2542ee7 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -22,3 +22,7 @@ config.action_controller.perform_caching = true # Disable delivery errors, bad email addresses will be ignored # config.action_mailer.raise_delivery_errors = false + +# SyslogLogger +require 'syslog_logger' +RAILS_DEFAULT_LOGGER = SyslogLogger.new 'f2p' diff --git a/lib/google_maps.rb b/lib/google_maps.rb index ec6982c..f0c819d 100644 --- a/lib/google_maps.rb +++ b/lib/google_maps.rb @@ -72,6 +72,8 @@ module GoogleMaps end class GoogleGeocoder + include HashUtils + URL = 'http://maps.google.com/maps/geo' def initialize(httpclient, key) @@ -79,16 +81,56 @@ module GoogleMaps @key = key end - def search(str, hl = 'ja') + def search(str, en = 'utf-8') query = { 'q' => str, 'output' => 'json', - 'hl' => hl, + 'en' => en, + 'key' => @key + } + result = JSON.parse(NKF.nkf('-wm0', @httpclient.get_content(URL, query))) + if result.nil? or v(result, 'error') + nil + elsif v(result, 'Status', 'code') != 200 + nil + elsif v(result, 'Placemark').size > 1 + Candidates.new(v(result, 'Placemark')) + else + address = v(result, 'name') + address = nil if address and address.empty? + c = v(result, 'Placemark') + cord = v(c[0], 'Point', 'coordinates') + lat = cord[1] + long = cord[0] + if address and lat and long + Point.new(address, lat, long) + end + end + end + + def reversesearch(lat, long, oe = 'utf-8') + query = { + 'll' => lat + ',' + long, + 'output' => 'json', + 'oe' => oe, 'key' => @key } result = JSON.parse(NKF.nkf('-wm0', @httpclient.get_content(URL, query))) - # TODO: need to construct Point or Candidates. - nil + if result.nil? or v(result, 'error') + nil + elsif v(result, 'Status', 'code') != 200 + nil + else + address = v(result, 'name') + address = nil if address and address.empty? + c = v(result, 'Placemark') + cord = v(c[0], 'Point', 'coordinates') + lat = cord[1] + long = cord[0] + if address and lat and long + Point.new(address, lat, long) + end + end end end @@ -133,5 +175,7 @@ end if $0 == __FILE__ require 'httpclient' require 'pp' - pp GoogleMaps::Geocoder.new(HTTPClient).search('日本、東京駅') + pp GoogleMaps::GeocodingJpGeocoder.new(HTTPClient).search('日本、東京駅') + pp GoogleMaps::GoogleGeocoder.new(HTTPClient).search('日本、東京駅') + pp GoogleMaps::GoogleGeocoder.new(HTTPClient).reversesearch(35.306, 139.274) end