Module: AIPP::LF::Helpers::Base

Constant Summary collapse

VERSION =

Supported version of the XML_SIA database dump

'5'.freeze

Instance Method Summary collapse

Instance Method Details

#b_from(content) ⇒ Boolean

Convert content to boolean

Parameters:

  • content (String)

    either “oui” or “non”

Returns:

  • (Boolean)


80
81
82
83
84
85
86
# File 'lib/aipp/regions/LF/helpers/base.rb', line 80

def b_from(content)
  case content
    when 'oui' then true
    when 'non' then false
    else fail "`#{content}' is not boolean content"
  end
end

#d_from(content) ⇒ AIXM::D

Build distance from content

Parameters:

  • content (String)

    source content

Returns:

  • (AIXM::D)


119
120
121
122
# File 'lib/aipp/regions/LF/helpers/base.rb', line 119

def d_from(content)
  parts = content.split(/\s/)
  AIXM.d(parts[0].to_f, parts[1])
end

#geometry_from(content) ⇒ AIXM::Component::Geometry

Build geometry from content

Parameters:

  • content (String)

    source content

Returns:

  • (AIXM::Component::Geometry)


128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/aipp/regions/LF/helpers/base.rb', line 128

def geometry_from(content)
  AIXM.geometry.tap do |geometry|
    buffer = {}
    content.split("\n").each do |element|
      parts = element.split(',', 3).last.split(/[():,]/)
      # Write explicit geometry from previous iteration
      if (bordure_name, xy = buffer.delete(:fnt))
        border = AIPP.borders.send(bordure_name)
        geometry.add_segments border.segment(
          from_position: border.nearest(xy: xy),
          to_position: border.nearest(xy: xy_from(parts[0]))
        ).map(&:to_point)
      end
      # Write current iteration
      geometry.add_segment(
        case parts[1]
        when 'grc'
          AIXM.point(
            xy: xy_from(parts[0])
          )
        when 'rhl'
          AIXM.rhumb_line(
            xy: xy_from(parts[0])
          )
        when 'cwa', 'cca'
          AIXM.arc(
            xy: xy_from(parts[0]),
            center_xy: xy_from(parts[5]),
            clockwise: (parts[1] == 'cwa')
          )
        when 'cir'
          AIXM.circle(
            center_xy: xy_from(parts[0]),
            radius: d_from(parts[3..4].join(' '))
          )
        when 'fnt'
          bordure = AIPP.cache.bordure.at_css(%Q(Bordure[pk="#{parts[3]}"]))
          bordure_name = bordure.(:Code)
          if bordure_name.match? /:/   # explicit geometry
            AIPP.borders[bordure_name] ||= AIPP::Border.from_array([bordure.(:Geometrie).split])
            buffer[:fnt] = [bordure_name, xy_from(parts[2])]
            AIXM.point(
              xy: xy_from(parts[0])
            )
          else
            AIXM.border(   # named border
              xy: xy_from(parts[0]),
              name: bordure_name
            )
          end
        else
          fail "geometry `#{parts[1]}' not recognized"
        end
      )
    end
  end
end

#layer_from(volume_node) ⇒ AIXM::Component::Layer

Build layer from “volume” node

Parameters:

Returns:

  • (AIXM::Component::Layer)


198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/aipp/regions/LF/helpers/base.rb', line 198

def layer_from(volume_node)
  AIXM.layer(
    class: volume_node.(:Classe),
    vertical_limit: AIXM.vertical_limit(
      upper_z: z_from(value: volume_node.(:Plafond), unit: volume_node.(:PlafondRefUnite)),
      max_z: z_from(value: volume_node.(:Plafond2)),
      lower_z: z_from(value: volume_node.(:Plancher), unit: volume_node.(:PlancherRefUnite)),
      min_z: z_from(value: volume_node.(:Plancher2))
    )
  ).tap do |layer|
    layer.timetable = timetable_from(volume_node.(:HorCode))
    layer.remarks = volume_node.(:Remarque)
  end
end

#organisation_lfObject

Templates



42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/aipp/regions/LF/helpers/base.rb', line 42

def organisation_lf
  unless AIPP.cache.organisation_lf
    AIPP.cache.organisation_lf = AIXM.organisation(
      source: source(position: 1, document: "GEN-3.1"),
      name: 'FRANCE',
      type: 'S'
    ).tap do |organisation|
      organisation.id = 'LF'
    end
    add AIPP.cache.organisation_lf
  end
  AIPP.cache.organisation_lf
