Class: Bahn::Agent

Inherits:
Object
  • Object
show all
Defined in:
lib/bahn/bahn_agent.rb

Overview

Agent class that searches stations, street addresses and public transportation routes for germany Example: agent = Agent.new routes = agent.get_routes “Düsseldorf Heerdter Sandberg 25”, “Düsseldorf Am Dreieck 1” routes.each {|route| route.parts.each {|part| puts part } }

You can go even use far distances… routes = agent.get_routes “Heerdter Sandberg 35 Düsseldorf, Düsseldorf”, “Berlin Hauptstraße 10” routes.each {|route| route.parts.each {|part| puts part } } => Am 2013-02-01 von 17:32 bis 17:33 : Düsseldorf - Oberkassel, Heerdter Sandberg 60 nach Heerdter Sandberg U, Düsseldorf via Fußweg => Am 2013-02-01 von 17:33 bis 17:47 : Heerdter Sandberg U, Düsseldorf nach Düsseldorf Hauptbahnhof via U 7 => Am 2013-02-01 von 17:47 bis 17:53 : Düsseldorf Hauptbahnhof nach Düsseldorf Hbf via Fußweg => Am 2013-02-01 von 17:53 bis 22:22 : Düsseldorf Hbf nach Berlin Hbf via ICE 945 => Am 2013-02-01 von 22:34 bis 22:40 : Berlin Hbf nach Berlin Alexanderplatz via RE 37386 => Am 2013-02-01 von 22:40 bis 22:46 : Berlin Alexanderplatz nach Alexanderplatz (U), Berlin via Fußweg => Am 2013-02-01 von 22:46 bis 23:07 : Alexanderplatz (U), Berlin nach Oberseestr., Berlin via STR M5 => Am 2013-02-01 von 23:07 bis 23:15 : Oberseestr., Berlin nach Berlin - Alt-Hohenschönhausen, Hauptstraße 10 via Fußweg

Constant Summary collapse

TYPES =
{
  :station => 1,
  :address => 2
}.freeze
TIME_RELATION =
{
  :arrival => 0,
  :depature => 1
}.freeze
JOURNEY_PRODUCT_PRESETS =
{
  :alle => "1:1111111111000000",
  :alle_ohne_ice => "2:0111111111000000",
  :nur_nahverkehr => "4:0001111111000000",
}.freeze
@@options =
{
  :url_route => 'http://mobile.bahn.de/bin/mobil/query.exe/dox?country=DEU&rt=1&use_realtime_filter=1&searchMode=ADVANCED',
  :uri_adresses => 'http://reiseauskunft.bahn.de/bin/ajax-getstop.exe/en?REQ0JourneyStopsS0A=2&REQ0JourneyStopsS0G=',
  :uri_stations => 'http://reiseauskunft.bahn.de/bin/ajax-getstop.exe/en?REQ0JourneyStopsS0A=1&REQ0JourneyStopsS0G=',
  :uri_stations_near => 'http://mobile.bahn.de/bin/mobil/query.exe/dox?ld=9627&n=1&rt=1&use_realtime_filter=1&performLocating=2&tpl=stopsnear&look_maxdist=1000&look_stopclass=1023&look_y=%i&look_x=%i'
}

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeAgent

Initialize a new Agent options:

:user_agent => Set the user agent. Default: "bahn.rb"


55
56
57
58
59
# File 'lib/bahn/bahn_agent.rb', line 55

def initialize
  @agent = Mechanize.new
  @agent.set_defaults if @agent.respond_to?(:set_defaults)
  @agent.user_agent = @@user_agent ||= "bahn.rb"
end

Class Method Details

.user_agent=(val) ⇒ Object

Set the used user agent



30
31
32
# File 'lib/bahn/bahn_agent.rb', line 30

def self.user_agent=val
  @@user_agent = val
end

Instance Method Details

#find_address(address, options = {}) ⇒ Object

Finds the first usable address for the given parameter. The returned address can then be used for further processing in routes Example:

Input: Roßstr. 41 40476 Düsseldorf 
Output: Düsseldorf - Golzheim, Rossstraße 41


140
141
142
143
144
145
146
# File 'lib/bahn/bahn_agent.rb', line 140

