notam 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1063 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NOTAM
4
+
5
+ class << self
6
+
7
+ # Expand informal two letter ICAO FIR identifier.
8
+ #
9
+ # @example
10
+ # NOTAM.expand_fir('LF') # => ["LFBB", "LFEE", "LFFF", "LFMM", "LFRR", "LFXX]
11
+ #
12
+ # @param fir [String] informal two letter ICAO FIR identifier
13
+ # @return [Array<String>] four letter ICAO FIR identifiers
14
+ def expand_fir(informal_fir)
15
+ FIRS.keys.select { _1.start_with? informal_fir }.tap do |firs|
16
+ fail(ArgumentError, "unknown wildcard FIR") unless firs.any?
17
+ firs << "#{informal_fir}XX"
18
+ end
19
+ end
20
+
21
+ # Get countries for the given ICAO FIR (wildcard) identifier
22
+ #
23
+ # @param fir [String] four letter ICAO FIR identifier
24
+ # @return [Array<Symbol>] array of country ISO alpha 2 codes
25
+ def countries_for(fir)
26
+ FIRS.fetch(fir)
27
+ end
28
+
29
+ # Translates the NOTAM subject code to human/machine readable symbol
30
+ #
31
+ # @param code [String] two letter subject code
32
+ # @return [Symbol] value from {NOTAM::SUBJECTS}
33
+ def subject_for(code)
34
+ SUBJECTS.fetch(code)
35
+ end
36
+
37
+ # Translates the NOTAM condition code to human/machine readable symbol
38
+ #
39
+ # @param code [String] two letter condition code
40
+ # @return [Symbol] value from {NOTAM::CONDITIONS}
41
+ def condition_for(code)
42
+ CONDITIONS.fetch(code)
43
+ end
44
+
45
+ # Translates the NOTAM traffic code to human/machine readable symbol
46
+ #
47
+ # @param code [String] traffic code
48
+ # @return [Symbol] value from {NOTAM::TRAFFIC}
49
+ def traffic_for(code)
50
+ TRAFFIC.fetch(code)
51
+ end
52
+
53
+ # Translates the NOTAM purpose code to human/machine readable symbol
54
+ #
55
+ # @param code [String] one letter purpose code
56
+ # @return [Symbol] value from {NOTAM::PURPOSES}
57
+ def purpose_for(code)
58
+ PURPOSES.fetch(code)
59
+ end
60
+
61
+ # Translates the NOTAM scope code to human/machine readable symbol
62
+ #
63
+ # @param code [String] one letter scope code
64
+ # @return [Symbol] value from {NOTAM::SCOPES}
65
+ def scope_for(code)
66
+ SCOPES.fetch(code)
67
+ end
68
+
69
+ # Expands and optionally translates the NOTAM contraction
70
+ #
71
+ # @param contraction [String] approved NOTAM contraction
72
+ # @param translate [Boolean] returns expanded and translated String when
73
+ # +true+ or expanded only Symbol otherwise (default)
74
+ # @return [Symbol, String, nil] expansion from {NOTAM::CONTRACTIONS},
75
+ # translation or +nil+
76
+ def expand(contraction, translate: false)
77
+ if expansion = CONTRACTIONS[contraction]
78
+ translate ? I18n.t("contractions.#{expansion}", default: nil) : expansion
79
+ end
80
+ end
81
+ end
82
+
83
+ # FIR ICAO codes to countries
84
+ #
85
+ # @see https://en.wikipedia.org/wiki/Flight_information_region
86
+ FIRS = {
87
+ 'AGGG' => [:SB],
88
+ 'ANAU' => [:NR],
89
+ 'AYPM' => [:PG],
90
+ 'BGGL' => [:GL, :DK],
91
+ 'BIRD' => [:IS],
92
+ 'CZEG' => [:CA],
93
+ 'CZQM' => [:CA],
94
+ 'CZQX' => [:CA],
95
+ 'CZUL' => [:CA],
96
+ 'CZVR' => [:CA],
97
+ 'CZWG' => [:CA],
98
+ 'CZYZ' => [:CA],
99
+ 'DAAA' => [:DZ],
100
+ 'DGAC' => [:GH],
101
+ 'DIII' => [:CI],
102
+ 'DNKK' => [:NG],
103
+ 'DRRR' => [:NE],
104
+ 'DTTC' => [:TN],
105
+ 'EZZZ' => [:BE],
106
+ 'EBBU' => [:BE, :LU],
107
+ 'EDGG' => [:DE],
108
+ 'EDMM' => [:DE],
109
+ 'EDUU' => [:DE],
110
+ 'EDVV' => [:DE],
111
+ 'EDWW' => [:DE],
112
+ 'EDYY' => [:BE, :DE, :NL],
113
+ 'EETT' => [:EE],
114
+ 'EFIN' => [:FI],
115
+ 'EGGX' => [:UK],
116
+ 'EGPX' => [:UK],
117
+ 'EGQQ' => [:UK],
118
+ 'EGTT' => [:UK],
119
+ 'EHAA' => [:NL],
120
+ 'EISN' => [:IE],
121
+ 'EKDK' => [:DK],
122
+ 'ENOB' => [:NO],
123
+ 'ENOR' => [:NO],
124
+ 'EPWW' => [:PL],
125
+ 'ESAA' => [:SE],
126
+ 'ESMM' => [:SE],
127
+ 'ESOS' => [:SE],
128
+ 'EVRR' => [:LV],
129
+ 'EYVL' => [:LT],
130
+ 'FABL' => [:ZA],
131
+ 'FACA' => [:ZA],
132
+ 'FACT' => [:ZA],
133
+ 'FADN' => [:ZA],
134
+ 'FAJO' => [:ZA],
135
+ 'FAJX' => [:ZA],
136
+ 'FAPX' => [:ZA],
137
+ 'FBGR' => [:BW],
138
+ 'FCCC' => [:CD],
139
+ 'FIMM' => [:MU],
140
+ 'FKKK' => [:CM],
141
+ 'FLFI' => [:ZM],
142
+ 'FMCX' => [:KM],
143
+ 'FMMM' => [:MG],
144
+ 'FNAN' => [:AO],
145
+ 'FOOO' => [:GA],
146
+ 'FQBE' => [:MZ],
147
+ 'FSSS' => [:SC],
148
+ 'FTTT' => [:TD],
149
+ 'FVHF' => [:ZW],
150
+ 'FWLL' => [:MW],
151
+ 'FYWF' => [:NA],
152
+ 'FZZA' => [:CG],
153
+ 'GCCC' => [:ES],
154
+ 'GLRB' => [:LR],
155
+ 'GMMM' => [:MA],
156
+ 'GOOO' => [:SN],
157
+ 'GVSC' => [:CV],
158
+ 'HAAA' => [:ET],
159
+ 'HBBA' => [:BI],
160
+ 'HCSM' => [:SO],
161
+ 'HECC' => [:EG],
162
+ 'HHAA' => [:EG],
163
+ 'HKNA' => [:KE],
164
+ 'HLLL' => [:LY],
165
+ 'HRYR' => [:RW],
166
+ 'HSSS' => [:SD],
167
+ 'HTDC' => [:TZ],
168
+ 'HUEC' => [:UG],
169
+ 'KZAB' => [:US],
170
+ 'KZAK' => [:US],
171
+ 'KZAU' => [:US],
172
+ 'KZBW' => [:US],
173
+ 'KZDC' => [:US],
174
+ 'KZDV' => [:US],
175
+ 'KZFW' => [:US],
176
+ 'KZHU' => [:US],
177
+ 'KZID' => [:US],
178
+ 'KZJX' => [:US],
179
+ 'KZKC' => [:US],
180
+ 'KZLA' => [:US],
181
+ 'KZLC' => [:US],
182
+ 'KZMA' => [:US],
183
+ 'KZME' => [:US],
184
+ 'KZMP' => [:US],
185
+ 'KZNY' => [:US],
186
+ 'KZOA' => [:US],
187
+ 'KZOB' => [:US],
188
+ 'KZSE' => [:US],
189
+ 'KZTL' => [:US],
190
+ 'KZWY' => [:US],
191
+ 'LAAA' => [:AL],
192
+ 'LBSR' => [:BG],
193
+ 'LBWR' => [:BG],
194
+ 'LCCC' => [:CY],
195
+ 'LDZO' => [:HR],
196
+ 'LECB' => [:ES],
197
+ 'LECM' => [:ES],
198
+ 'LECS' => [:ES],
199
+ 'LFBB' => [:FR],
200
+ 'LFEE' => [:FR],
201
+ 'LFFF' => [:FR],
202
+ 'LFMM' => [:FR],
203
+ 'LFRR' => [:FR],
204
+ 'LGGG' => [:GR],
205
+ 'LHCC' => [:HU],
206
+ 'LIBB' => [:IT],
207
+ 'LIMM' => [:IT],
208
+ 'LIRR' => [:IT],
209
+ 'LJLA' => [:SI],
210
+ 'LKAA' => [:CZ],
211
+ 'LLLL' => [:IL],
212
+ 'LMMM' => [:MT],
213
+ 'LOVV' => [:AT],
214
+ 'LPPC' => [:PT],
215
+ 'LPPO' => [:PT],
216
+ 'LQSB' => [:BA],
217
+ 'LRBB' => [:RO],
218
+ 'LSAG' => [:CH],
219
+ 'LSAS' => [:CH],
220
+ 'LSAZ' => [:CH],
221
+ 'LTAA' => [:TR],
222
+ 'LTBB' => [:TR],
223
+ 'LUUU' => [:MD],
224
+ 'LWSS' => [:MK],
225
+ 'LYBA' => [:RS],
226
+ 'LZBB' => [:SK],
227
+ 'MDCS' => [:DO],
228
+ 'MHTG' => [:HN],
229
+ 'MKJK' => [:JM],
230
+ 'MMFO' => [:MX],
231
+ 'MMFR' => [:MX],
232
+ 'MPZL' => [:PA],
233
+ 'MTEG' => [:HT],
234
+ 'MUFH' => [:CU],
235
+ 'MYNA' => [:BS],
236
+ 'NFFF' => [:FJ],
237
+ 'NTTT' => [:PF, :FR],
238
+ 'NWWX' => [:NC, :FR],
239
+ 'NZZC' => [:NZ],
240
+ 'NZZO' => [:NZ],
241
+ 'OAKX' => [:AF],
242
+ 'OBBB' => [:BH],
243
+ 'OEJD' => [:SA],
244
+ 'OIIX' => [:IR],
245
+ 'OJAC' => [:JO],
246
+ 'OKAC' => [:KW],
247
+ 'OLBB' => [:LB],
248
+ 'OMAE' => [:AE],
249
+ 'OOMM' => [:OM],
250
+ 'OPKR' => [:PK],
251
+ 'OPLR' => [:PK],
252
+ 'ORBB' => [:IQ],
253
+ 'ORMM' => [:IQ],
254
+ 'OSTT' => [:SY],
255
+ 'OYSC' => [:YE],
256
+ 'PAZA' => [:US],
257
+ 'PAZN' => [:US],
258
+ 'PHZH' => [:US],
259
+ 'RCAA' => [:TW],
260
+ 'RJJJ' => [:JA],
261
+ 'RKRR' => [:KR],
262
+ 'RPHI' => [:PH],
263
+ 'SACF' => [:AR],
264
+ 'SACU' => [:AR],
265
+ 'SAEF' => [:AR],
266
+ 'SAEU' => [:AR],
267
+ 'SAMF' => [:AR],
268
+ 'SAMV' => [:AR],
269
+ 'SARR' => [:AR],
270
+ 'SAVF' => [:AR],
271
+ 'SAVU' => [:AR],
272
+ 'SBAO' => [:BR],
273
+ 'SBAZ' => [:BR],
274
+ 'SBBS' => [:BR],
275
+ 'SBCW' => [:BR],
276
+ 'SBRE' => [:BR],
277
+ 'SCCZ' => [:CL],
278
+ 'SCEZ' => [:CL],
279
+ 'SCFZ' => [:CL],
280
+ 'SCIZ' => [:CL],
281
+ 'SCTZ' => [:CL],
282
+ 'SEFG' => [:EC],
283
+ 'SGFA' => [:PY],
284
+ 'SKEC' => [:CO],
285
+ 'SKED' => [:CO],
286
+ 'SLLF' => [:BO],
287
+ 'SMPM' => [:SR],
288
+ 'SOOO' => [:GF, :FR],
289
+ 'SPIM' => [:PU],
290
+ 'SUEO' => [:UY],
291
+ 'SVZM' => [:VE],
292
+ 'SYGC' => [:GY],
293
+ 'TJZS' => [:PR, :US],
294
+ 'TNCF' => [:CW, :NL],
295
+ 'TTZP' => [:TT],
296
+ 'UAAX' => [:KZ],
297
+ 'UACX' => [:KZ],
298
+ 'UAFX' => [:KG],
299
+ 'UASS' => [:KZ],
300
+ 'UDDD' => [:AM],
301
+ 'UEMH' => [:RU],
302
+ 'UENN' => [:RU],
303
+ 'UESS' => [:RU],
304
+ 'UESU' => [:RU],
305
+ 'UEVV' => [:RU],
306
+ 'UGEE' => [:RU],
307
+ 'UGGG' => [:GE],
308
+ 'UHBI' => [:RU],
309
+ 'UHHH' => [:RU],
310
+ 'UHMI' => [:RU],
311
+ 'UHMM' => [:RU],
312
+ 'UHMP' => [:RU],
313
+ 'UHNN' => [:RU],
314
+ 'UHPT' => [:RU],
315
+ 'UHPU' => [:RU],
316
+ 'UHSH' => [:RU],
317
+ 'UIKB' => [:RU],
318
+ 'UIKK' => [:RU],
319
+ 'UKBV' => [:UA],
320
+ 'UKCV' => [:UA],
321
+ 'UKDV' => [:UA],
322
+ 'UKFV' => [:UA],
323
+ 'UKHV' => [:UA],
324
+ 'UKLV' => [:UA],
325
+ 'UKOV' => [:UA],
326
+ 'ULLL' => [:RU],
327
+ 'ULOL' => [:RU],
328
+ 'UMKD' => [:RU],
329
+ 'UMMV' => [:BY],
330
+ 'UNLL' => [:RU],
331
+ 'UOTT' => [:RU],
332
+ 'URRV' => [:RU],
333
+ 'USDK' => [:RU],
334
+ 'USHB' => [:RU],
335
+ 'USHH' => [:RU],
336
+ 'UTAK' => [:TM],
337
+ 'UTNR' => [:UZ],
338
+ 'UTSD' => [:UZ],
339
+ 'UTTR' => [:UZ],
340
+ 'UUWV' => [:RU],
341
+ 'UUYW' => [:RU],
342
+ 'UUYY' => [:RU],
343
+ 'UWOO' => [:RU],
344
+ 'VABF' => [:IN],
345
+ 'VCCC' => [:LK],
346
+ 'VDPF' => [:KH],
347
+ 'VECF' => [:IN],
348
+ 'VGFR' => [:BD],
349
+ 'VHHK' => [:HK],
350
+ 'VIDF' => [:IN],
351
+ 'VLIV' => [:LA],
352
+ 'VLVT' => [:LA],
353
+ 'VNSM' => [:NP],
354
+ 'VOMF' => [:IN],
355
+ 'VRMF' => [:MV],
356
+ 'VTBB' => [:TH],
357
+ 'VVHM' => [:VN],
358
+ 'VVHN' => [:VN],
359
+ 'VYMD' => [:MM],
360
+ 'VYYF' => [:MM],
361
+ 'WAAF' => [:ID],
362
+ 'WAAZ' => [:ID],
363
+ 'WABZ' => [:ID],
364
+ 'WADZ' => [:ID],
365
+ 'WAJZ' => [:ID],
366
+ 'WAKZ' => [:ID],
367
+ 'WALZ' => [:ID],
368
+ 'WAMZ' => [:ID],
369
+ 'WAOZ' => [:ID],
370
+ 'WAPZ' => [:ID],
371
+ 'WATZ' => [:ID],
372
+ 'WBFC' => [:BN, :MY],
373
+ 'WIIF' => [:ID],
374
+ 'WIIZ' => [:ID],
375
+ 'WIMZ' => [:ID],
376
+ 'WIOZ' => [:ID],
377
+ 'WIPZ' => [:ID],
378
+ 'WMFC' => [:MY],
379
+ 'WSJC' => [:SG],
380
+ 'YBBB' => [:AU],
381
+ 'YMMM' => [:AU],
382
+ 'ZBPE' => [:CH],
383
+ 'ZGJD' => [:CH],
384
+ 'ZGZU' => [:CH],
385
+ 'ZHWH' => [:CH],
386
+ 'ZJSA' => [:CH],
387
+ 'ZKKP' => [:KP],
388
+ 'ZLHW' => [:CH],
389
+ 'ZMUB' => [:MN],
390
+ 'ZPKM' => [:CH],
391
+ 'ZSHA' => [:CH],
392
+ 'ZWUQ' => [:CH],
393
+ 'ZYSH' => [:CH]
394
+ }.freeze
395
+
396
+ # International NOTAM Q codes for subjects
397
+ #
398
+ # @see https://www.faa.gov/air_traffic/publications/atpubs/notam_html/appendix_b.html
399
+ SUBJECTS = {
400
+ 'AA' => :minimum_altitude,
401
+ 'AC' => :class_bcde_surface_area,
402
+ 'AD' => :air_defense_identification_zone,
403
+ 'AE' => :control_area,
404
+ 'AF' => :flight_information_region,
405
+ 'AH' => :upper_control_area,
406
+ 'AL' => :minimum_usable_flight_level,
407
+ 'AN' => :area_navigation_route,
408
+ 'AO' => :oceanic_control_area,
409
+ 'AP' => :reporting_point,
410
+ 'AR' => :ats_route,
411
+ 'AT' => :terminal_control_area,
412
+ 'AU' => :upper_flight_information_region,
413
+ 'AV' => :upper_advisory_area,
414
+ 'AX' => :significant_point,
415
+ 'AZ' => :aerodrome_traffic_zone,
416
+ 'CA' => :air_ground_facility,
417
+ 'CB' => :automatic_dependent_surveillance_broadcast,
418
+ 'CC' => :automatic_dependent_surveillance_contract,
419
+ 'CD' => :controller_pilot_data_link,
420
+ 'CE' => :en_route_surveillance_radar,
421
+ 'CG' => :ground_controlled_approach_system,
422
+ 'CL' => :selective_calling_system,
423
+ 'CM' => :surface_movement_radar,
424
+ 'CP' => :precision_approach_radar,
425
+ 'CR' => :surveillance_radar_element_of_par,
426
+ 'CS' => :secondary_surveillance_radar,
427
+ 'CT' => :terminal_area_surveillance_radar,
428
+ 'FA' => :aerodrome,
429
+ 'FB' => :friction_measuring_device,
430
+ 'FC' => :ceiling_measurement_equipment,
431
+ 'FD' => :docking_system,
432
+ 'FE' => :oxygen,
433
+ 'FF' => :fire_fighting_and_rescue,
434
+ 'FG' => :ground_movement_control,
435
+ 'FH' => :helicopter_alighting_area,
436
+ 'FI' => :aircraft_de_icing,
437
+ 'FJ' => :oils,
438
+ 'FL' => :landing_direction_indicator,
439
+ 'FM' => :meteorological_service,
440
+ 'FO' => :fog_dispersal_system,
441
+ 'FP' => :heliport,
442
+ 'FS' => :snow_removal_equipment,
443
+ 'FT' => :transmissometer,
444
+ 'FU' => :fuel_availability,
445
+ 'FW' => :wind_direction_indicator,
446
+ 'FZ' => :customs,
447
+ 'GA' => :gnss_airfield_specific_operations,
448
+ 'GW' => :gnss_area_wide_operations,
449
+ 'IC' => :instrument_landing_system,
450
+ 'ID' => :dme_associated_with_ils,
451
+ 'IG' => :glide_path,
452
+ 'II' => :inner_marker,
453
+ 'IL' => :localizer,
454
+ 'IM' => :middle_marker,
455
+ 'IN' => :localizer_without_ils,
456
+ 'IO' => :outer_marker,
457
+ 'IS' => :ils_category_1,
458
+ 'IT' => :ils_category_2,
459
+ 'IU' => :ils_category_3,
460
+ 'IW' => :microwave_landing_system,
461
+ 'IX' => :locator_outer,
462
+ 'IY' => :locator_middle,
463
+ 'KK' => :checklist,
464
+ 'LA' => :approach_lighting_system,
465
+ 'LB' => :aerodrome_beacon,
466
+ 'LC' => :runway_centre_line_lights,
467
+ 'LD' => :landing_direction_indicator_lights,
468
+ 'LE' => :runway_edge_lights,
469
+ 'LF' => :sequenced_flashing_lights,
470
+ 'LG' => :pilot_controlled_lighting,
471
+ 'LH' => :high_intensity_runway_lights,
472
+ 'LI' => :runway_end_identifier_lights,
473
+ 'LJ' => :runway_alignment_indicator_lights,
474
+ 'LK' => :category_2_components_of_als,
475
+ 'LL' => :low_intensity_runway_lights,
476
+ 'LM' => :medium_intensity_runway_lights,
477
+ 'LP' => :precision_approach_path_indicator,
478
+ 'LR' => :all_landing_area_lighting_facilities,
479
+ 'LS' => :stopway_lights,
480
+ 'LT' => :threshold_lights,
481
+ 'LU' => :helicopter_approach_path_indicator,
482
+ 'LV' => :visual_approach_slope_indicator_system,
483
+ 'LW' => :heliport_lighting,
484
+ 'LX' => :taxiway_centre_line_lights,
485
+ 'LY' => :taxiway_edge_lights,
486
+ 'LZ' => :runway_touchdown_zone_lights,
487
+ 'MA' => :movement_area,
488
+ 'MB' => :bearing_strength,
489
+ 'MC' => :clearway,
490
+ 'MD' => :declared_distances,
491
+ 'MG' => :taxiing_guidance_system,
492
+ 'MH' => :runway_arresting_gear,
493
+ 'MK' => :parking_area,
494
+ 'MM' => :daylight_markings,
495
+ 'MN' => :apron,
496
+ 'MO' => :stopbar,
497
+ 'MP' => :aircraft_stands,
498
+ 'MR' => :runway,
499
+ 'MS' => :stopway,
500
+ 'MT' => :threshold,
501
+ 'MU' => :runway_turning_bay,
502
+ 'MW' => :strip_shoulder,
503
+ 'MX' => :taxiway,
504
+ 'MY' => :rapid_exit_taxiway,
505
+ 'NA' => :all_radio_navigation_facilities,
506
+ 'NB' => :nondirectional_radio_beacon,
507
+ 'NC' => :decca,
508
+ 'ND' => :dme,
509
+ 'NF' => :fan_marker,
510
+ 'NL' => :locator,
511
+ 'NM' => :vor_dme,
512
+ 'NN' => :tacan,
513
+ 'NO' => :omega,
514
+ 'NT' => :vortac,
515
+ 'NV' => :vor,
516
+ 'OA' => :aeronautical_information_service,
517
+ 'OB' => :obstacle,
518
+ 'OE' => :aircraft_entry_requirements,
519
+ 'OL' => :obstacle_lights,
520
+ 'OR' => :rescue_coordination_centre,
521
+ 'PA' => :standard_instrument_arrival,
522
+ 'PB' => :standard_vfr_arrival,
523
+ 'PC' => :contingency_procedures,
524
+ 'PD' => :standard_instrument_departure,
525
+ 'PE' => :standard_vfr_departure,
526
+ 'PF' => :flow_control_procedure,
527
+ 'PH' => :holding_procedure,
528
+ 'PI' => :instrument_approach_procedure,
529
+ 'PK' => :vfr_approach_procedure,
530
+ 'PL' => :flight_plan_processing,
531
+ 'PM' => :aerodrome_operating_minima,
532
+ 'PN' => :noise_operating_restriction,
533
+ 'PO' => :obstacle_clearance_altitude,
534
+ 'PR' => :radio_failure_procedure,
535
+ 'PT' => :transition_altitude_or_level,
536
+ 'PU' => :missed_approach_procedure,
537
+ 'PX' => :minimum_holding_altitude,
538
+ 'PZ' => :adiz_procedure,
539
+ 'RA' => :airspace_reservation,
540
+ 'RD' => :danger_area,
541
+ 'RM' => :military_operating_area,
542
+ 'RO' => :overflying,
543
+ 'RP' => :prohibited_area,
544
+ 'RR' => :restricted_area,
545
+ 'RT' => :temporary_restricted_area,
546
+ 'SA' => :automatic_terminal_information_service,
547
+ 'SB' => :ats_reporting_office,
548
+ 'SC' => :area_control_centre,
549
+ 'SE' => :flight_information_service,
550
+ 'SF' => :aerodrome_flight_information_service,
551
+ 'SL' => :flow_control_centre,
552
+ 'SO' => :oceanic_area_control_centre,
553
+ 'SP' => :approach_control_service,
554
+ 'SS' => :flight_service_station,
555
+ 'ST' => :aerodrome_control_tower,
556
+ 'SU' => :upper_area_control_centre,
557
+ 'SV' => :volmet_broadcast,
558
+ 'SY' => :upper_advisory_service,
559
+ 'WA' => :air_display,
560
+ 'WB' => :aerobatics,
561
+ 'WC' => :captive_balloon_or_kite,
562
+ 'WD' => :demolition_of_explosives,
563
+ 'WE' => :exercises,
564
+ 'WF' => :air_refueling,
565
+ 'WG' => :glider_flying,
566
+ 'WH' => :blasting,
567
+ 'WJ' => :banner_towing,
568
+ 'WL' => :ascent_of_free_balloon,
569
+ 'WM' => :missile_gun_firing,
570
+ 'WP' => :parachute_paragliding_or_hang_gliding,
571
+ 'WR' => :radioactive_or_toxic_materials,
572
+ 'WS' => :blowing_gas,
573
+ 'WT' => :mass_movement_of_aircraft,
574
+ 'WU' => :unmanned_aircraft,
575
+ 'WV' => :formation_flight,
576
+ 'WW' => :volcanic_activity,
577
+ 'WY' => :aerial_survey,
578
+ 'WZ' => :model_flying,
579
+ 'XX' => :other
580
+ }.freeze
581
+
582
+ # International NOTAM Q codes for conditions
583
+ #
584
+ # @see https://www.faa.gov/air_traffic/publications/atpubs/notam_html/appendix_b.html
585
+ CONDITIONS = {
586
+ 'AC' => :withdrawn_for_maintenance,
587
+ 'AD' => :available_for_daylight_operation,
588
+ 'AF' => :flight_checked_and_found_reliable,
589
+ 'AG' => :operating_but_ground_checked_only,
590
+ 'AH' => :hours_of_service,
591
+ 'AK' => :resumed_normal_operations,
592
+ 'AL' => :operative_subject_to_previously_published_conditions,
593
+ 'AM' => :military_operations_only,
594
+ 'AN' => :available_for_night_operation,
595
+ 'AO' => :operational,
596
+ 'AP' => :available_with_prior_permission,
597
+ 'AR' => :available_on_request,
598
+ 'AS' => :unserviceable,
599
+ 'AU' => :not_available,
600
+ 'AW' => :completely_withdrawn,
601
+ 'AX' => :previously_announced_shutdown_canceled,
602
+ 'CA' => :activated,
603
+ 'CC' => :completed,
604
+ 'CD' => :deactivated,
605
+ 'CE' => :erected,
606
+ 'CF' => :operating_frequency_changed,
607
+ 'CG' => :downgraded,
608
+ 'CH' => :changed,
609
+ 'CI' => :identification_changed,
610
+ 'CL' => :realigned,
611
+ 'CM' => :displaced,
612
+ 'CN' => :canceled,
613
+ 'CO' => :operating,
614
+ 'CP' => :operating_on_reduced_power,
615
+ 'CR' => :temporarily_replaced,
616
+ 'CS' => :installed,
617
+ 'CT' => :on_test,
618
+ 'HA' => :braking_action,
619
+ 'HB' => :friction_coefficient,
620
+ 'HC' => :covered_by_compacted_snow,
621
+ 'HD' => :covered_by_dry_snow,
622
+ 'HE' => :covered_by_water,
623
+ 'HF' => :free_of_snow_and_ice,
624
+ 'HG' => :grass_cutting_in_progress,
625
+ 'HH' => :hazard,
626
+ 'HI' => :covered_by_ice,
627
+ 'HJ' => :launch_planned,
628
+ 'HK' => :bird_migration_in_progress,
629
+ 'HL' => :snow_clearance_completed,
630
+ 'HM' => :marked,
631
+ 'HN' => :covered_by_wet_snow,
632
+ 'HO' => :obscured_by_snow,
633
+ 'HP' => :snow_clearance_in_progress,
634
+ 'HQ' => :operation_canceled,
635
+ 'HR' => :standing_water,
636
+ 'HS' => :sanding_in_progress,
637
+ 'HT' => :approach_according_to_signal_area_only,
638
+ 'HU' => :launch_in_progress,
639
+ 'HV' => :work_completed,
640
+ 'HW' => :work_in_progress,
641
+ 'HX' => :concentration_of_birds,
642
+ 'HY' => :snow_banks_exist,
643
+ 'HZ' => :covered_by_frozen_ruts,
644
+ 'KK' => :checklist,
645
+ 'LA' => :operating_on_auxiliary_power_supply,
646
+ 'LB' => :reserved_for_aircraft_based_therein,
647
+ 'LC' => :closed,
648
+ 'LD' => :unsafe,
649
+ 'LE' => :operating_without_auxiliary_power_supply,
650
+ 'LF' => :interference,
651
+ 'LG' => :operating_without_identification,
652
+ 'LH' => :unserviceable_for_heavier_aircraft,
653
+ 'LI' => :closed_to_ifr_operations,
654
+ 'LK' => :operating_as_fixed_light,
655
+ 'LL' => :usable_for_smaller_only,
656
+ 'LN' => :closed_to_night_operations,
657
+ 'LP' => :prohibited,
658
+ 'LR' => :restricted_to_runways_and_taxiways,
659
+ 'LS' => :subject_to_interruption,
660
+ 'LT' => :limited,
661
+ 'LV' => :closed_to_vfr_operations,
662
+ 'LW' => :will_take_place,
663
+ 'LX' => :operating_but_caution_advised,
664
+ 'TT' => :trigger,
665
+ 'XX' => :other
666
+ }.freeze
667
+
668
+ # Kinds of traffic
669
+ TRAFFIC = {
670
+ 'IV' => :ifr_and_vfr,
671
+ 'I' => :ifr,
672
+ 'V' => :vfr,
673
+ 'K' => :checklist
674
+ }.freeze
675
+
676
+ # Purpose identifiers
677
+ PURPOSES = {
678
+ 'N' => :immediate_attention,
679
+ 'B' => :operational_significance,
680
+ 'O' => :flight_operations,
681
+ 'M' => :miscellaneous,
682
+ 'K' => :checklist
683
+ }.freeze
684
+
685
+ # Scope identifiers
686
+ SCOPES = {
687
+ 'A' => :aerodrome,
688
+ 'E' => :en_route,
689
+ 'W' => :navigation_warning,
690
+ 'K' => :checklist
691
+ }.freeze
692
+
693
+ # Approved NOTAM contractions
694
+ #
695
+ # @note Contractions are applied in the given order, therefore multi-word
696
+ # contractions should be listed first!
697
+ #
698
+ # @see https://www.notams.faa.gov/downloads/contractions.pdf
699
+ CONTRACTIONS = {
700
+ 'AP LGT' => :airport_lighting,
701
+ 'BA FAIR' => :braking_action_fair,
702
+ 'BA NIL' => :braking_action_nil,
703
+ 'BA POOR' => :braking_action_poor,
704
+ 'DEP PROC' => :departure_procedure,
705
+ 'FAN MKR' => :fan_marker,
706
+ 'TDZ LGT' => :touchdown_zone_lights,
707
+ 'VOR VHF' => :omni_directional_radio_range,
708
+ 'ABN' => :airport_beacon,
709
+ 'ABV' => :above,
710
+ 'ACC' => :area_control_center,
711
+ 'ACCUM' => :accumulate,
712
+ 'ACFT' => :aircraft,
713
+ 'ACR' => :air_carrier,
714
+ 'ACT' => :active,
715
+ 'ADJ' => :adjacent,
716
+ 'ADZD' => :advised,
717
+ 'AFD' => :airport_facility_directory,
718
+ 'AGL' => :above_ground_level,
719
+ 'ALS' => :approach_lighting_system,
720
+ 'ALT' => :altitude,
721
+ 'ALTM' => :altimeter,
722
+ 'ALTN' => :alternate,
723
+ 'ALTNLY' => :alternately,
724
+ 'ALSTG' => :altimeter_setting,
725
+ 'AMDT' => :amendment,
726
+ 'AMGR' => :airport_manager,
727
+ 'AMOS' => :automatic_meteorological_observing_system,
728
+ 'AP' => :airport,
729
+ 'APCH' => :approach,
730
+ 'APP' => :approach_control,
731
+ 'ARFF' => :aircraft_rescue_and_fire_fighting,
732
+ 'ARR' => :arrival,
733
+ 'ASOS' => :automatic_surface_observing_system,
734
+ 'ASPH' => :asphalt,
735
+ 'ATC' => :air_traffic_control,
736
+ 'ATCCC' => :air_traffic_control_command_center,
737
+ 'ATIS' => :automatic_terminal_information_service,
738
+ 'AUTOB' => :automatic_weather_reporting_system,
739
+ 'AUTH' => :authority,
740
+ 'AVBL' => :available,
741
+ 'AWOS' => :automatic_weather_observing_system,
742
+ 'AWY' => :airway,
743
+ 'AZM' => :azimuth,
744
+ 'BC' => :back_course,
745
+ 'BCN' => :beacon,
746
+ 'BERM' => :snowbanks_containing_earth,
747
+ 'BLW' => :below,
748
+ 'BND' => :bound,
749
+ 'BRG' => :bearing,
750
+ 'BYD' => :beyond,
751
+ 'CAAS' => :class_a_airspace,
752
+ 'CAT' => :category,
753
+ 'CBAS' => :class_b_airspace,
754
+ 'CBSA' => :class_b_surface_area,
755
+ 'CCAS' => :class_c_airspace,
756
+ 'CCLKWS' => :counterclockwise,
757
+ 'CCSA' => :class_c_surface_area,
758
+ 'CD' => :clearance_delivery,
759
+ 'CDAS' => :class_d_airspace,
760
+ 'CDSA' => :class_d_surface_area,
761
+ 'CEAS' => :class_e_airspace,
762
+ 'CESA' => :class_e_surface_area,
763
+ 'CFR' => :code_of_federal_regulations,
764
+ 'CGAS' => :class_g_airspace,
765
+ 'CHAN' => :channel,
766
+ 'CHG' => :change_or_modification,
767
+ 'CIG' => :ceiling,
768
+ 'CK' => :check,
769
+ 'CL' => :centre_line,
770
+ 'CLKWS' => :clockwise,
771
+ 'CLR' => :clear,
772
+ 'CLSD' => :closed,
773
+ 'CMB' => :climb,
774
+ 'CMSND' => :commissioned,
775
+ 'CNL' => :cancel,
776
+ 'CNTRLN' => :centerline,
777
+ 'COM' => :communications,
778
+ 'CONC' => :concrete,
779
+ 'CPD' => :coupled,
780
+ 'CRS' => :course,
781
+ 'CTC' => :contact,
782
+ 'CTL' => :control,
783
+ 'DALGT' => :daylight,
784
+ 'DCMSN' => :decommission,
785
+ 'DCMSND' => :decommissioned,
786
+ 'DCT' => :direct,
787
+ 'DEGS' => :degrees,
788
+ 'DEP' => :departure,
789
+ 'DH' => :decision_height,
790
+ 'DISABLD' => :disabled,
791
+ 'DIST' => :distance,
792
+ 'DLA' => :delay_or_delayed,
793
+ 'DLT' => :delete,
794
+ 'DLY' => :daily,
795
+ 'DME' => :distance_measuring_equipment,
796
+ 'DMSTN' => :demonstration,
797
+ 'DP' => :dewpoint_temperature,
798
+ 'DRFT' => :snowbanks_caused_by_wind,
799
+ 'DSPLCD' => :displaced,
800
+ 'E' => :east,
801
+ 'EB' => :eastbound,
802
+ 'EFAS' => :en_route_flight_advisory_service,
803
+ 'ELEV' => :elevation,
804
+ 'ENG' => :engine,
805
+ 'ENRT' => :en_route,
806
+ 'ENTR' => :entire,
807
+ 'EXC' => :except,
808
+ 'FAC' => :facility_or_facilities,
809
+ 'FAF' => :final_approach_fix,
810
+ 'FDC' => :flight_data_center,
811
+ 'FI/T': :flight_inspection_temporay,
812
+ 'FI/P': :flight_inspection_permanent,
813
+ 'FM' => :from,
814
+ 'FNA' => :final_approach,
815
+ 'FPM' => :feet_per_minute,
816
+ 'FREQ' => :frequency,
817
+ 'FRH' => :fly_runway_heading,
818
+ 'FRI' => :friday,
819
+ 'FRZN' => :frozen,
820
+ 'FSS' => :flight_service_station,
821
+ 'FT' => :foot,
822
+ 'GC' => :ground_control,
823
+ 'GCA' => :ground_control_approach,
824
+ 'GCO' => :ground_communications_outlet,
825
+ 'GOVT' => :government,
826
+ 'GP' => :glide_path,
827
+ 'GPS' => :global_positioning_system,
828
+ 'GRVL' => :gravel,
829
+ 'HAA' => :height_above_airport,
830
+ 'HAT' => :height_above_touchdown,
831
+ 'HDG' => :heading,
832
+ 'HEL' => :helicopter,
833
+ 'HELI' => :heliport,
834
+ 'HIRL' => :high_intensity_runway_lights,
835
+ 'HIWAS' => :hazardous_inflight_weather_advisory_service,
836
+ 'HLDG' => :holding,
837
+ 'HOL' => :holiday,
838
+ 'HP' => :holding_pattern,
839
+ 'HR' => :hour,
840
+ 'IAF' => :initial_approach_fix,
841
+ 'IAP' => :instrument_approach_procedure,
842
+ 'INBD' => :inbound,
843
+ 'ID' => :identification,
844
+ 'IDENT' => :identify,
845
+ 'IF' => :intermediate_fix,
846
+ 'ILS' => :instrument_landing_system,
847
+ 'IM' => :inner_marker,
848
+ 'IMC' => :instrument_meteorological_conditions,
849
+ 'IN' => :inch,
850
+ 'INDEFLY' => :indefinitely,
851
+ 'INFO' => :information,
852
+ 'INOP' => :inoperative,
853
+ 'INSTR' => :instrument,
854
+ 'INT' => :intersection,
855
+ 'INTL' => :international,
856
+ 'INTST' => :intensity,
857
+ 'IR' => :ice_on_runway,
858
+ 'KT' => :knots,
859
+ 'L' => :left,
860
+ 'LAA' => :local_airport_advisory,
861
+ 'LAT' => :latitude,
862
+ 'LAWRS' => :limited_aviation_weather_reporting_station,
863
+ 'LB' => :pounds,
864
+ 'LC' => :local_control,
865
+ 'LOC' => :local,
866
+ 'LCTD' => :located,
867
+ 'LDA' => :localizer_type_directional_aid,
868
+ 'LGT' => :light_or_lighting,
869
+ 'LGTD' => :lighted,
870
+ 'LIRL' => :low_intensity_runway_lights,
871
+ 'LLWAS' => :low_level_wind_shear_alert_system,
872
+ 'LM' => :compass_locator_at_ils_middle_marker,
873
+ 'LDG' => :landing,
874
+ 'LLZ' => :localizer,
875
+ 'LO' => :compass_locator_at_ils_outer_marker,
876
+ 'LONG' => :longitude,
877
+ 'LRN' => :long_range_navigation,
878
+ 'LSR' => :loose_snow_on_runway,
879
+ 'LT' => :left_turn,
880
+ 'MAG' => :magnetic,
881
+ 'MAINT' => :maintenance,
882
+ 'MALS' => :medium_intensity_approach_light_system,
883
+ 'MALSF' => :medium_intensity_approach_light_system_with_sequenced_flashers,
884
+ 'MALSR' => :medium_intensity_approach_light_system_with_runway_alignment_indicator_lights,
885
+ 'MAPT' => :missed_approach_point,
886
+ 'MCA' => :minimum_crossing_altitude,
887
+ 'MDA' => :minimum_descent_altitude,
888
+ 'MEA' => :minimum_en_route_altitude,
889
+ 'MED' => :medium,
890
+ 'MIN' => :minutes,
891
+ 'MIRL' => :medium_intensity_runway_lights,
892
+ 'MKR' => :marker,
893
+ 'MLS' => :microwave_landing_system,
894
+ 'MM' => :middle_marker,
895
+ 'MNM' => :minimum,
896
+ 'MNT' => :monitor,
897
+ 'MOC' => :minimum_obstruction_clearance,
898
+ 'MON' => :monday,
899
+ 'MRA' => :minimum_reception_altitude,
900
+ 'MSA' => :minimum_safe_altitude,
901
+ 'MSAW' => :minimum_safe_altitude_warning,
902
+ 'MSG' => :message,
903
+ 'MSL' => :mean_sea_level,
904
+ 'MU' => :mu_meters,
905
+ 'MUD' => :mud,
906
+ 'MUNI' => :municipal,
907
+ 'N' => :north,
908
+ 'NA' => :not_authorized,
909
+ 'NAV' => :navigation,
910
+ 'NB' => :northbound,
911
+ 'NDB' => :nondirectional_radio_beacon,
912
+ 'NE' => :northeast,
913
+ 'NGT' => :night,
914
+ 'NM' => :nautical_miles,
915
+ 'NMR' => :nautical_mile_radius,
916
+ 'NONSTD' => :nonstandard,
917
+ 'NOPT' => :no_procedure_turn_required,
918
+ 'NR' => :number,
919
+ 'NTAP' => :notice_to_airmen_publication,
920
+ 'NW' => :northwest,
921
+ 'OBSC' => :obscured,
922
+ 'OBST' => :obstacle,
923
+ 'OM' => :outer_marker,
924
+ 'OPR' => :operate,
925
+ 'OPS' => :operations,
926
+ 'ORIG' => :original,
927
+ 'OTS' => :out_of_service,
928
+ 'OVR' => :over,
929
+ 'PAEW' => :personnel_and_equipment_working,
930
+ 'PAX' => :passengers,
931
+ 'PAPI' => :precision_approach_path_indicator,
932
+ 'PAR' => :precision_approach_radar,
933
+ 'PARL' => :parallel,
934
+ 'PAT' => :pattern,
935
+ 'PCL' => :pilot_controlled_lighting,
936
+ 'PERM' => :permanent,
937
+ 'PJE' => :parachute_jumping_exercise,
938
+ 'PLA' => :practice_low_approach,
939
+ 'PLW' => :plow,
940
+ 'PN' => :prior_notice_required,
941
+ 'PPR' => :prior_permission_required,
942
+ 'PRN' => :psuedo_random_noise,
943
+ 'PROC' => :procedure,
944
+ 'PROP' => :propeller,
945
+ 'PSR' => :packed_snow_on_runway,
946
+ 'PTCHY' => :patchy,
947
+ 'PTN' => :procedure_turn,
948
+ 'PVT' => :private,
949
+ 'RAIL' => :runway_alignment_indicator_lights,
950
+ 'RAMOS' => :remote_automatic_meteorological_observing_system,
951
+ 'RCAG' => :remote_communication_air_ground_facility,
952
+ 'RCL' => :runway_center_line,
953
+ 'RCLL' => :runway_center_line_lights,
954
+ 'RCO' => :remote_communication_outlet,
955
+ 'REC' => :receive_or_receiver,
956
+ 'REIL' => :runway_end_identifier_lights,
957
+ 'RELCTD' => :relocated,
958
+ 'REP' => :report,
959
+ 'RLLS' => :runway_lead_in_light_system,
960
+ 'RMNDR' => :remainder,
961
+ 'RMK' => :remarks,
962
+ 'RNAV' => :area_navigation,
963
+ 'RPLC' => :replace,
964
+ 'RQRD' => :required,
965
+ 'RRL' => :runway_remaining_lights,
966
+ 'RSR' => :en_route_surveillance_radar,
967
+ 'RSVN' => :reservation,
968
+ 'RT' => :right_turn,
969
+ 'RTE' => :route,
970
+ 'RTR' => :remote_transmitter_receiver,
971
+ 'RTS' => :return_to_service,
972
+ 'RUF' => :rough,
973
+ 'RVR' => :runway_visual_range,
974
+ 'RVRM' => :runway_visual_range_midpoint,
975
+ 'RVRR' => :runway_visual_range_rollout,
976
+ 'RVRT' => :runway_visual_range_touchdown,
977
+ 'RWY' => :runway,
978
+ 'S' => :south,
979
+ 'SA' => :sand,
980
+ 'SAT' => :saturday,
981
+ 'SAWRS' => :supplementary_aviation_weather_reporting_station,
982
+ 'SB' => :southbound,
983
+ 'SDF' => :simplified_directional_facility,
984
+ 'SE' => :southeast,
985
+ 'SFL' => :sequence_flashing_lights,
986
+ 'SIMUL' => :simultaneous,
987
+ 'SIR' => :packed_snow_and_ice_on_runway,
988
+ 'SKED' => :schedule,
989
+ 'SLR' => :slush_on_runway,
990
+ 'SN' => :snow,
991
+ 'SNBNK' => :snowbanks_caused_by_plowing,
992
+ 'SNGL' => :single,
993
+ 'SPD' => :speed,
994
+ 'SSALF' => :simplified_short_approach_lighting_with_sequence_flashers,
995
+ 'SSALR' => :simplified_short_approach_lighting_with_runway_alignment_indicator_lights,
996
+ 'SSALS' => :simplified_short_approach_lighting_system,
997
+ 'SSR' => :secondary_surveillance_radar,
998
+ 'STA' => :straight_in_approach,
999
+ 'STAR' => :standard_terminal_arrival,
1000
+ 'SUN' => :sunday,
1001
+ 'SVC' => :service,
1002
+ 'SVN' => :satellite_vehicle_number,
1003
+ 'SW' => :southwest,
1004
+ 'SWEPT' => :swept,
1005
+ 'T' => :temperature,
1006
+ 'TACAN' => :tactical_air_navigational_aid,
1007
+ 'TAR' => :terminal_area_surveillance_radar,
1008
+ 'TDWR' => :terminal_doppler_weather_radar,
1009
+ 'TDZ' => :touchdown_zone,
1010
+ 'TEMPO' => :temporary_or_temporarily,
1011
+ 'TFC' => :traffic,
1012
+ 'TFR' => :temporary_flight_restriction,
1013
+ 'TGL' => :touch_and_go_landings,
1014
+ 'THN' => :thin,
1015
+ 'THR' => :threshold,
1016
+ 'THRU' => :through,
1017
+ 'THU' => :thursday,
1018
+ 'TIL' => :until,
1019
+ 'TKOF' => :takeoff,
1020
+ 'TM' => :traffic_management,
1021
+ 'TMPA' => :traffic_management_program_alert,
1022
+ 'TRML' => :terminal,
1023
+ 'TRNG' => :training,
1024
+ 'TRSN' => :transition,
1025
+ 'TSNT' => :transient,
1026
+ 'TUE' => :tuesday,
1027
+ 'TWR' => :airport_control_tower,
1028
+ 'TWY' => :taxiway,
1029
+ 'UAV' => :unmanned_air_vehicles,
1030
+ 'UFN' => :until_further_notice,
1031
+ 'UNAVBL' => :unavailable,
1032
+ 'UNLGTD' => :unlighted,
1033
+ 'UNMKD' => :unmarked,
1034
+ 'UNMNT' => :unmonitored,
1035
+ 'UNREL' => :unreliable,
1036
+ 'UNUSBL' => :unusable,
1037
+ 'VASI' => :visual_approach_slope_indicator_system,
1038
+ 'VDP' => :visual_descent_point,
1039
+ 'VIA' => :by_way_of,
1040
+ 'VICE' => :versus,
1041
+ 'VIS' => :visibility,
1042
+ 'VMC' => :visual_meteorological_conditions,
1043
+ 'VOL' => :volume,
1044
+ 'VORTAC' => :vor_and_tacan,
1045
+ 'W' => :west,
1046
+ 'WB' => :westbound,
1047
+ 'WED' => :wednesday,
1048
+ 'WEF' => :with_effect_from_or_effective_from,
1049
+ 'WI' => :within,
1050
+ 'WIE' => :with_immediate_effect_or_effective_immediately,
1051
+ 'WIP' => :work_in_progress,
1052
+ 'WKDAYS' => :monday_through_friday,
1053
+ 'WKEND' => :saturday_and_sunday,
1054
+ 'WND' => :wind,
1055
+ 'WPT' => :waypoint,
1056
+ 'WSR' => :wet_snow_on_runway,
1057
+ 'WTR' => :water_on_runway,
1058
+ 'WX' => :weather
1059
+ }.freeze
1060
+
1061
+ end
1062
+
1063
+