class AIPP::LF::AD13

Aerodromes

Constants

DEPENDS
ID_LESS_AIRPORTS

Map names of id-less airports to unofficial ids

PURPOSES

Public Instance Methods

parse() click to toggle source
   # File lib/aipp/regions/LF/AD-1.3.rb
36 def parse
37   ad2_exists = false
38   tbody = prepare(html: read).css('tbody').first   # skip altiports
39   tbody.css('tr').to_enum.with_index(1).each do |tr, index|
40     if tr.attr(:id).match?(/-TXT_NAME-/)
41       add @airport if @airport && !ad2_exists
42       @airport = airport_from tr
43       verbose_info "Parsing #{@airport.id}"
44       ad2_exists = false
45       if airport = find_by(:airport, id: @airport.id).first
46         ad2_exists = true
47         @airport = airport
48       end
49       add_usage_limitations_from tr
50       next
51     end
52     @airport.add_runway(runway_from(tr)) unless ad2_exists
53   rescue => error
54     warn("error parsing #{@airport.id} at ##{index}: #{error.message}", pry: error)
55   end
56   add @airport if @airport && !ad2_exists
57 end

Private Instance Methods

add_usage_limitations_from(tr) click to toggle source
    # File lib/aipp/regions/LF/AD-1.3.rb
 77 def add_usage_limitations_from(tr)
 78   raw_limitation = tr.css('td:nth-of-type(8)').text.cleanup.downcase
 79   raw_conditions = tr.css('td:nth-of-type(6)').text.cleanup.downcase.split(%r([\s/]+))
 80   limitation = case raw_limitation
 81     when /ouv.+cap|milit/ then :permitted
 82     when /usa.+restr|priv/ then :reservation_required
 83   end
 84   @airport.add_usage_limitation(type: limitation) do |l|
 85     (%w(s ns p) & raw_conditions).each do |raw_purpose|
 86       l.add_condition do |c|
 87         c.realm = raw_limitation.match?(/milit/) ? :military : :civilian
 88         if (%w(intl ntl) - raw_conditions).empty?
 89           c.origin = :any
 90         else
 91           c.origin = :national if raw_conditions.include?('ntl')
 92           c.origin = :international if raw_conditions.include?('intl')
 93         end
 94         if (%w(ifr vfr) - raw_conditions).empty?
 95           c.rule = :ifr_and_vfr
 96         else
 97           c.rule = :ifr if raw_conditions.include?('ifr')
 98           c.rule = :vfr if raw_conditions.include?('vfr')
 99         end
100         c.purpose = PURPOSES[raw_purpose]
101       end
102     end
103     l.remarks = "Usage restreint (voir VAC) / restricted use (see VAC)" if raw_limitation.match?(/usa.+restr/)
104     l.remarks = "Propriété privée / privately owned" if raw_limitation.match?(/priv/)
105   end
106 end
airport_from(tr) click to toggle source
   # File lib/aipp/regions/LF/AD-1.3.rb
61       def airport_from(tr)
62         tds = tr.css('td')
63         id = tds[0].text.strip.blank_to_nil || ID_LESS_AIRPORTS.fetch(tds[1].text.strip)
64         AIXM.airport(
65           source: source(position: tr.line),
66           organisation: organisation_lf,   # TODO: not yet implemented
67           id: id,
68           name: tds[1].text.strip,
69           xy: xy_from(tds[3].text)
70         ).tap do |airport|
71           airport.z = AIXM.z(tds[4].text.strip.to_i, :qnh)
72           airport.declination = tds[2].text.remove('°').strip.to_f
73 #         airport.transition_z = AIXM.z(5000, :qnh)   # TODO: default - exceptions exist
74         end
75       end
displaced_thresholds_from(td) click to toggle source
    # File lib/aipp/regions/LF/AD-1.3.rb
139 def displaced_thresholds_from(td)
140   values = td.text.strip.split
141   case values.count
142     when 1 then []
143     when 2 then [AIXM.xy(lat: values[0], long: values[1]), nil]
144     when 3 then [nil, AIXM.xy(lat: values[1], long: values[2])]
145     when 4 then [AIXM.xy(lat: values[0], long: values[1]), AIXM.xy(lat: values[2], long: values[3])]
146     else fail "cannot parse displaced thresholds"
147   end
148 end
runway_from(tr) click to toggle source
    # File lib/aipp/regions/LF/AD-1.3.rb
108 def runway_from(tr)
109   tds = tr.css('td')
110   AIXM.runway(
111     name: tds[0].text.strip.split.join('/')
112   ).tap do |runway|
113     @runway = runway   # TODO: needed for now for surface composition patches to work
114     bidirectional = runway.name.include? '/'
115     runway.length = AIXM.d(tds[1].css('span[id$="VAL_LEN"]').text.to_i, :m)
116     runway.width = AIXM.d(tds[1].css('span[id$="VAL_WID"]').text.to_i, :m)
117     unless (text = tds[1].css('span[id*="SURFACE"]').text.compact).blank?
118       surface = SURFACES.metch(text)
119       runway.surface.composition = surface[:composition]
120       runway.surface.preparation = surface[:preparation]
121       runway.surface.remarks = surface[:remarks]
122     end
123     runway.remarks = tds[7].text.cleanup.blank_to_nil
124     values = tds[2].text.remove('°').strip.split
125     runway.forth.geographic_orientation = AIXM.a(values.first.to_i)
126     runway.back.geographic_orientation = AIXM.a(values.last.to_i) if bidirectional
127     parts = tds[3].text.strip.split(/\n\s+\n\s+/, 2)
128     runway.forth.xy = (xy_from(parts[0]) unless parts[0].blank?)
129     runway.back.xy = (xy_from(parts[1]) unless parts[1].blank?) if bidirectional
130     values = tds[4].text.strip.split
131     runway.forth.z = AIXM.z(values.first.to_i, :qnh)
132     runway.back.z = AIXM.z(values.last.to_i, :qnh) if bidirectional
133     displaced_thresholds = displaced_thresholds_from(tds[5])
134     runway.forth.displaced_threshold = displaced_thresholds.first
135     runway.back.displaced_threshold = displaced_thresholds.last if bidirectional
136   end
137 end