dimensional 0.0.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.
@@ -0,0 +1,185 @@
1
+ require 'test/unit'
2
+ require 'dimensional/measure'
3
+ require 'dimensional/configurator'
4
+ require 'rational'
5
+
6
+ class MeasureTest < Test::Unit::TestCase
7
+ include Dimensional
8
+
9
+ def setup
10
+ System.register('International System of Units', 'SI')
11
+ System.register('United States Customary Units', 'US')
12
+ System.register('British Admiralty', 'BA')
13
+
14
+ Dimension.register('Length')
15
+ Dimension.register('Mass')
16
+
17
+ Metric.register('length', :L)
18
+
19
+ Configurator.start do
20
+ dimension(:L) do
21
+ system(:SI) do
22
+ base('meter', :detector => /\A(meters?|m)\Z/, :abbreviation => 'm') do
23
+ prefer(:length_over_all, :precision => 0.01)
24
+ derive('centimeter', 1e-2, :detector => /\A(centimeters?|cm)\Z/, :abbreviation => 'cm')
25
+ derive('kilometer', 1e3, :detector => /\A(kilometers?|km)\Z/, :abbreviation => 'km')
26
+ end
27
+ end
28
+ system(:US) do # As of 1 July 1959 (http://en.wikipedia.org/wiki/United_States_customary_units#Units_of_length)
29
+ reference('yard', Unit[:L, :SI, 'meter'], 0.9144, :detector => /\A(yards?|yds?)\Z/, :abbreviation => 'yd') do
30
+ derive('foot', Rational(1,3), :detector => /\A(foot|feet|ft|')\Z/, :abbreviation => "ft", :format => "%p'") do
31
+ prefer(:length_over_all, :precision => Rational(1, 12))
32
+ derive('inch', Rational(1,12), :detector => /\A(inch|inches|in|")\Z/, :abbreviation =>"in", :format => "%p\"")
33
+ end
34
+ derive('furlong', 220, :detector => /\A(furlongs?)\Z/) do
35
+ derive('mile', 8, :detector => /\Amiles?\Z/, :abbreviation => 'mi')
36
+ end
37
+ end
38
+ end
39
+ system(:BA) do
40
+ base('mile', :detector => /\A(miles?|nm|nmi)\Z/, :abbreviation => 'nm') do
41
+ prefer(:distance, :precision => -2)
42
+ derive('cable', Rational(1,10), :detector => /\A(cables?|cbls?)\Z/) do
43
+ derive('fathom', Rational(1,10), :detector => /\A(fathoms?|fms?)\Z/, :abbreviation => 'fm') do
44
+ derive('yard', Rational(1,6), :detector => /\A(yards?|yds?)\Z/, :abbreviation => 'yd') do
45
+ derive('foot', Rational(1,3), :detector => /\A(foot|feet|ft|')\Z/, :abbreviation => "ft") do
46
+ prefer(:length_over_all, :precision => Rational(1, 12))
47
+ derive('inch', Rational(1,12), :detector => /\A(inch|inches|in|")\Z/, :abbreviation => "in")
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ dimension(:M) do
56
+ system(:SI) do
57
+ base('kilogram', :detector => /\A(kilograms?|kg)\Z/, :abbreviation => 'kg') do
58
+ derive('tonne', 1000, :detector => /\A(tonnes?)\Z/, :abbreviation => 't') # metric ton
59
+ derive('gram', Rational(1, 1000), :detector => /\A(grams?|g)\Z/, :abbreviation => 'g')
60
+ end
61
+ end
62
+ end
63
+ # Dimensionless Units
64
+ base('each', :abbreviation => 'ea') do
65
+ derive('dozen', 12, :abbreviation => 'dz')
66
+ end
67
+ end
68
+ end
69
+
70
+ def teardown
71
+ Dimension.reset!
72
+ System.reset!
73
+ Unit.reset!
74
+ Metric.reset!
75
+ end
76
+
77
+ def test_create_new_measure
78
+ u = Unit[:L, :BA, 'mile']
79
+ assert m = Measure.new(3000, u, :length)
80
+ assert_equal 3000, m
81
+ assert_equal u, m.unit
82
+ assert_same Metric[:length], m.metric
83
+ end
84
+
85
+ def test_to_f
86
+ d = Measure.parse("1.85m", :L, :SI)
87
+ assert_instance_of Float, d.to_f
88
+ end
89
+
90
+ def test_to_i
91
+ d = Measure.parse("1 each", Metric[nil])
92
+ assert_instance_of Fixnum, d.to_i
93
+ end
94
+
95
+ def test_to_native
96
+ d = Measure.parse("1 each", Metric[nil])
97
+ assert_instance_of Fixnum, d.native
98
+ end
99
+
100
+ def test_convert
101
+ old_unit = Unit[:L, :BA, 'cable']
102
+ new_unit = Unit[:L, :BA, 'fathom']
103
+ new = Measure.new(1, old_unit).convert(new_unit)
104
+ assert_in_delta(10, new, 0.000001)
105
+ assert_same new_unit, new.unit
106
+ end
107
+
108
+ def test_do_identity_conversion
109
+ old_unit = Unit[:L, :BA, 'cable']
110
+ new_unit = old_unit
111
+ old_value = Measure.new(12, old_unit)
112
+ new_value = old_value.convert(new_unit)
113
+ assert_equal old_value, new_value
114
+ end
115
+
116
+ def test_return_base
117
+ u = Unit[:L, :BA, 'fathom']
118
+ b = Measure.new(1, u).base
119
+ assert_in_delta(1e-2, b, 0.000001)
120
+ assert_same u.base, b.unit
121
+ end
122
+
123
+ def test_parse
124
+ assert m = Measure.parse("15'", :L, :BA)
125
+ assert_same Unit[:L, :BA, 'foot'], m.unit
126
+ assert_equal 15, m
127
+ end
128
+
129
+ def test_parse_with_whitespace
130
+ m = Measure.parse("15 feet", :L, :BA)
131
+ assert_same Unit[:L, :BA, 'foot'], m.unit
132
+ assert_equal 15, m
133
+ end
134
+
135
+ def test_parse_compound
136
+ d = Measure.parse("15'11\"", :L, :US)
137
+ assert_in_delta(15 + Rational(11, 12), d, 0.000001)
138
+ end
139
+
140
+ def test_parse_compound_with_whitespace
141
+ d = Measure.parse("1 foot 11 inches", :L, :US)
142
+ assert_same d.unit, Unit[:L, :US, 'foot']
143
+ assert_in_delta(1 + Rational(11, 12).to_f, d, 0.000001)
144
+ end
145
+
146
+ def test_raise_on_parse_of_mixed_compound
147
+ assert_raises ArgumentError do
148
+ Measure.parse("1 foot 11cm", :L)
149
+ end
150
+ end
151
+
152
+ def test_parse_with_default_unit
153
+ metric = Metric[:L]
154
+ du = metric.units.first
155
+ assert_instance_of Measure, m = Measure.parse("10", :L)
156
+ assert_equal du, m.unit
157
+ end
158
+
159
+ def test_parse_dimensionless_units
160
+ assert m = Measure.parse('2 dozen', nil)
161
+ assert_instance_of Measure, m
162
+ assert_equal 2, m
163
+ assert_equal Unit[nil, nil, 'dozen'], m.unit
164
+ assert_equal 12, m.unit.factor
165
+ assert_nil m.unit.dimension
166
+ end
167
+
168
+ def test_stringify_with_abbreviation
169
+ assert_equal "1.85nm", Measure.parse('1.85 miles', :L, :BA).to_s
170
+ end
171
+
172
+ def test_parse_gibberish_as_nil
173
+ assert_nil Measure.parse("gibberish", :L)
174
+ end
175
+
176
+ def test_format_output
177
+ m = Measure.parse("15'3\"", :L, :BA)
178
+ assert_equal "15.25 (ft)", m.strfmeasure("%4.2f (%U)")
179
+ end
180
+
181
+ def test_precision_recognition
182
+ assert_equal "1.8600nm", Measure.parse('1.8565454 miles', :distance, :BA).strfmeasure("%.4f%U")
183
+ assert_equal "1.86", Measure.parse('1.8565454 miles', :distance, :BA).strfmeasure("%s")
184
+ end
185
+ end
@@ -0,0 +1,90 @@
1
+ require 'test/unit'
2
+ require 'dimensional/metric'
3
+ require 'dimensional/unit'
4
+ require 'rational'
5
+
6
+ class MetricTest < Test::Unit::TestCase
7
+ include Dimensional
8
+
9
+ def setup
10
+ Dimension.register('Length')
11
+ Dimension.register('Mass')
12
+ Dimension.register('Force')
13
+ System.register('British Admiralty', 'BA')
14
+ 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)
22
+ end
23
+
24
+ def teardown
25
+ Dimension.reset!
26
+ System.reset!
27
+ 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
+ end
@@ -0,0 +1,40 @@
1
+ require 'test/unit'
2
+ require 'dimensional/system'
3
+
4
+ class SystemTest < Test::Unit::TestCase
5
+ include Dimensional
6
+
7
+ def teardown
8
+ System.reset!
9
+ end
10
+
11
+ def test_create_new_measurement_system
12
+ assert_instance_of System, s = System.new('British Admiralty')
13
+ assert_equal 'British Admiralty', s.name
14
+ assert_nil s.abbreviation
15
+ end
16
+
17
+ def test_create_new_measurement_system_with_abbreviation
18
+ assert_instance_of System, s = System.new('British Admiralty', 'BA')
19
+ assert_equal 'British Admiralty', s.name
20
+ assert_equal 'BA', s.abbreviation
21
+ end
22
+
23
+ def test_register_new_measurement_system
24
+ assert_instance_of System, s = System.register('British Admiralty')
25
+ assert_same s, System['British Admiralty']
26
+ end
27
+
28
+ def test_register_new_measurement_system_with_abbreviation
29
+ assert_instance_of System, s = System.register('British Admiralty', 'BA')
30
+ assert_same s, System['BA']
31
+ assert defined?(System::BA)
32
+ assert_same s, System::BA
33
+ end
34
+
35
+ def test_not_raise_exception_when_system_not_found
36
+ assert_nothing_raised do
37
+ System['British Admiralty']
38
+ end
39
+ end
40
+ end
data/test/unit_test.rb ADDED
@@ -0,0 +1,102 @@
1
+ require 'test/unit'
2
+ require 'dimensional/unit'
3
+
4
+ class UnitTest < Test::Unit::TestCase
5
+ include Dimensional
6
+
7
+ def setup
8
+ System.register('International System of Units', 'SI')
9
+ System.register('United States Customary', 'US')
10
+ System.register('British Admiralty', 'BA')
11
+ Dimension.register('Length')
12
+ Dimension.register('Mass')
13
+ Dimension.register('Force')
14
+ end
15
+
16
+ def teardown
17
+ Dimension.reset!
18
+ System.reset!
19
+ Unit.reset!
20
+ end
21
+
22
+ def test_create_new_base_unit
23
+ assert_instance_of Unit, u = Unit.new('cable', System::BA, Dimension::L, {})
24
+ assert_same System::BA, u.system
25
+ assert_same Dimension::L, u.dimension
26
+ assert u.base?
27
+ assert_same u, u.base
28
+ assert_same 1, u.factor
29
+ end
30
+
31
+ def test_create_new_dimensionless_unit
32
+ assert_instance_of Unit, u = Unit.new('each', System::BA, nil, {})
33
+ assert_nil u.dimension
34
+ end
35
+
36
+ def test_create_new_derived_unit
37
+ 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)
39
+ assert !u.base?
40
+ assert_same cable, u.base
41
+ assert_equal 1E-1, u.factor
42
+ end
43
+
44
+ def test_create_new_combined_unit
45
+ 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])
47
+ assert !u.base?
48
+ assert_equal [meter, meter], u.base
49
+ assert_equal 1, u.factor
50
+ end
51
+
52
+ def test_regsiter_new_unit
53
+ assert_instance_of Unit, u = Unit.register('fathom', System::BA, Dimension::L, {:abbreviation => 'fm'})
54
+ assert_same u, Unit[Dimension::L, System::BA, 'fathom']
55
+ assert_same u, Unit[Dimension::L, System::BA, 'fm']
56
+ end
57
+
58
+ def test_regsiter_new_dimensionless_unit
59
+ assert_instance_of Unit, u = Unit.register('each', System::BA, nil, {:abbreviation => 'ea'})
60
+ assert_same u, Unit[nil, System::BA, 'each']
61
+ assert_same u, Unit[nil, System::BA, 'ea']
62
+ end
63
+
64
+ def test_lookup_unit_with_symbols
65
+ 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
+ assert_same u, Unit[:L, :BA, 'fathom']
70
+ end
71
+
72
+ def test_convert
73
+ cable = Unit.new('cable', System::BA, Dimension::L, {})
74
+ fathom = Unit.new('fathom', System::BA, Dimension::L, :reference_factor => 1E-1, :reference_unit => cable)
75
+ assert_equal 10, cable.convert(fathom)
76
+ assert_equal 1E-1, fathom.convert(cable)
77
+ assert_equal 1, fathom.convert(fathom)
78
+ end
79
+
80
+ def test_match_per_unit
81
+ u = Unit.new('mile', System::BA, Dimension::L, :detector => /\A(nm|nmi)\Z/)
82
+ md = u.match('nmi')
83
+ assert_instance_of MatchData, md
84
+ assert_equal 'nmi', md[0]
85
+ end
86
+
87
+ def test_identify_commensurable_units
88
+ u0 = Unit.new('mile', System::BA, Dimension::L, :detector => /\A(nm|nmi)\Z/, :abbreviation => 'nm')
89
+ u1 = Unit.new('cable', System::BA, Dimension::L, :detector => /\A(cables?|cbls?)\Z/, :reference_factor => 1E-1, :reference_unit => u0)
90
+ u2 = Unit.new('ton', System::BA, Dimension::M, :abbreviation => 't')
91
+ assert u0.commensurable?(u1)
92
+ assert !u0.commensurable?(u2)
93
+ end
94
+
95
+ def test_identify_commensurable_composed_units
96
+ u0 = Unit.new('mile', System::BA, Dimension::L, :detector => /\A(nm|nmi)\Z/, :abbreviation => 'nm')
97
+ u1 = Unit.new('cable', System::BA, Dimension::L, :detector => /\A(cables?|cbls?)\Z/, :reference_factor => 1E-1, :reference_unit => u0)
98
+ u2 = Unit.new('ton', System::BA, Dimension::M, :abbreviation => 't')
99
+ assert u0.commensurable?(u1)
100
+ assert !u0.commensurable?(u2)
101
+ end
102
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dimensional
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Chris Hapgood
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-09 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: " Dimensional provides handling for dimensional values (numbers with units). Dimensional values\n can be parsed, stored, converted and formatted for output.\n"
17
+ email: cch1@hapgoods.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/dimensional/configurator.rb
26
+ - lib/dimensional/dimension.rb
27
+ - lib/dimensional/measure.rb
28
+ - lib/dimensional/metric.rb
29
+ - lib/dimensional/system.rb
30
+ - lib/dimensional/unit.rb
31
+ - lib/dimensional.rb
32
+ - test/configurator_test.rb
33
+ - test/demo.rb
34
+ - test/dimension_test.rb
35
+ - test/dimensional_test.rb
36
+ - test/measure_test.rb
37
+ - test/metric_test.rb
38
+ - test/system_test.rb
39
+ - test/unit_test.rb
40
+ - README
41
+ - CHANGELOG
42
+ - LICENSE
43
+ - Rakefile
44
+ has_rdoc: true
45
+ homepage: http://cho.hapgoods.com/dimensional
46
+ licenses: []
47
+
48
+ post_install_message:
49
+ rdoc_options: []
50
+
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: 1.6.8
58
+ version:
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ requirements: []
66
+
67
+ rubyforge_project:
68
+ rubygems_version: 1.3.5
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: Dimensional provides handling for numbers with units.
72
+ test_files:
73
+ - test/configurator_test.rb
74
+ - test/demo.rb
75
+ - test/dimension_test.rb
76
+ - test/dimensional_test.rb
77
+ - test/measure_test.rb
78
+ - test/metric_test.rb
79
+ - test/system_test.rb
80
+ - test/unit_test.rb