dimensional 0.0.6 → 0.1.1

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.
data/test/metric_test.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require 'test/unit'
2
2
  require 'dimensional/metric'
3
- require 'dimensional/unit'
4
3
  require 'rational'
5
4
 
6
5
  class MetricTest < Test::Unit::TestCase
@@ -12,88 +11,261 @@ class MetricTest < Test::Unit::TestCase
12
11
  Dimension.register('Force')
13
12
  System.register('British Admiralty', 'BA')
14
13
  System.register('United States Customary', 'US')
15
- cable = Unit.register('cable', System::BA, Dimension::L, {})
16
- fathom = Unit.register('fathom', System::BA, Dimension::L, {:reference_unit => cable, :reference_factor => Rational(1,10)})
17
- yard = Unit.register('yard', System::BA, Dimension::L, {:reference_unit => fathom, :reference_factor => Rational(1,6)})
18
- Unit.register('foot', System::BA, Dimension::L, {:reference_unit => yard, :reference_factor => Rational(1,3)})
19
- Unit.register('foot', System::US, Dimension::L, {:reference_unit => yard, :reference_factor => Rational(1,3)})
20
- Unit.register('pound', System::US, Dimension::M)
21
- Unit.register('pound', System::US, Dimension::F)
14
+ System.register('International System of Units', 'SI')
15
+ # Length Units - SI
16
+ @meter = Unit.register('meter', System::SI, Dimension::L, {:abbreviation => 'm'})
17
+ @kilometer = Unit.register('kilometer', System::SI, Dimension::L, {:reference_units => {@meter => 1}, :reference_factor => 1000, :abbreviation => 'km'})
18
+ @centimeter = Unit.register('centimeter', System::SI, Dimension::L, {:reference_units => {@meter => 1}, :reference_factor => Rational(1,100), :abbreviation => 'cm'})
19
+ # Length Units - US
20
+ @yard_us = Unit.register('yard', System::US, Dimension::L, {:reference_units => {@meter => 1}, :reference_factor => 0.9144, :abbreviation => 'yd'})
21
+ @foot_us = Unit.register('foot', System::US, Dimension::L, {:reference_units => {@yard_us => 1}, :reference_factor => Rational(1,3), :abbreviation => 'ft'})
22
+ @mile_us = Unit.register('mile', System::US, Dimension::L, {:reference_units => {@foot_us => 1}, :reference_factor => 5280, :abbreviation => 'mi'})
23
+ @inch_us = Unit.register('inch', System::US, Dimension::L, {:reference_units => {@foot_us => 1}, :reference_factor => Rational(1,12), :abbreviation => 'in'})
24
+ # Length Units - BA
25
+ @nautical_mile = Unit.register('mile', System::BA, Dimension::L, {:abbreviation => 'nm'})
26
+ @cable = Unit.register('cable', System::BA, Dimension::L, {:reference_units => {@nautical_mile => 1}, :reference_factor => Rational(1,10)})
27
+ @fathom = Unit.register('fathom', System::BA, Dimension::L, {:reference_units => {@cable => 1}, :reference_factor => Rational(1,10), :abbreviation => 'fm'})
28
+ @yard_ba = Unit.register('yard', System::BA, Dimension::L, {:reference_units => {@fathom => 1}, :reference_factor => Rational(1,6), :abbreviation => 'yd'})
29
+ @foot_ba = Unit.register('foot', System::BA, Dimension::L, {:reference_units => {@yard_ba => 1}, :reference_factor => Rational(1,3), :abbreviation => 'ft'})
30
+ @inch_ba = Unit.register('inch', System::BA, Dimension::L, {:reference_units => {@foot_ba => 1}, :reference_factor => Rational(1,12), :abbreviation => 'in'})
31
+ # Mass Units
32
+ @pound_mass = Unit.register('pound', System::US, Dimension::M, {:abbreviation => 'lb'})
33
+ # Force Units
34
+ @pound_force = Unit.register('pound', System::US, Dimension::F, {:abbreviation => 'ft'})
35
+ # Dimensionless Units
36
+ @each = Unit.register('each', System::US, nil, {:abbreviation => 'ea'})
37
+ @dozen = Unit.register('dozen', System::US, nil, {:reference_units => {@each => 0}, :reference_factor => 12, :abbreviation => 'dz'})
22
38
  end
23
39
 
24
40
  def teardown
25
41
  Dimension.reset!
26
42
  System.reset!
27
43
  Unit.reset!
28
- Metric.reset!
29
- end
30
-
31
- def test_create
32
- assert_instance_of Metric, m = Metric.new('draft', Dimension::L)
33
- assert_same Dimension::L, m.dimension
34
- assert_equal 'draft', m.name
35
- end
36
-
37
- def test_register
38
- assert_instance_of Metric, m = Metric.register('draft', Dimension::L)
39
- assert_same m, Metric[:draft]
40
- end
41
-
42
- def test_register_metric_with_parent
43
- parent = Metric.register('L', Dimension::L)
44
- child = Metric.register('depth', nil, parent)
45
- assert_same parent, child.parent
46
- end
47
-
48
- def test_register_dimensionless_metric
49
- assert_instance_of Metric, m = Metric.register('population', nil)
50
- assert_same m, Metric[:population]
51
- end
52
-
53
- def test_register_default_dimensionless_metric
54
- assert_instance_of Metric, m = Metric.register(nil, nil)
55
- assert_same m, Metric[nil]
56
- end
57
-
58
- def test_unit_preferences
59
- length = Metric.register('L', Dimension::L)
60
- draft = Metric.register('draft', Dimension::L, length)
61
- foot = Unit[Dimension::L, System::BA, 'foot']
62
- length.prefer(foot, {:detector => /(foot|ft)?s/})
63
- draft.prefer(foot, {:precision => Rational(1, 12)})
64
- assert_instance_of Hash, draft.preferences(foot)
65
- assert_equal Rational(1,12), draft.preferences(foot)[:precision]
66
- assert_equal /(foot|ft)?s/, draft.preferences(foot)[:detector]
67
- end
68
-
69
- def test_unit_membership
70
- length = Metric.register('L', Dimension::L)
71
- mass = Metric.register('M', Dimension::M)
72
- depth = Metric.register('depth', Dimension::L, length)
73
- foot = Unit[:L, :BA, 'foot']
74
- fathom = Unit[:L, :BA, 'fathom']
75
- pound = Unit[:M, :US, 'pound']
76
- length.prefer(foot)
77
- length.prefer(fathom)
78
- depth.prefer(fathom)
79
- mass.prefer(pound)
80
- assert_same fathom, depth.units.first # Units should be ordered with preferred units first...
81
- assert_same foot, depth.units.last # ...followed by remaining units from parent.
82
- assert_equal 2, depth.units.size # Units should be de-duped with parent
83
- end
84
-
85
- def test_enumerate
86
- length = Metric.register('L', Dimension::L)
87
- assert length.to_enum.kind_of?(Enumerable::Enumerator)
88
- assert_respond_to length, :map
89
- end
90
-
91
- def test_preferences_query_does_not_modify_preferences
92
- draft = Metric.register('draft', Dimension::L)
93
- foot = Unit[:L, :BA, 'foot']
94
- p0 = draft.preference(foot)
95
- draft.preferences(foot)
96
- p1 = draft.preference(foot)
97
- assert_equal p0, p1
44
+ end
45
+
46
+ def test_associated_units
47
+ beam = Class.new(Metric)
48
+ beam.dimension = Dimension::L
49
+ assert beam.units.include?(@cable)
50
+ assert !beam.units.include?(@pound_force)
51
+ end
52
+
53
+ def test_register_conflicting_unit
54
+ displacement = Class.new(Metric)
55
+ displacement.dimension = Dimension::M
56
+ assert_raises RuntimeError do
57
+ displacement.configure(@pound_force)
58
+ end
59
+ end
60
+
61
+ def test_create_new_measure
62
+ depth = Class.new(Metric)
63
+ depth.dimension = Dimension::L
64
+ assert m = depth.new(20, @fathom)
65
+ assert_equal 20, m
66
+ assert_equal @fathom, m.unit
67
+ end
68
+
69
+ def test_create_new_metric_with_default_unit
70
+ frontage = Class.new(Metric)
71
+ frontage.dimension = Dimension::L
72
+ frontage.default = Unit[:L, :US, :yard]
73
+ assert m = frontage.new(200)
74
+ assert_equal 200, m
75
+ assert_equal @yard_us, m.unit
76
+ end
77
+
78
+ def test_find_unit
79
+ depth = Class.new(Metric)
80
+ depth.dimension = Dimension::L
81
+ assert_same @foot_ba, depth.find_unit('foot', :BA)
82
+ assert_same @foot_us, depth.find_unit('foot', :US)
83
+ end
84
+
85
+ def test_parse
86
+ depth = Class.new(Metric)
87
+ depth.dimension = Dimension::L
88
+ assert m = depth.parse("15ft", :BA)
89
+ assert_same @foot_ba, m.unit
90
+ assert_equal 15, m
91
+ end
92
+
93
+ def test_parse_with_whitespace
94
+ depth = Class.new(Metric)
95
+ depth.dimension = Dimension::L
96
+ m = depth.parse("15 ft", :BA)
97
+ assert_same @foot_ba, m.unit
98
+ assert_equal 15, m
99
+ end
100
+
101
+ def test_parse_compound
102
+ depth = Class.new(Metric)
103
+ depth.dimension = Dimension::L
104
+ d = depth.parse("15ft11in", :US)
105
+ assert_in_delta(15 + Rational(11, 12), d, 0.000001)
106
+ assert_same @foot_us, d.unit
107
+ end
108
+
109
+ def test_parse_compound_with_whitespace
110
+ depth = Class.new(Metric)
111
+ depth.dimension = Dimension::L
112
+ d = depth.parse("1 ft 11 in", :US)
113
+ assert_same d.unit, @foot_us
114
+ assert_in_delta(1 + Rational(11, 12).to_f, d, 0.000001)
115
+ assert_same @foot_us, d.unit
116
+ end
117
+
118
+ def test_raise_on_parse_of_mixed_compound
119
+ depth = Class.new(Metric)
120
+ depth.dimension = Dimension::L
121
+ assert_raises ArgumentError do
122
+ depth.parse("1 foot 11cm", :L)
123
+ end
124
+ end
125
+
126
+ def test_parse_with_default_unit
127
+ depth = Class.new(Metric)
128
+ depth.dimension = Dimension::L
129
+ depth.default = @meter
130
+ assert_instance_of depth, m = depth.parse("10", :US)
131
+ assert_equal @meter, m.unit
132
+ end
133
+
134
+ def test_parse_dimensionless_units
135
+ count = Class.new(Metric)
136
+ assert m = count.parse('2 dozen')
137
+ assert_instance_of count, m
138
+ assert_equal 2, m
139
+ assert_equal @dozen, m.unit
140
+ assert_equal 12, m.unit.factor
141
+ assert_nil m.unit.dimension
142
+ end
143
+
144
+ def test_to_f
145
+ depth = Class.new(Metric)
146
+ depth.dimension = Dimension::L
147
+ d = depth.parse("1.85m", :SI)
148
+ assert_instance_of Float, d.to_f
149
+ end
150
+
151
+ def test_to_i
152
+ count = Class.new(Metric)
153
+ d = count.parse("1 each")
154
+ assert_instance_of Fixnum, d.to_i
155
+ end
156
+
157
+ def test_convert
158
+ depth = Class.new(Metric)
159
+ depth.dimension = Dimension::L
160
+ new = depth.new(1, @cable).convert(@fathom)
161
+ assert_in_delta(10, new, 0.000001)
162
+ assert_same @fathom, new.unit
163
+ end
164
+
165
+ def test_identity_conversion
166
+ depth = Class.new(Metric)
167
+ depth.dimension = Dimension::L
168
+ old_value = depth.new(12, @cable)
169
+ new_value = old_value.convert(@cable)
170
+ assert_equal old_value, new_value
171
+ end
172
+
173
+ # These system-conversion tests rely on very specific constants in the heuristics of #change_system
174
+ def test_change_system_yd
175
+ range = Class.new(Metric)
176
+ range.dimension = Dimension::L
177
+ m0 = range.new(1, @yard_us)
178
+ assert m1 = m0.change_system(:SI)
179
+ assert_same @meter, m1.unit
180
+ end
181
+
182
+ def test_change_system_with_oom_dominance
183
+ width = Class.new(Metric)
184
+ width.dimension = Dimension::L
185
+ m0 = width.new(1, @inch_us)
186
+ assert m1 = m0.change_system(:SI)
187
+ assert_same @centimeter, m1.unit
188
+ end
189
+
190
+ def test_change_system_ft
191
+ range = Class.new(Metric)
192
+ range.dimension = Dimension::L
193
+ m0 = range.new(1, @foot_us)
194
+ assert m1 = m0.change_system(:SI)
195
+ assert_same @meter, m1.unit
196
+ end
197
+
198
+ def test_change_system_mile
199
+ range = Class.new(Metric)
200
+ range.dimension = Dimension::L
201
+ m0 = range.new(1, @mile_us)
202
+ assert m1 = m0.change_system(:SI)
203
+ assert_same @kilometer, m1.unit
204
+ end
205
+
206
+ # These preferred tests rely on very specific constants in the heuristics of #prefer
207
+ def test_preferred_unit_with_only_oom
208
+ range = Class.new(Metric)
209
+ range.instance_eval do
210
+ self.dimension = Dimension::L
211
+ end
212
+ m0 = range.new(100000, @meter)
213
+ assert m1 = m0.preferred
214
+ assert_same @kilometer, m1.unit
215
+ end
216
+
217
+ # These preferred tests rely on very specific constants in the heuristics of #prefer
218
+ def test_preferred_unit_with_oom_and_preference
219
+ range = Class.new(Metric)
220
+ range.instance_eval do
221
+ self.dimension = Dimension::L
222
+ configure Unit[:L, :SI, :meter], {:preference => 3.01}
223
+ end
224
+ m0 = range.new(100000, Unit[:L, :SI, :meter])
225
+ assert m1 = m0.preferred
226
+ assert_same @meter, m1.unit
227
+ end
228
+
229
+ def test_convert_to_base
230
+ range = Class.new(Metric)
231
+ range.dimension = Dimension::L
232
+ range.base = @nautical_mile
233
+ b = range.new(1, @fathom).base
234
+ assert_in_delta(1e-2, b, 0.000001)
235
+ assert_same @nautical_mile, b.unit
236
+ end
237
+
238
+ def test_stringify_with_abbreviation
239
+ range = Class.new(Metric)
240
+ range.dimension = Dimension::L
241
+ assert_equal "1.85nm", range.parse('1.85 miles', :BA).to_s
242
+ end
243
+
244
+ def test_parse_gibberish_as_nil
245
+ beam = Class.new(Metric)
246
+ beam.dimension = Dimension::L
247
+ assert_nil beam.parse("gibberish", :L)
248
+ end
249
+
250
+ def test_format_output
251
+ depth = Class.new(Metric)
252
+ depth.dimension = Dimension::L
253
+ m = depth.parse("15ft3in", :BA)
254
+ assert_equal "15.25 (ft)", m.strfmeasure("%4.2f (%U)")
255
+ end
256
+
257
+ def test_format_output_with_multiple_substitutions
258
+ depth = Class.new(Metric)
259
+ depth.dimension = Dimension::L
260
+ m = depth.parse("15ft4in", :BA)
261
+ assert_equal "15.33 (ft)\t%\t<15.3333333ft>", m.strfmeasure("%4.2f (%U)\t%%\t<%10.7f%U>")
262
+ end
263
+
264
+ def test_precision_recognition
265
+ distance = Class.new(Metric)
266
+ distance.dimension = Dimension::L
267
+ distance.configure(@nautical_mile, :precision => -2)
268
+ assert_equal "1.8600nm", distance.parse('1.8565454 nm', :BA).strfmeasure("%.4f%U")
269
+ assert_equal "1.86", distance.parse('1.8565454 nm', :BA).strfmeasure("%s")
98
270
  end
