matsadler-tube 0.1.1 → 0.1.2
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/status.rb +16 -76
- data/lib/status_parser.rb +130 -0
- data/lib/tube.rb +2 -0
- metadata +5 -3
data/lib/status.rb
CHANGED
@@ -76,44 +76,31 @@ module Tube # :nodoc:
|
|
76
76
|
def reload
|
77
77
|
doc = Hpricot( open( @url ) )
|
78
78
|
|
79
|
-
|
80
|
-
time_text = time_el.inner_text.match( /(\d?\d:\d\d(a|p)m)/ )[0]
|
81
|
-
time_zone = if is_bst? then "+0100" else "+0000" end
|
82
|
-
@updated = Time.parse( "#{time_text} #{time_zone}" )
|
79
|
+
results = Tube::StatusParser.parse( doc )
|
83
80
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
else
|
93
|
-
status_text = status.inner_text.strip
|
94
|
-
end
|
95
|
-
problem = status.attributes["class"] == "problem"
|
81
|
+
@updated = results[:updated]
|
82
|
+
|
83
|
+
lines = results[:lines].map do |line|
|
84
|
+
id = line[:html_class]
|
85
|
+
name = line[:name]
|
86
|
+
status_text = line[:status][:headline]
|
87
|
+
problem = line[:status][:problem]
|
88
|
+
message = line[:status][:message]
|
96
89
|
|
97
90
|
Line.new( id, status_text, problem, message, name )
|
98
91
|
end
|
99
92
|
@lines = LineGroup.new( lines )
|
100
93
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
while el = el.next_sibling
|
105
|
-
if el.to_html =~ /^<dd/ && name_el = el.at( "h3" )
|
106
|
-
name = name_el.inner_text.strip
|
107
|
-
message = format_messages( el.search( "div.message p" ) )
|
108
|
-
station = Station.new( name, message )
|
109
|
-
station_group.push( station )
|
110
|
-
elsif el.to_html =~ /^<dt/
|
111
|
-
break
|
112
|
-
end
|
94
|
+
station_groups = results[:station_groups].map do |station_group|
|
95
|
+
stations = station_group[:stations].map do |station|
|
96
|
+
Station.new( station[:name], station[:message] )
|
113
97
|
end
|
114
|
-
|
98
|
+
|
99
|
+
StationGroup.new( station_group[:name], stations )
|
115
100
|
end
|
116
101
|
|
102
|
+
@station_groups = StationGroupGroup.new( station_groups )
|
103
|
+
|
117
104
|
self
|
118
105
|
end
|
119
106
|
|
@@ -266,52 +253,5 @@ module Tube # :nodoc:
|
|
266
253
|
if as_string then doc.to_s else doc end
|
267
254
|
end
|
268
255
|
|
269
|
-
private
|
270
|
-
|
271
|
-
# :call-seq: format_messages(messages) -> string
|
272
|
-
#
|
273
|
-
# Takes an array of elements, strips those elements of elements they contain
|
274
|
-
# and returns only the text within the root elements.
|
275
|
-
# <p>Suspended. Rail replacement bus services operate.</p>
|
276
|
-
# <p>Service A: ...</p>
|
277
|
-
# <p><a href="/transform">See how we are transforming the Tube</a></p>
|
278
|
-
# becomes
|
279
|
-
# Suspended. Rail replacement bus services operate.
|
280
|
-
# Service A: ...
|
281
|
-
#
|
282
|
-
def format_messages( messages )
|
283
|
-
text_messages = messages.map do |message|
|
284
|
-
if message.children
|
285
|
-
message.children.select {|child| child.text?}.join( " " )
|
286
|
-
end
|
287
|
-
end.compact
|
288
|
-
text_messages.reject! {|m| m.empty?}
|
289
|
-
text_messages.map {|m| m.gsub( /\s+/, " " ).strip}.join( "\n" )
|
290
|
-
end
|
291
|
-
|
292
|
-
# :call-seq: is_bst? -> bool
|
293
|
-
#
|
294
|
-
# Is British Summer Time currently in effect.
|
295
|
-
#
|
296
|
-
def is_bst?
|
297
|
-
bst_start = last_sunday_of_preceding_month( "april" )
|
298
|
-
bst_end = last_sunday_of_preceding_month( "november" )
|
299
|
-
|
300
|
-
one_hour = 3600
|
301
|
-
bst_start = Time.gm(bst_start.year, bst_start.month) + one_hour
|
302
|
-
bst_end = Time.gm(bst_end.year, bst_end.month) + one_hour
|
303
|
-
|
304
|
-
(bst_start..bst_end).include?(Time.now.getgm)
|
305
|
-
end
|
306
|
-
|
307
|
-
# :call-seq: last_sunday_of_preceding_month(month_name) -> date
|
308
|
-
#
|
309
|
-
def last_sunday_of_preceding_month( month_name )
|
310
|
-
start_of_preceding_month = Date.parse( month_name )
|
311
|
-
week_day = start_of_preceding_month.wday
|
312
|
-
distance_from_sunday = if week_day == 0 then 7 else week_day end
|
313
|
-
start_of_preceding_month - distance_from_sunday
|
314
|
-
end
|
315
|
-
|
316
256
|
end
|
317
257
|
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module Tube # :nodoc:
|
2
|
+
module StatusParser
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def parse( hpricot_doc )
|
6
|
+
service_board = hpricot_doc.at( "#service-board" )
|
7
|
+
|
8
|
+
updated_element = service_board.previous_sibling.children.first
|
9
|
+
updated = parse_updated( updated_element )
|
10
|
+
|
11
|
+
lines = service_board.search( "dl#lines dt" ).map do |line_element|
|
12
|
+
parse_line( line_element )
|
13
|
+
end
|
14
|
+
|
15
|
+
station_group_elements = service_board.search( "dl#stations dt" )
|
16
|
+
station_groups = station_group_elements.map do |station_group_element|
|
17
|
+
parse_station_group( station_group_element )
|
18
|
+
end
|
19
|
+
|
20
|
+
{:updated => updated, :lines => lines, :station_groups => station_groups}
|
21
|
+
end
|
22
|
+
|
23
|
+
def parse_updated( updated_element )
|
24
|
+
time_text = updated_element.inner_text.match( /(\d?\d:\d\d(a|p)m)/ )[0]
|
25
|
+
time_zone = if is_bst? then "+0100" else "+0000" end
|
26
|
+
|
27
|
+
Time.parse( "#{time_text} #{time_zone}" )
|
28
|
+
end
|
29
|
+
|
30
|
+
def parse_line( line_element )
|
31
|
+
name = line_element.inner_text.strip
|
32
|
+
html_class = line_element.attributes["class"]
|
33
|
+
status = parse_status( line_element.next_sibling )
|
34
|
+
|
35
|
+
{:name => name, :html_class => html_class, :status => status}
|
36
|
+
end
|
37
|
+
|
38
|
+
def parse_status( status_element )
|
39
|
+
header = status_element.at( "h3" )
|
40
|
+
|
41
|
+
if header
|
42
|
+
headline = header.inner_text.strip
|
43
|
+
message = parse_status_message( status_element.search( "div.message p" ) )
|
44
|
+
else
|
45
|
+
headline = status_element.inner_text.strip
|
46
|
+
end
|
47
|
+
problem = status_element.attributes["class"] == "problem"
|
48
|
+
|
49
|
+
{:headline => headline, :problem => problem, :message => message}
|
50
|
+
end
|
51
|
+
|
52
|
+
def parse_station_group( station_group_element )
|
53
|
+
name = station_group_element.inner_text.strip
|
54
|
+
stations = []
|
55
|
+
|
56
|
+
station_element = station_group_element
|
57
|
+
while station_element = station_element.next_sibling
|
58
|
+
if station_element.to_html =~ /^<dd/
|
59
|
+
stations.push( parse_station( station_element ) )
|
60
|
+
elsif station_element.to_html =~ /^<dt/
|
61
|
+
break
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
{:name => name, :stations => stations}
|
66
|
+
end
|
67
|
+
|
68
|
+
def parse_station( station_element )
|
69
|
+
name = station_element.at( "h3" ).inner_text.strip
|
70
|
+
message = parse_status_message( station_element.search( "div.message p" ) )
|
71
|
+
|
72
|
+
{:name => name, :message => message}
|
73
|
+
end
|
74
|
+
|
75
|
+
def parse_status_message( messages )
|
76
|
+
text_messages = messages.map do |message|
|
77
|
+
if message.children
|
78
|
+
message.children.select {|child| child.text?}.join( " " )
|
79
|
+
end
|
80
|
+
end.compact
|
81
|
+
text_messages.reject! {|m| m.empty?}
|
82
|
+
|
83
|
+
text_messages.map {|m| m.gsub( /\s+/, " " ).strip}.join( "\n" )
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
# :call-seq: is_bst? -> bool
|
89
|
+
#
|
90
|
+
# Is British Summer Time currently in effect.
|
91
|
+
#
|
92
|
+
def is_bst?
|
93
|
+
bst_start = last_sunday_of_month( "march" )
|
94
|
+
bst_end = last_sunday_of_month( "october" )
|
95
|
+
|
96
|
+
one_hour = 3600
|
97
|
+
bst_start = Time.gm( bst_start.year, bst_start.month ) + one_hour
|
98
|
+
bst_end = Time.gm( bst_end.year, bst_end.month ) + one_hour
|
99
|
+
|
100
|
+
(bst_start..bst_end).include?( Time.now.getgm )
|
101
|
+
end
|
102
|
+
|
103
|
+
# :call-seq: last_sunday_of_month(month_name) -> date
|
104
|
+
#
|
105
|
+
def last_sunday_of_month( month )
|
106
|
+
start_of_next_month = Date.parse( next_month_name( month ) )
|
107
|
+
|
108
|
+
week_day = start_of_next_month.wday
|
109
|
+
|
110
|
+
distance_from_sunday = if week_day == 0 then 7 else week_day end
|
111
|
+
start_of_next_month - distance_from_sunday
|
112
|
+
end
|
113
|
+
|
114
|
+
# :call-seq: next_month_name(month_name) -> string
|
115
|
+
#
|
116
|
+
def next_month_name( month )
|
117
|
+
index = Date::MONTHNAMES.index( month.capitalize )
|
118
|
+
index ||= ABBR_MONTHNAMES.index( month.capitalize )
|
119
|
+
|
120
|
+
index += 1
|
121
|
+
|
122
|
+
if index >= 12
|
123
|
+
index = 1
|
124
|
+
end
|
125
|
+
|
126
|
+
Date::MONTHNAMES[index]
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
data/lib/tube.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: matsadler-tube
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mat Sadler
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-08-01 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -42,6 +42,7 @@ extra_rdoc_files: []
|
|
42
42
|
|
43
43
|
files:
|
44
44
|
- lib/line.rb
|
45
|
+
- lib/status_parser.rb
|
45
46
|
- lib/line_group.rb
|
46
47
|
- lib/station.rb
|
47
48
|
- lib/station_group.rb
|
@@ -50,6 +51,7 @@ files:
|
|
50
51
|
- lib/tube.rb
|
51
52
|
has_rdoc: true
|
52
53
|
homepage: http://github.com/matsadler/tube
|
54
|
+
licenses:
|
53
55
|
post_install_message:
|
54
56
|
rdoc_options:
|
55
57
|
- --line-numbers
|
@@ -75,7 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
75
77
|
requirements: []
|
76
78
|
|
77
79
|
rubyforge_project:
|
78
|
-
rubygems_version: 1.
|
80
|
+
rubygems_version: 1.3.5
|
79
81
|
signing_key:
|
80
82
|
specification_version: 2
|
81
83
|
summary: A simple Ruby library to access the status of the London Underground network.
|