aipp 2.1.1 → 2.1.3
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 +12 -0
- data/lib/aipp/downloader/http.rb +2 -1
- data/lib/aipp/regions/LS/README.md +8 -0
- data/lib/aipp/regions/LS/helpers/base.rb +1 -2
- data/lib/aipp/regions/LS/shoot/shooting_grounds.rb +72 -39
- data/lib/aipp/scopes/shoot/executable.rb +6 -4
- data/lib/aipp/scopes/shoot/runner.rb +1 -1
- data/lib/aipp/version.rb +1 -1
- data/lib/core_ext/array.rb +23 -0
- data.tar.gz.sig +0 -0
- metadata +5 -5
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49b92a16dc5db1de68956dafe4d916867dff4847f11620b309eda93afd4bac30
|
4
|
+
data.tar.gz: 41eb770daa79b0c4ef44214652ea97e3c51696ddcbd80a6e605551f7a8e03d45
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01c3e7c184624fa4122e28391bd4a67dbb150b79240d87c7bbede6a354a0c3bd46d7ba6ce69dd22da2c392fd16b6c3fbcc95735c917726ee98c710060877940e
|
7
|
+
data.tar.gz: 8c2edd95391aa94587bbdd537f5daefef869272bf44b60ddf60cec6eb03c41bf04e834a2e2a525bcec680e64d9a16b3aa92ca966d50540f882998bb0773a2263
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,18 @@
|
|
2
2
|
|
3
3
|
Nothing so far
|
4
4
|
|
5
|
+
## 2.1.3
|
6
|
+
|
7
|
+
#### Changes
|
8
|
+
* Use uncompressed OFMX download for LS NOTAM
|
9
|
+
|
10
|
+
## 2.1.2
|
11
|
+
|
12
|
+
#### Changes
|
13
|
+
* Improve timesheet calculation for shooting grounds in LS
|
14
|
+
* Improve safety margins for shooting grounds in LS
|
15
|
+
* Switch to unzipped OFMX for now due to issues upstream
|
16
|
+
|
5
17
|
## 2.1.1
|
6
18
|
|
7
19
|
#### Additions
|
data/lib/aipp/downloader/http.rb
CHANGED
@@ -92,6 +92,14 @@ TOT | 0 | Row | text(3) | yes | "TOT" (aka: Total)
|
|
92
92
|
TOT | 1 | Created at | datetime(yyyymmddhhmmss) | yes | Date and time of CSV creation
|
93
93
|
TOT | 2 | SPL count | number | yes | Number of SPL records
|
94
94
|
|
95
|
+
### Safety Margins
|
96
|
+
|
97
|
+
The max height (BSZ col 15) has to be treated as an advisory value, not a guarantee:
|
98
|
+
|
99
|
+
If no value is given, the ammunition *should* not exceed 250m above ground. However, regulations for certain ammunition types allow for higher peaks. As of March 2023, 6cm mortars *may* reach up to 500m and future weapon systems *may* even go beyond that.
|
100
|
+
|
101
|
+
To account for this, the two constants `DEFAULT_Z` and `SAFETY` should be revisited from time to time.
|
102
|
+
|
95
103
|
## Asynchronous Use
|
96
104
|
|
97
105
|
### Command Line Arguments
|
@@ -48,8 +48,7 @@ module AIPP
|
|
48
48
|
fail "not yet implemented"
|
49
49
|
when 'AIP'
|
50
50
|
AIPP::Downloader::HTTP.new(
|
51
|
-
|
52
|
-
file: "ofmx_ls/isolated/ofmx_ls.ofmx"
|
51
|
+
file: "https://snapshots.openflightmaps.org/live/#{AIRAC::Cycle.new.id}/ofmx/lsas/latest/isolated/ofmx_ls.xml"
|
53
52
|
)
|
54
53
|
when 'DABS'
|
55
54
|
if aixm.effective_at.to_date == Date.today # DABS cross check works reliably for today only
|
@@ -5,33 +5,40 @@ module AIPP::LS::SHOOT
|
|
5
5
|
|
6
6
|
include AIPP::LS::Helpers::Base
|
7
7
|
|
8
|
-
DEFAULT_Z = AIXM.z(
|
8
|
+
DEFAULT_Z = AIXM.z(2000, :qfe) # fallback if no max height is defined
|
9
|
+
SAFETY = 100 # safety margin in meters added to max height
|
9
10
|
|
10
11
|
def parse
|
11
|
-
effective_date =
|
12
|
+
effective_date = AIPP.options.local_effective_at.strftime('%Y%m%d')
|
12
13
|
airac_date = AIRAC::Cycle.new(aixm.effective_at).to_s('%Y-%m-%d')
|
13
14
|
shooting_grounds = {}
|
14
15
|
read.each_with_index do |row, line|
|
15
16
|
type, id, date, no_shooting = row[0], row[1], row[2], (row[17] == "1")
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
17
|
+
next unless type == 'BSZ'
|
18
|
+
next if no_shooting || date != effective_date
|
19
|
+
next if AIPP.options.id && AIPP.options.id != id
|
20
|
+
# TODO: Several BSZ lines may exist for the same shooting area with
|
21
|
+
# different location codes (aka: partial activations). The geometries
|
22
|
+
# of those location codes are not currently available, we therefore
|
23
|
+
# have to merge the data into one record. The geometries should become
|
24
|
+
# available by the end of 2023 which will make it possible to map
|
25
|
+
# each line to one geometry and remove the merging logic.
|
26
|
+
upper_z = row[15] ? AIXM.z(AIXM.d(row[15].to_i + SAFETY, :m).to_ft.dim.round, :qfe) : DEFAULT_Z
|
27
|
+
(shooting_grounds[id] ||= { schedules: [], upper_z: AIXM::GROUND }).then do |s|
|
28
|
+
s[:feature] ||= read("shooting_grounds-#{id}").fetch(:feature)
|
29
|
+
s[:csv_line] ||= line
|
30
|
+
s[:url] ||= row[10].blank_to_nil
|
31
|
+
s[:details] = [s[:details], row[6].blank_to_nil].compact.join("\n")
|
32
|
+
s[:dabs] ||= (row[16] == '1')
|
33
|
+
s[:upper_z] = upper_z if upper_z.alt > s[:upper_z].alt
|
34
|
+
s[:schedules] += schedules_for(row)
|
29
35
|
end
|
30
36
|
end
|
31
37
|
shooting_grounds.each do |id, data|
|
32
|
-
data in csv_line:,
|
33
|
-
|
34
|
-
|
38
|
+
data in csv_line:, details:, url:, upper_z:, schedules:, dabs:, feature: { geometry: polygons, properties: { bezeichnung: name, infotelefonnr: phone, infoemail: email } }
|
39
|
+
schedules = consolidate(schedules)
|
40
|
+
if schedules.any?
|
41
|
+
geometries = geometries_for polygons
|
35
42
|
indexed = geometries.count > 1
|
36
43
|
geometries.each_with_index do |geometry, index|
|
37
44
|
remarks = {
|
@@ -49,7 +56,7 @@ module AIPP::LS::SHOOT
|
|
49
56
|
).tap do |airspace|
|
50
57
|
airspace.add_layer layer_for(upper_z, schedules, remarks)
|
51
58
|
airspace.geometry = geometry
|
52
|
-
airspace.comment = "DABS: marked for publication"
|
59
|
+
airspace.comment = "DABS: marked for publication" if dabs
|
53
60
|
end
|
54
61
|
)
|
55
62
|
end
|
@@ -59,18 +66,34 @@ module AIPP::LS::SHOOT
|
|
59
66
|
|
60
67
|
private
|
61
68
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
69
|
+
def schedules_for(row)
|
70
|
+
from, to = time_for(row[3]), time_for(row[4], ending: true)
|
71
|
+
if from.to_date == to.to_date
|
72
|
+
[
|
73
|
+
[AIXM.date(from), (AIXM.time(from)..AIXM.time(to))]
|
74
|
+
]
|
75
|
+
else
|
76
|
+
[
|
77
|
+
[AIXM.date(from), (AIXM.time(from)..AIXM::END_OF_DAY)],
|
78
|
+
[AIXM.date(to), (AIXM::BEGINNING_OF_DAY..AIXM.time(to))]
|
79
|
+
]
|
71
80
|
end
|
72
81
|
end
|
73
82
|
|
83
|
+
def time_for(string, ending: false)
|
84
|
+
hour, min = case string.strip
|
85
|
+
when /(\d{2})(\d{2})/
|
86
|
+
[$1.to_i, $2.to_i]
|
87
|
+
when '', '0'
|
88
|
+
[0, 0]
|
89
|
+
else
|
90
|
+
warn("ignoring malformed time `#{string}'")
|
91
|
+
[0, 0]
|
92
|
+
end
|
93
|
+
hour = 24 if hour.zero? && min.zero? && ending
|
94
|
+
AIPP.options.local_effective_at.change(hour: hour, min: min).utc
|
95
|
+
end
|
96
|
+
|
74
97
|
def geometries_for(polygons)
|
75
98
|
fail "only type MultiPolygon supported" unless polygons[:type] == 'MultiPolygon'
|
76
99
|
fail "polygon coordinates missing" unless polygons[:coordinates]
|
@@ -97,20 +120,30 @@ module AIPP::LS::SHOOT
|
|
97
120
|
|
98
121
|
def timetable_for(schedules)
|
99
122
|
AIXM.timetable.tap do |timetable|
|
100
|
-
schedules.each do |
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
123
|
+
schedules.each do |date, times_array|
|
124
|
+
times_array.each do |times|
|
125
|
+
timetable.add_timesheet(
|
126
|
+
AIXM.timesheet(
|
127
|
+
adjust_to_dst: true,
|
128
|
+
dates: (date..date)
|
129
|
+
# TODO: transform to...
|
130
|
+
# dates: AIXM.date(date)
|
131
|
+
).tap do |timesheet|
|
132
|
+
timesheet.times = times
|
133
|
+
end
|
134
|
+
)
|
135
|
+
end
|
111
136
|
end
|
112
137
|
end
|
113
138
|
end
|
114
139
|
|
140
|
+
# TODO: Consolidate will become obsolete once location code geometries
|
141
|
+
# are available.
|
142
|
+
def consolidate(schedules)
|
143
|
+
schedules
|
144
|
+
.group_by(&:first)
|
145
|
+
.transform_values { _1.map(&:last).consolidate_ranges(:time) }
|
146
|
+
end
|
147
|
+
|
115
148
|
end
|
116
149
|
end
|
@@ -6,7 +6,8 @@ module AIPP
|
|
6
6
|
def options
|
7
7
|
AIPP.options.merge(
|
8
8
|
module: 'Shoot',
|
9
|
-
|
9
|
+
local_effective_at: Time.now.at_midnight,
|
10
|
+
id: nil
|
10
11
|
)
|
11
12
|
end
|
12
13
|
|
@@ -15,12 +16,13 @@ module AIPP
|
|
15
16
|
Download online shooting activities and convert them to #{AIPP.options.schema.upcase}.
|
16
17
|
Usage: #{File.basename($0)} shoot [options]
|
17
18
|
END
|
18
|
-
o.on('-t', '--effective (DATE)', String, %Q[effective on this date (default: "#{AIPP.options.
|
19
|
+
o.on('-t', '--effective (DATE)', String, %Q[effective on this date (default: "#{AIPP.options.local_effective_at.to_date}")]) { AIPP.options.local_effective_at = Time.parse("#{_1} CET") }
|
20
|
+
o.on('-i', '--id ID', String, %Q[process shooting ground with this ID only]) { AIPP.options.id = _1 }
|
19
21
|
end
|
20
22
|
|
21
23
|
def guard
|
22
|
-
AIPP.options.time_zone = AIPP.options.
|
23
|
-
AIPP.options.effective_at = AIPP.options.
|
24
|
+
AIPP.options.time_zone = AIPP.options.local_effective_at.at_noon.strftime('%z')
|
25
|
+
AIPP.options.effective_at = AIPP.options.local_effective_at.at_midnight.utc
|
24
26
|
end
|
25
27
|
|
26
28
|
end
|
data/lib/aipp/version.rb
CHANGED
data/lib/core_ext/array.rb
CHANGED
@@ -10,4 +10,27 @@ class Array
|
|
10
10
|
map(&:to_s).join('::').constantize
|
11
11
|
end
|
12
12
|
|
13
|
+
# Consolidate array of possibly overlapping ranges.
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
# [15..17, 7..11, 12..13, 8..12, 12..13].consolidate_ranges
|
17
|
+
# # => [7..13, 15..17]
|
18
|
+
#
|
19
|
+
# @param [Symbol, nil] method to call on range members for comparison
|
20
|
+
# @return [Array] consolidated array
|
21
|
+
def consolidate_ranges(method=:itself)
|
22
|
+
uniq.sort_by { [_1.begin, _1.end] }.then do |ranges|
|
23
|
+
consolidated, a = [], ranges.first
|
24
|
+
Array(ranges[1..]).each do |b|
|
25
|
+
if a.end.send(method) >= b.begin.send(method) # overlapping
|
26
|
+
a = (a.begin..(a.end.send(method) > b.end.send(method) ? a.end : b.end))
|
27
|
+
else # not overlapping
|
28
|
+
consolidated << a
|
29
|
+
a = b
|
30
|
+
end
|
31
|
+
end
|
32
|
+
consolidated << a
|
33
|
+
end.compact
|
34
|
+
end
|
35
|
+
|
13
36
|
end
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aipp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sven Schwyn
|
@@ -29,7 +29,7 @@ cert_chain:
|
|
29
29
|
kAyiRqgxF4dJviwtqI7mZIomWL63+kXLgjOjMe1SHxfIPo/0ji6+r1p4KYa7o41v
|
30
30
|
fwIwU1MKlFBdsjkd
|
31
31
|
-----END CERTIFICATE-----
|
32
|
-
date: 2023-
|
32
|
+
date: 2023-04-25 00:00:00.000000000 Z
|
33
33
|
dependencies:
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
35
|
name: airac
|
@@ -60,7 +60,7 @@ dependencies:
|
|
60
60
|
version: '1'
|
61
61
|
- - ">="
|
62
62
|
- !ruby/object:Gem::Version
|
63
|
-
version: 1.4.
|
63
|
+
version: 1.4.2
|
64
64
|
type: :runtime
|
65
65
|
prerelease: false
|
66
66
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -70,7 +70,7 @@ dependencies:
|
|
70
70
|
version: '1'
|
71
71
|
- - ">="
|
72
72
|
- !ruby/object:Gem::Version
|
73
|
-
version: 1.4.
|
73
|
+
version: 1.4.2
|
74
74
|
- !ruby/object:Gem::Dependency
|
75
75
|
name: notam
|
76
76
|
requirement: !ruby/object:Gem::Requirement
|
@@ -442,7 +442,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
442
442
|
- !ruby/object:Gem::Version
|
443
443
|
version: '0'
|
444
444
|
requirements: []
|
445
|
-
rubygems_version: 3.4.
|
445
|
+
rubygems_version: 3.4.12
|
446
446
|
signing_key:
|
447
447
|
specification_version: 4
|
448
448
|
summary: Parser for aeronautical information publications
|
metadata.gz.sig
CHANGED
Binary file
|