octranspo_fetch 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/lib/octranspo_fetch.rb +84 -39
- metadata +2 -2
data/lib/octranspo_fetch.rb
CHANGED
|
@@ -15,13 +15,15 @@ class OCTranspo
|
|
|
15
15
|
def initialize(options)
|
|
16
16
|
@app_id = options[:application_id]
|
|
17
17
|
@app_key = options[:application_key]
|
|
18
|
-
@
|
|
18
|
+
@next_trips_cache = LruRedux::Cache.new(NEXT_TRIPS_CACHE_SIZE)
|
|
19
19
|
@route_summary_cache = LruRedux::Cache.new(ROUTE_CACHE_SIZE)
|
|
20
20
|
@api_calls = 0
|
|
21
|
+
@cache_hits = 0
|
|
22
|
+
@cache_misses = 0
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
def clear_cache()
|
|
24
|
-
@
|
|
26
|
+
@next_trips_cache.clear()
|
|
25
27
|
@route_summary_cache.clear()
|
|
26
28
|
end
|
|
27
29
|
|
|
@@ -30,6 +32,10 @@ class OCTranspo
|
|
|
30
32
|
return @api_calls
|
|
31
33
|
end
|
|
32
34
|
|
|
35
|
+
def cache_stats()
|
|
36
|
+
return {hits: @cache_hits, misses: @cache_misses}
|
|
37
|
+
end
|
|
38
|
+
|
|
33
39
|
# Get a list of routes for a specific stop.
|
|
34
40
|
#
|
|
35
41
|
# Returns a {stop, stop_description, routes: [{route, direction_id, direction, heading}]} object.
|
|
@@ -37,10 +43,19 @@ class OCTranspo
|
|
|
37
43
|
#
|
|
38
44
|
# Arguments:
|
|
39
45
|
# stop: (String) The stop number.
|
|
46
|
+
# options[:max_cache_time]: (Integer) Maximum cache age, in seconds. If cached data is
|
|
47
|
+
# available and is newer than this, then the cached value will be returned. Defaults to
|
|
48
|
+
# one day.
|
|
40
49
|
#
|
|
41
|
-
def get_route_summary_for_stop(stop)
|
|
50
|
+
def get_route_summary_for_stop(stop, options={})
|
|
51
|
+
max_cache_time = (options[:max_cache_time] or 60*60*24)
|
|
42
52
|
cached_result = @route_summary_cache[stop]
|
|
43
|
-
if !cached_result.nil?
|
|
53
|
+
if !cached_result.nil? and ((cached_result[:time] + max_cache_time) > Time.now.to_i)
|
|
54
|
+
@cache_hits += 1
|
|
55
|
+
return cached_result[:route_summary]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
@cache_misses += 1
|
|
44
59
|
|
|
45
60
|
xresult = fetch "GetRouteSummaryForStop", "stopNo=#{stop}"
|
|
46
61
|
|
|
@@ -63,7 +78,10 @@ class OCTranspo
|
|
|
63
78
|
raise "No routes found"
|
|
64
79
|
end
|
|
65
80
|
|
|
66
|
-
@route_summary_cache[stop] =
|
|
81
|
+
@route_summary_cache[stop] = {
|
|
82
|
+
route_summary: result,
|
|
83
|
+
time: Time.now.to_i
|
|
84
|
+
}
|
|
67
85
|
|
|
68
86
|
return result
|
|
69
87
|
end
|
|
@@ -74,16 +92,33 @@ class OCTranspo
|
|
|
74
92
|
# Arguments:
|
|
75
93
|
# stop: (String) The stop number.
|
|
76
94
|
# route_no: (String) The route number.
|
|
95
|
+
# options[:max_cache_time]: (Integer) Maximum cache age, in seconds. If cached data is
|
|
96
|
+
# available and is newer than this, then the cached value will be returned. Defaults
|
|
97
|
+
# to five minutes.
|
|
77
98
|
#
|
|
78
|
-
def get_next_trips_for_stop(stop, route_no)
|
|
99
|
+
def get_next_trips_for_stop(stop, route_no, options={})
|
|
100
|
+
max_cache_time = (options[:max_cache_time] or 60*5)
|
|
101
|
+
|
|
102
|
+
# Return result from cache, if available
|
|
103
|
+
cache_key = "#{stop}-#{route_no}"
|
|
104
|
+
cached_result = @next_trips_cache[cache_key]
|
|
105
|
+
if !cached_result.nil? and ((cached_result[:time] + max_cache_time) > Time.now.to_i)
|
|
106
|
+
@cache_hits += 1
|
|
107
|
+
return adjust_cached_trip_times(cached_result[:next_trips])
|
|
108
|
+
end
|
|
109
|
+
@cache_misses += 1
|
|
110
|
+
|
|
79
111
|
xresult = fetch "GetNextTripsForStop", "stopNo=#{stop}&routeNo=#{route_no}"
|
|
80
112
|
|
|
81
113
|
result = {
|
|
82
114
|
stop: get_value(xresult, "t:StopNo"),
|
|
83
115
|
stop_description: get_value(xresult, "t:StopLabel"),
|
|
116
|
+
time: Time.now,
|
|
84
117
|
routes: []
|
|
85
118
|
}
|
|
86
119
|
|
|
120
|
+
found_data = false
|
|
121
|
+
|
|
87
122
|
xresult.xpath('t:Route/t:RouteDirection', OCT_NS).each do |route|
|
|
88
123
|
get_error(route, "Error for route: #{route_no}")
|
|
89
124
|
|
|
@@ -109,41 +144,27 @@ class OCTranspo
|
|
|
109
144
|
})
|
|
110
145
|
end
|
|
111
146
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
#
|
|
115
|
-
|
|
116
|
-
if !trips.nil?
|
|
117
|
-
time_delta = Time.now.to_i - trips[:time]
|
|
118
|
-
route_obj[:request_processing_time] += time_delta
|
|
119
|
-
route_obj[:trips] = deep_copy(trips[:trips])
|
|
120
|
-
route_obj[:cached] = true
|
|
121
|
-
route_obj[:trips].each do |trip|
|
|
122
|
-
trip[:adjusted_schedule_time] -= (time_delta.to_f / 60).round
|
|
123
|
-
if trip[:adjustment_age] > 0
|
|
124
|
-
trip[:adjustment_age] += time_delta.to_f / 60
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
# Filter out results with negative arrival times, since they've probably
|
|
129
|
-
# already gone by.
|
|
130
|
-
route_obj[:trips].select! { |trip| trip[:adjusted_schedule_time] >= 0 }
|
|
131
|
-
|
|
132
|
-
else
|
|
133
|
-
# No data in the cache... Hrm...
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
else
|
|
137
|
-
# Cache the trips for later
|
|
138
|
-
@trips_cache[cache_key] = {
|
|
139
|
-
time: Time.now.to_i,
|
|
140
|
-
trips: route_obj[:trips]
|
|
141
|
-
}
|
|
147
|
+
if route_obj[:trips].length != 0
|
|
148
|
+
# Assume that if any trips are filled in, then all the trips will be filled in?
|
|
149
|
+
# Is this a safe assumption?
|
|
150
|
+
found_data = true
|
|
142
151
|
end
|
|
143
152
|
|
|
144
153
|
result[:routes].push route_obj
|
|
145
154
|
end
|
|
146
155
|
|
|
156
|
+
# Sometimes OC Transpo doesn't return any data for a route, even though it should. When
|
|
157
|
+
# this happens, if we have cached data, we use that, even if it's slightly stale.
|
|
158
|
+
if !found_data and !cached_result.nil?
|
|
159
|
+
# Use the cached data, even if it's stale
|
|
160
|
+
result = adjust_cached_trip_times(cached_result[:next_trips])
|
|
161
|
+
else
|
|
162
|
+
@next_trips_cache[cache_key] = {
|
|
163
|
+
next_trips: result,
|
|
164
|
+
time: Time.now.to_i
|
|
165
|
+
}
|
|
166
|
+
end
|
|
167
|
+
|
|
147
168
|
|
|
148
169
|
return result
|
|
149
170
|
end
|
|
@@ -199,14 +220,13 @@ class OCTranspo
|
|
|
199
220
|
|
|
200
221
|
BASE_URL = "https://api.octranspo1.com/v1.1"
|
|
201
222
|
OCT_NS = {'oct' => 'http://octranspo.com', 't' => 'http://tempuri.org/'}
|
|
202
|
-
|
|
223
|
+
NEXT_TRIPS_CACHE_SIZE = 100
|
|
203
224
|
ROUTE_CACHE_SIZE = 100
|
|
204
225
|
|
|
205
226
|
# Fetch and parse some data from the OC-Transpo API. Returns a nokogiri object for
|
|
206
227
|
# the Result within the XML document.
|
|
207
228
|
def fetch(resource, params)
|
|
208
229
|
@api_calls = (@api_calls + 1)
|
|
209
|
-
|
|
210
230
|
response = RestClient.post("#{BASE_URL}/#{resource}",
|
|
211
231
|
"appID=#{@app_id}&apiKey=#{@app_key}&#{params}")
|
|
212
232
|
|
|
@@ -259,5 +279,30 @@ class OCTranspo
|
|
|
259
279
|
def deep_copy(o)
|
|
260
280
|
Marshal.load(Marshal.dump(o))
|
|
261
281
|
end
|
|
262
|
-
end
|
|
263
282
|
|
|
283
|
+
# When returning cached trips, we need to adjust the `:adjustment_age` and
|
|
284
|
+
# `:adjusted_schedule_time` of each entry to reflect how long the object has been
|
|
285
|
+
# sitting in the cache.
|
|
286
|
+
def adjust_cached_trip_times(cached_routes)
|
|
287
|
+
|
|
288
|
+
cached_routes = deep_copy cached_routes
|
|
289
|
+
cached_routes[:cached] = true
|
|
290
|
+
|
|
291
|
+
time_delta = Time.now.to_i - cached_routes[:time].to_i
|
|
292
|
+
cached_routes[:routes].each do |route_obj|
|
|
293
|
+
route_obj[:trips].each do |trip|
|
|
294
|
+
trip[:adjusted_schedule_time] -= (time_delta.to_f / 60).round
|
|
295
|
+
if trip[:adjustment_age] > 0
|
|
296
|
+
trip[:adjustment_age] += time_delta.to_f / 60
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# Filter out results with negative arrival times, since they've probably
|
|
301
|
+
# already gone by.
|
|
302
|
+
route_obj[:trips].select! { |trip| trip[:adjusted_schedule_time] >= 0 }
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
return cached_routes
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: octranspo_fetch
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.3
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2013-09-
|
|
12
|
+
date: 2013-09-23 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: nokogiri
|