aixm 0.3.2 → 0.3.3

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: d3f7a1a1f47a40725a1f7444d97ca6f11acf3c1805d3d2521d9c79c72494abe5
4
- data.tar.gz: a45d00f0667b808e4e44f5a065392c4d0f6a00fbcd7e085c8bab072288fcdf7b
3
+ metadata.gz: a4e0b32c04cba8526128ce56c60abf4343b7ac8f2e8a3e8252e1046ce3ccbfe3
4
+ data.tar.gz: c88875a5a1921f90a1d4055302469c1608ae610bce5b513c9a3e2d50ed32f842
5
5
  SHA512:
6
- metadata.gz: e58d749b2c1face5c6ec67c1e0f23e5fba2ebca6e3d111cc5075ce561c6c7d6b022585f2cdf0ace8e9320f7b1684385f7ab7bb7c1ca80ecf485afb19e7257cba
7
- data.tar.gz: 5888395288986381ed501d7b7a488729e6be98dc65ed1e77c1bb9522022b95cc7d62f13031272edb86c86a3ce41c301917c30e5cce1e88756d88688b8ca2bd87
6
+ metadata.gz: e0f11994c12259bee9a013b92162ed14f763206855adfb5f0d25fc45807a885da5b330010c1c7768590cd3cca19c260976c68674b0354091b2ef64288a70914e
7
+ data.tar.gz: 800ef3ea1d7e298281454957f3471e06452d9a23a4333c0f978c24590cd9fc140b21948d7588a07a896995731897810bffc317ae610e39822b6e27e51554cb10
data/.travis.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
2
  language: ruby
3
3
  rvm:
4
- - 2.5.0
5
- before_install: gem install bundler -v 1.16.1
4
+ - 2.5.3
5
+ before_install: gem install bundler -v 1.17.1
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 0.3.3
2
+
3
+ #### Additions
4
+ * `AIXM::H` (heading)
5
+
6
+ #### Changes
7
+ * Updated OFMX schema URI
8
+ * Added `eql?` and `hash` to `AIXM::XY|Z|D|H|F` to allow for instances of these classes to be used as Hash keys.
9
+
1
10
  ## 0.3.2
2
11
 
3
12
  #### Additions
@@ -106,9 +106,11 @@ module AIXM
106
106
 
107
107
  # @return [String]
108
108
  def inspect
