auom 0.2.0 → 0.3.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.
Files changed (52) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +18 -0
  3. data/.rubocop.yml +1 -1
  4. data/Changelog.md +5 -0
  5. data/Gemfile +2 -0
  6. data/Rakefile +2 -0
  7. data/auom.gemspec +6 -4
  8. data/config/devtools.yml +2 -0
  9. data/config/flay.yml +1 -1
  10. data/config/reek.yml +96 -97
  11. data/config/rubocop.yml +3 -0
  12. data/lib/auom.rb +2 -1
  13. data/lib/auom/algebra.rb +2 -0
  14. data/lib/auom/equalization.rb +2 -2
  15. data/lib/auom/inspection.rb +15 -10
  16. data/lib/auom/relational.rb +6 -76
  17. data/lib/auom/unit.rb +6 -8
  18. data/spec/shared/incompatible_operation_behavior.rb +2 -0
  19. data/spec/shared/operation_behavior.rb +3 -0
  20. data/spec/shared/sunits_shared.rb +2 -0
  21. data/spec/spec_helper.rb +2 -0
  22. data/spec/unit/auom/algebra_spec.rb +279 -0
  23. data/spec/unit/auom/{equalization/equality_operator_spec.rb → equalization_spec.rb} +2 -1
  24. data/spec/unit/auom/inspection_spec.rb +73 -0
  25. data/spec/unit/auom/relational_spec.rb +39 -0
  26. data/spec/unit/auom/unit_spec.rb +377 -0
  27. metadata +18 -57
  28. data/.circle.yml +0 -4
  29. data/TODO +0 -1
  30. data/spec/unit/auom/algebra/add_spec.rb +0 -57
  31. data/spec/unit/auom/algebra/divide_spec.rb +0 -83
  32. data/spec/unit/auom/algebra/multiply_spec.rb +0 -80
  33. data/spec/unit/auom/algebra/substract_spec.rb +0 -57
  34. data/spec/unit/auom/inspection/class_methods/prettify_unit_part_spec.rb +0 -29
  35. data/spec/unit/auom/inspection/inspect_spec.rb +0 -39
  36. data/spec/unit/auom/relational/greater_than_or_equal_to_predicate_spec.rb +0 -38
  37. data/spec/unit/auom/relational/greater_than_predicate_spec.rb +0 -38
  38. data/spec/unit/auom/relational/less_than_or_equal_to_predicate_spec.rb +0 -38
  39. data/spec/unit/auom/relational/less_than_predicate_spec.rb +0 -38
  40. data/spec/unit/auom/unit/assert_same_unit_spec.rb +0 -20
  41. data/spec/unit/auom/unit/class_methods/convert_spec.rb +0 -33
  42. data/spec/unit/auom/unit/class_methods/lookup_spec.rb +0 -19
  43. data/spec/unit/auom/unit/class_methods/new_spec.rb +0 -152
  44. data/spec/unit/auom/unit/class_methods/try_convert_spec.rb +0 -35
  45. data/spec/unit/auom/unit/class_methods/units_spec.rb +0 -9
  46. data/spec/unit/auom/unit/denominators_spec.rb +0 -14
  47. data/spec/unit/auom/unit/numerators_spec.rb +0 -14
  48. data/spec/unit/auom/unit/same_unit_predicate_spec.rb +0 -20
  49. data/spec/unit/auom/unit/scalar_spec.rb +0 -14
  50. data/spec/unit/auom/unit/unit +0 -0
  51. data/spec/unit/auom/unit/unit_spec.rb +0 -14
  52. data/spec/unit/auom/unit/unitless_predicate_spec.rb +0 -22
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AUOM
2
4
  # A scalar with units
3
5
  class Unit
@@ -102,7 +104,7 @@ module AUOM
102
104
  # @api public
103
105
  #
104
106
  def unitless?
105
- numerators.empty? and denominators.empty?
107
+ numerators.empty? && denominators.empty?
106
108
  end
107
109
 
108
110
  # Test if units are the same
@@ -173,8 +175,7 @@ module AUOM
173
175
  scalar, numerators = resolve([*numerators], scalar, :*)
174
176
  scalar, denominators = resolve([*denominators], scalar, :/)
175
177
 
176
- # sorting on #to_s as Symbol#<=> is not present on 1.8.7
177
- super(scalar, *[numerators, denominators].map { |base| base.sort_by(&:to_s) }).freeze
178
+ super(scalar, *[numerators, denominators].map(&:sort)).freeze
178
179
  end
179
180
 
180
181
  # Assert units are the same
@@ -186,9 +187,7 @@ module AUOM
186
187
  # @api private
187
188
  #
188
189
  def assert_same_unit(other)
