ruby-measurement 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .idea
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in measurement.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Matt Huggins
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,153 @@
1
+ # Measurement
2
+
3
+ [ruby-measurement](https://github.com/mhuggins/ruby-measurement) is a simple
4
+ Ruby gem for calculating and converting units of measure.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'ruby-measurement'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install ruby-measurement
19
+
20
+ ## Usage
21
+
22
+ The `Measurement` class is responsible for parsing strings to determine the
23
+ quantity entered as well as the unit of measure. This can be done through the
24
+ `parse` method.
25
+
26
+ Measurement.parse('3 feet') # => 3.0 ft.
27
+ Measurement.parse('25 fl oz') # => 25.0 fl. oz.
28
+ Measurement.parse('12 tonnes') # => 12.0 t
29
+ Measurement.parse('25 "') # => 25.0 in.
30
+
31
+ The object returned by `Measurement.parse` is of type `Measurement`.
32
+
33
+ m = Measurement.parse('12 yd') # => 12.0 yd.
34
+ Measurement.quantity # => 12.0
35
+ Measurement.unit # => yd.
36
+
37
+ The object returned by `Measurement#unit` is of type `Measurement::Unit`.
38
+
39
+ u = Measurement.unit # => yd.
40
+ u.name # => "yd."
41
+ u.aliases # => ["yd.", "yd", "yard", "yards"]
42
+
43
+ ## Converting units
44
+
45
+ This gem allows you to convert among compatible units as long as a conversion
46
+ has been supplied when defining a unit. The default supplied units include
47
+ conversions among the same unit types (e.g.: converting feet to yards or meters
48
+ to kilometers).
49
+
50
+ m = Measurement.parse('3 feet') # => 3.0 ft.
51
+ m.convert_to(:yards) # => 1.0 yd.
52
+ m.convert_to(:in) # => 36.0 in.
53
+ m.convert_to(:inches) # => 36.0 in.
54
+
55
+ NOTE: Converting between metric and U.S. customary systems is currently not
56
+ included by default. It is intended to be shipped in a future release.
57
+
58
+ ## Calculations
59
+
60
+ This gem allows you to add, subtract, multiply, or divide measurements that can
61
+ be converted into one-another.
62
+
63
+ m1 = Measurement.parse('3 feet') # => 3.0 ft.
64
+ m2 = Measurement.parse('6 inch') # => 6.0 in.
65
+ m1 + m2 # => 3.5 ft.
66
+
67
+ Additionally, measurements can have basic math operations performed using basic
68
+ numeric values.
69
+
70
+ m = Measurement.parse('2 yards') # => 2.0 yd.
71
+ m * 6 # => 12.0 yd.
72
+ m / 5 # => 0.4 yd.
73
+ m + 3 # => 5.0 yd.
74
+ m - 1 # => 1.0 yd.
75
+ m ** 2 # => 4.0 yd.
76
+
77
+ ## Specifying units
78
+
79
+ By default, ruby-measurement ships with common areas, lengths, volumes, and
80
+ weights/masses for the metric and U.S. customary systems. This happens
81
+ automatically when requiring the gem in the following manner.
82
+
83
+ require 'ruby-measurement'
84
+
85
+ To include just one of these systems of measure, require the gem in per the
86
+ following.
87
+
88
+ require 'ruby-measurement/measurement'
89
+
90
+ # Metric units/conversions
91
+ require 'ruby-measurement/definitions/metric'
92
+
93
+ # U.S. customary units/conversions
94
+ require 'ruby-measurement/definitions/us_customary'
95
+
96
+ Additionally, specific categories of units of measure can be included per
97
+ system.
98
+
99
+ require 'ruby-measurement/measurement'
100
+
101
+ # Metric units/conversions
102
+ require 'ruby-measurement/definitions/metric/area'
103
+ require 'ruby-measurement/definitions/metric/length'
104
+ require 'ruby-measurement/definitions/metric/volume'
105
+ require 'ruby-measurement/definitions/metric/weight'
106
+
107
+ # U.S. customary units/conversions
108
+ require 'ruby-measurement/definitions/us_customary/area'
109
+ require 'ruby-measurement/definitions/us_customary/length'
110
+ require 'ruby-measurement/definitions/us_customary/volume'
111
+ require 'ruby-measurement/definitions/us_customary/weight'
112
+
113
+ ## Defining custom units & conversions
114
+
115
+ This gem also enabled you to define units of measure that aren't included by
116
+ default.
117
+
118
+ Measurement.define(:day) do |unit|
119
+ unit.alias :days
120
+ unit.convert_to(:week) { |value| value / 7.0 }
121
+ unit.convert_to(:year) { |value| value / 365.0 }
122
+ end
123
+
124
+ Measurement.define(:wk) do |unit|
125
+ unit.alias :week, :weeks
126
+ unit.convert_to(:day) { |value| value * 7.0 }
127
+ unit.convert_to(:year) { |value| value / 52.0 }
128
+ end
129
+
130
+ Measurement.define(:yr) do |unit|
131
+ unit.alias :year, :years
132
+ unit.convert_to(:day) { |value| value * 365.0 }
133
+ unit.convert_to(:week) { |value| value * 52.0 }
134
+ end
135
+
136
+ Note that the first value passed to `Measurement.define` is the unit format
137
+ that will be used when displaying a measurement.
138
+
139
+ Measurement.parse('3 yr') # => 3.0 yr
140
+ Measurement.parse('3 year') # => 3.0 yr
141
+ Measurement.parse('3 years') # => 3.0 yr
142
+
143
+ ## Contributing
144
+
145
+ 1. Fork it
146
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
147
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
148
+ 4. Push to the branch (`git push origin my-new-feature`)
149
+ 5. Create new Pull Request
150
+
151
+ ## License
152
+
153
+ ruby-measurement is released under the [MIT License](http://www.opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ Dir.glob('tasks/**/*.rake').each(&method(:import))
@@ -0,0 +1,29 @@
1
+ # encoding: UTF-8
2
+
3
+ Measurement.define(:'km²') do |unit|
4
+ unit.alias :km2, :'km^2', :'km*km', :'sq km', :'square kilometer', :'square kilometers'
5
+ unit.convert_to(:ha) { |value| value * 100.0 }
6
+ unit.convert_to(:a) { |value| value * 10_000.0 }
7
+ unit.convert_to(:cm2) { |value| value * 10_000_000_000.0 }
8
+ end
9
+
10
+ Measurement.define(:ha) do |unit|
11
+ unit.alias :hectare, :hectares
12
+ unit.convert_to(:km2) { |value| value / 100.0 }
13
+ unit.convert_to(:a) { |value| value * 100.0 }
14
+ unit.convert_to(:cm2) { |value| value * 100_000_000.0 }
15
+ end
16
+
17
+ Measurement.define(:a) do |unit|
18
+ unit.alias :are, :ares
19
+ unit.convert_to(:km2) { |value| value / 10_000.0 }
20
+ unit.convert_to(:ha) { |value| value / 100.0 }
21
+ unit.convert_to(:cm2) { |value| value * 1_000_000.0 }
22
+ end
23
+
24
+ Measurement.define(:'cm²') do |unit|
25
+ unit.alias :cm2, :'cm^2', :'cm*cm', :'sq cm', :'square centimeter', :'square centimeters'
26
+ unit.convert_to(:km2) { |value| value / 10_000_000_000.0 }
27
+ unit.convert_to(:ha) { |value| value / 100_000_000.0 }
28
+ unit.convert_to(:a) { |value| value / 1_000_000.0 }
29
+ end
@@ -0,0 +1,89 @@
1
+ # encoding: UTF-8
2
+
3
+ Measurement.define(:kl) do |unit|
4
+ unit.alias :kiloliter, :kiloliters
5
+ unit.convert_to(:hl) { |value| value * 10.0 }
6
+ unit.convert_to(:dal) { |value| value * 100.0 }
7
+ unit.convert_to(:l) { |value| value * 1000.0 }
8
+ unit.convert_to(:dl) { |value| value * 10000.0 }
9
+ unit.convert_to(:cl) { |value| value * 100000.0 }
10
+ unit.convert_to(:ml) { |value| value * 1000000.0 }
11
+ unit.convert_to(:µl) { |value| value * 10000000.0 }
12
+ end
13
+
14
+ Measurement.define(:hl) do |unit|
15
+ unit.alias :hectoliter, :hectoliters
16
+ unit.convert_to(:kl) { |value| value / 10.0 }
17
+ unit.convert_to(:dal) { |value| value * 10.0 }
18
+ unit.convert_to(:l) { |value| value * 100.0 }
19
+ unit.convert_to(:dl) { |value| value * 1_000.0 }
20
+ unit.convert_to(:cl) { |value| value * 10_000.0 }
21
+ unit.convert_to(:ml) { |value| value * 100_000.0 }
22
+ unit.convert_to(:µl) { |value| value * 1_000_000.0 }
23
+ end
24
+
25
+ Measurement.define(:dal) do |unit|
26
+ unit.alias :dekaliter, :dekaliters
27
+ unit.convert_to(:kl) { |value| value / 100.0 }
28
+ unit.convert_to(:hl) { |value| value / 10.0 }
29
+ unit.convert_to(:l) { |value| value * 10.0 }
30
+ unit.convert_to(:dl) { |value| value * 100.0 }
31
+ unit.convert_to(:cl) { |value| value * 1_000.0 }
32
+ unit.convert_to(:ml) { |value| value * 10_000.0 }
33
+ unit.convert_to(:µl) { |value| value * 100_000.0 }
34
+ end
35
+
36
+ Measurement.define(:l) do |unit|
37
+ unit.alias :liter, :liters
38
+ unit.convert_to(:kl) { |value| value / 1_000.0 }
39
+ unit.convert_to(:hl) { |value| value / 100.0 }
40
+ unit.convert_to(:dal) { |value| value / 10.0 }
41
+ unit.convert_to(:dl) { |value| value * 10.0 }
42
+ unit.convert_to(:cl) { |value| value * 100.0 }
43
+ unit.convert_to(:ml) { |value| value * 1_000.0 }
44
+ unit.convert_to(:µl) { |value| value * 10_000.0 }
45
+ end
46
+
47
+ Measurement.define(:dl) do |unit|
48
+ unit.alias :deciliter, :deciliters
49
+ unit.convert_to(:kl) { |value| value / 10_000.0 }
50
+ unit.convert_to(:hl) { |value| value / 1_000.0 }
51
+ unit.convert_to(:dal) { |value| value / 100.0 }
52
+ unit.convert_to(:l) { |value| value / 10.0 }
53
+ unit.convert_to(:cl) { |value| value * 10.0 }
54
+ unit.convert_to(:ml) { |value| value * 100.0 }
55
+ unit.convert_to(:µl) { |value| value * 1_000.0 }
56
+ end
57
+
58
+ Measurement.define(:cl) do |unit|
59
+ unit.alias :centiliter, :centiliters
60
+ unit.convert_to(:kl) { |value| value / 10_0000.0 }
61
+ unit.convert_to(:hl) { |value| value / 10_000.0 }
62
+ unit.convert_to(:dal) { |value| value / 1_000.0 }
63
+ unit.convert_to(:l) { |value| value / 100.0 }
64
+ unit.convert_to(:dl) { |value| value / 10.0 }
65
+ unit.convert_to(:ml) { |value| value * 10.0 }
66
+ unit.convert_to(:µl) { |value| value * 100.0 }
67
+ end
68
+
69
+ Measurement.define(:ml) do |unit|
70
+ unit.alias :milliliter, :milliliters
71
+ unit.convert_to(:kl) { |value| value / 1_000_000.0 }
72
+ unit.convert_to(:hl) { |value| value / 100_000.0 }
73
+ unit.convert_to(:dal) { |value| value / 10_000.0 }
74
+ unit.convert_to(:l) { |value| value / 1_000.0 }
75
+ unit.convert_to(:dl) { |value| value / 100.0 }
76
+ unit.convert_to(:cl) { |value| value / 10.0 }
77
+ unit.convert_to(:µl) { |value| value * 10.0 }
78
+ end
79
+
80
+ Measurement.define(:µl) do |unit|
81
+ unit.alias :microliter, :microliters
82
+ unit.convert_to(:kl) { |value| value / 10_000_000.0 }
83
+ unit.convert_to(:hl) { |value| value / 1_000_000.0 }
84
+ unit.convert_to(:dal) { |value| value / 100_000.0 }
85
+ unit.convert_to(:l) { |value| value / 10_000.0 }
86
+ unit.convert_to(:dl) { |value| value / 1_000.0 }
87
+ unit.convert_to(:cl) { |value| value / 100.0 }
88
+ unit.convert_to(:ml) { |value| value / 10.0 }
89
+ end
@@ -0,0 +1,89 @@
1
+ # encoding: UTF-8
2
+
3
+ Measurement.define(:km) do |unit|
4
+ unit.alias :kilometer, :kilometers
5
+ unit.convert_to(:hm) { |value| value * 10.0 }
6
+ unit.convert_to(:dam) { |value| value * 100.0 }
7
+ unit.convert_to(:m) { |value| value * 1_000.0 }
8
+ unit.convert_to(:dm) { |value| value * 10_000.0 }
9
+ unit.convert_to(:cm) { |value| value * 100_000.0 }
10
+ unit.convert_to(:mm) { |value| value * 1_000_000.0 }
11
+ unit.convert_to(:µm) { |value| value * 10_000_000.0 }
12
+ end
13
+
14
+ Measurement.define(:hm) do |unit|
15
+ unit.alias :hectometer, :hectometers
16
+ unit.convert_to(:km) { |value| value / 10.0 }
17
+ unit.convert_to(:dam) { |value| value * 10.0 }
18
+ unit.convert_to(:m) { |value| value * 100.0 }
19
+ unit.convert_to(:dm) { |value| value * 1_000.0 }
20
+ unit.convert_to(:cm) { |value| value * 10_000.0 }
21
+ unit.convert_to(:mm) { |value| value * 100_000.0 }
22
+ unit.convert_to(:µm) { |value| value * 1_000_000.0 }
23
+ end
24
+
25
+ Measurement.define(:dam) do |unit|
26
+ unit.alias :dekameter, :dekameters
27
+ unit.convert_to(:km) { |value| value / 100.0 }
28
+ unit.convert_to(:hm) { |value| value / 10.0 }
29
+ unit.convert_to(:m) { |value| value * 10.0 }
30
+ unit.convert_to(:dm) { |value| value * 100.0 }
31
+ unit.convert_to(:cm) { |value| value * 1_000.0 }
32
+ unit.convert_to(:mm) { |value| value * 10_000.0 }
33
+ unit.convert_to(:µm) { |value| value * 100_000.0 }
34
+ end
35
+
36
+ Measurement.define(:m) do |unit|
37
+ unit.alias :meter, :meters
38
+ unit.convert_to(:km) { |value| value / 1_000.0 }
39
+ unit.convert_to(:hm) { |value| value / 100.0 }
40
+ unit.convert_to(:dam) { |value| value / 10.0 }
41
+ unit.convert_to(:dm) { |value| value * 10.0 }
42
+ unit.convert_to(:cm) { |value| value * 100.0 }
43
+ unit.convert_to(:mm) { |value| value * 1_000.0 }
44
+ unit.convert_to(:µm) { |value| value * 10_000.0 }
45
+ end
46
+
47
+ Measurement.define(:dm) do |unit|
48
+ unit.alias :decimeter, :decimeters
49
+ unit.convert_to(:km) { |value| value / 10_000.0 }
50
+ unit.convert_to(:hm) { |value| value / 1_000.0 }
51
+ unit.convert_to(:dam) { |value| value / 100.0 }
52
+ unit.convert_to(:m) { |value| value / 10.0 }
53
+ unit.convert_to(:cm) { |value| value * 10.0 }
54
+ unit.convert_to(:mm) { |value| value * 100.0 }
55
+ unit.convert_to(:µm) { |value| value * 1_000.0 }
56
+ end
57
+
58
+ Measurement.define(:cm) do |unit|
59
+ unit.alias :centimeter, :centimeters
60
+ unit.convert_to(:km) { |value| value / 100_000.0 }
61
+ unit.convert_to(:hm) { |value| value / 10_000.0 }
62
+ unit.convert_to(:dam) { |value| value / 1_000.0 }
63
+ unit.convert_to(:m) { |value| value / 100.0 }
64
+ unit.convert_to(:dm) { |value| value / 10.0 }
65
+ unit.convert_to(:mm) { |value| value * 10.0 }
66
+ unit.convert_to(:µm) { |value| value * 100.0 }
67
+ end
68
+
69
+ Measurement.define(:mm) do |unit|
70
+ unit.alias :millimeter, :millimeters
71
+ unit.convert_to(:km) { |value| value / 1_000_000.0 }
72
+ unit.convert_to(:hm) { |value| value / 100_000.0 }
73
+ unit.convert_to(:dam) { |value| value / 10_000.0 }
74
+ unit.convert_to(:m) { |value| value / 1_000.0 }
75
+ unit.convert_to(:dm) { |value| value / 100.0 }
76
+ unit.convert_to(:cm) { |value| value / 10.0 }
77
+ unit.convert_to(:µm) { |value| value * 10.0 }
78
+ end
79
+
80
+ Measurement.define(:µm) do |unit|
81
+ unit.alias :micrometer, :micrometers
82
+ unit.convert_to(:km) { |value| value / 10_000_000.0 }
83
+ unit.convert_to(:hm) { |value| value / 1_000_000.0 }
84
+ unit.convert_to(:dam) { |value| value / 100_000.0 }
85
+ unit.convert_to(:m) { |value| value / 10_000.0 }
86
+ unit.convert_to(:dm) { |value| value / 1_000.0 }
87
+ unit.convert_to(:cm) { |value| value / 100.0 }
88
+ unit.convert_to(:mm) { |value| value / 10.0 }
89
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: UTF-8
2
+
3
+ Measurement.define(:'m³') do |unit|
4
+ unit.alias :m3, :'m^3', :'m*m*m', :'cubic meter', :'cubic meters'
5
+ unit.convert_to(:dm3) { |value| value * 1_000.0 }
6
+ unit.convert_to(:cm3) { |value| value * 1_000_000.0 }
7
+ end
8
+
9
+ Measurement.define(:'dm³') do |unit|
10
+ unit.alias :dm3, :'dm^3', :'dm*dm*dm', :'cubic decimeter', :'cubic decimeters'
11
+ unit.convert_to(:m3) { |value| value / 1_000.0 }
12
+ unit.convert_to(:cm3) { |value| value * 1_000.0 }
13
+ end
14
+
15
+ Measurement.define(:'cm³') do |unit|
16
+ unit.alias :cm3, :'cm^3', :'cm*cm*cm', :'cubic centimeter', :'cubic centimeters'
17
+ unit.convert_to(:m3) { |value| value / 1_000_000.0 }
18
+ unit.convert_to(:dm3) { |value| value / 1_000.0 }
19
+ end
@@ -0,0 +1,109 @@
1
+ # encoding: UTF-8
2
+
3
+ Measurement.define(:t) do |unit|
4
+ unit.alias :'metric tonne', :'metric tonnes', :tonne, :tonnes
5
+ unit.convert_to(:kg) { |value| value * 1_000.0 }
6
+ unit.convert_to(:hg) { |value| value * 10_000.0 }
7
+ unit.convert_to(:dag) { |value| value * 100_000.0 }
8
+ unit.convert_to(:g) { |value| value * 1_000_000.0 }
9
+ unit.convert_to(:dg) { |value| value * 10_000_000.0 }
10
+ unit.convert_to(:cg) { |value| value * 100_000_000.0 }
11
+ unit.convert_to(:mg) { |value| value * 1_000_000_000.0 }
12
+ unit.convert_to(:µg) { |value| value * 10_000_000_000.0 }
13
+ end
14
+
15
+ Measurement.define(:kg) do |unit|
16
+ unit.alias :kilogram, :kilograms
17
+ unit.convert_to(:t) { |value| value / 1_000.0 }
18
+ unit.convert_to(:hg) { |value| value * 10.0 }
19
+ unit.convert_to(:dag) { |value| value * 100.0 }
20
+ unit.convert_to(:g) { |value| value * 1_000.0 }
21
+ unit.convert_to(:dg) { |value| value * 10_000.0 }
22
+ unit.convert_to(:cg) { |value| value * 100_000.0 }
23
+ unit.convert_to(:mg) { |value| value * 1_000_000.0 }
24
+ unit.convert_to(:µg) { |value| value * 10_000_000.0 }
25
+ end
26
+
27
+ Measurement.define(:hg) do |unit|
28
+ unit.alias :hectogram, :hectograms
29
+ unit.convert_to(:t) { |value| value / 10_000.0 }
30
+ unit.convert_to(:kg) { |value| value / 10.0 }
31
+ unit.convert_to(:dag) { |value| value * 10.0 }
32
+ unit.convert_to(:g) { |value| value * 100.0 }
33
+ unit.convert_to(:dg) { |value| value * 1_000.0 }
34
+ unit.convert_to(:cg) { |value| value * 10_000.0 }
35
+ unit.convert_to(:mg) { |value| value * 100_000.0 }
36
+ unit.convert_to(:µg) { |value| value * 1_000_000.0 }
37
+ end
38
+
39
+ Measurement.define(:dag) do |unit|
40
+ unit.alias :dekagram, :dekagrams
41
+ unit.convert_to(:t) { |value| value / 100_000.0 }
42
+ unit.convert_to(:kg) { |value| value / 100.0 }
43
+ unit.convert_to(:hg) { |value| value / 10.0 }
44
+ unit.convert_to(:g) { |value| value * 10.0 }
45
+ unit.convert_to(:dg) { |value| value * 100.0 }
46
+ unit.convert_to(:cg) { |value| value * 1_000.0 }
47
+ unit.convert_to(:mg) { |value| value * 10_000.0 }
48
+ unit.convert_to(:µg) { |value| value * 100_000.0 }
49
+ end
50
+
51
+ Measurement.define(:g) do |unit|
52
+ unit.alias :gram, :grams
53
+ unit.convert_to(:t) { |value| value / 1_000_000.0 }
54
+ unit.convert_to(:kg) { |value| value / 1_000.0 }
55
+ unit.convert_to(:hg) { |value| value / 100.0 }
56
+ unit.convert_to(:dag) { |value| value / 10.0 }
57
+ unit.convert_to(:dg) { |value| value * 10.0 }
58
+ unit.convert_to(:cg) { |value| value * 100.0 }
59
+ unit.convert_to(:mg) { |value| value * 1_000.0 }
60
+ unit.convert_to(:µg) { |value| value * 10_000.0 }
61
+ end
62
+
63
+ Measurement.define(:dg) do |unit|
64
+ unit.alias :decigram, :decigrams
65
+ unit.convert_to(:t) { |value| value / 10_000_000.0 }
66
+ unit.convert_to(:kg) { |value| value / 10_000.0 }
67
+ unit.convert_to(:hg) { |value| value / 1_000.0 }
68
+ unit.convert_to(:dag) { |value| value / 100.0 }
69
+ unit.convert_to(:g) { |value| value / 10.0 }
70
+ unit.convert_to(:cg) { |value| value * 10.0 }
71
+ unit.convert_to(:mg) { |value| value * 100.0 }
72
+ unit.convert_to(:µg) { |value| value * 1_000.0 }
73
+ end
74
+
75
+ Measurement.define(:cg) do |unit|
76
+ unit.alias :centigram, :centigrams
77
+ unit.convert_to(:t) { |value| value / 100_000_000.0 }
78
+ unit.convert_to(:kg) { |value| value / 100_000.0 }
79
+ unit.convert_to(:hg) { |value| value / 10_000.0 }
80
+ unit.convert_to(:dag) { |value| value / 1_000.0 }
81
+ unit.convert_to(:g) { |value| value / 100.0 }
82
+ unit.convert_to(:dg) { |value| value / 10.0 }
83
+ unit.convert_to(:mg) { |value| value * 10.0 }
84
+ unit.convert_to(:µg) { |value| value * 100.0 }
85
+ end
86
+
87
+ Measurement.define(:mg) do |unit|
88
+ unit.alias :milligram, :milligrams
89
+ unit.convert_to(:t) { |value| value / 1_000_000_000.0 }
90
+ unit.convert_to(:kg) { |value| value / 1_000_000.0 }
91
+ unit.convert_to(:hg) { |value| value / 100_000.0 }
92
+ unit.convert_to(:dag) { |value| value / 10_000.0 }
93
+ unit.convert_to(:g) { |value| value / 1_000.0 }
94
+ unit.convert_to(:dg) { |value| value / 100.0 }
95
+ unit.convert_to(:cg) { |value| value / 10.0 }
96
+ unit.convert_to(:µg) { |value| value * 10.0 }
97
+ end
98
+
99
+ Measurement.define(:µg) do |unit|
100
+ unit.alias :microgram, :micrograms
101
+ unit.convert_to(:t) { |value| value / 10_000_000_000.0 }
102
+ unit.convert_to(:kg) { |value| value / 10_000_000.0 }
103
+ unit.convert_to(:hg) { |value| value / 1_000_000.0 }
104
+ unit.convert_to(:dag) { |value| value / 100_000.0 }
105
+ unit.convert_to(:g) { |value| value / 10_000.0 }
106
+ unit.convert_to(:dg) { |value| value / 1_000.0 }
107
+ unit.convert_to(:cg) { |value| value / 100.0 }
108
+ unit.convert_to(:mg) { |value| value / 10.0 }
109
+ end
@@ -0,0 +1,4 @@
1
+ require 'ruby-measurement/definitions/metric/area'
2
+ require 'ruby-measurement/definitions/metric/capacity'
3
+ require 'ruby-measurement/definitions/metric/length'
4
+ require 'ruby-measurement/definitions/metric/volume'
@@ -0,0 +1,55 @@
1
+ # encoding: UTF-8
2
+
3
+ Measurement.define(:'mi²') do |unit|
4
+ unit.alias :mi2, :'mi*mi', :'sq mi', :'square mile', :'square miles'
5
+ unit.convert_to(:fur2) { |value| value * 64.0 }
6
+ unit.convert_to(:ch2) { |value| value * 6_400.0 }
7
+ unit.convert_to(:yd2) { |value| value * 3_097_600.0 }
8
+ unit.convert_to(:ft2) { |value| value * 27_878_400.0 }
9
+ unit.convert_to(:in2) { |value| value * 4_014_489_600.0 }
10
+ end
11
+
12
+ Measurement.define(:'fur²') do |unit|
13
+ unit.alias :fur2, :'fur*fur', :'sq fur', :'square furlong', :'square furlongs'
14
+ unit.convert_to(:mi2) { |value| value / 64.0 }
15
+ unit.convert_to(:ch2) { |value| value * 100.0 }
16
+ unit.convert_to(:yd2) { |value| value * 48_400.0 }
17
+ unit.convert_to(:ft2) { |value| value * 435_600.0 }
18
+ unit.convert_to(:in2) { |value| value * 62_726_400.0 }
19
+ end
20
+
21
+ Measurement.define(:'ch²') do |unit|
22
+ unit.alias :ch2, :'ch*ch', :'sq ch', :'square chain', :'square chains'
23
+ unit.convert_to(:mi2) { |value| value / 6_400.0 }
24
+ unit.convert_to(:fur2) { |value| value / 100.0 }
25
+ unit.convert_to(:yd2) { |value| value * 484.0 }
26
+ unit.convert_to(:ft2) { |value| value * 4_356.0 }
27
+ unit.convert_to(:in2) { |value| value * 627_264.0 }
28
+ end
29
+
30
+ Measurement.define(:'yd²') do |unit|
31
+ unit.alias :yd2, :'yd*yd', :'sq yd', :'square yard', :'square yard'
32
+ unit.convert_to(:mi2) { |value| value / 3_097_600.0 }
33
+ unit.convert_to(:fur2) { |value| value / 48_400.0 }
34
+ unit.convert_to(:ch2) { |value| value / 484.0 }
35
+ unit.convert_to(:ft2) { |value| value * 9.0 }
36
+ unit.convert_to(:in2) { |value| value * 1_296.0 }
37
+ end
38
+
39
+ Measurement.define(:'ft²') do |unit|
40
+ unit.alias :ft2, :'ft*ft', :'sq ft', :'square foot', :'square foot'
41
+ unit.convert_to(:mi2) { |value| value / 27_878_400.0 }
42
+ unit.convert_to(:fur2) { |value| value / 435_600.0 }
43
+ unit.convert_to(:ch2) { |value| value / 4_356.0 }
44
+ unit.convert_to(:yd2) { |value| value / 9.0 }
45
+ unit.convert_to(:in2) { |value| value * 144.0 }
46
+ end
47
+
48
+ Measurement.define(:'in²') do |unit|
49
+ unit.alias :in2, :'in*in', :'sq in', :'square inch', :'square inches'
50
+ unit.convert_to(:mi2) { |value| value / 4_014_489_600.0 }
51
+ unit.convert_to(:fur2) { |value| value / 62_726_400.0 }
52
+ unit.convert_to(:ch2) { |value| value / 627_264.0 }
53
+ unit.convert_to(:yd2) { |value| value / 1_296.0 }
54
+ unit.convert_to(:ft2) { |value| value / 144.0 }
55
+ end
@@ -0,0 +1,109 @@
1
+ # encoding: UTF-8
2
+
3
+ Measurement.define(:'lea.') do |unit|
4
+ unit.alias :lea, :league, :leagues
5
+ unit.convert_to(:mi) { |value| value * 3.45233834 }
6
+ unit.convert_to(:fur) { |value| value * 27.6187068 }
7
+ unit.convert_to(:ch) { |value| value * 276.187068 }
8
+ unit.convert_to(:ftm) { |value| value * 3_038.05774 }
9
+ unit.convert_to(:yd) { |value| value * 6_076.11549 }
10
+ unit.convert_to(:ft) { |value| value * 18_228.3465 }
11
+ unit.convert_to(:in) { |value| value * 218_740.157 }
12
+ unit.convert_to(:th) { |value| value * 218_740_157.0 }
13
+ end
14
+
15
+ Measurement.define(:'mi.') do |unit|
16
+ unit.alias :mi, :mile, :miles
17
+ unit.convert_to(:lea) { |value| value / 3.45233834 }
18
+ unit.convert_to(:fur) { |value| value * 8.0 }
19
+ unit.convert_to(:ch) { |value| value * 80.0 }
20
+ unit.convert_to(:ftm) { |value| value * 880.0 }
21
+ unit.convert_to(:yd) { |value| value * 1_760.0 }
22
+ unit.convert_to(:ft) { |value| value * 5_280.0 }
23
+ unit.convert_to(:in) { |value| value * 63_360.0 }
24
+ unit.convert_to(:th) { |value| value * 63_360_000.0 }
25
+ end
26
+
27
+ Measurement.define(:'fur.') do |unit|
28
+ unit.alias :fur, :furlong, :furlongs
29
+ unit.convert_to(:lea) { |value| value / 27.6187068 }
30
+ unit.convert_to(:mi) { |value| value / 8.0 }
31
+ unit.convert_to(:ch) { |value| value * 10.0 }
32
+ unit.convert_to(:ftm) { |value| value * 110.0 }
33
+ unit.convert_to(:yd) { |value| value * 220.0 }
34
+ unit.convert_to(:ft) { |value| value * 660.0 }
35
+ unit.convert_to(:in) { |value| value * 7_920.0 }
36
+ unit.convert_to(:th) { |value| value * 7_920_000.0 }
37
+ end
38
+
39
+ Measurement.define(:'ch.') do |unit|
40
+ unit.alias :ch, :chain, :chains
41
+ unit.convert_to(:lea) { |value| value / 276.187068 }
42
+ unit.convert_to(:mi) { |value| value / 80.0 }
43
+ unit.convert_to(:fur) { |value| value / 10.0 }
44
+ unit.convert_to(:ftm) { |value| value * 11.0 }
45
+ unit.convert_to(:yd) { |value| value * 22.0 }
46
+ unit.convert_to(:ft) { |value| value * 66.0 }
47
+ unit.convert_to(:in) { |value| value * 792.0 }
48
+ unit.convert_to(:th) { |value| value * 792_000.0 }
49
+ end
50
+
51
+ Measurement.define(:'ftm.') do |unit|
52
+ unit.alias :ftm, :fathom, :fathoms
53
+ unit.convert_to(:lea) { |value| value / 3_038.05774 }
54
+ unit.convert_to(:mi) { |value| value / 880.0 }
55
+ unit.convert_to(:fur) { |value| value / 110.0 }
56
+ unit.convert_to(:ch) { |value| value / 11.0 }
57
+ unit.convert_to(:yd) { |value| value * 2.0 }
58
+ unit.convert_to(:ft) { |value| value * 6.0 }
59
+ unit.convert_to(:in) { |value| value * 72.0 }
60
+ unit.convert_to(:th) { |value| value * 72_000.0 }
61
+ end
62
+
63
+ Measurement.define(:'yd.') do |unit|
64
+ unit.alias :yd, :yard, :yards
65
+ unit.convert_to(:lea) { |value| value / 6_076.11549 }
66
+ unit.convert_to(:mi) { |value| value / 1_760.0 }
67
+ unit.convert_to(:fur) { |value| value / 220.0 }
68
+ unit.convert_to(:ch) { |value| value / 22.0 }
69
+ unit.convert_to(:ftm) { |value| value / 2.0 }
70
+ unit.convert_to(:ft) { |value| value * 3.0 }
71
+ unit.convert_to(:in) { |value| value * 36.0 }
72
+ unit.convert_to(:th) { |value| value * 36_000.0 }
73
+ end
74
+
75
+ Measurement.define(:'ft.') do |unit|
76
+ unit.alias :ft, :foot, :feet, :"'"
77
+ unit.convert_to(:lea) { |value| value / 18_228.3465 }
78
+ unit.convert_to(:mi) { |value| value / 5_280.0 }
79
+ unit.convert_to(:ch) { |value| value / 66.0 }
80
+ unit.convert_to(:fur) { |value| value / 660.0 }
81
+ unit.convert_to(:yd) { |value| value / 3.0 }
82
+ unit.convert_to(:ftm) { |value| value / 6.0 }
83
+ unit.convert_to(:in) { |value| value * 12.0 }
84
+ unit.convert_to(:th) { |value| value * 12_000.0 }
85
+ end
86
+
87
+ Measurement.define(:'in.') do |unit|
88
+ unit.alias :in, :inch, :inches, :'"'
89
+ unit.convert_to(:lea) { |value| value / 218_740.157 }
90
+ unit.convert_to(:mi) { |value| value / 63_360.0 }
91
+ unit.convert_to(:fur) { |value| value / 7_920.0 }
92
+ unit.convert_to(:ch) { |value| value / 792.0 }
93
+ unit.convert_to(:ftm) { |value| value / 72.0 }
94
+ unit.convert_to(:yd) { |value| value / 36.0 }
95
+ unit.convert_to(:ft) { |value| value / 12.0 }
96
+ unit.convert_to(:th) { |value| value * 1000.0 }
97
+ end
98
+
99
+ Measurement.define(:'th.') do |unit|
100
+ unit.alias :th, :thou
101
+ unit.convert_to(:lea) { |value| value / 218_740_157.0 }
102
+ unit.convert_to(:mi) { |value| value / 63_360_000.0 }
103
+ unit.convert_to(:fur) { |value| value / 7_920_000.0 }
104
+ unit.convert_to(:ch) { |value| value / 792_000.0 }
105
+ unit.convert_to(:ftm) { |value| value / 72_000.0 }
106
+ unit.convert_to(:yd) { |value| value / 36_000.0 }
107
+ unit.convert_to(:ft) { |value| value / 12_000.0 }
108
+ unit.convert_to(:in) { |value| value / 1000.0 }
109
+ end
@@ -0,0 +1,71 @@
1
+ # encoding: UTF-8
2
+
3
+ Measurement.define(:'gal.') do |unit|
4
+ unit.alias :gal, :gallon, :gallons
5
+ unit.convert_to(:qt) { |value| value * 4.0 }
6
+ unit.convert_to(:pt) { |value| value * 8.0 }
7
+ unit.convert_to(:c) { |value| value * 16.0 }
8
+ unit.convert_to(:'fl oz') { |value| value * 128.0 }
9
+ unit.convert_to(:tbsp) { |value| value * 256.0 }
10
+ unit.convert_to(:tsp) { |value| value * 768.0 }
11
+ end
12
+
13
+ Measurement.define(:'qt.') do |unit|
14
+ unit.alias :qt, :quart, :quarts
15
+ unit.convert_to(:gal) { |value| value / 4.0 }
16
+ unit.convert_to(:pt) { |value| value * 2.0 }
17
+ unit.convert_to(:c) { |value| value * 4.0 }
18
+ unit.convert_to(:'fl oz') { |value| value * 32.0 }
19
+ unit.convert_to(:tbsp) { |value| value * 64.0 }
20
+ unit.convert_to(:tsp) { |value| value * 192.0 }
21
+ end
22
+
23
+ Measurement.define(:'pt.') do |unit|
24
+ unit.alias :pt, :pint, :pints
25
+ unit.convert_to(:gal) { |value| value / 8.0 }
26
+ unit.convert_to(:qt) { |value| value / 2.0 }
27
+ unit.convert_to(:c) { |value| value * 2.0 }
28
+ unit.convert_to(:'fl oz') { |value| value * 16.0 }
29
+ unit.convert_to(:tbsp) { |value| value * 32.0 }
30
+ unit.convert_to(:tsp) { |value| value * 96.0 }
31
+ end
32
+
33
+ Measurement.define(:'c.') do |unit|
34
+ unit.alias :c, :cup, :cups
35
+ unit.convert_to(:gal) { |value| value / 16.0 }
36
+ unit.convert_to(:qt) { |value| value / 4.0 }
37
+ unit.convert_to(:pt) { |value| value / 2.0 }
38
+ unit.convert_to(:'fl oz') { |value| value * 8.0 }
39
+ unit.convert_to(:tbsp) { |value| value * 16.0 }
40
+ unit.convert_to(:tsp) { |value| value * 48.0 }
41
+ end
42
+
43
+ Measurement.define(:'fl. oz.') do |unit|
44
+ unit.alias :'fl oz', :'oz. fl.', :'fluid ounce', :'fluid ounces'
45
+ unit.convert_to(:gal) { |value| value / 128.0 }
46
+ unit.convert_to(:qt) { |value| value / 32.0 }
47
+ unit.convert_to(:pt) { |value| value / 16.0 }
48
+ unit.convert_to(:c) { |value| value / 8.0 }
49
+ unit.convert_to(:tbsp) { |value| value * 2.0 }
50
+ unit.convert_to(:tsp) { |value| value * 6.0 }
51
+ end
52
+
53
+ Measurement.define(:'tbsp.') do |unit|
54
+ unit.alias :tbsp, :tablespoon, :tablespoons
55
+ unit.convert_to(:gal) { |value| value / 256.0 }
56
+ unit.convert_to(:qt) { |value| value / 64.0 }
57
+ unit.convert_to(:pt) { |value| value / 32.0 }
58
+ unit.convert_to(:c) { |value| value / 16.0 }
59
+ unit.convert_to(:'fl oz') { |value| value / 2.0 }
60
+ unit.convert_to(:tsp) { |value| value * 3.0 }
61
+ end
62
+
63
+ Measurement.define(:'tsp.') do |unit|
64
+ unit.alias :tsp, :teaspoon, :teaspoons
65
+ unit.convert_to(:gal) { |value| value / 768.0 }
66
+ unit.convert_to(:qt) { |value| value / 192.0 }
67
+ unit.convert_to(:pt) { |value| value / 96.0 }
68
+ unit.convert_to(:c) { |value| value / 48.0 }
69
+ unit.convert_to(:'fl oz') { |value| value / 6.0 }
70
+ unit.convert_to(:tbsp) { |value| value / 3.0 }
71
+ end
@@ -0,0 +1,55 @@
1
+ # encoding: UTF-8
2
+
3
+ Measurement.define(:ton) do |unit|
4
+ unit.alias :'short ton', :'short tons', :tons
5
+ unit.convert_to(:cwt) { |value| value * 20.0 }
6
+ unit.convert_to(:lb) { |value| value * 2000.0 }
7
+ unit.convert_to(:oz) { |value| value * 32_000.0 }
8
+ unit.convert_to(:dr) { |value| value * 512_000.0 }
9
+ unit.convert_to(:gr) { |value| value * 14_000_000.0 }
10
+ end
11
+
12
+ Measurement.define(:cwt) do |unit|
13
+ unit.alias :hundredweight, :hundredweights
14
+ unit.convert_to(:ton) { |value| value / 20.0 }
15
+ unit.convert_to(:lb) { |value| value * 100.0 }
16
+ unit.convert_to(:oz) { |value| value * 1_600.0 }
17
+ unit.convert_to(:dr) { |value| value * 28_672.0 }
18
+ unit.convert_to(:gr) { |value| value * 784_000.0 }
19
+ end
20
+
21
+ Measurement.define(:lb) do |unit|
22
+ unit.alias :lbs, :pound, :pounds
23
+ unit.convert_to(:ton) { |value| value / 2000.0 }
24
+ unit.convert_to(:cwt) { |value| value / 100.0 }
25
+ unit.convert_to(:oz) { |value| value * 16.0 }
26
+ unit.convert_to(:dr) { |value| value * 256.0 }
27
+ unit.convert_to(:gr) { |value| value * 7000.0 }
28
+ end
29
+
30
+ Measurement.define(:oz) do |unit|
31
+ unit.alias :ounce, :ounces
32
+ unit.convert_to(:ton) { |value| value / 32_000.0 }
33
+ unit.convert_to(:cwt) { |value| value / 1_600.0 }
34
+ unit.convert_to(:lb) { |value| value / 16.0 }
35
+ unit.convert_to(:dr) { |value| value * 16.0 }
36
+ unit.convert_to(:gr) { |value| value * 437.5 }
37
+ end
38
+
39
+ Measurement.define(:dr) do |unit|
40
+ unit.alias :dram, :drams
41
+ unit.convert_to(:ton) { |value| value / 512_000.0 }
42
+ unit.convert_to(:cwt) { |value| value / 28_672.0 }
43
+ unit.convert_to(:lb) { |value| value / 256.0 }
44
+ unit.convert_to(:oz) { |value| value / 16.0 }
45
+ unit.convert_to(:gr) { |value| value * 27.34375 }
46
+ end
47
+
48
+ Measurement.define(:gr) do |unit|
49
+ unit.alias :grain, :grains
50
+ unit.convert_to(:ton) { |value| value / 14_000_000.0 }
51
+ unit.convert_to(:cwt) { |value| value / 784_000.0 }
52
+ unit.convert_to(:lb) { |value| value / 7000.0 }
53
+ unit.convert_to(:oz) { |value| value / 437.5 }
54
+ unit.convert_to(:dr) { |value| value / 27.34375 }
55
+ end
@@ -0,0 +1,4 @@
1
+ require 'ruby-measurement/definitions/us_customary/area'
2
+ require 'ruby-measurement/definitions/us_customary/length'
3
+ require 'ruby-measurement/definitions/us_customary/volume'
4
+ require 'ruby-measurement/definitions/us_customary/weight'
@@ -0,0 +1,2 @@
1
+ require 'ruby-measurement/definitions/metric'
2
+ require 'ruby-measurement/definitions/us_customary'
@@ -0,0 +1,162 @@
1
+ require 'ruby-measurement/unit'
2
+ require 'ruby-measurement/version'
3
+
4
+ class Measurement
5
+ SCIENTIFIC_NUMBER = %r{([+-]?\d*[.]?\d+(?:[Ee][+-]?)?\d*)}.freeze
6
+ RATIONAL_NUMBER = /\A\(?([+-]?\d+)\/(\d+)\)?\z/.freeze
7
+ COMPLEX_NUMBER = /\A#{SCIENTIFIC_NUMBER}?#{SCIENTIFIC_NUMBER}i\b\z/.freeze
8
+
9
+ attr_reader :quantity, :unit
10
+
11
+ class << self; attr_accessor :units end
12
+ @units = {}
13
+
14
+ def initialize(str)
15
+ parse(str)
16
+ end
17
+
18
+ def inspect
19
+ to_s
20
+ end
21
+
22
+ def to_s
23
+ "#{quantity} #{unit}"
24
+ end
25
+
26
+ def +(obj)
27
+ case obj
28
+ when Numeric
29
+ self.class.new("#{quantity + obj.to_f} #{unit}")
30
+ when self.class
31
+ if obj.unit == unit
32
+ self.class.new("#{quantity + obj.quantity} #{unit}")
33
+ else
34
+ self + obj.convert_to(unit)
35
+ end
36
+ else
37
+ raise ArgumentError, "Invalid arithmetic: #{self} + #{obj}"
38
+ end
39
+ end
40
+
41
+ def -(obj)
42
+ case obj
43
+ when Numeric
44
+ self.class.new("#{quantity - obj.to_f} #{unit}")
45
+ when self.class
46
+ if obj.unit == unit
47
+ self.class.new("#{quantity - obj.quantity} #{unit}")
48
+ else
49
+ self - obj.convert_to(unit)
50
+ end
51
+ else
52
+ raise ArgumentError, "Invalid arithmetic: #{self} - #{obj}"
53
+ end
54
+ end
55
+
56
+ def *(obj)
57
+ case obj
58
+ when Numeric
59
+ self.class.new("#{quantity * obj.to_f} #{unit}")
60
+ when self.class
61
+ if obj.unit == unit
62
+ self.class.new("#{quantity * obj.quantity} #{unit}")
63
+ else
64
+ self * obj.convert_to(unit)
65
+ end
66
+ else
67
+ raise ArgumentError, "Invalid arithmetic: #{self} * #{obj}"
68
+ end
69
+ end
70
+
71
+ def /(obj)
72
+ case obj
73
+ when Numeric
74
+ self.class.new("#{quantity / obj.to_f} #{unit}")
75
+ when self.class
76
+ if obj.unit == unit
77
+ self.class.new("#{quantity / obj.quantity} #{unit}")
78
+ else
79
+ self / obj.convert_to(unit)
80
+ end
81
+ else
82
+ raise ArgumentError, "Invalid arithmetic: #{self} / #{obj}"
83
+ end
84
+ end
85
+
86
+ def **(obj)
87
+ case obj
88
+ when Numeric
89
+ self.class.new("#{quantity ** obj.to_f} #{unit}")
90
+ else
91
+ raise ArgumentError, "Invalid arithmetic: #{self} ** #{obj}"
92
+ end
93
+ end
94
+
95
+ def ==(obj)
96
+ obj.kind_of?(self.class) && quantity == obj.quantity && unit == obj.unit
97
+ end
98
+
99
+ def convert_to(unit_name)
100
+ unit = self.class.unit(unit_name)
101
+ raise ArgumentError, "Invalid unit: '#{unit_name}'" unless unit
102
+
103
+ return dup if unit == @unit
104
+
105
+ conversion = @unit.conversion(unit.name)
106
+ raise ArgumentError, "Invalid conversion: '#@unit' to '#{unit.name}'" unless conversion
107
+
108
+ self.class.new("#{conversion.call(@quantity)} #{unit.name}")
109
+ end
110
+
111
+ def convert_to!(unit_name)
112
+ measurement = convert_to(unit_name)
113
+ @unit, @quantity = measurement.unit, measurement.quantity
114
+ self
115
+ end
116
+
117
+ def self.unit(unit_name)
118
+ unit_name = unit_name.to_s
119
+ @units.values.find { |unit| unit.aliases.include?(unit_name) }
120
+ end
121
+
122
+ def self.parse(str = '0')
123
+ new(str)
124
+ end
125
+
126
+ def self.define(unit_name, &block)
127
+ unit = Unit.new(unit_name, &block)
128
+ unit.aliases.each { |a| @units[a.downcase] = unit }
129
+ end
130
+
131
+ private
132
+
133
+ def parse(str)
134
+ value = str.strip
135
+
136
+ quantity, unit_name = value.split(/\s+/, 2)
137
+ unit_name ||= 'count'
138
+ raise ArgumentError, "Missing quantity: '#{str}'" if !quantity || quantity.empty?
139
+
140
+ @unit = self.class.units[unit_name.downcase]
141
+ raise ArgumentError, "Invalid unit: '#{unit_name}'" unless @unit
142
+
143
+ if quantity =~ COMPLEX_NUMBER
144
+ real, imaginary = quantity.scan(COMPLEX_NUMBER).first
145
+ @quantity = Complex(real.to_f, imaginary.to_f).to_f
146
+ elsif quantity =~ RATIONAL_NUMBER
147
+ numerator, denominator = quantity.scan(RATIONAL_NUMBER).first
148
+ @quantity = Rational(numerator.to_i, denominator.to_i).to_f
149
+ else
150
+ @quantity = quantity.to_f
151
+ end
152
+ end
153
+
154
+ define(:count) do |unit|
155
+ unit.convert_to(:dozen) { |value| value / 12.0 }
156
+ end
157
+
158
+ define(:doz) do |unit|
159
+ unit.alias :dozen
160
+ unit.convert_to(:count) { |value| value * 12.0 }
161
+ end
162
+ end
@@ -0,0 +1,43 @@
1
+ require 'set'
2
+
3
+ class Measurement
4
+ class Unit
5
+ attr_reader :name, :aliases, :conversions
6
+
7
+ def initialize(name, &block)
8
+ @name = name.to_s
9
+ @aliases = Set.new
10
+ @conversions = {}
11
+
12
+ self.alias(name)
13
+ block.call(self) if block_given?
14
+ end
15
+
16
+ def alias(*args)
17
+ args.each { |arg| @aliases << arg.to_s }
18
+ end
19
+
20
+ def convert_to(name, &block)
21
+ @conversions[name.to_s] = block
22
+ end
23
+
24
+ def conversion(name)
25
+ Measurement.unit(name).aliases.each do |a|
26
+ conversion = @conversions[a.to_s]
27
+ return conversion if conversion
28
+ end
29
+ end
30
+
31
+ def inspect
32
+ to_s
33
+ end
34
+
35
+ def to_s
36
+ name
37
+ end
38
+
39
+ def ==(obj)
40
+ obj.kind_of?(self.class) && hash == obj.hash
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,3 @@
1
+ class Measurement
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,3 @@
1
+ require 'ruby-measurement/version'
2
+ require 'ruby-measurement/measurement'
3
+ require 'ruby-measurement/definitions'
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ruby-measurement/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = 'ruby-measurement'
8
+ gem.version = Measurement::VERSION
9
+ gem.author = 'Matt Huggins'
10
+ gem.email = 'matt.huggins@gmail.com'
11
+ gem.description = 'Simple gem for calculating and converting measurements'
12
+ gem.summary = 'Simple gem for calculating and converting measurements'
13
+ gem.homepage = 'https://github.com/mhuggins/measurement'
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_path = 'lib'
19
+
20
+ gem.add_development_dependency 'rake'
21
+ end
data/tasks/debug.rake ADDED
@@ -0,0 +1,4 @@
1
+ desc 'Open an irb session preloaded with this library'
2
+ task :console do
3
+ sh 'irb -rubygems -I lib -r ruby-measurement.rb'
4
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-measurement
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Matt Huggins
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-22 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: &2160164820 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *2160164820
25
+ description: Simple gem for calculating and converting measurements
26
+ email: matt.huggins@gmail.com
27
+ executables: []
28
+ extensions: []
29
+ extra_rdoc_files: []
30
+ files:
31
+ - .gitignore
32
+ - Gemfile
33
+ - LICENSE.txt
34
+ - README.md
35
+ - Rakefile
36
+ - lib/ruby-measurement.rb
37
+ - lib/ruby-measurement/definitions.rb
38
+ - lib/ruby-measurement/definitions/metric.rb
39
+ - lib/ruby-measurement/definitions/metric/area.rb
40
+ - lib/ruby-measurement/definitions/metric/capacity.rb
41
+ - lib/ruby-measurement/definitions/metric/length.rb
42
+ - lib/ruby-measurement/definitions/metric/volume.rb
43
+ - lib/ruby-measurement/definitions/metric/weight.rb
44
+ - lib/ruby-measurement/definitions/us_customary.rb
45
+ - lib/ruby-measurement/definitions/us_customary/area.rb
46
+ - lib/ruby-measurement/definitions/us_customary/length.rb
47
+ - lib/ruby-measurement/definitions/us_customary/volume.rb
48
+ - lib/ruby-measurement/definitions/us_customary/weight.rb
49
+ - lib/ruby-measurement/measurement.rb
50
+ - lib/ruby-measurement/unit.rb
51
+ - lib/ruby-measurement/version.rb
52
+ - ruby-measurement.gemspec
53
+ - tasks/debug.rake
54
+ homepage: https://github.com/mhuggins/measurement
55
+ licenses: []
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ requirements: []
73
+ rubyforge_project:
74
+ rubygems_version: 1.8.10
75
+ signing_key:
76
+ specification_version: 3
77
+ summary: Simple gem for calculating and converting measurements
78
+ test_files: []