aipp 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -2
  3. data/CHANGELOG.md +17 -1
  4. data/README.md +269 -150
  5. data/exe/aip2aixm +2 -8
  6. data/exe/aip2ofmx +2 -8
  7. data/exe/notam2aixm +5 -0
  8. data/exe/notam2ofmx +5 -0
  9. data/lib/aipp/aip/README.md +10 -0
  10. data/lib/aipp/aip/executable.rb +40 -0
  11. data/lib/aipp/aip/parser.rb +9 -0
  12. data/lib/aipp/aip/runner.rb +85 -0
  13. data/lib/aipp/border.rb +2 -2
  14. data/lib/aipp/debugger.rb +14 -19
  15. data/lib/aipp/downloader/file.rb +57 -0
  16. data/lib/aipp/downloader/graphql.rb +29 -0
  17. data/lib/aipp/downloader/http.rb +48 -0
  18. data/lib/aipp/downloader.rb +78 -29
  19. data/lib/aipp/environment.rb +88 -0
  20. data/lib/aipp/executable.rb +36 -53
  21. data/lib/aipp/notam/README.md +25 -0
  22. data/lib/aipp/notam/executable.rb +27 -0
  23. data/lib/aipp/notam/parser.rb +9 -0
  24. data/lib/aipp/notam/runner.rb +28 -0
  25. data/lib/aipp/parser.rb +133 -160
  26. data/lib/aipp/patcher.rb +4 -5
  27. data/lib/aipp/regions/LF/README.md +6 -2
  28. data/lib/aipp/regions/LF/aip/aerodromes.rb +220 -0
  29. data/lib/aipp/regions/LF/aip/d_p_r_airspaces.rb +53 -0
  30. data/lib/aipp/regions/LF/aip/dangerous_activities.rb +48 -0
  31. data/lib/aipp/regions/LF/aip/designated_points.rb +44 -0
  32. data/lib/aipp/regions/LF/aip/helipads.rb +119 -0
  33. data/lib/aipp/regions/LF/aip/navigational_aids.rb +82 -0
  34. data/lib/aipp/regions/LF/aip/obstacles.rb +150 -0
  35. data/lib/aipp/regions/LF/aip/serviced_airspaces.rb +67 -0
  36. data/lib/aipp/regions/LF/aip/services.rb +169 -0
  37. data/lib/aipp/regions/LF/fixtures/aerodromes.yml +2 -2
  38. data/lib/aipp/regions/LF/helpers/base.rb +32 -32
  39. data/lib/aipp/regions/LS/README.md +59 -0
  40. data/lib/aipp/regions/LS/helpers/base.rb +111 -0
  41. data/lib/aipp/regions/LS/notam/ENR.rb +173 -0
  42. data/lib/aipp/runner.rb +152 -0
  43. data/lib/aipp/version.rb +1 -1
  44. data/lib/aipp.rb +30 -11
  45. data/lib/core_ext/array.rb +13 -0
  46. data/lib/core_ext/nokogiri.rb +56 -8
  47. data/lib/core_ext/string.rb +63 -1
  48. data.tar.gz.sig +0 -0
  49. metadata +115 -64
  50. metadata.gz.sig +0 -0
  51. data/lib/aipp/aip.rb +0 -166
  52. data/lib/aipp/regions/LF/aerodromes.rb +0 -223
  53. data/lib/aipp/regions/LF/d_p_r_airspaces.rb +0 -56
  54. data/lib/aipp/regions/LF/dangerous_activities.rb +0 -49
  55. data/lib/aipp/regions/LF/designated_points.rb +0 -47
  56. data/lib/aipp/regions/LF/helipads.rb +0 -122
  57. data/lib/aipp/regions/LF/navigational_aids.rb +0 -85
  58. data/lib/aipp/regions/LF/obstacles.rb +0 -153
  59. data/lib/aipp/regions/LF/serviced_airspaces.rb +0 -70
  60. data/lib/aipp/regions/LF/services.rb +0 -172
