class TacviewClient::Reader::Parser

Parses an event coming out of the Tacview server when they are too complicated for simple extraction.

Not to be used directly by library users, should only be called by an instance of the Reader class

See www.tacview.net/documentation/acmi/en/ for information of the Tacview ACMI format this module is parsing @private

Constants

END_OF_FIELD
END_OF_FILE
FIELD_SEPARATOR
HEX_NUMBER
OPTIONALLY_DECIMAL_NUMBER
POSITION_SEPARATOR
POSITION_START_INDICATOR

Public Instance Methods

parse_object_update(line) click to toggle source

Parse an ACMI line associated with the update of an object.

# File lib/tacview_client/reader/parser.rb, line 26
def parse_object_update(line)
  @scanner = StringScanner.new(line)
  @result = {}

  parse_object_id

  return nil if own_vehicle_message?

  parse_lon_lat_alt
  parse_heading
  parse_fields

  @result
end

Private Instance Methods

end_of_message?() click to toggle source
# File lib/tacview_client/reader/parser.rb, line 91
def end_of_message?
  @scanner.eos?
end
own_vehicle_message?() click to toggle source

Updates without a position are always from own vehicle based on looking through samples. We don't care about these so ignore them

# File lib/tacview_client/reader/parser.rb, line 50
def own_vehicle_message?
  @scanner.peek(2) != POSITION_START_INDICATOR.source
end
parse_fields() click to toggle source
# File lib/tacview_client/reader/parser.rb, line 81
def parse_fields
  until end_of_message?
    field = @scanner.scan_until END_OF_FIELD
    field.chomp! FIELD_SEPARATOR.source

    key, value = field.split('=', 2)
    @result[key.downcase.to_sym] = value
  end
end
parse_heading() click to toggle source
# File lib/tacview_client/reader/parser.rb, line 64
def parse_heading
  return if end_of_message?

  # Check to see if the heading (9th field which is 4 more
  # separators from our current position) is present
  if @scanner.check_until(END_OF_FIELD)
             .count(POSITION_SEPARATOR.source) == 4
    # If it is then we will save that as well by skipping all the
    # text until the heading value
    @scanner.scan_until(/\|[\|\-?0-9.]*\|/)
    heading = @scanner.scan OPTIONALLY_DECIMAL_NUMBER
    @result[:heading] = BigDecimal(heading) if heading
  end

  @scanner.scan_until END_OF_FIELD
end
parse_lon_lat_alt() click to toggle source
# File lib/tacview_client/reader/parser.rb, line 54
def parse_lon_lat_alt
  @scanner.skip POSITION_START_INDICATOR

  %i[longitude latitude altitude].each do |field|
    value = @scanner.scan(OPTIONALLY_DECIMAL_NUMBER)
    @result[field] = BigDecimal(value) if value
    @scanner.skip POSITION_SEPARATOR
  end
end
parse_object_id() click to toggle source
# File lib/tacview_client/reader/parser.rb, line 43
def parse_object_id
  @result[:object_id] = @scanner.scan(HEX_NUMBER)
  @scanner.skip FIELD_SEPARATOR
end