99
271
  end
data/test/unit_test.rb CHANGED
@@ -11,6 +11,7 @@ class UnitTest < Test::Unit::TestCase
11
11
  Dimension.register('Length')
12
12
  Dimension.register('Mass')
13
13
  Dimension.register('Force')
14
+ Dimension.register('Area', 'A', {Dimension::L => 4})
14
15
  end
15
16
 
16
17
  def teardown
@@ -24,72 +25,135 @@ class UnitTest < Test::Unit::TestCase
24
25
  assert_same System::BA, u.system
25
26
  assert_same Dimension::L, u.dimension
26
27
  assert u.base?
27
- assert_same u, u.base
28
+ assert_equal({u => 1}, u.base)
28
29
  assert_same 1, u.factor
29
30
  end
30
-
31
+
32
+ def test_enumerability
33
+ u = Unit.register('each', System::BA, nil, {})
34
+ assert Unit.to_a.include?(u)
35
+ end
36
+
31
37
  def test_create_new_dimensionless_unit
32
38
  assert_instance_of Unit, u = Unit.new('each', System::BA, nil, {})
33
39
  assert_nil u.dimension
34
40
  end
35
-
41
+
36
42
  def test_create_new_derived_unit
37
43
  cable = Unit.new('cable', System::BA, Dimension::L, {})
