aipp 0.1.3 → 0.2.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
- data/.gitignore +2 -0
- data/.ruby-version +1 -1
- data/.yardopts +3 -0
- data/CHANGELOG.md +25 -10
- data/README.md +116 -27
- data/aipp.gemspec +4 -2
- data/exe/aip2aixm +1 -50
- data/exe/aip2ofmx +11 -0
- data/lib/aipp.rb +20 -3
- data/lib/aipp/aip.rb +63 -0
- data/lib/aipp/airac.rb +17 -9
- data/lib/aipp/executable.rb +82 -0
- data/lib/aipp/parser.rb +97 -0
- data/lib/aipp/progress.rb +40 -0
- data/lib/aipp/refinements.rb +91 -28
- data/lib/aipp/regions/LF/ENR-2.1.rb +89 -0
- data/lib/aipp/regions/LF/ENR-4.1.rb +101 -0
- data/lib/aipp/regions/LF/ENR-4.3.rb +26 -0
- data/lib/aipp/regions/LF/ENR-5.1.rb +65 -0
- data/lib/aipp/regions/LF/helper.rb +177 -0
- data/lib/aipp/t_hash.rb +46 -0
- data/lib/aipp/version.rb +1 -1
- data/spec/lib/aipp/airac_spec.rb +3 -3
- data/spec/lib/aipp/refinements_spec.rb +97 -27
- data/spec/lib/aipp/t_hash_spec.rb +44 -0
- metadata +50 -14
- data/lib/aipp/loader.rb +0 -52
- data/lib/aipp/parsers/LF/AD-1.5.rb +0 -128
- data/lib/aipp/parsers/LF/ENR-4.1.rb +0 -105
- data/lib/aipp/parsers/LF/ENR-4.3.rb +0 -32
- data/lib/aipp/parsers/LF/ENR-5.1.rb +0 -134
- data/lib/aipp/parsers/LF/helpers/html.rb +0 -11
- data/lib/aipp/parsers/LF/helpers/url.rb +0 -15
@@ -1,32 +0,0 @@
|
|
1
|
-
module AIPP
|
2
|
-
module Parsers
|
3
|
-
include Helpers::URL
|
4
|
-
include Helpers::HTML
|
5
|
-
|
6
|
-
def convert!
|
7
|
-
cleanup!
|
8
|
-
html.css('tbody').each do |tbody|
|
9
|
-
tbody.css('tr').to_enum.with_index(1).each do |tr, index|
|
10
|
-
break if index >= @limit
|
11
|
-
tds = tr.css('td')
|
12
|
-
designated_point = AIXM.designated_point(
|
13
|
-
type: :icao,
|
14
|
-
id: tds[0].text.strip,
|
15
|
-
xy: xy_from(tds[1])
|
16
|
-
)
|
17
|
-
aixm.features << designated_point
|
18
|
-
rescue => exception
|
19
|
-
warn("WARNING: error parsing designated point at ##{index}: #{exception.message}", binding)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
true
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def xy_from(td)
|
28
|
-
parts = td.text.strip.split(/\s+/)
|
29
|
-
AIXM.xy(lat: parts[0], long: parts[1])
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,134 +0,0 @@
|
|
1
|
-
module AIPP
|
2
|
-
module Parsers
|
3
|
-
include Helpers::URL
|
4
|
-
include Helpers::HTML
|
5
|
-
using AIPP::Refinements
|
6
|
-
using AIXM::Refinements
|
7
|
-
|
8
|
-
TYPES = {
|
9
|
-
'D' => 'D',
|
10
|
-
'P' => 'P',
|
11
|
-
'R' => 'R',
|
12
|
-
'ZIT' => 'P'
|
13
|
-
}.freeze
|
14
|
-
|
15
|
-
BORDERS = {
|
16
|
-
'franco-allemande' => 'FRANCE_GERMANY',
|
17
|
-
'franco-espagnole' => 'FRANCE_SPAIN',
|
18
|
-
'franco-italienne' => 'FRANCE_ITALY',
|
19
|
-
'franco-suisse' => 'FRANCE_SWITZERLAND',
|
20
|
-
'franco-luxembourgeoise' => 'FRANCE_LUXEMBOURG',
|
21
|
-
'franco-belge' => 'BELGIUM_FRANCE'
|
22
|
-
}.freeze
|
23
|
-
|
24
|
-
def convert!
|
25
|
-
cleanup!
|
26
|
-
html.css('tbody:has(tr[id^=mid])').each do |tbody|
|
27
|
-
airspace = nil
|
28
|
-
tbody.css('tr').to_enum.with_index(1).each do |tr, index|
|
29
|
-
if tr.attr(:class) =~ /keep-with-next-row/
|
30
|
-
airspace = airspace_from tr
|
31
|
-
else
|
32
|
-
begin
|
33
|
-
tds = tr.css('td')
|
34
|
-
airspace.geometry = geometry_from tds[0]
|
35
|
-
airspace.class_layers << class_layer_from(tds[1])
|
36
|
-
airspace.schedule = schedule_from tds[2]
|
37
|
-
airspace.remarks = remarks_from(tds[2], tds[3], tds[4])
|
38
|
-
fail "airspace `#{airspace.name}' is not complete" unless airspace.complete?
|
39
|
-
aixm.features << airspace
|
40
|
-
break if index / 2 >= @limit
|
41
|
-
rescue => exception
|
42
|
-
warn("WARNING: error parsing airspace `#{airspace.name}' at ##{index}: #{exception.message}", binding)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
true
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
def airspace_from(tr)
|
53
|
-
spans = tr.css(:span)
|
54
|
-
AIXM.airspace(
|
55
|
-
name: [spans[1], spans[2], spans[3], spans[5].text.blank_to_nil].compact.join(' '),
|
56
|
-
short_name: [spans[1], spans[2], spans[3]].compact.join(' '),
|
57
|
-
type: TYPES.fetch(spans[2].text)
|
58
|
-
)
|
59
|
-
end
|
60
|
-
|
61
|
-
def geometry_from(td)
|
62
|
-
AIXM.geometry.tap do |geometry|
|
63
|
-
buffer = {}
|
64
|
-
td.text.gsub(/\s+/, ' ').strip.split(/ - /).append('end').each do |element|
|
65
|
-
case element
|
66
|
-
when /frontière (.+)/i
|
67
|
-
geometry << AIXM.border(
|
68
|
-
xy: buffer.delete(:xy),
|
69
|
-
name: BORDERS.fetch($1)
|
70
|
-
)
|
71
|
-
when /arc (anti-)?horaire .+ sur (\S+) , (\S+)/i
|
72
|
-
geometry << AIXM.arc(
|
73
|
-
xy: buffer.delete(:xy),
|
74
|
-
center_xy: AIXM.xy(lat: $2, long: $3),
|
75
|
-
clockwise: $1.nil?
|
76
|
-
)
|
77
|
-
when /cercle de ([\d\.]+) (NM|km|m) .+ sur (\S+) , (\S+)/i
|
78
|
-
geometry << AIXM.circle(
|
79
|
-
center_xy: AIXM.xy(lat: $3, long: $4),
|
80
|
-
radius: $1.to_f.to_km(from: $2).round(3)
|
81
|
-
)
|
82
|
-
when /end|(\S+) , (\S+)/
|
83
|
-
geometry << AIXM.point(xy: buffer[:xy]) if buffer.has_key?(:xy)
|
84
|
-
buffer[:xy] = AIXM.xy(lat: $1, long: $2) if $1
|
85
|
-
else
|
86
|
-
fail "geometry `#{element}' not recognized"
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def class_layer_from(td)
|
93
|
-
above, below = td.text.gsub(/ /, '').split(/\n+/).select(&:blank_to_nil).split(/---+/)
|
94
|
-
above.reverse!
|
95
|
-
AIXM.class_layer(
|
96
|
-
vertical_limits: AIXM.vertical_limits(
|
97
|
-
max_z: z_from(above[1]),
|
98
|
-
upper_z: z_from(above[0]),
|
99
|
-
lower_z: z_from(below[0]),
|
100
|
-
min_z: z_from(below[1])
|
101
|
-
)
|
102
|
-
)
|
103
|
-
end
|
104
|
-
|
105
|
-
def z_from(limit)
|
106
|
-
case limit
|
107
|
-
when nil then nil
|
108
|
-
when 'SFC' then AIXM::GROUND
|
109
|
-
when 'UNL' then AIXM::UNLIMITED
|
110
|
-
when /(\d+)ftASFC/ then AIXM.z($1.to_i, :qfe)
|
111
|
-
when /(\d+)ftAMSL/ then AIXM.z($1.to_i, :qnh)
|
112
|
-
when /FL(\d+)/ then AIXM.z($1.to_i, :qne)
|
113
|
-
else fail "z `#{limit}' not recognized"
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def schedule_from(td)
|
118
|
-
AIXM::H24 if td.text.gsub(/\W/, '') == 'H24'
|
119
|
-
end
|
120
|
-
|
121
|
-
def remarks_from(*parts)
|
122
|
-
part_titles = ['SCHEDULE', 'RESTRICTION', 'AUTHORITY/CONDITIONS']
|
123
|
-
[].tap do |remarks|
|
124
|
-
parts.each.with_index do |part, index|
|
125
|
-
if part = part.text.gsub(/ +/, ' ').gsub(/(\n ?)+/, "\n").strip.blank_to_nil
|
126
|
-
unless index.zero? && part == 'H24'
|
127
|
-
remarks << "#{part_titles[index]}:\n#{part}"
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end.join("\n\n").blank_to_nil
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
module AIPP
|
2
|
-
module Helpers
|
3
|
-
module URL
|
4
|
-
|
5
|
-
def url
|
6
|
-
"https://www.sia.aviation-civile.gouv.fr/dvd/eAIP_%s/FRANCE/AIRAC-%s/html/eAIP/FR-%s-fr-FR.html" % [
|
7
|
-
aixm.effective_at.strftime('%d_%^b_%Y'), # 04_JAN_2018
|
8
|
-
aixm.effective_at.to_date.xmlschema, # 2018-01-04
|
9
|
-
@aip # ENR-5.1
|
10
|
-
]
|
11
|
-
end
|
12
|
-
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|