def find_address address, options={}
  val = get_address_or_station(address, :address)
  options[:coords] = address.respond_to?(:coordinates) ? address.coordinates : nil
  result = @agent.get("#{@@options[:uri_adresses]}#{val}").body.gsub("SLs.sls=", "").gsub(";SLs.showSuggestion();", "")
  options[:current_station_type] = :address
  find_nearest_station result, options
end

#find_station(name, options = {}) ⇒ Object

Find the first best station by name Example:

Input: HH Allee Düsseldorf
Output: Heinrich-Heine-Allee U, Düsseldorf


127
128
129
130
131
132
133
134
# File 'lib/bahn/bahn_agent.rb', line 127

def find_station name, options={}
  val = get_address_or_station(name, :station)
  options[:coords] = name.respond_to?(:coordinates) ? name.coordinates : nil
  result = @agent.get("#{@@options[:uri_stations]}#{val}").body.gsub("SLs.sls=", "").gsub(";SLs.showSuggestion();", "")
  options[:current_station_type] = :station
  options[:searched_name] = name
  find_nearest_station result, options
end

#find_station_at(lat, lon, options = {}) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/bahn/bahn_agent.rb', line 148

def find_station_at lat, lon, options={}
  uri = @@options[:uri_stations_near] % [(lat * 1000000), (lon * 1000000)]
  result = @agent.get(uri)
  stations = result.links.select{|l| l.href.include?("HWAI=STATION!")}.map do |link|
    s = Station.new({:do_load => false})
    s.name = link.text
    lat_match = link.href.match(/Y=(\d{7,})/)
    s.lat = lat_match[1].insert(-7, ".") unless lat_match.nil?
    lon_match = link.href.match(/X=(\d{7,})/)
    s.lon = lon_match[1].insert(-7, ".") unless lon_match.nil?
    # not needed but hey, since we got it ;)
    dist_match = link.href.match(/dist=(\d+)!/)
    s.distance = (dist_match[1].to_i / 1000) unless dist_match.nil? # meter to km
    s.station_type = :station
    s
  end
  
  # prefer HBF or Hauptbahnhof if there is one nearby
  station = stations.select{|s| s.name.include?("Hauptbahnhof") || s.name.include?("HBF")}.first
  return (station.nil? ? stations.first : station)
end

#get_routes(from, to, options = {}) ⇒ Object

Get the next few routes with public transportation from A to B.

Options:

* :time => start time for the connection
* :include_coords => Include coordiantes for the station. This takes a while especially for longer routes! default: true

Returns:

Array of Bahn::Route(s)

Raises:

"no_route" if no route could be found


70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/bahn/bahn_agent.rb', line 70

def get_routes from, to, options = {}
  options[:start_type] = check_point_type(from) || options[:start_type]
  options[:target_type] = check_point_type(to) || options[:target_type]
  # default options
  options = {
    :time => Time.now, 
    :depth => 0, 
    :include_coords => true, 
    :limit => 2,
    :time_relation => :depature }.merge(options)
  
  options[:time] = options[:time].in_time_zone("Berlin") #+ 10.minutes # Ansonsten liegt die erste Verbindung in der Vergangenheit
  page = @agent.get @@options[:url_route]
  
  result = submit_form page.forms.first, from, to, options		
  
  routes = []
  links = result.links_with(:href => /details=opened!/).select { |l| l.to_s.size > 0} # only select connection links, no warning links
  links.each do |link|
    page = link.click
    routes << Route.new(page, options)
    break if routes.count == options[:limit]
  end
  
  # Keine Station gefunden also suchen wir nach der nächstbesten Adresse/Station
  if links.count == 0 && options[:depth] == 0
    if options[:start_type] == :address
      from = find_address(from, options)
      options[:start_type] = from.station_type
      from = from.name
    elsif options[:start_type] == :station
      from = find_station(from, options)
      options[:start_type] = from.station_type
      from = from.name
    end
    
    if options[:target_type] == :address
      to = find_address(to, options)
      options[:target_type] = to.station_type
      to = to.name
    elsif options[:target_type] == :station
      to = find_station(to, options)
      options[:target_type] = to.station_type
      to = to.name
    end
    
    return get_routes from, to, options.merge(:depth => options[:depth]+1)
  end
  
  raise "no_route" if routes.count == 0 || links.count == 0			
  routes
end