muni 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -2,3 +2,6 @@
2
2
  .bundle
3
3
  Gemfile.lock
4
4
  pkg/*
5
+
6
+ bin/*
7
+ !bin/muni
data/README.md CHANGED
@@ -4,6 +4,13 @@ About
4
4
  `muni` is a simple NextBus API Client library and command line tool for retrieving
5
5
  San Francisco Muni bus route and stop prediction information.
6
6
 
7
+ Install
8
+ =======
9
+
10
+ ```bash
11
+ $ gem install muni
12
+ ```
13
+
7
14
  Client Library
8
15
  ===============
9
16
 
@@ -4,24 +4,21 @@ module Muni
4
4
  class Base < Mash
5
5
  class << self
6
6
  private
7
- def fetch(command, options = nil)
8
- url = build_url(command, options)
9
- xml = Net::HTTP.get(URI.parse(url))
10
- doc = XmlSimple.xml_in(xml)
11
- fail NextBusError, doc['Error'].first['content'].gsub(/\n/,'') if doc['Error']
12
- doc
13
- end
14
-
15
- def build_url(command, options = nil)
16
- url = "http://webservices.nextbus.com/service/publicXMLFeed?command=%s&a=sf-muni" % command
17
- if options
18
- options.each { |key,value|
19
- url << "&#{key}=#{value}"
20
- }
21
- end
22
- url
23
- end
24
-
7
+
8
+ def fetch(command, options = {})
9
+ url = build_url(command, options)
10
+ xml = Net::HTTP.get(URI.parse(url))
11
+ doc = XmlSimple.xml_in(xml) || {}
12
+ fail NextBusError, doc['Error'].first['content'].gsub(/\n/,'') if doc['Error']
13
+ doc
14
+ end
15
+
16
+ def build_url(command, options = {})
17
+ url = "http://webservices.nextbus.com/service/publicXMLFeed?command=#{command}&a=sf-muni"
18
+ options.each { |key,value| url << "&#{key}=#{value}" }
19
+ url
20
+ end
21
+
25
22
  end
26
23
  end
27
24
  end
@@ -3,11 +3,11 @@ require 'amatch'
3
3
  module Muni
4
4
  class Direction < Base
5
5
  def stop_at(place)
6
- return stops.select{|stop| stop.tag == place}.first if place =~ /[1-9][0-9]+/
7
- pattern = Amatch::Sellers.new(place)
6
+ return stops.select{ |stop| stop.tag == place }.first if place =~ /[1-9][0-9]+/
7
+ pattern = Amatch::Sellers.new(place)
8
8
  stops.sort_by{ |stop|
9
9
  pattern.match(stop.title)
10
10
  }.first
11
11
  end
12
12
  end
13
- end
13
+ end
@@ -6,7 +6,7 @@ module Muni
6
6
  def time
7
7
  Time.at((epochTime.to_i / 1000.0).to_i)
8
8
  end
9
-
9
+
10
10
  def pretty_time
11
11
  if time > Time.now
12
12
  distance_of_time_in_words_to_now(time)
@@ -10,13 +10,13 @@ module Muni
10
10
  return send(direction.downcase.to_sym) if direction =~ /(outbound|inbound)/i
11
11
  directions.select{|dir| dir.id == direction}.first
12
12
  end
13
-
13
+
14
14
  def outbound
15
- directions.select{|dir| dir.name =~ /outbound/i}.first
15
+ directions.select{ |dir| dir.name =~ /outbound/i }.first
16
16
  end
17
17
 
18
18
  def inbound
19
- directions.select{|dir| dir.name =~ /inbound/i}.first
19
+ directions.select{ |dir| dir.name =~ /inbound/i }.first
20
20
  end
21
21
 
22
22
  class << self
@@ -24,10 +24,10 @@ module Muni
24
24
  if tag == :all
25
25
  find_all
26
26
  else
27
- find_by_tag(tag)
27
+ find_by_tag(tag)
28
28
  end
29
29
  end
30
-
30
+
31
31
  private
32
32
  def find_all
33
33
  document = fetch(:routeList)
@@ -35,30 +35,30 @@ module Muni
35
35
  Route.new(el)
36
36
  end
37
37
  end
38
-
38
+
39
39
  def find_by_tag(tag)
40
40
  document = fetch(:routeConfig, {:r => tag})
41
41
  route = Route.new({:tag => document['route'].first['tag'], :title => document['route'].first['title']})
42
-
42
+
43
43
  stops = {}
44
-
44
+
45
45
  document['route'].first['stop'].each do |stop|
46
46
  st = Stop.new({
47
47
  :tag => stop['tag'],
48
48
  :title => stop['title'],
49
49
  :lat => stop['lat'],
50
50
  :lon => stop['lat'],
51
- :stopId => stop['lat'],
51
+ :stopId => stop['lat'],
52
52
  })
53
53
  stops[st[:tag]] = st
54
54
  end
55
-
55
+
56
56
  directions = []
57
57
  route.directions = document['route'].first['direction'].collect do |direction|
58
58
  direction_stops = direction['stop'].collect do |stop|
59
59
  stops[stop['tag']]
60
60
  end
61
-
61
+
62
62
  direction_stops.each do |stop|
63
63
  stop.route_tag = route.tag
64
64
  stop.direction = direction['tag']
@@ -70,7 +70,7 @@ module Muni
70
70
  :stops => direction_stops
71
71
  })
72
72
  end
73
-
73
+
74
74
  route
75
75
  end
76
76
  end
@@ -4,8 +4,9 @@ require 'muni/prediction'
4
4
  module Muni
5
5
  class Stop < Base
6
6
  def predictions
7
- document = Stop.send(:fetch, :predictions, {:r => route_tag, :d => direction, :s => tag})
8
- document['predictions'].first['direction'].first['prediction'].collect do |pred|
7
+ stop = Stop.send(:fetch, :predictions, r: route_tag, d: direction, s: tag)
8
+ return [] unless stop && stop['predictions']
9
+ stop['predictions'].first['direction'].first['prediction'].collect do |pred|
9
10
  Prediction.new(pred)
10
11
  end
11
12
  end
@@ -1,3 +1,3 @@
1
1
  module Muni
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -157,7 +157,7 @@ Route 21-Hayes going Outbound to Fulton St &amp; Shrader St at Hayes St &amp; Sh
157
157
 
158
158
  <p>With a fuzzy direction and stop name:</p>
159
159
 
160
- <pre><code>$ muni predict 21 inbound hayes and shrader
160
+ <pre><code>$ muni predict 21 inbound hayes and shrader
161
161
  Route 21-Hayes going Inbound to Steuart Terminal at Hayes St &amp; Shrader St:
162
162
  8102 less than a minute
163
163
  2832 2 minutes
@@ -7,8 +7,8 @@ muni(1) -- show san francisco muni routes and stop predictions
7
7
  `muni` `list`<br/>
8
8
  `muni` `predict` <route> <direction> <stop><br/>
9
9
  `muni` `show` `-v`|`--verbose` <route> [<direction>]<br/>
10
-
11
- ## DESCRIPTION
10
+
11
+ ## DESCRIPTION
12
12
 
13
13
  **muni** retrieves San Francisco MUNI routes information and bus stop prediction
14
14
  times. `muni` is mostly an exercise in implementing the core functions of the `muni`
@@ -25,7 +25,7 @@ List all available routes:
25
25
  L L-Taraval
26
26
  M M-Ocean View
27
27
  ....
28
-
28
+
29
29
  Show basic route information:
30
30
 
31
31
  $ muni show 21
@@ -45,7 +45,7 @@ Show a route and all stops using `-v` or `--verbose`:
45
45
  6501 Steuart St & Market St
46
46
  5669 Market St & Drumm St
47
47
  ...
48
-
48
+
49
49
  Show a route and all stops for a particular direction:
50
50
 
51
51
  $ muni show 21 outbound --verbose
@@ -59,7 +59,7 @@ Show a route and all stops for a particular direction:
59
59
  Get predictions for a bus, going a certain direction, at a given stop.
60
60
  `predict` can take the formal tag names for the direction and stop, or
61
61
  it will perform it's best guess.
62
-
62
+
63
63
  With formal direction and stop tags:
64
64
 
65
65
  $ muni predict 21 21_OB4 5008
@@ -71,7 +71,7 @@ With formal direction and stop tags:
71
71
  2823 about 1 hour
72
72
 
73
73
  With a fuzzy stop name:
74
-
74
+
75
75
  $ muni predict 21 21_OB4 hayes and shrader
76
76
  Route 21-Hayes going Outbound to Fulton St & Shrader St at Hayes St & Shrader St:
77
77
  2831 2 minutes
@@ -81,15 +81,14 @@ With a fuzzy stop name:
81
81
  2823 about 1 hour
82
82
 
83
83
  With a fuzzy direction and stop name:
84
-
85
- $ muni predict 21 inbound hayes and shrader
84
+
85
+ $ muni predict 21 inbound hayes and shrader
86
86
  Route 21-Hayes going Inbound to Steuart Terminal at Hayes St & Shrader St:
87
87
  8102 less than a minute
88
88
  2832 2 minutes
89
89
  2831 22 minutes
90
90
  8189 32 minutes
91
91
  2842 about 1 hour
92
-
93
-
94
-
95
-
92
+
93
+
94
+
@@ -22,7 +22,8 @@ Gem::Specification.new do |s|
22
22
  s.add_dependency "xml-simple"
23
23
  s.add_dependency "actionpack"
24
24
  s.add_dependency "amatch"
25
- # For the executable
26
- s.add_dependency "thor"
27
- s.add_development_dependency "rspec", "~> 2.0.0.beta.22"
25
+ s.add_dependency "thor" # For the executable
26
+ s.add_development_dependency "rspec", "~> 2"
27
+ s.add_development_dependency "webmock"
28
+ s.add_development_dependency "vcr"
28
29
  end
@@ -0,0 +1,263 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://webservices.nextbus.com/service/publicXMLFeed?a=sf-muni&command=routeList
6
+ body: ''
7
+ headers:
8
+ Accept:
9
+ - ! '*/*'
10
+ User-Agent:
11
+ - Ruby
12
+ response:
13
+ status:
14
+ code: 200
15
+ message: OK
16
+ headers:
17
+ Date:
18
+ - Wed, 21 Nov 2012 17:58:13 GMT
19
+ Server:
20
+ - Apache/2.2.4 (Unix) mod_ssl/2.2.4 OpenSSL/0.9.7m DAV/2 mod_jk/1.2.30
21
+ Access-Control-Allow-Origin:
22
+ - ! '*'
23
+ Content-Length:
24
+ - '3473'
25
+ Vary:
26
+ - Accept-Encoding
27
+ Content-Type:
28
+ - text/xml
29
+ body: ! "<?xml version=\"1.0\" encoding=\"utf-8\" ?> \n<body copyright=\"All data
30
+ copyright San Francisco Muni 2012.\">\n<route tag=\"F\" title=\"F-Market &amp;
31
+ Wharves\"/>\n<route tag=\"J\" title=\"J-Church\"/>\n<route tag=\"KT\" title=\"KT-Ingleside/Third
32
+ Street\"/>\n<route tag=\"L\" title=\"L-Taraval\"/>\n<route tag=\"M\" title=\"M-Ocean
33
+ View\"/>\n<route tag=\"N\" title=\"N-Judah\"/>\n<route tag=\"NX\" title=\"NX-N
34
+ Express\"/>\n<route tag=\"1\" title=\"1-California\"/>\n<route tag=\"1AX\" title=\"1AX-California
35
+ A Express\"/>\n<route tag=\"1BX\" title=\"1BX-California B Express\"/>\n<route
36
+ tag=\"2\" title=\"2-Clement\"/>\n<route tag=\"3\" title=\"3-Jackson\"/>\n<route
37
+ tag=\"5\" title=\"5-Fulton\"/>\n<route tag=\"6\" title=\"6-Parnassus\"/>\n<route
38
+ tag=\"8X\" title=\"8X-Bayshore Exp\"/>\n<route tag=\"8AX\" title=\"8AX-Bayshore
39
+ A Exp\"/>\n<route tag=\"8BX\" title=\"8BX-Bayshore B Exp\"/>\n<route tag=\"9\"
40
+ title=\"9-San Bruno\"/>\n<route tag=\"9L\" title=\"9L-San Bruno Limited\"/>\n<route
41
+ tag=\"10\" title=\"10-Townsend\"/>\n<route tag=\"12\" title=\"12-Folsom/Pacific\"/>\n<route
42
+ tag=\"14\" title=\"14-Mission\"/>\n<route tag=\"14L\" title=\"14L-Mission Limited\"/>\n<route
43
+ tag=\"14X\" title=\"14X-Mission Express\"/>\n<route tag=\"16X\" title=\"16X-Noriega
44
+ Express\"/>\n<route tag=\"17\" title=\"17-Park Merced\"/>\n<route tag=\"18\"
45
+ title=\"18-46th Avenue\"/>\n<route tag=\"19\" title=\"19-Polk\"/>\n<route tag=\"21\"
46
+ title=\"21-Hayes\"/>\n<route tag=\"22\" title=\"22-Fillmore\"/>\n<route tag=\"23\"
47
+ title=\"23-Monterey\"/>\n<route tag=\"24\" title=\"24-Divisadero\"/>\n<route
48
+ tag=\"27\" title=\"27-Bryant\"/>\n<route tag=\"28\" title=\"28-19th Avenue\"/>\n<route
49
+ tag=\"28L\" title=\"28L-19th Avenue Limited\"/>\n<route tag=\"29\" title=\"29-Sunset\"/>\n<route
50
+ tag=\"30\" title=\"30-Stockton\"/>\n<route tag=\"30X\" title=\"30X-Marina Express\"/>\n<route
51
+ tag=\"31\" title=\"31-Balboa\"/>\n<route tag=\"31AX\" title=\"31AX-Balboa A
52
+ Express\"/>\n<route tag=\"31BX\" title=\"31BX-Balboa B Express\"/>\n<route tag=\"33\"
53
+ title=\"33-Stanyan\"/>\n<route tag=\"35\" title=\"35-Eureka\"/>\n<route tag=\"36\"
54
+ title=\"36-Teresita\"/>\n<route tag=\"37\" title=\"37-Corbett\"/>\n<route tag=\"38\"
55
+ title=\"38-Geary\"/>\n<route tag=\"38AX\" title=\"38AX-Geary A Express\"/>\n<route
56
+ tag=\"38BX\" title=\"38BX-Geary B Express\"/>\n<route tag=\"38L\" title=\"38L-Geary
57
+ Limited\"/>\n<route tag=\"39\" title=\"39-Coit\"/>\n<route tag=\"41\" title=\"41-Union\"/>\n<route
58
+ tag=\"43\" title=\"43-Masonic\"/>\n<route tag=\"44\" title=\"44-O&apos;Shaughnessy\"/>\n<route
59
+ tag=\"45\" title=\"45-Union/Stockton\"/>\n<route tag=\"47\" title=\"47-Van Ness\"/>\n<route
60
+ tag=\"48\" title=\"48-Quintara - 24th Street\"/>\n<route tag=\"49\" title=\"49-Mission-Van
61
+ Ness\"/>\n<route tag=\"52\" title=\"52-Excelsior\"/>\n<route tag=\"54\" title=\"54-Felton\"/>\n<route
62
+ tag=\"56\" title=\"56-Rutland\"/>\n<route tag=\"66\" title=\"66-Quintara\"/>\n<route
63
+ tag=\"67\" title=\"67-Bernal Heights\"/>\n<route tag=\"71\" title=\"71-Haight-Noriega\"/>\n<route
64
+ tag=\"71L\" title=\"71L-Haight-Noriega Limited\"/>\n<route tag=\"76\" title=\"76-Marin
65
+ Headlands\"/>\n<route tag=\"80X\" title=\"80X-Gateway Express\"/>\n<route tag=\"81X\"
66
+ title=\"81X-Caltrain Express\"/>\n<route tag=\"82X\" title=\"82X-Levi Plaza
67
+ Express\"/>\n<route tag=\"83X\" title=\"83X-Caltrain\"/>\n<route tag=\"88\"
68
+ title=\"88-B.A.R.T. Shuttle\"/>\n<route tag=\"90\" title=\"90-San Bruno Owl\"/>\n<route
69
+ tag=\"91\" title=\"91-Owl\"/>\n<route tag=\"108\" title=\"108-Treasure Island\"/>\n<route
70
+ tag=\"K OWL\" title=\"K-Owl\"/>\n<route tag=\"L OWL\" title=\"L-Owl\"/>\n<route
71
+ tag=\"M OWL\" title=\"M-Owl\"/>\n<route tag=\"N OWL\" title=\"N-Owl\"/>\n<route
72
+ tag=\"T OWL\" title=\"T-Owl\"/>\n<route tag=\"59\" title=\"Powell/Mason Cable
73
+ Car\"/>\n<route tag=\"60\" title=\"Powell/Hyde Cable Car\"/>\n<route tag=\"61\"
74
+ title=\"California Cable Car\"/>\n</body>\n"
75
+ http_version:
76
+ recorded_at: Wed, 21 Nov 2012 17:58:15 GMT
77
+ - request:
78
+ method: get
79
+ uri: http://webservices.nextbus.com/service/publicXMLFeed?a=sf-muni&command=routeConfig&r=21
80
+ body: ''
81
+ headers:
82
+ Accept:
83
+ - ! '*/*'
84
+ User-Agent:
85
+ - Ruby
86
+ response:
87
+ status:
88
+ code: 200
89
+ message: OK
90
+ headers:
91
+ Date:
92
+ - Wed, 21 Nov 2012 17:58:13 GMT
93
+ Server:
94
+ - Apache/2.2.4 (Unix) mod_ssl/2.2.4 OpenSSL/0.9.7m DAV/2 mod_jk/1.2.30
95
+ Access-Control-Allow-Origin:
96
+ - ! '*'
97
+ Vary:
98
+ - Accept-Encoding
99
+ Transfer-Encoding:
100
+ - chunked
101
+ Content-Type:
102
+ - text/xml
103
+ body: ! "<?xml version=\"1.0\" encoding=\"utf-8\" ?> \n<body copyright=\"All data
104
+ copyright San Francisco Muni 2012.\">\n<route tag=\"21\" title=\"21-Hayes\"
105
+ color=\"660000\" oppositeColor=\"ffffff\" latMin=\"37.7729599\" latMax=\"37.7944299\"
106
+ lonMin=\"-122.46384\" lonMax=\"-122.39323\">\n<stop tag=\"6497\" title=\"Steuart
107
+ St &amp; Mission St\" lat=\"37.7933499\" lon=\"-122.39323\" stopId=\"16497\"/>\n<stop
108
+ tag=\"6501\" title=\"Steuart St &amp; Market St\" lat=\"37.7944299\" lon=\"-122.3945499\"
109
+ stopId=\"16501\"/>\n<stop tag=\"5669\" title=\"Market St &amp; Drumm St\" lat=\"37.79347\"
110
+ lon=\"-122.3961799\" stopId=\"15669\"/>\n<stop tag=\"5671\" title=\"Market St
111
+ &amp; Front St\" lat=\"37.79192\" lon=\"-122.3981499\" stopId=\"15671\"/>\n<stop
112
+ tag=\"5689\" title=\"Market St &amp; Sansome St\" lat=\"37.7901599\" lon=\"-122.40041\"
113
+ stopId=\"15689\"/>\n<stop tag=\"5684\" title=\"Market St &amp; Montgomery St\"
114
+ lat=\"37.7884899\" lon=\"-122.40248\" stopId=\"15684\"/>\n<stop tag=\"5674\"
115
+ title=\"Market St &amp; Grant Ave\" lat=\"37.78639\" lon=\"-122.4051599\" stopId=\"15674\"/>\n<stop
116
+ tag=\"5688\" title=\"Market St &amp; Powell St\" lat=\"37.7846799\" lon=\"-122.40731\"
117
+ stopId=\"15688\"/>\n<stop tag=\"5683\" title=\"Market St &amp; Mason St\" lat=\"37.7828499\"
118
+ lon=\"-122.40964\" stopId=\"15683\"/>\n<stop tag=\"5656\" title=\"Market St
119
+ &amp; 7th St North\" lat=\"37.7805699\" lon=\"-122.41244\" stopId=\"15656\"/>\n<stop
120
+ tag=\"7423\" title=\"Market St &amp; Hyde St\" lat=\"37.7787799\" lon=\"-122.41472\"
121
+ stopId=\"17423\"/>\n<stop tag=\"4997\" title=\"Hayes St &amp; Larkin St\" lat=\"37.7777099\"
122
+ lon=\"-122.41685\" stopId=\"14997\"/>\n<stop tag=\"5013\" title=\"Hayes St &amp;
123
+ Van Ness Ave\" lat=\"37.7772899\" lon=\"-122.42019\" stopId=\"15013\"/>\n<stop
124
+ tag=\"4996\" title=\"Hayes St &amp; Gough St\" lat=\"37.77689\" lon=\"-122.4233299\"
125
+ stopId=\"14996\"/>\n<stop tag=\"4998\" title=\"Hayes St &amp; Laguna St\" lat=\"37.7765299\"
126
+ lon=\"-122.42615\" stopId=\"14998\"/>\n<stop tag=\"4983\" title=\"Hayes St &amp;
127
+ Buchanan St\" lat=\"37.7762599\" lon=\"-122.42827\" stopId=\"14983\"/>\n<stop
128
+ tag=\"5014\" title=\"Hayes St &amp; Webster St\" lat=\"37.7760599\" lon=\"-122.42988\"
129
+ stopId=\"15014\"/>\n<stop tag=\"4993\" title=\"Hayes St &amp; Fillmore St\"
130
+ lat=\"37.77584\" lon=\"-122.4315599\" stopId=\"14993\"/>\n<stop tag=\"5011\"
131
+ title=\"Hayes St &amp; Steiner St\" lat=\"37.77563\" lon=\"-122.4331999\" stopId=\"15011\"/>\n<stop
132
+ tag=\"5003\" title=\"Hayes St &amp; Pierce St\" lat=\"37.77547\" lon=\"-122.4344399\"
133
+ stopId=\"15003\"/>\n<stop tag=\"4991\" title=\"Hayes St &amp; Divisadero St\"
134
+ lat=\"37.7749899\" lon=\"-122.43818\" stopId=\"14991\"/>\n<stop tag=\"4979\"
135
+ title=\"Hayes St &amp; Baker St\" lat=\"37.7745699\" lon=\"-122.4415\" stopId=\"14979\"/>\n<stop
136
+ tag=\"4999\" title=\"Hayes St &amp; Lyon St\" lat=\"37.77443\" lon=\"-122.4426299\"
137
+ stopId=\"14999\"/>\n<stop tag=\"4985\" title=\"Hayes St &amp; Central Ave\"
138
+ lat=\"37.7742\" lon=\"-122.4442999\" stopId=\"14985\"/>\n<stop tag=\"5001\"
139
+ title=\"Hayes St &amp; Masonic Ave\" lat=\"37.7739299\" lon=\"-122.44651\" stopId=\"15001\"/>\n<stop
140
+ tag=\"4987\" title=\"Hayes St &amp; Clayton St\" lat=\"37.7736099\" lon=\"-122.44917\"
141
+ stopId=\"14987\"/>\n<stop tag=\"5007\" title=\"Hayes St &amp; Shrader St\" lat=\"37.7731699\"
142
+ lon=\"-122.4525\" stopId=\"15007\"/>\n<stop tag=\"5009\" title=\"Hayes St &amp;
143
+ Stanyan St\" lat=\"37.7729599\" lon=\"-122.45415\" stopId=\"15009\"/>\n<stop
144
+ tag=\"37499\" title=\"Fulton St &amp; Shrader St\" lat=\"37.7748699\" lon=\"-122.45309\"
145
+ stopId=\"137499\"/>\n<stop tag=\"7499\" title=\"Fulton St &amp; Shrader St\"
146
+ lat=\"37.7748699\" lon=\"-122.45309\" stopId=\"17499\"/>\n<stop tag=\"7561\"
147
+ title=\"Hayes St &amp; Shrader St\" lat=\"37.77306\" lon=\"-122.4525099\" stopId=\"17561\"/>\n<stop
148
+ tag=\"4988\" title=\"Hayes St &amp; Clayton St\" lat=\"37.7734199\" lon=\"-122.44946\"
149
+ stopId=\"14988\"/>\n<stop tag=\"5002\" title=\"Hayes St &amp; Masonic Ave\"
150
+ lat=\"37.7739499\" lon=\"-122.44568\" stopId=\"15002\"/>\n<stop tag=\"4986\"
151
+ title=\"Hayes St &amp; Central Ave\" lat=\"37.77409\" lon=\"-122.4445099\" stopId=\"14986\"/>\n<stop
152
+ tag=\"5000\" title=\"Hayes St &amp; Lyon St\" lat=\"37.7742899\" lon=\"-122.44286\"
153
+ stopId=\"15000\"/>\n<stop tag=\"4980\" title=\"Hayes St &amp; Baker St\" lat=\"37.7745099\"
154
+ lon=\"-122.44126\" stopId=\"14980\"/>\n<stop tag=\"4992\" title=\"Hayes St &amp;
155
+ Divisadero St\" lat=\"37.7749999\" lon=\"-122.4374\" stopId=\"14992\"/>\n<stop
156
+ tag=\"5004\" title=\"Hayes St &amp; Pierce St\" lat=\"37.7754099\" lon=\"-122.43418\"
157
+ stopId=\"15004\"/>\n<stop tag=\"5012\" title=\"Hayes St &amp; Steiner St\" lat=\"37.77563\"
158
+ lon=\"-122.4324799\" stopId=\"15012\"/>\n<stop tag=\"4994\" title=\"Hayes St
159
+ &amp; Fillmore St\" lat=\"37.7757999\" lon=\"-122.43083\" stopId=\"14994\"/>\n<stop
160
+ tag=\"5015\" title=\"Hayes St &amp; Webster St\" lat=\"37.7760399\" lon=\"-122.42919\"
161
+ stopId=\"15015\"/>\n<stop tag=\"4984\" title=\"Hayes St &amp; Buchanan St\"
162
+ lat=\"37.77624\" lon=\"-122.4275499\" stopId=\"14984\"/>\n<stop tag=\"5260\"
163
+ title=\"Laguna St &amp; Hayes St\" lat=\"37.7767499\" lon=\"-122.42627\" stopId=\"15260\"/>\n<stop
164
+ tag=\"4921\" title=\"Grove St &amp; Laguna St\" lat=\"37.77738\" lon=\"-122.4263199\"
165
+ stopId=\"14921\"/>\n<stop tag=\"4920\" title=\"Grove St &amp; Gough St\" lat=\"37.77775\"
166
+ lon=\"-122.4233099\" stopId=\"14920\"/>\n<stop tag=\"4923\" title=\"Grove St
167
+ &amp; Van Ness Ave\" lat=\"37.7781899\" lon=\"-122.41974\" stopId=\"14923\"/>\n<stop
168
+ tag=\"7463\" title=\"Grove St &amp; Polk St\" lat=\"37.77838\" lon=\"-122.4183099\"
169
+ stopId=\"17463\"/>\n<stop tag=\"5652\" title=\"Market St &amp; 9th St\" lat=\"37.77741\"
170
+ lon=\"-122.4163399\" stopId=\"15652\"/>\n<stop tag=\"5651\" title=\"Market St
171
+ &amp; 8th St\" lat=\"37.77861\" lon=\"-122.4148299\" stopId=\"15651\"/>\n<stop
172
+ tag=\"5650\" title=\"Market St &amp; 7th St\" lat=\"37.7803599\" lon=\"-122.41261\"
173
+ stopId=\"15650\"/>\n<stop tag=\"5647\" title=\"Market St &amp; 6th St\" lat=\"37.7820999\"
174
+ lon=\"-122.4104\" stopId=\"15647\"/>\n<stop tag=\"5645\" title=\"Market St &amp;
175
+ 5th St\" lat=\"37.7838899\" lon=\"-122.40814\" stopId=\"15645\"/>\n<stop tag=\"5643\"
176
+ title=\"Market St &amp; 4th St\" lat=\"37.7856499\" lon=\"-122.40589\" stopId=\"15643\"/>\n<stop
177
+ tag=\"5640\" title=\"Market St &amp; 3rd St\" lat=\"37.7875299\" lon=\"-122.40352\"
178
+ stopId=\"15640\"/>\n<stop tag=\"5685\" title=\"Market St &amp; New Montgomery
179
+ St\" lat=\"37.7886099\" lon=\"-122.40216\" stopId=\"15685\"/>\n<stop tag=\"7264\"
180
+ title=\"Market St &amp; 1st St\" lat=\"37.79094\" lon=\"-122.3991899\" stopId=\"17264\"/>\n<stop
181
+ tag=\"5658\" title=\"Market St &amp; Beale St\" lat=\"37.79257\" lon=\"-122.3970199\"
182
+ stopId=\"15658\"/>\n<stop tag=\"6475\" title=\"Spear St &amp; Market St\" lat=\"37.7935899\"
183
+ lon=\"-122.3955499\" stopId=\"16475\"/>\n<stop tag=\"36497\" title=\"Steuart
184
+ St &amp; Mission St\" lat=\"37.7933499\" lon=\"-122.39323\" stopId=\"136497\"/>\n<stop
185
+ tag=\"4733\" title=\"Fulton St &amp; 6th Ave\" lat=\"37.7735299\" lon=\"-122.46384\"
186
+ stopId=\"14733\"/>\n<stop tag=\"3089\" title=\"Beale St &amp; Mission St\" lat=\"37.7917499\"
187
+ lon=\"-122.3967\" stopId=\"13089\"/>\n<direction tag=\"21_IB1\" title=\"Inbound
188
+ to Downtown\" name=\"Inbound\" useForUI=\"true\">\n <stop tag=\"7499\" />\n
189
+ \ <stop tag=\"7561\" />\n <stop tag=\"4988\" />\n <stop tag=\"5002\" />\n
190
+ \ <stop tag=\"4986\" />\n <stop tag=\"5000\" />\n <stop tag=\"4980\" />\n
191
+ \ <stop tag=\"4992\" />\n <stop tag=\"5004\" />\n <stop tag=\"5012\" />\n
192
+ \ <stop tag=\"4994\" />\n <stop tag=\"5015\" />\n <stop tag=\"4984\" />\n
193
+ \ <stop tag=\"5260\" />\n <stop tag=\"4921\" />\n <stop tag=\"4920\" />\n
194
+ \ <stop tag=\"4923\" />\n <stop tag=\"7463\" />\n <stop tag=\"5652\" />\n
195
+ \ <stop tag=\"5651\" />\n <stop tag=\"5650\" />\n <stop tag=\"5647\" />\n
196
+ \ <stop tag=\"5645\" />\n <stop tag=\"5643\" />\n <stop tag=\"5640\" />\n
197
+ \ <stop tag=\"5685\" />\n <stop tag=\"7264\" />\n <stop tag=\"5658\" />\n
198
+ \ <stop tag=\"6475\" />\n <stop tag=\"36497\" />\n</direction>\n<direction
199
+ tag=\"21_OB4\" title=\"Outbound to Golden Gate Park\" name=\"Outbound\" useForUI=\"true\">\n
200
+ \ <stop tag=\"6497\" />\n <stop tag=\"6501\" />\n <stop tag=\"5669\" />\n
201
+ \ <stop tag=\"5671\" />\n <stop tag=\"5689\" />\n <stop tag=\"5684\" />\n
202
+ \ <stop tag=\"5674\" />\n <stop tag=\"5688\" />\n <stop tag=\"5683\" />\n
203
+ \ <stop tag=\"5656\" />\n <stop tag=\"7423\" />\n <stop tag=\"4997\" />\n
204
+ \ <stop tag=\"5013\" />\n <stop tag=\"4996\" />\n <stop tag=\"4998\" />\n
205
+ \ <stop tag=\"4983\" />\n <stop tag=\"5014\" />\n <stop tag=\"4993\" />\n
206
+ \ <stop tag=\"5011\" />\n <stop tag=\"5003\" />\n <stop tag=\"4991\" />\n
207
+ \ <stop tag=\"4979\" />\n <stop tag=\"4999\" />\n <stop tag=\"4985\" />\n
208
+ \ <stop tag=\"5001\" />\n <stop tag=\"4987\" />\n <stop tag=\"5007\" />\n
209
+ \ <stop tag=\"5009\" />\n <stop tag=\"37499\" />\n</direction>\n<path>\n<point
210
+ lat=\"37.775\" lon=\"-122.4374\"/>\n<point lat=\"37.77541\" lon=\"-122.43418\"/>\n<point
211
+ lat=\"37.77563\" lon=\"-122.43248\"/>\n<point lat=\"37.7757999\" lon=\"-122.43083\"/>\n<point
212
+ lat=\"37.77604\" lon=\"-122.42919\"/>\n<point lat=\"37.77624\" lon=\"-122.42755\"/>\n<point
213
+ lat=\"37.77646\" lon=\"-122.42627\"/>\n<point lat=\"37.77675\" lon=\"-122.42627\"/>\n<point
214
+ lat=\"37.7773899\" lon=\"-122.42646\"/>\n<point lat=\"37.77738\" lon=\"-122.42632\"/>\n<point
215
+ lat=\"37.77775\" lon=\"-122.42331\"/>\n<point lat=\"37.77819\" lon=\"-122.41974\"/>\n</path>\n<path>\n<point
216
+ lat=\"37.77487\" lon=\"-122.45309\"/>\n<point lat=\"37.77496\" lon=\"-122.45299\"/>\n<point
217
+ lat=\"37.7731\" lon=\"-122.45262\"/>\n<point lat=\"37.77306\" lon=\"-122.45251\"/>\n<point
218
+ lat=\"37.77342\" lon=\"-122.44946\"/>\n<point lat=\"37.77395\" lon=\"-122.44568\"/>\n</path>\n<path>\n<point
219
+ lat=\"37.77819\" lon=\"-122.41974\"/>\n<point lat=\"37.77848\" lon=\"-122.41823\"/>\n<point
220
+ lat=\"37.77838\" lon=\"-122.41831\"/>\n<point lat=\"37.7768\" lon=\"-122.4179\"/>\n<point
221
+ lat=\"37.77654\" lon=\"-122.41751\"/>\n<point lat=\"37.77741\" lon=\"-122.41634\"/>\n<point
222
+ lat=\"37.77861\" lon=\"-122.41483\"/>\n<point lat=\"37.78036\" lon=\"-122.41261\"/>\n</path>\n<path>\n<point
223
+ lat=\"37.77393\" lon=\"-122.44651\"/>\n<point lat=\"37.77361\" lon=\"-122.44917\"/>\n<point
224
+ lat=\"37.77317\" lon=\"-122.4525\"/>\n<point lat=\"37.77296\" lon=\"-122.45415\"/>\n<point
225
+ lat=\"37.7728899\" lon=\"-122.45428\"/>\n<point lat=\"37.77464\" lon=\"-122.45463\"/>\n<point
226
+ lat=\"37.7749\" lon=\"-122.45346\"/>\n<point lat=\"37.77487\" lon=\"-122.45309\"/>\n</path>\n<path>\n<point
227
+ lat=\"37.7856499\" lon=\"-122.40589\"/>\n<point lat=\"37.7875299\" lon=\"-122.40352\"/>\n<point
228
+ lat=\"37.78861\" lon=\"-122.40216\"/>\n</path>\n<path>\n<point lat=\"37.78036\"
229
+ lon=\"-122.41261\"/>\n<point lat=\"37.7821\" lon=\"-122.4104\"/>\n<point lat=\"37.78389\"
230
+ lon=\"-122.40814\"/>\n<point lat=\"37.7856499\" lon=\"-122.40589\"/>\n</path>\n<path>\n<point
231
+ lat=\"37.77487\" lon=\"-122.45309\"/>\n<point lat=\"37.7731\" lon=\"-122.45262\"/>\n<point
232
+ lat=\"37.77306\" lon=\"-122.45251\"/>\n<point lat=\"37.77342\" lon=\"-122.44946\"/>\n<point
233
+ lat=\"37.77395\" lon=\"-122.44568\"/>\n</path>\n<path>\n<point lat=\"37.77499\"
234
+ lon=\"-122.43818\"/>\n<point lat=\"37.77457\" lon=\"-122.4415\"/>\n<point lat=\"37.77443\"
235
+ lon=\"-122.44263\"/>\n<point lat=\"37.7742\" lon=\"-122.4443\"/>\n<point lat=\"37.77393\"
236
+ lon=\"-122.44651\"/>\n</path>\n<path>\n<point lat=\"37.77729\" lon=\"-122.42019\"/>\n<point
237
+ lat=\"37.77689\" lon=\"-122.42333\"/>\n<point lat=\"37.77653\" lon=\"-122.42615\"/>\n<point
238
+ lat=\"37.77626\" lon=\"-122.42827\"/>\n<point lat=\"37.77606\" lon=\"-122.42988\"/>\n<point
239
+ lat=\"37.77584\" lon=\"-122.43156\"/>\n<point lat=\"37.77563\" lon=\"-122.4332\"/>\n<point
240
+ lat=\"37.77547\" lon=\"-122.43444\"/>\n<point lat=\"37.77499\" lon=\"-122.43818\"/>\n</path>\n<path>\n<point
241
+ lat=\"37.78468\" lon=\"-122.40731\"/>\n<point lat=\"37.78285\" lon=\"-122.40964\"/>\n<point
242
+ lat=\"37.78057\" lon=\"-122.41244\"/>\n</path>\n<path>\n<point lat=\"37.78861\"
243
+ lon=\"-122.40216\"/>\n<point lat=\"37.79094\" lon=\"-122.39919\"/>\n<point lat=\"37.79257\"
244
+ lon=\"-122.39702\"/>\n<point lat=\"37.79378\" lon=\"-122.39563\"/>\n<point lat=\"37.79359\"
245
+ lon=\"-122.39555\"/>\n<point lat=\"37.79254\" lon=\"-122.39407\"/>\n<point lat=\"37.79322\"
246
+ lon=\"-122.39319\"/>\n<point lat=\"37.7933499\" lon=\"-122.39323\"/>\n</path>\n<path>\n<point
247
+ lat=\"37.7933499\" lon=\"-122.39323\"/>\n<point lat=\"37.79443\" lon=\"-122.39455\"/>\n<point
248
+ lat=\"37.7944699\" lon=\"-122.39476\"/>\n<point lat=\"37.79347\" lon=\"-122.39618\"/>\n<point
249
+ lat=\"37.79192\" lon=\"-122.39815\"/>\n<point lat=\"37.79016\" lon=\"-122.40041\"/>\n</path>\n<path>\n<point
250
+ lat=\"37.79016\" lon=\"-122.40041\"/>\n<point lat=\"37.78849\" lon=\"-122.40248\"/>\n<point
251
+ lat=\"37.78639\" lon=\"-122.40516\"/>\n<point lat=\"37.78468\" lon=\"-122.40731\"/>\n</path>\n<path>\n<point
252
+ lat=\"37.78861\" lon=\"-122.40216\"/>\n<point lat=\"37.7924\" lon=\"-122.39739\"/>\n<point
253
+ lat=\"37.79175\" lon=\"-122.3967\"/>\n</path>\n<path>\n<point lat=\"37.77353\"
254
+ lon=\"-122.46384\"/>\n<point lat=\"37.77487\" lon=\"-122.45309\"/>\n</path>\n<path>\n<point
255
+ lat=\"37.77395\" lon=\"-122.44568\"/>\n<point lat=\"37.77409\" lon=\"-122.44451\"/>\n<point
256
+ lat=\"37.77429\" lon=\"-122.44286\"/>\n<point lat=\"37.77451\" lon=\"-122.44126\"/>\n<point
257
+ lat=\"37.775\" lon=\"-122.4374\"/>\n</path>\n<path>\n<point lat=\"37.78057\"
258
+ lon=\"-122.41244\"/>\n<point lat=\"37.77878\" lon=\"-122.41472\"/>\n<point lat=\"37.77779\"
259
+ lon=\"-122.41593\"/>\n<point lat=\"37.77771\" lon=\"-122.41685\"/>\n<point lat=\"37.77729\"
260
+ lon=\"-122.42019\"/>\n</path>\n</route>\n</body>\n"
261
+ http_version:
262
+ recorded_at: Wed, 21 Nov 2012 17:58:15 GMT
263
+ recorded_with: VCR 2.0.0.rc1