aipp 2.1.1 → 2.1.2
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 +2 -3
- data/CHANGELOG.md +7 -0
- data/lib/aipp/regions/LS/README.md +8 -0
- data/lib/aipp/regions/LS/helpers/base.rb +5 -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: cb4a7ae75e5b180c62d60b63a28ef1e28de3d23e0fe008defc4cc7bc0cf61f14
|
4
|
+
data.tar.gz: 6705dbfab25adfb9c71b1781c8ded9106ab1adc6906ec67f3c1330beb73de3e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f394783a21b6aaac134155d06c1e3f5c082dcfdd835d0cb3abf708bc1a417fcc2a4bebf382fa1cc70b82c8fe8fa440cacb6a2f73eb73a1efbd0d3b72c437d5e4
|
7
|
+
data.tar.gz: 6c9d845076a9c2f894c2d4e586f66a32616d1a1903beb54423844b26d12e930bf85089b72494abe51a47c2701450044ef35508b0221c994d9ed512e3a821b6be
|
checksums.yaml.gz.sig
CHANGED
@@ -1,3 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
r�}��Q==J����ÑeF��0*L2��!���?���r�L�������
|
1
|
+
M{��T��8(��3;p=[PR��oS�WoE���ʦ�q�3���U~���
|
2
|
+
\�ܚ)��o�>�g���
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,13 @@
|
|
2
2
|
|
3
3
|
Nothing so far
|
4
4
|
|
5
|
+
## 2.1.2
|
6
|
+
|
7
|
+
#### Changes
|
8
|
+
* Improve timesheet calculation for shooting grounds in LS
|
9
|
+
* Improve safety margins for shooting grounds in LS
|
10
|
+
* Switch to unzipped OFMX for now due to issues upstream
|
11
|
+
|
5
12
|
## 2.1.1
|
6
13
|
|
7
14
|
#### Additions
|
@@ -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,9 +48,12 @@ 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://storage.googleapis.com/snapshots.openflightmaps.org/live/#{AIRAC::Cycle.new.id}/ofmx/lsas/latest/isolated/ofmx_ls.xml"
|
53
52
|
)
|
53
|
+
# AIPP::Downloader::HTTP.new(
|
54
|
+
# archive: "https://snapshots.openflightmaps.org/live/#{AIRAC::Cycle.new.id}/ofmx/lsas/latest/ofmx_ls.zip",
|
55
|
+
# file: "ofmx_ls/isolated/ofmx_ls.ofmx"
|
56
|
+
# )
|
54
57
|
when 'DABS'
|
55
58
|
if aixm.effective_at.to_date == Date.today # DABS cross check works reliably for today only
|
56
59
|
AIPP::Downloader::HTTP.new(
|
@@ -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.2
|
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-03-23 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.9
|
446
446
|
signing_key:
|
447
447
|
specification_version: 4
|
448
448
|
summary: Parser for aeronautical information publications
|
metadata.gz.sig
CHANGED
Binary file
|