Permalink
Browse files

allow OTP to be configured as an alternate source for transit data

  • Loading branch information...
1 parent bfc4a7e commit 210025d6d499aa73abb719ae6c197e5f416af248 @atogle atogle committed Apr 16, 2012
Showing with 89 additions and 2 deletions.
  1. +23 −2 choices.rb
  2. +9 −0 constants.rb
  3. +57 −0 otp.rb
View
@@ -2,6 +2,7 @@
require 'cgi'
require './fare.rb'
require './constants.rb'
+require './otp.rb'
require 'pp'
def get_info_from_bing(params)
@@ -15,7 +16,7 @@ def get_info_from_bing(params)
}.map {|k,v| "#{k}=#{CGI.escape(v)}"}*"&"
modes=%w{driving walking transit}
- results =modes.map do |mode|
+ results = modes.map do |mode|
Thread.new do
begin
usable_url=URI.parse(base_url+mode+query_params)
@@ -124,6 +125,10 @@ def calculate_transit_by_bing_resource(resource)
return [200,{},JSON.pretty_generate(results)]
end
+ # Save the geocoded address points in an array [lat,lon] for OTP to use
+ origin = results["driving"]["routeLegs"][0]["actualStart"]["coordinates"]
+ destination = results["driving"]["routeLegs"][0]["actualEnd"]["coordinates"]
+
if (resource=results["driving"])
results["driving"]=generic_by_bing_resource(resource)
results["driving"][:emissions] = results["driving"][:distance] * SOV_LBS_CO2_PASSENGER_KM
@@ -150,7 +155,23 @@ def calculate_transit_by_bing_resource(resource)
results["biking"][:emissions] = 0
results["biking"][:cost]= (results["biking"][:distance] * BIKING_COST_PER_KM).round(2)
end
- if (resource=results["transit"])
+
+ # If we have an OTP config for both the origin and destination, then use OTP over Bing
+ if (has_otp_config(origin[0], origin[1]) && has_otp_config(destination[0], destination[1]))
+ params = {
+ :origin => origin,
+ :destination => destination,
+ :date => Date.today.strftime("%m/%d/%Y"),
+ :time => Time.now.strftime("%I:%M %p")
+ }
+
+ resource = get_info_from_otp(params)
+ results["transit"][:duration] = resource[:duration]
+ results["transit"][:calories] = resource[:walk_duration] * CALORIES_PER_SECOND_WALKING + resource[:transit_duration] * CALORIES_PER_SECOND_SITTING
+ results["transit"][:emissions] = results["driving"][:distance] * BUS_LBS_CO2_PASSENGER_KM
+ results["transit"][:cost] = resource[:cost]
+ # If we got results from Bing and there's not OTP, use Bing
+ elsif (resource=results["transit"])
resource[:distance] = results["driving"][:distance]
results["transit"] = calculate_transit_by_bing_resource(resource)
end
View
@@ -14,6 +14,15 @@
SOV_LBS_CO2_PASSENGER_KM = 0.597 #Average SOV car pounds of CO2 emitted per km (0.96 * 0.6214)
BUS_LBS_CO2_PASSENGER_KM = 0.404 #Average bus pounds of CO2 emitted per km (0.65 * 0.6214)
+# Map a bbox (left, bottom, right, top) to an OTP service url
+# You can get the bbox from the /meta route on your OTP service
+OTP_MAPPING = [
+ {
+ "bbox" => {"min_lon"=>-75.56027, "min_lat"=>38.92998, "max_lon"=>-71.91406, "max_lat"=>41.85966},
+ "url" =>"http://nyc.deployer.opentripplanner.org/opentripplanner-api-webapp/ws/"
+ }
+]
+
GTFS_MAPPING = {
"San Francisco Municipal Transportation Agency"=>["MUNI_google_transit","SFMTA"],
"Bay Area Rapid Transit"=>["BART_google_transit","BART"],
View
57 otp.rb
@@ -0,0 +1,57 @@
+require 'cgi'
+require 'net/http'
+require 'json'
+require 'pp'
+require './constants'
+
+# Is this point within the configured bbox of an OTP instance?
+def has_otp_config(lat, lon)
+ match = OTP_MAPPING.select {|m| lon >= m["bbox"]["min_lon"] && lon <= m["bbox"]["max_lon"] &&
+ lat >= m["bbox"]["min_lat"] && lat <= m["bbox"]["max_lat"] }
+ !match.empty?
+end
+
+# Get the base url for the OTP instance for this point
+def get_otp_url(lat, lon)
+ match = OTP_MAPPING.select {|m| lon >= m["bbox"]["min_lon"] && lon <= m["bbox"]["max_lon"] &&
+ lat >= m["bbox"]["min_lat"] && lat <= m["bbox"]["max_lat"] }
+ match.first["url"] if !match.empty?
+end
+
+# Get the important data from OTP
+def get_info_from_otp(params)
+ base_url=get_otp_url(params[:origin][0], params[:origin][1])
+
+ # Do we have a url?
+ if (!base_url.nil?)
+
+ # Params to pas to OTP
+ query_params = "plan?" + {
+ "arriveBy" => "false",
+ "date" => params[:date] || Date.today.strftime("%m/%d/%Y"),
+ "time" => params[:time] || Time.now.strftime("%I:%M %p"),
+ "mode" => "TRANSIT,WALK",
+ "optimize" => "QUICK",
+ "maxWalkDistance" => "1260",
+ "toPlace" => params[:origin].join(","),
+ "fromPlace" => params[:destination].join(",")
+ }.map {|k,v| "#{k}=#{CGI.escape(v)}"}*"&"
+
+ uri = URI.parse(base_url+query_params)
+ http = Net::HTTP.new(uri.host, uri.port)
+ request = Net::HTTP::Get.new(uri.request_uri)
+ # Be sure to ask for JSON
+ request.initialize_http_header({"Accept" => "application/json"})
+
+ # puts "calling url #{uri}"
+ res = JSON.parse(http.request(request).body)
+
+ {
+ :walk_duration => res["plan"]["itineraries"].first["walkTime"],
+ :transit_duration => res["plan"]["itineraries"].first["transitTime"],
+ :wait_duration => res["plan"]["itineraries"].first["waitingTime"],
+ :duration => res["plan"]["itineraries"].first["duration"].fdiv(1000),
+ :cost => res["plan"]["itineraries"].first["fare"]["fare"]["regular"]["cents"].fdiv(100) || nil
+ }
+ end
+end

0 comments on commit 210025d

Please sign in to comment.