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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aipp
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sven Schwyn
@@ -10,27 +10,26 @@ bindir: exe
10
10
  cert_chain:
11
11
  - |
12
12
  -----BEGIN CERTIFICATE-----
13
- MIIDcDCCAligAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MQ0wCwYDVQQDDARydWJ5
14
- MRkwFwYKCZImiZPyLGQBGRYJYml0Y2V0ZXJhMRMwEQYKCZImiZPyLGQBGRYDY29t
15
- MB4XDTIxMTEwODE0MzIyM1oXDTIyMTEwODE0MzIyM1owPzENMAsGA1UEAwwEcnVi
16
- eTEZMBcGCgmSJomT8ixkARkWCWJpdGNldGVyYTETMBEGCgmSJomT8ixkARkWA2Nv
17
- bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANwuD4geNdhpSVNJTtHb
18
- fmVAoPxmER4oyGgaVJSidn/OjU5PcpdypMI/WIxfvjfFizq6kQYAsJZbCr6fG+UN
19
- 2dZGMXcAC/uKQL5nYESjCPJ4IJP/SC+fiiEpxHQk7PNFoiUVRUieUZIAfHZAdnY3
20
- ye1/niW7ud0vwKIMrysKWxjgkE0Y6Af1QLzV/6brVRRC5MvHIzYJd8BiSP+wY1O8
21
- VElw1f6d90KEz2vaQfX7vCxrzIbvAnYiSvM0AIPy/zigTqpW6w3w4sQxQj81oQ9U
22
- 9vDYtQzXj0c9VrSLvb0DgiGug2cU2bDjA4L3cBE1szX4tbfo8syYqMq51/kTGDxW
23
- YNUCAwEAAaN3MHUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFJ8r
24
- wy1HraZDqg3Khf9UonMWMtJUMB0GA1UdEQQWMBSBEnJ1YnlAYml0Y2V0ZXJhLmNv
25
- bTAdBgNVHRIEFjAUgRJydWJ5QGJpdGNldGVyYS5jb20wDQYJKoZIhvcNAQEFBQAD
26
- ggEBACI7lJKRbnRjz0T4Wb9jH4SE0A2yaHAoBzj96luVDjNyoRT3688trEZS75Sg
27
- GKfChxqKncBrSpxJ0YfWbymNHfUrKhcdSifJ/TtUrTasm6LSnJYLOnLKDO3v8eL3
28
- gRTq8a5wA7Xtijx3MJEyzdeUh7N+UMKuPps/flPgH5yabUxgxrvuhrXF7Z96nrsP
29
- EOmNMTc8H7wo4BAKfuMcI/Gh2oCf+tAhr0bGsXyBikmJ6XA45mrOMgv19M1+aMpn
30
- 1+2Y1+i+4jd1B7qxIgOLxQTNIJiwE0sqU1itFfuesfgUACS7M0IV9u9Bp4hBGNEw
31
- 5JcY2h7owdMxXIvgk1oakgldFJc=
13
+ MIIDODCCAiCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhydWJ5
14
+ L0RDPWJpdGNldGVyYS9EQz1jb20wHhcNMjIxMTA2MTIzNjUwWhcNMjMxMTA2MTIz
15
+ NjUwWjAjMSEwHwYDVQQDDBhydWJ5L0RDPWJpdGNldGVyYS9EQz1jb20wggEiMA0G
16
+ CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDcLg+IHjXYaUlTSU7R235lQKD8ZhEe
17
+ KMhoGlSUonZ/zo1OT3KXcqTCP1iMX743xYs6upEGALCWWwq+nxvlDdnWRjF3AAv7
18
+ ikC+Z2BEowjyeCCT/0gvn4ohKcR0JOzzRaIlFUVInlGSAHx2QHZ2N8ntf54lu7nd
19
+ L8CiDK8rClsY4JBNGOgH9UC81f+m61UUQuTLxyM2CXfAYkj/sGNTvFRJcNX+nfdC
20
+ hM9r2kH1+7wsa8yG7wJ2IkrzNACD8v84oE6qVusN8OLEMUI/NaEPVPbw2LUM149H
21
+ PVa0i729A4IhroNnFNmw4wOC93ARNbM1+LW36PLMmKjKudf5Exg8VmDVAgMBAAGj
22
+ dzB1MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBSfK8MtR62mQ6oN
23
+ yoX/VKJzFjLSVDAdBgNVHREEFjAUgRJydWJ5QGJpdGNldGVyYS5jb20wHQYDVR0S
24
+ BBYwFIEScnVieUBiaXRjZXRlcmEuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQAYG2na
25
+ ye8OE2DANQIFM/xDos/E4DaPWCJjX5xvFKNKHMCeQYPeZvLICCwyw2paE7Otwk6p
26
+ uvbg2Ks5ykXsbk5i6vxDoeeOLvmxCqI6m+tHb8v7VZtmwRJm8so0eSX0WvTaKnIf
27
+ CAn1bVUggczVdNoBXw9WAILKyw9bvh3Ft740XZrR74sd+m2pGwjCaM8hzLvrVbGP
28
+ DyYhlBeRWyQKQ0WDIsiTSRhzK8HwSTUWjvPwx7SEdIU/HZgyrk0ETObKPakVu6bH
29
+ kAyiRqgxF4dJviwtqI7mZIomWL63+kXLgjOjMe1SHxfIPo/0ji6+r1p4KYa7o41v
30
+ fwIwU1MKlFBdsjkd
32
31
  -----END CERTIFICATE-----
