rail_feeds 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ -