aipp 0.2.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -0
  3. data/CHANGELOG.md +38 -0
  4. data/README.md +222 -88
  5. data/exe/aip2aixm +2 -2
  6. data/exe/aip2ofmx +2 -2
  7. data/lib/aipp/aip.rb +113 -31
  8. data/lib/aipp/border.rb +77 -46
  9. data/lib/aipp/debugger.rb +101 -0
  10. data/lib/aipp/downloader.rb +39 -26
  11. data/lib/aipp/executable.rb +41 -22
  12. data/lib/aipp/parser.rb +94 -21
  13. data/lib/aipp/patcher.rb +5 -2
  14. data/lib/aipp/pdf.rb +1 -1
  15. data/lib/aipp/regions/LF/README.md +49 -0
  16. data/lib/aipp/regions/LF/aerodromes.rb +223 -0
  17. data/lib/aipp/regions/LF/d_p_r_airspaces.rb +56 -0
  18. data/lib/aipp/regions/LF/dangerous_activities.rb +49 -0
  19. data/lib/aipp/regions/LF/designated_points.rb +47 -0
  20. data/lib/aipp/regions/LF/fixtures/aerodromes.yml +608 -0
  21. data/lib/aipp/regions/LF/helipads.rb +122 -0
  22. data/lib/aipp/regions/LF/helpers/base.rb +218 -0
  23. data/lib/aipp/regions/LF/helpers/surface.rb +49 -0
  24. data/lib/aipp/regions/LF/helpers/usage_limitation.rb +20 -0
  25. data/lib/aipp/regions/LF/navigational_aids.rb +85 -0
  26. data/lib/aipp/regions/LF/obstacles.rb +153 -0
  27. data/lib/aipp/regions/LF/serviced_airspaces.rb +70 -0
  28. data/lib/aipp/regions/LF/services.rb +172 -0
  29. data/lib/aipp/t_hash.rb +4 -5
  30. data/lib/aipp/version.rb +1 -1
  31. data/lib/aipp.rb +11 -5
  32. data/lib/core_ext/enumerable.rb +9 -9
  33. data/lib/core_ext/hash.rb +21 -5
  34. data/lib/core_ext/nokogiri.rb +54 -0
  35. data/lib/core_ext/string.rb +38 -66
  36. data.tar.gz.sig +2 -0
  37. metadata +180 -188
  38. metadata.gz.sig +0 -0
  39. data/.gitignore +0 -8
  40. data/.ruby-version +0 -1
  41. data/.travis.yml +0 -8
  42. data/.yardopts +0 -3
  43. data/Guardfile +0 -7
  44. data/TODO.md +0 -6
  45. data/aipp.gemspec +0 -44
  46. data/gems.rb +0 -3
  47. data/lib/aipp/airac.rb +0 -55
  48. data/lib/aipp/regions/LF/AD-1.3.rb +0 -162
  49. data/lib/aipp/regions/LF/AD-1.6.rb +0 -31
  50. data/lib/aipp/regions/LF/AD-2.rb +0 -313
  51. data/lib/aipp/regions/LF/AD-3.1.rb +0 -185
  52. data/lib/aipp/regions/LF/ENR-2.1.rb +0 -92
  53. data/lib/aipp/regions/LF/ENR-4.1.rb +0 -97
  54. data/lib/aipp/regions/LF/ENR-4.3.rb +0 -28
  55. data/lib/aipp/regions/LF/ENR-5.1.rb +0 -75
  56. data/lib/aipp/regions/LF/ENR-5.5.rb +0 -53
  57. data/lib/aipp/regions/LF/fixtures/AD-1.3.yml +0 -511
  58. data/lib/aipp/regions/LF/fixtures/AD-2.yml +0 -185
  59. data/lib/aipp/regions/LF/fixtures/AD-3.1.yml +0 -10
  60. data/lib/aipp/regions/LF/helpers/AD_radio.rb +0 -90
  61. data/lib/aipp/regions/LF/helpers/URL.rb +0 -26
  62. data/lib/aipp/regions/LF/helpers/common.rb +0 -217
  63. data/lib/core_ext/object.rb +0 -43
  64. data/rakefile.rb +0 -12
  65. data/spec/fixtures/archive.zip +0 -0
  66. data/spec/fixtures/border.geojson +0 -201
  67. data/spec/fixtures/document.pdf +0 -0
  68. data/spec/fixtures/document.pdf.json +0 -1
  69. data/spec/fixtures/new.html +0 -6
  70. data/spec/fixtures/new.pdf +0 -0
  71. data/spec/fixtures/new.txt +0 -1
  72. data/spec/lib/aipp/airac_spec.rb +0 -98
  73. data/spec/lib/aipp/border_spec.rb +0 -135
  74. data/spec/lib/aipp/downloader_spec.rb +0 -81
  75. data/spec/lib/aipp/patcher_spec.rb +0 -46
  76. data/spec/lib/aipp/pdf_spec.rb +0 -124
  77. data/spec/lib/aipp/t_hash_spec.rb +0 -44
  78. data/spec/lib/aipp/version_spec.rb +0 -7
  79. data/spec/lib/core_ext/enumberable_spec.rb +0 -76
  80. data/spec/lib/core_ext/hash_spec.rb +0 -27
  81. data/spec/lib/core_ext/integer_spec.rb +0 -15
  82. data/spec/lib/core_ext/nil_class_spec.rb +0 -11
  83. data/spec/lib/core_ext/string_spec.rb +0 -112
  84. data/spec/sounds/failure.mp3 +0 -0
  85. data/spec/sounds/success.mp3 +0 -0
  86. data/spec/spec_helper.rb +0 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 70da2e53874e0c550cbbacc863ff421cbd38dfc2cb1b7e4d2c77e2821839fdea
4
- data.tar.gz: 62e9d5c5413756490d03f057e8851aba54c7d8802f4012a2f9626f78eb241d6f
3
+ metadata.gz: '09151e277b537c1529951cd69b38bb5d6fc47f855e6041ca3537d36462f93907'
4
+ data.tar.gz: f0b9d43b940ced7998a079cf6dce602386d52ad90995b7e77a6b6429f09f798e
5
5
  SHA512:
6
- metadata.gz: 6508c2a1565fdd92ed4fe2593b883278940e10fa10e68a0ffc75391b7e6d8ba8c66ca19c7e91495da39f60c4257e7882611a235ad9c8a5314b928140625a6e90
7
- data.tar.gz: ade8abd0e5f521faf63b684d719c1e71a85278ec57f56edf4c83349c1ca4fc68422c9948c74f059c064cbb6ec21d66c91216f6418d3749bd53dd6eb1ecca24cc
6
+ metadata.gz: 205b609c8aad3999495447f7c55aba98282b5b6347a4f89caef3e06e3edc8f8e28c4e523cc48737522f895813309fe9d4f7b8d3d2d0db37a12d5808c41509137
7
+ data.tar.gz: 9a228dd7a152dfd5e0bbbd22b8a068e8de404ba9a4d48f4a30f7b3f0b352c694f12b4a45b543880b20884645fbd52fa475dd738f7385541113462dcadce1fc29
checksums.yaml.gz.sig ADDED
@@ -0,0 +1,2 @@
1
+ `��˼��e����z�t��pR3�^±�ܛ�Q�.ܾ�`�ާz|�/����rH��.c JS�@�,W��&v����C1�8�"�u��Mʡ��2| �&5tp[q�MD^�T'�C��:���2#]Zu}�oP�~ ����� �@��nE�NÞJ�4~��kW
2
+ �}�T�v����/;��E� ��P�_"��KR���lWz��^�d/�l�9KY��-+'��wY�����1R�Z[_���bv���*V��(�;�
data/CHANGELOG.md CHANGED
@@ -1,3 +1,41 @@
1
+ ## Main
2
+
3
+ Nothing so far
4
+
5
+ ## 1.0.0
6
+
7
+ #### Breaking Changes
8
+ * Switch from individual AIP HTML section files to the comprehensive AIP XML
9
+ database dump for the LF region reference implementation.
10
+ * Drop the mandatory `URL` helper in favour of a mandatory `url_for` method.
11
+ * Renamed default git branch to `main`
12
+ * Improve calculation of short feature hash in manifest in order to include
13
+ e.g. geometries of airspaces.
14
+
15
+ #### Changes
16
+ * Switch from `pry` to `debug`
17
+
18
+ #### Additions
19
+ * Unsevere warnings
20
+ * Support for .xlsx, .ods and .csv files
21
+
22
+ ## 0.2.6
23
+
24
+ #### Additions
25
+ * Detect duplicate features
26
+
27
+ #### Changes
28
+ * Require Ruby 2.7
29
+
30
+ ## 0.2.5
31
+
32
+ #### Additions
33
+ * LF/AD-2>2.19 (AD navigational aids relevant to VFR)
34
+ * Write build and manifest to `~/.aipp/<region>/builds`
35
+
36
+ #### Changes
37
+ * Renamed `~/.aipp/<region>/archive` to `~/.aipp/<region>/sources`
38
+
1
39
  ## 0.2.4
2
40
 
3
41
  #### Additions