189
- unless same_unit?(other)
190
- fail ArgumentError, 'Incompatible units'
191
- end
190
+ fail ArgumentError, 'Incompatible units' unless same_unit?(other)
192
191
 
193
192
  self
194
193
  end
@@ -209,6 +208,7 @@ module AUOM
209
208
  unless converted
210
209
  fail ArgumentError, "Cannot convert #{operand.inspect} to #{self}"
211
210
  end
211
+
212
212
  converted
213
213
  end
214
214
 
@@ -254,7 +254,6 @@ module AUOM
254
254
  @denominators = denominators.freeze
255
255
 
256
256
  @unit = [numerators, denominators].freeze
257
- scalar.freeze
258
257
  end
259
258
 
260
259
  # Return rational converted from value
@@ -317,6 +316,5 @@ module AUOM
317
316
  end
318
317
 
319
318
  private_class_method :lookup
320
-
321
319
  end # Unit
322
320
  end # AUOM
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  shared_examples_for 'an incompatible operation' do
2
4
  it 'should raise ArgumentError' do
3
5
  expect { subject }.to raise_error(ArgumentError, 'Incompatible units')
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  shared_examples_for 'an operation' do
2
4
  it 'returns a new object' do
3
5
  expect(object).to_not equal(subject)
@@ -6,6 +8,7 @@ shared_examples_for 'an operation' do
6
8
  it 'is idempotent on equivalency' do
7
9
  first = subject
8
10
  fail unless RSpec.configuration.threadsafe?
11
+
9
12
  mutex = __memoized.instance_variable_get(:@mutex)
10
13
  memoized = __memoized.instance_variable_get(:@memoized)
11
14
  mutex.synchronize { memoized.delete(:subject) }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  shared_examples_for 'unitless unit' do
2
4
  its(:numerators) { should == [] }
3
5
  its(:denominators) { should == [] }
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'auom'
2
4
  require 'devtools/spec_helper'
