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 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