dimensional 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/lib/dimensional.rb +1 -1
- data/lib/dimensional/configuration.rb +48 -0
- data/lib/dimensional/configurator.rb +24 -18
- data/lib/dimensional/measure.rb +15 -14
- data/lib/dimensional/system.rb +5 -1
- data/lib/dimensional/unit.rb +5 -11
- data/test/configurator_test.rb +25 -13
- data/test/demo.rb +43 -43
- data/test/measure_test.rb +24 -24
- data/test/unit_test.rb +0 -7
- metadata +2 -1
data/Rakefile
CHANGED
@@ -16,7 +16,7 @@ Rake::Task['test'].comment = "Run all tests in test/*_test.rb"
|
|
16
16
|
spec = Gem::Specification.new do |s|
|
17
17
|
s.platform = Gem::Platform::RUBY
|
18
18
|
s.name = %q{dimensional}
|
19
|
-
s.version = "0.0.
|
19
|
+
s.version = "0.0.5"
|
20
20
|
s.required_ruby_version = '>= 1.6.8'
|
21
21
|
s.date = %q{2009-10-09}
|
22
22
|
s.authors = ["Chris Hapgood"]
|
data/lib/dimensional.rb
CHANGED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'dimensional/dimension'
|
2
|
+
require 'dimensional/system'
|
3
|
+
require 'dimensional/unit'
|
4
|
+
require 'dimensional/metric'
|
5
|
+
|
6
|
+
# Encapsulates the application-specific configuration of Dimensional elements, including
|
7
|
+
# * Dimensions, including which are considered fundamental.
|
8
|
+
# * Systems, including a prioritized array of Systems to be consulted during parsing.
|
9
|
+
# * Metrics, including Unit formatting and parsing options per Metric
|
10
|
+
# * Units
|
11
|
+
# Configurations can be constructed with a Configurator. They can also be copied and extended.
|
12
|
+
#
|
13
|
+
# Metric == context
|
14
|
+
#
|
15
|
+
# Configuration#options(unit, context) => options_hash
|
16
|
+
|
17
|
+
# Configuration#format(unit, context) => format_string
|
18
|
+
# #strfmeasure-compatible format string for given unit and given context
|
19
|
+
|
20
|
+
# Configuration#detectors(context) => detector_hash
|
21
|
+
# #parse-compatible detector->unit pairs suitable for given context
|
22
|
+
|
23
|
+
# Measure.parse(str, detectors) => instance of measure with unit matched by detectors
|
24
|
+
# Measure#strfmeasure(format)
|
25
|
+
# Measure#change_system(system)
|
26
|
+
|
27
|
+
class Configuration
|
28
|
+
class Systems < Array
|
29
|
+
end
|
30
|
+
|
31
|
+
class Dimensions < Set
|
32
|
+
end
|
33
|
+
|
34
|
+
class Metrics < Set
|
35
|
+
end
|
36
|
+
|
37
|
+
class Units < Set
|
38
|
+
end
|
39
|
+
|
40
|
+
attr_reader :dimensions, :systems, :units, :metrics
|
41
|
+
|
42
|
+
def initialize
|
43
|
+
@dimensions = Dimensions.new
|
44
|
+
@systems = Systems.new
|
45
|
+
@metrics = Metrics.new
|
46
|
+
@units = Units.new
|
47
|
+
end
|
48
|
+
end
|
@@ -56,35 +56,35 @@ module Dimensional
|
|
56
56
|
end
|
57
57
|
|
58
58
|
# Register a new base unit
|
59
|
-
def base(name, options = {}, &block)
|
60
|
-
u =
|
59
|
+
def base(name, abbreviation = nil, options = {}, &block)
|
60
|
+
u = unit(name, {:abbreviation => abbreviation})
|
61
|
+
dimension_metric.prefer(u, default_preferences(u).merge(options))
|
61
62
|
change_context({:unit => u}, block)
|
62
63
|
end
|
63
64
|
|
64
65
|
# Register a new derived unit
|
65
|
-
def derive(name, factor, options = {}, &block)
|
66
|
-
|
67
|
-
|
68
|
-
u = register_unit(name, options)
|
66
|
+
def derive(name, abbreviation, factor, options = {}, &block)
|
67
|
+
u = unit(name, {:abbreviation => abbreviation, :reference_unit => context.unit, :reference_factor => factor})
|
68
|
+
dimension_metric.prefer(u, default_preferences(u).merge(options))
|
69
69
|
change_context({:unit => u}, block)
|
70
70
|
end
|
71
71
|
|
72
72
|
# Register an alias for the unit in context
|
73
|
-
def alias(name, options = {}, &block)
|
74
|
-
derive(name, 1, options, &block)
|
73
|
+
def alias(name, abbreviation = nil, options = {}, &block)
|
74
|
+
derive(name, abbreviation, 1, options, &block)
|
75
75
|
end
|
76
76
|
|
77
77
|
# Register a new unit in the current context that references an arbitrary unit
|
78
|
-
def reference(name,
|
79
|
-
|
80
|
-
u
|
78
|
+
def reference(name, abbreviation, u, f, options = {}, &block)
|
79
|
+
u = unit(name, :abbreviation => abbreviation, :reference_unit => u, :reference_factor => f)
|
80
|
+
dimension_metric.prefer(u, default_preferences(u).merge(options))
|
81
81
|
change_context({:unit => u}, block)
|
82
82
|
end
|
83
83
|
|
84
84
|
# Register a new unit in the current context that is composed of multiple units
|
85
|
-
def combine(name, components, options = {}, &block)
|
86
|
-
|
87
|
-
u
|
85
|
+
def combine(name, abbreviation, components, options = {}, &block)
|
86
|
+
u = unit(name, :abbreviation => abbreviation, :reference_factor => 1, :reference_unit => components)
|
87
|
+
dimension_metric.prefer(u, default_preferences(u).merge(options))
|
88
88
|
change_context({:unit => u}, block)
|
89
89
|
end
|
90
90
|
|
@@ -99,15 +99,21 @@ module Dimensional
|
|
99
99
|
end
|
100
100
|
|
101
101
|
private
|
102
|
-
def
|
103
|
-
|
104
|
-
dimension_metric.prefer(u, options)
|
105
|
-
u
|
102
|
+
def unit(name, options = {})
|
103
|
+
Unit.register(name, context.system, context.dimension, options)
|
106
104
|
end
|
107
105
|
|
108
106
|
def dimension_metric
|
109
107
|
find_or_register_metric(self.class.dimension_default_metric_name(context.dimension), nil)
|
110
108
|
end
|
109
|
+
|
110
|
+
# Basic preferences for formatting and parsing the given unit
|
111
|
+
def default_preferences(u)
|
112
|
+
o = {}
|
113
|
+
o[:format] = u.dimension.nil? ? "%s %U" : "%s%U"
|
114
|
+
o[:detector] = /\A#{[u.name, u.abbreviation].compact.join('|')}\Z/
|
115
|
+
o
|
116
|
+
end
|
111
117
|
|
112
118
|
# Register the metric defined by the given key and the current context if it does not already exist.
|
113
119
|
def find_or_register_metric(name, parent = nil)
|
data/lib/dimensional/measure.rb
CHANGED
@@ -22,7 +22,7 @@ module Dimensional
|
|
22
22
|
units = metric.units
|
23
23
|
elements = str.to_s.scan(NUMERIC_REGEXP).map do |(v, us)|
|
24
24
|
units = units.select{|u| system == u.system} if system
|
25
|
-
unit = us.nil? ? units.first : units.detect{|u| u.match(us)}
|
25
|
+
unit = us.nil? ? units.first : units.detect{|u| metric.preferences(u)[:detector].match(us)}
|
26
26
|
raise ArgumentError, "Unit cannot be determined (#{us})" unless unit
|
27
27
|
system = unit.system
|
28
28
|
value = unit.dimension.nil? ? v.to_i : v.to_f
|
@@ -82,12 +82,8 @@ module Dimensional
|
|
82
82
|
convert(unit.base)
|
83
83
|
end
|
84
84
|
|
85
|
-
def native
|
86
|
-
metric.dimension ? to_f : to_i
|
87
|
-
end
|
88
|
-
|
89
85
|
def to_s
|
90
|
-
strfmeasure(metric.preferences(unit)[:format]
|
86
|
+
strfmeasure(metric.preferences(unit)[:format] || "%s%U")
|
91
87
|
end
|
92
88
|
|
93
89
|
# Like Date, Time and DateTime, Measure represents both a value and a context. Like those built-in classes,
|
@@ -97,25 +93,30 @@ module Dimensional
|
|
97
93
|
# In addition, this specifier supports the same width and precision modfiers as the '%s' specifier.
|
98
94
|
# For example: %#10.10U
|
99
95
|
# All other specifiers are applied to the numeric value of the measure.
|
100
|
-
# TODO: Support positional arguments (n$).
|
101
96
|
# TODO: Support modulo subordinate units with format hash -> {1 => "'", 12 => :inch} or {1 => "%d#", 16 => "%doz."}
|
102
|
-
def strfmeasure(format
|
97
|
+
def strfmeasure(format)
|
98
|
+
# We need the native value to prevent infinite recursion if the user specifies the %s specifier.
|
103
99
|
v = if precision = metric.preferences(unit)[:precision]
|
104
100
|
pfactor = 10**(-precision)
|
105
101
|
((self * pfactor).round / pfactor.to_f).to_s
|
106
102
|
else
|
107
103
|
native
|
108
104
|
end
|
109
|
-
format = format
|
110
|
-
|
111
|
-
|
112
|
-
Kernel.sprintf("%#{$2}s", arg)
|
105
|
+
format = format.gsub(/%(#)?([\d.\-\*]*)U/) do |s|
|
106
|
+
us = ($1) ? unit.name : (unit.abbreviation || unit.name)
|
107
|
+
Kernel.sprintf("%#{$2}s", us)
|
113
108
|
end
|
114
|
-
|
109
|
+
count = format.scan(/(?:\A|[^%])(%[^% ]*[A-Za-z])/).size
|
110
|
+
Kernel.sprintf(format, *Array.new(count, v))
|
115
111
|
end
|
116
112
|
|
117
113
|
def inspect
|
118
|
-
"
|
114
|
+
strfmeasure("<%p <%#U>>")
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
def native
|
119
|
+
metric.dimension ? to_f : to_i
|
119
120
|
end
|
120
121
|
end
|
121
122
|
end
|
data/lib/dimensional/system.rb
CHANGED
@@ -3,6 +3,8 @@ require 'delegate'
|
|
3
3
|
module Dimensional
|
4
4
|
# Represents a set of units for comprehensive measurement of physical quantities.
|
5
5
|
class System < DelegateClass(String)
|
6
|
+
PRIORITY = []
|
7
|
+
|
6
8
|
@registry = Hash.new
|
7
9
|
@abbreviation_registry = Hash.new
|
8
10
|
|
@@ -12,6 +14,7 @@ module Dimensional
|
|
12
14
|
raise "System #{s}'s abbreviation already exists" if @abbreviation_registry[s.abbreviation]
|
13
15
|
@registry[s.to_sym] = s
|
14
16
|
@abbreviation_registry[s.abbreviation.to_sym] = s if s.abbreviation
|
17
|
+
PRIORITY << s
|
15
18
|
const_set(s.abbreviation, s) rescue nil # Not all symbols strings are valid constant names
|
16
19
|
s
|
17
20
|
end
|
@@ -24,7 +27,8 @@ module Dimensional
|
|
24
27
|
|
25
28
|
# Purge all systems from storage.
|
26
29
|
def self.reset!
|
27
|
-
constants.each {|d| remove_const(d)}
|
30
|
+
constants.each {|d| remove_const(d) unless d == 'PRIORITY'}
|
31
|
+
PRIORITY.clear
|
28
32
|
@registry.clear
|
29
33
|
@abbreviation_registry.clear
|
30
34
|
end
|
data/lib/dimensional/unit.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'dimensional/dimension'
|
2
2
|
require 'dimensional/system'
|
3
3
|
require 'set'
|
4
|
-
require 'enumerator'
|
5
4
|
|
6
5
|
module Dimensional
|
7
6
|
# A standard scale unit for measuring physical quantities. In addition to the Dimension and System attribute
|
@@ -15,7 +14,7 @@ module Dimensional
|
|
15
14
|
def self.register(*args)
|
16
15
|
u = new(*args)
|
17
16
|
raise "Namespace collision: #{u.dimension}:#{u.system}:#{u.name}" if self[u.dimension, u.system, u.name.to_sym]
|
18
|
-
raise "Namespace collision: #{u.dimension}:#{u.system}:#{u.abbreviation}" if self[u.dimension, u.system, u.abbreviation.to_sym]
|
17
|
+
raise "Namespace collision: #{u.dimension}:#{u.system}:#{u.abbreviation}" if self[u.dimension, u.system, u.abbreviation.to_sym] if u.abbreviation
|
19
18
|
@store << u
|
20
19
|
u
|
21
20
|
end
|
@@ -25,14 +24,15 @@ module Dimensional
|
|
25
24
|
dim = Dimension[dim] unless dim.kind_of?(Dimension)
|
26
25
|
sys = System[sys] unless sys.kind_of?(System)
|
27
26
|
sym = sym.to_sym
|
28
|
-
@store.select{|u| u.dimension == dim}.select{|u| u.system == sys}
|
27
|
+
us = @store.select{|u| u.dimension == dim}.select{|u| u.system == sys}
|
28
|
+
us.detect{|u| sym == u.name.to_sym || (u.abbreviation && sym == u.abbreviation.to_sym)}
|
29
29
|
end
|
30
30
|
|
31
31
|
def self.reset!
|
32
32
|
@store.clear
|
33
33
|
end
|
34
34
|
|
35
|
-
attr_reader :name, :abbreviation
|
35
|
+
attr_reader :name, :abbreviation
|
36
36
|
attr_reader :system, :dimension
|
37
37
|
attr_reader :reference_factor, :reference_unit
|
38
38
|
|
@@ -42,13 +42,7 @@ module Dimensional
|
|
42
42
|
@dimension = dimension
|
43
43
|
@reference_factor = options[:reference_factor]
|
44
44
|
@reference_unit = options[:reference_unit]
|
45
|
-
@
|
46
|
-
@abbreviation = (options[:abbreviation] || self.name).to_s
|
47
|
-
@format = options[:format] || dimension.nil? ? "%s %U" : "%s%U"
|
48
|
-
end
|
49
|
-
|
50
|
-
def match(s)
|
51
|
-
@detector.match(s)
|
45
|
+
@abbreviation = options[:abbreviation]
|
52
46
|
end
|
53
47
|
|
54
48
|
# If no reference was provided during initialization, this unit must itself be a base unit.
|
data/test/configurator_test.rb
CHANGED
@@ -66,7 +66,7 @@ class ConfiguratorTest < Test::Unit::TestCase
|
|
66
66
|
system(:SI) do
|
67
67
|
base('meter') do
|
68
68
|
test_context.assert uc = context.unit
|
69
|
-
derive('centimeter', 1e-2)
|
69
|
+
derive('centimeter', 'cm', 1e-2)
|
70
70
|
test_context.assert_same uc, context.unit
|
71
71
|
end
|
72
72
|
end
|
@@ -76,19 +76,21 @@ class ConfiguratorTest < Test::Unit::TestCase
|
|
76
76
|
|
77
77
|
def test_build_base_unit
|
78
78
|
Configurator.start(:system => System::SI, :dimension => Dimension::L) do
|
79
|
-
base('meter', :detector => /\A(meters?|m)\Z
|
79
|
+
base('meter', 'm', :detector => /\A(meters?|m)\Z/)
|
80
80
|
end
|
81
81
|
assert_instance_of Unit, u = Unit[Dimension::L, System::SI, 'meter']
|
82
82
|
assert_same System::SI, u.system
|
83
83
|
assert_same Dimension::L, u.dimension
|
84
84
|
assert u.base?
|
85
|
-
|
85
|
+
assert_equal 'm', u.abbreviation
|
86
|
+
assert_instance_of Metric, m = Metric[:L]
|
87
|
+
assert m.preferences(u)[:detector]
|
86
88
|
end
|
87
89
|
|
88
90
|
def test_build_derived_unit
|
89
91
|
Configurator.start(:system => System::SI, :dimension => Dimension::L) do
|
90
|
-
base('meter', :detector => /\A(meters?|m)\Z
|
91
|
-
derive('centimeter', 1e-2, :detector => /\A(centimeters?|cm)\Z
|
92
|
+
base('meter', 'm', :detector => /\A(meters?|m)\Z/) do
|
93
|
+
derive('centimeter', 'cm', 1e-2, :detector => /\A(centimeters?|cm)\Z/)
|
92
94
|
end
|
93
95
|
end
|
94
96
|
u0 = Unit[Dimension::L, System::SI, 'meter']
|
@@ -98,12 +100,11 @@ class ConfiguratorTest < Test::Unit::TestCase
|
|
98
100
|
assert_same u0, u.base
|
99
101
|
assert_equal 1E-2, u.factor
|
100
102
|
assert_equal 'cm', u.abbreviation
|
101
|
-
assert u.match("centimeters")
|
102
103
|
end
|
103
104
|
|
104
105
|
def test_build_aliased_unit
|
105
106
|
Configurator.start(:system => System::SI, :dimension => Dimension::L) do
|
106
|
-
base('meter', :detector => /\A(meters?|m)\Z
|
107
|
+
base('meter', 'm', :detector => /\A(meters?|m)\Z/) do
|
107
108
|
self.alias('decadecimeter')
|
108
109
|
end
|
109
110
|
end
|
@@ -117,9 +118,9 @@ class ConfiguratorTest < Test::Unit::TestCase
|
|
117
118
|
|
118
119
|
def test_build_referenced_unit
|
119
120
|
Configurator.start(:system => System::SI, :dimension => Dimension::L) do
|
120
|
-
base('meter', :detector => /\A(meters?|m)\Z
|
121
|
+
base('meter', 'm', :detector => /\A(meters?|m)\Z/)
|
121
122
|
system(:US) do
|
122
|
-
reference('yard', Unit[:L, :SI, 'meter'], 0.9144, :detector => /\A(yards?|yds?)\Z
|
123
|
+
reference('yard', 'yd', Unit[:L, :SI, 'meter'], 0.9144, :detector => /\A(yards?|yds?)\Z/)
|
123
124
|
end
|
124
125
|
end
|
125
126
|
u0 = Unit[Dimension::L, System::SI, 'meter']
|
@@ -130,11 +131,11 @@ class ConfiguratorTest < Test::Unit::TestCase
|
|
130
131
|
|
131
132
|
def test_build_combined_unit
|
132
133
|
Configurator.start(:system => System::SI, :dimension => Dimension::L) do
|
133
|
-
base('meter', :detector => /\A(meters?|m)\Z
|
134
|
+
base('meter', 'm', :detector => /\A(meters?|m)\Z/)
|
134
135
|
system(:US) do
|
135
|
-
reference('yard', Unit[:L, :SI, 'meter'], 0.9144, :detector => /\A(yards?|yds?)\Z
|
136
|
+
reference('yard', 'yd', Unit[:L, :SI, 'meter'], 0.9144, :detector => /\A(yards?|yds?)\Z/)
|
136
137
|
dimension(:A) do
|
137
|
-
combine('square yard', [Unit[:L, :US, 'yard'], Unit[:L, :US, 'yard']], :detector =>
|
138
|
+
combine('square yard', 'yd2', [Unit[:L, :US, 'yard'], Unit[:L, :US, 'yard']], :detector => /\A(yd|yard)2\Z/)
|
138
139
|
end
|
139
140
|
end
|
140
141
|
end
|
@@ -145,9 +146,20 @@ class ConfiguratorTest < Test::Unit::TestCase
|
|
145
146
|
assert_equal [u1.base, u1.base], u.base
|
146
147
|
end
|
147
148
|
|
149
|
+
def test_add_default_preferences
|
150
|
+
Configurator.start(:system => System::SI, :dimension => Dimension::L) do
|
151
|
+
base('meter', 'm')
|
152
|
+
end
|
153
|
+
u = Unit[Dimension::L, System::SI, 'meter']
|
154
|
+
m = Metric[:L]
|
155
|
+
assert d = m.preferences(u)[:detector]
|
156
|
+
assert_match d, 'meter'
|
157
|
+
assert f = m.preferences(u)[:format]
|
158
|
+
end
|
159
|
+
|
148
160
|
def test_register_metric_options
|
149
161
|
Configurator.start(:system => System::SI, :dimension => Dimension::L) do
|
150
|
-
base('meter', :detector => /\A(meters?|m)\Z
|
162
|
+
base('meter', 'm', :detector => /\A(meters?|m)\Z/) do
|
151
163
|
prefer(:length_over_all, :precision => 0.01)
|
152
164
|
end
|
153
165
|
end
|
data/test/demo.rb
CHANGED
@@ -20,75 +20,75 @@ Dimensional::System.register('British Imperial (lbs, ton, ft)', 'Imp') # http:/
|
|
20
20
|
Dimensional::Configurator.start do
|
21
21
|
dimension(:L) do
|
22
22
|
system(:SI) do
|
23
|
-
base('meter', :detector => /\A(meters?|m)\Z
|
24
|
-
derive('centimeter',
|
25
|
-
derive('kilometer',
|
23
|
+
base('meter', 'm', :detector => /\A(meters?|m)\Z/) do
|
24
|
+
derive('centimeter', 'cm', Rational(1, 100), :detector => /\A(centimeters?|cm)\Z/)
|
25
|
+
derive('kilometer', 'km', 1000, :detector => /\A(kilometers?|km)\Z/)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
system(:US) do # As of 1 July 1959 (http://en.wikipedia.org/wiki/United_States_customary_units#Units_of_length)
|
29
|
-
reference('yard', Dimensional::Unit[:L, :SI, 'meter'], 0.9144, :detector => /\A(yards?|yds?)\Z
|
30
|
-
derive('foot', Rational(1,3), :detector => /\A(foot|feet|ft|')\Z/, :
|
29
|
+
reference('yard', 'yd', Dimensional::Unit[:L, :SI, 'meter'], 0.9144, :detector => /\A(yards?|yds?)\Z/) do
|
30
|
+
derive('foot', 'ft', Rational(1,3), :detector => /\A(foot|feet|ft|')\Z/, :format => "%p'") do
|
31
31
|
prefer(:hull)
|
32
|
-
derive('inch', Rational(1,12), :detector => /\A(inch|inches|in|")\Z/, :
|
32
|
+
derive('inch', 'in', Rational(1,12), :detector => /\A(inch|inches|in|")\Z/, :format => "%p\"")
|
33
33
|
end
|
34
|
-
derive('furlong', 220, :detector => /\A(furlongs?)\Z/) do
|
35
|
-
derive('mile', 8, :detector => /\Amiles?\Z
|
34
|
+
derive('furlong', nil, 220, :detector => /\A(furlongs?)\Z/) do
|
35
|
+
derive('mile', 'mi', 8, :detector => /\Amiles?\Z/)
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
40
40
|
dimension(:M) do
|
41
41
|
system(:SI) do
|
42
|
-
base('kilogram', :detector => /\A(kilograms?|kg)\Z
|
43
|
-
derive('tonne',
|
42
|
+
base('kilogram', 'kg', :detector => /\A(kilograms?|kg)\Z/) do
|
43
|
+
derive('tonne', 't', 1000, :detector => /\A(tonnes?)\Z/) do # metric ton
|
44
44
|
prefer(:displacement)
|
45
45
|
end
|
46
|
-
derive('gram',
|
46
|
+
derive('gram', 'g', Rational(1, 1000), :detector => /\A(grams?|g)\Z/)
|
47
47
|
end
|
48
48
|
end
|
49
49
|
system(:US) do # Common units for mass and, occasionally, force/weight (http://en.wikipedia.org/wiki/United_States_customary_units#Units_of_mass)
|
50
|
-
reference('pound', Dimensional::Unit[:M, :SI, 'gram'], 453.59237, :detector => /\A(pounds?|lbs?|#)\Z
|
51
|
-
derive('hundredweight', 100, :detector => /\A(hundredweights?|cwt)\Z
|
52
|
-
derive('ton', 20, :detector => /\A(tons?|t)\Z
|
50
|
+
reference('pound', 'lb', Dimensional::Unit[:M, :SI, 'gram'], 453.59237, :detector => /\A(pounds?|lbs?|#)\Z/) do # avoirdupois
|
51
|
+
derive('hundredweight', 'cwt', 100, :detector => /\A(hundredweights?|cwt)\Z/) do
|
52
|
+
derive('ton', 't', 20, :detector => /\A(tons?|t)\Z/) do # short ton
|
53
53
|
prefer(:displacement)
|
54
54
|
end
|
55
55
|
end
|
56
|
-
derive('
|
57
|
-
|
58
|
-
|
59
|
-
end
|
56
|
+
derive('ounce', 'oz', Rational(1, 16), :detector => /\A(ounces?|ozs?)\Z/)
|
57
|
+
derive('grain', 'gr', Rational(1, 7000), :detector => /\A(grains?|gr)\Z/) do
|
58
|
+
derive('dram', 'dr', 27 + Rational(11, 32), :detector => /\A(drams?|dr)\Z/)
|
60
59
|
end
|
61
60
|
end
|
62
61
|
end
|
63
62
|
system(:Imp) do
|
64
|
-
reference('pound', Dimensional::Unit[:M, :SI, 'gram'], 453.59237, :detector => /\A(pounds?|lbs?|#)\Z
|
65
|
-
derive('grain',
|
66
|
-
derive('drachm',
|
67
|
-
derive('ounce',
|
68
|
-
derive('stone', 14, :detector => /\A(stones?)\Z/)
|
69
|
-
derive('quarter', 28, :detector => /\A(quarters?)\Z/)
|
70
|
-
derive('hundredweight', 112, :detector => /\A(hundredweights?|cwt)\Z
|
71
|
-
derive('ton', 2240, :detector => /\A(tons?|t)\Z
|
63
|
+
reference('pound', 'lb', Dimensional::Unit[:M, :SI, 'gram'], 453.59237, :detector => /\A(pounds?|lbs?|#)\Z/) do
|
64
|
+
derive('grain', 'gr', Rational(1, 7000), :detector => /\A(grains?|gr)\Z/)
|
65
|
+
derive('drachm', 'dr', Rational(1, 256), :detector => /\A(drachms?|dr)\Z/)
|
66
|
+
derive('ounce', 'oz', Rational(1, 16), :detector => /\A(ounces?|ozs?)\Z/)
|
67
|
+
derive('stone', nil, 14, :detector => /\A(stones?)\Z/)
|
68
|
+
derive('quarter', nil, 28, :detector => /\A(quarters?)\Z/)
|
69
|
+
derive('hundredweight', 'cwt', 112, :detector => /\A(hundredweights?|cwt)\Z/)
|
70
|
+
derive('ton', 't', 2240, :detector => /\A(tons?|t)\Z/) do # long ton
|
72
71
|
prefer(:displacement)
|
73
72
|
end
|
74
73
|
end
|
75
74
|
end
|
76
75
|
end
|
76
|
+
|
77
77
|
dimension(:A) do
|
78
78
|
system(:SI) do
|
79
|
-
combine('square meter', %w(meter meter).map{|name| Dimensional::Unit[:L, :SI, name]}, :detector => /\A(sq\.?\s?meters?|m2)\Z
|
80
|
-
derive('hectare', 10000, :format => "%.4f%U"
|
79
|
+
combine('square meter', 'm2', %w(meter meter).map{|name| Dimensional::Unit[:L, :SI, name]}, :detector => /\A(sq\.?\s?meters?|m2)\Z/) do
|
80
|
+
derive('hectare', 'ha', 10000, :format => "%.4f%U") do
|
81
81
|
prefer(:forestry, :precision => -4, :format => "%s%U")
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
85
85
|
system(:US) do # All measures below are approximations due to the difference between a survey foot and an international foot.
|
86
|
-
combine('square yard', %w(yard yard).map{|name| Dimensional::Unit[:L, :US, name]}, :detector => /yd2
|
87
|
-
derive('acre', 4840
|
86
|
+
combine('square yard', 'yd2', %w(yard yard).map{|name| Dimensional::Unit[:L, :US, name]}, :detector => /yd2/) do
|
87
|
+
derive('acre', nil, 4840)
|
88
88
|
end
|
89
|
-
combine('square mile', %w(mile mile).map{|name| Dimensional::Unit[:L, :US, name]}, :detector => /\A(sq(uare|\.)?\s?miles?)\Z/) do
|
90
|
-
self.alias('section', :detector => /\Asections?\Z/) do
|
91
|
-
derive('township', 36, :detector => /\Atownships?\Z/)
|
89
|
+
combine('square mile', nil, %w(mile mile).map{|name| Dimensional::Unit[:L, :US, name]}, :detector => /\A(sq(uare|\.)?\s?miles?)\Z/) do
|
90
|
+
self.alias('section', nil, :detector => /\Asections?\Z/) do
|
91
|
+
derive('township', 'twp', 36, :detector => /\Atownships?\Z/)
|
92
92
|
end
|
93
93
|
end
|
94
94
|
end
|
@@ -96,16 +96,16 @@ Dimensional::Configurator.start do
|
|
96
96
|
|
97
97
|
dimension(:V) do
|
98
98
|
system(:SI) do
|
99
|
-
combine('cubic meter', %w(meter meter meter).map{|name| Dimensional::Unit[:L, :SI, name]}, :detector => /\A(cubic meters?|m3)\Z
|
100
|
-
derive('cubic decimeter',
|
101
|
-
self.alias('liter', :detector => /\A(liters?|l|L)\Z
|
102
|
-
derive('milliliter',
|
99
|
+
combine('cubic meter', 'm3', %w(meter meter meter).map{|name| Dimensional::Unit[:L, :SI, name]}, :detector => /\A(cubic meters?|m3)\Z/) do
|
100
|
+
derive('cubic decimeter', 'dm3', Rational(1, 1000), :detector => /\A(cubic decimeters?|dm3)\Z/) do
|
101
|
+
self.alias('liter', 'l', :detector => /\A(liters?|l|L)\Z/) do
|
102
|
+
derive('milliliter', 'ml', Rational(1, 1000), :detector => /\A(milliliters?|ml|mL)\Z/)
|
103
103
|
end
|
104
104
|
end
|
105
105
|
end
|
106
106
|
end
|
107
107
|
system(:Imp) do
|
108
|
-
reference('ounce', Dimensional::Unit[:V, :SI, 'milliliter'], 28.4130625, :detector => /\A((fluid )?ounces?|oz)\Z
|
108
|
+
reference('ounce', 'fl oz', Dimensional::Unit[:V, :SI, 'milliliter'], 28.4130625, :detector => /\A((fluid )?ounces?|oz)\Z/)
|
109
109
|
# register :ounce, :conversion => [28.4130625, :milliliter], :detector => /\A(imperial\s(fluid )?imp\.\sounces?|imp\.\soz)\Z/, :abbreviation => "imp. oz"
|
110
110
|
# register :gill, :conversion => [5, :ounce], :detector => /\A(gills?|gi)\Z/, :abbreviation => "gi"
|
111
111
|
# register :cup, :conversion => [2, :gill], :detector => /\A(cups?)\Z/, :abbreviation => "cp"
|
@@ -128,12 +128,12 @@ Dimensional::Configurator.start do
|
|
128
128
|
|
129
129
|
dimension(nil) do
|
130
130
|
system(:US) do
|
131
|
-
base('each', :detector => /\Aea(ch)?\Z
|
132
|
-
derive('pair', 2, :detector => /\A(pr|pair)\Z
|
133
|
-
derive('dozen', 12, :detector => /\A(dz|dozen)\Z
|
134
|
-
derive('gross', 12)
|
131
|
+
base('each', 'ea', :detector => /\Aea(ch)?\Z/) do
|
132
|
+
derive('pair', 'pr', 2, :detector => /\A(pr|pair)\Z/)
|
133
|
+
derive('dozen', 'dz', 12, :detector => /\A(dz|dozen)\Z/) do
|
134
|
+
derive('gross', nil, 12)
|
135
135
|
end
|
136
|
-
derive('score', 20)
|
136
|
+
derive('score', nil, 20)
|
137
137
|
end
|
138
138
|
end
|
139
139
|
end
|
data/test/measure_test.rb
CHANGED
@@ -19,32 +19,32 @@ class MeasureTest < Test::Unit::TestCase
|
|
19
19
|
Configurator.start do
|
20
20
|
dimension(:L) do
|
21
21
|
system(:SI) do
|
22
|
-
base('meter', :detector => /\A(meters?|m)\Z
|
22
|
+
base('meter', 'm', :detector => /\A(meters?|m)\Z/) do
|
23
23
|
prefer(:length_over_all, :precision => 0.01)
|
24
|
-
derive('centimeter', 1e-2, :detector => /\A(centimeters?|cm)\Z
|
25
|
-
derive('kilometer', 1e3, :detector => /\A(kilometers?|km)\Z
|
24
|
+
derive('centimeter', 'cm', 1e-2, :detector => /\A(centimeters?|cm)\Z/)
|
25
|
+
derive('kilometer', 'km', 1e3, :detector => /\A(kilometers?|km)\Z/)
|
26
26
|
end
|
27
27
|
end
|
28
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
|
30
|
-
derive('foot', Rational(1,3), :detector => /\A(foot|feet|ft|')\Z/, :
|
29
|
+
reference('yard', 'yd', Unit[:L, :SI, 'meter'], 0.9144, :detector => /\A(yards?|yds?)\Z/) do
|
30
|
+
derive('foot', 'ft', Rational(1,3), :detector => /\A(foot|feet|ft|')\Z/, :format => "%p'") do
|
31
31
|
prefer(:length_over_all, :precision => Rational(1, 12))
|
32
|
-
derive('inch', Rational(1,12), :detector => /\A(inch|inches|in|")\Z/, :
|
32
|
+
derive('inch', 'in', Rational(1,12), :detector => /\A(inch|inches|in|")\Z/, :format => "%p\"")
|
33
33
|
end
|
34
|
-
derive('furlong', 220, :detector => /\A(furlongs?)\Z/) do
|
35
|
-
derive('mile', 8, :detector => /\Amiles?\Z
|
34
|
+
derive('furlong', nil, 220, :detector => /\A(furlongs?)\Z/) do
|
35
|
+
derive('mile', 'mi', 8, :detector => /\Amiles?\Z/)
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
39
39
|
system(:BA) do
|
40
|
-
base('mile', :detector => /\A(miles?|nm|nmi)\Z
|
40
|
+
base('mile', 'nm', :detector => /\A(miles?|nm|nmi)\Z/) do
|
41
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
|
44
|
-
derive('yard', Rational(1,6), :detector => /\A(yards?|yds?)\Z
|
45
|
-
derive('foot', Rational(1,3), :detector => /\A(foot|feet|ft|')\Z
|
42
|
+
derive('cable', nil, Rational(1,10), :detector => /\A(cables?|cbls?)\Z/) do
|
43
|
+
derive('fathom', 'fm', Rational(1,10), :detector => /\A(fathoms?|fms?)\Z/) do
|
44
|
+
derive('yard', 'yd', Rational(1,6), :detector => /\A(yards?|yds?)\Z/) do
|
45
|
+
derive('foot', 'ft', Rational(1,3), :detector => /\A(foot|feet|ft|')\Z/) do
|
46
46
|
prefer(:length_over_all, :precision => Rational(1, 12))
|
47
|
-
derive('inch', Rational(1,12), :detector => /\A(inch|inches|in|")\Z
|
47
|
+
derive('inch', 'in', Rational(1,12), :detector => /\A(inch|inches|in|")\Z/)
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
@@ -54,15 +54,15 @@ class MeasureTest < Test::Unit::TestCase
|
|
54
54
|
end
|
55
55
|
dimension(:M) do
|
56
56
|
system(:SI) do
|
57
|
-
base('kilogram', :detector => /\A(kilograms?|kg)\Z
|
58
|
-
derive('tonne', 1000, :detector => /\A(tonnes?)\Z
|
59
|
-
derive('gram', Rational(1, 1000), :detector => /\A(grams?|g)\Z
|
57
|
+
base('kilogram', 'kg', :detector => /\A(kilograms?|kg)\Z/) do
|
58
|
+
derive('tonne', 't', 1000, :detector => /\A(tonnes?)\Z/) # metric ton
|
59
|
+
derive('gram', 'g', Rational(1, 1000), :detector => /\A(grams?|g)\Z/)
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
63
63
|
# Dimensionless Units
|
64
|
-
base('each',
|
65
|
-
derive('dozen',
|
64
|
+
base('each', 'ea') do
|
65
|
+
derive('dozen', 'dz', 12)
|
66
66
|
end
|
67
67
|
end
|
68
68
|
end
|
@@ -92,11 +92,6 @@ class MeasureTest < Test::Unit::TestCase
|
|
92
92
|
assert_instance_of Fixnum, d.to_i
|
93
93
|
end
|
94
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
95
|
def test_convert
|
101
96
|
old_unit = Unit[:L, :BA, 'cable']
|
102
97
|
new_unit = Unit[:L, :BA, 'fathom']
|
@@ -219,6 +214,11 @@ class MeasureTest < Test::Unit::TestCase
|
|
219
214
|
assert_equal "15.25 (ft)", m.strfmeasure("%4.2f (%U)")
|
220
215
|
end
|
221
216
|
|
217
|
+
def test_format_output_with_multiple_substitutions
|
218
|
+
m = Measure.parse("15'4\"", :L, :BA)
|
219
|
+
assert_equal "15.33 (ft)\t%\t<15.3333333ft>", m.strfmeasure("%4.2f (%U)\t%%\t<%.10s%U>")
|
220
|
+
end
|
221
|
+
|
222
222
|
def test_precision_recognition
|
223
223
|
assert_equal "1.8600nm", Measure.parse('1.8565454 miles', :distance, :BA).strfmeasure("%.4f%U")
|
224
224
|
assert_equal "1.86", Measure.parse('1.8565454 miles', :distance, :BA).strfmeasure("%s")
|
data/test/unit_test.rb
CHANGED
@@ -77,13 +77,6 @@ class UnitTest < Test::Unit::TestCase
|
|
77
77
|
assert_equal 1, fathom.convert(fathom)
|
78
78
|
end
|
79
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
80
|
def test_identify_commensurable_units
|
88
81
|
u0 = Unit.new('mile', System::BA, Dimension::L, :detector => /\A(nm|nmi)\Z/, :abbreviation => 'nm')
|
89
82
|
u1 = Unit.new('cable', System::BA, Dimension::L, :detector => /\A(cables?|cbls?)\Z/, :reference_factor => 1E-1, :reference_unit => u0)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dimensional
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Hapgood
|
@@ -22,6 +22,7 @@ extensions: []
|
|
22
22
|
extra_rdoc_files: []
|
23
23
|
|
24
24
|
files:
|
25
|
+
- lib/dimensional/configuration.rb
|
25
26
|
- lib/dimensional/configurator.rb
|
26
27
|
- lib/dimensional/dimension.rb
|
27
28
|
- lib/dimensional/measure.rb
|