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 +5 -0
- data/lib/hopstop.rb +206 -0
- data/spec/hopstop_spec.rb +262 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/xml_responses.rb +204 -0
- metadata +8 -2
data/lib/app_id.rb
ADDED
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
|
data/spec/spec_helper.rb
ADDED
@@ -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/=>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.
|
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/
|
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
|
- - ">="
|