109
- %Q(#<#{self.class} class=#{@klass.inspect}>)
109
+ %Q(#<#{original_class} class=#{@klass.inspect}>)
110
110
  end
111
111
 
112
+ alias_method :original_class, :class
113
+
112
114
  # @!attribute class
113
115
  # @return [Symbol] class of layer (see {CLASSES})
114
116
  def class
@@ -21,7 +21,7 @@ module AIXM
21
21
  # runway.composition = COMPOSITIONS or nil
22
22
  # runway.status = STATUSES or nil
23
23
  # runway.remarks = String or nil
24
- # runway.forth.name = String # preset based on the runway name
24
+ # runway.forth.name = AIXM.h # preset based on the runway name
25
25
  # runway.forth.geographic_orientation = Integer or nil # degrees
26
26
  # runway.forth.xy = AIXM.xy
27
27
  # runway.forth.z = AIXM.z or nil
@@ -31,15 +31,15 @@ module AIXM
31
31
  # @example Bidirectional runway
32
32
  # runway = AIXM.runway(name: '16L/34R')
33
33
  # runway.name # => '16L/34R'
34
- # runway.forth.name = '16L'
34
+ # runway.forth.name.to_s = '16L'
35
35
  # runway.forth.geographic_orientation = 165
36
- # runway.back.name = '34R'
36
+ # runway.back.name.to_s = '34R'
37
37
  # runway.back.geographic_orientation = 345
38
38
  #
39
39
  # @example Unidirectional runway:
40
40
  # runway = AIXM.runway(name: '16L')
41
41
  # runway.name # => '16L'
42
- # runway.forth.name = '16L'
42
+ # runway.forth.name.to_s = '16L'
43
43
  # runway.forth.geographic_orientation = 165
44
44
  # runway.back = nil
45
45
  #
@@ -97,8 +97,9 @@ module AIXM
97
97
  def initialize(name:)
98
98
  self.name = name
99
99
  @name.split('/').tap do |forth, back|
100
- @forth = Direction.new(runway: self, name: forth)
101
- @back = Direction.new(runway: self, name: back) if back
100
+ @forth = Direction.new(runway: self, name: AIXM.h(forth))
101
+ @back = Direction.new(runway: self, name: AIXM.h(back)) if back
102
+ fail(ArgumentError, "invalid name") unless !@back || @back.name.inverse_of?(@forth.name)
102
103
  end
103
104
  end
104
105
 
@@ -183,7 +184,7 @@ module AIXM
183
184
  # @return [AIXM::Component::Runway] runway the runway direction is further describing
184
185
  attr_reader :runway
185
186
 
186
- # @return [String] partial name of runway (e.g. "12" or "16L")
187
+ # @return [AIXM::H] partial name of runway (e.g. "12" or "16L")
187
188
  attr_reader :name
188
189
 
189
190
  # @return [Integer, nil] geographic orientation (true bearing) in degrees
@@ -219,15 +220,15 @@ module AIXM
219
220
  private :runway
220
221
 
221
222
  def name=(value)
222
- fail(ArgumentError, "invalid name") unless value.is_a? String
223
- @name = value.uptrans
223
+ fail(ArgumentError, "invalid name") unless value.is_a? AIXM::H
224
+ @name = value
224
225
  end
225
226
 
226
227
  def geographic_orientation=(value)
227
228
  return @geographic_orientation = nil if value.nil?
228
229
  fail(ArgumentError, "invalid geographic orientation") unless value.is_a? Numeric
229
230
  @geographic_orientation = value.to_i
230
- fail(ArgumentError, "invalid geographic orientation") unless (0..359).include? @geographic_orientation
231
+ fail(ArgumentError, "invalid geographic orientation") unless (1..360).include? @geographic_orientation
231
232
  end
232
233
 
233
234
  def xy=(value)
data/lib/aixm/config.rb CHANGED
@@ -9,7 +9,7 @@ module AIXM
9
9
  },
10
10
  ofmx: {
11
11
  version: '0',
12
- namespace: 'http://openflightmaps.org/schema/0/OFMX-Snapshot.xsd',
12
+ namespace: 'http://schema.openflightmaps.org/0/OFMX-Snapshot.xsd',
13
13
  xsd: Pathname(__dir__).join('..', '..', 'schemas', 'ofmx', '0', 'OFMX-Snapshot.xsd'),
14
14
  root: 'OFMX-Snapshot'
15
15
  }
data/lib/aixm/d.rb CHANGED
@@ -47,10 +47,6 @@ module AIXM
47
47
  fail(ArgumentError, "invalid unit") unless UNITS.has_key? @unit
48
48
  end
49
49
 
50
- def <=>(other)
51
- to_m.dist <=> other.to_m.dist
52
- end
53
-
54
50
  # @!method to_ft
55
51
  # @!method to_km
56
52
  # @!method to_m
@@ -62,5 +58,24 @@ module AIXM
62
58
  self.class.new((dist * UNITS[unit][target_unit]).round(8), target_unit)
63
59
  end
64
60
  end
61
+
62
+ # @see Object#<=>
63
+ # @return [Integer]
64
+ def <=>(other)
65
+ to_m.dist <=> other.to_m.dist
66
+ end
67
+
68
+ # @see Object#==
69
+ # @return [Boolean]
70
+ def ==(other)
71
+ self.class === other && (self <=> other).zero?
72
+ end
73
+ alias_method :eql?, :==
74
+
75
+ # @see Object#hash
76
+ # @return [Integer]
77
+ def hash
78
+ to_s.hash
79
+ end
65
80
  end
66
81
  end
data/lib/aixm/f.rb CHANGED
@@ -40,14 +40,22 @@ module AIXM
40
40
  fail(ArgumentError, "invalid unit") unless UNITS.include? @unit
41
41
  end
42
42
 
43
+ # @return [Boolean] whether this frequency is part of a frequency band
44
+ def between?(lower_freq, upper_freq, unit)
45
+ freq.between?(lower_freq, upper_freq) && self.unit == unit
46
+ end
47
+
48
+ # @see Object#==
43
49
  # @return [Boolean]
44
50
  def ==(other)
45
- other.is_a?(self.class) && freq == other.freq && unit == other.unit
51
+ self.class === other && freq == other.freq && unit == other.unit
46
52
  end
53
+ alias_method :eql?, :==
47
54
 
48
- # @return [Boolean] whether this frequency is part of a frequency band
49
- def between?(lower_freq, upper_freq, unit)
50
- freq.between?(lower_freq, upper_freq) && self.unit == unit
55
+ # @see Object#hash
56
+ # @return [Integer]
57
+ def hash
58
+ to_s.hash
51
59
  end
52
60
 
53
61
  end
data/lib/aixm/feature.rb CHANGED
@@ -19,7 +19,7 @@ module AIXM
19
19
 
20
20
  # @return [Boolean]
21
21
  def ==(other)
22
- other.is_a?(self.class) && self.to_uid == other.to_uid
22
+ self.class === other && self.to_uid == other.to_uid
23
23
  end
24
24
  end
25
25
 
data/lib/aixm/h.rb ADDED
@@ -0,0 +1,87 @@
1
+ using AIXM::Refinements
2
+
3
+ module AIXM
4
+
5
+ # Heading of an aircraft or runway
6
+ #
7
+ # @example
8
+ # AIXM.h(12)
9
+ # AIXM.h('12')
10
+ # AIXM.h('34L')
11
+ # AIXM.h('05X')
12
+ class H
13
+ SUFFIX_INVERSIONS = {
14
+ R: :L,
15
+ L: :R
16
+ }.freeze
17
+
18
+ # @return [Integer] heading
19
+ attr_reader :deg
20
+
21
+ # @return [Symbol, nil] suffix
22
+ attr_reader :suffix
23
+
24
+ def initialize(deg_and_suffix)
25
+ fail(ArgumentError, "invalid heading") unless deg_and_suffix.to_s =~ /\A(\d+)([A-Z]+)?\z/
26
+ self.deg, self.suffix = $1.to_i, $2
27
+ end
28
+
29
+ # @return [String]
30
+ def inspect
31
+ %Q(#<#{self.class} #{to_s}>)
32
+ end
33
+
34
+ # @return [String] human readable representation (e.g. "05" or "34L")
35
+ def to_s
36
+ [('%02d' % deg), suffix].map(&:to_s).join
37
+ end
38
+
39
+ def deg=(value)
40
+ fail(ArgumentError, "invalid deg") unless value.between?(1, 36)
41
+ @deg = value
42
+ end
43
+
44
+ def suffix=(value)
45
+ fail(ArgumentError, "invalid suffix") unless value.nil? || value.to_s =~ /\A[A-Z]+\z/
46
+ @suffix = value&.to_s&.to_sym
47
+ end
48
+
49
+ # Invert a heading by 180 degrees
50
+ #
51
+ # @example
52
+ # AIXM.h('12').invert # => AIXM.h(30)
53
+ # AIXM.h('34L').invert # => AIXM.h(16, 'R')
54
+ # AIXM.h('33X').invert # => AIXM.h(17, 'bravo')
55
+ #
56
+ # @return [AIXM::H] inverted heading
57
+ def invert
58
+ AIXM.h([(((deg + 17) % 36) + 1), SUFFIX_INVERSIONS.fetch(suffix, suffix)].join)
59
+ end
60
+
61
+ # Check whether +other+ heading is the inverse
62
+ #
63
+ # @example
64
+ # AIXM.h('12').inverse_of? AIXM.h('30') # => true
65
+ # AIXM.h('34L').inverse_of? AIXM.h('16R') # => true
66
+ # AIXM.h('16R').inverse_of? AIXM.h('16L') # => false
67
+ #
68
+ # @return [AIXM::H] inverted heading
69
+ def inverse_of?(other)
70
+ invert == other
71
+ end
72
+
73
+ # @see Object#==
74
+ # @return [Boolean]
75
+ def ==(other)
76
+ self.class === other && deg == other.deg && suffix == other.suffix
77
+ end
78
+ alias_method :eql?, :==
79
+
80
+ # @see Object#hash
81
+ # @return [Integer]
82
+ def hash
83
+ to_s.hash
84
+ end
85
+ end
86
+
87
+ end
@@ -33,7 +33,7 @@ module AIXM
33
33
  #
34
34
  # @example
35
35
  # ['foo', :bar, nil, [123]].to_uuid
36
- # # => "f3920098"
36
+ # # => "a68e9aae-81ef-c6f1-d954-2eefe2820c50"
37
37
  #
38
38
  # @note This is a refinement for +Array+
39
39
  # @return [String] UUID version 3
@@ -6,6 +6,7 @@ module AIXM
6
6
  z: Z,
7
7
  d: D,
8
8
  f: F,
9
+ h: H,
9
10
  organisation: Feature::Organisation,
10
11
  unit: Feature::Unit,
11
12
  service: Component::Service,
data/lib/aixm/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module AIXM
2
- VERSION = "0.3.2".freeze
2
+ VERSION = "0.3.3".freeze
3
3
  end
data/lib/aixm/xy.rb CHANGED
@@ -6,12 +6,13 @@ module AIXM
6
6
  #
7
7
  # ===Recognized notations:
8
8
  # * DD - examples: 12.12345678 (north or east), -12.12345678 (south or west)
9
- # * DMS - examples: 11°22'33.44"N, 1112233.44W
9
+ # * DMS - examples: 11°22'33.44"N, 1112233.44W,
10
10
  #
11
11
  # @example All of the below are equivalent
12
+ # AIXM.xy(lat: 11.375955555555556, long: -111.37595555555555)
12
13
  # AIXM.xy(lat: %q(11°22'33.44"), long: %q(-111°22'33.44"))
14
+ # AIXM.xy(lat: %q(11°22'33.44N"), long: %q(111°22'33.44W"))
13
15
  # AIXM.xy(lat: '112233.44N', long: '1112233.44W')
14
- # AIXM.xy(lat: 11.375955555555556, long: -111.37595555555555)
15
16
  #
16
17
  # @see https://github.com/openflightmaps/ofmx/wiki/Coordinates
17
18
  class XY
@@ -63,11 +64,6 @@ module AIXM
63
64
  end
64
65
  end
65
66
 
66
- # @return [Boolean]
67
- def ==(other)
68
- other.is_a?(self.class) && lat == other.lat && long == other.long
69
- end
70
-
71
67
  # @return [AIXM::D] distance as calculated by use of the Haversine formula
72
68
  def distance(other)
73
69
  if self == other
@@ -84,6 +80,19 @@ module AIXM
84
80
  end
85
81
  end
86
82
 
83
+ # @see Object#==
84
+ # @return [Boolean]
85
+ def ==(other)
86
+ self.class === other && lat == other.lat && long == other.long
87
+ end
88
+ alias_method :eql?, :==
89
+
90
+ # @see Object#hash
91
+ # @return [Integer]
92
+ def hash
93
+ to_s.hash
94
+ end
95
+
87
96
  private
88
97
 
89
98
  def float_for(value)
data/lib/aixm/z.rb CHANGED
@@ -46,11 +46,6 @@ module AIXM
46
46
  fail(ArgumentError, "invalid code") unless CODES.include? @code
47
47
  end
48
48
 
49
- # @return [Boolean]
50
- def ==(other)
51
- other.is_a?(self.class) && alt == other.alt && code == other.code
52
- end
53
-
54
49
  # @example
55
50
  # z = AIXM.z(123, :qnh)
56
51
  # z.qnh? # => true
@@ -74,6 +69,19 @@ module AIXM
74
69
  qne? ? :fl : :ft
75
70
  end
76
71
 
72
+ # @see Object#==
73
+ # @return [Boolean]
74
+ def ==(other)
75
+ self.class === other && alt == other.alt && code == other.code
76
+ end
77
+ alias_method :eql?, :==
78
+
79
+ # @see Object#hash
80
+ # @return [Integer]
81
+ def hash
82
+ to_s.hash
83
+ end
84
+
77
85
  end
78
86
 
79
87
  end
data/lib/aixm.rb CHANGED
@@ -16,6 +16,7 @@ require_relative 'aixm/xy'
16
16
  require_relative 'aixm/z'
17
17
  require_relative 'aixm/d'
18
18
  require_relative 'aixm/f'
19
+ require_relative 'aixm/h'
19
20
 
20
21
  require_relative 'aixm/component'
21
22
  require_relative 'aixm/component/service'
data/spec/factory.rb CHANGED
@@ -20,6 +20,10 @@ module AIXM
20
20
  AIXM.f(123.35, :mhz)
21
21
  end
22
22
 
23
+ def h
24
+ AIXM.h('34L')
25
+ end
26
+
23
27
  # Components
24
28
 
25
29
  def timetable
@@ -7,15 +7,19 @@ describe AIXM::Component::Runway do
7
7
 
8
8
  describe :initialize do
9
9
  it "sets defaults for bidirectional runways" do
10
- subject.forth.name.must_equal '16L'
11
- subject.back.name.must_equal '34R'
10
+ subject.forth.name.must_equal AIXM.h('16L')
11
+ subject.back.name.must_equal AIXM.h('34R')
12
12
  end
13
13
 
14
14
  it "sets defaults for unidirectional runways" do
15
15
  subject = AIXM::Component::Runway.new(name: '30')
16
- subject.forth.name.must_equal '30'
16
+ subject.forth.name.must_equal AIXM.h('30')
17
17
  subject.back.must_be_nil
18
18
  end
19
+
20
+ it "fails on non-inverse bidirectional runways" do
21
+ -> { AIXM.runway(name: '16L/14R') }.must_raise ArgumentError
22
+ end
19
23
  end
20
24
 
21
25
  describe :name= do
@@ -267,16 +271,20 @@ describe AIXM::Component::Runway::Direction do
267
271
  end
268
272
 
269
273
  describe :name= do
274
+ it "fails on invalid values" do
275
+ [nil, :foobar, '16R'].wont_be_written_to subject, :name
276
+ end
277
+
270
278
  it "overwrites preset name" do
271
- subject.name.must_equal '16L'
272
- subject.name = 'x01x'
273
- subject.name.must_equal 'X01X'
279
+ subject.name.to_s.must_equal '16L'
280
+ subject.name = AIXM.h('34L')
281
+ subject.name.to_s.must_equal '34L'
274
282
  end
275
283
  end
276
284
 
277
285
  describe :geographic_orientation= do
278
286
  it "fails on invalid values" do
279
- [:foobar, -1, 360].wont_be_written_to subject, :geographic_orientation
287
+ [:foobar, -1, 0, 361].wont_be_written_to subject, :geographic_orientation
280
288
  end
281
289
 
282
290
  it "converts valid Numeric values to integer" do
@@ -25,32 +25,6 @@ describe AIXM::D do
25
25
  end
26
26
  end
27
27
 
28
- describe :<=> do
29
- it "recognizes objects with identical unit and distance as equal" do
30
- a = AIXM.d(123, :m)
31
- b = AIXM.d(123.0, 'M')
32
- a.must_equal b
33
- end
34
-
35
- it "recognizes objects with different units and converted distance as equal" do
36
- a = AIXM.d(123, :m)
37
- b = AIXM.d(403.54330709, 'FT')
38
- a.must_equal b
39
- end
40
-
41
- it "recognizes objects with different units and identical distance as unequal" do
42
- a = AIXM.d(123, :m)
43
- b = AIXM.d(123, :ft)
44
- a.wont_equal b
45
- end
46
-
47
- it "recognizes objects of different class as unequal" do
48
- a = AIXM.d(123, :m)
49
- b = :oggy
50
- a.wont_equal b
51
- end
52
- end
53
-
54
28
  describe :to_ft do
55
29
  it "leaves feet untouched" do
56
30
  subject = AIXM.d(2, :ft)
@@ -127,4 +101,40 @@ describe AIXM::D do
127
101
  end
128
102
  end
129
103
 
104
+ describe :<=> do
105
+ it "recognizes objects with identical unit and distance as equal" do
106
+ a = AIXM.d(123, :m)
107
+ b = AIXM.d(123.0, 'M')
108
+ a.must_equal b
109
+ end
110
+
111
+ it "recognizes objects with different units and converted distance as equal" do
112
+ a = AIXM.d(123, :m)
113
+ b = AIXM.d(403.54330709, 'FT')
114
+ a.must_equal b
115
+ end
116
+
117
+ it "recognizes objects with different units and identical distance as unequal" do
118
+ a = AIXM.d(123, :m)
119
+ b = AIXM.d(123, :ft)
120
+ a.wont_equal b
121
+ end
122
+
123
+ it "recognizes objects of different class as unequal" do
124
+ a = AIXM.d(123, :m)
125
+ b = :oggy
126
+ a.wont_equal b
127
+ end
128
+ end
129
+
130
+ describe :hash do
131
+ it "returns an integer" do
132
+ subject.hash.must_be_instance_of Integer
133
+ end
134
+
135
+ it "allows for the use of instances as hash keys" do
136
+ dupe = subject.dup
137
+ { subject => true }[dupe].must_equal true
138
+ end
139
+ end
130
140
  end
@@ -727,7 +727,7 @@ describe AIXM::Document do
727
727
  it "builds correct OFMX" do
728
728
  subject.to_xml.must_equal <<~"END"
729
729
  <?xml version="1.0" encoding="UTF-8"?>
730
- <OFMX-Snapshot xmlns:xsi="http://openflightmaps.org/schema/0/OFMX-Snapshot.xsd" version="0" origin="rubygem aixm-#{AIXM::VERSION}" region="LF" namespace="00000000-0000-0000-0000-000000000000" created="2018-01-01T12:00:00+01:00" effective="2018-01-01T12:00:00+01:00">
730
+ <OFMX-Snapshot xmlns:xsi="http://schema.openflightmaps.org/0/OFMX-Snapshot.xsd" version="0" origin="rubygem aixm-#{AIXM::VERSION}" region="LF" namespace="00000000-0000-0000-0000-000000000000" created="2018-01-01T12:00:00+01:00" effective="2018-01-01T12:00:00+01:00">
731
731
  <!-- Organisation: FRANCE -->
732
732
  <Org source="LF|GEN|0.0 FACTORY|0|0">
733
733
  <OrgUid>
@@ -25,6 +25,23 @@ describe AIXM::F do
25
25
  end
26
26
  end
27
27
 
28
+ describe :between? do
29
+ subject do
30
+ AIXM.f(100, :mhz)
31
+ end
32
+
33
+ it "detect frequencies within a frequency band" do
34
+ subject.between?(90, 110, :mhz).must_equal true
35
+ subject.between?(90, 100, :mhz).must_equal true
36
+ subject.between?(100.0, 100.1, :mhz).must_equal true
37
+ end
38
+
39
+ it "detect frequencies outside of a frequency band" do
40
+ subject.between?(90, 110, :khz).must_equal false
41
+ subject.between?(90, 95, :mhz).must_equal false
42
+ end
43
+ end
44
+
28
45
  describe :== do
29
46
  it "recognizes objects with identical frequency and unit as equal" do
30
47
  a = AIXM.f(123.0, :mhz)
@@ -45,21 +62,14 @@ describe AIXM::F do
45
62
  end
46
63
  end
47
64
 
48
- describe :between? do
49
- subject do
50
- AIXM.f(100, :mhz)
65
+ describe :hash do
66
+ it "returns an integer" do
67
+ subject.hash.must_be_instance_of Integer
51
68
  end
52
69
 
53
- it "detect frequencies within a frequency band" do
54
- subject.between?(90, 110, :mhz).must_equal true
55
- subject.between?(90, 100, :mhz).must_equal true
56
- subject.between?(100.0, 100.1, :mhz).must_equal true
57
- end
58
-
59
- it "detect frequencies outside of a frequency band" do
60
- subject.between?(90, 110, :khz).must_equal false
61
- subject.between?(90, 95, :mhz).must_equal false
70
+ it "allows for the use of instances as hash keys" do
71
+ dupe = subject.dup
72
+ { subject => true }[dupe].must_equal true
62
73
  end
63
74
  end
64
-
65
75
  end
@@ -0,0 +1,113 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe AIXM::H do
4
+ subject do
5
+ AIXM::Factory.h
6
+ end
7
+
8
+ describe :initialize do
9
+ it "fails on invalid values" do
10
+ -> { AIXM.h('foobar') }.must_raise ArgumentError
11
+ end
12
+
13
+ it "parses valid values" do
14
+ AIXM.h('34L').tap do |h|
15
+ h.deg.must_equal 34
16
+ h.suffix.must_equal :L
17
+ end
18
+ AIXM.h(12).tap do |h|
19
+ h.deg.must_equal 12
20
+ h.suffix.must_be :nil?
21
+ end
22
+ end
23
+ end
24
+
25
+ describe :to_s do
26
+ it "pads deg with zero and concats suffix" do
27
+ AIXM.h(5).to_s.must_equal '05'
28
+ AIXM.h('5L').to_s.must_equal '05L'
29
+ AIXM.h('16L').to_s.must_equal '16L'
30
+ end
31
+ end
32
+
33
+ describe :deg= do
34
+ it "fails on invalid values" do
35
+ [:foobar, '1', 0, 37].wont_be_written_to subject, :deg
36
+ end
37
+
38
+ it "accepts valid values" do
39
+ (1..36).to_a.must_be_written_to subject, :deg
40
+ end
41
+ end
42
+
43
+ describe :suffix= do
44
+ it "fails on invalid values" do
45
+ [123, 'r'].wont_be_written_to subject, :suffix
46
+ end
47
+
48
+ it "accepts nil value" do
49
+ [nil].must_be_written_to subject, :suffix
50
+ end
51
+
52
+ it "symbolizes valid values" do
53
+ subject.tap { |s| s.suffix = 'Z' }.suffix.must_equal :Z
54
+ end
55
+ end
56
+
57
+ describe :invert do
58
+ it "must calculate inverse deg correctly" do
59
+ {
60
+ 1 => 19, 2 => 20, 3 => 21, 4 => 22, 5 => 23, 6 => 24, 7 => 25, 8 => 26, 9 => 27,
61
+ 10 => 28, 11 => 29, 12 => 30, 13 => 31, 14 => 32, 15 => 33, 16 => 34, 17 => 35, 18 => 36,
62
+ 19 => 1, 20 => 2, 21 => 3, 22 => 4, 23 => 5, 24 => 6, 25 => 7, 26 => 8, 27 => 9,
63
+ 28 => 10, 29 => 11, 30 => 12, 31 => 13, 32 => 14, 33 => 15, 34 => 16, 35 => 17, 36 => 18
64
+ }.each do |from, to|
65
+ AIXM.h(from).invert.deg.must_equal to
66
+ end
67
+ end
68
+
69
+ it "must invert left/right suffix" do
70
+ AIXM.h('34L').invert.suffix.must_equal :R
71
+ end
72
+
73
+ it "must leave other suffixes untouched" do
74
+ AIXM.h('35X').invert.suffix.must_equal :X
75
+ end
76
+ end
77
+
78
+ describe :inverse_of? do
79
+ it "must return true for inverse pairs" do
80
+ AIXM.h('34L').inverse_of?(AIXM.h('16R')).must_equal true
81
+ end
82
+
83
+ it "must return false for non-inverse pairs" do
84
+ AIXM.h('34L').inverse_of?(AIXM.h('12L')).must_equal false
85
+ end
86
+ end
87
+
88
+ describe :== do
89
+ it "recognizes objects with identical deg and suffix as equal" do
90
+ AIXM.h('34L').must_equal AIXM.h('34L')
91
+ end
92
+
93
+ it "recognizes objects with different deg or suffix as unequal" do
94
+ AIXM.h('34L').wont_equal AIXM.h('35L')
95
+ AIXM.h('34L').wont_equal AIXM.h('34R')
96
+ end
97
+
98
+ it "recognizes objects of different class as unequal" do
99
+ subject.wont_equal :oggy
100
+ end
101
+ end
102
+
103
+ describe :hash do
104
+ it "returns an integer" do
105
+ subject.hash.must_be_instance_of Integer
106
+ end
107
+
108
+ it "allows for the use of instances as hash keys" do
109
+ dupe = subject.dup
110
+ { subject => true }[dupe].must_equal true
111
+ end
112
+ end
113
+ end
@@ -111,6 +111,21 @@ describe AIXM::XY do
111
111
  end
112
112
  end
113
113
 
114
+ describe :distance do
115
+ subject do
116
+ AIXM.xy(lat: %q(44°00'07.63"N), long: %q(004°45'07.81"E))
117
+ end
118
+
119
+ it "calculates the distance between the same point as zero" do
120
+ subject.distance(subject).must_equal AIXM.d(0, :m)
121
+ end
122
+
123
+ it "calculates the distance between two points correctly" do
124
+ other = AIXM.xy(lat: %q(43°59'25.31"N), long: %q(004°45'23.24"E))
125
+ subject.distance(other).must_equal AIXM.d(1351, :m)
126
+ end
127
+ end
128
+
114
129
  describe :== do
115
130
  it "recognizes objects with identical latitude and longitude as equal" do
116
131
  a = AIXM.xy(lat: "112233N", long: "0223344E")
@@ -131,18 +146,14 @@ describe AIXM::XY do
131
146
  end
132
147
  end
133
148
 
134
- describe :distance do
135
- subject do
136
- AIXM.xy(lat: %q(44°00'07.63"N), long: %q(004°45'07.81"E))
137
- end
138
-
139
- it "calculates the distance between the same point as zero" do
140
- subject.distance(subject).must_equal AIXM.d(0, :m)
149
+ describe :hash do
150
+ it "returns an integer" do
151
+ subject.hash.must_be_instance_of Integer
141
152
  end
142
153
 
143
- it "calculates the distance between two points correctly" do
144
- other = AIXM.xy(lat: %q(43°59'25.31"N), long: %q(004°45'23.24"E))
145
- subject.distance(other).must_equal AIXM.d(1351, :m)
154
+ it "allows for the use of instances as hash keys" do
155
+ dupe = subject.dup
156
+ { subject => true }[dupe].must_equal true
146
157
  end
147
158
  end
148
159
  end
@@ -25,26 +25,6 @@ describe AIXM::Z do
25
25
  end
26
26
  end
27
27
 
28
- describe :== do
29
- it "recognizes objects with identical altitude and Q code as equal" do
30
- a = AIXM.z(111, :qnh)
31
- b = AIXM.z(111, :qnh)
32
- a.must_equal b
33
- end
34
-
35
- it "recognizes objects with different altitude or Q code as unequal" do
36
- a = AIXM.z(111, :qnh)
37
- b = AIXM.z(222, :qnh)
38
- a.wont_equal b
39
- end
40
-
41
- it "recognizes objects of different class as unequal" do
42
- a = AIXM.z(111, :qnh)
43
- b = :oggy
44
- a.wont_equal b
45
- end
46
- end
47
-
48
28
  describe :qfe? do
49
29
  it "recognizes same Q code" do
50
30
  AIXM.z(111, :qfe).must_be :qfe?
@@ -70,4 +50,35 @@ describe AIXM::Z do
70
50
  AIXM.z(0, :qne).unit.must_equal :fl
71
51
  end
72
52
  end
53
+
54
+ describe :== do
55
+ it "recognizes objects with identical altitude and Q code as equal" do
56
+ a = AIXM.z(111, :qnh)
57
+ b = AIXM.z(111, :qnh)
58
+ a.must_equal b
59
+ end
60
+
61
+ it "recognizes objects with different altitude or Q code as unequal" do
62
+ a = AIXM.z(111, :qnh)
63
+ b = AIXM.z(222, :qnh)
64
+ a.wont_equal b
65
+ end
66
+
67
+ it "recognizes objects of different class as unequal" do
68
+ a = AIXM.z(111, :qnh)
69
+ b = :oggy
70
+ a.wont_equal b
71
+ end
72
+ end
73
+
74
+ describe :hash do
75
+ it "returns an integer" do
76
+ subject.hash.must_be_instance_of Integer
77
+ end
78
+
79
+ it "allows for the use of instances as hash keys" do
80
+ dupe = subject.dup
81
+ { subject => true }[dupe].must_equal true
82
+ end
83
+ end
73
84
  end
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.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sven Schwyn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-30 00:00:00.000000000 Z
11
+ date: 2018-11-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -201,6 +201,7 @@ files:
201
201
  - lib/aixm/feature/obstacle_group.rb
202
202
  - lib/aixm/feature/organisation.rb
203
203
  - lib/aixm/feature/unit.rb
204
+ - lib/aixm/h.rb
204
205
  - lib/aixm/refinements.rb
205
206
  - lib/aixm/shortcuts.rb
206
207
  - lib/aixm/version.rb
@@ -246,6 +247,7 @@ files:
246
247
  - spec/lib/aixm/feature/organisation_spec.rb
247
248
  - spec/lib/aixm/feature/unit_spec.rb
248
249
  - spec/lib/aixm/feature_spec.rb
250
+ - spec/lib/aixm/h_spec.rb
249
251
  - spec/lib/aixm/refinements_spec.rb
250
252
  - spec/lib/aixm/version_spec.rb
251
253
  - spec/lib/aixm/xy_spec.rb
@@ -315,6 +317,7 @@ test_files:
315
317
  - spec/lib/aixm/feature/organisation_spec.rb
316
318
  - spec/lib/aixm/feature/unit_spec.rb
317
319
  - spec/lib/aixm/feature_spec.rb
320
+ - spec/lib/aixm/h_spec.rb
318
321
  - spec/lib/aixm/refinements_spec.rb
319
322
  - spec/lib/aixm/version_spec.rb
320
323
  - spec/lib/aixm/xy_spec.rb