aipp 0.2.6 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +21 -0
- data/README.md +147 -91
- data/exe/aip2aixm +2 -2
- data/exe/aip2ofmx +2 -2
- data/lib/aipp/aip.rb +96 -11
- data/lib/aipp/border.rb +77 -46
- data/lib/aipp/debugger.rb +101 -0
- data/lib/aipp/downloader.rb +18 -5
- data/lib/aipp/executable.rb +33 -20
- data/lib/aipp/parser.rb +42 -37
- data/lib/aipp/patcher.rb +5 -2
- data/lib/aipp/regions/LF/README.md +49 -0
- data/lib/aipp/regions/LF/aerodromes.rb +223 -0
- data/lib/aipp/regions/LF/d_p_r_airspaces.rb +56 -0
- data/lib/aipp/regions/LF/dangerous_activities.rb +49 -0
- data/lib/aipp/regions/LF/designated_points.rb +47 -0
- data/lib/aipp/regions/LF/fixtures/aerodromes.yml +608 -0
- data/lib/aipp/regions/LF/helipads.rb +122 -0
- data/lib/aipp/regions/LF/helpers/base.rb +167 -174
- data/lib/aipp/regions/LF/helpers/surface.rb +49 -0
- data/lib/aipp/regions/LF/helpers/usage_limitation.rb +20 -0
- data/lib/aipp/regions/LF/navigational_aids.rb +85 -0
- data/lib/aipp/regions/LF/obstacles.rb +153 -0
- data/lib/aipp/regions/LF/serviced_airspaces.rb +70 -0
- data/lib/aipp/regions/LF/services.rb +172 -0
- data/lib/aipp/t_hash.rb +3 -4
- data/lib/aipp/version.rb +1 -1
- data/lib/aipp.rb +7 -5
- data/lib/core_ext/enumerable.rb +2 -2
- data/lib/core_ext/hash.rb +21 -5
- data/lib/core_ext/nokogiri.rb +54 -0
- data/lib/core_ext/string.rb +32 -65
- data.tar.gz.sig +0 -0
- metadata +70 -81
- metadata.gz.sig +0 -0
- data/lib/aipp/airac.rb +0 -55
- data/lib/aipp/regions/LF/AD-1.3.rb +0 -177
- data/lib/aipp/regions/LF/AD-1.6.rb +0 -33
- data/lib/aipp/regions/LF/AD-2.rb +0 -344
- data/lib/aipp/regions/LF/AD-3.1.rb +0 -185
- data/lib/aipp/regions/LF/ENR-2.1.rb +0 -167
- data/lib/aipp/regions/LF/ENR-4.1.rb +0 -41
- data/lib/aipp/regions/LF/ENR-4.3.rb +0 -27
- data/lib/aipp/regions/LF/ENR-5.1.rb +0 -106
- data/lib/aipp/regions/LF/ENR-5.4.rb +0 -90
- data/lib/aipp/regions/LF/ENR-5.5.rb +0 -55
- data/lib/aipp/regions/LF/fixtures/AD-1.3.yml +0 -511
- data/lib/aipp/regions/LF/fixtures/AD-2.yml +0 -185
- data/lib/aipp/regions/LF/fixtures/AD-3.1.yml +0 -10
- data/lib/aipp/regions/LF/helpers/URL.rb +0 -26
- data/lib/aipp/regions/LF/helpers/navigational_aid.rb +0 -104
- data/lib/aipp/regions/LF/helpers/radio_AD.rb +0 -110
- data/lib/core_ext/object.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '09151e277b537c1529951cd69b38bb5d6fc47f855e6041ca3537d36462f93907'
|
4
|
+
data.tar.gz: f0b9d43b940ced7998a079cf6dce602386d52ad90995b7e77a6b6429f09f798e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 205b609c8aad3999495447f7c55aba98282b5b6347a4f89caef3e06e3edc8f8e28c4e523cc48737522f895813309fe9d4f7b8d3d2d0db37a12d5808c41509137
|
7
|
+
data.tar.gz: 9a228dd7a152dfd5e0bbbd22b8a068e8de404ba9a4d48f4a30f7b3f0b352c694f12b4a45b543880b20884645fbd52fa475dd738f7385541113462dcadce1fc29
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,24 @@
|
|
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
|
+
|
1
22
|
## 0.2.6
|
2
23
|
|
3
24
|
#### Additions
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@
|
|
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
|
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)
|
@@ -18,9 +18,8 @@ This gem incluces two executables to download and parse aeronautical data as HTM
|
|
18
18
|
[Usage](#usage)<br>
|
19
19
|
[Storage](#storage)<br>
|
20
20
|
[Regions](#regions)<br>
|
21
|
-
[AIP Parsers](#aip-parsers)<br>
|
22
|
-
[References](#references)<br>
|
23
21
|
[AIRAC Date Calculations](#airac-date-calculations)<br>
|
22
|
+
[References](#references)<br>
|
24
23
|
[Development](#development)
|
25
24
|
|
26
25
|
## Install
|
@@ -30,7 +29,7 @@ This gem incluces two executables to download and parse aeronautical data as HTM
|
|
30
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:
|
31
30
|
|
32
31
|
```
|
33
|
-
gem cert --add <(curl -Ls https://raw.github.com/svoop/aipp/
|
32
|
+
gem cert --add <(curl -Ls https://raw.github.com/svoop/aipp/main/certs/svoop.pem)
|
34
33
|
```
|
35
34
|
|
36
35
|
### Standalone
|
@@ -124,6 +123,24 @@ module AIPP
|
|
124
123
|
|
125
124
|
DEPENDS = %w(ENR-2.1 ENR-2.2) # declare dependencies to other AIPs
|
126
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
|
+
|
127
144
|
def parse
|
128
145
|
html = read # read the Nokogiri::HTML5 document
|
129
146
|
feature = (...) # build the feature
|
@@ -144,8 +161,8 @@ module AIPP
|
|
144
161
|
|
145
162
|
def parse
|
146
163
|
%i(one two three).each do |part|
|
147
|
-
html = read(
|
148
|
-
support_html = read(
|
164
|
+
html = read("#{aip}.#{part}") # read with a non-standard name
|
165
|
+
support_html = read('AD-0.6') # maybe read necessary support documents
|
149
166
|
(...)
|
150
167
|
end
|
151
168
|
end
|
@@ -157,26 +174,85 @@ end
|
|
157
174
|
|
158
175
|
Inside the `parse` method, you have access to the following methods:
|
159
176
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
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.
|
226
|
+
|
227
|
+
#### Optional `setup` Method
|
228
|
+
|
229
|
+
The class may implement the `setup` method. If present, it will be called when this parser is instantiated:
|
167
230
|
|
168
|
-
As well as the following methods:
|
169
231
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
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
|
+
```
|
174
246
|
|
175
247
|
### Borders
|
176
248
|
|
177
|
-
AIXM knows named borders for country boundaries. However, you might need additional borders which don't exist as named
|
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.
|
178
252
|
|
179
|
-
|
253
|
+
#### From GeoJSON
|
254
|
+
|
255
|
+
Create simple GeoJSON files in the <tt>lib/aipp/regions/{REGION}/borders/</tt> directory, for example this `my_border_1.geojson`:
|
180
256
|
|
181
257
|
```json
|
182
258
|
{
|
@@ -188,6 +264,13 @@ To define additional borders, create simple GeoJSON files in the <tt>lib/aipp/re
|
|
188
264
|
[6.009531650000042, 45.12013319700009],
|
189
265
|
[6.015747738000073, 45.12006702600007]
|
190
266
|
]
|
267
|
+
},
|
268
|
+
{
|
269
|
+
"type": "LineString",
|
270
|
+
"coordinates": [
|
271
|
+
[4.896732957592112, 43.95662950764992],
|
272
|
+
[4.005739165537195, 44.10769266295027]
|
273
|
+
]
|
191
274
|
}
|
192
275
|
]
|
193
276
|
}
|
@@ -195,73 +278,44 @@ To define additional borders, create simple GeoJSON files in the <tt>lib/aipp/re
|
|
195
278
|
|
196
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.
|
197
280
|
|
198
|
-
|
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:
|
199
284
|
|
200
285
|
```ruby
|
201
|
-
|
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
|
+
)
|
202
292
|
```
|
203
293
|
|
204
|
-
The
|
205
|
-
|
206
|
-
See [`AIPP::Border`](https://www.rubydoc.info/gems/aipp/AIPP/Border) for more on this.
|
207
|
-
|
208
|
-
### Helpers
|
209
|
-
|
210
|
-
Helpers are modules defined in the <tt>lib/aipp/regions/{REGION}/helpers/</tt> directory. All helper modules are required automatically in alphabetic order.
|
211
|
-
|
212
|
-
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:
|
213
295
|
|
214
296
|
```ruby
|
215
|
-
|
216
|
-
module LF
|
217
|
-
module Helpers
|
218
|
-
module URL
|
219
|
-
|
220
|
-
def url_for(aip_file)
|
221
|
-
# build and return the download URL for the aip file
|
222
|
-
end
|
223
|
-
|
224
|
-
end
|
225
|
-
end
|
226
|
-
end
|
227
|
-
end
|
297
|
+
borders["my_border_2"] = my_border_2
|
228
298
|
```
|
229
299
|
|
230
|
-
|
231
|
-
|
232
|
-
```ruby
|
233
|
-
module AIPP
|
234
|
-
module LF
|
235
|
-
module Helpers
|
236
|
-
module Base
|
300
|
+
#### Usage in Parsers
|
237
301
|
|
238
|
-
|
239
|
-
(...)
|
240
|
-
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:
|
241
303
|
|
242
|
-
|
243
|
-
|
244
|
-
end
|
245
|
-
end
|
304
|
+
```ruby
|
305
|
+
borders # => { "my_border_1" => #<AIPP::Border>, "my_border_2" => #<AIPP::Border> }
|
246
306
|
```
|
247
307
|
|
248
|
-
|
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).
|
249
309
|
|
250
|
-
|
251
|
-
module AIPP
|
252
|
-
module LF
|
253
|
-
class AD2 < AIP
|
310
|
+
See [`AIPP::Border`](https://www.rubydoc.info/gems/aipp/AIPP/Border) for more on this.
|
254
311
|
|
255
|
-
|
312
|
+
### Helpers
|
256
313
|
|
257
|
-
|
258
|
-
end
|
259
|
-
end
|
260
|
-
```
|
314
|
+
Helpers are modules defined in the <tt>lib/aipp/regions/{REGION}/helpers/</tt> directory. All helper modules are required automatically in alphabetic order.
|
261
315
|
|
262
316
|
### Fixtures and Patches
|
263
317
|
|
264
|
-
Fixtures
|
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`).
|
265
319
|
|
266
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`:
|
267
321
|
|
@@ -270,14 +324,10 @@ module AIPP
|
|
270
324
|
module LF
|
271
325
|
class AD2 < AIP
|
272
326
|
|
273
|
-
patch AIXM::
|
274
|
-
throw
|
275
|
-
|
276
|
-
|
277
|
-
direction_name = object.name.to_s
|
278
|
-
throw :abort if (xy = parser.fixture.dig('runways', airport_id, direction_name, 'xy')).nil?
|
279
|
-
lat, long = xy.split(/\s+/)
|
280
|
-
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)
|
281
331
|
end
|
282
332
|
|
283
333
|
end
|
@@ -285,7 +335,17 @@ module AIPP
|
|
285
335
|
end
|
286
336
|
```
|
287
337
|
|
288
|
-
The patch
|
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
|
+
```
|
289
349
|
|
290
350
|
### Source File Line Numbers
|
291
351
|
|
@@ -295,11 +355,9 @@ In order to reference the source of an AIXM/OFMX feature, it's necessary to know
|
|
295
355
|
tr.line
|
296
356
|
```
|
297
357
|
|
298
|
-
⚠️ 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.
|
299
|
-
|
300
358
|
### Errors
|
301
359
|
|
302
|
-
You should `fail` on fatal problems. The
|
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:
|
303
361
|
|
304
362
|
```ruby
|
305
363
|
fail "my message"
|
@@ -307,11 +365,11 @@ fail "my message"
|
|
307
365
|
|
308
366
|
### Warnings
|
309
367
|
|
310
|
-
You should `warn` on non-fatal problems. The
|
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:
|
311
369
|
|
312
370
|
```ruby
|
313
|
-
warn("my message"
|
314
|
-
warn("my message",
|
371
|
+
warn("my message")
|
372
|
+
warn("my message", severe: false) # show warning only when --unsevere-warn argument is set
|
315
373
|
```
|
316
374
|
|
317
375
|
### Messages
|
@@ -333,11 +391,13 @@ Use `verbose_info` for in-depth info messages which are only shown if the `--ver
|
|
333
391
|
verbose_info("my message") # displays "my message" in blue
|
334
392
|
```
|
335
393
|
|
336
|
-
|
394
|
+
#### debug
|
337
395
|
|
338
|
-
|
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:
|
339
397
|
|
340
|
-
|
398
|
+
```ruby
|
399
|
+
debugger
|
400
|
+
```
|
341
401
|
|
342
402
|
## AIRAC Date Calculations
|
343
403
|
|
@@ -353,10 +413,6 @@ airac.next_id # => 1801
|
|
353
413
|
|
354
414
|
## References
|
355
415
|
|
356
|
-
* LF - France
|
357
|
-
* [SIA – AIP publisher](https://www.sia.aviation-civile.gouv.fr)
|
358
|
-
* [OpenData – public data files](https://www.data.gouv.fr)
|
359
|
-
* [Protected Planet – protected area data files](https://www.protectedplanet.net)
|
360
416
|
* [Geo Maps – programmatically generated GeoJSON maps](https://github.com/simonepri/geo-maps)
|
361
417
|
* [open flightmaps – open-source aeronautical maps](https://openflightmaps.org)
|
362
418
|
* [AIXM Rubygem – AIXM/OFMX generator for Ruby](https://github.com/svoop/aixm)
|
data/exe/aip2aixm
CHANGED
data/exe/aip2ofmx
CHANGED
data/lib/aipp/aip.rb
CHANGED
@@ -3,13 +3,18 @@ module AIPP
|
|
3
3
|
# @abstract
|
4
4
|
class AIP
|
5
5
|
extend Forwardable
|
6
|
+
include AIPP::Debugger
|
6
7
|
include AIPP::Patcher
|
7
8
|
|
8
9
|
DEPENDS = []
|
9
10
|
|
10
|
-
# @return [String] AIP name (
|
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")
|
11
13
|
attr_reader :aip
|
12
14
|
|
15
|
+
# @return [String] AIP file as passed and possibly updated by `url_for`
|
16
|
+
attr_reader :aip_file
|
17
|
+
|
13
18
|
# @return [Object] Fixture read from YAML file
|
14
19
|
attr_reader :fixture
|
15
20
|
|
@@ -30,7 +35,12 @@ module AIPP
|
|
30
35
|
|
31
36
|
def initialize(aip:, downloader:, fixture:, parser:)
|
32
37
|
@aip, @downloader, @fixture, @parser = aip, downloader, fixture, parser
|
33
|
-
|
38
|
+
setup if respond_to? :setup
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [String]
|
42
|
+
def inspect
|
43
|
+
"#<AIPP::AIP #{aip}>"
|
34
44
|
end
|
35
45
|
|
36
46
|
# Read an AIP source file
|
@@ -38,15 +48,18 @@ module AIPP
|
|
38
48
|
# Read the cached source file if it exists in the source archive. Otherwise,
|
39
49
|
# download it from URL and cache it.
|
40
50
|
#
|
41
|
-
# An URL builder method +url_for(aip_file)+ must be
|
42
|
-
#
|
51
|
+
# An URL builder method +url_for(aip_file)+ must be implemented by the AIP
|
52
|
+
# parser definition (e.g. +ENR-2.1.rb+).
|
43
53
|
#
|
44
|
-
# @param aip_file [String] e.g. "ENR-2.1" or "AD-2.LFMV" (default: +aip+
|
45
|
-
#
|
46
|
-
#
|
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
|
47
59
|
def read(aip_file=nil)
|
48
|
-
aip_file
|
49
|
-
|
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)
|
50
63
|
end
|
51
64
|
|
52
65
|
# Add feature to AIXM
|
@@ -54,7 +67,7 @@ module AIPP
|
|
54
67
|
# @param feature [AIXM::Feature] e.g. airport or airspace
|
55
68
|
# @return [AIXM::Feature] added feature
|
56
69
|
def add(feature)
|
57
|
-
verbose_info "
|
70
|
+
verbose_info "adding #{feature.inspect}"
|
58
71
|
aixm.add_feature feature
|
59
72
|
feature
|
60
73
|
end
|
@@ -76,6 +89,78 @@ module AIPP
|
|
76
89
|
aixm.features.send(method, *args)
|
77
90
|
end
|
78
91
|
end
|
79
|
-
end
|
80
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
|
81
166
|
end
|