ruby-measurement 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: []