33
- date: 2022-03-05 00:00:00.000000000 Z
32
+ date: 2022-11-20 00:00:00.000000000 Z
34
33
  dependencies:
35
34
  - !ruby/object:Gem::Dependency
36
35
  name: airac
@@ -39,6 +38,9 @@ dependencies:
39
38
  - - "~>"
40
39
  - !ruby/object:Gem::Version
41
40
  version: '1.0'
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.0.1
42
44
  type: :runtime
43
45
  prerelease: false
44
46
  version_requirements: !ruby/object:Gem::Requirement
@@ -46,11 +48,37 @@ dependencies:
46
48
  - - "~>"
47
49
  - !ruby/object:Gem::Version
48
50
  version: '1.0'
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 1.0.1
49
54
  - !ruby/object:Gem::Dependency
50
55
  name: aixm
51
56
  requirement: !ruby/object:Gem::Requirement
52
57
  requirements:
53
58
  - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1'
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 1.3.2
64
+ type: :runtime
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: '1'
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 1.3.2
74
+ - !ruby/object:Gem::Dependency
75
+ name: notam
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '1'
81
+ - - ">="
54
82
  - !ruby/object:Gem::Version
55
83
  version: '1.1'
56
84
  type: :runtime
@@ -58,6 +86,9 @@ dependencies:
58
86
  version_requirements: !ruby/object:Gem::Requirement
59
87
  requirements:
60
88
  - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '1'
91
+ - - ">="
61
92
  - !ruby/object:Gem::Version
62
93
  version: '1.1'
63
94
  - !ruby/object:Gem::Dependency
@@ -74,6 +105,34 @@ dependencies:
74
105
  - - "~>"
75
106
  - !ruby/object:Gem::Version
76
107
  version: '7'
108
+ - !ruby/object:Gem::Dependency
109
+ name: excon
110
+ requirement: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - "~>"
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ type: :runtime
116
+ prerelease: false
117
+ version_requirements: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - "~>"
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ - !ruby/object:Gem::Dependency
123
+ name: graphql-client
124
+ requirement: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - "~>"
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ type: :runtime
130
+ prerelease: false
131
+ version_requirements: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - "~>"
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
77
136
  - !ruby/object:Gem::Dependency
78
137
  name: nokogiri
79
138
  requirement: !ruby/object:Gem::Requirement
@@ -206,20 +265,6 @@ dependencies:
206
265
  - - ">="
207
266
  - !ruby/object:Gem::Version
208
267
  version: '0'
209
- - !ruby/object:Gem::Dependency
210
- name: minitest-reporters
211
- requirement: !ruby/object:Gem::Requirement
212
- requirements:
213
- - - ">="
214
- - !ruby/object:Gem::Version
215
- version: '0'
216
- type: :development
217
- prerelease: false
218
- version_requirements: !ruby/object:Gem::Requirement
219
- requirements:
220
- - - ">="
221
- - !ruby/object:Gem::Version
222
- version: '0'
223
268
  - !ruby/object:Gem::Dependency
