rail_feeds 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.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/.rspec +3 -0
- data/.rubocop.yml +31 -0
- data/.travis.yml +26 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +6 -0
- data/Guardfile +25 -0
- data/LICENSE.md +32 -0
- data/README.md +77 -0
- data/Rakefile +3 -0
- data/doc/guides/Logging.md +13 -0
- data/doc/guides/Network Rail/CORPUS.md +34 -0
- data/doc/guides/Network Rail/SMART.md +39 -0
- data/doc/guides/Network Rail/Schedule.md +138 -0
- data/file +0 -0
- data/lib/rail_feeds/credentials.rb +45 -0
- data/lib/rail_feeds/logging.rb +51 -0
- data/lib/rail_feeds/network_rail/corpus.rb +77 -0
- data/lib/rail_feeds/network_rail/credentials.rb +22 -0
- data/lib/rail_feeds/network_rail/http_client.rb +57 -0
- data/lib/rail_feeds/network_rail/schedule/association.rb +208 -0
- data/lib/rail_feeds/network_rail/schedule/data.rb +215 -0
- data/lib/rail_feeds/network_rail/schedule/days.rb +95 -0
- data/lib/rail_feeds/network_rail/schedule/fetcher.rb +193 -0
- data/lib/rail_feeds/network_rail/schedule/header/cif.rb +102 -0
- data/lib/rail_feeds/network_rail/schedule/header/json.rb +79 -0
- data/lib/rail_feeds/network_rail/schedule/header.rb +22 -0
- data/lib/rail_feeds/network_rail/schedule/parser/cif.rb +141 -0
- data/lib/rail_feeds/network_rail/schedule/parser/json.rb +87 -0
- data/lib/rail_feeds/network_rail/schedule/parser.rb +108 -0
- data/lib/rail_feeds/network_rail/schedule/stp_indicator.rb +72 -0
- data/lib/rail_feeds/network_rail/schedule/tiploc.rb +100 -0
- data/lib/rail_feeds/network_rail/schedule/train_schedule/change_en_route.rb +158 -0
- data/lib/rail_feeds/network_rail/schedule/train_schedule/location/intermediate.rb +119 -0
- data/lib/rail_feeds/network_rail/schedule/train_schedule/location/origin.rb +91 -0
- data/lib/rail_feeds/network_rail/schedule/train_schedule/location/terminating.rb +72 -0
- data/lib/rail_feeds/network_rail/schedule/train_schedule/location.rb +76 -0
- data/lib/rail_feeds/network_rail/schedule/train_schedule.rb +392 -0
- data/lib/rail_feeds/network_rail/schedule.rb +33 -0
- data/lib/rail_feeds/network_rail/smart.rb +186 -0
- data/lib/rail_feeds/network_rail/stomp_client.rb +77 -0
- data/lib/rail_feeds/network_rail.rb +16 -0
- data/lib/rail_feeds/version.rb +14 -0
- data/lib/rail_feeds.rb +10 -0
- data/rail_feeds.gemspec +32 -0
- data/spec/fixtures/network_rail/schedule/data/full.yaml +60 -0
- data/spec/fixtures/network_rail/schedule/data/starting.yaml +131 -0
- data/spec/fixtures/network_rail/schedule/data/update-gap.yaml +10 -0
- data/spec/fixtures/network_rail/schedule/data/update-next.yaml +13 -0
- data/spec/fixtures/network_rail/schedule/data/update-old.yaml +10 -0
- data/spec/fixtures/network_rail/schedule/data/update.yaml +112 -0
- data/spec/fixtures/network_rail/schedule/parser/train_create.json +1 -0
- data/spec/fixtures/network_rail/schedule/parser/train_delete.json +1 -0
- data/spec/fixtures/network_rail/schedule/train_schedule/json-data.yaml +67 -0
- data/spec/rail_feeds/credentials_spec.rb +46 -0
- data/spec/rail_feeds/logging_spec.rb +81 -0
- data/spec/rail_feeds/network_rail/corpus_spec.rb +92 -0
- data/spec/rail_feeds/network_rail/credentials_spec.rb +22 -0
- data/spec/rail_feeds/network_rail/http_client_spec.rb +88 -0
- data/spec/rail_feeds/network_rail/schedule/association_spec.rb +205 -0
- data/spec/rail_feeds/network_rail/schedule/data_spec.rb +219 -0
- data/spec/rail_feeds/network_rail/schedule/days_shared.rb +99 -0
- data/spec/rail_feeds/network_rail/schedule/days_spec.rb +4 -0
- data/spec/rail_feeds/network_rail/schedule/fetcher_spec.rb +228 -0
- data/spec/rail_feeds/network_rail/schedule/header/cif_spec.rb +72 -0
- data/spec/rail_feeds/network_rail/schedule/header/json_spec.rb +51 -0
- data/spec/rail_feeds/network_rail/schedule/header_spec.rb +19 -0
- data/spec/rail_feeds/network_rail/schedule/parser/cif_spec.rb +197 -0
- data/spec/rail_feeds/network_rail/schedule/parser/json_spec.rb +172 -0
- data/spec/rail_feeds/network_rail/schedule/parser_spec.rb +34 -0
- data/spec/rail_feeds/network_rail/schedule/stp_indicator_shared.rb +49 -0
- data/spec/rail_feeds/network_rail/schedule/stp_indicator_spec.rb +4 -0
- data/spec/rail_feeds/network_rail/schedule/tiploc_spec.rb +77 -0
- data/spec/rail_feeds/network_rail/schedule/train_schedule/change_en_route_spec.rb +121 -0
- data/spec/rail_feeds/network_rail/schedule/train_schedule/location/intermediate_spec.rb +95 -0
- data/spec/rail_feeds/network_rail/schedule/train_schedule/location/origin_spec.rb +87 -0
- data/spec/rail_feeds/network_rail/schedule/train_schedule/location/terminating_spec.rb +81 -0
- data/spec/rail_feeds/network_rail/schedule/train_schedule/location_spec.rb +35 -0
- data/spec/rail_feeds/network_rail/schedule/train_schedule_spec.rb +284 -0
- data/spec/rail_feeds/network_rail/schedule_spec.rb +41 -0
- data/spec/rail_feeds/network_rail/smart_spec.rb +194 -0
- data/spec/rail_feeds/network_rail/stomp_client_spec.rb +151 -0
- data/spec/rail_feeds/network_rail_spec.rb +7 -0
- data/spec/rail_feeds_spec.rb +11 -0
- data/spec/spec_helper.rb +47 -0
- metadata +282 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'set'
|
|
5
|
+
|
|
6
|
+
module RailFeeds
|
|
7
|
+
module NetworkRail
|
|
8
|
+
# rubocop:disable Metrics/ModuleLength
|
|
9
|
+
# A module for getting information out of the SMART data.
|
|
10
|
+
module SMART
|
|
11
|
+
Step = Struct.new(
|
|
12
|
+
:td_area, :from_berth, :to_berth, :step_type, :event_direction, :from_line,
|
|
13
|
+
:to_line, :trust_offset, :platform, :event_type, :route, :stanox,
|
|
14
|
+
:stanox_name, :comment
|
|
15
|
+
) do
|
|
16
|
+
def from_direction
|
|
17
|
+
return :up if event_direction.eql?(:down)
|
|
18
|
+
return :down if event_direction.eql?(:up)
|
|
19
|
+
nil
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def to_direction
|
|
23
|
+
event_direction
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
Berth = Struct.new(
|
|
28
|
+
:id, :up_steps, :down_steps, :up_berths, :down_berths
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Download the current SMART data.
|
|
32
|
+
# @param [RailFeeds::NetworkRail::Credentials] credentials
|
|
33
|
+
# @param [String] file
|
|
34
|
+
# The path to the file to save the .json.gz download in.
|
|
35
|
+
def self.download(file, credentials: Credentials)
|
|
36
|
+
client = HTTPClient.new(credentials: credentials)
|
|
37
|
+
client.download 'ntrod/SupportingFileAuthenticate?type=SMART', file
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Fetch the current SMART data.
|
|
41
|
+
# @param [RailFeeds::NetworkRail::Credentials] credentials
|
|
42
|
+
# @return [Tempfile]
|
|
43
|
+
def self.fetch(credentials: Credentials)
|
|
44
|
+
client = HTTPClient.new(credentials: credentials)
|
|
45
|
+
client.fetch 'ntrod/SupportingFileAuthenticate?type=SMART'
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Load SMART data from either a .json or .json.gz file.
|
|
49
|
+
# @param [String] file The path of the file to open.
|
|
50
|
+
# @return [Array<RailFeeds::NetworkRail::SMART::Step>]
|
|
51
|
+
def self.load_file(file)
|
|
52
|
+
Zlib::GzipReader.open(file) do |gz|
|
|
53
|
+
parse_json gz.read
|
|
54
|
+
end
|
|
55
|
+
rescue Zlib::GzipFile::Error
|
|
56
|
+
parse_json File.read(file)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Load SMART data from the internet.
|
|
60
|
+
# @param [RailFeeds::NetworkRail::Credentials] credentials
|
|
61
|
+
# The credentials to authenticate with.
|
|
62
|
+
# @return [Array<RailFeeds::NetworkRail::SMART::Step>]
|
|
63
|
+
def self.fetch_data(credentials: Credentials)
|
|
64
|
+
client = HTTPClient.new(credentials: credentials)
|
|
65
|
+
client.fetch_unzipped('ntrod/SupportingFileAuthenticate?type=SMART') do |file|
|
|
66
|
+
break parse_json file.read
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# rubocop:disable Metrics/AbcSize
|
|
71
|
+
# rubocop:disable Metrics/MethodLength
|
|
72
|
+
# Generate an berth data from step data.
|
|
73
|
+
# You'll get an array of berths which list the steps into and out of them,
|
|
74
|
+
# which in turn have references to other (via the to_berth attribute) to
|
|
75
|
+
# other berths.
|
|
76
|
+
# @param [Array<RailFeeds::NetworkRail::SMART::Step] steps
|
|
77
|
+
# The steps to build the berth information from.
|
|
78
|
+
# @return [Hash{String=>Hash{String=>RailFeeds::NetworkRail::SMART::Step}}
|
|
79
|
+
# Nested hashes which take a String for the td_area, then a String for
|
|
80
|
+
# the berth.id (from either step.from_berth or step.to_berth) to get a
|
|
81
|
+
# specific berth.
|
|
82
|
+
def self.build_berths(steps)
|
|
83
|
+
berths = Hash.new do |hash, key|
|
|
84
|
+
hash[key] = Hash.new do |hash2, key2|
|
|
85
|
+
hash2[key2] = Berth.new nil, Set.new, Set.new, Set.new, Set.new
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
steps.each do |step|
|
|
90
|
+
next if step.event_direction.nil?
|
|
91
|
+
|
|
92
|
+
# from_berth -> step -> to_berth ---> up
|
|
93
|
+
from_berth = berths.dig(step.td_area, step.from_berth)
|
|
94
|
+
to_berth = berths.dig(step.td_area, step.to_berth)
|
|
95
|
+
|
|
96
|
+
from_berth.id ||= step.from_berth
|
|
97
|
+
to_berth.id ||= step.to_berth
|
|
98
|
+
|
|
99
|
+
from_berth.send("#{step.to_direction}_steps").add step
|
|
100
|
+
to_berth.send("#{step.from_direction}_steps").add step
|
|
101
|
+
from_berth.send("#{step.to_direction}_berths").add step.to_berth
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Convert sets to arrays
|
|
105
|
+
berths.each do |_area, hash|
|
|
106
|
+
hash.each do |_id, value|
|
|
107
|
+
value.up_steps = value.up_steps.to_a
|
|
108
|
+
value.down_steps = value.down_steps.to_a
|
|
109
|
+
value.up_berths = value.up_berths.to_a
|
|
110
|
+
value.down_berths = value.down_berths.to_a
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
# rubocop:enable Metrics/AbcSize
|
|
115
|
+
# rubocop:enable Metrics/MethodLength
|
|
116
|
+
|
|
117
|
+
# private methods below
|
|
118
|
+
|
|
119
|
+
# rubocop:disable Metrics/AbcSize
|
|
120
|
+
# rubocop:disable Metrics/MethodLength
|
|
121
|
+
def self.parse_json(json)
|
|
122
|
+
data = JSON.parse json
|
|
123
|
+
data['BERTHDATA'].map do |item|
|
|
124
|
+
Step.new(
|
|
125
|
+
nilify(item['TD']&.strip),
|
|
126
|
+
nilify(item['FROMBERTH']&.strip),
|
|
127
|
+
nilify(item['TOBERTH']&.strip),
|
|
128
|
+
step_type(item['STEPTYPE']),
|
|
129
|
+
event_direction(item['EVENT']),
|
|
130
|
+
nilify(item['FROMLINE']&.strip),
|
|
131
|
+
nilify(item['TOLINE']&.strip),
|
|
132
|
+
(item['BERTHOFFSET']&.to_i || 0),
|
|
133
|
+
nilify(item['PLATFORM']&.strip),
|
|
134
|
+
event_type(item['EVENT']),
|
|
135
|
+
nilify(item['ROUTE']&.strip),
|
|
136
|
+
nilify(item['STANOX']&.strip)&.to_i,
|
|
137
|
+
nilify(item['STANME']&.strip),
|
|
138
|
+
nilify(item['COMMENT']&.strip)
|
|
139
|
+
)
|
|
140
|
+
# berths[step.from_berth].up_steps.push ....
|
|
141
|
+
# berths[step.to_berth].down_steps.push ....
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
# rubocop:enable Metrics/AbcSize
|
|
145
|
+
# rubocop:enable Metrics/MethodLength
|
|
146
|
+
private_class_method :parse_json
|
|
147
|
+
|
|
148
|
+
def self.nilify(value)
|
|
149
|
+
return nil if value.nil? || value.empty?
|
|
150
|
+
value
|
|
151
|
+
end
|
|
152
|
+
private_class_method :nilify
|
|
153
|
+
|
|
154
|
+
def self.event_type(value)
|
|
155
|
+
return :arrive if value.eql?('A') || value.eql?('C')
|
|
156
|
+
return :depart if value.eql?('B') || value.eql?('D')
|
|
157
|
+
nil
|
|
158
|
+
end
|
|
159
|
+
private_class_method :event_type
|
|
160
|
+
|
|
161
|
+
def self.event_direction(value)
|
|
162
|
+
return :up if value.eql?('A') || value.eql?('B')
|
|
163
|
+
return :down if value.eql?('C') || value.eql?('D')
|
|
164
|
+
nil
|
|
165
|
+
end
|
|
166
|
+
private_class_method :event_direction
|
|
167
|
+
|
|
168
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
169
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
|
170
|
+
def self.step_type(value)
|
|
171
|
+
return :between if value.eql?('B')
|
|
172
|
+
return :from if value.eql?('F')
|
|
173
|
+
return :to if value.eql?('T')
|
|
174
|
+
return :intermediate_first if value.eql?('D')
|
|
175
|
+
return :clearout if value.eql?('C')
|
|
176
|
+
return :interpose if value.eql?('I')
|
|
177
|
+
return :intermediate if value.eql?('E')
|
|
178
|
+
nil
|
|
179
|
+
end
|
|
180
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
181
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
|
182
|
+
private_class_method :step_type
|
|
183
|
+
end
|
|
184
|
+
# rubocop:enable Metrics/ModuleLength
|
|
185
|
+
end
|
|
186
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'socket'
|
|
4
|
+
require 'stomp'
|
|
5
|
+
|
|
6
|
+
module RailFeeds
|
|
7
|
+
module NetworkRail
|
|
8
|
+
# A wrapper class for ::Stomp::Client which provides durable subscriptions
|
|
9
|
+
class StompClient
|
|
10
|
+
include Logging
|
|
11
|
+
extend Forwardable
|
|
12
|
+
|
|
13
|
+
HOST = 'datafeeds.networkrail.co.uk'
|
|
14
|
+
PORT = '61618'
|
|
15
|
+
|
|
16
|
+
# Initialize a new stomp client.
|
|
17
|
+
# @param [RailFeeds::NetworkRail::Credentials] credentials
|
|
18
|
+
# The credentials for connecting to the feed.
|
|
19
|
+
# @param [Logger, nil] logger
|
|
20
|
+
# The logger for outputting evetns, if nil the global logger will be used.
|
|
21
|
+
def initialize(credentials: Credentials, logger: nil)
|
|
22
|
+
@credentials = credentials
|
|
23
|
+
self.logger = logger unless logger.nil?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# rubocop:disable Metrics/MethodLength
|
|
27
|
+
# Connect to the network rail server.
|
|
28
|
+
def connect
|
|
29
|
+
return if @client && client.open?
|
|
30
|
+
client_options = {
|
|
31
|
+
hosts: [{
|
|
32
|
+
host: HOST,
|
|
33
|
+
port: PORT,
|
|
34
|
+
login: @credentials.username,
|
|
35
|
+
password: @credentials.password
|
|
36
|
+
}],
|
|
37
|
+
connect_headers: {
|
|
38
|
+
'host' => HOST,
|
|
39
|
+
'client-id' => @credentials.username,
|
|
40
|
+
'accept-version' => '1.1',
|
|
41
|
+
'heart-beat' => '5000,10000'
|
|
42
|
+
},
|
|
43
|
+
logger: logger
|
|
44
|
+
}
|
|
45
|
+
@client = Stomp::Client.new client_options
|
|
46
|
+
end
|
|
47
|
+
# rubocop:enable Metrics/MethodLength
|
|
48
|
+
|
|
49
|
+
# Disconnect from the network rail server.
|
|
50
|
+
def disconnect
|
|
51
|
+
return if @client.nil?
|
|
52
|
+
@client.close
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Subscribe to a topic.
|
|
56
|
+
# Will connect to the server if required.
|
|
57
|
+
# Must be passed a block which will be called with each message received.
|
|
58
|
+
# @param [String, #to_s] topic
|
|
59
|
+
# The topic to subscribe to (e.g. "TSR_WESS_ROUTE" or "TD_ALL_SIG_AREA").
|
|
60
|
+
# @param [Hash] headers
|
|
61
|
+
# Extra headers to pass to the server.
|
|
62
|
+
def subscribe(topic, headers = {}, &block)
|
|
63
|
+
connect if @client.nil? || @client.closed?
|
|
64
|
+
headers['activemq.subscriptionName'] ||= "#{::Socket.gethostname}+#{topic}"
|
|
65
|
+
headers['id'] ||= @client.uuid
|
|
66
|
+
headers['ack'] ||= 'client'
|
|
67
|
+
@client.subscribe "/topic/#{topic}", headers, &block
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def_delegators :@client, :ack, :acknowledge, :nack, :unreceive,
|
|
71
|
+
:create_error_handler, :open?, :closed?, :join, :running?,
|
|
72
|
+
:begin, :abort, :commit, :unsubscribe, :uuid, :poll,
|
|
73
|
+
:hbsend_interval, :hbrecv_interval,
|
|
74
|
+
:hbsend_count, :hbrecv_count
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'network_rail/credentials'
|
|
4
|
+
require_relative 'network_rail/http_client'
|
|
5
|
+
require_relative 'network_rail/stomp_client'
|
|
6
|
+
require_relative 'network_rail/corpus'
|
|
7
|
+
require_relative 'network_rail/schedule'
|
|
8
|
+
require_relative 'network_rail/smart'
|
|
9
|
+
|
|
10
|
+
module RailFeeds
|
|
11
|
+
module NetworkRail # :nodoc:
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Add alias for module
|
|
16
|
+
::NetRailFeeds = RailFeeds::NetworkRail
|
data/lib/rail_feeds.rb
ADDED
data/rail_feeds.gemspec
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
|
4
|
+
require File.join(File.dirname(__FILE__), 'lib', 'rail_feeds', 'version')
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |s|
|
|
7
|
+
s.name = 'rail_feeds'
|
|
8
|
+
s.license = 'BSD 3 clause'
|
|
9
|
+
s.version = RailFeeds::Version
|
|
10
|
+
s.authors = ['Robert Gauld']
|
|
11
|
+
s.email = ['robert@robertgauld.co.uk']
|
|
12
|
+
s.homepage = 'https://github.com/robertgauld/rail_feeds'
|
|
13
|
+
s.summary = 'Make use of the various open data rails feeds in the UK.'
|
|
14
|
+
s.description = 'Make use of the various open data rails feeds in the UK. Currently only some from Network Rail.'
|
|
15
|
+
|
|
16
|
+
s.files = `git ls-files`.split("\n")
|
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
|
19
|
+
s.require_paths = ['lib']
|
|
20
|
+
|
|
21
|
+
s.add_dependency 'stomp', '~> 1.4'
|
|
22
|
+
|
|
23
|
+
s.add_development_dependency 'coveralls', '~> 0.7'
|
|
24
|
+
s.add_development_dependency 'guard-rspec', '~> 4.2', '>= 4.2.5'
|
|
25
|
+
s.add_development_dependency 'guard-rubocop', '~> 1.3'
|
|
26
|
+
s.add_development_dependency 'rake', '~> 12.0'
|
|
27
|
+
s.add_development_dependency 'rb-inotify', '~> 0.9'
|
|
28
|
+
s.add_development_dependency 'rspec', '>= 3.7', '< 4'
|
|
29
|
+
s.add_development_dependency 'rubocop', '~> 0.57.1'
|
|
30
|
+
s.add_development_dependency 'simplecov', '~> 0.7'
|
|
31
|
+
s.add_development_dependency 'timecop', '~> 0.5'
|
|
32
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
|
|
3
|
+
- - :on_header
|
|
4
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Header::CIF
|
|
5
|
+
current_file_reference: DFROC2Q
|
|
6
|
+
update_indicator: F
|
|
7
|
+
extracted_at: 2018-06-18 19:45:00
|
|
8
|
+
start_date: 2018-06-18
|
|
9
|
+
end_date: 2019-06-17
|
|
10
|
+
|
|
11
|
+
- - :on_tiploc_create
|
|
12
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Tiploc
|
|
13
|
+
tiploc: '1'
|
|
14
|
+
- - :on_tiploc_create
|
|
15
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Tiploc
|
|
16
|
+
tiploc: '2'
|
|
17
|
+
- - :on_tiploc_create
|
|
18
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Tiploc
|
|
19
|
+
tiploc: '3'
|
|
20
|
+
|
|
21
|
+
- - :on_association_create
|
|
22
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Association
|
|
23
|
+
tiploc: '1'
|
|
24
|
+
main_location_suffix: 'a'
|
|
25
|
+
category: JJ
|
|
26
|
+
days: [true, true, true, true, true, false, false]
|
|
27
|
+
- - :on_association_create
|
|
28
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Association
|
|
29
|
+
tiploc: '2'
|
|
30
|
+
main_location_suffix: 'b'
|
|
31
|
+
category: JJ
|
|
32
|
+
days: [true, true, true, true, true, true, false, false]
|
|
33
|
+
- - :on_association_create
|
|
34
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Association
|
|
35
|
+
tiploc: '3'
|
|
36
|
+
main_location_suffix: 'c'
|
|
37
|
+
category: JJ
|
|
38
|
+
days: [true, true, true, true, true, false, false]
|
|
39
|
+
|
|
40
|
+
- - :on_train_schedule_create
|
|
41
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::TrainSchedule
|
|
42
|
+
uid: 1
|
|
43
|
+
signalling_headcode: '1A11'
|
|
44
|
+
days: [true, true, true, true, true, false, false]
|
|
45
|
+
journey: []
|
|
46
|
+
- - :on_train_schedule_create
|
|
47
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::TrainSchedule
|
|
48
|
+
uid: 2
|
|
49
|
+
signalling_headcode: '2B22'
|
|
50
|
+
days: [true, true, true, true, true, false, false]
|
|
51
|
+
journey: []
|
|
52
|
+
- - :on_train_schedule_create
|
|
53
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::TrainSchedule
|
|
54
|
+
uid: 3
|
|
55
|
+
signalling_headcode: '3C33'
|
|
56
|
+
days: [true, true, true, true, true, false, false]
|
|
57
|
+
journey: []
|
|
58
|
+
|
|
59
|
+
- - :on_trailer
|
|
60
|
+
-
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
---
|
|
2
|
+
:last_header: !ruby/object:RailFeeds::NetworkRail::Schedule::Header::CIF
|
|
3
|
+
mainframe_identity: mainframe
|
|
4
|
+
extracted_at: 2018-06-14 19:43:37 +00:00
|
|
5
|
+
current_file_reference: starting-update
|
|
6
|
+
last_file_reference:
|
|
7
|
+
update_indicator: U
|
|
8
|
+
version: a
|
|
9
|
+
start_date: 2018-06-14
|
|
10
|
+
end_date: 2019-06-13
|
|
11
|
+
|
|
12
|
+
:associations:
|
|
13
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Association
|
|
14
|
+
main_train_uid: 1
|
|
15
|
+
associated_train_uid: 2
|
|
16
|
+
category: JJ
|
|
17
|
+
start_date: 2018-06-14
|
|
18
|
+
end_date: 2019-06-13
|
|
19
|
+
date_indicator: S
|
|
20
|
+
days: [true, true, true, true, true, true, false, false]
|
|
21
|
+
tiploc: 1
|
|
22
|
+
base_location_suffix: a
|
|
23
|
+
association_location_suffix: b
|
|
24
|
+
type: O
|
|
25
|
+
stp_indicator: S
|
|
26
|
+
transaction_type: N
|
|
27
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Association
|
|
28
|
+
main_train_uid: 3
|
|
29
|
+
associated_train_uid: 4
|
|
30
|
+
category: VV
|
|
31
|
+
start_date: 2018-06-14
|
|
32
|
+
end_date: 2019-06-13
|
|
33
|
+
date_indicator: S
|
|
34
|
+
days: [true, true, true, true, true, true, false, false]
|
|
35
|
+
tiploc: 2
|
|
36
|
+
base_location_suffix: a
|
|
37
|
+
association_location_suffix: b
|
|
38
|
+
type: O
|
|
39
|
+
stp_indicator: S
|
|
40
|
+
transaction_type: N
|
|
41
|
+
|
|
42
|
+
:tiplocs:
|
|
43
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Tiploc
|
|
44
|
+
tiploc: '1'
|
|
45
|
+
nlc: 1
|
|
46
|
+
nlc_check_char: a
|
|
47
|
+
nlc_description: Nlc 1
|
|
48
|
+
tps_description: Tps 1
|
|
49
|
+
stanox: 1
|
|
50
|
+
crs: 1
|
|
51
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Tiploc
|
|
52
|
+
tiploc: '2'
|
|
53
|
+
nlc: 2
|
|
54
|
+
nlc_check_char: b
|
|
55
|
+
nlc_description: Nlc 2
|
|
56
|
+
tps_description: Tps 2
|
|
57
|
+
stanox: 2
|
|
58
|
+
crs: 2
|
|
59
|
+
|
|
60
|
+
:trains:
|
|
61
|
+
'1':
|
|
62
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::TrainSchedule
|
|
63
|
+
journey:
|
|
64
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::TrainSchedule::Location::Origin
|
|
65
|
+
scheduled_departure: '1111'
|
|
66
|
+
public_departure: '1111'
|
|
67
|
+
tiploc_with_suffix: 1
|
|
68
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::TrainSchedule::Location::Terminating
|
|
69
|
+
scheduled_arrival: '2222'
|
|
70
|
+
public_arrival: '2222'
|
|
71
|
+
tiploc_with_suffix: 2
|
|
72
|
+
uid: 1
|
|
73
|
+
category:
|
|
74
|
+
status:
|
|
75
|
+
stp_indicator:
|
|
76
|
+
portion_id:
|
|
77
|
+
reservation_headcode:
|
|
78
|
+
signalling_headcode: 1A11
|
|
79
|
+
service_code:
|
|
80
|
+
start_date: 2018-06-14
|
|
81
|
+
end_date: 2019-06-13
|
|
82
|
+
days: [true, true, true, true, true, true, false, false]
|
|
83
|
+
run_on_bank_holiday: ''
|
|
84
|
+
power_type: DMU
|
|
85
|
+
timing_load:
|
|
86
|
+
speed: 75
|
|
87
|
+
operating_characteristics:
|
|
88
|
+
seating_class: B
|
|
89
|
+
sleeping_class:
|
|
90
|
+
reservations:
|
|
91
|
+
catering:
|
|
92
|
+
branding:
|
|
93
|
+
uic_code:
|
|
94
|
+
atoc_code:
|
|
95
|
+
applicable_timetable: Y
|
|
96
|
+
transaction_type: N
|
|
97
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::TrainSchedule
|
|
98
|
+
journey:
|
|
99
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::TrainSchedule::Location::Origin
|
|
100
|
+
scheduled_departure: '1111'
|
|
101
|
+
public_departure: '1111'
|
|
102
|
+
tiploc_with_suffix: 2
|
|
103
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::TrainSchedule::Location::Terminating
|
|
104
|
+
scheduled_arrival: '2222'
|
|
105
|
+
public_arrival: '2222'
|
|
106
|
+
tiploc_with_suffix: 1
|
|
107
|
+
uid: 1
|
|
108
|
+
category:
|
|
109
|
+
status:
|
|
110
|
+
stp_indicator:
|
|
111
|
+
portion_id:
|
|
112
|
+
reservation_headcode:
|
|
113
|
+
signalling_headcode: 1A11
|
|
114
|
+
service_code:
|
|
115
|
+
start_date: 2018-06-14
|
|
116
|
+
end_date: 2019-06-13
|
|
117
|
+
days: [true, true, true, true, true, true, false, false]
|
|
118
|
+
run_on_bank_holiday: ''
|
|
119
|
+
power_type: DMU
|
|
120
|
+
timing_load:
|
|
121
|
+
speed: 75
|
|
122
|
+
operating_characteristics:
|
|
123
|
+
seating_class: B
|
|
124
|
+
sleeping_class:
|
|
125
|
+
reservations:
|
|
126
|
+
catering:
|
|
127
|
+
branding:
|
|
128
|
+
uic_code:
|
|
129
|
+
atoc_code:
|
|
130
|
+
applicable_timetable: Y
|
|
131
|
+
transaction_type: N
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
|
|
3
|
+
- - :on_header
|
|
4
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Header::CIF
|
|
5
|
+
current_file_reference: DFROC1N
|
|
6
|
+
previous_file_reference: DFROC1M
|
|
7
|
+
update_indicator: U
|
|
8
|
+
extracted_at: 2018-06-21 19:45:00
|
|
9
|
+
start_date: 2018-06-21
|
|
10
|
+
end_date: 2019-06-20
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
|
|
3
|
+
- - :on_header
|
|
4
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Header::CIF
|
|
5
|
+
current_file_reference: DFROC1M
|
|
6
|
+
previous_file_reference: DFROC1L
|
|
7
|
+
update_indicator: U
|
|
8
|
+
extracted_at: 2018-06-19 19:45:00
|
|
9
|
+
start_date: 2018-06-20
|
|
10
|
+
end_date: 2019-06-19
|
|
11
|
+
|
|
12
|
+
- - :on_trailer
|
|
13
|
+
-
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
|
|
3
|
+
- - :on_header
|
|
4
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Header::CIF
|
|
5
|
+
current_file_reference: DFROC1B
|
|
6
|
+
previous_file_reference: DFROC1A
|
|
7
|
+
update_indicator: U
|
|
8
|
+
extracted_at: 2018-06-12 19:45:00
|
|
9
|
+
start_date: 2018-06-12
|
|
10
|
+
end_date: 2019-06-11
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
|
|
3
|
+
- - :on_header
|
|
4
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Header::CIF
|
|
5
|
+
current_file_reference: DFROC1L
|
|
6
|
+
previous_file_reference: DFROC1K
|
|
7
|
+
update_indicator: U
|
|
8
|
+
extracted_at: 2018-06-18 19:45:00
|
|
9
|
+
start_date: 2018-06-19
|
|
10
|
+
end_date: 2019-06-18
|
|
11
|
+
|
|
12
|
+
# Insert new tiploc
|
|
13
|
+
- - :on_tiploc_create
|
|
14
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Tiploc
|
|
15
|
+
tiploc: '4'
|
|
16
|
+
# Delete existing tiploc
|
|
17
|
+
- - :on_tiploc_delete
|
|
18
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Tiploc
|
|
19
|
+
tiploc: '2'
|
|
20
|
+
# Delete nonexisting tiploc
|
|
21
|
+
- - :on_tiploc_delete
|
|
22
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Tiploc
|
|
23
|
+
tiploc: '22'
|
|
24
|
+
# Amend existing tiploc
|
|
25
|
+
- - :on_tiploc_update
|
|
26
|
+
- - '3'
|
|
27
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Tiploc
|
|
28
|
+
tiploc: '3a'
|
|
29
|
+
# Amend nonexisting tiploc
|
|
30
|
+
- - :on_tiploc_update
|
|
31
|
+
- - '5'
|
|
32
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Tiploc
|
|
33
|
+
tiploc: '5a'
|
|
34
|
+
|
|
35
|
+
# New association
|
|
36
|
+
- - :on_association_create
|
|
37
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Association
|
|
38
|
+
tiploc: '4'
|
|
39
|
+
main_location_suffix: 'd'
|
|
40
|
+
category: JJ
|
|
41
|
+
days: [true, true, true, true, true, false, false]
|
|
42
|
+
# Delete existing association
|
|
43
|
+
- - :on_association_delete
|
|
44
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Association
|
|
45
|
+
tiploc: '2'
|
|
46
|
+
main_location_suffix: 'b'
|
|
47
|
+
# Delete nonexisting association
|
|
48
|
+
- - :on_association_delete
|
|
49
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Association
|
|
50
|
+
tiploc: '22'
|
|
51
|
+
main_location_suffix: 'D'
|
|
52
|
+
# Revise existing association
|
|
53
|
+
- - :on_association_update
|
|
54
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Association
|
|
55
|
+
tiploc: '3'
|
|
56
|
+
main_location_suffix: 'c'
|
|
57
|
+
category: VV
|
|
58
|
+
days: [true, true, true, true, true, false, false]
|
|
59
|
+
# Revise nonexisting association
|
|
60
|
+
- - :on_association_update
|
|
61
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::Association
|
|
62
|
+
tiploc: '5'
|
|
63
|
+
main_location_suffix: 'e'
|
|
64
|
+
category: JJ
|
|
65
|
+
days: [true, true, true, true, true, false, false]
|
|
66
|
+
|
|
67
|
+
# New train
|
|
68
|
+
- - :on_train_schedule_create
|
|
69
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::TrainSchedule
|
|
70
|
+
uid: 4
|
|
71
|
+
signalling_headcode: '4D44'
|
|
72
|
+
days: [true, true, true, true, true, false, false]
|
|
73
|
+
journey:
|
|
74
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::TrainSchedule::Location::Origin
|
|
75
|
+
scheduled_departure: '1111'
|
|
76
|
+
public_departure: '1111'
|
|
77
|
+
tiploc: 1
|
|
78
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::TrainSchedule::ChangeEnRoute
|
|
79
|
+
tiploc: 2
|
|
80
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::TrainSchedule::Location::Intermediate
|
|
81
|
+
scheduled_departure: '1111'
|
|
82
|
+
public_departure: '1111'
|
|
83
|
+
tiploc: 2
|
|
84
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::TrainSchedule::Location::Terminating
|
|
85
|
+
scheduled_arrival: '2222'
|
|
86
|
+
public_arrival: '2222'
|
|
87
|
+
tiploc: 3
|
|
88
|
+
# Delete existing train
|
|
89
|
+
- - :on_train_schedule_delete
|
|
90
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::TrainSchedule
|
|
91
|
+
uid: 2
|
|
92
|
+
# Delete nonexisting train
|
|
93
|
+
- - :on_train_schedule_delete
|
|
94
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::TrainSchedule
|
|
95
|
+
uid: 22
|
|
96
|
+
# Revise existing train
|
|
97
|
+
- - :on_train_schedule_update
|
|
98
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::TrainSchedule
|
|
99
|
+
uid: 3
|
|
100
|
+
signalling_headcode: '3c33'
|
|
101
|
+
days: [true, true, true, true, true, false, false]
|
|
102
|
+
journey: []
|
|
103
|
+
# Revise nonexisting train
|
|
104
|
+
- - :on_train_schedule_update
|
|
105
|
+
- !ruby/object:RailFeeds::NetworkRail::Schedule::TrainSchedule
|
|
106
|
+
uid: 5
|
|
107
|
+
signalling_headcode: '5E55'
|
|
108
|
+
days: [true, true, true, true, true, false, false]
|
|
109
|
+
journey: []
|
|
110
|
+
|
|
111
|
+
- - :on_trailer
|
|
112
|
+
-
|