aixm 0.3.6 → 0.3.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d13df653e543e46983fa5d15d841afae85142eb249e0272ecfa9e440047f8998
4
- data.tar.gz: 988b5d2736771137ba4764b320c886d456576ecdea0c1115d3dde4d9ab33dbb4
3
+ metadata.gz: bad5f1c431575562810faf541c197660e815e3652213dc8d6fedc8cde897f9d4
4
+ data.tar.gz: f1a750f511dc13146af92a25aea066a89a67d358534f2f4a582e415919855ef4
5
5
  SHA512:
6
- metadata.gz: 86b872de155b94fd83a331b7935e4496a8558fdff94e60d64fcceb9973e1ce21acf7f08a52e5955f03352990f0a818b3844fda3ad598e394bcf83aabb7b5dd0e
7
- data.tar.gz: da0e8ab2566abb6530085c632a4e84bc7628ec2aa42cc93566c0b35c2768657f7c42764848b9a0b5149d15617aa25990bb0c5a7a368f39f67cc19f17d702ebc4
6
+ metadata.gz: f587e9d97f7a1fdb21e38f79c2be3567a9a8a8a4c0bc692b74c19305db8b0c2c8fb734d0b90b7ba488916ca9bc23a2a60ba4e836510be6984d1bd95055ffbe28
7
+ data.tar.gz: ac70ee0a8c63f20f0fb0277ba075c0880ed2ad39ae32e6c5e38d9fa76d80943a7c8efb394bb33af52f5c6ce00081d066e59d9df9a1105812bfaf8bafc2a23596
@@ -1 +1 @@
1
- ruby-2.6.3
1
+ ruby-2.6.4
@@ -1,3 +1,9 @@
1
+ ## 0.3.7
2
+
3
+ #### Additions
4
+ * `AIXM::Document#select_features`
5
+ * `AIXM::Document#group_obstacles!`
6
+
1
7
  ## 0.3.6
2
8
 
3
9
  #### Additions
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency 'minitest-reporters'
26
26
  spec.add_development_dependency 'minitest-sound'
27
27
  spec.add_development_dependency 'minitest-matchers'
28
+ spec.add_development_dependency 'minitest-focus'
28
29
  spec.add_development_dependency 'guard'
29
30
  spec.add_development_dependency 'guard-minitest'
30
31
  spec.add_development_dependency 'yard'
@@ -62,6 +62,53 @@ module AIXM
62
62
  @effective_at = value&.to_time || created_at || Time.now
63
63
  end
64
64
 
65
+ # Search features and return those matching the given class and attribute
66
+ # values
67
+ #
68
+ # @example
69
+ # select_features(:airport, id: "LFNT")
70
+ #
71
+ # @param klass [Class, Symbol] feature class like AIXM::Feature::Airport or
72
+ # AIXM::Feature::NavigationalAid::VOR, shorthand notations as symbols
73
+ # e.g. :airport or :vor as listed in AIXM::CLASSES are recognized as well
74
+ # @param attributes [Hash] search attributes by their values
75
+ # @return [Array<AIXM::Feature>]
76
+ def select_features(klass, attributes={})
77
+ if klass.is_a? Symbol
78
+ klass = AIXM::CLASSES.fetch(klass, nil)
79
+ fail(ArgumentError, "unknown feature shortcut") unless klass
80
+ end
81
+ features.select do |feature|
82
+ if feature.is_a? klass
83
+ attributes.reduce(true) do |memo, (attribute, value)|
84
+ memo && feature.send(attribute) == value
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ # Compare all ungrouped obstacles and create new obstacle groups whose
91
+ # members are located within +max_distance+ pairwise.
92
+ #
93
+ # @param max_distance [AIXM::D] max distance between obstacle group member
94
+ # pairs (default: 1 NM)
95
+ # @return [Integer] number of obstacle groups added
96
+ def group_obstacles!(max_distance: AIXM.d(1, :nm))
97
+ obstacles, list = select_features(:obstacle), {}
98
+ while subject = obstacles.shift
99
+ obstacles.each do |obstacle|
100
+ if subject.xy.distance(obstacle.xy) <= max_distance
101
+ [subject, obstacle].each { |o| list[o] = list[subject] || SecureRandom.uuid }
102
+ end
103
+ end
104
+ end
105
+ list.group_by(&:last).each do |_, grouped_list|
106
+ obstacle_group = AIXM.obstacle_group(source: grouped_list.first.first.source)
107
+ grouped_list.each { |o, _| obstacle_group.obstacles << features.delete(o) }
108
+ features << obstacle_group
109
+ end.count
110
+ end
111
+
65
112
  # Validate the generated AIXM or OFMX atainst it's XSD.
66
113
  #
67
114
  # @return [Boolean] whether valid or not
@@ -107,7 +107,8 @@ module AIXM
107
107
 
108
108
  def initialize(source: nil, organisation:, id: nil, name:, xy:)
109
109
  super(source: source)
110
- self.organisation, self.id, self.name, self.xy = organisation, id, name, xy
110
+ self.organisation, self.name, self.xy = organisation, name, xy
111
+ self.id = id # name must already be set
111
112
  @runways, @fatos, @helipads, @usage_limitations, @addresses = [], [], [], [], []
112
113
  end
113
114
 
@@ -1,3 +1,3 @@
1
1
  module AIXM
2
- VERSION = "0.3.6".freeze
2
+ VERSION = "0.3.7".freeze
3
3
  end