224
269
  name: minitest-sound
225
270
  requirement: !ruby/object:Gem::Requirement
@@ -249,21 +294,7 @@ dependencies:
249
294
  - !ruby/object:Gem::Version
250
295
  version: '0'
251
296
  - !ruby/object:Gem::Dependency
252
- name: minitest-matchers
253
- requirement: !ruby/object:Gem::Requirement
254
- requirements:
255
- - - ">="
256
- - !ruby/object:Gem::Version
257
- version: '0'
258
- type: :development
259
- prerelease: false
260
- version_requirements: !ruby/object:Gem::Requirement
261
- requirements:
262
- - - ">="
263
- - !ruby/object:Gem::Version
264
- version: '0'
265
- - !ruby/object:Gem::Dependency
266
- name: spy
297
+ name: guard
267
298
  requirement: !ruby/object:Gem::Requirement
268
299
  requirements:
269
300
  - - ">="
@@ -277,7 +308,7 @@ dependencies:
277
308
  - !ruby/object:Gem::Version
278
309
  version: '0'
279
310
  - !ruby/object:Gem::Dependency
280
- name: guard
311
+ name: guard-minitest
281
312
  requirement: !ruby/object:Gem::Requirement
282
313
  requirements:
283
314
  - - ">="
@@ -291,7 +322,7 @@ dependencies:
291
322
  - !ruby/object:Gem::Version
292
323
  version: '0'
293
324
  - !ruby/object:Gem::Dependency
294
- name: guard-minitest
325
+ name: yard
295
326
  requirement: !ruby/object:Gem::Requirement
296
327
  requirements:
297
328
  - - ">="
@@ -313,6 +344,8 @@ email:
313
344
  executables:
314
345
  - aip2aixm
315
346
  - aip2ofmx
347
+ - notam2aixm
348
+ - notam2ofmx
316
349
  extensions: []
317
350
  extra_rdoc_files:
318
351
  - README.md
@@ -324,35 +357,53 @@ files:
324
357
  - README.md
325
358
  - exe/aip2aixm
326
359
  - exe/aip2ofmx
360
+ - exe/notam2aixm
361
+ - exe/notam2ofmx
327
362
  - lib/aipp.rb
328
- - lib/aipp/aip.rb
363
+ - lib/aipp/aip/README.md
364
+ - lib/aipp/aip/executable.rb
365
+ - lib/aipp/aip/parser.rb
366
+ - lib/aipp/aip/runner.rb
329
367
  - lib/aipp/border.rb
330
368
  - lib/aipp/debugger.rb
331
369
  - lib/aipp/downloader.rb
370
+ - lib/aipp/downloader/file.rb
371
+ - lib/aipp/downloader/graphql.rb
372
+ - lib/aipp/downloader/http.rb
373
+ - lib/aipp/environment.rb
332
374
  - lib/aipp/executable.rb
375
+ - lib/aipp/notam/README.md
376
+ - lib/aipp/notam/executable.rb
377
+ - lib/aipp/notam/parser.rb
378
+ - lib/aipp/notam/runner.rb
333
379
  - lib/aipp/parser.rb
334
380
  - lib/aipp/patcher.rb
335
381
  - lib/aipp/pdf.rb
336
382
  - lib/aipp/regions/LF/README.md
337
- - lib/aipp/regions/LF/aerodromes.rb
383
+ - lib/aipp/regions/LF/aip/aerodromes.rb
384
+ - lib/aipp/regions/LF/aip/d_p_r_airspaces.rb
385
+ - lib/aipp/regions/LF/aip/dangerous_activities.rb
386
+ - lib/aipp/regions/LF/aip/designated_points.rb
387
+ - lib/aipp/regions/LF/aip/helipads.rb
388
+ - lib/aipp/regions/LF/aip/navigational_aids.rb
389
+ - lib/aipp/regions/LF/aip/obstacles.rb
390
+ - lib/aipp/regions/LF/aip/serviced_airspaces.rb
391
+ - lib/aipp/regions/LF/aip/services.rb
338
392
  - lib/aipp/regions/LF/borders/france_atlantic_coast.geojson
