muni 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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