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.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +31 -0
  5. data/.travis.yml +26 -0
  6. data/CHANGELOG.md +3 -0
  7. data/Gemfile +6 -0
  8. data/Guardfile +25 -0
  9. data/LICENSE.md +32 -0
  10. data/README.md +77 -0
  11. data/Rakefile +3 -0
  12. data/doc/guides/Logging.md +13 -0
  13. data/doc/guides/Network Rail/CORPUS.md +34 -0
  14. data/doc/guides/Network Rail/SMART.md +39 -0
  15. data/doc/guides/Network Rail/Schedule.md +138 -0
  16. data/file +0 -0
  17. data/lib/rail_feeds/credentials.rb +45 -0
  18. data/lib/rail_feeds/logging.rb +51 -0
  19. data/lib/rail_feeds/network_rail/corpus.rb +77 -0
  20. data/lib/rail_feeds/network_rail/credentials.rb +22 -0
  21. data/lib/rail_feeds/network_rail/http_client.rb +57 -0
  22. data/lib/rail_feeds/network_rail/schedule/association.rb +208 -0
  23. data/lib/rail_feeds/network_rail/schedule/data.rb +215 -0
  24. data/lib/rail_feeds/network_rail/schedule/days.rb +95 -0
  25. data/lib/rail_feeds/network_rail/schedule/fetcher.rb +193 -0
  26. data/lib/rail_feeds/network_rail/schedule/header/cif.rb +102 -0
  27. data/lib/rail_feeds/network_rail/schedule/header/json.rb +79 -0
  28. data/lib/rail_feeds/network_rail/schedule/header.rb +22 -0
  29. data/lib/rail_feeds/network_rail/schedule/parser/cif.rb +141 -0
  30. data/lib/rail_feeds/network_rail/schedule/parser/json.rb +87 -0
  31. data/lib/rail_feeds/network_rail/schedule/parser.rb +108 -0
  32. data/lib/rail_feeds/network_rail/schedule/stp_indicator.rb +72 -0
  33. data/lib/rail_feeds/network_rail/schedule/tiploc.rb +100 -0
  34. data/lib/rail_feeds/network_rail/schedule/train_schedule/change_en_route.rb +158 -0
  35. data/lib/rail_feeds/network_rail/schedule/train_schedule/location/intermediate.rb +119 -0
  36. data/lib/rail_feeds/network_rail/schedule/train_schedule/location/origin.rb +91 -0
  37. data/lib/rail_feeds/network_rail/schedule/train_schedule/location/terminating.rb +72 -0
  38. data/lib/rail_feeds/network_rail/schedule/train_schedule/location.rb +76 -0
  39. data/lib/rail_feeds/network_rail/schedule/train_schedule.rb +392 -0
  40. data/lib/rail_feeds/network_rail/schedule.rb +33 -0
  41. data/lib/rail_feeds/network_rail/smart.rb +186 -0
  42. data/lib/rail_feeds/network_rail/stomp_client.rb +77 -0
  43. data/lib/rail_feeds/network_rail.rb +16 -0
  44. data/lib/rail_feeds/version.rb +14 -0
  45. data/lib/rail_feeds.rb +10 -0
  46. data/rail_feeds.gemspec +32 -0
  47. data/spec/fixtures/network_rail/schedule/data/full.yaml +60 -0
  48. data/spec/fixtures/network_rail/schedule/data/starting.yaml +131 -0
  49. data/spec/fixtures/network_rail/schedule/data/update-gap.yaml +10 -0
  50. data/spec/fixtures/network_rail/schedule/data/update-next.yaml +13 -0
  51. data/spec/fixtures/network_rail/schedule/data/update-old.yaml +10 -0
  52. data/spec/fixtures/network_rail/schedule/data/update.yaml +112 -0
  53. data/spec/fixtures/network_rail/schedule/parser/train_create.json +1 -0
  54. data/spec/fixtures/network_rail/schedule/parser/train_delete.json +1 -0
  55. data/spec/fixtures/network_rail/schedule/train_schedule/json-data.yaml +67 -0
  56. data/spec/rail_feeds/credentials_spec.rb +46 -0
  57. data/spec/rail_feeds/logging_spec.rb +81 -0
  58. data/spec/rail_feeds/network_rail/corpus_spec.rb +92 -0
  59. data/spec/rail_feeds/network_rail/credentials_spec.rb +22 -0
  60. data/spec/rail_feeds/network_rail/http_client_spec.rb +88 -0
  61. data/spec/rail_feeds/network_rail/schedule/association_spec.rb +205 -0
  62. data/spec/rail_feeds/network_rail/schedule/data_spec.rb +219 -0
  63. data/spec/rail_feeds/network_rail/schedule/days_shared.rb +99 -0
  64. data/spec/rail_feeds/network_rail/schedule/days_spec.rb +4 -0
  65. data/spec/rail_feeds/network_rail/schedule/fetcher_spec.rb +228 -0
  66. data/spec/rail_feeds/network_rail/schedule/header/cif_spec.rb +72 -0
  67. data/spec/rail_feeds/network_rail/schedule/header/json_spec.rb +51 -0
  68. data/spec/rail_feeds/network_rail/schedule/header_spec.rb +19 -0
  69. data/spec/rail_feeds/network_rail/schedule/parser/cif_spec.rb +197 -0
  70. data/spec/rail_feeds/network_rail/schedule/parser/json_spec.rb +172 -0
  71. data/spec/rail_feeds/network_rail/schedule/parser_spec.rb +34 -0
  72. data/spec/rail_feeds/network_rail/schedule/stp_indicator_shared.rb +49 -0
  73. data/spec/rail_feeds/network_rail/schedule/stp_indicator_spec.rb +4 -0
  74. data/spec/rail_feeds/network_rail/schedule/tiploc_spec.rb +77 -0
  75. data/spec/rail_feeds/network_rail/schedule/train_schedule/change_en_route_spec.rb +121 -0
  76. data/spec/rail_feeds/network_rail/schedule/train_schedule/location/intermediate_spec.rb +95 -0
  77. data/spec/rail_feeds/network_rail/schedule/train_schedule/location/origin_spec.rb +87 -0
  78. data/spec/rail_feeds/network_rail/schedule/train_schedule/location/terminating_spec.rb +81 -0
  79. data/spec/rail_feeds/network_rail/schedule/train_schedule/location_spec.rb +35 -0
  80. data/spec/rail_feeds/network_rail/schedule/train_schedule_spec.rb +284 -0
  81. data/spec/rail_feeds/network_rail/schedule_spec.rb +41 -0
  82. data/spec/rail_feeds/network_rail/smart_spec.rb +194 -0
  83. data/spec/rail_feeds/network_rail/stomp_client_spec.rb +151 -0
  84. data/spec/rail_feeds/network_rail_spec.rb +7 -0
  85. data/spec/rail_feeds_spec.rb +11 -0
  86. data/spec/spec_helper.rb +47 -0
  87. 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
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailFeeds
4
+ # Holds information on the current gem version.
5
+ class Version
6
+ MAJOR = 0
7
+ MINOR = 0
8
+ PATCH = 1
9
+
10
+ def self.to_s
11
+ [MAJOR, MINOR, PATCH].join('.')
12
+ end
13
+ end
14
+ end
data/lib/rail_feeds.rb ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ require_relative 'rail_feeds/logging'
6
+ require_relative 'rail_feeds/credentials'
7
+ require_relative 'rail_feeds/network_rail'
8
+
9
+ module RailFeeds # :nodoc:
10
+ end
@@ -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
+ -