339
393
  - lib/aipp/regions/LF/borders/france_atlantic_territorial_sea.geojson
340
394
  - lib/aipp/regions/LF/borders/france_ecrins_national_park.geojson
341
395
  - lib/aipp/regions/LF/borders/france_mediterranean_coast.geojson
342
- - lib/aipp/regions/LF/d_p_r_airspaces.rb
343
- - lib/aipp/regions/LF/dangerous_activities.rb
344
- - lib/aipp/regions/LF/designated_points.rb
345
396
  - lib/aipp/regions/LF/fixtures/aerodromes.yml
346
- - lib/aipp/regions/LF/helipads.rb
347
397
  - lib/aipp/regions/LF/helpers/base.rb
348
398
  - lib/aipp/regions/LF/helpers/surface.rb
349
399
  - lib/aipp/regions/LF/helpers/usage_limitation.rb
350
- - lib/aipp/regions/LF/navigational_aids.rb
351
- - lib/aipp/regions/LF/obstacles.rb
352
- - lib/aipp/regions/LF/serviced_airspaces.rb
353
- - lib/aipp/regions/LF/services.rb
400
+ - lib/aipp/regions/LS/README.md
401
+ - lib/aipp/regions/LS/helpers/base.rb
402
+ - lib/aipp/regions/LS/notam/ENR.rb
403
+ - lib/aipp/runner.rb
354
404
  - lib/aipp/t_hash.rb
355
405
  - lib/aipp/version.rb
406
+ - lib/core_ext/array.rb
356
407
  - lib/core_ext/enumerable.rb
357
408
  - lib/core_ext/hash.rb
358
409
  - lib/core_ext/integer.rb
@@ -383,14 +434,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
383
434
  requirements:
384
435
  - - ">="
385
436
  - !ruby/object:Gem::Version
386
- version: 3.0.0
437
+ version: 3.1.0
387
438
  required_rubygems_version: !ruby/object:Gem::Requirement
388
439
  requirements:
389
440
  - - ">="
390
441
  - !ruby/object:Gem::Version
391
442
  version: '0'
392
443
  requirements: []
393
- rubygems_version: 3.3.8
444
+ rubygems_version: 3.3.26
394
445
  signing_key:
395
446
  specification_version: 4
396
447
  summary: Parser for aeronautical information publications