38
- assert_instance_of Unit, u = Unit.new('fathom', System['BA'], Dimension['L'], :reference_factor => 1E-1, :reference_unit => cable)
44
+ assert_instance_of Unit, u = Unit.new('fathom', System['BA'], Dimension['L'], :reference_factor => 1E-1, :reference_units => {cable => 1})
39
45
  assert !u.base?
40
- assert_same cable, u.base
46
+ t = u.base
47
+ assert_equal({cable => 1}, t)
41
48
  assert_equal 1E-1, u.factor
42
49
  end
43
50
 
44
51
  def test_create_new_combined_unit
45
52
  meter = Unit.new('meter', System::SI, Dimension::L, {})
46
- assert_instance_of Unit, u = Unit.new('square meter', System::SI, Dimension::L, :reference_factor => 1, :reference_unit => [meter, meter])
53
+ assert_instance_of Unit, u = Unit.new('square meter', System::SI, Dimension::L, :reference_factor => 1, :reference_units => {meter => 2})
47
54
  assert !u.base?
48
- assert_equal [meter, meter], u.base
55
+ assert_equal({meter => 2}, u.base)
49
56
  assert_equal 1, u.factor
50
57
  end
51
58
 
59
+ def test_create_new_combined_with_derived_unit_and_big_exponents
60
+ meter = Unit.new('meter', System::SI, Dimension::L, {})
61
+ assert_instance_of Unit, yard = Unit.new('yard', System::US, Dimension::L, :reference_factor => 0.9144, :reference_units => {meter => 1})
62
+ assert_instance_of Unit, yard2 = Unit.new('square yard', System::SI, Dimension::A, :reference_factor => 1, :reference_units => {yard => 2})
63
+ assert !yard2.base?
64
+ assert_equal({meter => 2}, yard2.base)
65
+ assert_equal 0.83612736, yard2.factor
66
+ end
67
+
52
68
  def test_regsiter_new_unit
