dimensional 0.0.4 → 0.0.5
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/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
|