metadata.gz.sig CHANGED
Binary file
data/lib/aipp/aip.rb DELETED
@@ -1,166 +0,0 @@
1
- module AIPP
2
-
3
- # @abstract
4
- class AIP
5
- extend Forwardable
6
- include AIPP::Debugger
7
- include AIPP::Patcher
8
-
9
- DEPENDS = []
10
-
11
- # @return [String] AIP name (equal to the parser file name without its
12
- # file extension such as "ENR-2.1" implemented in the file "ENR-2.1.rb")
13
- attr_reader :aip
14
-
15
- # @return [String] AIP file as passed and possibly updated by `url_for`
16
- attr_reader :aip_file
17
-
18
- # @return [Object] Fixture read from YAML file
19
- attr_reader :fixture
20
-
21
- # @!method close
22
- # @see AIPP::Downloader#close
23
- def_delegator :@downloader, :close
24
-
25
- # @!method config
26
- # @see AIPP::Parser#config
27
- # @!method options
28
- # @see AIPP::Parser#options
29
- # @!method borders
30
- # @see AIPP::Parser#borders
31
- # @!method cache
32
- # @see AIPP::Parser#cache
33
- def_delegators :@parser, :aixm, :config, :options, :borders, :cache
34
- private :aixm
35
-
36
- def initialize(aip:, downloader:, fixture:, parser:)
37
- @aip, @downloader, @fixture, @parser = aip, downloader, fixture, parser
38
- setup if respond_to? :setup
39
- end
40
-
41
- # @return [String]
42
- def inspect
43
- "#<AIPP::AIP #{aip}>"
44
- end
45
-
46
- # Read an AIP source file
47
- #
48
- # Read the cached source file if it exists in the source archive. Otherwise,
49
- # download it from URL and cache it.
50
- #
51
- # An URL builder method +url_for(aip_file)+ must be implemented by the AIP
52
- # parser definition (e.g. +ENR-2.1.rb+).
53
- #
54
- # @param aip_file [String] e.g. "ENR-2.1" or "AD-2.LFMV" (default: +aip+
55
- # with section stripped e.g. "AD-1.3-2" -> "AD-1.3")
56
- # @return [Nokogiri::XML::Document, Nokogiri::HTML5::Document,
57
- # Roo::Spreadsheet, String] XML/HTML as Nokogiri document, XLSX/ODS/CSV
58
- # as Roo document, PDF and TXT as String
59
- def read(aip_file=nil)
60
- @aip_file = aip_file || aip.remove(/(?<![A-Z])-\d+$/)
61
- url = url_for(@aip_file) # may update aip_file string
62
- @downloader.read(document: @aip_file, url: url)
63
- end
64
-
65
- # Add feature to AIXM
66
- #
67
- # @param feature [AIXM::Feature] e.g. airport or airspace
68
- # @return [AIXM::Feature] added feature
69
- def add(feature)
70
- verbose_info "adding #{feature.inspect}"
71
- aixm.add_feature feature
72
- feature
73
- end
74
-
75
- # @!method find_by(klass, attributes={})
76
- # Find objects of the given class and optionally with the given attribute
77
- # values previously written to AIXM.
78
- #
79
- # @note This method is delegated to +AIXM::Association::Array+.
80
- # @see https://www.rubydoc.info/gems/aixm/AIXM/Association/Array#find_by-instance_method
81
- #
82
- # @!method find(object)
83
- # Find equal objects previously written to AIXM.
84
- #
85
- # @note This method is delegated to +AIXM::Association::Array+.
86
- # @see https://www.rubydoc.info/gems/aixm/AIXM/Association/Array#find-instance_method
87
- %i(find_by find).each do |method|
88
- define_method method do |*args|
89
- aixm.features.send(method, *args)
90
- end
91
- end
92
-
93
- # @overload given(*objects)
94
- # Return +objects+ unless at least one of them equals nil
95
- #
96
- # @example
97
- # # Instead of this:
98
- # first, last = unless ((first = expensive_first).nil? || (last = expensive_last).nil?)
99
- # [first, last]
100
- # end
101
- #
102
- # # Use the following:
103
- # first, last = given(expensive_first, expensive_last)
104
- #
105
- # @param *objects [Array<Object>] any objects really
106
- # @return [Object] nil if at least one of the objects is nil, given
107
- # objects otherwise
108
- #
109
- # @overload given(*objects)
110
- # Yield +objects+ unless at least one of them equals nil
111
- #
112
- # @example
113
- # # Instead of this:
114
- # name = unless ((first = expensive_first.nil? || (last = expensive_last.nil?)
115
- # "#{first} #{last}"
116
- # end
117
- #
118
- # # Use any of the following:
119
- # name = given(expensive_first, expensive_last) { |f, l| "#{f} #{l}" }
120
- # name = given(expensive_first, expensive_last) { "#{_1} #{_2}" }
121
- #
122
- # @param *objects [Array<Object>] any objects really
123
- # @yield [Array<Object>] objects passed as parameter
124
- # @return [Object] nil if at least one of the objects is nil, return of
125
- # block otherwise
126
- def given(*objects)
127
- if objects.none?(&:nil?)
128
- block_given? ? yield(*objects) : objects
129
- end
130
- end
131
-
132
- # Build and optionally check a Markdown link
133
- #
134
- # @example
135
- # options[:check_links] = false
136
- # link_to('foo', 'https://bar.com/exists') # => "[foo](https://bar.com/exists)"
137
- # link_to('foo', 'https://bar.com/not-found') # => "[foo](https://bar.com/not-found)"
138
- # options[:check_links] = true
139
- # link_to('foo', 'https://bar.com/exists') # => "[foo](https://bar.com/exists)"
140
- # link_to('foo', 'https://bar.com/not-found') # => nil
141
- #
142
- # @params body [String] body text of the link
143
- # @params url [String] URL of the link
144
- # @return [String, nil] Markdown link
145
- def link_to(body, url)
146
- "[#{body}](#{url})" if !options[:check_links] || url_exists?(url)
147
- end
148
-
149
- private
150
-
151
- def url_exists?(url)
152
- uri = URI.parse(url)
153
- Net::HTTP.new(uri.host, uri.port).tap do |request|
154
- request.use_ssl = (uri.scheme == 'https')
155
- path = uri.path.present? ? uri.path : '/'
156
- result = request.request_head(path)
157
- if result.kind_of? Net::HTTPRedirection
158
- url_exist?(result['location'])
159
- else
160
- result.code == '200'
161
- end
162
- end
163
- end
164
-
165
- end
166
- end
@@ -1,223 +0,0 @@
1
- module AIPP
2
- module LF
3
-
4
- class Aerodromes < AIP
5
-
6
- include AIPP::LF::Helpers::Base
7
- include AIPP::LF::Helpers::UsageLimitation
8
- include AIPP::LF::Helpers::Surface
9
-
10
- APPROACH_LIGHTING_TYPES = {
11
- 'CAT I' => :cat_1,
12
- 'CAT II' => :cat_2,
13
- 'CAT III' => :cat_3,
14
- 'CAT II-III' => :cat_2_and_3
15
- }.freeze
16
-
17
- LIGHTING_POSITIONS = {
18
- threshold: 'Thr',
19
- touch_down_zone: 'Tdz',
20
- center_line: 'Axe',
21
- edge: 'Bord',
22
- runway_end: 'Fin',
23
- stopway_center_line: 'Swy'
24
- }.freeze
25
-
26
- LIGHTING_COLORS = {
27
- 'W' => :white,
28
- 'R' => :red,
29
- 'G' => :green,
30
- 'B' => :blue,
31
- 'Y' => :yellow
32
- }.freeze
33
-
34
- ICAO_LIGHTING_COLORS = {
35
- center_line: :white,
36
- edge: :white
37
- }.freeze
38
-
39
- def parse
40
- cache.ad.css(%Q(Ad[lk^="[LF]"])).each do |ad_node|
41
- # Build airport
42
- next unless limitation_type = LIMITATION_TYPES.fetch(ad_node.(:AdStatut))
43
- airport = AIXM.airport(
44
- source: source(section: 'AD', position: ad_node.line),
45
- organisation: organisation_lf,
46
- id: id_from(ad_node.(:AdCode)),
47
- name: ad_node.(:AdNomComplet),
48
- xy: xy_from(ad_node.(:Geometrie))
49
- ).tap do |airport|
50
- airport.meta = ad_node.attr('pk')
51
- airport.z = given(ad_node.(:AdRefAltFt)) { AIXM.z(_1.to_i, :qnh) }
52
- airport.declination = ad_node.(:AdMagVar)&.to_f
53
- airport.add_usage_limitation(type: limitation_type.fetch(:limitation)) do |limitation|
54
- limitation.remarks = limitation_type[:remarks]
55
- [
56
- (:scheduled if ad_node.(:TfcRegulier?)),
57
- (:not_scheduled if ad_node.(:TfcNonRegulier?)),
58
- (:private if ad_node.(:TfcPrive?)),
59
- (:other unless ad_node.(:TfcRegulier?) || ad_node.(:TfcNonRegulier?) || ad_node.(:TfcPrive?))
60
- ].compact.each do |purpose|
61
- limitation.add_condition do |condition|
62
- condition.realm = limitation_type.fetch(:realm)
63
- condition.origin = case
64
- when ad_node.(:TfcIntl?) && ad_node.(:TfcNtl?) then :any
65
- when ad_node.(:TfcIntl?) then :international
66
- when ad_node.(:TfcNtl?) then :national
67
- else :other
68
- end
69
- condition.rule = case
70
- when ad_node.(:TfcIfr?) && ad_node.(:TfcVfr?) then :ifr_and_vfr
71
- when ad_node.(:TfcIfr?) then :ifr
72
- when ad_node.(:TfcVfr?) then :vfr
73
- else
74
- warn("falling back to VFR rule for `#{airport.id}'", severe: false)
75
- :vfr
76
- end
77
- condition.purpose = purpose
78
- end
79
- end
80
- end
81
- # TODO: link to VAC once supported downstream
82
- # # Link to VAC
83
- # airport.remarks = [
84
- # airport.remarks.to_s,
85
- # link_to('VAC-AD', url_for("VAC-#{airport.id}"))
86
- # ].join("\n")
87
- cache.rwy.css(%Q(Rwy:has(Ad[pk="#{ad_node.attr(:pk)}"]))).each do |rwy_node|
88
- add_runway_to(airport, rwy_node)
89
- end
90
- end
91
- add airport
92
- end
93
- end
94
-
95
- private
96
-
97
- def id_from(content)
98
- case content
99
- when /^\d{2}$/ then 'LF00' + content # private aerodromes without official ID
100
- else 'LF' + content
101
- end
102
- end
103
-
104
- def add_runway_to(airport, rwy_node)
105
- AIXM.runway(
106
- name: rwy_node.(:Rwy)
107
- ).tap do |runway|
108
- rwylgt_nodes = cache.rwylgt.css(%Q(RwyLgt:has(Rwy[pk="#{rwy_node.attr(:pk)}"])))
109
- airport.add_runway(runway)
110
- runway.dimensions = AIXM.r(AIXM.d(rwy_node.(:Longueur)&.to_i, :m), AIXM.d(rwy_node.(:Largeur)&.to_i, :m))
111
- runway.surface = surface_from(rwy_node)
112
- runway.forth.geographic_bearing = given(rwy_node.(:OrientationGeo)) { AIXM.a(_1.to_f) }
113
- runway.forth.xy = given(rwy_node.(:LatThr1), rwy_node.(:LongThr1)) { AIXM.xy(lat: _1.to_f, long: _2.to_f) }
114
- runway.forth.displaced_threshold = given(rwy_node.(:LatDThr1), rwy_node.(:LongDThr1)) { AIXM.xy(lat: _1.to_f, long: _2.to_f) }
115
- runway.forth.z = given(rwy_node.(:AltFtDThr1)) { AIXM.z(_1.to_i, :qnh) }
116
- runway.forth.z ||= given(rwy_node.(:AltFtThr1)) { AIXM.z(_1.to_i, :qnh) }
117
- if rwylgt_node = rwylgt_nodes[0]
118
- runway.forth.vasis = vasis_from(rwylgt_node)
119
- given(approach_lighting_from(rwylgt_node)) { runway.forth.add_approach_lighting(_1) }
120
- LIGHTING_POSITIONS.each_key do |position|
121
- given(lighting_from(rwylgt_node, position)) { runway.forth.add_lighting(_1) }
122
- end
123
- end
124
- if rwy_node.(:Rwy).match? '/'
125
- runway.back.xy = given(rwy_node.(:LatThr2), rwy_node.(:LongThr2)) { AIXM.xy(lat: _1.to_f, long: _2.to_f) }
126
- runway.back.displaced_threshold = given(rwy_node.(:LatDThr2), rwy_node.(:LongDThr2)) { AIXM.xy(lat: _1.to_f, long: _2.to_f) }
127
- runway.back.z = given(rwy_node.(:AltFtDThr2)) { AIXM.z(_1.to_i, :qnh) }
128
- runway.back.z ||= given(rwy_node.(:AltFtThr2)) { AIXM.z(_1.to_i, :qnh) }
129
- if rwylgt_node = rwylgt_nodes[1]
130
- runway.back.vasis = vasis_from(rwylgt_node)
131
- given(approach_lighting_from(rwylgt_node)) { runway.back.add_approach_lighting(_1) }
132
- LIGHTING_POSITIONS.each_key do |position|
133
- given(lighting_from(rwylgt_node, position)) { runway.back.add_lighting(_1) }
134
- end
135
- end
136
- end
137
- end
138
- end
139
-
140
- def vasis_from(rwylgt_node)
141
- if rwylgt_node.(:PapiVasis)
142
- AIXM.vasis.tap do |vasis|
143
- vasis.type = rwylgt_node.(:PapiVasis)
144
- vasis.slope_angle = AIXM.a(rwylgt_node.(:PapiVasisPente).to_f)
145
- vasis.meht = AIXM.z(rwylgt_node.(:MehtFt).to_i, :qfe)
146
- end
147
- end
148
- end
149
-
150
- def approach_lighting_from(rwylgt_node)
151
- if rwylgt_node.(:LgtApchCat)
152
- AIXM.approach_lighting(
153
- type: APPROACH_LIGHTING_TYPES.fetch(rwylgt_node.(:LgtApchCat) , :other)
154
- ).tap do |approach_lighting|
155
- approach_lighting.length = AIXM.d(rwylgt_node.(:LgtApchLongueur).to_i, :m) if rwylgt_node.(:LgtApchLongueur)
156
- approach_lighting.intensity = rwylgt_node.(:LgtApchIntensite)&.first_match(/LIH/, /LIM/, /LIL/, default: :other)
157
- approach_lighting.remarks = {
158
- 'type' => (rwylgt_node.(:LgtApchCat) if approach_lighting.type == :other),
159
- 'intensité/intensity' => (rwylgt_node.(:LgtApchIntensite) if approach_lighting.intensity == :other)
160
- }.to_remarks
161
- end
162
- end
163
- end
164
-
165
- def lighting_from(rwylgt_node, position)
166
- prefix = "Lgt" + LIGHTING_POSITIONS.fetch(position)
167
- if rwylgt_node.(:"#{prefix}Couleur") || rwylgt_node.(:"#{prefix}Longueur")
168
- AIXM.lighting(position: position).tap do |lighting|
169
- couleur, intensite = rwylgt_node.(:"#{prefix}Couleur"), rwylgt_node.(:"#{prefix}Intensite")
170
- lighting.intensity = if intensite
171
- intensite.first_match(/LIH/, /LIM/, /LIL/, default: :other)
172
- elsif couleur
173
- couleur.first_match(/LIH/, /LIM/, /LIL/).tap { couleur.remove!(/LIH|LIM|LIL/) }
174
- end
175
- lighting.color = if couleur
176
- if couleur.match? /ICAO|EASA|OACI|AESA/
177
- ICAO_LIGHTING_COLORS[position]
178
- else
179
- couleur.remove(/[^#{LIGHTING_COLORS.keys.join}]/).compact
180
- LIGHTING_COLORS.fetch(couleur, :other)
181
- end
182
- end
183
- lighting.description = {
184
- 'couleur/color' => (rwylgt_node.(:"#{prefix}Couleur") if [nil, :other].include?(lighting.color)),
185
- 'longueur/length' => rwylgt_node.(:"#{prefix}Longueur"),
186
- 'espace/spacing' => rwylgt_node.(:"#{prefix}Espace")
187
- }.to_remarks
188
- lighting.remarks = rwylgt_node.(:LgtRem)
189
- end
190
- end
191
- end
192
-
193
- patch AIXM::Feature::Airport, :xy do |parser, object, value|
194
- throw(:abort) unless coordinate = parser.fixture.dig(object.id, 'xy')
195
- lat, long = coordinate.split(/\s+/)
196
- AIXM.xy(lat: lat, long: long)
197
- end
198
-
199
- patch AIXM::Feature::Airport, :z do |parser, object, value|
200
- throw(:abort) unless value.nil?
201
- throw(:abort, 'fixture missing') unless elevation = parser.fixture.dig(object.id, 'z')
202
- AIXM.z(elevation, :qnh)
203
- end
204
-
205
- patch AIXM::Component::Runway, :dimensions do |parser, object, value|
206
- throw(:abort) unless value.surface.zero?
207
- throw(:abort, 'fixture missing') unless dimensions = parser.fixture.dig(object.airport.id, object.name, 'dimensions')
208
- length, width = dimensions.split(/\D+/)
209
- length = length&.match?(/^\d+$/) ? AIXM.d(length.to_i, :m) : value.length
210
- width = width&.match?(/^\d+$/) ? AIXM.d(width.to_i, :m) : value.width
211
- AIXM.r(length, width).tap { |r| throw(:abort, 'fixture incomplete') if r.surface.zero? }
212
- end
213
-
214
- patch AIXM::Component::Runway::Direction, :xy do |parser, object, value|
215
- throw(:abort) unless value.nil?
216
- throw(:abort, 'fixture missing') unless coordinate = parser.fixture.dig(object.runway.airport.id, object.name.to_s(:runway), 'xy')
217
- lat, long = coordinate.split(/\s+/)
218
- AIXM.xy(lat: lat, long: long)
219
- end
220
-
221
- end
222
- end
223
- end