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 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.4"
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
@@ -4,5 +4,5 @@ require 'dimensional/unit'
4
4
  require 'dimensional/measure'
5
5
 
6
6
  module Dimensional
7
- VERSION = "0.0.4"
7
+ VERSION = "0.0.5"
8
8
  end
@@ -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 = register_unit(name, options)
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
- options[:reference_factor] = factor
67
- options[:reference_unit] = context.unit
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, reference, factor, options = {}, &block)
79
- options.merge!(:reference_factor => factor, :reference_unit => reference)
80
- u = register_unit(name, options)
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
- options.merge!(:reference_factor => 1, :reference_unit => components)
87
- u = register_unit(name, options)
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 register_unit(name, options)
103
- u = Unit.register(name, context.system, context.dimension, options)
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)
@@ -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]) rescue super
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 = nil, *args)
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 || unit.format
110
- format.gsub!(/%(#)?([\d.\-\*]*)U/) do |s|
111
- arg = ($1) ? unit.name : unit.abbreviation
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
- Kernel.sprintf(format, v, *args)
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
- "#{super} : #{unit.inspect}"
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
@@ -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
@@ -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}.detect{|u| sym == u.abbreviation.to_sym || sym == u.name.to_sym}
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, :format
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
- @detector = options[:detector] || /\A#{self.name}\Z/
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.
@@ -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/, :abbreviation => 'm')
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
- assert_instance_of Metric, Metric[:L]
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/, :abbreviation => 'm') do
91
- derive('centimeter', 1e-2, :detector => /\A(centimeters?|cm)\Z/, :abbreviation => 'cm')
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/, :abbreviation => 'm') do
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/, :abbreviation => 'm')
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/, :abbreviation => 'yd')
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/, :abbreviation => 'm')
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/, :abbreviation => 'yd')
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 => //, :abbreviation => 'yd2')
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/, :abbreviation => 'm') do
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/, :abbreviation => 'm') do
24
- derive('centimeter', 1e-2, :detector => /\A(centimeters?|cm)\Z/, :abbreviation => 'cm')
25
- derive('kilometer', 1e3, :detector => /\A(kilometers?|km)\Z/, :abbreviation => 'km')
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/, :abbreviation => 'yd') do
30
- derive('foot', Rational(1,3), :detector => /\A(foot|feet|ft|')\Z/, :abbreviation => "ft", :format => "%p'") do
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/, :abbreviation =>"in", :format => "%p\"")
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/, :abbreviation => 'mi')
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/, :abbreviation => 'kg') do
43
- derive('tonne', 1e3, :detector => /\A(tonnes?)\Z/, :abbreviation => 't') do # metric ton
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', 1e-3, :detector => /\A(grams?|g)\Z/, :abbreviation => 'g')
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/, :abbreviation => 'lb') do # avoirdupois
51
- derive('hundredweight', 100, :detector => /\A(hundredweights?|cwt)\Z/, :abbreviation => 'cwt') do
52
- derive('ton', 20, :detector => /\A(tons?|t)\Z/, :abbreviation => 't') do # short ton
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('grain', 7000**-1, :detector => /\A(grains?|gr)\Z/, :abbreviation => 'gr') do
57
- derive('dram', 27 + Rational(11, 32), :detector => /\A(drams?|dr)\Z/, :abbreviation => 'dr') do
58
- derive('ounce', :detector => /\A(ounces?|ozs?)\Z/, :conversion => [437.5, :grain], :abbreviation => 'oz')
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/, :abbreviation => 'lb') do
65
- derive('grain', 7000**-1, :detector => /\A(grains?|gr)\Z/, :abbreviation => 'gr')
66
- derive('drachm', 256**-1, :detector => /\A(drachms?|dr)\Z/, :abbreviation => 'dr')
67
- derive('ounce', 16**-1, :detector => /\A(ounces?|ozs?)\Z/, :abbreviation => 'oz')
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/, :abbreviation => 'cwt')
71
- derive('ton', 2240, :detector => /\A(tons?|t)\Z/, :abbreviation => 't') do # long ton
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/, :abbreviation => 'm2') do
80
- derive('hectare', 10000, :format => "%.4f%U", :abbreviation => 'ha') do
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/, :abbreviation => 'yd2') do
87
- derive('acre', 4840.0)
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/, :abbreviation => "m3") do
100
- derive('cubic decimeter', 1e-3, :detector => /\A(cubic decimeters?|dm3)\Z/, :abbreviation => "dm3") do
101
- self.alias('liter', :detector => /\A(liters?|l|L)\Z/, :abbreviation => "l") do
102
- derive('milliliter', 1E-3, :detector => /\A(milliliters?|ml|mL)\Z/, :abbreviation => "ml")
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/, :abbreviation => "fl oz")
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/, :abbreviation => 'ea') do
132
- derive('pair', 2, :detector => /\A(pr|pair)\Z/, :abbreviation => 'pr')
133
- derive('dozen', 12, :detector => /\A(dz|dozen)\Z/, :abbreviation => 'dz') do
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/, :abbreviation => 'm') do
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/, :abbreviation => 'cm')
25
- derive('kilometer', 1e3, :detector => /\A(kilometers?|km)\Z/, :abbreviation => 'km')
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/, :abbreviation => 'yd') do
30
- derive('foot', Rational(1,3), :detector => /\A(foot|feet|ft|')\Z/, :abbreviation => "ft", :format => "%p'") do
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/, :abbreviation =>"in", :format => "%p\"")
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/, :abbreviation => 'mi')
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/, :abbreviation => 'nm') do
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/, :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
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/, :abbreviation => "in")
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/, :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')
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', :abbreviation => 'ea') do
65
- derive('dozen', 12, :abbreviation => 'dz')
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
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