service_disruption 0.0.1
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/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.markdown +38 -0
- data/Rakefile +16 -0
- data/bin/service_disruption +6 -0
- data/lib/service_disruption/command.rb +22 -0
- data/lib/service_disruption/core_ext/hash.rb +30 -0
- data/lib/service_disruption/data_source.rb +35 -0
- data/lib/service_disruption/line.rb +31 -0
- data/lib/service_disruption/network.rb +54 -0
- data/lib/service_disruption/notifier.rb +35 -0
- data/lib/service_disruption/status.rb +42 -0
- data/lib/service_disruption.rb +45 -0
- data/service_disruption.gemspec +37 -0
- data/spec/data_source_spec.rb +33 -0
- data/spec/fixtures/line_status.xml +103 -0
- data/spec/line_spec.rb +63 -0
- data/spec/network_spec.rb +31 -0
- data/spec/service_disruption_spec.rb +17 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/status_spec.rb +51 -0
- data/static/cs.png +0 -0
- data/static/gs.png +0 -0
- data/static/md.png +0 -0
- data/static/ps.png +0 -0
- data/static/sd.png +0 -0
- metadata +195 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.markdown
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
Service Disruption
|
2
|
+
=============
|
3
|
+
|
4
|
+
A little library to easily tell you when the Tube has problems
|
5
|
+
|
6
|
+
## Install
|
7
|
+
|
8
|
+
gem install service_disruption
|
9
|
+
|
10
|
+
|
11
|
+
## Running
|
12
|
+
|
13
|
+
$: service_disruption start
|
14
|
+
|
15
|
+
Extra arguments are: `-d` to deamonise and `-i` to change the polling time, defaults to once every 30 seconds
|
16
|
+
|
17
|
+
Alternatively if you'd like to see some pretty colours on your command line you can run
|
18
|
+
|
19
|
+
$: service_disruption status
|
20
|
+
|
21
|
+
That will tell you the current state of the tube network, you can also incude it as any other ruby library. It exposes the following API:
|
22
|
+
|
23
|
+
network = ServiceDisruption.network
|
24
|
+
|
25
|
+
network.lines # Array of lines
|
26
|
+
bakerloo = network.find_by_name('Bakerloo') # Line object
|
27
|
+
|
28
|
+
bakerloo.status # Status object
|
29
|
+
|
30
|
+
network.update! # Updates all of the lines status information if it has changed
|
31
|
+
|
32
|
+
## Who?
|
33
|
+
|
34
|
+
[Adam Carlile](http://adamcarlile.com) built this. Ping me on Twitter —
|
35
|
+
[@frozenproduce](http://twitter.com/frozenproduce).
|
36
|
+
|
37
|
+
NOTE: Not to be used for mission critical service monitoring!
|
38
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
|
4
|
+
desc 'Default: run specs.'
|
5
|
+
task :default => :spec
|
6
|
+
|
7
|
+
desc "Run specs"
|
8
|
+
RSpec::Core::RakeTask.new do |t|
|
9
|
+
t.rspec_opts = "--colour --format Fuubar"
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Generate code coverage"
|
13
|
+
RSpec::Core::RakeTask.new(:coverage) do |t|
|
14
|
+
t.rcov = true
|
15
|
+
t.rcov_opts = ['--exclude', 'spec']
|
16
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module ServiceDisruption
|
2
|
+
class Command < Thor
|
3
|
+
|
4
|
+
desc "start", "Run the monitor"
|
5
|
+
method_option :daemonize, :aliases => "-d", :default => false, :type => :boolean, :banner => "Run as daemon"
|
6
|
+
method_option :interval, :aliases => "-i", :default => 30, :type => :numeric, :banner => "Interval to wait to poll in seconds"
|
7
|
+
def start
|
8
|
+
network = ServiceDisruption.network
|
9
|
+
EventMachine::run do
|
10
|
+
EventMachine::add_periodic_timer(options[:interval]) do
|
11
|
+
network.update!
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "status", "Show the current line status"
|
17
|
+
def status
|
18
|
+
puts ServiceDisruption.network
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Hash
|
2
|
+
|
3
|
+
def rubyfy_keys!
|
4
|
+
keys.each do |key|
|
5
|
+
self[(key.underscore rescue key) || key] = delete(key)
|
6
|
+
end
|
7
|
+
self
|
8
|
+
end
|
9
|
+
|
10
|
+
def recursive_rubyfy_keys!
|
11
|
+
rubyfy_keys!
|
12
|
+
values.each{|h| h.recursive_rubyfy_keys! if h.is_a?(Hash) }
|
13
|
+
values.select{|v| v.is_a?(Array) }.flatten.each{|h| h.recursive_rubyfy_keys! if h.is_a?(Hash) }
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def recursive_symbolize_keys!
|
18
|
+
symbolize_keys!
|
19
|
+
values.each{|h| h.recursive_symbolize_keys! if h.is_a?(Hash) }
|
20
|
+
values.select{|v| v.is_a?(Array) }.flatten.each{|h| h.recursive_symbolize_keys! if h.is_a?(Hash) }
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def recursive_rubyfy_and_symbolize_keys!
|
25
|
+
recursive_rubyfy_keys!
|
26
|
+
recursive_symbolize_keys!
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module ServiceDisruption
|
2
|
+
class DataSource
|
3
|
+
include HTTParty
|
4
|
+
|
5
|
+
def initialize(url)
|
6
|
+
@url = URI.parse(url)
|
7
|
+
end
|
8
|
+
|
9
|
+
def get_latest_dataset
|
10
|
+
response = self.class.get(@url.to_s)
|
11
|
+
if response.success?
|
12
|
+
response.recursive_rubyfy_and_symbolize_keys!
|
13
|
+
else
|
14
|
+
false
|
15
|
+
end
|
16
|
+
rescue
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
def parse_data_set
|
21
|
+
lines_array = []
|
22
|
+
if get_latest_dataset
|
23
|
+
get_latest_dataset[:array_of_line_status][:line_status].each do |line_status|
|
24
|
+
lines_array << line_status
|
25
|
+
end
|
26
|
+
end
|
27
|
+
lines_array
|
28
|
+
end
|
29
|
+
|
30
|
+
def available_lines
|
31
|
+
parse_data_set
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ServiceDisruption
|
2
|
+
class Line
|
3
|
+
|
4
|
+
attr_accessor :name, :status, :id
|
5
|
+
|
6
|
+
def initialize(line)
|
7
|
+
@id = line[:line][:id]
|
8
|
+
@name = line[:line][:name]
|
9
|
+
@status = ServiceDisruption::Status.new(line[:status], line[:status_details])
|
10
|
+
ServiceDisruption.notifier.status_change(self) if @status.disrupted?
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
"#{@name}: #{@status}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def update_status(data)
|
18
|
+
old_status = @status
|
19
|
+
new_status = ServiceDisruption::Status.new(data[:status], data[:status_details])
|
20
|
+
unless old_status == new_status
|
21
|
+
@status = new_status
|
22
|
+
ServiceDisruption.notifier.status_change(self)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def disrupted?
|
27
|
+
@status.disrupted?
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module ServiceDisruption
|
2
|
+
class Network
|
3
|
+
|
4
|
+
attr_accessor :lines, :updated_at
|
5
|
+
|
6
|
+
def initialize(data_source)
|
7
|
+
@lines = []
|
8
|
+
@updated_at = Time.now
|
9
|
+
data_source.available_lines.each {|x| add_line ServiceDisruption::Line.new(x)}
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_line(line)
|
13
|
+
@lines << line
|
14
|
+
end
|
15
|
+
|
16
|
+
def [](index)
|
17
|
+
@lines[index]
|
18
|
+
end
|
19
|
+
|
20
|
+
def find_by_name(name)
|
21
|
+
@lines.select {|x| x.name == name}
|
22
|
+
end
|
23
|
+
|
24
|
+
def find_by_id(id)
|
25
|
+
@lines.select {|x| x.id == id}
|
26
|
+
end
|
27
|
+
|
28
|
+
def update!
|
29
|
+
begin
|
30
|
+
ServiceDisruption.data_source.available_lines.each do |new_data|
|
31
|
+
line = find_by_id(new_data[:line][:id]).first
|
32
|
+
line.update_status(new_data)
|
33
|
+
end
|
34
|
+
@updated_at = Time.now
|
35
|
+
true
|
36
|
+
rescue
|
37
|
+
false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_s
|
42
|
+
out = []
|
43
|
+
out << ' '
|
44
|
+
out << '==========================='
|
45
|
+
out << @lines
|
46
|
+
out << '==========================='
|
47
|
+
out << "Updated at: #{@updated_at}"
|
48
|
+
out << '==========================='
|
49
|
+
out << ' '
|
50
|
+
out.join("\n")
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module ServiceDisruption
|
2
|
+
class Notifier
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@client = GNTP.new("Service Disruption")
|
6
|
+
register_notifications
|
7
|
+
end
|
8
|
+
|
9
|
+
def status_change(line)
|
10
|
+
@client.notify({:name => "status_change",
|
11
|
+
:title => "#{line.name} | #{line.status.status_description}",
|
12
|
+
:text => line.status.status_details,
|
13
|
+
:icon => line.status.image,
|
14
|
+
:sticky => true
|
15
|
+
})
|
16
|
+
true
|
17
|
+
rescue
|
18
|
+
false
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def register_notifications
|
24
|
+
@client.register({:notifications => [{
|
25
|
+
:name => "status_change",
|
26
|
+
:enabled => true,
|
27
|
+
}]
|
28
|
+
})
|
29
|
+
true
|
30
|
+
rescue
|
31
|
+
false
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module ServiceDisruption
|
2
|
+
class Status
|
3
|
+
|
4
|
+
COLOUR_CODES = {
|
5
|
+
:GS => :green,
|
6
|
+
:MD => :yellow,
|
7
|
+
:SD => :red,
|
8
|
+
:CS => :yellow,
|
9
|
+
:PS => :red,
|
10
|
+
:PC => :yellow
|
11
|
+
}
|
12
|
+
|
13
|
+
attr_accessor :id, :status_details, :status_description, :active
|
14
|
+
|
15
|
+
def initialize(status, status_details)
|
16
|
+
@id = status[:id].upcase.to_sym
|
17
|
+
@status_details = status_details
|
18
|
+
@status_description = status[:description]
|
19
|
+
@active = status[:is_active]
|
20
|
+
@updated_at = Time.now
|
21
|
+
end
|
22
|
+
|
23
|
+
def image
|
24
|
+
"#{ROOT_PATH}/static/#{@id.to_s.downcase}.png"
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
out = [@status_description]
|
29
|
+
out << @status_details unless @status_details.nil?
|
30
|
+
out.join(' ').color(COLOUR_CODES[@id])
|
31
|
+
end
|
32
|
+
|
33
|
+
def disrupted?
|
34
|
+
[:MD, :SD, :CS, :PS, :PC].include? @id
|
35
|
+
end
|
36
|
+
|
37
|
+
def ==(another_status)
|
38
|
+
(self.id == another_status.id) && (self.status_details == another_status.status_details)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
begin
|
2
|
+
require 'rubygems'
|
3
|
+
rescue LoadError
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'uri'
|
7
|
+
require 'thor'
|
8
|
+
require 'httparty'
|
9
|
+
require 'eventmachine'
|
10
|
+
require 'rainbow'
|
11
|
+
require 'ruby_gntp'
|
12
|
+
require 'active_support/core_ext'
|
13
|
+
|
14
|
+
#Redefine runtime loadpath
|
15
|
+
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
16
|
+
|
17
|
+
require "service_disruption/command"
|
18
|
+
require "service_disruption/data_source"
|
19
|
+
require "service_disruption/line"
|
20
|
+
require "service_disruption/status"
|
21
|
+
require "service_disruption/network"
|
22
|
+
require "service_disruption/notifier"
|
23
|
+
|
24
|
+
require "service_disruption/core_ext/hash"
|
25
|
+
|
26
|
+
module ServiceDisruption
|
27
|
+
VERSION = '0.0.1'
|
28
|
+
TFL_ENDPOINT = 'http://cloud.tfl.gov.uk/TrackerNet/LineStatus'
|
29
|
+
ROOT_PATH = File.dirname(File.dirname(__FILE__))
|
30
|
+
|
31
|
+
extend self
|
32
|
+
|
33
|
+
def notifier
|
34
|
+
@notifier ||= ServiceDisruption::Notifier.new
|
35
|
+
end
|
36
|
+
|
37
|
+
def data_source
|
38
|
+
@data_source ||= ServiceDisruption::DataSource.new(TFL_ENDPOINT)
|
39
|
+
end
|
40
|
+
|
41
|
+
def network
|
42
|
+
@network ||= ServiceDisruption::Network.new(data_source)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "service_disruption"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "service_disruption"
|
7
|
+
s.version = ServiceDisruption::VERSION
|
8
|
+
s.authors = ["Adam Carlile"]
|
9
|
+
s.email = ["adam@benchmedia.co.uk"]
|
10
|
+
s.homepage = "http://adamcarlile.com"
|
11
|
+
s.summary = %q{
|
12
|
+
A simple gem to track the current status of London Underground services
|
13
|
+
}
|
14
|
+
s.description = %q{
|
15
|
+
BOOM!
|
16
|
+
}
|
17
|
+
|
18
|
+
s.rubyforge_project = "service_disruption"
|
19
|
+
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
23
|
+
s.require_paths = ["lib"]
|
24
|
+
|
25
|
+
# specify any dependencies here; for example:
|
26
|
+
s.add_development_dependency 'rake', '~> 0.9.2'
|
27
|
+
s.add_development_dependency 'rspec', '~> 2.9.0'
|
28
|
+
s.add_development_dependency 'fakeweb', '~> 1.3.0'
|
29
|
+
s.add_development_dependency 'fuubar', '~> 1.0.0'
|
30
|
+
|
31
|
+
s.add_runtime_dependency "thor", '~> 0.14.6'
|
32
|
+
s.add_runtime_dependency "httparty", '~> 0.8.3'
|
33
|
+
s.add_runtime_dependency "eventmachine", '~> 0.12.10'
|
34
|
+
s.add_runtime_dependency "rainbow", '~> 1.1.3'
|
35
|
+
s.add_runtime_dependency "activesupport", '~> 3.2.0'
|
36
|
+
s.add_runtime_dependency "ruby_gntp", '~> 0.3.4'
|
37
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Service Disruption / Data Source" do
|
4
|
+
|
5
|
+
context 'with a successful HTTP request' do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@data_source = ServiceDisruption::DataSource.new(ServiceDisruption::TFL_ENDPOINT)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should return an array of available lines' do
|
12
|
+
@data_source.available_lines.class.should eq(Array)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should return an aray with more then one line' do
|
16
|
+
@data_source.available_lines.should_not be_empty
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'with an unsuccessful HTTP request' do
|
22
|
+
|
23
|
+
before(:each) do
|
24
|
+
@data_source = ServiceDisruption::DataSource.new('http://cloud.tfl.gov.uk/unsuccessful.xml')
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should return an empty array' do
|
28
|
+
@data_source.available_lines.should be_empty
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
|
2
|
+
<?xml version="1.0" encoding="utf-8"?>
|
3
|
+
<ArrayOfLineStatus xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://webservices.lul.co.uk/">
|
4
|
+
<LineStatus ID="0" StatusDetails="">
|
5
|
+
<BranchDisruptions />
|
6
|
+
<Line ID="1" Name="Bakerloo" />
|
7
|
+
<Status ID="GS" CssClass="GoodService" Description="Good Service" IsActive="true">
|
8
|
+
<StatusType ID="1" Description="Line" />
|
9
|
+
</Status>
|
10
|
+
</LineStatus>
|
11
|
+
<LineStatus ID="1" StatusDetails="">
|
12
|
+
<BranchDisruptions />
|
13
|
+
<Line ID="2" Name="Central" />
|
14
|
+
<Status ID="GS" CssClass="GoodService" Description="Good Service" IsActive="true">
|
15
|
+
<StatusType ID="1" Description="Line" />
|
16
|
+
</Status>
|
17
|
+
</LineStatus>
|
18
|
+
<LineStatus ID="10" StatusDetails="">
|
19
|
+
<BranchDisruptions />
|
20
|
+
<Line ID="7" Name="Circle" />
|
21
|
+
<Status ID="GS" CssClass="GoodService" Description="Good Service" IsActive="true">
|
22
|
+
<StatusType ID="1" Description="Line" />
|
23
|
+
</Status>
|
24
|
+
</LineStatus>
|
25
|
+
<LineStatus ID="2" StatusDetails="No service between Turnham Green and Richmond due to planned engineering work. GOOD SERVICE on the rest of the line.">
|
26
|
+
<BranchDisruptions>
|
27
|
+
<BranchDisruption>
|
28
|
+
<StationTo ID="190" Name="Richmond" />
|
29
|
+
<StationFrom ID="238" Name="Turnham Green" />
|
30
|
+
</BranchDisruption>
|
31
|
+
</BranchDisruptions>
|
32
|
+
<Line ID="9" Name="District" />
|
33
|
+
<Status ID="PC" CssClass="DisruptedService" Description="Part Closure" IsActive="true">
|
34
|
+
<StatusType ID="1" Description="Line" />
|
35
|
+
</Status>
|
36
|
+
</LineStatus>
|
37
|
+
<LineStatus ID="8" StatusDetails="">
|
38
|
+
<BranchDisruptions />
|
39
|
+
<Line ID="8" Name="Hammersmith and City" />
|
40
|
+
<Status ID="GS" CssClass="GoodService" Description="Good Service" IsActive="true">
|
41
|
+
<StatusType ID="1" Description="Line" />
|
42
|
+
</Status>
|
43
|
+
</LineStatus>
|
44
|
+
<LineStatus ID="4" StatusDetails="">
|
45
|
+
<BranchDisruptions />
|
46
|
+
<Line ID="4" Name="Jubilee" />
|
47
|
+
<Status ID="GS" CssClass="GoodService" Description="Good Service" IsActive="true">
|
48
|
+
<StatusType ID="1" Description="Line" />
|
49
|
+
</Status>
|
50
|
+
</LineStatus>
|
51
|
+
<LineStatus ID="9" StatusDetails="">
|
52
|
+
<BranchDisruptions />
|
53
|
+
<Line ID="11" Name="Metropolitan" />
|
54
|
+
<Status ID="GS" CssClass="GoodService" Description="Good Service" IsActive="true">
|
55
|
+
<StatusType ID="1" Description="Line" />
|
56
|
+
</Status>
|
57
|
+
</LineStatus>
|
58
|
+
<LineStatus ID="5" StatusDetails="">
|
59
|
+
<BranchDisruptions />
|
60
|
+
<Line ID="5" Name="Northern" />
|
61
|
+
<Status ID="GS" CssClass="GoodService" Description="Good Service" IsActive="true">
|
62
|
+
<StatusType ID="1" Description="Line" />
|
63
|
+
</Status>
|
64
|
+
</LineStatus>
|
65
|
+
<LineStatus ID="6" StatusDetails="">
|
66
|
+
<BranchDisruptions />
|
67
|
+
<Line ID="6" Name="Piccadilly" />
|
68
|
+
<Status ID="GS" CssClass="GoodService" Description="Good Service" IsActive="true">
|
69
|
+
<StatusType ID="1" Description="Line" />
|
70
|
+
</Status>
|
71
|
+
</LineStatus>
|
72
|
+
<LineStatus ID="7" StatusDetails="">
|
73
|
+
<BranchDisruptions />
|
74
|
+
<Line ID="3" Name="Victoria" />
|
75
|
+
<Status ID="GS" CssClass="GoodService" Description="Good Service" IsActive="true">
|
76
|
+
<StatusType ID="1" Description="Line" />
|
77
|
+
</Status>
|
78
|
+
</LineStatus>
|
79
|
+
<LineStatus ID="11" StatusDetails="Train service will resume at 06.15 on Monday.">
|
80
|
+
<BranchDisruptions />
|
81
|
+
<Line ID="12" Name="Waterloo and City" />
|
82
|
+
<Status ID="CS" CssClass="DisruptedService" Description="Planned Closure" IsActive="true">
|
83
|
+
<StatusType ID="1" Description="Line" />
|
84
|
+
</Status>
|
85
|
+
</LineStatus>
|
86
|
+
<LineStatus ID="82" StatusDetails="No service between Willesden Junction and Richmond. No service between Euston and Watford Junction due to planned works. GOOD SERVICE on other routes.">
|
87
|
+
<BranchDisruptions>
|
88
|
+
<BranchDisruption />
|
89
|
+
<BranchDisruption />
|
90
|
+
</BranchDisruptions>
|
91
|
+
<Line ID="82" Name="Overground" />
|
92
|
+
<Status ID="PC" CssClass="DisruptedService" Description="Part Closure" IsActive="true">
|
93
|
+
<StatusType ID="1" Description="Line" />
|
94
|
+
</Status>
|
95
|
+
</LineStatus>
|
96
|
+
<LineStatus ID="81" StatusDetails="">
|
97
|
+
<BranchDisruptions />
|
98
|
+
<Line ID="81" Name="DLR" />
|
99
|
+
<Status ID="GS" CssClass="GoodService" Description="Good Service" IsActive="true">
|
100
|
+
<StatusType ID="1" Description="Line" />
|
101
|
+
</Status>
|
102
|
+
</LineStatus>
|
103
|
+
</ArrayOfLineStatus>
|
data/spec/line_spec.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Service Disruption / Line" do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
@bakerloo = {
|
7
|
+
:line => {:id => "1", :name => "Bakerloo"},
|
8
|
+
:status => {
|
9
|
+
:id => "GS",
|
10
|
+
:description => "Good Service",
|
11
|
+
:is_active => true
|
12
|
+
},
|
13
|
+
:status_details => ""
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
context "Line with good service" do
|
18
|
+
|
19
|
+
before(:each) do
|
20
|
+
@line = ServiceDisruption::Line.new(@bakerloo)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should not be disrupted" do
|
24
|
+
@line.disrupted?.should be_false
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should return it's name and status" do
|
28
|
+
@line.to_s.should be_an_instance_of String
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
context "Line with minor disruptions" do
|
34
|
+
|
35
|
+
before(:each) do
|
36
|
+
@broken_bakerloo = @bakerloo.merge({
|
37
|
+
:status_details => "Oops, looks like the Bakerloo line is broken again",
|
38
|
+
:status => {
|
39
|
+
:id => "MD",
|
40
|
+
:description => "Minor Delays"
|
41
|
+
}})
|
42
|
+
@line = ServiceDisruption::Line.new(@broken_bakerloo)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should be disrupted" do
|
46
|
+
@line.disrupted?.should be_true
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should allow me to change the lines status" do
|
50
|
+
@line.disrupted?.should be_true
|
51
|
+
@line.update_status(@bakerloo)
|
52
|
+
@line.disrupted?.should be_false
|
53
|
+
end
|
54
|
+
|
55
|
+
it "shouldn't create a new status object if the line status hasn't changed" do
|
56
|
+
old_status = @line.status
|
57
|
+
@line.update_status(@broken_bakerloo)
|
58
|
+
@line.status.object_id.should eq(old_status.object_id)
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Service Disruption / Network" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@network = ServiceDisruption::Network.new(ServiceDisruption.data_source)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should return a list of available lines" do
|
10
|
+
@network.lines.should_not be_empty
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should allow me to find lines by position" do
|
14
|
+
@network[0].class.should eq(ServiceDisruption::Line)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should allow me to find lines by name" do
|
18
|
+
@network.find_by_name('Bakerloo').should_not be_empty
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should allow me to find lines by id" do
|
22
|
+
@network.find_by_id('1').should_not be_empty
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should be able to update it's list" do
|
26
|
+
old_time = @network.updated_at
|
27
|
+
@network.update!
|
28
|
+
@network.updated_at.should_not eq(old_time)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Service Disruption" do
|
4
|
+
|
5
|
+
it "should return a network object" do
|
6
|
+
ServiceDisruption.network.class.should eq(ServiceDisruption::Network)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should return a datasource" do
|
10
|
+
ServiceDisruption.data_source.class.should eq(ServiceDisruption::DataSource)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return a notifier" do
|
14
|
+
ServiceDisruption.notifier.class.should eq(ServiceDisruption::Notifier)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
2
|
+
require 'service_disruption'
|
3
|
+
require 'fakeweb'
|
4
|
+
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
7
|
+
config.before(:suite) do
|
8
|
+
FakeWeb.allow_net_connect = false
|
9
|
+
|
10
|
+
FakeWeb.register_uri(:get, ServiceDisruption::TFL_ENDPOINT,
|
11
|
+
:body => File.read(File.join(File.dirname(__FILE__), 'fixtures', 'line_status.xml')),
|
12
|
+
:content_type => "text/xml")
|
13
|
+
|
14
|
+
FakeWeb.register_uri(:get, 'http://cloud.tfl.gov.uk/unsuccessful.xml',
|
15
|
+
:status => ['500', 'Internal Server Error'])
|
16
|
+
end
|
17
|
+
end
|
data/spec/status_spec.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Service Disruption / Status" do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
@good_status = {
|
7
|
+
:id => "GS",
|
8
|
+
:description => "Good Service",
|
9
|
+
:is_active => true
|
10
|
+
}
|
11
|
+
@severe_delays = {
|
12
|
+
:id => "SD",
|
13
|
+
:description => "Severe Delays",
|
14
|
+
:is_active => true
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
context "Status with good service" do
|
19
|
+
before(:each) do
|
20
|
+
@status = ServiceDisruption::Status.new(@good_status, "Everything is running great")
|
21
|
+
end
|
22
|
+
|
23
|
+
it "shouldn't be disrupted" do
|
24
|
+
@status.disrupted?.should be_false
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
context "Status with severe delays" do
|
30
|
+
before(:each) do
|
31
|
+
@status = ServiceDisruption::Status.new(@severe_delays, "It's all horribly broken")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should be disrupted" do
|
35
|
+
@status.disrupted?.should be_true
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should be equal when two statuses with the same attributes are compared" do
|
41
|
+
status = ServiceDisruption::Status.new(@good_status, "It's going great")
|
42
|
+
status.should == status
|
43
|
+
end
|
44
|
+
|
45
|
+
it "shouldn't be equal when two statuses with the same attributes are compared" do
|
46
|
+
good_status = ServiceDisruption::Status.new(@good_status, "It's going great")
|
47
|
+
bad_status = ServiceDisruption::Status.new(@severe_delays, "Oh dear")
|
48
|
+
good_status.should_not == bad_status
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
data/static/cs.png
ADDED
Binary file
|
data/static/gs.png
ADDED
Binary file
|
data/static/md.png
ADDED
Binary file
|
data/static/ps.png
ADDED
Binary file
|
data/static/sd.png
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,195 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: service_disruption
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Adam Carlile
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-29 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: &70126178324100 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.9.2
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70126178324100
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
requirement: &70126178339920 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.9.0
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70126178339920
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: fakeweb
|
38
|
+
requirement: &70126178339400 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.3.0
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70126178339400
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: fuubar
|
49
|
+
requirement: &70126178338900 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.0.0
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70126178338900
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: thor
|
60
|
+
requirement: &70126178338400 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 0.14.6
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70126178338400
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: httparty
|
71
|
+
requirement: &70126178337940 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 0.8.3
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70126178337940
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: eventmachine
|
82
|
+
requirement: &70126178337480 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ~>
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: 0.12.10
|
88
|
+
type: :runtime
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *70126178337480
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: rainbow
|
93
|
+
requirement: &70126178337020 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ~>
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: 1.1.3
|
99
|
+
type: :runtime
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *70126178337020
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: activesupport
|
104
|
+
requirement: &70126178336560 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 3.2.0
|
110
|
+
type: :runtime
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: *70126178336560
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: ruby_gntp
|
115
|
+
requirement: &70126178336080 !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
117
|
+
requirements:
|
118
|
+
- - ~>
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: 0.3.4
|
121
|
+
type: :runtime
|
122
|
+
prerelease: false
|
123
|
+
version_requirements: *70126178336080
|
124
|
+
description: ! "\n BOOM!\n "
|
125
|
+
email:
|
126
|
+
- adam@benchmedia.co.uk
|
127
|
+
executables:
|
128
|
+
- service_disruption
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- .gitignore
|
133
|
+
- Gemfile
|
134
|
+
- README.markdown
|
135
|
+
- Rakefile
|
136
|
+
- bin/service_disruption
|
137
|
+
- lib/service_disruption.rb
|
138
|
+
- lib/service_disruption/command.rb
|
139
|
+
- lib/service_disruption/core_ext/hash.rb
|
140
|
+
- lib/service_disruption/data_source.rb
|
141
|
+
- lib/service_disruption/line.rb
|
142
|
+
- lib/service_disruption/network.rb
|
143
|
+
- lib/service_disruption/notifier.rb
|
144
|
+
- lib/service_disruption/status.rb
|
145
|
+
- service_disruption.gemspec
|
146
|
+
- spec/data_source_spec.rb
|
147
|
+
- spec/fixtures/line_status.xml
|
148
|
+
- spec/line_spec.rb
|
149
|
+
- spec/network_spec.rb
|
150
|
+
- spec/service_disruption_spec.rb
|
151
|
+
- spec/spec_helper.rb
|
152
|
+
- spec/status_spec.rb
|
153
|
+
- static/cs.png
|
154
|
+
- static/gs.png
|
155
|
+
- static/md.png
|
156
|
+
- static/ps.png
|
157
|
+
- static/sd.png
|
158
|
+
homepage: http://adamcarlile.com
|
159
|
+
licenses: []
|
160
|
+
post_install_message:
|
161
|
+
rdoc_options: []
|
162
|
+
require_paths:
|
163
|
+
- lib
|
164
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
165
|
+
none: false
|
166
|
+
requirements:
|
167
|
+
- - ! '>='
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: '0'
|
170
|
+
segments:
|
171
|
+
- 0
|
172
|
+
hash: -2835984172953313753
|
173
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
174
|
+
none: false
|
175
|
+
requirements:
|
176
|
+
- - ! '>='
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: '0'
|
179
|
+
segments:
|
180
|
+
- 0
|
181
|
+
hash: -2835984172953313753
|
182
|
+
requirements: []
|
183
|
+
rubyforge_project: service_disruption
|
184
|
+
rubygems_version: 1.8.17
|
185
|
+
signing_key:
|
186
|
+
specification_version: 3
|
187
|
+
summary: A simple gem to track the current status of London Underground services
|
188
|
+
test_files:
|
189
|
+
- spec/data_source_spec.rb
|
190
|
+
- spec/fixtures/line_status.xml
|
191
|
+
- spec/line_spec.rb
|
192
|
+
- spec/network_spec.rb
|
193
|
+
- spec/service_disruption_spec.rb
|
194
|
+
- spec/spec_helper.rb
|
195
|
+
- spec/status_spec.rb
|