Module: AIPP::LF::Helpers::Common

Included in:
AD13, AD16, AD2, AD31, ENR21, ENR41, ENR43, ENR51, ENR55
Defined in:
lib/aipp/regions/LF/helpers/common.rb

Constant Summary collapse

BORDERS =

Map border names to OFMX

{
  'franco-allemande' => 'FRANCE_GERMANY',
  'franco-espagnole' =>  'FRANCE_SPAIN',
  'franco-italienne' => 'FRANCE_ITALY',
  'franco-suisse' => 'FRANCE_SWITZERLAND',
  'franco-luxembourgeoise' => 'FRANCE_LUXEMBOURG',
  'franco-belge' => 'BELGIUM_FRANCE',
  'germano-suisse' => 'GERMANY_SWITZERLAND',
  'hispano-andorrane' => 'ANDORRA_SPAIN',
  'la côte atlantique française' => 'FRANCE_ATLANTIC_COAST',
  'côte méditérrannéenne' => 'FRANCE_MEDITERRANEAN_COAST',
  'limite des eaux territoriales atlantique françaises' => 'FRANCE_ATLANTIC_TERRITORIAL_SEA',
  'parc national des écrins' => 'FRANCE_ECRINS_NATIONAL_PARK'
}.freeze
INTERSECTIONS =

Intersection points between three countries

{
  'FRANCE_SPAIN|ANDORRA_SPAIN' => AIXM.xy(lat: 42.502720, long: 1.725965),
  'ANDORRA_SPAIN|FRANCE_SPAIN' => AIXM.xy(lat: 42.603571, long: 1.442681),
  'FRANCE_SWITZERLAND|FRANCE_ITALY' => AIXM.xy(lat: 45.922701, long: 7.044125),
  'BELGIUM_FRANCE|FRANCE_LUXEMBOURG' => AIXM.xy(lat: 49.546428, long: 5.818415),
  'FRANCE_LUXEMBOURG|FRANCE_GERMANY' => AIXM.xy(lat: 49.469438, long: 6.367516),
  'FRANCE_GERMANY|FRANCE_SWITZERLAND' => AIXM.xy(lat: 47.589831, long: 7.589049),
  'GERMANY_SWITZERLAND|FRANCE_GERMANY' => AIXM.xy(lat: 47.589831, long: 7.589049)
}.freeze
SURFACES =

Map surface to OFMX composition, preparation and remarks

{
  /^revêtue?$/ => { preparation: :paved },
  /^non revêtue?$/ => { preparation: :natural },
  'macadam' => { composition: :macadam },
  /^bitume ?(traité|psp)?$/ =>  { composition: :bitumen },
  'ciment' => { composition: :concrete, preparation: :paved },
  /^b[eé]ton ?(armé|bitume|bitumineux)?$/ => { composition: :concrete, preparation: :paved },
  /^béton( de)? ciment$/ => { composition: :concrete, preparation: :paved },
  'béton herbe' => { composition: :concrete_and_grass },
  'béton avec résine' => { composition: :concrete, preparation: :paved, remarks: 'Avec résine / with resin' },
  "béton + asphalte d'étanchéité sablé" => { composition: :concrete_and_asphalt, preparation: :paved, remarks: 'Étanchéité sablé / sandblasted waterproofing' },
  'béton armé + support bitumastic' => { composition: :concrete, preparation: :paved, remarks: 'Support bitumastic / bitumen support' },
  /résine (époxy )?su[er] béton/ => { composition: :concrete, preparation: :paved, remarks: 'Avec couche résine / with resin seal coat' },
  /^(asphalte|tarmac)$/ => { composition: :asphalt, preparation: :paved },
  'enrobé' => { preparation: :other, remarks: 'Enrobé / coated' },
  'enrobé anti-kérozène' => { preparation: :other, remarks: 'Enrobé anti-kérozène / anti-kerosene coating' },
  /^enrobé bitum(e|iné|ineux)$/ => { composition: :bitumen, preparation: :paved, remarks: 'Enrobé / coated' },
  'enrobé béton' => { composition: :concrete, preparation: :paved, remarks: 'Enrobé / coated' },
  /^résine( époxy)?$/ => { composition: :other, remarks: 'Résine / resin' },
  'tole acier larmé' => { composition: :metal, preparation: :grooved },
  /^(structure métallique|aluminium)$/ => { composition: :metal },
  'matériaux composites ignifugés' => { composition: :other, remarks: 'Matériaux composites ignifugés / fire resistant mixed materials' },
  /^(gazon|herbe)$/ => { composition: :grass },
  'neige' => { composition: :snow },
  'neige damée' => { composition: :snow, preparation: :rolled }
}.freeze
ANGLICISE_MAP =

Transform French text fragments to English

{
  /[^A-Z0-9 .\-]/ => '',
  /0(\d)/ => '\1',
  /(\d)-(\d)/ => '\1.\2',
  /PARTIE/ => '',
  /DELEG\./ => 'DELEG ',
  /FRANCAISE?/ => 'FR',
  /ANGLAISE?/ => 'UK',
  /BELGE/ => 'BE',
  /LUXEMBOURGEOISE?/ => 'LU',
  /ALLEMANDE?/ => 'DE',
  /SUISSE/ => 'CH',
  /ITALIEN(?:NE)?/ => 'IT',
  /ESPAGNOLE?/ => 'ES',
  /ANDORRANE?/ => 'AD',
  /NORD/ => 'N',
  /EST/ => 'E',
  /SUD/ => 'S',
  /OEST/ => 'W',
  /ANGLO NORMANDES/ => 'ANGLO-NORMANDES',
  / +/ => ' '
}.freeze

