lothianbusestimetable 0.1.0
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.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/lib/lothianbusestimetable.rb +223 -0
- data.tar.gz.sig +0 -0
- metadata +67 -0
- metadata.gz.sig +2 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 89109e7c243f925900258b5abfaf15ccc4171fef
|
4
|
+
data.tar.gz: 8036b687f860a180f3cd8a238f5c4c1e7e64b2bb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2551f7e1894eb925bc324935298c91e89849e95a64e7b83570d3e5aca527190a06d7267070f98fad437b4d0908e2386dfe90afcd57bbc0fa4c06ccf435fd6dc8
|
7
|
+
data.tar.gz: ecabce83a5273642bba82590710e8b3b21c0a091676e0a42f935a5c7979fe60ba167a318d3698f4256900a00e94468fde0373e474f0206acb479c501fdaa45df
|
checksums.yaml.gz.sig
ADDED
Binary file
|
@@ -0,0 +1,223 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# file: lothianbusestimetable.rb
|
4
|
+
|
5
|
+
require 'time'
|
6
|
+
require 'nokorexi'
|
7
|
+
|
8
|
+
=begin
|
9
|
+
|
10
|
+
# Example usage:
|
11
|
+
|
12
|
+
lbt = LothianBusesTimetable.new
|
13
|
+
lbt.fetch_timetable '44'
|
14
|
+
lbt.timetable.keys #=> [:service, :weekday, :saturday, :sunday]
|
15
|
+
lbt.timetable[:weekday][:inbound]
|
16
|
+
|
17
|
+
# return the bus times for Juniper Green heading towards Balerno
|
18
|
+
lbt.timetable[:weekday][:outbound]["Juniper Green Post Office"]
|
19
|
+
|
20
|
+
=end
|
21
|
+
|
22
|
+
|
23
|
+
class LothianBusesTimetable
|
24
|
+
|
25
|
+
attr_reader :timetable
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
super()
|
29
|
+
@base_url = 'https://lothianbuses.co.uk/timetables-and-maps/timetables/'
|
30
|
+
end
|
31
|
+
|
32
|
+
def fetch_timetable(service_number)
|
33
|
+
|
34
|
+
url = @base_url + service_number
|
35
|
+
|
36
|
+
doc = Nokorexi.new(url).to_doc
|
37
|
+
|
38
|
+
table = doc.root.element('//table')
|
39
|
+
|
40
|
+
prev_col = ''
|
41
|
+
a0 = []
|
42
|
+
|
43
|
+
# get the destinations
|
44
|
+
# inbound and outbound
|
45
|
+
table.xpath('tr').each do |tr|
|
46
|
+
|
47
|
+
# get the name
|
48
|
+
a = tr.xpath('td//text()').map(&:to_s)
|
49
|
+
|
50
|
+
col1 = a.shift.strip
|
51
|
+
|
52
|
+
if col1 =~ /Service (\w?\d+)/ then
|
53
|
+
|
54
|
+
a0 << {service: $1}
|
55
|
+
|
56
|
+
elsif col1.empty? or col1.length <= 1
|
57
|
+
|
58
|
+
if prev_col.empty? or prev_col.length <= 1 and a0.last.any? then
|
59
|
+
|
60
|
+
a0 << {}
|
61
|
+
|
62
|
+
else
|
63
|
+
|
64
|
+
prev_col = ''
|
65
|
+
end
|
66
|
+
|
67
|
+
elsif prev_col =~ /Service \w?\d+/
|
68
|
+
|
69
|
+
a0.last.merge!(timetable: col1)
|
70
|
+
|
71
|
+
else
|
72
|
+
|
73
|
+
if a.any? then
|
74
|
+
|
75
|
+
h = a0.last
|
76
|
+
|
77
|
+
if h.has_key? col1 then
|
78
|
+
h[col1].concat a
|
79
|
+
else
|
80
|
+
h[col1] = a
|
81
|
+
end
|
82
|
+
|
83
|
+
else
|
84
|
+
a0.pop if a0.last.empty?
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
prev_col = col1
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
master = {
|
94
|
+
service: '',
|
95
|
+
weekday: {desc: '', inbound: {}, outbound: {}},
|
96
|
+
saturday: {desc: '', inbound: {}, outbound: {}},
|
97
|
+
sunday: {desc: '', inbound: {}, outbound: {}}
|
98
|
+
}
|
99
|
+
|
100
|
+
h = a0.shift
|
101
|
+
master[:service] = h[:service]
|
102
|
+
master[:weekday][:desc] = h[:timetable]
|
103
|
+
|
104
|
+
h = a0.shift
|
105
|
+
master[:weekday][:inbound] = h
|
106
|
+
h = a0.shift
|
107
|
+
master[:weekday][:outbound] = h
|
108
|
+
|
109
|
+
h = a0.shift
|
110
|
+
h = a0.shift until h.any?
|
111
|
+
master[:saturday][:desc] = h[:timetable]
|
112
|
+
h = a0.shift
|
113
|
+
master[:saturday][:inbound] = h
|
114
|
+
h = a0.shift
|
115
|
+
master[:saturday][:outbound] = h
|
116
|
+
|
117
|
+
h = a0.shift
|
118
|
+
h = a0.shift until h.any?
|
119
|
+
master[:sunday][:desc] = h[:timetable]
|
120
|
+
h = a0.shift
|
121
|
+
master[:sunday][:inbound] = h
|
122
|
+
h = a0.shift
|
123
|
+
master[:sunday][:outbound] = h
|
124
|
+
|
125
|
+
# note: the special character looks like a space
|
126
|
+
# but is in fact " ".ord #=> 160
|
127
|
+
|
128
|
+
master.to_a[1..-1].each do |key, timetable|
|
129
|
+
|
130
|
+
timetable.to_a[1..-1].each do |direction, printed_rows|
|
131
|
+
|
132
|
+
# find the interval gaps
|
133
|
+
|
134
|
+
a = printed_rows.to_a
|
135
|
+
index = a.index a.detect {|x| x.last.grep(/^ $/).any? }
|
136
|
+
a2 = a[index].last
|
137
|
+
|
138
|
+
gaps = a2.map.with_index.select {|x,i| x == " "}.map(&:last)
|
139
|
+
|
140
|
+
gaps.delete_at -1 if gaps.last >= a2.length - 1
|
141
|
+
|
142
|
+
# sanitise the times (where short hand times are
|
143
|
+
# given i.e. minutes only)
|
144
|
+
|
145
|
+
printed_rows.each do |name, row|
|
146
|
+
|
147
|
+
prev_time = nil
|
148
|
+
printed_rows[name] = row.map.with_index do |col,i|
|
149
|
+
|
150
|
+
if gaps.include? i then
|
151
|
+
col
|
152
|
+
else
|
153
|
+
case col
|
154
|
+
when /^\d{4}$/
|
155
|
+
# record the time
|
156
|
+
prev_time = Time.strptime(col, "%H%M")
|
157
|
+
col
|
158
|
+
when /^\d{2}$/
|
159
|
+
|
160
|
+
# substitute with a time
|
161
|
+
val = "%02d%02d" % [prev_time.hour, col.to_i]
|
162
|
+
|
163
|
+
#if col is less than minutes, increment the hour
|
164
|
+
t = Time.strptime(val, "%H%M")
|
165
|
+
t = t + (60 * 60) if prev_time.min > t.min
|
166
|
+
prev_time = t
|
167
|
+
t.strftime("%H%M")
|
168
|
+
else
|
169
|
+
col
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
# fill in the gaps
|
177
|
+
|
178
|
+
periods = gaps.map {|i| a.map {|k,v| v[i].to_s.gsub(/\W/,'')}
|
179
|
+
.compact.join(' ').strip }
|
180
|
+
|
181
|
+
gap_times = gaps.zip(periods)
|
182
|
+
|
183
|
+
|
184
|
+
intervaltimes = gap_times.map do |i, desc|
|
185
|
+
|
186
|
+
interval = desc[/then every (\d+) mins until/,1].to_i
|
187
|
+
|
188
|
+
new_rows = printed_rows.map do |k,v|
|
189
|
+
|
190
|
+
times = []
|
191
|
+
next unless v[i-1] && v[i-1] =~ /^\d{4}$/
|
192
|
+
|
193
|
+
t = Time.strptime(v[i-1], "%H%M") #if v[i-1] =~ /^\d{4}$/
|
194
|
+
|
195
|
+
while t + (60 * interval) < Time.strptime(v[i+1], "%H%M") do
|
196
|
+
t = t + (60 * interval)
|
197
|
+
times << t.strftime("%H%M")
|
198
|
+
end
|
199
|
+
|
200
|
+
[k,times]
|
201
|
+
end.compact
|
202
|
+
|
203
|
+
[i, new_rows]
|
204
|
+
end
|
205
|
+
|
206
|
+
intervaltimes.reverse.each do |i, rows|
|
207
|
+
|
208
|
+
rows.each do |name, xtimes|
|
209
|
+
|
210
|
+
printed_rows[name].delete_at i
|
211
|
+
printed_rows[name].insert i, *xtimes
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
@timetable = master
|
220
|
+
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
data.tar.gz.sig
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lothianbusestimetable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Robertson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain:
|
11
|
+
- |
|
12
|
+
-----BEGIN CERTIFICATE-----
|
13
|
+
MIIDljCCAn6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBIMRIwEAYDVQQDDAlnZW1t
|
14
|
+
YXN0ZXIxHjAcBgoJkiaJk/IsZAEZFg5qYW1lc3JvYmVydHNvbjESMBAGCgmSJomT
|
15
|
+
8ixkARkWAmV1MB4XDTE3MDgyMjEyMzg1OFoXDTE4MDgyMjEyMzg1OFowSDESMBAG
|
16
|
+
A1UEAwwJZ2VtbWFzdGVyMR4wHAYKCZImiZPyLGQBGRYOamFtZXNyb2JlcnRzb24x
|
17
|
+
EjAQBgoJkiaJk/IsZAEZFgJldTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
|
18
|
+
ggEBANn4wnsqPgnkuEmMe25DFlvzQD22UYMiPEFTfNC6WWoD/XGT/YV9hgPQ0Vxe
|
19
|
+
JdP67UjkqAT7dGceN7dBie6cjDx0koddtOOdioYQQ4i/ugCeyQPuqHbsSbDr2Dpu
|
20
|
+
wEQFUWAY3QXSuQojLwNIF9N1jwa6eTZji77VyA/+t5HO485EB4AQjBAgS1j09XRQ
|
21
|
+
8mInZcpsDFXy+SRmKy/k5UgoO+UPl1l7frGfF7ngad6Y66hFhv/qBg4bSbyHytfL
|
22
|
+
G1BSTbsXYFw+TemSHNOZ6omP5Gi6PIMZHbc8nOgPSVJ3miMTI3HSIvArrnmsF3Dg
|
23
|
+
FtLWSyZhm09xfPQp6O+eRkRugHUCAwEAAaOBijCBhzAJBgNVHRMEAjAAMAsGA1Ud
|
24
|
+
DwQEAwIEsDAdBgNVHQ4EFgQUWWYnDtPOZj84D4zYKoL5ka1Xg/gwJgYDVR0RBB8w
|
25
|
+
HYEbZ2VtbWFzdGVyQGphbWVzcm9iZXJ0c29uLmV1MCYGA1UdEgQfMB2BG2dlbW1h
|
26
|
+
c3RlckBqYW1lc3JvYmVydHNvbi5ldTANBgkqhkiG9w0BAQUFAAOCAQEAb8XQ6GME
|
27
|
+
ZhiRy44IrSVoTn9x+0/vXlSiR0A5pp/6l/tIhnCLRj033XA6WEYLGhhh8pYP8rbW
|
28
|
+
YPThZ/7jz2yzazCzfcvHi8dTd5RHtHZC2P5doj0yqjG+zBtq4nlmfZFSDD+m5+wJ
|
29
|
+
FNnNN1AZxxllHLxtBFvBhHMpccjU1BP/Rnmw9x9+l25eCn+GbvqvV1jurtKGWcml
|
30
|
+
DF7dZobpSzQTyh2BO/HWiJSdKHB6sB5oKWvpCDW4eltRAg/QLku5bkCK25zPVg5f
|
31
|
+
K7yWGJq+eGl34xrLaucvTbO8Ua3rHayCkBzgfx5LVcch22Axj8quw+YGsPnhuosr
|
32
|
+
BHdCmx9eUF/TKg==
|
33
|
+
-----END CERTIFICATE-----
|
34
|
+
date: 2017-08-22 00:00:00.000000000 Z
|
35
|
+
dependencies: []
|
36
|
+
description:
|
37
|
+
email: james@jamesrobertson.eu
|
38
|
+
executables: []
|
39
|
+
extensions: []
|
40
|
+
extra_rdoc_files: []
|
41
|
+
files:
|
42
|
+
- lib/lothianbusestimetable.rb
|
43
|
+
homepage: https://github.com/jrobertson/lothianbusestimetable
|
44
|
+
licenses:
|
45
|
+
- MIT
|
46
|
+
metadata: {}
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 2.6.8
|
64
|
+
signing_key:
|
65
|
+
specification_version: 4
|
66
|
+
summary: lothianbusestimetable
|
67
|
+
test_files: []
|
metadata.gz.sig
ADDED