53
69
  assert_instance_of Unit, u = Unit.register('fathom', System::BA, Dimension::L, {:abbreviation => 'fm'})
54
70
  assert_same u, Unit[Dimension::L, System::BA, 'fathom']
55
71
  assert_same u, Unit[Dimension::L, System::BA, 'fm']
56
72
  end
57
-
73
+
58
74
  def test_regsiter_new_dimensionless_unit
59
75
  assert_instance_of Unit, u = Unit.register('each', System::BA, nil, {:abbreviation => 'ea'})
60
76
  assert_same u, Unit[nil, System::BA, 'each']
61
77
  assert_same u, Unit[nil, System::BA, 'ea']
62
78
  end
63
-
79
+
64
80
  def test_lookup_unit_with_symbols
65
81
  u = Unit.register('fathom', System::BA, Dimension::L, {:abbreviation => 'fm'})
66
- assert_nil Unit[:L, :SI, 'fathom']
67
- assert_nil Unit[:M, :BA, 'fathom']
68
- assert_nil Unit[:L, :BA, 'somethingelse']
69
82
  assert_same u, Unit[:L, :BA, 'fathom']
70
83
  end
71
-
84
+
85
+ def test_lookup_failure
86
+ assert_raises ArgumentError do
87
+ Unit[:L, :SI, 'fathom']
88
+ end
89
+ assert_raises ArgumentError do
90
+ Unit[:M, :BA, 'fathom']
91
+ end
92
+ assert_raises ArgumentError do
93
+ Unit[:L, :BA, 'somethingelse']
94
+ end
95
+ end
96
+
72
97
  def test_convert