Instance Method Summary collapse

Instance Method Details

#anglicise(name:) ⇒ Object



106
107
108
109
110
111
112
# File 'lib/aipp/regions/LF/helpers/common.rb', line 106

def anglicise(name:)
  name&.uptrans&.tap do |string|
    ANGLICISE_MAP.each do |regexp, replacement|
      string.gsub!(regexp, replacement)
    end
  end
end

#elevation_from(text) ⇒ Object



144
145
146
147
# File 'lib/aipp/regions/LF/helpers/common.rb', line 144

def elevation_from(text)
  value, unit = text.strip.split
  AIXM.z(AIXM.d(value.to_i, unit).to_ft.dist, :qnh)
end

#geometry_from(text) ⇒ Object



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/aipp/regions/LF/helpers/common.rb', line 162

def geometry_from(text)
  AIXM.geometry.tap do |geometry|
    buffer = {}
    text.gsub(/\s+/, ' ').strip.split(/ - /).append('end').each do |element|
      case element
      when /arc (anti-)?horaire .+ sur (\S+) , (\S+)/i
        geometry << AIXM.arc(
          xy: buffer.delete(:xy),
          center_xy: AIXM.xy(lat: $2, long: $3),
          clockwise: $1.nil?
        )
      when /cercle de ([\d\.]+) (NM|km|m) .+ sur (\S+) , (\S+)/i
        geometry << AIXM.circle(
          center_xy: AIXM.xy(lat: $3, long: $4),
          radius: AIXM.d($1.to_f, $2)
        )
      when /end|(\S+) , (\S+)/
        geometry << AIXM.point(xy: buffer[:xy]) if buffer.has_key?(:xy)
        buffer[:xy] = AIXM.xy(lat: $1, long: $2) if $1
        if border = buffer.delete(:border)
          from = border.nearest(xy: geometry.segments.last.xy)
          to = border.nearest(xy: buffer[:xy], geometry_index: from.geometry_index)
          geometry.concat border.segment(from_position: from, to_position: to).map(&:to_point)
        end
      when /^frontière ([\w-]+)/i, /^(\D[^(]+)/i
        border_name = BORDERS.fetch($1.downcase.strip)
        if borders.has_key? border_name   # border from GeoJSON
          buffer[:border] = borders[border_name]
        else   # named border
          buffer[:xy] ||= INTERSECTIONS.fetch("#{buffer[:border_name]}|#{border_name}")
          buffer[:border_name] = border_name
          if border_name == 'FRANCE_SPAIN'   # specify which part of this split border
            border_name += buffer[:xy].lat < 42.55 ? '_EAST' : '_WEST'
          end
          geometry << AIXM.border(
            xy: buffer.delete(:xy),
            name: border_name
          )
        end
      else
        fail "geometry `#{element}' not recognized"
      end
    end
  end
end

#layer_from(text_for_limits, text_for_class = nil) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/aipp/regions/LF/helpers/common.rb', line 149

def layer_from(text_for_limits, text_for_class=nil)
  above, below = text_for_limits.gsub(/ /, '').split(/\n+/).select(&:blank_to_nil).split { |e| e.match? '---+' }
  AIXM.layer(
    class: text_for_class,
    vertical_limits: AIXM.vertical_limits(
      upper_z: z_from(above[0]),
      max_z: z_from(above[1]),
      lower_z: z_from(below[0]),
      min_z: z_from(below[1])
    )
  )
end

#organisation_lfObject

Templates



89
90
91
92
93
94
95
96
# File 'lib/aipp/regions/LF/helpers/common.rb', line 89

def organisation_lf
  @organisation_lf ||= AIXM.organisation(
    name: 'FRANCE',
    type: 'S'
  ).tap do |organisation|
    organisation.id = 'LF'
  end
end

#prepare(html:) ⇒ Object

Transformations



100
101
102
103
104
# File 'lib/aipp/regions/LF/helpers/common.rb', line 100

def prepare(html:)
  html.tap do |node|
    node.css('del, tr[class*="AmdtDeletedAIRAC"]').each(&:remove)   # remove deleted entries
  end
end

#source(position:, aip_file: nil) ⇒ Object

Parsers



116
117
118
119
120
121
122
123
124
125
# File 'lib/aipp/regions/LF/helpers/common.rb', line 116

def source(position:, aip_file: nil)
  aip_file ||= @aip
  [
    options[:region],
    aip_file.split('-').first,
    aip_file,
    options[:airac].date.xmlschema,
    position
  ].join('|')
end

#timetable_from!(text) ⇒ Object



208
209
210
211
212
# File 'lib/aipp/regions/LF/helpers/common.rb', line 208

def timetable_from!(text)
  if text.gsub!(/^\s*#{AIXM::H_RE}\s*$/, '')
    AIXM.timetable(code: Regexp.last_match&.to_s&.strip)
  end
end

#xy_from(text) ⇒ Object



127
128
129
130
# File 'lib/aipp/regions/LF/helpers/common.rb', line 127

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

#z_from(limit) ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
# File 'lib/aipp/regions/LF/helpers/common.rb', line 132

def z_from(limit)
  case limit
    when nil then nil
    when 'SFC' then AIXM::GROUND
    when 'UNL' then AIXM::UNLIMITED
    when /(\d+)ftASFC/ then AIXM.z($1.to_i, :qfe)
    when /(\d+)ftAMSL/ then AIXM.z($1.to_i, :qnh)
    when /FL(\d+)/ then AIXM.z($1.to_i, :qne)
    else fail "z `#{limit}' not recognized"
  end
end