aipp 0.2.6 → 1.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.
- 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
data/lib/core_ext/string.rb
CHANGED
@@ -32,60 +32,13 @@ class String
|
|
32
32
|
# are preserved and not collapsed into one space.
|
33
33
|
#
|
34
34
|
# @example
|
35
|
-
# " foo\n\nbar \r".
|
35
|
+
# " foo\n\nbar \r".compact # => "foo\nbar"
|
36
36
|
#
|
37
37
|
# @return [String] compacted string
|
38
38
|
def compact
|
39
39
|
split("\n").map { _1.squish.blank_to_nil }.compact.join("\n")
|
40
40
|
end
|
41
41
|
|
42
|
-
# Calculate the correlation of two strings by counting mutual words
|
43
|
-
#
|
44
|
-
# Both strings are normalized as follows:
|
45
|
-
# * remove accents, umlauts etc
|
46
|
-
# * remove everything but members of the +\w+ class
|
47
|
-
# * downcase
|
48
|
-
#
|
49
|
-
# The normalized strings are split into words. Only words fulfilling either
|
50
|
-
# of the following conditions are taken into consideration:
|
51
|
-
# * words present in and translated by the +synonyms+ map
|
52
|
-
# * words of at least 5 characters length
|
53
|
-
# * words consisting of exactly one letter followed by any number of digits
|
54
|
-
# (an optional whitespace between the two is ignored, e.g. "D 25" is the
|
55
|
-
# same as "D25")
|
56
|
-
#
|
57
|
-
# The +synonyms+ map is an array where terms in even positions map to their
|
58
|
-
# synonym in the following (odd) position:
|
59
|
-
#
|
60
|
-
# SYNONYMS = ['term1', 'synonym1', 'term2', 'synonym2']
|
61
|
-
#
|
62
|
-
# @example
|
63
|
-
# subject = "Truck en route on N 3 sud"
|
64
|
-
# subject.correlate("my car is on D25") # => 0
|
65
|
-
# subject.correlate("my truck is on D25") # => 1
|
66
|
-
# subject.correlate("my truck is on N3") # => 2
|
67
|
-
# subject.correlate("south", ['sud', 'south']) # => 1
|
68
|
-
#
|
69
|
-
# @param other [String] string to compare with
|
70
|
-
# @param synonyms [Array<String>] array of synonym pairs
|
71
|
-
# @return [Integer] 0 for unrelated strings and positive integers for related
|
72
|
-
# strings with higher numbers indicating tighter correlation
|
73
|
-
def correlate(other, synonyms=[])
|
74
|
-
self_words, other_words = [self, other].map do |string|
|
75
|
-
string.
|
76
|
-
unicode_normalize(:nfd).
|
77
|
-
downcase.gsub(/[-\u2013]/, ' ').
|
78
|
-
remove(/[^\w\s]/).
|
79
|
-
gsub(/\b(\w)\s?(\d+)\b/, '\1\2').
|
80
|
-
compact.
|
81
|
-
split(/\W+/).
|
82
|
-
map { (i = synonyms.index(_1)).nil? ? _1 : (i.odd? ? _1 : synonyms[i + 1]).upcase }.
|
83
|
-
keep_if { _1.match?(/\w{5,}|\w\d+|[[:upper:]]/) }.
|
84
|
-
uniq
|
85
|
-
end
|
86
|
-
(self_words & other_words).count
|
87
|
-
end
|
88
|
-
|
89
42
|
# Similar to +strip+, but remove any leading or trailing non-letters/numbers
|
90
43
|
# which includes whitespace
|
91
44
|
def full_strip
|
@@ -97,6 +50,37 @@ class String
|
|
97
50
|
scan(pattern).tap { remove! pattern }
|
98
51
|
end
|
99
52
|
|
53
|
+
# Apply the patterns in the given order and return...
|
54
|
+
# * first capture group - if a pattern matches and contains a capture group
|
55
|
+
# * entire match - if a pattern matches and contains no capture group
|
56
|
+
# * +default+ - if no pattern matches and a +default+ is set
|
57
|
+
# * +nil+ - if no pattern matches and no +default+ is set
|
58
|
+
#
|
59
|
+
# @example
|
60
|
+
# "A/A: 123.5 mhz".first_match(/123\.5/) # => "123.5"
|
61
|
+
# "A/A: 123.5 mhz".first_match(/:\s+([\d.]+)/) # => "123.5"
|
62
|
+
# "A/A: 123.5 mhz".first_match(/121\.5/) # nil
|
63
|
+
# "A/A: 123.5 mhz".first_match(/(121\.5)/) # nil
|
64
|
+
# "A/A: 123.5 mhz".first_match(/121\.5/, default: "123") # "123"
|
65
|
+
#
|
66
|
+
# @param patterns [Array<Regexp>] one or more patterns to apply in order
|
67
|
+
# @param default [String] string to return instead of +nil+ if the pattern
|
68
|
+
# doesn't match
|
69
|
+
# @return [String, nil]
|
70
|
+
def first_match(*patterns, default: nil)
|
71
|
+
patterns.each do |pattern|
|
72
|
+
if captures = match(pattern)
|
73
|
+
return captures[1] || captures[0]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
default
|
77
|
+
end
|
78
|
+
|
79
|
+
# Remove all XML/HTML tags and entities from the string
|
80
|
+
def strip_markup
|
81
|
+
self.gsub(/<.*?>|&[#\da-z]+;/i, '')
|
82
|
+
end
|
83
|
+
|
100
84
|
# Same as +to_f+ but accept both dot and comma as decimal separator
|
101
85
|
#
|
102
86
|
# @example
|
@@ -109,21 +93,4 @@ class String
|
|
109
93
|
sub(/,/, '.').to_f
|
110
94
|
end
|
111
95
|
|
112
|
-
# Add spaces between obviously glued words:
|
113
|
-
# * camel glued words
|
114
|
-
# * three-or-more-letter and number-only words
|
115
|
-
#
|
116
|
-
# @example
|
117
|
-
# "thisString has spaceProblems".unglue # => "this String has space problems"
|
118
|
-
# "the first123meters of D25".unglue # => "the first 123 meters of D25"
|
119
|
-
#
|
120
|
-
# @return [String] unglued string
|
121
|
-
def unglue
|
122
|
-
self.dup.tap do |string|
|
123
|
-
[/([[:lower:]])([[:upper:]])/, /([[:alpha:]]{3,})(\d)/, /(\d)([[:alpha:]]{3,})/].freeze.each do |regexp|
|
124
|
-
string.gsub!(regexp, '\1 \2')
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
96
|
end
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,95 +1,101 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aipp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sven Schwyn
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain:
|
11
11
|
- |
|
12
12
|
-----BEGIN CERTIFICATE-----
|
13
13
|
MIIDcDCCAligAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MQ0wCwYDVQQDDARydWJ5
|
14
14
|
MRkwFwYKCZImiZPyLGQBGRYJYml0Y2V0ZXJhMRMwEQYKCZImiZPyLGQBGRYDY29t
|
15
|
-
|
15
|
+
MB4XDTIxMTEwODE0MzIyM1oXDTIyMTEwODE0MzIyM1owPzENMAsGA1UEAwwEcnVi
|
16
16
|
eTEZMBcGCgmSJomT8ixkARkWCWJpdGNldGVyYTETMBEGCgmSJomT8ixkARkWA2Nv
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
25
|
bTAdBgNVHRIEFjAUgRJydWJ5QGJpdGNldGVyYS5jb20wDQYJKoZIhvcNAQEFBQAD
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
ggEBACI7lJKRbnRjz0T4Wb9jH4SE0A2yaHAoBzj96luVDjNyoRT3688trEZS75Sg
|
27
|
+
GKfChxqKncBrSpxJ0YfWbymNHfUrKhcdSifJ/TtUrTasm6LSnJYLOnLKDO3v8eL3
|
28
|
+
gRTq8a5wA7Xtijx3MJEyzdeUh7N+UMKuPps/flPgH5yabUxgxrvuhrXF7Z96nrsP
|
29
|
+
EOmNMTc8H7wo4BAKfuMcI/Gh2oCf+tAhr0bGsXyBikmJ6XA45mrOMgv19M1+aMpn
|
30
|
+
1+2Y1+i+4jd1B7qxIgOLxQTNIJiwE0sqU1itFfuesfgUACS7M0IV9u9Bp4hBGNEw
|
31
|
+
5JcY2h7owdMxXIvgk1oakgldFJc=
|
32
32
|
-----END CERTIFICATE-----
|
33
|
-
date:
|
33
|
+
date: 2022-03-05 00:00:00.000000000 Z
|
34
34
|
dependencies:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
|
-
name:
|
36
|
+
name: airac
|
37
37
|
requirement: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- - "
|
39
|
+
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: 0
|
41
|
+
version: '1.0'
|
42
42
|
type: :runtime
|
43
43
|
prerelease: false
|
44
44
|
version_requirements: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- - "
|
46
|
+
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: 0
|
48
|
+
version: '1.0'
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
|
-
name:
|
50
|
+
name: aixm
|
51
51
|
requirement: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: '
|
55
|
+
version: '1.1'
|
56
56
|
type: :runtime
|
57
57
|
prerelease: false
|
58
58
|
version_requirements: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
60
|
- - "~>"
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: '
|
62
|
+
version: '1.1'
|
63
63
|
- !ruby/object:Gem::Dependency
|
64
|
-
name:
|
64
|
+
name: activesupport
|
65
65
|
requirement: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - "~>"
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: '
|
69
|
+
version: '7'
|
70
70
|
type: :runtime
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
74
|
- - "~>"
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version: '
|
76
|
+
version: '7'
|
77
77
|
- !ruby/object:Gem::Dependency
|
78
|
-
name:
|
78
|
+
name: nokogiri
|
79
79
|
requirement: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
81
|
- - "~>"
|
82
82
|
- !ruby/object:Gem::Version
|
83
|
-
version: '
|
83
|
+
version: '1'
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: 1.12.0
|
84
87
|
type: :runtime
|
85
88
|
prerelease: false
|
86
89
|
version_requirements: !ruby/object:Gem::Requirement
|
87
90
|
requirements:
|
88
91
|
- - "~>"
|
89
92
|
- !ruby/object:Gem::Version
|
90
|
-
version: '
|
93
|
+
version: '1'
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.12.0
|
91
97
|
- !ruby/object:Gem::Dependency
|
92
|
-
name:
|
98
|
+
name: roo
|
93
99
|
requirement: !ruby/object:Gem::Requirement
|
94
100
|
requirements:
|
95
101
|
- - "~>"
|
@@ -103,7 +109,7 @@ dependencies:
|
|
103
109
|
- !ruby/object:Gem::Version
|
104
110
|
version: '2'
|
105
111
|
- !ruby/object:Gem::Dependency
|
106
|
-
name:
|
112
|
+
name: pdf-reader
|
107
113
|
requirement: !ruby/object:Gem::Requirement
|
108
114
|
requirements:
|
109
115
|
- - "~>"
|
@@ -117,7 +123,7 @@ dependencies:
|
|
117
123
|
- !ruby/object:Gem::Version
|
118
124
|
version: '2'
|
119
125
|
- !ruby/object:Gem::Dependency
|
120
|
-
name:
|
126
|
+
name: json
|
121
127
|
requirement: !ruby/object:Gem::Requirement
|
122
128
|
requirements:
|
123
129
|
- - "~>"
|
@@ -131,21 +137,21 @@ dependencies:
|
|
131
137
|
- !ruby/object:Gem::Version
|
132
138
|
version: '2'
|
133
139
|
- !ruby/object:Gem::Dependency
|
134
|
-
name:
|
140
|
+
name: rubyzip
|
135
141
|
requirement: !ruby/object:Gem::Requirement
|
136
142
|
requirements:
|
137
143
|
- - "~>"
|
138
144
|
- !ruby/object:Gem::Version
|
139
|
-
version: '
|
145
|
+
version: '2'
|
140
146
|
type: :runtime
|
141
147
|
prerelease: false
|
142
148
|
version_requirements: !ruby/object:Gem::Requirement
|
143
149
|
requirements:
|
144
150
|
- - "~>"
|
145
151
|
- !ruby/object:Gem::Version
|
146
|
-
version: '
|
152
|
+
version: '2'
|
147
153
|
- !ruby/object:Gem::Dependency
|
148
|
-
name:
|
154
|
+
name: colorize
|
149
155
|
requirement: !ruby/object:Gem::Requirement
|
150
156
|
requirements:
|
151
157
|
- - "~>"
|
@@ -159,33 +165,19 @@ dependencies:
|
|
159
165
|
- !ruby/object:Gem::Version
|
160
166
|
version: '0'
|
161
167
|
- !ruby/object:Gem::Dependency
|
162
|
-
name:
|
168
|
+
name: debug
|
163
169
|
requirement: !ruby/object:Gem::Requirement
|
164
170
|
requirements:
|
165
|
-
- - "
|
166
|
-
- !ruby/object:Gem::Version
|
167
|
-
version: '1'
|
168
|
-
type: :runtime
|
169
|
-
prerelease: false
|
170
|
-
version_requirements: !ruby/object:Gem::Requirement
|
171
|
-
requirements:
|
172
|
-
- - "~>"
|
173
|
-
- !ruby/object:Gem::Version
|
174
|
-
version: '1'
|
175
|
-
- !ruby/object:Gem::Dependency
|
176
|
-
name: pry-stack_explorer
|
177
|
-
requirement: !ruby/object:Gem::Requirement
|
178
|
-
requirements:
|
179
|
-
- - "~>"
|
171
|
+
- - ">="
|
180
172
|
- !ruby/object:Gem::Version
|
181
|
-
version:
|
173
|
+
version: 1.0.0
|
182
174
|
type: :runtime
|
183
175
|
prerelease: false
|
184
176
|
version_requirements: !ruby/object:Gem::Requirement
|
185
177
|
requirements:
|
186
|
-
- - "
|
178
|
+
- - ">="
|
187
179
|
- !ruby/object:Gem::Version
|
188
|
-
version:
|
180
|
+
version: 1.0.0
|
189
181
|
- !ruby/object:Gem::Dependency
|
190
182
|
name: rake
|
191
183
|
requirement: !ruby/object:Gem::Requirement
|
@@ -334,52 +326,49 @@ files:
|
|
334
326
|
- exe/aip2ofmx
|
335
327
|
- lib/aipp.rb
|
336
328
|
- lib/aipp/aip.rb
|
337
|
-
- lib/aipp/airac.rb
|
338
329
|
- lib/aipp/border.rb
|
330
|
+
- lib/aipp/debugger.rb
|
339
331
|
- lib/aipp/downloader.rb
|
340
332
|
- lib/aipp/executable.rb
|
341
333
|
- lib/aipp/parser.rb
|
342
334
|
- lib/aipp/patcher.rb
|
343
335
|
- lib/aipp/pdf.rb
|
344
|
-
- lib/aipp/regions/LF/
|
345
|
-
- lib/aipp/regions/LF/
|
346
|
-
- lib/aipp/regions/LF/AD-2.rb
|
347
|
-
- lib/aipp/regions/LF/AD-3.1.rb
|
348
|
-
- lib/aipp/regions/LF/ENR-2.1.rb
|
349
|
-
- lib/aipp/regions/LF/ENR-4.1.rb
|
350
|
-
- lib/aipp/regions/LF/ENR-4.3.rb
|
351
|
-
- lib/aipp/regions/LF/ENR-5.1.rb
|
352
|
-
- lib/aipp/regions/LF/ENR-5.4.rb
|
353
|
-
- lib/aipp/regions/LF/ENR-5.5.rb
|
336
|
+
- lib/aipp/regions/LF/README.md
|
337
|
+
- lib/aipp/regions/LF/aerodromes.rb
|
354
338
|
- lib/aipp/regions/LF/borders/france_atlantic_coast.geojson
|
355
339
|
- lib/aipp/regions/LF/borders/france_atlantic_territorial_sea.geojson
|
356
340
|
- lib/aipp/regions/LF/borders/france_ecrins_national_park.geojson
|
357
341
|
- lib/aipp/regions/LF/borders/france_mediterranean_coast.geojson
|
358
|
-
- lib/aipp/regions/LF/
|
359
|
-
- lib/aipp/regions/LF/
|
360
|
-
- lib/aipp/regions/LF/
|
361
|
-
- lib/aipp/regions/LF/
|
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
|
+
- lib/aipp/regions/LF/fixtures/aerodromes.yml
|
346
|
+
- lib/aipp/regions/LF/helipads.rb
|
362
347
|
- lib/aipp/regions/LF/helpers/base.rb
|
363
|
-
- lib/aipp/regions/LF/helpers/
|
364
|
-
- lib/aipp/regions/LF/helpers/
|
348
|
+
- lib/aipp/regions/LF/helpers/surface.rb
|
349
|
+
- 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
|
365
354
|
- lib/aipp/t_hash.rb
|
366
355
|
- lib/aipp/version.rb
|
367
356
|
- lib/core_ext/enumerable.rb
|
368
357
|
- lib/core_ext/hash.rb
|
369
358
|
- lib/core_ext/integer.rb
|
370
359
|
- lib/core_ext/nil_class.rb
|
371
|
-
- lib/core_ext/
|
360
|
+
- lib/core_ext/nokogiri.rb
|
372
361
|
- lib/core_ext/string.rb
|
373
362
|
homepage: https://github.com/svoop/aipp
|
374
363
|
licenses:
|
375
364
|
- MIT
|
376
365
|
metadata:
|
377
366
|
homepage_uri: https://github.com/svoop/aipp
|
378
|
-
changelog_uri: https://github.com/svoop/aipp/blob/
|
367
|
+
changelog_uri: https://github.com/svoop/aipp/blob/main/CHANGELOG.md
|
379
368
|
source_code_uri: https://github.com/svoop/aipp
|
380
369
|
documentation_uri: https://www.rubydoc.info/gems/aipp
|
381
370
|
bug_tracker_uri: https://github.com/svoop/aipp/issues
|
382
|
-
post_install_message:
|
371
|
+
post_install_message:
|
383
372
|
rdoc_options:
|
384
373
|
- "--title"
|
385
374
|
- AIP Parser and Converter
|
@@ -394,15 +383,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
394
383
|
requirements:
|
395
384
|
- - ">="
|
396
385
|
- !ruby/object:Gem::Version
|
397
|
-
version:
|
386
|
+
version: 3.0.0
|
398
387
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
399
388
|
requirements:
|
400
389
|
- - ">="
|
401
390
|
- !ruby/object:Gem::Version
|
402
391
|
version: '0'
|
403
392
|
requirements: []
|
404
|
-
rubygems_version: 3.
|
405
|
-
signing_key:
|
393
|
+
rubygems_version: 3.3.8
|
394
|
+
signing_key:
|
406
395
|
specification_version: 4
|
407
396
|
summary: Parser for aeronautical information publications
|
408
397
|
test_files: []
|
metadata.gz.sig
CHANGED
Binary file
|
data/lib/aipp/airac.rb
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
module AIPP
|
2
|
-
|
3
|
-
# AIRAC cycle date calculations
|
4
|
-
#
|
5
|
-
# @example
|
6
|
-
# airac = AIPP::AIRAC.new('2018-01-01')
|
7
|
-
# airac.date # => #<Date: 2017-12-07 ((2458095j,0s,0n),+0s,2299161j)>
|
8
|
-
# airac.id # => 1713
|
9
|
-
# airac.next_date # => #<Date: 2018-01-04 ((2458123j,0s,0n),+0s,2299161j)>
|
10
|
-
# airac.next_id # => 1801
|
11
|
-
class AIRAC
|
12
|
-
# First AIRAC date following the last cycle length modification
|
13
|
-
ROOT_DATE = Date.parse('2015-06-25').freeze
|
14
|
-
|
15
|
-
# Length of one AIRAC cycle
|
16
|
-
DAYS_PER_CYCLE = 28
|
17
|
-
|
18
|
-
# @return [Date] AIRAC effective on date
|
19
|
-
attr_reader :date
|
20
|
-
|
21
|
-
# @return [Integer] AIRAC cycle ID
|
22
|
-
attr_reader :id
|
23
|
-
|
24
|
-
# @param any_date [Date] any date within the AIRAC cycle (default: today)
|
25
|
-
def initialize(any_date = nil)
|
26
|
-
any_date = any_date ? Date.parse(any_date.to_s) : Date.today
|
27
|
-
fail(ArgumentError, "cannot calculate dates before #{ROOT_DATE}") if any_date < ROOT_DATE
|
28
|
-
@date = date_for(any_date)
|
29
|
-
@id = id_for(@date)
|
30
|
-
end
|
31
|
-
|
32
|
-
# @return [Date] next AIRAC effective on date
|
33
|
-
def next_date
|
34
|
-
date + DAYS_PER_CYCLE
|
35
|
-
end
|
36
|
-
|
37
|
-
# @return [Integer] next AIRAC cycle ID
|
38
|
-
def next_id
|
39
|
-
id_for next_date
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
# Find the AIRAC date for +any_date+
|
45
|
-
def date_for(any_date)
|
46
|
-
ROOT_DATE + (any_date - ROOT_DATE).to_i / DAYS_PER_CYCLE * DAYS_PER_CYCLE
|
47
|
-
end
|
48
|
-
|
49
|
-
# Find the AIRAC ID for the AIRAC +date+
|
50
|
-
def id_for(date)
|
51
|
-
(date.year % 100) * 100 + ((date.yday - 1) / 28) + 1
|
52
|
-
end
|
53
|
-
|
54
|
-
end
|
55
|
-
end
|
@@ -1,177 +0,0 @@
|
|
1
|
-
module AIPP
|
2
|
-
module LF
|
3
|
-
|
4
|
-
# Aerodromes
|
5
|
-
class AD13 < AIP
|
6
|
-
|
7
|
-
include AIPP::LF::Helpers::Base
|
8
|
-
|
9
|
-
DEPENDS = %w(AD-2)
|
10
|
-
|
11
|
-
# Map names of id-less airports to unofficial ids
|
12
|
-
ID_LESS_AIRPORTS = {
|
13
|
-
"ALBE" => 'LF9001',
|
14
|
-
"BEAUMONT DE LOMAGNE" => 'LF9002',
|
15
|
-
"BERDOUES" => 'LF9003',
|
16
|
-
"BOULOC" => 'LF9004',
|
17
|
-
"BUXEUIL ST REMY / CREUSE" => 'LF9005',
|
18
|
-
"CALVIAC" => 'LF9006',
|
19
|
-
"CAYLUS" => 'LF9007',
|
20
|
-
"CORBONOD" => 'LF9008',
|
21
|
-
"L'ISLE EN DODON" => 'LF9009',
|
22
|
-
"LACAVE LE FRAU" => 'LF9010',
|
23
|
-
"LUCON CHASNAIS" => 'LF9011',
|
24
|
-
"PEYRELEVADE" => 'LF9012',
|
25
|
-
"SAINT CYR LA CAMPAGNE" => 'LF9013',
|
26
|
-
"SEPTFONDS" => 'LF9014',
|
27
|
-
"TALMONT VENDEE AIR PARK" => 'LF9015'
|
28
|
-
}.freeze
|
29
|
-
|
30
|
-
PURPOSES = {
|
31
|
-
"s" => :scheduled,
|
32
|
-
"ns" => :not_scheduled,
|
33
|
-
"p" => :private
|
34
|
-
}.freeze
|
35
|
-
|
36
|
-
def parse
|
37
|
-
ad2_exists = false
|
38
|
-
tbody = prepare(html: read).css('tbody').first # skip altiports
|
39
|
-
tbody.css('tr').to_enum.with_index(1).each do |tr, index|
|
40
|
-
if tr.attr(:id).match?(/-TXT_NAME-/)
|
41
|
-
add @airport if @airport && !ad2_exists
|
42
|
-
@airport = airport_from tr
|
43
|
-
verbose_info "Parsing #{@airport.id}"
|
44
|
-
ad2_exists = false
|
45
|
-
if airport = find_by(:airport, id: @airport.id).first
|
46
|
-
ad2_exists = true
|
47
|
-
@airport = airport
|
48
|
-
end
|
49
|
-
add_usage_limitations_from tr
|
50
|
-
next
|
51
|
-
end
|
52
|
-
@airport.add_runway(runway_from(tr)) unless ad2_exists
|
53
|
-
rescue => error
|
54
|
-
warn("error parsing #{@airport.id} at ##{index}: #{error.message}", pry: error)
|
55
|
-
end
|
56
|
-
add @airport if @airport && !ad2_exists
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
def airport_from(tr)
|
62
|
-
tds = tr.css('td')
|
63
|
-
id = tds[0].text.strip.blank_to_nil || ID_LESS_AIRPORTS.fetch(tds[1].text.strip)
|
64
|
-
AIXM.airport(
|
65
|
-
source: source(position: tr.line),
|
66
|
-
organisation: organisation_lf, # TODO: not yet implemented
|
67
|
-
id: id,
|
68
|
-
name: tds[1].text.strip,
|
69
|
-
xy: xy_from(tds[3].text)
|
70
|
-
).tap do |airport|
|
71
|
-
airport.z = AIXM.z(tds[4].text.strip.to_i, :qnh)
|
72
|
-
airport.declination = tds[2].text.remove('°').strip.to_f
|
73
|
-
# airport.transition_z = AIXM.z(5000, :qnh) # TODO: default - exceptions exist
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def add_usage_limitations_from(tr)
|
78
|
-
raw_limitation = tr.css('td:nth-of-type(8)').text.cleanup.downcase
|
79
|
-
raw_conditions = tr.css('td:nth-of-type(6)').text.cleanup.downcase.split(%r([\s/]+))
|
80
|
-
limitation = case raw_limitation
|
81
|
-
when /ouv.+cap|milit/ then :permitted
|
82
|
-
when /usa.+restr|priv/ then :reservation_required
|
83
|
-
end
|
84
|
-
@airport.add_usage_limitation(type: limitation) do |l|
|
85
|
-
(%w(s ns p) & raw_conditions).each do |raw_purpose|
|
86
|
-
l.add_condition do |c|
|
87
|
-
c.realm = raw_limitation.match?(/milit/) ? :military : :civilian
|
88
|
-
if (%w(intl ntl) - raw_conditions).empty?
|
89
|
-
c.origin = :any
|
90
|
-
else
|
91
|
-
c.origin = :national if raw_conditions.include?('ntl')
|
92
|
-
c.origin = :international if raw_conditions.include?('intl')
|
93
|
-
end
|
94
|
-
if (%w(ifr vfr) - raw_conditions).empty?
|
95
|
-
c.rule = :ifr_and_vfr
|
96
|
-
else
|
97
|
-
c.rule = :ifr if raw_conditions.include?('ifr')
|
98
|
-
c.rule = :vfr if raw_conditions.include?('vfr')
|
99
|
-
end
|
100
|
-
c.purpose = PURPOSES[raw_purpose]
|
101
|
-
end
|
102
|
-
end
|
103
|
-
l.remarks = "Usage restreint (voir VAC) / restricted use (see VAC)" if raw_limitation.match?(/usa.+restr/)
|
104
|
-
l.remarks = "Propriété privée / privately owned" if raw_limitation.match?(/priv/)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
def runway_from(tr)
|
109
|
-
tds = tr.css('td')
|
110
|
-
AIXM.runway(
|
111
|
-
name: tds[0].text.strip.split.join('/')
|
112
|
-
).tap do |runway|
|
113
|
-
@runway = runway # TODO: needed for now for surface composition patches to work
|
114
|
-
bidirectional = runway.name.include? '/'
|
115
|
-
runway.length = AIXM.d(tds[1].css('span[id$="VAL_LEN"]').text.to_i, :m)
|
116
|
-
runway.width = AIXM.d(tds[1].css('span[id$="VAL_WID"]').text.to_i, :m)
|
117
|
-
unless (text = tds[1].css('span[id*="SURFACE"]').text.compact).blank?
|
118
|
-
surface = SURFACES.metch(text)
|
119
|
-
runway.surface.composition = surface[:composition]
|
120
|
-
runway.surface.preparation = surface[:preparation]
|
121
|
-
runway.surface.remarks = surface[:remarks]
|
122
|
-
end
|
123
|
-
runway.remarks = tds[7].text.cleanup.blank_to_nil
|
124
|
-
values = tds[2].text.remove('°').strip.split
|
125
|
-
runway.forth.geographic_orientation = AIXM.a(values.first.to_i)
|
126
|
-
runway.back.geographic_orientation = AIXM.a(values.last.to_i) if bidirectional
|
127
|
-
parts = tds[3].text.strip.split(/\n\s+\n\s+/, 2)
|
128
|
-
runway.forth.xy = (xy_from(parts[0]) unless parts[0].blank?)
|
129
|
-
runway.back.xy = (xy_from(parts[1]) unless parts[1].blank?) if bidirectional
|
130
|
-
values = tds[4].text.strip.split
|
131
|
-
runway.forth.z = AIXM.z(values.first.to_i, :qnh)
|
132
|
-
runway.back.z = AIXM.z(values.last.to_i, :qnh) if bidirectional
|
133
|
-
displaced_thresholds = displaced_thresholds_from(tds[5])
|
134
|
-
runway.forth.displaced_threshold = displaced_thresholds.first
|
135
|
-
runway.back.displaced_threshold = displaced_thresholds.last if bidirectional
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
def displaced_thresholds_from(td)
|
140
|
-
values = td.text.strip.split
|
141
|
-
case values.count
|
142
|
-
when 1 then []
|
143
|
-
when 2 then [AIXM.xy(lat: values[0], long: values[1]), nil]
|
144
|
-
when 3 then [nil, AIXM.xy(lat: values[1], long: values[2])]
|
145
|
-
when 4 then [AIXM.xy(lat: values[0], long: values[1]), AIXM.xy(lat: values[2], long: values[3])]
|
146
|
-
else fail "cannot parse displaced thresholds"
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
patch AIXM::Component::Runway, :width do |parser, object, value|
|
151
|
-
throw :abort unless value.zero?
|
152
|
-
airport_id = parser.instance_variable_get(:@airport).id
|
153
|
-
runway_name = object.name.to_s
|
154
|
-
throw :abort if (width = parser.fixture.dig('runways', airport_id, runway_name, 'width')).nil?
|
155
|
-
AIXM.d(width.to_i, :m)
|
156
|
-
end
|
157
|
-
|
158
|
-
patch AIXM::Component::Runway::Direction, :xy do |parser, object, value|
|
159
|
-
throw :abort unless value.nil?
|
160
|
-
airport_id = parser.instance_variable_get(:@airport).id
|
161
|
-
direction_name = object.name.to_s
|
162
|
-
throw :abort if (xy = parser.fixture.dig('runways', airport_id, direction_name, 'xy')).nil?
|
163
|
-
lat, long = xy.split(/\s+/)
|
164
|
-
AIXM.xy(lat: lat, long: long)
|
165
|
-
end
|
166
|
-
|
167
|
-
patch AIXM::Component::Surface, :composition do |parser, object, value|
|
168
|
-
throw :abort unless value.blank?
|
169
|
-
airport_id = parser.instance_variable_get(:@airport).id
|
170
|
-
runway_name = parser.instance_variable_get(:@runway).name
|
171
|
-
throw :abort if (composition = parser.fixture.dig('runways', airport_id, runway_name, 'composition')).nil?
|
172
|
-
composition
|
173
|
-
end
|
174
|
-
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|