73
98
  cable = Unit.new('cable', System::BA, Dimension::L, {})
74
- fathom = Unit.new('fathom', System::BA, Dimension::L, :reference_factor => 1E-1, :reference_unit => cable)
99
+ fathom = Unit.new('fathom', System::BA, Dimension::L, :reference_factor => 1E-1, :reference_unit => cable)
75
100
  assert_equal 10, cable.convert(fathom)
76
101
  assert_equal 1E-1, fathom.convert(cable)
77
102
  assert_equal 1, fathom.convert(fathom)
78
103
  end
79
-
104
+
80
105
  def test_identify_commensurable_units
81
- u0 = Unit.new('mile', System::BA, Dimension::L, :detector => /\A(nm|nmi)\Z/, :abbreviation => 'nm')
82
- u1 = Unit.new('cable', System::BA, Dimension::L, :detector => /\A(cables?|cbls?)\Z/, :reference_factor => 1E-1, :reference_unit => u0)
106
+ u0 = Unit.new('mile', System::BA, Dimension::L, :abbreviation => 'nm')
107
+ u1 = Unit.new('cable', System::BA, Dimension::L, :reference_factor => 1E-1, :reference_unit => u0)
83
108
  u2 = Unit.new('ton', System::BA, Dimension::M, :abbreviation => 't')
84
109
  assert u0.commensurable?(u1)
85
110
  assert !u0.commensurable?(u2)
86
111
  end
87
112
 
88
113
  def test_identify_commensurable_composed_units
89
- u0 = Unit.new('mile', System::BA, Dimension::L, :detector => /\A(nm|nmi)\Z/, :abbreviation => 'nm')
90
- u1 = Unit.new('cable', System::BA, Dimension::L, :detector => /\A(cables?|cbls?)\Z/, :reference_factor => 1E-1, :reference_unit => u0)
114
+ u0 = Unit.new('mile', System::BA, Dimension::L, :abbreviation => 'nm')
115
+ u1 = Unit.new('cable', System::BA, Dimension::L, :reference_factor => 1E-1, :reference_unit => u0)
91
116
  u2 = Unit.new('ton', System::BA, Dimension::M, :abbreviation => 't')
92
117
  assert u0.commensurable?(u1)
93
118
  assert !u0.commensurable?(u2)
94
119
  end
120
+
121
+ def test_identity
122
+ u0 = Unit.new('mile', System::BA, Dimension::L)
123
+ u1 = Unit.new('mile', System::BA, Dimension::L)
124
+ u2 = Unit.new('statute mile', System::BA, Dimension::L)
125
+ # u0 and u1 are effectively identical and should collide in hashes
126
+ assert_same u0.hash, u1.hash
127
+ assert u0.eql?(u1)
128
+ # u0 and u2 are distinct and should not collide in hashes
129
+ assert_not_same u0.hash, u2.hash
130
+ assert !u0.eql?(u2)
131
+ end
132
+
133
+ def test_equality
134
+ u0 = Unit.new('mile', System::BA, Dimension::L)
135
+ u1 = Unit.new('sea mile', System::BA, Dimension::L, :reference_factor => 1, :reference_units => {u0 => 1})
136
+ u2 = Unit.new('mile', System::BA, Dimension::L, :reference_factor => 0.93, :reference_units => {u0 => 1}) # modern approximation
137
+ # u0 and u1 have the same value but different identities
138
+ assert_equal u0, u1
139
+ # u0 and u2 have the same identity but different values
140
+ assert_not_equal u0, u2
141
+ end
142
+
143
+ def test_default_detector
144
+ u0 = Unit.new('mile', System::BA, Dimension::L, :abbreviation => 'nm')
145
+ assert_match u0.detector, 'mile'
146
+ assert_match u0.detector, 'nm'
147
+ end
148
+
149
+ def test_default_format
150
+ u0 = Unit.new('mile', System::BA, Dimension::L, :abbreviation => 'nm')
151
+ assert_match /%.*s/, u0.format
152
+ assert_match /%.*U/i, u0.format
153
+ end
154
+
155
+ def test_default_preference
156
+ u0 = Unit.new('mile', System::BA, Dimension::L, :abbreviation => 'nm')
157
+ assert_equal 0, u0.preference
158
+ end
95
159
  end