limores_hopstop 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/app_id.rb ADDED
@@ -0,0 +1,5 @@
1
+ module LimoresHopstop
2
+ module Hopstop
3
+ APP_ID = "bieilq6dov2muo8x"
4
+ end
5
+ end
data/lib/hopstop.rb ADDED
@@ -0,0 +1,206 @@
1
+ require 'open-uri'
2
+ require 'rexml/document'
3
+ require File.expand_path(File.dirname(__FILE__) + '/app_id')
4
+
5
+ module LimoresHopstop
6
+ module Hopstop
7
+ module Mashup
8
+ def self.populate_with_response_status(result, doc)
9
+ result.result_code =
10
+ (doc.root.elements["//ResponseStatus/ResultCode"] || doc.root.elements["//ResponseStatus/FaultCode"]).text.to_i
11
+ result.result_string = (doc.root.elements["//ResponseStatus/ResultString"] || doc.root.elements["//ResponseStatus/FaultString"]).text
12
+ end
13
+
14
+ #Contains a list of City results from the HopStop API
15
+ class Cities < Array
16
+ attr_accessor :result_code, :result_string
17
+
18
+ def self.all
19
+ doc = REXML::Document.new(fetch_cities)
20
+ results = new
21
+
22
+ Mashup.populate_with_response_status results, doc
23
+
24
+ doc.root.elements.each('//Cities/item') do |city|
25
+ data = city.elements
26
+ results << City.new(
27
+ data['Id'].text,
28
+ data['CellGateway'].text,
29
+ data['DefaultCounty'].text,
30
+ data['Name'].text,
31
+ data['State'].text,
32
+ data['UsePlaces'].text
33
+ )
34
+ end
35
+ results
36
+ end
37
+
38
+ def self.find(city_id)
39
+ all.each {|city| return city if city.id == city_id}
40
+ return nil
41
+ end
42
+
43
+ def valid?
44
+ self.result_code == 200 and self.result_string == 'Success.'
45
+ end
46
+
47
+ private
48
+
49
+ def self.fetch_cities
50
+ url = "http://www.hopstop.com/ws/GetCities?licenseKey=#{LimoresHopstop::Hopstop::APP_ID}"
51
+
52
+ begin
53
+ xml = open(URI.encode(url)).read
54
+ rescue OpenURI::HTTPError => error
55
+ raise BadRequestException.new(error.to_s)
56
+ rescue
57
+ raise ConnectionException.new("Unable to connect to HopStop REST service")
58
+ end
59
+ xml
60
+ end
61
+ end
62
+
63
+ class City < Struct.new(:id,:cell_gateway,:default_country,:name,:state,:use_places)
64
+ end
65
+
66
+ class Route
67
+ attr_accessor :result_code, :result_string
68
+ attr_reader :nodes, :maps, :refined_addresses1, :refined_addresses2
69
+
70
+ def initialize
71
+ @maps ||= []
72
+ @refined_addresses1 ||= []
73
+ @refined_addresses2 ||= []
74
+ end
75
+
76
+ def self.find(params={})
77
+ validate_params params
78
+ parse_from fetch_route( params )
79
+ end
80
+
81
+ def valid?
82
+ self.result_code == 200 and self.result_string == 'Route found.'
83
+ end
84
+
85
+ def multi_choice?
86
+ self.result_code == 201 and self.result_string == 'Several choices found.'
87
+ end
88
+
89
+ def populate_as_valid(doc)
90
+ route_node = doc.root.elements["//RouteInfo/Route"]
91
+ @nodes = RouteInfos.new
92
+ @nodes.id = doc.root.elements["//RouteInfo/Id"].text
93
+ @nodes.total_time_description = doc.root.elements["//RouteInfo/TotalTimeVerb"].text
94
+ @nodes.distance_in_miles = doc.root.elements["//RouteInfo/ABDistance"].text.to_f
95
+ @nodes.parse_route_node(doc.root.elements["//RouteInfo/Route"].text)
96
+ parse_maps_node(doc)
97
+ end
98
+
99
+ def populate_as_multiple_choice(doc)
100
+ @refined_addresses1.clear
101
+ @refined_addresses2.clear
102
+ populate_addresses1 = doc.root.elements["//RouteInfo/Address1FoundExact"].text != "1"
103
+ populate_addresses2 = doc.root.elements["//RouteInfo/Address2FoundExact"].text != "1"
104
+ doc.root.elements.each("//Thumbnails/item") do |item_node|
105
+ data = item_node.elements
106
+ if data['AddressId'].text == "1"
107
+ add_refined_address( data, :into => @refined_addresses1 ) if populate_addresses1
108
+ else
109
+ add_refined_address( data, :into => @refined_addresses2 ) if populate_addresses2
110
+ end
111
+ end
112
+ end
113
+
114
+ private
115
+
116
+ def add_refined_address( node, params )
117
+ destination = params[:into]
118
+ destination << RefinedAddress.new(
119
+ node['Id'].text, node['Address'].text, node['City'].text, node['County'].text, node['Title'].text, node['URL'].text
120
+ )
121
+ end
122
+
123
+ def parse_maps_node(doc)
124
+ @maps.clear
125
+ doc.root.elements.each("//Maps/item") do |item_node|
126
+ data = item_node.elements
127
+ @maps << Map.new(
128
+ data['Id'].text,
129
+ data['Number'].text.to_i,
130
+ data['Height'].text.to_i,
131
+ data['Width'].text.to_i,
132
+ data['URL'].text,
133
+ data['Title'].text
134
+ )
135
+ end
136
+ end
137
+
138
+ def self.validate_params(params)
139
+ #mode parameter should be 's' - subway only, or 'b' - bus only, or 'a' - subway and bus, or 'w' - walking only
140
+ params[:mode] ||= 'a'
141
+ required_fields = %w(address1 address2 day time)
142
+ missing_arguments = []
143
+ required_fields.each do |field|
144
+ missing_arguments << field unless params[field.intern]
145
+ end
146
+ raise ArgumentError.new(missing_arguments) if missing_arguments.size > 0
147
+ end
148
+
149
+ def self.fetch_route(params={})
150
+ url = "http://www.hopstop.com/ws/GetRoute?licenseKey=#{LimoresHopstop::Hopstop::APP_ID}"
151
+ params.each do |param, value|
152
+ url += "&#{param.to_s}=#{value}"
153
+ end
154
+
155
+ begin
156
+ xml = open(URI.encode(url)).read
157
+ rescue OpenURI::HTTPError => error
158
+ raise BadRequestException.new(error.to_s)
159
+ rescue
160
+ raise ConnectionException.new("Unable to connect to HopStop REST service")
161
+ end
162
+ xml
163
+ end
164
+
165
+ def self.parse_from(xml)
166
+ doc = REXML::Document.new(xml)
167
+ result = new
168
+
169
+ Mashup.populate_with_response_status result, doc
170
+ if result.valid?
171
+ result.populate_as_valid(doc)
172
+ elsif result.multi_choice?
173
+ result.populate_as_multiple_choice(doc)
174
+ end
175
+ result
176
+ end
177
+ end
178
+
179
+ class RouteInfos < Array
180
+ attr_accessor :id, :total_time_description, :distance_in_miles
181
+
182
+ def parse_route_node(text)
183
+ clear
184
+ for line in text.split("\n")
185
+ txt, time, type, icon_url = line.split("\t")
186
+ txt = txt.strip if txt
187
+ time = time.to_i
188
+ type = type.strip if type
189
+ icon_url = icon_url.strip if icon_url
190
+ node = RouteNode.new( txt, time, type, icon_url )
191
+ self << node unless node.text.nil?
192
+ end
193
+ end
194
+ end
195
+
196
+ class RouteNode < Struct.new(:text, :time, :type, :icon_url)
197
+ end
198
+
199
+ class Map < Struct.new(:id, :number, :height, :width, :url, :title)
200
+ end
201
+
202
+ class RefinedAddress < Struct.new(:id, :address, :city, :county, :title, :url)
203
+ end
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,262 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/xml_responses')
3
+
4
+ describe Cities do
5
+ context "fetch live data" do
6
+ it "should fetch all cities from hopstop" do
7
+ cities = Cities.all
8
+ cities.should be_instance_of(Cities)
9
+ cities.should have_at_least(1).city
10
+ cities.should be_valid
11
+ end
12
+ end
13
+
14
+ it "should parse 2 cities from response with 2 items" do
15
+ xml_response = XmlResponses.valid_cities
16
+ Cities.stubs(:fetch_cities).returns(xml_response)
17
+
18
+ cities = Cities.all
19
+
20
+ cities.should have(2).cities
21
+ cities.should be_valid
22
+ end
23
+
24
+ it "should be valid if response status is 200 - Success." do
25
+ xml_response = XmlResponses.valid_cities :result_code => 200, :result_string => 'Success.'
26
+ Cities.stubs(:fetch_cities).returns(xml_response)
27
+
28
+ cities = Cities.all
29
+
30
+ cities.result_code.should == 200
31
+ cities.result_string.should == "Success."
32
+ cities.should be_valid
33
+ end
34
+
35
+ it "should be invalid unless response status is 200 - Success." do
36
+ xml_response = XmlResponses.invalid_response :fault_code => 112, :fault_string => 'Invalid license Key.'
37
+ Cities.stubs(:fetch_cities).returns(xml_response)
38
+
39
+ cities = Cities.all
40
+
41
+ cities.result_code.should == 112
42
+ cities.result_string.should == "Invalid license Key."
43
+ cities.should_not be_valid
44
+ end
45
+
46
+ it "should return City for find if ID is valid" do
47
+ xml_response = XmlResponses.valid_cities :city1 => 'boston'
48
+ Cities.stubs(:fetch_cities).returns(xml_response)
49
+
50
+ boston = Cities.find 'boston'
51
+ boston.should be_instance_of(City)
52
+ boston.id.should == 'boston'
53
+ end
54
+
55
+ it "should return nil for find unless ID is valid" do
56
+ xml_response = XmlResponses.valid_cities
57
+ Cities.stubs(:fetch_cities).returns(xml_response)
58
+
59
+ city = Cities.find 'doesnt_exist'
60
+ city.should be(nil)
61
+ end
62
+ end
63
+
64
+ describe Route do
65
+ context "fetch live data" do
66
+ it "should be valid for valid, non-multi choice request" do
67
+
68
+ route = Route.find :address1 => 'jfk', :address2 => '940 2ND ave, Manhattan', :day => 1, :time => '09:30'
69
+
70
+ route.should be_valid
71
+ end
72
+
73
+ it "should be invalid / multi-choice for valid but multi choice request" do
74
+
75
+ route = Route.find :address1 => 'jfk', :address2 => '2nd Ave', :day => 1, :time => '09:30'
76
+
77
+ route.should_not be_valid
78
+ route.should be_multi_choice
79
+ end
80
+
81
+ it "should be invalid for invalid request" do
82
+ Route.stubs(:validate_params)
83
+
84
+ route = Route.find
85
+
86
+ route.should_not be_valid
87
+ route.should_not be_multi_choice
88
+ end
89
+ end
90
+
91
+ it "should raise missing parameter exception unless all required fields are provided" do
92
+ cities_response = XmlResponses.valid_cities :city1 => 'boston', :city2 => 'newyork'
93
+ error_messages = nil
94
+
95
+ lambda { Route.find }.should raise_error(ArgumentError) { |error| error_messages = error.message }
96
+
97
+ error_messages.should be_instance_of(Array)
98
+ %w(address1 address2 day time).each { |field| error_messages.should include(field) }
99
+ end
100
+
101
+ context "for valid, non-multi choice request" do
102
+ it "should be valid with nodes and maps populated" do
103
+ route_response = XmlResponses.valid_route
104
+ Route.stubs(:validate_params)
105
+ Route.stubs(:fetch_route).returns(route_response)
106
+
107
+ route = Route.find
108
+
109
+ route.should be_instance_of(Route)
110
+ route.should be_valid
111
+ route.nodes.should have_at_least(1).node
112
+ route.maps.should have_at_least(1).map
113
+ end
114
+
115
+ it "should have correct values in route nodes after parsing" do
116
+ route_response = XmlResponses.valid_route :route_node1 => {
117
+ :text => 'Some direction info', :time => 23, :type => 'W', :icon_url => 'http://hopstop.com/icon.png'
118
+ }
119
+ Route.stubs(:validate_params)
120
+ Route.stubs(:fetch_route).returns(route_response)
121
+
122
+ route = Route.find
123
+
124
+ route.nodes.first.text.should == 'Some direction info'
125
+ route.nodes.first.time.should == 23
126
+ route.nodes.first.type.should == 'W'
127
+ route.nodes.first.icon_url.should == 'http://hopstop.com/icon.png'
128
+ end
129
+
130
+ it "should have correct values in map nodes after parsing" do
131
+ route_response = XmlResponses.valid_route :map1 => {
132
+ :id => 'id_1', :number => 1, :title => 'Title for map 1', :url => 'http://hopstop.com/maps?id_1'
133
+ }
134
+ Route.stubs(:validate_params)
135
+ Route.stubs(:fetch_route).returns(route_response)
136
+
137
+ route = Route.find
138
+
139
+ route.maps.first.id.should == 'id_1'
140
+ route.maps.first.number.should == 1
141
+ route.maps.first.title.should == 'Title for map 1'
142
+ route.maps.first.url.should == 'http://hopstop.com/maps?id_1'
143
+ end
144
+ end
145
+
146
+ context "for valid but multi choice request" do
147
+ it "should not be valid but multi choice" do
148
+ route_response = XmlResponses.several_choices_for_route
149
+ Route.stubs(:validate_params)
150
+ Route.stubs(:fetch_route).returns(route_response)
151
+
152
+ route = Route.find
153
+
154
+ route.should be_instance_of(Route)
155
+ route.should_not be_valid
156
+ route.should be_multi_choice
157
+ end
158
+
159
+ it "should offer refined addresses with correctly parsed data for multi choice address2 but not for address1" do
160
+ route_response = XmlResponses.several_choices_for_route(
161
+ :refined_addresses2 => [
162
+ { :address => '1210 2ND ave', :city => 'newyork', :county => '36061',
163
+ :title => '1210 2ND ave, Manhattan [UA 64th St and 2nd Ave]', :url => 'http://www.hopstop.com/ws/map?qdtck3cough5b1sl'},
164
+ { :address => '111TH st and LIBERTY ave', :city => 'newyork', :county => '36081',
165
+ :title => '111TH st and LIBERTY ave, Queens [111 St [A Train]]', :url => 'http://www.hopstop.com/ws/map?3863qjw7qn6co52o'}
166
+ ]
167
+ )
168
+ Route.stubs(:validate_params)
169
+ Route.stubs(:fetch_route).returns(route_response)
170
+
171
+ route = Route.find
172
+
173
+ route.should be_multi_choice
174
+ route.refined_addresses1.should have(0).refined_addresses_1
175
+ route.refined_addresses2.should have(2).refined_addresses_2
176
+ route.refined_addresses2[0].address.should == "1210 2ND ave"
177
+ route.refined_addresses2[0].city.should == "newyork"
178
+ route.refined_addresses2[0].county.should == "36061"
179
+ route.refined_addresses2[0].title.should == "1210 2ND ave, Manhattan [UA 64th St and 2nd Ave]"
180
+ route.refined_addresses2[0].url.should == "http://www.hopstop.com/ws/map?qdtck3cough5b1sl"
181
+ route.refined_addresses2[1].address.should == "111TH st and LIBERTY ave"
182
+ route.refined_addresses2[1].city.should == "newyork"
183
+ route.refined_addresses2[1].county.should == "36081"
184
+ route.refined_addresses2[1].title.should == "111TH st and LIBERTY ave, Queens [111 St [A Train]]"
185
+ route.refined_addresses2[1].url.should == "http://www.hopstop.com/ws/map?3863qjw7qn6co52o"
186
+ end
187
+
188
+ it "should offer refined addresses with correctly parsed data for multi choice address1 but not for address2" do
189
+ route_response = XmlResponses.several_choices_for_route(
190
+ :refined_addresses1 => [
191
+ { :address => '1210 2ND ave', :city => 'newyork', :county => '36061',
192
+ :title => '1210 2ND ave, Manhattan [UA 64th St and 2nd Ave]', :url => 'http://www.hopstop.com/ws/map?qdtck3cough5b1sl'},
193
+ { :address => '111TH st and LIBERTY ave', :city => 'newyork', :county => '36081',
194
+ :title => '111TH st and LIBERTY ave, Queens [111 St [A Train]]', :url => 'http://www.hopstop.com/ws/map?3863qjw7qn6co52o'}
195
+ ]
196
+ )
197
+ Route.stubs(:validate_params)
198
+ Route.stubs(:fetch_route).returns(route_response)
199
+
200
+ route = Route.find
201
+
202
+ route.should be_multi_choice
203
+ route.refined_addresses1.should have(2).refined_addresses_1
204
+ route.refined_addresses2.should have(0).refined_addresses_2
205
+ route.refined_addresses1[0].address.should == "1210 2ND ave"
206
+ route.refined_addresses1[0].city.should == "newyork"
207
+ route.refined_addresses1[0].county.should == "36061"
208
+ route.refined_addresses1[0].title.should == "1210 2ND ave, Manhattan [UA 64th St and 2nd Ave]"
209
+ route.refined_addresses1[0].url.should == "http://www.hopstop.com/ws/map?qdtck3cough5b1sl"
210
+ route.refined_addresses1[1].address.should == "111TH st and LIBERTY ave"
211
+ route.refined_addresses1[1].city.should == "newyork"
212
+ route.refined_addresses1[1].county.should == "36081"
213
+ route.refined_addresses1[1].title.should == "111TH st and LIBERTY ave, Queens [111 St [A Train]]"
214
+ route.refined_addresses1[1].url.should == "http://www.hopstop.com/ws/map?3863qjw7qn6co52o"
215
+ end
216
+
217
+ it "should offer refined addresses with correctly parsed data for multi choice address1 and address2" do
218
+ route_response = XmlResponses.several_choices_for_route(
219
+ :refined_addresses1 => [
220
+ { :address => '1210 2ND ave', :city => 'newyork', :county => '36061',
221
+ :title => '1210 2ND ave, Manhattan [UA 64th St and 2nd Ave]', :url => 'http://www.hopstop.com/ws/map?qdtck3cough5b1sl'},
222
+ { :address => '111TH st and LIBERTY ave', :city => 'newyork', :county => '36081',
223
+ :title => '111TH st and LIBERTY ave, Queens [111 St [A Train]]', :url => 'http://www.hopstop.com/ws/map?3863qjw7qn6co52o'}
224
+ ],
225
+ :refined_addresses2 => [
226
+ { :address => '2210 2ND ave', :city => 'newyork2', :county => '26061',
227
+ :title => '2210 2ND ave, Manhattan [UA 64th St and 2nd Ave]', :url => 'http://www.hopstop.com/ws/map?qdtck3cough5b1sl2'},
228
+ { :address => '211TH st and LIBERTY ave', :city => 'newyork2', :county => '26081',
229
+ :title => '211TH st and LIBERTY ave, Queens [111 St [A Train]]', :url => 'http://www.hopstop.com/ws/map?3863qjw7qn6co52o2'}
230
+ ]
231
+ )
232
+ Route.stubs(:validate_params)
233
+ Route.stubs(:fetch_route).returns(route_response)
234
+
235
+ route = Route.find
236
+
237
+ route.should be_multi_choice
238
+ route.refined_addresses1.should have(2).refined_addresses_1
239
+ route.refined_addresses2.should have(2).refined_addresses_2
240
+ route.refined_addresses1[0].address.should == "1210 2ND ave"
241
+ route.refined_addresses1[0].city.should == "newyork"
242
+ route.refined_addresses1[0].county.should == "36061"
243
+ route.refined_addresses1[0].title.should == "1210 2ND ave, Manhattan [UA 64th St and 2nd Ave]"
244
+ route.refined_addresses1[0].url.should == "http://www.hopstop.com/ws/map?qdtck3cough5b1sl"
245
+ route.refined_addresses1[1].address.should == "111TH st and LIBERTY ave"
246
+ route.refined_addresses1[1].city.should == "newyork"
247
+ route.refined_addresses1[1].county.should == "36081"
248
+ route.refined_addresses1[1].title.should == "111TH st and LIBERTY ave, Queens [111 St [A Train]]"
249
+ route.refined_addresses1[1].url.should == "http://www.hopstop.com/ws/map?3863qjw7qn6co52o"
250
+ route.refined_addresses2[0].address.should == "2210 2ND ave"
251
+ route.refined_addresses2[0].city.should == "newyork2"
252
+ route.refined_addresses2[0].county.should == "26061"
253
+ route.refined_addresses2[0].title.should == "2210 2ND ave, Manhattan [UA 64th St and 2nd Ave]"
254
+ route.refined_addresses2[0].url.should == "http://www.hopstop.com/ws/map?qdtck3cough5b1sl2"
255
+ route.refined_addresses2[1].address.should == "211TH st and LIBERTY ave"
256
+ route.refined_addresses2[1].city.should == "newyork2"
257
+ route.refined_addresses2[1].county.should == "26081"
258
+ route.refined_addresses2[1].title.should == "211TH st and LIBERTY ave, Queens [111 St [A Train]]"
259
+ route.refined_addresses2[1].url.should == "http://www.hopstop.com/ws/map?3863qjw7qn6co52o2"
260
+ end
261
+ end
262
+ end
@@ -0,0 +1,6 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/hopstop')
2
+ include LimoresHopstop::Hopstop::Mashup
3
+
4
+ Spec::Runner.configure do |config|
5
+ config.mock_with :mocha
6
+ end
@@ -0,0 +1,204 @@
1
+ class XmlResponses
2
+
3
+ def self.invalid_response(params={})
4
+ result = <<XML
5
+ <HopStopResponse>
6
+ <ResponseStatus>
7
+ <FaultCode>#{params[:fault_code] || 112}</FaultCode>
8
+ <FaultString>#{params[:fault_string] || "Invalid license Key."}</FaultString>
9
+ </ResponseStatus>
10
+ </HopStopResponse>
11
+ XML
12
+ end
13
+
14
+ def self.valid_cities(params={})
15
+ result = <<XML
16
+ <?xml version="1.0"?>
17
+ <StopResponse xmlns="http://www.stop.com/ws/">
18
+ <Cities>
19
+ <item>
20
+ <CellGateway>boston@stop.com</CellGateway>
21
+ <DefaultCounty>boston, ma</DefaultCounty>
22
+ <Id>#{params[:city1] || "boston"}</Id>
23
+ <Name>Boston</Name>
24
+ <State>MA</State>
25
+ <UsePlaces>y</UsePlaces>
26
+ </item>
27
+ <item>
28
+ <CellGateway>nyc@stop.com</CellGateway>
29
+ <DefaultCounty>36061</DefaultCounty>
30
+ <Id>#{params[:city2] || "newyork"}</Id>
31
+ <Name>New York</Name>
32
+ <State>NY</State>
33
+ <UsePlaces>n</UsePlaces>
34
+ </item>
35
+ </Cities>
36
+ <ResponseStatus>
37
+ <ResultCode>#{params[:result_code] || "200"}</ResultCode>
38
+ <ResultString>#{params[:result_string] || "Success."}</ResultString>
39
+ </ResponseStatus>
40
+ </StopResponse>
41
+ XML
42
+ end
43
+
44
+ def self.valid_route(params={})
45
+ params[:map1] ||= {}
46
+ params[:route_node1] ||= {}
47
+ result = <<XML
48
+ <HopStopResponse>
49
+ <Disclaimer>
50
+ These directions are informational only. No representation is made or warranty given as to their content, route usability or expeditiousness. User assumes all risk of use. Hopstop and its suppliers assume no responsibility for any loss or delay resulting from such use.
51
+ </Disclaimer>
52
+ <Maps>
53
+ <item>
54
+ <Height>300</Height>
55
+ <Id>#{params[:map1][:id] || "lesnford7qshyg8a"}</Id>
56
+ <Number>#{params[:map1][:number] || 1}</Number>
57
+ <Title>#{params[:map1][:title] || "From 49 TEMPLE PL to subway station (Total Walking: 0.11 miles/2 mins)"}</Title>
58
+ <URL>#{params[:map1][:url] || "http://www.hopstop.com/ws/map?lesnford7qshyg8a"}</URL>
59
+ <Width>400</Width>
60
+ </item>
61
+ <item>
62
+ <Height>300</Height>
63
+ <Id>nhrl946erk80rp3q</Id>
64
+ <Number>2</Number>
65
+ <Title>From train station to bus stop</Title>
66
+ <URL>http://www.hopstop.com/ws/map?nhrl946erk80rp3q</URL>
67
+ <Width>400</Width>
68
+ </item>
69
+ <item>
70
+ <Height>300</Height>
71
+ <Id>wr5l7k3titew6i2p</Id>
72
+ <Number>3</Number>
73
+ <Title>
74
+ From bus stop to subway station (Total Walking: 0.03 miles/1 min)
75
+ </Title>
76
+ <URL>http://www.hopstop.com/ws/map?wr5l7k3titew6i2p</URL>
77
+ <Width>400</Width>
78
+ </item>
79
+ <item>
80
+ <Height>300</Height>
81
+ <Id>o3ly7w3pqma9adyo</Id>
82
+ <Number>4</Number>
83
+ <Title>
84
+ From subway station to 1210 2ND ave (Total Walking: 0.26 miles/4 mins)
85
+ </Title>
86
+ <URL>http://www.hopstop.com/ws/map?o3ly7w3pqma9adyo</URL>
87
+ <Width>400</Width>
88
+ </item>
89
+ </Maps>
90
+ <ResponseStatus>
91
+ <ResultCode>200</ResultCode>
92
+ <ResultString>Route found.</ResultString>
93
+ </ResponseStatus>
94
+ <RouteInfo>
95
+ <ABDistance>185.891626750759</ABDistance>
96
+ <Address1>49 TEMPLE PL</Address1>
97
+ <Address2>1210 2ND ave</Address2>
98
+ <City>boston</City>
99
+ <City1>boston</City1>
100
+ <City1Name>Boston</City1Name>
101
+ <City2>newyork</City2>
102
+ <City2Name>New York</City2Name>
103
+ <CityName>Boston</CityName>
104
+ <County1>boston, ma</County1>
105
+ <County1Name>Boston, MA</County1Name>
106
+ <County2>36061</County2>
107
+ <County2Name>Manhattan</County2Name>
108
+ <Day>1</Day>
109
+ <EnableDisabledLinks>0</EnableDisabledLinks>
110
+ <Id>gng5ywt38rhxlaia</Id>
111
+ <Language>en</Language>
112
+ <MaxBuses>255</MaxBuses>
113
+ <MaxTrains>255</MaxTrains>
114
+ <MaxWalked>160932790</MaxWalked>
115
+ <MaxWalkingTripShown>3600</MaxWalkingTripShown>
116
+ <Mode>a</Mode>
117
+ <Route>\n #{params[:route_node1][:text] || "Start out going East on Temple Pl towards Washington St"}\t#{params[:route_node1][:time] || 56}\t#{params[:route_node1][:type] || "W"}\t#{params[:route_node1][:icon_url] || "http://www.hopstop.com/i/boston/walk.gif"}\t23\t34\t\t\t\t\tboston\t\t\t\t-71.062113,42.355118,-71.06047,42.35541,1,27120,120,1\n Turn left onto Washington St\t64\tW\t\t\t\t\t\t\t\tboston\t\t\t\t\n Entrance near intersection of Summer St and Washington St\t120\tE\t\t\t\t\t\t\t\tboston\t\t\t\t\n Take the Orange Line from Downtown Crossing station heading to Forest Hills\t300\tS\thttp://www.hopstop.com/i/boston/Orangeline.gif\t43\t43\t\t\t\t\tboston\t\t2968\t\t\n Pass Chinatown\t81\tS\t\t\t\t\t\t\t\tboston\t\t\t\t\n Pass New England Medical Center\t82\tS\t\t\t\t\t\t\t\tboston\t\t\t\t\n Get off at Back Bay\t138\tS\t\t\t\t\t\t\t\tboston\t\t1903\t\t\n Transfer\t0\tT\t\t\t\t\t\t\t\tboston\t\t\t163688186\t\n Take the 8:20 AM Amtrak - Regional Train from Boston - Back Bay (BBY) station heading to Newport News, VA\t2159\tU\thttp://www.hopstop.com/i/boston/Amtrak.gif\t43\t43\t\t\tA\t\tboston\t\t5167504\t\t\n Pass Westwood - Route 128 Station (RTE)\t660\tU\t\t\t\t\t\t\t\tboston\t\t\t\t\n Pass Providence, RI (PVD)\t1500\tU\t\t\t\t\t\t\t\tboston\t\t\t\t\n Pass New London, CT (NLC)\t3180\tU\t\t\t\t\t\t\t\trhodeisland\t\t\t\t\n Pass New Haven (NHV)\t3120\tU\t\t\t\t\t\t\t\tmetronorth\t\t\t\t\n Pass Stamford, CT (STM)\t2700\tU\t\t\t\t\t\t\t\tmetronorth\t\t\t\t\n Get off at New York - Penn Station (NYP)\t2940\tU\t\t\t\t\t\t\t\tmetronorth\t\t3919322\t\t\n Exit near intersection of W 32nd St and 7th Ave\t30\tE\t\t\t\t\t\t\t\tnewyork\t\t\t\t\n Take the M4 Bus from W 32 St and 7 Av station heading to Fort Tryon Park\t300\tC\thttp://www.hopstop.com/i/newyork/M4.gif\t70\t30\thttp://www.hopstop.com/i2/newyork/=&gt;Q32.gif,35,15\t\t\t\tnewyork\t\t36759\t\t\n Get off at W 32 St and Av Of The Americas\t106\tC\t\t\t\t\t\t\t\tnewyork\t\t71440\t\t\n Start out going East on W 32nd St towards Broadway\t34\tW\thttp://www.hopstop.com/i/newyork/walk.gif\t23\t34\t\thttp://www.hopstop.com/pano/img/83924754.jpa,113.07\t\t\tnewyork\t\t\t\t-73.98871,40.74851,-73.98817,40.74828,1,44570,34,3\n Entrance near intersection of W 32nd St and Broadway\t120\tE\t\t\t\t\t\t\t\tnewyork\t\t\t\t\n Take the F train from 34 Street - Herald Sq station heading Uptown / to Jamaica\t300\tS\thttp://www.hopstop.com/i/newyork/F.gif\t43\t43\t\t\t\t\tnewyork\t\t3367255\t\t\n Pass 42 Street - Bryant Park\t105\tS\t\t\t\t\t\t\t\tnewyork\t\t\t\t\n Pass 47-50 Streets - Rockefeller Center\t83\tS\t\t\t\t\t\t\t\tnewyork\t\t\t\t\n Pass 57 Street - 6 Av\t119\tS\t\t\t\t\t\t\t\tnewyork\t\t\t\t\n Get off at Lexington Av - 63rd St\t130\tS\t\t\t\t\t\t\t\tnewyork\t\t864\t\t\n Exit near intersection of E 63rd St and Lexington Ave\t120\tE\t\t\t\t\t\t\t\tnewyork\t\t\t\t\n Start out going East on E 63rd St towards 3rd Ave\t242\tW\thttp://www.hopstop.com/i/newyork/walk.gif\t23\t34\t\thttp://www.hopstop.com/pano/img/77424659.jpa,112.59\t\t\tnewyork\t\t\t\t-73.96636,40.76473,-73.962285,40.763425,1,45789,268,4\n Turn left onto 2nd Ave\t26\tW\t\t\t\t\t\t\t\tnewyork\t\t\t\t\n </Route>
118
+ <SegmentsLen>202.402345303428</SegmentsLen>
119
+ <SimpleWalking>0</SimpleWalking>
120
+ <SimplifiedDirs>0</SimplifiedDirs>
121
+ <Time>27000</Time>
122
+ <TotalTime>18815</TotalTime>
123
+ <TotalTimeVerb>5 hours 14 mins</TotalTimeVerb>
124
+ <TransferPriority>0</TransferPriority>
125
+ <X1>-71.062113</X1>
126
+ <X2>-73.962285</X2>
127
+ <Y1>42.355118</Y1>
128
+ <Y2>40.763425</Y2>
129
+ <Zip1>02111</Zip1>
130
+ <Zip2>10065</Zip2>
131
+ </RouteInfo>
132
+ </HopStopResponse>
133
+ XML
134
+ end
135
+
136
+ def self.several_choices_for_route(params={})
137
+ params[:refined_addresses1] ||= [{ :address => '111TH st and LIBERTY ave', :city => 'newyork', :county => '36081',
138
+ :title => '111TH st and LIBERTY ave, Queens [111 St [A Train]]', :url => 'http://www.hopstop.com/ws/map?3863qjw7qn6co52o'}]
139
+ params[:refined_addresses2] ||= [{ :address => '1210 2ND ave', :city => 'newyork', :county => '36061',
140
+ :title => '1210 2ND ave, Manhattan [UA 64th St and 2nd Ave]', :url => 'http://www.hopstop.com/ws/map?qdtck3cough5b1sl'}]
141
+
142
+ refined_addresses1 = ''
143
+ params[:refined_addresses1].each do |address|
144
+ addr = <<ADDRESS
145
+ <item>
146
+ <Address>#{address[:address]}</Address>
147
+ <AddressId>1</AddressId>
148
+ <City>#{address[:city]}</City>
149
+ <County>#{address[:county]}</County>
150
+ <Height>130</Height>
151
+ <Id>utobk5eyag0yv0z4</Id>
152
+ <Title>#{address[:title]}</Title>
153
+ <URL>#{address[:url]}</URL>
154
+ <Width>150</Width>
155
+ <X>-71.062113</X>
156
+ <Y>42.355118</Y>
157
+ <Zip>02111</Zip>
158
+ </item>
159
+ ADDRESS
160
+ refined_addresses1 += addr
161
+ end
162
+
163
+ refined_addresses2 = ''
164
+ params[:refined_addresses2].each do |address|
165
+ addr = <<ADDRESS
166
+ <item>
167
+ <Address>#{address[:address]}</Address>
168
+ <AddressId>2</AddressId>
169
+ <City>#{address[:city]}</City>
170
+ <County>#{address[:county]}</County>
171
+ <Height>130</Height>
172
+ <Id>utobk5eyag0yv0z4</Id>
173
+ <Title>#{address[:title]}</Title>
174
+ <URL>#{address[:url]}</URL>
175
+ <Width>150</Width>
176
+ <X>-71.062113</X>
177
+ <Y>42.355118</Y>
178
+ <Zip>02111</Zip>
179
+ </item>
180
+ ADDRESS
181
+ refined_addresses2 += addr
182
+ end
183
+
184
+ result = <<XML
185
+ <HopStopResponse>
186
+ <ResponseStatus>
187
+ <ResultCode>201</ResultCode>
188
+ <ResultString>Several choices found.</ResultString>
189
+ </ResponseStatus>
190
+ <RouteInfo>
191
+ <Address1FoundExact>#{ params[:refined_addresses1].size == 1 ? 1 : 0 }</Address1FoundExact>
192
+ <Address1OneLocation>#{ params[:refined_addresses1].size == 1 ? 1 : 0 }</Address1OneLocation>
193
+ <Address2FoundExact>#{ params[:refined_addresses2].size == 1 ? 1 : 0 }</Address2FoundExact>
194
+ <Address2Message>Couldn't find an exact match for [111TH st and LIBERTY ave, ]. Closest matches found are below, please select one.</Address2Message>
195
+ <Address2OneLocation>#{ params[:refined_addresses2].size == 1 ? 1 : 0 }</Address2OneLocation>
196
+ </RouteInfo>
197
+ <Thumbnails>
198
+ #{refined_addresses1}
199
+ #{refined_addresses2}
200
+ </Thumbnails>
201
+ </HopStopResponse>
202
+ XML
203
+ end
204
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: limores_hopstop
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Milan Burmaja
@@ -22,9 +22,14 @@ extensions: []
22
22
  extra_rdoc_files:
23
23
  - README.rdoc
24
24
  files:
25
+ - lib/app_id.rb
26
+ - lib/hopstop.rb
27
+ - spec/hopstop_spec.rb
28
+ - spec/spec_helper.rb
29
+ - spec/xml_responses.rb
25
30
  - README.rdoc
26
31
  has_rdoc: true
27
- homepage: http://gemcutter.org/technicalpickles/the-perfect-gem
32
+ homepage: http://gemcutter.org/gems/limores_hopstop
28
33
  licenses: []
29
34
 
30
35
  post_install_message:
@@ -32,6 +37,7 @@ rdoc_options:
32
37
  - --charset=UTF-8
33
38
  require_paths:
34
39
  - lib
40
+ - spec
35
41
  required_ruby_version: !ruby/object:Gem::Requirement
36
42
  requirements:
37
43
  - - ">="