aipp 0.2.2 → 0.2.3
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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/CHANGELOG.md +9 -0
- data/README.md +47 -13
- data/TODO.md +5 -2
- data/aipp.gemspec +1 -1
- data/lib/aipp.rb +2 -0
- data/lib/aipp/aip.rb +4 -3
- data/lib/aipp/border.rb +146 -0
- data/lib/aipp/downloader.rb +1 -1
- data/lib/aipp/executable.rb +2 -2
- data/lib/aipp/parser.rb +12 -1
- data/lib/aipp/patcher.rb +1 -1
- data/lib/aipp/pdf.rb +5 -5
- data/lib/aipp/regions/LF/AD-1.3.rb +4 -4
- data/lib/aipp/regions/LF/AD-1.6.rb +1 -1
- data/lib/aipp/regions/LF/AD-2.rb +7 -7
- data/lib/aipp/regions/LF/ENR-2.1.rb +9 -7
- data/lib/aipp/regions/LF/ENR-4.1.rb +2 -7
- data/lib/aipp/regions/LF/ENR-4.3.rb +1 -1
- data/lib/aipp/regions/LF/ENR-5.1.rb +2 -2
- data/lib/aipp/regions/LF/ENR-5.5.rb +53 -0
- data/lib/aipp/regions/LF/borders/france_atlantic_coast.geojson +2546 -0
- data/lib/aipp/regions/LF/borders/france_atlantic_territorial_sea.geojson +1663 -0
- data/lib/aipp/regions/LF/borders/france_ecrins_national_park.geojson +5861 -0
- data/lib/aipp/regions/LF/borders/france_mediterranean_coast.geojson +6203 -0
- data/lib/aipp/regions/LF/helpers/common.rb +26 -16
- data/lib/aipp/version.rb +1 -1
- data/lib/core_ext/integer.rb +16 -0
- data/lib/core_ext/object.rb +4 -4
- data/spec/fixtures/border.geojson +201 -0
- data/spec/lib/aipp/border_spec.rb +135 -0
- data/spec/lib/core_ext/integer_spec.rb +15 -0
- metadata +17 -5
- data/lib/aipp/regions/LF/ENR-5.5.rb-NEW +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d97409845a7b08285c77294aa116873fdcb668bd0f10d13d2ceecd9ef3922a9
|
4
|
+
data.tar.gz: 2594b4ad9bd0b9deba766704778ff1710eaaf71ce675bb4fd378481f4f13dfc6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa0ac5dafcc6e36a113e2a97c270f768265379b09c34a833e785adf44f45e5dfcd5bb3951b0d6741ae15bc765386eb55c3118154a48ce568f9fae14f06bf6ae5
|
7
|
+
data.tar.gz: 92dd8d6134a1882b0ceada8e130ed834e3dc866e4b84e2dd513084c5313a42d8fd89b47d3726ff36e1f38bb8837fa190790bcc3f99d752e7504757e1a2b4eb84
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -51,9 +51,9 @@ module AIPP
|
|
51
51
|
DEPENDS = %w(ENR-2.1 ENR-2.2) # declare dependencies to other AIPs
|
52
52
|
|
53
53
|
def parse
|
54
|
-
html = read
|
55
|
-
feature = (...)
|
56
|
-
|
54
|
+
html = read # read the Nokogiri::HTML5 document
|
55
|
+
feature = (...) # build the feature
|
56
|
+
add(feature: feature) # add the feature to AIXM::Document
|
57
57
|
end
|
58
58
|
|
59
59
|
end
|
@@ -84,16 +84,50 @@ end
|
|
84
84
|
Inside the `parse` method, you have access to the following methods:
|
85
85
|
|
86
86
|
* [`read`](https://www.rubydoc.info/gems/aipp/AIPP/AIP#read-instance_method) – download and read an AIP file
|
87
|
-
* [`
|
88
|
-
* [`select`](https://www.rubydoc.info/gems/aipp/AIPP/AIP#find-instance_method – search previously written [`AIXM::Feature`s](
|
87
|
+
* [`add`](https://www.rubydoc.info/gems/aipp/AIPP/AIP#add-instance_method) – add a [`AIXM::Feature`](https://www.rubydoc.info/gems/aixm/AIXM/Feature)
|
88
|
+
* [`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)
|
89
89
|
* 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)
|
90
|
-
* core extensions from this gem – [`Object`](https://www.rubydoc.info/gems/aipp/Object), [`String`](https://www.rubydoc.info/gems/aipp/String), [`NilClass`](https://www.rubydoc.info/gems/aipp/NilClass) and [`Enumerable`](https://www.rubydoc.info/gems/aipp/Enumerable)
|
90
|
+
* core extensions from this gem – [`Object`](https://www.rubydoc.info/gems/aipp/Object), [`Integer`](https://www.rubydoc.info/gems/aipp/Integer), [`String`](https://www.rubydoc.info/gems/aipp/String), [`NilClass`](https://www.rubydoc.info/gems/aipp/NilClass) and [`Enumerable`](https://www.rubydoc.info/gems/aipp/Enumerable)
|
91
|
+
|
92
|
+
As well as the following methods:
|
93
|
+
|
94
|
+
* [`options`](https://www.rubydoc.info/gems/aipp/AIPP/Parser#options-instance_method) – arguments read from <tt>aip2aixm</tt> or <tt>aip2ofmx</tt> respectively
|
95
|
+
* [`config`](https://www.rubydoc.info/gems/aipp/AIPP/Parser#config-instance_method) – configuration read from <tt>config.yml</tt>
|
96
|
+
* [`borders`](https://www.rubydoc.info/gems/aipp/AIPP/Parser#borders-instance_method) – borders defined as GeoJSON read from the region (see below)
|
97
|
+
* [`cache`](https://www.rubydoc.info/gems/aipp/AIPP/Parser#cache-instance_method) – virgin `OStruct` instance to make objects available across AIPs
|
98
|
+
|
99
|
+
### Borders
|
100
|
+
|
101
|
+
AIXM knows named borders for country boundaries. However, you might need additional borders which don't exist as named boarders.
|
102
|
+
|
103
|
+
To define additional borders, create simple GeoJSON files in the <tt>lib/aipp/regions/{REGION}/borders/</tt> directory, for example this `custom_border.geojson`:
|
104
|
+
|
105
|
+
```json
|
106
|
+
{
|
107
|
+
"type": "GeometryCollection",
|
108
|
+
"geometries": [
|
109
|
+
{
|
110
|
+
"type": "LineString",
|
111
|
+
"coordinates": [
|
112
|
+
[6.009531650000042, 45.12013319700009],
|
113
|
+
[6.015747738000073, 45.12006702600007]
|
114
|
+
]
|
115
|
+
}
|
116
|
+
]
|
117
|
+
}
|
118
|
+
```
|
119
|
+
|
120
|
+
⚠️ 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.
|
121
|
+
|
122
|
+
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:
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
borders # => { "CUSTOM_BORDER" => #<AIPP::Border file=custom_border.geojson> }
|
126
|
+
```
|
91
127
|
|
92
|
-
|
128
|
+
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).
|
93
129
|
|
94
|
-
|
95
|
-
* `config` – configuration read from <tt>config.yml</tt>
|
96
|
-
* `cache` – virgin `OStruct` instance to make objects available across AIPs
|
130
|
+
See [`AIPP::Border`](https://www.rubydoc.info/gems/aipp/AIPP/Border) for more on this.
|
97
131
|
|
98
132
|
### Helpers
|
99
133
|
|
@@ -213,12 +247,12 @@ info("my message") # displays "my message" in black
|
|
213
247
|
info("my message", color: :green) # displays "my message" in green
|
214
248
|
```
|
215
249
|
|
216
|
-
####
|
250
|
+
#### verbose info
|
217
251
|
|
218
|
-
Use `
|
252
|
+
Use `verbose_info` for in-depth info messages which are only shown if the `--verbose` mode is set:
|
219
253
|
|
220
254
|
```ruby
|
221
|
-
|
255
|
+
verbose_info("my message") # displays "my message" in blue
|
222
256
|
```
|
223
257
|
|
224
258
|
### Pry
|
data/TODO.md
CHANGED
data/aipp.gemspec
CHANGED
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.add_development_dependency 'guard'
|
31
31
|
spec.add_development_dependency 'guard-minitest'
|
32
32
|
|
33
|
-
spec.add_runtime_dependency 'aixm', '>= 0.3.
|
33
|
+
spec.add_runtime_dependency 'aixm', '>= 0.3.5'
|
34
34
|
spec.add_runtime_dependency 'activesupport', '~> 5'
|
35
35
|
spec.add_runtime_dependency 'nokogiri', '~> 1'
|
36
36
|
spec.add_runtime_dependency 'nokogumbo', '~> 2'
|
data/lib/aipp.rb
CHANGED
@@ -21,12 +21,14 @@ require 'active_support'
|
|
21
21
|
require 'active_support/core_ext/object/blank'
|
22
22
|
require 'active_support/core_ext/string'
|
23
23
|
require_relative 'core_ext/object'
|
24
|
+
require_relative 'core_ext/integer'
|
24
25
|
require_relative 'core_ext/string'
|
25
26
|
require_relative 'core_ext/nil_class'
|
26
27
|
require_relative 'core_ext/enumerable'
|
27
28
|
|
28
29
|
require_relative 'aipp/version'
|
29
30
|
require_relative 'aipp/pdf'
|
31
|
+
require_relative 'aipp/border'
|
30
32
|
require_relative 'aipp/t_hash'
|
31
33
|
require_relative 'aipp/executable'
|
32
34
|
require_relative 'aipp/airac'
|
data/lib/aipp/aip.rb
CHANGED
@@ -20,7 +20,7 @@ module AIPP
|
|
20
20
|
# @see AIPP::Parser#options
|
21
21
|
# @!method cache
|
22
22
|
# @see AIPP::Parser#cache
|
23
|
-
def_delegators :@parser, :aixm, :config, :options, :cache
|
23
|
+
def_delegators :@parser, :aixm, :config, :options, :borders, :cache
|
24
24
|
private :aixm
|
25
25
|
|
26
26
|
def initialize(aip:, downloader:, parser:)
|
@@ -45,10 +45,11 @@ module AIPP
|
|
45
45
|
@downloader.read(document: aip_file, url: url_for(aip_file))
|
46
46
|
end
|
47
47
|
|
48
|
-
#
|
48
|
+
# Add feature to AIXM
|
49
49
|
#
|
50
50
|
# @param feature [AIXM::Feature] e.g. airport or airspace
|
51
|
-
def
|
51
|
+
def add(feature)
|
52
|
+
verbose_info "Adding #{feature.class}"
|
52
53
|
aixm.features << feature
|
53
54
|
end
|
54
55
|
|
data/lib/aipp/border.rb
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
module AIPP
|
2
|
+
|
3
|
+
# Border GeoJSON file reader
|
4
|
+
#
|
5
|
+
# The border GeoJSON files must be a geometry collection of one or more
|
6
|
+
# line strings:
|
7
|
+
#
|
8
|
+
# {
|
9
|
+
# "type": "GeometryCollection",
|
10
|
+
# "geometries": [
|
11
|
+
# {
|
12
|
+
# "type": "LineString",
|
13
|
+
# "coordinates": [
|
14
|
+
# [6.009531650000042, 45.12013319700009],
|
15
|
+
# [6.015747738000073, 45.12006702600007]
|
16
|
+
# ]
|
17
|
+
# }
|
18
|
+
# ]
|
19
|
+
# }
|
20
|
+
#
|
21
|
+
# @example
|
22
|
+
# border = AIPP::Border.new("/path/to/file.geojson")
|
23
|
+
# border.geometries
|
24
|
+
# # => [[#<AIXM::XY 45.12013320N 006.00953165E>, <AIXM::XY 45.12006703N 006.01574774E>]]
|
25
|
+
class Border
|
26
|
+
attr_reader :file
|
27
|
+
attr_reader :geometries
|
28
|
+
|
29
|
+
def initialize(file)
|
30
|
+
@file = file.is_a?(Pathname) ? file : Pathname(file)
|
31
|
+
fail(ArgumentError, "file must have extension .geojson") unless @file.extname == '.geojson'
|
32
|
+
@geometries = load_geometries
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [String]
|
36
|
+
def inspect
|
37
|
+
%Q(#<#{self.class} file=#{@file}>)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Name of the border
|
41
|
+
#
|
42
|
+
# By convention, the name of the border is taken from the filename with
|
43
|
+
# both the extension .geojson and all non alphanumeric characters dropped
|
44
|
+
# and the resulting string upcased.
|
45
|
+
#
|
46
|
+
# @return [String]
|
47
|
+
def name
|
48
|
+
@file.basename('.geojson').to_s.gsub(/\W/, '').upcase
|
49
|
+
end
|
50
|
+
|
51
|
+
# Whether the given geometry is closed or not
|
52
|
+
#
|
53
|
+
# A geometry is considered closed when it's first coordinate equals the
|
54
|
+
# last coordinate.
|
55
|
+
#
|
56
|
+
# @param geometry_index [Integer] geometry to check
|
57
|
+
# @return [Boolean] true if the geometry is closed or false otherwise
|
58
|
+
def closed?(geometry_index:)
|
59
|
+
geometry = @geometries[geometry_index]
|
60
|
+
geometry.first == geometry.last
|
61
|
+
end
|
62
|
+
|
63
|
+
# Find a position on a geometry nearest to the given coordinates
|
64
|
+
#
|
65
|
+
# @param geometry_index [Integer] index of the geometry on which to search
|
66
|
+
# or +nil+ to search on all geometries
|
67
|
+
# @param xy [AIXM::XY] coordinates to approximate
|
68
|
+
# @return [AIPP::Border::Position] position nearest to the given coordinates
|
69
|
+
def nearest(geometry_index: nil, xy:)
|
70
|
+
position = nil
|
71
|
+
min_distance = 21_000_000 # max distance on earth in meters
|
72
|
+
@geometries.each.with_index do |geometry, g_index|
|
73
|
+
next unless geometry_index.nil? || geometry_index == g_index
|
74
|
+
geometry.each.with_index do |coordinates, c_index|
|
75
|
+
distance = xy.distance(coordinates).dist
|
76
|
+
if distance < min_distance
|
77
|
+
position = Position.new(geometries: geometries, geometry_index: g_index, coordinates_index: c_index)
|
78
|
+
min_distance = distance
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
position
|
83
|
+
end
|
84
|
+
|
85
|
+
# Get a segment of a geometry between the given starting and ending
|
86
|
+
# positions
|
87
|
+
#
|
88
|
+
# The segment ends either at the given ending position or at the last
|
89
|
+
# coordinates of the geometry. However, if the geometry is closed, the
|
90
|
+
# segment always continues up to the given ending position.
|
91
|
+
#
|
92
|
+
# @param from_position [AIPP::Border::Position] starting position
|
93
|
+
# @param to_position [AIPP::Border::Position] ending position
|
94
|
+
# @return [Array<AIXM::XY>] array of coordinates describing the segment
|
95
|
+
def segment(from_position:, to_position:)
|
96
|
+
fail(ArgumentError, "both positions must be on the same geometry") unless from_position.geometry_index == to_position.geometry_index
|
97
|
+
geometry_index = from_position.geometry_index
|
98
|
+
geometry = @geometries[geometry_index]
|
99
|
+
if closed?(geometry_index: geometry_index)
|
100
|
+
up = from_position.coordinates_index.upto(to_position.coordinates_index)
|
101
|
+
down = from_position.coordinates_index.downto(0) + (geometry.count - 2).downto(to_position.coordinates_index)
|
102
|
+
geometry.values_at(*(up.count < down.count ? up : down).to_a)
|
103
|
+
else
|
104
|
+
geometry.values_at(*from_position.coordinates_index.up_or_downto(to_position.coordinates_index).to_a)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def load_geometries
|
111
|
+
JSON.load(@file)['geometries'].map do |line_string|
|
112
|
+
line_string['coordinates'].map do |long, lat|
|
113
|
+
AIXM.xy(long: long, lat: lat)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Position defines an exact point on a border
|
119
|
+
#
|
120
|
+
# @example
|
121
|
+
# position = AIPP::Border::Position.new(
|
122
|
+
# geometries: border.geometries, geometry_index: 0, coordinates_index: 0
|
123
|
+
# )
|
124
|
+
# position.xy # => #<AIXM::XY 45.12013320N 006.00953165E>
|
125
|
+
class Position
|
126
|
+
attr_accessor :geometry_index
|
127
|
+
attr_accessor :coordinates_index
|
128
|
+
|
129
|
+
def initialize(geometries:, geometry_index:, coordinates_index:)
|
130
|
+
@geometries, @geometry_index, @coordinates_index = geometries, geometry_index, coordinates_index
|
131
|
+
end
|
132
|
+
|
133
|
+
# @return [String]
|
134
|
+
def inspect
|
135
|
+
%Q(#<#{self.class} xy=#{xy}>)
|
136
|
+
end
|
137
|
+
|
138
|
+
# Coordinates for this position
|
139
|
+
#
|
140
|
+
# @return [AIXM::XY, nil] coordinates or nil if the indexes don't exist
|
141
|
+
def xy
|
142
|
+
@geometries.dig(@geometry_index, @coordinates_index)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
data/lib/aipp/downloader.rb
CHANGED
@@ -57,7 +57,7 @@ module AIPP
|
|
57
57
|
type ||= Pathname(URI(url).path).extname[1..-1].to_sym
|
58
58
|
file = work_path.join([document, type].join('.'))
|
59
59
|
unless file.exist?
|
60
|
-
|
60
|
+
verbose_info "Downloading #{document}"
|
61
61
|
IO.copy_stream(Kernel.open(url), file)
|
62
62
|
end
|
63
63
|
convert file
|
data/lib/aipp/executable.rb
CHANGED
@@ -8,7 +8,7 @@ module AIPP
|
|
8
8
|
@options = options
|
9
9
|
@options[:airac] = AIPP::AIRAC.new
|
10
10
|
@options[:storage] = Pathname(Dir.home).join('.aipp')
|
11
|
-
@options[:force] = $PRY_ON_WARN = $PRY_ON_ERROR = false
|
11
|
+
@options[:force] = $VERBOSE_INFO = $PRY_ON_WARN = $PRY_ON_ERROR = false
|
12
12
|
OptionParser.new do |o|
|
13
13
|
o.banner = <<~END
|
14
14
|
Download online AIP and convert it to #{options[:schema].upcase}.
|
@@ -19,7 +19,7 @@ module AIPP
|
|
19
19
|
o.on('-a', '--aip STRING', String, 'process this AIP only (e.g. "ENR-5.1")') { |v| @options[:aip] = v.upcase }
|
20
20
|
o.on('-s', '--storage DIR', String, 'storage directory (default: "~/.aipp")') { |v| @options[:storage] = Pathname(v) }
|
21
21
|
o.on('-f', '--[no-]force', 'ignore XML schema validation (default: false)') { |v| @options[:force] = v }
|
22
|
-
o.on('-v', '--[no-]verbose', 'verbose output
|
22
|
+
o.on('-v', '--[no-]verbose', 'verbose output (default: false)') { |v| $VERBOSE_INFO = v }
|
23
23
|
o.on('-w', '--pry-on-warn [ID]', Integer, 'open pry on warn with ID (default: nil)') { |v| $PRY_ON_WARN = v || true }
|
24
24
|
o.on('-e', '--[no-]pry-on-error', 'open pry on error (default: false)') { |v| $PRY_ON_ERROR = v }
|
25
25
|
o.on('-A', '--about', 'show author/license information and exit') { about }
|
data/lib/aipp/parser.rb
CHANGED
@@ -12,6 +12,9 @@ module AIPP
|
|
12
12
|
# @return [AIXM::Document] target document
|
13
13
|
attr_reader :aixm
|
14
14
|
|
15
|
+
# @return [Hash] map from border names to border objects
|
16
|
+
attr_reader :borders
|
17
|
+
|
15
18
|
# @return [OpenStruct] object cache
|
16
19
|
attr_reader :cache
|
17
20
|
|
@@ -22,6 +25,7 @@ module AIPP
|
|
22
25
|
@config = {}
|
23
26
|
@aixm = AIXM.document(region: @options[:region], effective_at: @options[:airac].date)
|
24
27
|
@dependencies = THash.new
|
28
|
+
@borders = {}
|
25
29
|
@cache = OpenStruct.new
|
26
30
|
end
|
27
31
|
|
@@ -38,9 +42,16 @@ module AIPP
|
|
38
42
|
info("Reading region #{options[:region]}")
|
39
43
|
dir = Pathname(__FILE__).dirname.join('regions', options[:region])
|
40
44
|
fail("unknown region `#{options[:region]}'") unless dir.exist?
|
45
|
+
# Borders
|
46
|
+
dir.glob('borders/*.geojson').each do |file|
|
47
|
+
border = AIPP::Border.new(file)
|
48
|
+
@borders[border.name] = border
|
49
|
+
end
|
50
|
+
# Helpers
|
41
51
|
dir.glob('helpers/*.rb').each { |f| require f }
|
52
|
+
# Parsers
|
42
53
|
dir.glob('*.rb').each do |file|
|
43
|
-
|
54
|
+
verbose_info "Requiring #{file.basename}"
|
44
55
|
require file
|
45
56
|
aip = file.basename('.*').to_s
|
46
57
|
@dependencies[aip] = ("AIPP::%s::%s::DEPENDS" % [options[:region], aip.remove(/\W/).classify]).constantize
|
data/lib/aipp/patcher.rb
CHANGED
@@ -24,7 +24,7 @@ module AIPP
|
|
24
24
|
define_method(:"#{attribute}=") do |value|
|
25
25
|
catch :abort do
|
26
26
|
value = block.call(parser, self, value)
|
27
|
-
|
27
|
+
verbose_info("PATCH: #{self.inspect}", color: :magenta)
|
28
28
|
end
|
29
29
|
send(:"original_#{attribute}=", value)
|
30
30
|
end
|
data/lib/aipp/pdf.rb
CHANGED
@@ -97,13 +97,13 @@ module AIPP
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def read_cache
|
100
|
-
cache_file = "#{@file}.json"
|
101
|
-
if
|
102
|
-
JSON.load
|
100
|
+
cache_file = Pathname.new("#{@file}.json")
|
101
|
+
if cache_file.exist? && (@file.stat.mtime - cache_file.stat.mtime).abs < 1
|
102
|
+
JSON.load cache_file
|
103
103
|
else
|
104
104
|
read.tap do |data|
|
105
|
-
|
106
|
-
FileUtils.touch(cache_file, mtime:
|
105
|
+
cache_file.write data.to_json
|
106
|
+
FileUtils.touch(cache_file, mtime: @file.stat.mtime)
|
107
107
|
end
|
108
108
|
end
|
109
109
|
end
|
@@ -32,9 +32,9 @@ module AIPP
|
|
32
32
|
tbody = prepare(html: read).css('tbody').first # skip altiports
|
33
33
|
tbody.css('tr').to_enum.with_index(1).each do |tr, index|
|
34
34
|
if tr.attr(:id).match?(/-TXT_NAME-/)
|
35
|
-
|
35
|
+
add @airport if @airport && !ad2_exists
|
36
36
|
@airport = airport_from tr
|
37
|
-
|
37
|
+
verbose_info "Parsing #{@airport.id}"
|
38
38
|
ad2_exists = false
|
39
39
|
if airport = select(:airport, id: @airport.id).first
|
40
40
|
ad2_exists = true
|
@@ -47,7 +47,7 @@ module AIPP
|
|
47
47
|
rescue => error
|
48
48
|
warn("error parsing #{@airport.id} at ##{index}: #{error.message}", pry: error)
|
49
49
|
end
|
50
|
-
|
50
|
+
add @airport if @airport && !ad2_exists
|
51
51
|
end
|
52
52
|
|
53
53
|
private
|
@@ -64,7 +64,7 @@ module AIPP
|
|
64
64
|
).tap do |airport|
|
65
65
|
airport.z = AIXM.z(tds[4].text.strip.to_i, :qnh)
|
66
66
|
airport.declination = tds[2].text.remove('°').strip.to_f
|
67
|
-
|
67
|
+
# airport.transition_z = AIXM.z(5000, :qnh) # TODO: default - exceptions exist
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|