@@ -1,172 +0,0 @@
1
- module AIPP
2
- module LF
3
-
4
- class Services < AIP
5
-
6
- include AIPP::LF::Helpers::Base
7
-
8
- DEPENDS = %w(aerodromes serviced_airspaces)
9
-
10
- # Service types and how to treat them
11
- SOURCE_TYPES = {
12
- 'A/A' => :address,
13
- 'AFIS' => :service,
14
- 'APP' => :service,
15
- 'ATIS' => :service,
16
- 'CCM' => :ignore, # centre de contrôle militaire
17
- 'CEV' => :ignore, # centre d’essai en vol
18
- 'D-ATIS' => :ignore, # data link ATIS
19
- 'FIS' => :service,
20
- 'PAR' => :service,
21
- 'SRE' => :ignore, # surveillance radar element of PAR
22
- 'TWR' => :service,
23
- 'UAC' => :ignore, # upper area control
24
- 'VDF' => :service,
25
- 'OTHER' => :service # no <Service> specified at source
26
- }.freeze
27
-
28
- # Map French callsigns to English and service type
29
- CALLSIGNS = {
30
- 'Approche' => { en: 'Approach', service_type: 'APP' },
31
- 'Contrôle' => { en: 'Control', service_type: 'ACS' },
32
- 'Information' => { en: 'Information', service_type: 'FIS' },
33
- 'GCA' => { en: 'GCA', service_type: 'GCA' },
34
- 'Gonio' => { en: 'Gonio', service_type: 'VDF' },
35
- 'Prévol' => { en: 'Delivery', service_type: 'SMC' },
36
- 'Sol' => { en: 'Ground', service_type: 'SMC' },
37
- 'Tour' => { en: 'Tower', service_type: 'TWR' },
38
- 'Trafic' => { en: 'Apron', service_type: 'SMC' }
39
- }.freeze
40
-
41
- def parse
42
- cache.service.css(%Q(Service[lk^="[LF]"][pk])).each do |service_node|
43
- # Ignore private services/frequencies
44
- next if service_node.(:IndicLieu) == 'XX'
45
- # Load referenced airport
46
- airport = given(service_node.at_css('Ad')&.attr('pk')) do
47
- find_by(:airport, meta: _1).first
48
- end
49
- # Build addresses and services
50
- case SOURCE_TYPES.fetch(type_for(service_node))
51
- when :address
52
- fail "dangling address without airport" unless airport
53
- addresses_from(service_node).each { airport.add_address(_1) }
54
- when :service
55
- given service_from(service_node) do |service|
56
- cache.frequence.css(%Q(Frequence:has(Service[pk="#{service_node['pk']}"]))).each do |frequence_node|
57
- if frequency = frequency_from(frequence_node, service_node)
58
- service.add_frequency frequency
59
- end
60
- end
61
- if airport
62
- airport.add_unit(service.unit) if airport.units.find(service.unit).none?
63
- airport.add_service(service) if airport.services.find(service).none?
64
- end
65
- given service_node.at_css('Espace')&.attr('pk') do |espace_pk|
66
- find_by(:airspace, meta: espace_pk).each do |airspace|
67
- airspace.layers.each { _1.add_service(service) }
68
- end
69
- end
70
- end
71
- end
72
- end
73
- # Assign fallback address (default A/A frequency) to all yet radioless airports
74
- find_by(:airport).each do |airport|
75
- unless airport.services.find_by(:service, type: :aerodrome_control_tower_service).any? || airport.addresses.any?
76
- airport.add_address(fallback_address_for(airport.name))
77
- end
78
- end
79
- end
80
-
81
- private
82
-
83
- def type_for(service_node)
84
- SOURCE_TYPES.include?(type = service_node.(:Service)) ? type : 'OTHER'
85
- end
86
-
87
- def addresses_from(service_node)
88
- cache.frequence.css(%Q(Frequence:has(Service[pk="#{service_node['pk']}"]))).map do |frequence_node|
89
- if frequency = frequency_from(frequence_node, service_node)
90
- AIXM.address(
91
- type: :radio_frequency,
92
- address: frequency.transmission_f
93
- ).tap do |address|
94
- address.remarks = {
95
- 'type' => service_node.(:Service),
96
- 'indicatif/callsign' => frequency.callsigns.map { "#{_2} (#{_1})" }.join("/n")
97
- }.to_remarks
98
- end
99
- end
100
- end.compact
101
- end
102
-
103
- def fallback_address_for(callsign)
104
- AIXM.address(
105
- type: :radio_frequency,
106
- address: AIXM.f(123.5, :mhz)
107
- ).tap do |address|
108
- address.remarks = {
109
- 'type' => 'A/A',
110
- 'indicatif/callsign' => callsign
111
- }.to_remarks
112
- end
113
- end
114
-
115
- def service_from(service_node)
116
- service_type = CALLSIGNS.dig(service_node.(:IndicService), :service_type) || type_for(service_node)
117
- service = find_by(:service, type: service_type).first
118
- unit = service&.unit
119
- unless service
120
- service = AIXM.service(type: service_type)
121
- unit = find_by(:unit, name: service_node.(:IndicLieu), type: service.guessed_unit_type).first
122
- unless unit
123
- unit = AIXM.unit(
124
- source: source(section: 'GEN', position: service_node.line),
125
- organisation: organisation_lf,
126
- name: service_node.(:IndicLieu),
127
- type: service.guessed_unit_type,
128
- class: :icao
129
- )
130
- add unit
131
- end
132
- unit.add_service service
133
- service
134
- end
135
- end
136
-
137
- def frequency_from(frequence_node, service_node)
138
- frequency = frequence_node.(:Frequence).to_f
139
- case
140
- when frequency >= 137
141
- nil
142
- when frequency < 108
143
- warn("ignoring too low frequency `#{frequency}'", severe: false)
144
- nil
145
- else
146
- AIXM.frequency(
147
- transmission_f: AIXM.f(frequency, :mhz),
148
- callsigns: callsigns_from(service_node)
149
- ).tap do |frequency|
150
- frequency.timetable = timetable_from(frequence_node.(:HorCode))
151
- frequency.remarks = frequence_node.(:Remarque)
152
- end
153
- end
154
- end
155
-
156
- def callsigns_from(service_node)
157
- if service_node.(:IndicService) == '.' # auto-information
158
- %i(fr en).to_h { [_1, '(auto)'] }
159
- else
160
- warn("language other than french") unless service_node.(:Langue) == 'fr'
161
- english = CALLSIGNS.fetch(service_node.(:IndicService)).fetch(:en)
162
- warn("no english translation for callsign `#{service_node.(:IndicService)}'") unless english
163
- {
164
- fr: "#{service_node.(:IndicLieu)} #{service_node.(:IndicService)}",
165
- en: ("#{service_node.(:IndicLieu)} #{english}" if english)
166
- }.compact
167
- end
168
- end
169
-
170
- end
171
- end
172
- end