end

#origin_for(document) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/aipp/regions/LF/helpers/base.rb', line 24

def origin_for(document)
  sia_date = AIPP.options.airac.date.strftime('%d_%^b_%Y')   # 04_JAN_2018
  xml_date = AIPP.options.airac.date.xmlschema               # 2018-01-04
  sia_url = "https://www.sia.aviation-civile.gouv.fr/dvd/eAIP_#{sia_date}"
  case document
  when /^Obstacles$/   # obstacles spreadsheet
    AIPP::Downloader::HTTP.new(file: "#{sia_url}/FRANCE/ObstaclesDataZone1MFRANCE_#{xml_date.remove('-')}.xlsx")
  when /^VAC\-(\w+)/   # aerodrome VAC PDF
    AIPP::Downloader::HTTP.new(file: "#{sia_url}/Atlas-VAC/PDF_AIPparSSection/VAC/AD/AD-2.#{$1}.pdf")
  when /^VACH\-(\w+)/   # helipad VAC PDF
    AIPP::Downloader::HTTP.new(file: "#{sia_url}/Atlas-VAC/PDF_AIPparSSection/VACH/AD/AD-3.#{$1}.pdf")
  else   # SIA XML database dump
    AIPP::Downloader::File.new(file: "XML_SIA_#{xml_date}.xml")
  end
end

#setupObject

Mandatory Interface



13
14
15
16
17
18
19
20
21
22
# File 'lib/aipp/regions/LF/helpers/base.rb', line 13

def setup
  AIXM.config.voice_channel_separation = :any
  unless AIPP.cache.espace
    xml = read('XML_SIA')
    %i(Ad Bordure Espace Frequence Helistation NavFix Obstacle Partie RadioNav Rwy RwyLgt Service Volume).each do |table|
      AIPP.cache[table.downcase] = xml.css("#{table}S")
    end
    warn("XML_SIA database dump version mismatch") unless xml.at_css('SiaExport').attr(:Version) == VERSION
  end
end

#source(position:, part: nil, document: nil) ⇒ String

Build a source string

Parameters:

  • position (Integer)

    line on which to find the information

  • part (String) (defaults to: nil)

    override autodetected part (e.g. “ENR”)

  • document (String) (defaults to: nil)

    override autodetected document (e.g. “ENR-2.1”)

Returns:



64
65
66
67
68
69
70
71
72
73
74
# File 'lib/aipp/regions/LF/helpers/base.rb', line 64

def source(position:, part: nil, document: nil)
  document ||= 'XML_SIA'
  part ||= document.split(/-(?=\d)/).first
  [
    AIPP.options.region,
    part,
    document,
    AIPP.options.airac.date.xmlschema,
    position
  ].join('|')
end

#timetable_from(content) ⇒ AIXM::Component::Timetable

Build timetable from content

Parameters:

  • content (String)

    source content

Returns:

  • (AIXM::Component::Timetable)


190
191
192
# File 'lib/aipp/regions/LF/helpers/base.rb', line 190

def timetable_from(content)
  AIXM.timetable(code: content) if AIXM::H_RE.match? content
end

#xy_from(content) ⇒ AIXM::XY

Build coordinates from content

Parameters:

  • content (String)

    source content

Returns:

  • (AIXM::XY)


92
93
94
95
# File 'lib/aipp/regions/LF/helpers/base.rb', line 92

def xy_from(content)
  parts = content.split(/[\s,]+/)
  AIXM.xy(lat: parts[0].to_f, long: parts[1].to_f)
end

#z_from(value: nil, unit: 'ft ASFC') ⇒ AIXM::Z

Build altitude/elevation from value and unit

Parameters:

  • value (String, Numeric, nil) (defaults to: nil)

    numeric value

  • unit (String) (defaults to: 'ft ASFC')

    unit like “ft ASFC” or absolute like “SFC”

Returns:

  • (AIXM::Z)


102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/aipp/regions/LF/helpers/base.rb', line 102

def z_from(value: nil, unit: 'ft ASFC')
  if value
    case unit
      when 'SFC' then AIXM::GROUND
      when 'UNL' then AIXM::UNLIMITED
      when 'ft ASFC' then AIXM.z(value.to_i, :qfe)
      when 'ft AMSL' then AIXM.z(value.to_i, :qnh)
      when 'FL' then AIXM.z(value.to_i, :qne)
      else fail "z `#{[value, unit].join(' ')}' not recognized"
    end
  end
end