@@ -0,0 +1,279 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe AUOM::Algebra do
4
+ describe '#add' do
5
+ subject { object.add(operand) }
6
+
7
+ let(:object) { AUOM::Unit.new(*arguments) }
8
+
9
+ context 'when unit is unitless' do
10
+ let(:arguments) { [1] }
11
+
12
+ context 'and operand is an Integer' do
13
+ let(:operand) { 2 }
14
+
15
+ it_should_behave_like 'an operation'
16
+
17
+ it { should eql(AUOM::Unit.new(3)) }
18
+ end
19
+
20
+ context 'and operand is a unitless unit' do
21
+ let(:operand) { AUOM::Unit.new(2) }
22
+
23
+ it { should eql(AUOM::Unit.new(3)) }
24
+ end
25
+
26
+ context 'and operand is a unitful unit' do
27
+ let(:operand) { AUOM::Unit.new(2, :meter) }
28
+
29
+ it_should_behave_like 'an incompatible operation'
30
+ end
31
+ end
32
+
33
+ context 'when unit is unitful' do
34
+ let(:arguments) { [1, :meter, :euro] }
35
+
36
+ context 'and operand is an Integer' do
37
+ let(:operand) { 2 }
38
+
39
+ it_should_behave_like 'an incompatible operation'
40
+ end
41
+
42
+ context 'and operand is a unitless unit' do
43
+ let(:operand) { AUOM::Unit.new(2) }
44
+
45
+ it_should_behave_like 'an incompatible operation'
46
+ end
47
+
48
+ context 'and operand is a incompatible unit' do
49
+ let(:operand) { AUOM::Unit.new(2, :euro) }
50
+
51
+ it_should_behave_like 'an incompatible operation'
52
+ end
53
+
54
+ context 'and operand is a compatible unit' do
55
+ let(:operand) { AUOM::Unit.new(2, :meter, :euro) }
56
+
57
+ it { should eql(AUOM::Unit.new(3, :meter, :euro)) }
58
+ end
59
+ end
60
+ end
61
+
62
+ describe '#divide' do
63
+ subject { object.divide(operand) }
64
+
65
+ let(:object) { AUOM::Unit.new(*arguments) }
66
+
67
+ context 'with unitless unit' do
68
+ let(:arguments) { [4] }
69
+
70
+ context 'when operand is a fixnum' do
71
+ let(:operand) { 2 }
72
+
73
+ it_should_behave_like 'an operation'
74
+
75
+ it { should eql(AUOM::Unit.new(2)) }
76
+ end
77
+
78
+ context 'when operand is a unitless unit' do
79
+ let(:operand) { AUOM::Unit.new(2) }
80
+
81
+ it_should_behave_like 'an operation'
82
+
83
+ it { should eql(AUOM::Unit.new(2)) }
84
+ end
85
+
86
+ context 'when operand is a unitful unit' do
87
+ let(:operand) { AUOM::Unit.new(2, :meter) }
88
+
89
+ it_should_behave_like 'an operation'
90
+
91
+ it { should eql(AUOM::Unit.new(2, [], :meter)) }
92
+ end
93
+ end
94
+
95
+ context 'with unitful unit' do
96
+ let(:arguments) { [2, :meter] }
97
+
98
+ context 'when operand is a fixnum' do
99
+ let(:operand) { 1 }
100
+
101
+ it_should_behave_like 'an operation'
102
+
103
+ it { should eql(AUOM::Unit.new(2, :meter)) }
104
+ end
105
+
106
+ context 'when operand is a unitless unit' do
107
+ let(:operand) { AUOM::Unit.new(1) }
108
+
109
+ it_should_behave_like 'an operation'
110
+
111
+ it { should eql(AUOM::Unit.new(2, :meter)) }
112
+ end
113
+
114
+ context 'when operand is a unitful unit' do
115
+ context 'and units get added to denominator' do
116
+ let(:operand) { AUOM::Unit.new(1, :euro) }
117
+
118
+ it_should_behave_like 'an operation'
119
+
120
+ it { should eql(AUOM::Unit.new(2, :meter, :euro)) }
121
+ end
122
+
123
+ context 'and units get added to numerator' do
124
+ let(:operand) { AUOM::Unit.new(1, nil, :euro) }
125
+
126
+ it_should_behave_like 'an operation'
127
+
128
+ it { should eql(AUOM::Unit.new(2, %i[euro meter])) }
129
+ end
130
+
131
+ context 'and units cancel each other' do
132
+ let(:operand) { AUOM::Unit.new(1, :meter) }
133
+
134
+ it_should_behave_like 'an operation'
135
+
136
+ it { should eql(AUOM::Unit.new(2)) }
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ describe '#multiply' do
143
+ subject { object.multiply(operand) }
144
+
145
+ let(:object) { AUOM::Unit.new(*arguments) }
146
+
147
+ context 'with unitless unit' do
148
+ let(:arguments) { [2] }
149
+
150
+ context 'when operand is a fixnum' do
151
+ let(:operand) { 3 }
152
+
153
+ it_should_behave_like 'an operation'
154
+
155
+ it { should eql(AUOM::Unit.new(6)) }
156
+ end
157
+
158
+ context 'when operand is a unitless unit' do
159
+ let(:operand) { AUOM::Unit.new(3) }
160
+
161
+ it_should_behave_like 'an operation'
162
+
163
+ it { should eql(AUOM::Unit.new(6)) }
164
+ end
165
+
166
+ context 'when operand is a unitful unit' do
167
+ let(:operand) { AUOM::Unit.new(3, :meter) }
168
+
169
+ it_should_behave_like 'an operation'
170
+
171
+ it { should eql(AUOM::Unit.new(6, :meter)) }
172
+ end
173
+ end
174
+
175
+ context 'with unitful unit' do
176
+ let(:arguments) { [2, :meter, :kilogramm] }
177
+
178
+ context 'when operand is a fixnum' do
179
+ let(:operand) { 3 }
180
+
181
+ it_should_behave_like 'an operation'
182
+
183
+ it { should eql(AUOM::Unit.new(6, :meter, :kilogramm)) }
184
+ end
185
+
186
+ context 'when operand is a unitless unit' do
187
+ let(:operand) { AUOM::Unit.new(3) }
188
+
189
+ it_should_behave_like 'an operation'
190
+
191
+ it { should eql(AUOM::Unit.new(6, :meter, :kilogramm)) }
192
+ end
193
+
194
+ context 'when operand is a unitful unit' do
195
+ context 'and units get added to numerator' do
196
+ let(:operand) { AUOM::Unit.new(3, :meter) }
197
+
198
+ it_should_behave_like 'an operation'
199
+
200
+ it { should eql(AUOM::Unit.new(6, %i[meter meter], :kilogramm)) }
201
+ end
202
+
203
+ context 'and units get added to denominator' do
204
+ let(:operand) { AUOM::Unit.new(3, [], :euro) }
205
+
206
+ it_should_behave_like 'an operation'
207
+
208
+ it { should eql(AUOM::Unit.new(6, :meter, %i[euro kilogramm])) }
209
+ end
210
+
211
+ context 'and units cancel each other' do
212
+ let(:operand) { AUOM::Unit.new(3, [], :meter) }
213
+
214
+ it_should_behave_like 'an operation'
215
+
216
+ it { should eql(AUOM::Unit.new(6, [], :kilogramm)) }
217
+ end
218
+ end
219
+ end
220
+ end
221
+
222
+ describe '#subtract' do
223
+ subject { object.subtract(operand) }
224
+
225
+ let(:object) { AUOM::Unit.new(*arguments) }
226
+
227
+ context 'when unit is unitless' do
228
+ let(:arguments) { [1] }
229
+
230
+ context 'and operand is an Integer' do
231
+ let(:operand) { 1 }
232
+
233
+ it_should_behave_like 'an operation'
234
+
235
+ it { should eql(AUOM::Unit.new(0)) }
236
+ end
237
+
238
+ context 'and operand is a unitless unit' do
239
+ let(:operand) { AUOM::Unit.new(1) }
240
+
241
+ it { should eql(AUOM::Unit.new(0)) }
242
+ end
243
+
244
+ context 'and operand is a unitful unit' do
245
+ let(:operand) { AUOM::Unit.new(1, :meter) }
246
+
247
+ it_should_behave_like 'an incompatible operation'
248
+ end
249
+ end
250
+
251
+ context 'when unit is unitful' do
252
+ let(:arguments) { [1, :meter] }
253
+
254
+ context 'and operand is an Integer' do
255
+ let(:operand) { 1 }
256
+
257
+ it_should_behave_like 'an incompatible operation'
258
+ end
259
+
260
+ context 'and operand is a unitless unit' do
261
+ let(:operand) { AUOM::Unit.new(1) }
262
+
263
+ it_should_behave_like 'an incompatible operation'
264
+ end
265
+
266
+ context 'and operand is a incompatible unit' do
267
+ let(:operand) { AUOM::Unit.new(1, :euro) }
268
+
269
+ it_should_behave_like 'an incompatible operation'
270
+ end
271
+
272
+ context 'and operand is a compatible unit' do
273
+ let(:operand) { AUOM::Unit.new(1, :meter) }
274
+
275
+ it { should eql(AUOM::Unit.new(0, :meter)) }
276
+ end
277
+ end
278
+ end
279
+ end
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  describe AUOM::Equalization, '#==' do
2
4
  subject { object == other }