@@ -79,6 +79,83 @@ describe AIXM::Document do
79
79
  end
80
80
  end
81
81
 
82
+ describe :select_features do
83
+ subject do
84
+ AIXM::Factory.document
85
+ end
86
+
87
+ it "returns array of features by class" do
88
+ subject.select_features(:airport).map(&:id).must_equal %w(LFNT)
89
+ subject.select_features(AIXM::Feature::Airport).map(&:id).must_equal %w(LFNT)
90
+ end
91
+
92
+ it "returns array of features by class and attributes" do
93
+ subject.select_features(:airport, id: "LFNT").map(&:id).must_equal %w(LFNT)
94
+ subject.select_features(AIXM::Feature::Airport, id: "LFNT").map(&:id).must_equal %w(LFNT)
95
+ end
96
+
97
+ it "returns empty array if nothing matches" do
98
+ subject.select_features(:airport, id: "FAKE").must_equal []
99
+ end
100
+
101
+ it "fails on invalid shortcut" do
102
+ -> { subject.select_features(:fake) }.must_raise ArgumentError
103
+ end
104
+ end
105
+
106
+ describe :group_obstacles! do
107
+ subject do
108
+ AIXM.document.tap do |document|
109
+ {
110
+ 1 => AIXM.xy(lat: 32.665623, long: -111.488584), # 4 north ends:
111
+ 2 => AIXM.xy(lat: 32.665613, long: -111.487701), # 84m distance between each
112
+ 3 => AIXM.xy(lat: 32.665603, long: -111.486796), # 505m distance to south ends
113
+ 4 => AIXM.xy(lat: 32.665611, long: -111.485902),
114
+ 5 => AIXM.xy(lat: 32.661062, long: -111.488624), # 4 south ends:
115
+ 6 => AIXM.xy(lat: 32.661061, long: -111.487731), # 84m distance between each
116
+ 7 => AIXM.xy(lat: 32.661042, long: -111.486814), # 505m distance to north ends
117
+ 8 => AIXM.xy(lat: 32.661054, long: -111.485931),
118
+ 9 => AIXM.xy(lat: 0, long: 0) # far away from the others
119
+ }.to_a.shuffle.each do |index, xy|
120
+ document.features << AIXM.obstacle(
121
+ source: index.to_s,
122
+ name: index.to_s,
123
+ type: :other,
124
+ xy: xy,
125
+ radius: AIXM.d(10, :m),
126
+ z: AIXM.z(1680 , :qnh)
127
+ )
128
+ end
129
+ end
130
+ end
131
+
132
+ it "adds 1 group of obstacles with default max distance" do
133
+ subject.group_obstacles!.must_equal 1
134
+ obstacle_group = subject.select_features(:obstacle_group).first
135
+ obstacle_group.obstacles.count.must_equal 8
136
+ end
137
+
138
+ it "adds 2 groups of obstacles with max distance 400m" do
139
+ subject.group_obstacles!(max_distance: AIXM.d(400, :m)).must_equal 2
140
+ obstacle_groups = subject.features.select { |f| f.is_a? AIXM::Feature::ObstacleGroup }
141
+ obstacle_groups.each do |obstacle_group|
142
+ names = obstacle_group.obstacles.map(&:name).sort
143
+ names.must_equal names.include?('1') ? %w(1 2 3 4) : %w(5 6 7 8)
144
+ end
145
+ end
146
+
147
+ it "leaves ungrouped obstacles untouched" do
148
+ subject.group_obstacles!
149
+ subject.select_features(:obstacle).count.must_equal 1
150
+ end
151
+
152
+ it "copies source of first obstacle to obstacle group" do
153
+ subject.group_obstacles!
154
+ obstacle_group = subject.select_features(:obstacle_group).first
155
+ obstacle_group.source.must_equal obstacle_group.obstacles.first.source
156
+ end
157
+ end
158
+
82
159
  context "AIXM" do
83
160
  subject do
84
161
  AIXM.aixm!
@@ -33,6 +33,7 @@ describe AIXM::Feature::Airport do
33
33
 
34
34
  it "combines 2 character region with an 8 characters digest from name" do
35
35
  subject.tap { |s| s.id = 'lf' }.id.must_equal 'LFD18754F5'
36
+ subject.tap { |s| s.name = 'OTHER'; s.id = 'lf' }.id.must_equal 'LFD646E0F9'
36
37
  end
37
38
 
38
39
  it "upcases valid values" do
@@ -14,6 +14,7 @@ Minitest::Sound.failure = Pathname(__dir__).join('sounds/failure.mp3').to_s
14
14
  require 'minitest/reporters'
15
15
  Minitest::Reporters.use! [Minitest::Reporters::SpecReporter.new, Minitest::Sound::Reporter.new]
16
16
 
17
+ require 'minitest/focus'
17
18
  require 'minitest/matchers'
18
19
  require Pathname(__dir__).join('factory')
19
20
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aixm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.6
4
+ version: 0.3.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sven Schwyn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-22 00:00:00.000000000 Z
11
+ date: 2019-09-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest-focus
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: guard
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -293,7 +307,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
293
307
  - !ruby/object:Gem::Version
294
308
  version: '0'
295
309
  requirements: []
296
- rubygems_version: 3.0.3
310
+ rubygems_version: 3.0.6
297
311
  signing_key:
298
312
  specification_version: 4
299
313
  summary: Aeronautical Information Exchange Model (AIXM 4.5).