module RailFeeds::NetworkRail::SMART

rubocop:disable Metrics/ModuleLength A module for getting information out of the SMART data.

Constants

Berth
Step

Public Class Methods

build_berths(steps) click to toggle source

rubocop:disable Metrics/AbcSize rubocop:disable Metrics/MethodLength Generate an berth data from step data. You'll get an array of berths which list the steps into and out of them, which in turn have references to other (via the to_berth attribute) to other berths. @param [Array<RailFeeds::NetworkRail::SMART::Step] steps

The steps to build the berth information from.

@return [Hash{String=>Hash{String=>RailFeeds::NetworkRail::SMART::Step}}

Nested hashes which take a String for the td_area, then a String for

the berth.id (from either step.from_berth or step.to_berth) to get a specific berth.

# File lib/rail_feeds/network_rail/smart.rb, line 80
def self.build_berths(steps)
  berths = Hash.new do |hash, key|
    hash[key] = Hash.new do |hash2, key2|
      hash2[key2] = Berth.new nil, Set.new, Set.new, Set.new, Set.new
    end
  end

  steps.each do |step|
    next if step.event_direction.nil?

    # from_berth -> step -> to_berth   --->  up
    from_berth = berths.dig(step.td_area, step.from_berth)
    to_berth = berths.dig(step.td_area, step.to_berth)

    from_berth.id ||= step.from_berth
    to_berth.id ||= step.to_berth

    from_berth.send("#{step.to_direction}_steps").add step
    to_berth.send("#{step.from_direction}_steps").add step
    from_berth.send("#{step.to_direction}_berths").add step.to_berth
  end

  # Convert sets to arrays
  berths.each do |_area, hash|
    hash.each do |_id, value|
      value.up_steps = value.up_steps.to_a
      value.down_steps = value.down_steps.to_a
      value.up_berths = value.up_berths.to_a
      value.down_berths = value.down_berths.to_a
    end
  end
end
download(file, credentials = Credentials) click to toggle source

Download the current SMART data. @param [RailFeeds::NetworkRail::Credentials] credentials @param [String] file

The path to the file to save the .json.gz download in.
# File lib/rail_feeds/network_rail/smart.rb, line 33
def self.download(file, credentials = Credentials)
  client = HTTPClient.new(credentials: credentials)
  client.download 'ntrod/SupportingFileAuthenticate?type=SMART', file
end
fetch(credentials = Credentials) click to toggle source

Fetch the current SMART data. @param [RailFeeds::NetworkRail::Credentials] credentials @return [IO]

# File lib/rail_feeds/network_rail/smart.rb, line 41
def self.fetch(credentials = Credentials)
  client = HTTPClient.new(credentials: credentials)
  client.fetch 'ntrod/SupportingFileAuthenticate?type=SMART'
end
fetch_data(credentials = Credentials) click to toggle source

Load SMART data from the internet. @param [RailFeeds::NetworkRail::Credentials] credentials

The credentials to authenticate with.

@return [Array<RailFeeds::NetworkRail::SMART::Step>]

# File lib/rail_feeds/network_rail/smart.rb, line 61
def self.fetch_data(credentials = Credentials)
  client = HTTPClient.new(credentials: credentials)
  client.fetch_unzipped('ntrod/SupportingFileAuthenticate?type=SMART') do |file|
    break parse_json file.read
  end
end
load_file(file) click to toggle source

Load SMART data from either a .json or .json.gz file. @param [String] file The path of the file to open. @return [Array<RailFeeds::NetworkRail::SMART::Step>]

# File lib/rail_feeds/network_rail/smart.rb, line 49
def self.load_file(file)
  Zlib::GzipReader.open(file) do |gz|
    parse_json gz.read
  end
rescue Zlib::GzipFile::Error
  parse_json File.read(file)
end

Private Class Methods

event_direction(value) click to toggle source
# File lib/rail_feeds/network_rail/smart.rb, line 161
def self.event_direction(value)
  return :up if value.eql?('A') || value.eql?('B')
  return :down if value.eql?('C') || value.eql?('D')

  nil
end
event_type(value) click to toggle source
# File lib/rail_feeds/network_rail/smart.rb, line 153
def self.event_type(value)
  return :arrive if value.eql?('A') || value.eql?('C')
  return :depart if value.eql?('B') || value.eql?('D')

  nil
end
nilify(value) click to toggle source

rubocop:enable Metrics/AbcSize rubocop:enable Metrics/MethodLength

# File lib/rail_feeds/network_rail/smart.rb, line 146
def self.nilify(value)
  return nil if value.nil? || value.empty?

  value
end
parse_json(json) click to toggle source

rubocop:disable Metrics/AbcSize rubocop:disable Metrics/MethodLength

# File lib/rail_feeds/network_rail/smart.rb, line 119
def self.parse_json(json)
  data = JSON.parse json
  data['BERTHDATA'].map do |item|
    Step.new(
      nilify(item['TD']&.strip),
      nilify(item['FROMBERTH']&.strip),
      nilify(item['TOBERTH']&.strip),
      step_type(item['STEPTYPE']),
      event_direction(item['EVENT']),
      nilify(item['FROMLINE']&.strip),
      nilify(item['TOLINE']&.strip),
      (item['BERTHOFFSET']&.to_i || 0),
      nilify(item['PLATFORM']&.strip),
      event_type(item['EVENT']),
      nilify(item['ROUTE']&.strip),
      nilify(item['STANOX']&.strip)&.to_i,
      nilify(item['STANME']&.strip),
      nilify(item['COMMENT']&.strip)
    )
    # berths[step.from_berth].up_steps.push ....
    # berths[step.to_berth].down_steps.push ....
  end
end
step_type(value) click to toggle source

rubocop:disable Metrics/CyclomaticComplexity

# File lib/rail_feeds/network_rail/smart.rb, line 170
def self.step_type(value)
  case value
  when 'B' then :between
  when 'F' then :from
  when 'T' then :to
  when 'D' then :intermediate_first
  when 'E' then :intermediate
  when 'C' then :clearout
  when 'I' then :interpose
  end
end