metra_schedule 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.2
1
+ 0.3.0
data/lib/metra/cacher.rb CHANGED
@@ -3,10 +3,11 @@ require 'fileutils'
3
3
  module MetraSchedule
4
4
  class Cacher
5
5
 
6
- attr_accessor :cache_dir
6
+ attr_accessor :cache_dir, :delays
7
7
 
8
8
  def initialize
9
9
  @cache_dir = "#{ENV['HOME']}/.metra_schedule"
10
+ @delay_file = 'delays'
10
11
  end
11
12
 
12
13
  def self.load_from_cache(line)
@@ -43,6 +44,20 @@ module MetraSchedule
43
44
  end
44
45
  end
45
46
 
47
+ def delays_exist?
48
+ return true if File.exists?(File.join(@cache_dir, @delay_file))
49
+ false
50
+ end
51
+
52
+ def clear_delays
53
+ begin
54
+ FileUtils.rm(File.join(@cache_dir, @delay_file))
55
+ true
56
+ rescue
57
+ false
58
+ end
59
+ end
60
+
46
61
  def persist_line(line)
47
62
  create_cache_dir_if_not_exists
48
63
  return false unless line.engines
@@ -56,6 +71,20 @@ module MetraSchedule
56
71
  nil
57
72
  end
58
73
  end
74
+
75
+ def persist_delays(delays)
76
+ create_cache_dir_if_not_exists
77
+ return false unless delays
78
+ true if File.open(File.join(@cache_dir, @delay_file), 'w') {|f| Marshal.dump(delays, f)}
79
+ end
80
+
81
+ def retrieve_delays
82
+ if delays_exist?
83
+ File.open(File.join(@cache_dir, @delay_file), 'r') {|f| Marshal.load(f)}
84
+ else
85
+ nil
86
+ end
87
+ end
59
88
 
60
89
  end
61
90
  end
@@ -0,0 +1,60 @@
1
+ require 'nokogiri'
2
+ require 'open-uri'
3
+
4
+ module MetraSchedule
5
+ class DelayParser
6
+ attr_reader :html_doc, :url
7
+ attr_accessor :line
8
+
9
+ def initialize(html_doc=nil)
10
+ time = Time.now.to_i
11
+ @url = "http://metrarail.com/content/metra/en/home/service_updates/service_updates_alerts/jcr:content/serviceAdvisory.display.html?t=#{time}"
12
+ @html_doc = @url unless html_doc
13
+ @html_doc = html_doc if html_doc
14
+ end
15
+
16
+ def scrape
17
+ parse_nokogiri
18
+ make_train_delays
19
+ end
20
+
21
+ def parse_nokogiri
22
+ html_doc = open(@html_doc) if @html_doc.is_a?(String)
23
+ html_doc = @html_doc if @html_doc.is_a?(File)
24
+ @html_doc = Nokogiri::HTML(html_doc)
25
+ end
26
+
27
+ def make_train_delays
28
+ return unless has_delays?
29
+ all_advisories.inject([]) do |total, node|
30
+ total << {:train_num => find_train_num(node), :delay => find_delay(node)}
31
+ end
32
+ end
33
+
34
+ def find_train_num(node)
35
+ node.text.scan(/#([0-9]+)/).first.first.to_i
36
+ end
37
+
38
+ def find_delay(node)
39
+ text_array = node.text.delete("\r\n").split("\s")[3..-1]
40
+ text_array.delete_at(0) if text_array[0] == "-"
41
+ text_array.join("\s").strip
42
+ end
43
+
44
+ def has_delays?
45
+ @html_doc.css('#serviceAdvisory').count > 0
46
+ end
47
+
48
+ private
49
+
50
+ def all_advisories
51
+ nodes = @html_doc.css('#serviceAdvisory dl dd')
52
+ advisories = nodes.inject([]) do |total, node|
53
+ id = node.attributes.has_key?("id")
54
+ total << node unless id
55
+ total
56
+ end
57
+ end
58
+
59
+ end
60
+ end
@@ -2,7 +2,11 @@ module MetraSchedule
2
2
  module Extensions
3
3
  module TimeExtension
4
4
  def to_today
5
- Time.local(Time.now.year, Time.now.month, Time.now.day, self.hour, self.min, self.sec)
5
+ if self.hour >= 0 and self.hour <= 2 # Midnight to 2AM counts as the same day
6
+ Time.local(Time.now.year, Time.now.month, Time.now.day+1, self.hour, self.min, self.sec)
7
+ else
8
+ Time.local(Time.now.year, Time.now.month, Time.now.day, self.hour, self.min, self.sec)
9
+ end
6
10
  end
7
11
  end
8
12
  end
data/lib/metra/line.rb CHANGED
@@ -5,7 +5,7 @@ module MetraSchedule
5
5
  include MetraSchedule::TrainData
6
6
 
7
7
  attr_reader :cacher, :cache_dir
8
- attr_reader :line_key, :name, :url, :dir, :sched, :start, :destination, :time
8
+ attr_reader :line_key, :name, :url, :dir, :sched, :start, :destination, :time, :del_threshold
9
9
  attr_accessor :engines
10
10
 
11
11
  def initialize(line_name)
@@ -30,6 +30,7 @@ module MetraSchedule
30
30
  else
31
31
  @engines = cached_engines
32
32
  end
33
+ self
33
34
  end
34
35
 
35
36
  def update_schedule
@@ -155,8 +156,16 @@ module MetraSchedule
155
156
  @engines.find {|e| e.train_num == train_num}
156
157
  end
157
158
 
159
+ def delay_threshold(minutes)
160
+ @del_threshold = minutes if minutes
161
+ self
162
+ end
163
+
158
164
  def trains
159
165
  return [] unless engines
166
+ if MetraSchedule::Cacher.new.delays_exist?
167
+ @filters.insert(0, inject_delays)
168
+ end
160
169
  @filters.inject(engines) { |e, fun| fun.call(e) }.sort
161
170
  end
162
171
 
@@ -172,6 +181,20 @@ module MetraSchedule
172
181
  end
173
182
  end
174
183
 
184
+ def inject_delays
185
+ lambda do |engines|
186
+ delays = MetraSchedule::Cacher.new.retrieve_delays
187
+ delays.each do |d|
188
+ if engines.any? {|e| e.train_num == d[:train_num] }
189
+ train = find_train_by_train_num(d[:train_num])
190
+ train.delay = d[:delay]
191
+ train.del_threshold = @del_threshold if @del_threshold
192
+ end
193
+ end
194
+ engines
195
+ end
196
+ end
197
+
175
198
  def filter_by_stop
176
199
  lambda do |engines|
177
200
  if @start and not @destination
@@ -190,7 +213,11 @@ module MetraSchedule
190
213
  lambda do |engines|
191
214
  return engines unless @time and @start
192
215
  engines.find_all do |engine|
193
- engine.in_time?(@start, @time)
216
+ if @del_threshold and engine.delay
217
+ engine.in_time?(@start, @time - (60 * @del_threshold))
218
+ else
219
+ engine.in_time?(@start, @time)
220
+ end
194
221
  end
195
222
  end
196
223
  end
data/lib/metra/train.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module MetraSchedule
2
2
  class Train
3
3
  attr_reader :train_num, :schedule, :bike_limit, :direction, :stops
4
- attr_accessor :my_departure, :my_arrival # Injected when the line is filtered
4
+ attr_accessor :my_departure, :my_arrival, :delay, :del_threshold # Injected when the line is filtered
5
5
 
6
6
  def initialize(options={})
7
7
  unless options.empty?
@@ -20,17 +20,7 @@ module MetraSchedule
20
20
 
21
21
  def in_time?(station, time)
22
22
  stop_time = stops.find {|s| s.station == station}.time
23
- if (stop_time.hour == time.hour)
24
- if (stop_time.min > time.min)
25
- return true
26
- else
27
- return false
28
- end
29
- elsif (stop_time.hour > time.hour)
30
- return true
31
- else
32
- return false
33
- end
23
+ stop_time.to_today > time.to_today
34
24
  end
35
25
 
36
26
  def departure_and_arrival(start, destination)
@@ -39,11 +29,16 @@ module MetraSchedule
39
29
  {:departure => departure.to_today, :arrival => arrival.to_today}
40
30
  end
41
31
 
32
+ def departure_with_delay
33
+ return @my_departure unless @del_threshold
34
+ if @my_departure
35
+ @my_departure + (60 * @del_threshold)
36
+ end
37
+ end
38
+
42
39
  def my_travel_time
43
40
  return nil unless @my_departure and @my_arrival
44
- minutes = (@my_arrival.to_i - @my_departure.to_i) / 60
45
- return minutes if minutes > 0
46
- return minutes + 1440 if minutes < 0
41
+ minutes = (@my_arrival.to_today.to_i - @my_departure.to_today.to_i) / 60
47
42
  end
48
43
 
49
44
  def print_my_travel_time
data/lib/metra.rb CHANGED
@@ -3,6 +3,7 @@ require File.join(File.dirname(__FILE__), 'metra', 'line')
3
3
  require File.join(File.dirname(__FILE__), 'metra', 'train')
4
4
  require File.join(File.dirname(__FILE__), 'metra', 'stop')
5
5
  require File.join(File.dirname(__FILE__), 'metra', 'parser')
6
+ require File.join(File.dirname(__FILE__), 'metra', 'delay_parser')
6
7
  require File.join(File.dirname(__FILE__), 'metra', 'cacher')
7
8
  require File.join(File.dirname(__FILE__), 'metra', 'extensions', 'time_extension')
8
9
 
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{metra_schedule}
8
- s.version = "0.2.2"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Blake Smith"]
12
- s.date = %q{2010-01-05}
12
+ s.date = %q{2010-02-03}
13
13
  s.description = %q{metra_schedule provides a ruby object interface to the Chicago metra train schedule}
14
14
  s.email = %q{blakesmith0@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -25,6 +25,7 @@ Gem::Specification.new do |s|
25
25
  "lib/metra.rb",
26
26
  "lib/metra/cacher.rb",
27
27
  "lib/metra/classmethods.rb",
28
+ "lib/metra/delay_parser.rb",
28
29
  "lib/metra/extensions/time_extension.rb",
29
30
  "lib/metra/line.rb",
30
31
  "lib/metra/parser.rb",
@@ -33,6 +34,10 @@ Gem::Specification.new do |s|
33
34
  "lib/metra/train_data.rb",
34
35
  "metra_schedule.gemspec",
35
36
  "test/fixture/UP_NW.html",
37
+ "test/fixture/service_updates_alerts.html",
38
+ "test/fixture/service_updates_alerts_multiple_with_non_delay.html",
39
+ "test/fixture/service_updates_alerts_no_advisories.html",
40
+ "test/fixture/service_updates_alerts_no_range.html",
36
41
  "test/functional/test_all_filters.rb",
37
42
  "test/integration/test_line_integration.rb",
38
43
  "test/test_helper.rb",
@@ -46,6 +51,7 @@ Gem::Specification.new do |s|
46
51
  "test/timecop/lib/timecop/time_stack_item.rb",
47
52
  "test/timecop/lib/timecop/timecop.rb",
48
53
  "test/unit/test_cacher.rb",
54
+ "test/unit/test_delay_parser.rb",
49
55
  "test/unit/test_line.rb",
50
56
  "test/unit/test_metra.rb",
51
57
  "test/unit/test_parser.rb",
@@ -71,6 +77,7 @@ Gem::Specification.new do |s|
71
77
  "test/unit/test_metra.rb",
72
78
  "test/unit/test_stop.rb",
73
79
  "test/unit/test_parser.rb",
80
+ "test/unit/test_delay_parser.rb",
74
81
  "test/unit/test_cacher.rb",
75
82
  "test/test_helper.rb"
76
83
  ]
@@ -0,0 +1,26 @@
1
+ <div id="serviceAdvisory">
2
+
3
+
4
+
5
+ <h2><span class="hidden">Service Advisories</span></h2>
6
+
7
+
8
+ <dl>
9
+
10
+
11
+
12
+
13
+
14
+ <dt class="line md-n first">Milwaukee District / North Line</dt>
15
+
16
+
17
+
18
+
19
+ <dd class="first"><a href="#serviceAdvisory1">Inbound Train #2156 18 - 20 minutes delayed</a></dd>
20
+ <dd id="serviceAdvisory1" class="details">Inbound Train #2156 scheduled to arrive Chicago at 8:59 p.m., is operating approximately 20 minutes behind schedule due to freight train interference.</dd>
21
+
22
+
23
+ </dl>
24
+ </div>
25
+
26
+
@@ -0,0 +1,39 @@
1
+
2
+ <div id="serviceAdvisory">
3
+
4
+
5
+
6
+ <h2><span class="hidden">Service Advisories</span></h2>
7
+
8
+
9
+ <dl>
10
+
11
+
12
+
13
+
14
+
15
+ <dt class="line sws first">SouthWest Service</dt>
16
+
17
+
18
+
19
+
20
+ <dd class="first"><a href="#serviceAdvisory1">Outbound Train #807 - Stopped North of Ashburn</a></dd>
21
+ <dd id="serviceAdvisory1" class="details">Train #807, scheduled to arrive Orland Park 179th at 9:39 a.m., is stopped north of Ashburn due to switch problems. The duration of this delay is unknown. Metra will update this site as information becomes available.</dd>
22
+
23
+
24
+
25
+
26
+
27
+
28
+ <dt class="line up-w ">Union Pacific / West Line</dt>
29
+
30
+
31
+
32
+
33
+ <dd ><a href="#serviceAdvisory2">Outbound Train #25 - 15 Minute Delay</a></dd>
34
+ <dd id="serviceAdvisory2" class="details">Train #25, scheduled to arrive Elburn at 10:08 a.m., is operating 15 minutes behind schedule due to switch problems.</dd>
35
+
36
+
37
+ </dl>
38
+ </div>
39
+