data/README.md CHANGED
@@ -1,36 +1,111 @@
1
1
  [![Version](https://img.shields.io/gem/v/aipp.svg?style=flat)](https://rubygems.org/gems/aipp)
2
- [![Continuous Integration](https://img.shields.io/travis/svoop/aipp/master.svg?style=flat)](https://travis-ci.org/svoop/aipp)
2
+ [![Tests](https://img.shields.io/github/workflow/status/svoop/aipp/Test.svg?style=flat&label=tests)](https://github.com/svoop/aipp/actions?workflow=Test)
3
3
  [![Donorbox](https://img.shields.io/badge/donate-on_donorbox-yellow.svg)](https://donorbox.org/bitcetera)
4
4
 
5
5
  # AIPP
6
6
 
7
7
  Parser for Aeronautical Information Publication (AIP) available online.
8
8
 
9
- This gem incluces two executables to download and parse aeronautical data as HTML or PDF, then export is as [AIXM](https://github.com/svoop/aixm) or [OFMX](https://github.com/openflightmaps/ofmx/wiki).
9
+ This gem incluces two executables to download and parse aeronautical data as HTML, PDF, XSLX, ODS and CSV, then build and export is as [AIXM](https://github.com/svoop/aixm) or [OFMX](https://github.com/openflightmaps/ofmx/wiki).
10
10
 
11
11
  * [Homepage](https://github.com/svoop/aipp)
12
12
  * [Rubydoc](https://www.rubydoc.info/gems/aipp/AIPP)
13
13
  * Author: [Sven Schwyn - Bitcetera](http://www.bitcetera.com)
14
14
 
15
+ ## Table of Contents
16
+
17
+ [Install](#install)<br>
18
+ [Usage](#usage)<br>
19
+ [Storage](#storage)<br>
20
+ [Regions](#regions)<br>
21
+ [AIRAC Date Calculations](#airac-date-calculations)<br>
22
+ [References](#references)<br>
23
+ [Development](#development)
24
+
15
25
  ## Install
16
26
 
17
- Add this to your <tt>Gemfile</tt>:
27
+ ### Security
28
+
29
+ This gem is [cryptographically signed](https://guides.rubygems.org/security/#using-gems) in order to assure it hasn't been tampered with. Unless already done, please add the author's public key as a trusted certificate now:
30
+
31
+ ```
32
+ gem cert --add <(curl -Ls https://raw.github.com/svoop/aipp/main/certs/svoop.pem)
33
+ ```
34
+
35
+ ### Standalone
36
+
37
+ Make sure to have the [latest version of Ruby](https://www.ruby-lang.org/en/documentation/installation/) and then install this gem:
38
+
39
+ ```
40
+ gem install aipp --trust-policy MediumSecurity
41
+ ```
42
+
43
+ ### Bundler
44
+
45
+ If you're familiar with [Bundler](https://bundler.io) powered Ruby projects, you might prefer to add the following to your <tt>Gemfile</tt> or <tt>gems.rb</tt>:
18
46
 
19
47
  ```ruby
20
48
  gem aipp
21
49
  ```
22
50
 
51
+ And then install the bundle:
52
+
53
+ ```
54
+ bundle install --trust-policy MediumSecurity
55
+ ```
56
+
23
57
  ## Usage
24
58
 
59
+ See the built-in help for all options:
60
+
25
61
  ```
26
62
  aip2aixm --help
27
63
  aip2ofmx --help
28
64
  ```
29
65
 
66
+ Say, you with to build the complete OFMX file for the current AIRAC cycle of the region LF:
67
+
68
+ ```
69
+ aip2ofmx -r LF
70
+ ```
71
+
72
+ You'll find the OFMX file in the current directory if the binary exits successfully.
73
+
30
74
  ## Storage
31
75
 
32
76
  AIPP uses a storage directory for configuration, caching and in order to keep the results of previous runs. The default location is `~/.aipp`, however, you can pass a different directory with the `--storage` argument.
33
77
 
78
+ You'll find a directory for each region which contains the following items:
79
+
80
+ * `sources/`<br>This directory contains one ZIP archive per AIRAC cycle which incrementially caches all source files used to build the AIXM/OFMX file. Therefore, to make sure it contains all source files for a region, you have to build at least one complete AIXM/OFMX file for that region.
81
+ * `builds/`<br>This directory contains one ZIP archive per AIRAC cycle which is overwritten on every run. Therefore, to make sure it contains the complete build for a region, you have to make sure that your last run builds the complete AIXM/OFMX for that region. This archive contains:
82
+ * the built AIXM/OFMX file
83
+ * `build.yaml` – context of the build process
84
+ * `manifest.csv` – diffable manifest (see below)
85
+ * `config.yml`<br>This file contains configuration which will be read on subsequent runs, most notably the namespace UUID used to identify the creator of OFMX files.
86
+
87
+ The manifest is a CSV which lists every feature on a separate line along with its hashes, AIP and comment. You can `diff` or `git diff` two manifests:
88
+
89
+ ```diff
90
+ $ git diff -U0 2019-09-12/manifest.csv 2019-10-10/manifest.csv
91
+
92
+ --- a/2019-09-12/manifest.csv
93
+ +++ b/2019-10-10/manifest.csv
94
+ @@ -204 +204 @@ AD-1.3,Ahp,9e9f031e,d6f22057,Airport: LFLJ COURCHEVEL
95
+ -AD-1.3,Ahp,9f1eed18,37ddbbde,Airport: LFQD ARRAS ROCLINCOURT
96
+ +AD-1.3,Ahp,9f1eed18,f0e60105,Airport: LFQD ARRAS ROCLINCOURT
97
+ @@ -312 +312 @@ AD-2,Aha,4250c9ee,04d49dc7,Address: RADIO for LFHV
98
+ -AD-2,Aha,6b381b32,fb947716,Address: RADIO for LFPO
99
+ +AD-2,Aha,6b381b32,b9723b7e,Address: RADIO for LFPO
100
+ @@ -664 +663,0 @@ AD-2,Ser,3920a7fd,4545c5eb,Service: AFIS by LFGA TWR
101
+ -AD-2,Ser,39215774,1f13f2cf,Service: APP by LFCR APP
102
+ @@ -878 +876,0 @@ AD-2,Ser,bb5228d7,7cfb4572,Service: TWR by LFMH TWR
103
+ -AD-2,Ser,bc72caf2,0a15b39c,Service: FIS by LFCR FIC
104
+ (...)
105
+ ```
106
+
107
+ The advantage of `git diff` is it's ability to hightlight exactly which part of a line has changed. [Check out this post to learn how](https://www.viget.com/articles/dress-up-your-git-diffs-with-word-level-highlights/).
108
+
34
109
  ## Regions
35
110
 
36
111
  The reference implementation is region "LF" (France).
@@ -48,6 +123,24 @@ module AIPP
48
123
 
49
124
  DEPENDS = %w(ENR-2.1 ENR-2.2) # declare dependencies to other AIPs
50
125
 
126
+ end
127
+ end
128
+ end
129
+ ```
130
+
131
+ The class has to implement some methods either in the class itself or in a [helper](#Helpers) included by the class.
132
+
133
+ ⚠️ Parser files usually follow AIP naming conventions such as `ENR-4.3`. However, you're free to use arbitrary naming for parser files e.g. if you're working with one big data source which contains the full AIP dataset.
134
+
135
+ #### Mandatory `parse` Method
136
+
137
+ The class must implement the `parse` method which contains the code to read, parse and write the data:
138
+
139
+ ```ruby
140
+ module AIPP
141
+ module LF
142
+ class ENR43 < AIP
143
+
51
144
  def parse
52
145
  html = read # read the Nokogiri::HTML5 document
53
146
  feature = (...) # build the feature
@@ -68,8 +161,8 @@ module AIPP
68
161
 
69
162
  def parse
70
163
  %i(one two three).each do |part|
71
- html = read(aip_file: "#{aip}.#{part}") # read with a non-standard name
72
- support_html = read(aip_file: 'AD-0.6') # maybe read necessary support documents
164
+ html = read("#{aip}.#{part}") # read with a non-standard name
165
+ support_html = read('AD-0.6') # maybe read necessary support documents
73
166
  (...)
74
167
  end
75
168
  end
@@ -81,24 +174,85 @@ end
81
174
 
82
175
  Inside the `parse` method, you have access to the following methods:
83
176
 
84
- * [`read`](https://www.rubydoc.info/gems/aipp/AIPP/AIP#read-instance_method) – download and read an AIP file
85
- * [`add`](https://www.rubydoc.info/gems/aipp/AIPP/AIP#add-instance_method) – add a [`AIXM::Feature`](https://www.rubydoc.info/gems/aixm/AIXM/Feature)
86
- * [`select`](https://www.rubydoc.info/gems/aipp/AIPP/AIP#find-instance_method search previously written [`AIXM::Feature`s](https://www.rubydoc.info/gems/aixm/AIXM/Feature)
87
- * some core extensions from ActiveSupport – [`Object#blank`](https://www.rubydoc.info/gems/activesupport/Object#blank%3F-instance_method) and [`String`](https://www.rubydoc.info/gems/activesupport/String)
88
- * core extensions from this gem – [`Object`](https://www.rubydoc.info/gems/aipp/Object), [`NilClass`](https://www.rubydoc.info/gems/aipp/NilClass), [`Integer`](https://www.rubydoc.info/gems/aipp/Integer), [`String`](https://www.rubydoc.info/gems/aipp/String), [`Hash`](https://www.rubydoc.info/gems/aipp/Hash) and [`Enumerable`](https://www.rubydoc.info/gems/aipp/Enumerable)
177
+ Method | Description
178
+ -------|------------
179
+ [`read`](https://www.rubydoc.info/gems/aipp/AIPP/AIP#read-instance_method) | download and read an AIP file
180
+ [`add`](https://www.rubydoc.info/gems/aipp/AIPP/AIP#add-instance_method) | add a [`AIXM::Feature`](https://www.rubydoc.info/gems/aixm/AIXM/Feature)
181
+ [`find`](https://www.rubydoc.info/gems/aipp/AIPP/AIP#find-instance_method) | find previously written [`AIXM::Feature`](https://www.rubydoc.info/gems/aixm/AIXM/Feature)s by object
182
+ [`find_by`](https://www.rubydoc.info/gems/aipp/AIPP/AIP#find_by-instance_method) | find previously written [`AIXM::Feature`](https://www.rubydoc.info/gems/aixm/AIXM/Feature)s by class and attribute values
183
+ [`unique`](https://www.rubydoc.info/gems/aipp/AIPP/AIP#unique-instance_method) | prevent duplicate [`AIXM::Feature`](https://www.rubydoc.info/gems/aixm/AIXM/Feature)s
184
+ [`given`](https://www.rubydoc.info/gems/aipp/AIPP/AIP#given-instance_method) | inline condition for assignments
185
+ [`link_to`](https://www.rubydoc.info/gems/aipp/AIPP/AIP#link_to-instance_method) | optionally checked Markdown link
186
+ [`Object#blank`](https://www.rubydoc.info/gems/activesupport/Object#blank%3F-instance_method) and [`String`](https://www.rubydoc.info/gems/activesupport/String) | some core extensions from ActiveSupport
187
+ [`aip`](https://www.rubydoc.info/gems/aipp/AIPP%2FAIP:aip) | AIP name (equal to the parser file name without its file extension such as "ENR-2.1" implemented in the file "ENR-2.1.rb")
188
+ [`aip_file`](https://www.rubydoc.info/gems/aipp/AIPP%2FAIP:aip_file) | AIP file as passed and possibly renamed by `url_for`
189
+ [`options`](https://www.rubydoc.info/gems/aipp/AIPP/Parser#options-instance_method) | arguments read from <tt>aip2aixm</tt> or <tt>aip2ofmx</tt> respectively
190
+ [`config`](https://www.rubydoc.info/gems/aipp/AIPP/Parser#config-instance_method) | configuration read from <tt>config.yml</tt>
191
+ [`borders`](https://www.rubydoc.info/gems/aipp/AIPP/Parser#borders-instance_method) | borders defined as GeoJSON read from the region (see below)
192
+ [`cache`](https://www.rubydoc.info/gems/aipp/AIPP/Parser#cache-instance_method) | `OStruct` instance to make objects available across AIPs
193
+
194
+ To make the parser code more readable, this gem provides a few useful core extensions as well:
195
+
196
+ * [`NilClass`](https://www.rubydoc.info/gems/aipp/NilClass)
197
+ * [`Integer`](https://www.rubydoc.info/gems/aipp/Integer)
198
+ * [`String`](https://www.rubydoc.info/gems/aipp/String)
199
+ * [`Hash`](https://www.rubydoc.info/gems/aipp/Hash)
200
+ * [`Enumerable`](https://www.rubydoc.info/gems/aipp/Enumerable)
201
+ * [`Nokogiri`](https://www.rubydoc.info/gems/aipp/Nokogiri)
202
+
203
+ #### Mandatory `url_for` Method
204
+
205
+ The class must implement the `url_for` method which returns the URL from where to download the AIP file:
206
+
207
+ ```ruby
208
+ module AIPP
209
+ module LF
210
+ class AD2 < AIP
211
+
212
+ def url_for(aip_file)
213
+ # build and return the download URL for the aip file
214
+ end
215
+
216
+ end
217
+ end
218
+ end
219
+ ```
220
+
221
+ There are a few things to note about `url_for`:
222
+
223
+ * If the returned string begins with a protocol like `https:`, the downloader will fetch the file from there.
224
+ * If the returned string is just a file name, the downloader will look for this exact file in the current local directory.
225
+ * The passed `aip_file` will be used as the file name for the local copy in the sources directory. You can rename it on the fly by assigning a new value to this variable.
89
226
 
90
- As well as the following methods:
227
+ #### Optional `setup` Method
91
228
 
92
- * [`options`](https://www.rubydoc.info/gems/aipp/AIPP/Parser#options-instance_method) arguments read from <tt>aip2aixm</tt> or <tt>aip2ofmx</tt> respectively
93
- * [`config`](https://www.rubydoc.info/gems/aipp/AIPP/Parser#config-instance_method) – configuration read from <tt>config.yml</tt>
94
- * [`borders`](https://www.rubydoc.info/gems/aipp/AIPP/Parser#borders-instance_method) – borders defined as GeoJSON read from the region (see below)
95
- * [`cache`](https://www.rubydoc.info/gems/aipp/AIPP/Parser#cache-instance_method) – virgin `OStruct` instance to make objects available across AIPs
229
+ The class may implement the `setup` method. If present, it will be called when this parser is instantiated:
230
+
231
+
232
+ ```ruby
233
+ module AIPP
234
+ module LF
235
+ class AD2 < AIP
236
+
237
+ def setup
238
+ AIXM.config.voice_channel_separation = :any
239
+ cache.setup_at ||= Time.now
240
+ end
241
+
242
+ end
243
+ end
244
+ end
245
+ ```
96
246
 
97
247
  ### Borders
98
248
 
99
- AIXM knows named borders for country boundaries. However, you might need additional borders which don't exist as named boarders.
249
+ AIXM knows named borders for country boundaries. However, you might need additional borders which don't exist as named borders.
250
+
251
+ You can define additional borders as [`AIPP::Border`](https://www.rubydoc.info/gems/aipp/AIPP/Border) objects in two ways.
252
+
253
+ #### From GeoJSON
100
254
 
101
- To define additional borders, create simple GeoJSON files in the <tt>lib/aipp/regions/{REGION}/borders/</tt> directory, for example this `custom_border.geojson`:
255
+ Create simple GeoJSON files in the <tt>lib/aipp/regions/{REGION}/borders/</tt> directory, for example this `my_border_1.geojson`:
102
256
 
103
257
  ```json
104
258
  {
@@ -110,6 +264,13 @@ To define additional borders, create simple GeoJSON files in the <tt>lib/aipp/re
110
264
  [6.009531650000042, 45.12013319700009],
111
265
  [6.015747738000073, 45.12006702600007]
112
266
  ]
267
+ },
268
+ {
269
+ "type": "LineString",
270
+ "coordinates": [
271
+ [4.896732957592112, 43.95662950764992],
272
+ [4.005739165537195, 44.10769266295027]
273
+ ]
113
274
  }
114
275
  ]
115
276
  }
@@ -117,73 +278,44 @@ To define additional borders, create simple GeoJSON files in the <tt>lib/aipp/re
117
278
 
118
279
  ⚠️ The GeoJSON file must consist of exactly one `GeometryCollection` which may contain any number of `LineString` geometries. Only `LineString` geometries are recognized! To define a closed polygon, the first coordinates of a `LineString` must be identical to the last coordinates.
119
280
 
120
- The [`borders`](https://www.rubydoc.info/gems/aipp/AIPP/Parser#borders-instance_method) method gives you access to a map from the border name (upcased file name) to the corresponding [`AIPP::Border`](https://www.rubydoc.info/gems/aipp/AIPP/Border) object:
281
+ #### From Coordinates
282
+
283
+ It's also possible to create a [`AIPP::Border`](https://www.rubydoc.info/gems/aipp/AIPP/Border) objects on the fly:
121
284
 
122
285
  ```ruby
123
- borders # => { "CUSTOM_BORDER" => #<AIPP::Border file=custom_border.geojson> }
286
+ my_border_2 = AIPP::Border.from_array(
287
+ [
288
+ ["6.009531650000042 45.12013319700009", "6.015747738000073 45.12006702600007"],
289
+ ["4.896732957592112 43.95662950764992", "4.005739165537195 44.10769266295027"]
290
+ ]
291
+ )
124
292
  ```
125
293
 
126
- The border object implements simple nearest point and segment calculations to create arrays of [`AIXM::XY`](https://www.rubydoc.info/gems/aixm/AIXM/XY) which can be used with [`AIXM::Component::Geometry`](https://www.rubydoc.info/gems/aixm/AIXM/Component/Geometry).
127
-
128
- See [`AIPP::Border`](https://www.rubydoc.info/gems/aipp/AIPP/Border) for more on this.
129
-
130
- ### Helpers
131
-
132
- Helpers are modules defined in the <tt>lib/aipp/regions/{REGION}/helpers/</tt> directory. All helper modules are required automatically.
133
-
134
- There is one mandatory helper called `URL.rb` which must define the following method to build URLs from which to download AIPs:
294
+ The coordinate pairs must be separated with whitespaces and/or commas. If you want to use this border everywhere, make sure you add it to the others:
135
295
 
136
296
  ```ruby
137
- module AIPP
138
- module LF
139
- module Helpers
140
- module URL
141
-
142
- def url_for(aip_file)
143
- # build and return the download URL for the aip file
144
- end
145
-
146
- end
147
- end
148
- end
149
- end
297
+ borders["my_border_2"] = my_border_2
150
298
  ```
151
299
 
152
- Feel free to add more helpers to DRY code which is shared by multiple AIP parsers. Say you want to extract methods which are used by all AIP parsers:
300
+ #### Usage in Parsers
153
301
 
154
- ```ruby
155
- module AIPP
156
- module LF
157
- module Helpers
158
- module Common
159
-
160
- def source(position:, aip_file: nil)
161
- (...)
162
- end
302
+ In the parser, the [`borders`](https://www.rubydoc.info/gems/aipp/AIPP/Parser#borders-instance_method) method gives you access to all borders read from GeoJSON files:
163
303
 
164
- end
165
- end
166
- end
167
- end
304
+ ```ruby
305
+ borders # => { "my_border_1" => #<AIPP::Border>, "my_border_2" => #<AIPP::Border> }
168
306
  ```
169
307
 
170
- To use this `source` method, simply include the helper module in the AIP parser:
308
+ The border object implements simple nearest point and segment calculations to create arrays of [`AIXM::XY`](https://www.rubydoc.info/gems/aixm/AIXM/XY) which can be used with [`AIXM::Component::Geometry`](https://www.rubydoc.info/gems/aixm/AIXM/Component/Geometry).
171
309
 
172
- ```ruby
173
- module AIPP
174
- module LF
175
- class AD2 < AIP
310
+ See [`AIPP::Border`](https://www.rubydoc.info/gems/aipp/AIPP/Border) for more on this.
176
311
 
177
- include AIPP::LF::Helpers::Common
312
+ ### Helpers
178
313
 
179
- end
180
- end
181
- end
182
- ```
314
+ Helpers are modules defined in the <tt>lib/aipp/regions/{REGION}/helpers/</tt> directory. All helper modules are required automatically in alphabetic order.
183
315
 
184
316
  ### Fixtures and Patches
185
317
 
186
- Fixtures is static data defined as YAML in the <tt>lib/aipp/regions/{REGION}/fixtures/</tt> directory. All fixtures are read automatically. Please note that the name of the AIP parser (e.g. `AD-1.3.rb`) must match the name of the corresponding fixture (e.g. `fixtures/AD-1.3.yml`).
318
+ Fixtures are static YAML data files in the <tt>lib/aipp/regions/{REGION}/fixtures/</tt> directory. All fixtures are read automatically. Please note that the name of the AIP parser (e.g. `AD-1.3.rb`) must match the name of the corresponding fixture (e.g. `fixtures/AD-1.3.yml`).
187
319
 
188
320
  When parsed data is faulty or missing, you may fall back to such static data instead. This is where patches come in. You can patch any AIXM attribute setter by defining a patch block inside the AIP parser and accessing the static data via `parser.fixture`:
189
321
 
@@ -192,14 +324,10 @@ module AIPP
192
324
  module LF
193
325
  class AD2 < AIP
194
326
 
195
- patch AIXM::Component::Runway::Direction, :xy do |parser, object, value|
196
- throw :abort unless value.nil?
197
- @fixtures ||= YAML.load_file(Pathname(__FILE__).dirname.join('AD-1.3.yml'))
198
- airport_id = parser.instance_variable_get(:@airport).id
199
- direction_name = object.name.to_s
200
- throw :abort if (xy = parser.fixture.dig('runways', airport_id, direction_name, 'xy')).nil?
201
- lat, long = xy.split(/\s+/)
202
- AIXM.xy(lat: lat, long: long)
327
+ patch AIXM::Feature::Airport, :z do |parser, object, value|
328
+ throw(:abort) unless value.nil?
329
+ throw(:abort, 'fixture missing') unless z = parser.fixture.dig(object.id, 'z')
330
+ AIXM.z(z, :qnh)
203
331
  end
204
332
 
205
333
  end
@@ -207,7 +335,17 @@ module AIPP
207
335
  end
208
336
  ```
209
337
 
210
- The patch block receives the object and the current value. If this value is okay, `throw :abort` to leave the patch block without touching anything. Otherwise, have the patch block return a new value which will be used instead.
338
+ The patch receives the object and the value which is about to be assigned. It should implement something along these lines:
339
+
340
+ * If the value is okay, `throw(:abort)` to leave the patch block without touching anything.
341
+ * Otherwise, try to fetch a better value e.g. from the fixtures. If no better value can be found (e.g. outdated fixtures), `throw(:abort, "reason")` to leave the patch block and fail with a useful error message which contains the reason thrown.
342
+ * At last, build and return the value object which will be assigned instead of the original value.
343
+
344
+ In case the `object` does not carry enough details, you can access instance variables of the parser like so:
345
+
346
+ ```ruby
347
+ parser.instance_variable_get(:@instance_variable)
348
+ ```
211
349
 
212
350
  ### Source File Line Numbers
213
351
 
@@ -217,11 +355,9 @@ In order to reference the source of an AIXM/OFMX feature, it's necessary to know
217
355
  tr.line
218
356
  ```
219
357
 
220
- ⚠️ Make sure you have build Nokogumbo `--with-libxml2`. Otherwise, all elements will report line number `0` and therefore render OFMX documents invalid. See the [Nokogumbo README](https://github.com/rubys/nokogumbo/blob/master/README.md#flavors-of-nokogumbo) for more on this.
221
-
222
358
  ### Errors
223
359
 
224
- You should `fail` on fatal problems. The `-e` command line argument will open a Pry session when such an error occurs. Issue errors as usual:
360
+ You should `fail` on fatal problems which must be fixed. The `--debug-on-error` command line argument will open a debug session when such an error occurs. Issue errors as usual:
225
361
 
226
362
  ```ruby
227
363
  fail "my message"
@@ -229,11 +365,11 @@ fail "my message"
229
365
 
230
366
  ### Warnings
231
367
 
232
- You should `warn` on non-fatal problems. The `-w ID` command line argument will open a Pry session when then warning with the given ID occurs. To issue a warning:
368
+ You should `warn` on non-fatal problems which should be fixed (default) or might be ignored (`severe: false`). The `--debug-on-warning ID` command line argument will open a debug session when then warning with the given ID occurs. To issue a warning:
233
369
 
234
370
  ```ruby
235
- warn("my message", pry: binding) # open Pry attached to the binding
236
- warn("my message", pry: error) # open Pry attached to the error
371
+ warn("my message")
372
+ warn("my message", severe: false) # show warning only when --unsevere-warn argument is set
237
373
  ```
238
374
 
239
375
  ### Messages
@@ -255,11 +391,13 @@ Use `verbose_info` for in-depth info messages which are only shown if the `--ver
255
391
  verbose_info("my message") # displays "my message" in blue
256
392
  ```
257
393
 
258
- ### Pry
394
+ #### debug
259
395
 
260
- Pry is loaded with stack explorer support. Type `help` in the Pry console to see all available commands. The most useful command in the context of this gem is `up` which beams you one frame up in the caller stack.
396
+ The [default Ruby debugger](https://github.com/ruby/debug#debug-command-on-the-debug-console) is enabled by default, you can add a breakpoint as usual with:
261
397
 
262
- Note: It's not currently possible to use pry-byebug at this time since it [interferes with pry-rescue](https://github.com/ConradIrwin/pry-rescue/issues/71).
398
+ ```ruby
399
+ debugger
400
+ ```
263
401
 
264
402
  ## AIRAC Date Calculations
265
403
 
@@ -275,10 +413,6 @@ airac.next_id # => 1801
275
413
 
276
414
  ## References
277
415
 
278
- * LF - France
279
- * [SIA – AIP publisher](https://www.sia.aviation-civile.gouv.fr)
280
- * [OpenData – public data files](https://www.data.gouv.fr)
281
- * [Protected Planet – protected area data files](https://www.protectedplanet.net)
282
416
  * [Geo Maps – programmatically generated GeoJSON maps](https://github.com/simonepri/geo-maps)
283
417
  * [open flightmaps – open-source aeronautical maps](https://openflightmaps.org)
284
418
  * [AIXM Rubygem – AIXM/OFMX generator for Ruby](https://github.com/svoop/aixm)
data/exe/aip2aixm CHANGED
@@ -4,8 +4,8 @@ require 'bundler/inline'
4
4
 
5
5
  gemfile do
6
6
  source 'https://rubygems.org'
7
- ruby '>= 2.5'
8
- gem 'aipp', '~> 0'
7
+ ruby '>= 3.0.0'
8
+ gem 'aipp', '~> 1'
9
9
  end
10
10
 
11
11
  AIPP::Executable.new(schema: File.basename($0)[4..-1].to_sym).run
data/exe/aip2ofmx CHANGED
@@ -4,8 +4,8 @@ require 'bundler/inline'
4
4
 
5
5
  gemfile do
6
6
  source 'https://rubygems.org'
7
- ruby '>= 2.5'
8
- gem 'aipp', '~> 0'
7
+ ruby '>= 3.0.0'
8
+ gem 'aipp', '~> 1'
9
9
  end
10
10
 
11
11
  AIPP::Executable.new(schema: File.basename($0)[4..-1].to_sym).run