3
5
 
4
6
  let(:object) { AUOM::Unit.new(1, :meter) }
5
7
 
6
8
  context 'when is other kind of object' do
7
-
8
9
  context 'that cannot be converted' do
9
10
  let(:other) { Object.new }
10
11
 
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe AUOM::Inspection do
4
+ describe '#inspect' do
5
+ subject { object.inspect }
6
+
7
+ let(:object) { AUOM::Unit.new(scalar, *unit) }
8
+ let(:unit) { [] }
9
+
10
+ context 'when scalar is exact in decimal' do
11
+ let(:scalar) { 1 }
12
+
13
+ it { should eql('<AUOM::Unit @scalar=1>') }
14
+ end
15
+
16
+ context 'when scalar is NOT exact in decimal' do
17
+ let(:scalar) { Rational(1, 2) }
18
+
19
+ it { should eql('<AUOM::Unit @scalar=~0.5000>') }
20
+ end
21
+
22
+ context 'when has only numerator' do
23
+ let(:scalar) { Rational(1, 3) }
24
+ let(:unit) { [:meter] }
25
+
26
+ it { should eql('<AUOM::Unit @scalar=~0.3333 meter>') }
27
+ end
28
+
29
+ context 'when has only denominator' do
30
+ let(:scalar) { Rational(1, 3) }
31
+ let(:unit) { [[], :meter] }
32
+
33
+ it { should eql('<AUOM::Unit @scalar=~0.3333 1/meter>') }
34
+ end
35
+
36
+ context 'when has numerator and denominator' do
37
+ let(:scalar) { Rational(1, 3) }
38
+ let(:unit) { %i[euro meter] }
39
+
40
+ it { should eql('<AUOM::Unit @scalar=~0.3333 euro/meter>') }
41
+ end
42
+ end
43
+
44
+ describe '.prettify_unit_part' do
45
+ subject { object.prettify_unit_part(part) }
46
+
47
+ let(:object) { AUOM::Inspection }
48
+
49
+ context 'with simple part' do
50
+ let(:part) { [:meter] }
51
+
52
+ it { should eql('meter') }
53
+ end
54
+
55
+ context 'with mixed part' do
56
+ let(:part) { %i[meter euro] }
57
+
58
+ it { should eql('euro*meter') }
59
+ end
60
+
61
+ context 'with complex part' do
62
+ let(:part) { %i[meter meter euro] }
63
+
64
+ it { should eql('meter^2*euro') }
65
+ end
66
+
67
+ context 'with very complex part' do
68
+ let(:part) { %i[meter meter euro euro kilogramm] }
69
+
70
+ it { should eql('euro^2*meter^2*kilogramm') }
71
+ end
72
+ end
73
+ end