metamorphosis 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/LICENSE.txt +22 -0
- data/README.md +34 -0
- data/lib/metamorphosis.rb +8 -0
- data/lib/metamorphosis/constants.rb +341 -0
- data/lib/metamorphosis/engine.rb +96 -0
- data/lib/metamorphosis/errors.rb +4 -0
- data/lib/metamorphosis/prefix_parser.rb +35 -0
- data/lib/metamorphosis/unit_registry.rb +35 -0
- data/lib/metamorphosis/unit_value.rb +54 -0
- data/lib/metamorphosis/version.rb +3 -0
- data/lib/numeric.rb +9 -0
- data/metamorphosis.gemspec +15 -0
- data/spec/lib/metamorphosis/engine_spec.rb +104 -0
- data/spec/lib/metamorphosis/prefix_parser_spec.rb +43 -0
- data/spec/lib/metamorphosis/unit_registry_spec.rb +38 -0
- data/spec/lib/metamorphosis/unit_value_spec.rb +69 -0
- data/spec/lib/metamorphosis_spec.rb +18 -0
- data/spec/lib/numeric_spec.rb +21 -0
- data/spec/spec_helper.rb +19 -0
- metadata +80 -0
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT LICENSE
|
2
|
+
|
3
|
+
Copyright (c) 2012 Wegowise, Inc.
|
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,34 @@
|
|
1
|
+
Metamorphosis
|
2
|
+
=============
|
3
|
+
An engine for allowing numeric values to convert between units.
|
4
|
+
|
5
|
+
[](http://travis-ci.org/wegowise/metamorphosis)
|
6
|
+
[](https://codeclimate.com/github/wegowise/metamorphosis)
|
7
|
+
|
8
|
+
Usage
|
9
|
+
==============
|
10
|
+
|
11
|
+
Add 'metamorphosis' to your Gemfile,
|
12
|
+
|
13
|
+
Bundle install
|
14
|
+
|
15
|
+
Inside your intializer use the predefined units:
|
16
|
+
|
17
|
+
````
|
18
|
+
Metamorphosis.register_predefined_units
|
19
|
+
````
|
20
|
+
|
21
|
+
or register your own:
|
22
|
+
````
|
23
|
+
Metamorphosis.engine.register_unit(:wegowise, :british_thermal_units, 1)
|
24
|
+
Metamorphosis.engine.register_unit(:wegowise, :therms, 100_000)
|
25
|
+
````
|
26
|
+
|
27
|
+
Once you've defined your units you now have freedom to make your values
|
28
|
+
more expressive:
|
29
|
+
````
|
30
|
+
value = 200_000.british_thermal_units #200000.0 british_thermal_units
|
31
|
+
value = value.to.therms
|
32
|
+
value == 2.therms #true
|
33
|
+
|
34
|
+
````
|
@@ -0,0 +1,341 @@
|
|
1
|
+
module Metamorphosis
|
2
|
+
SI_UNITS = %w{m meter metre meters metres liter litre litres liters l L
|
3
|
+
farad farads F coulombs C gray grays Gy siemen siemens S
|
4
|
+
mhos mho ohm ohms volt volts V joule joules J newton newtons N
|
5
|
+
lux lx henry henrys H b B bits bytes bit byte lumen lumens lm
|
6
|
+
candela candelas cd tesla teslas T gauss Gs G gram gramme grams
|
7
|
+
grammes g watt watts W pascal pascals Pa becquerel becquerels
|
8
|
+
Bq curie curies Ci}.map(&:to_sym)
|
9
|
+
|
10
|
+
DEFAULT_PREFIXES = {
|
11
|
+
:googol => 1e+100,
|
12
|
+
:yotta => 1e+24, :Y => 1e+24,
|
13
|
+
:zetta => 1e+21, :Z => 1e+21,
|
14
|
+
:exa => 1e+18, :E => 1e+18,
|
15
|
+
:peta => 1e+15, :P => 1e+15,
|
16
|
+
:tera => 1e+12, :T => 1e+12,
|
17
|
+
:giga => 1e+9, :G => 1e+9,
|
18
|
+
:mega => 1e+6, :M => 1e+6,
|
19
|
+
:kilo => 1e+3, :k => 1e+3,
|
20
|
+
:hecto => 1e+2, :h => 1e+2,
|
21
|
+
:deca => 10, :da => 10,
|
22
|
+
:deci => 1e-1, :d => 1e-1,
|
23
|
+
:centi => 1e-2, :c => 1e-2,
|
24
|
+
:milli => 1e-3, :m => 1e-3,
|
25
|
+
:micro => 1e-6, :u => 1e-6,
|
26
|
+
:nano => 1e-9, :n => 1e-9,
|
27
|
+
:pico => 1e-12, :p => 1e-12,
|
28
|
+
:femto => 1e-15, :f => 1e-15,
|
29
|
+
:atto => 1e-18, :a => 1e-18,
|
30
|
+
:zepto => 1e-21, :z => 1e-21,
|
31
|
+
:yocto => 1e-24, :y => 1e-24,
|
32
|
+
|
33
|
+
# binary prefixes
|
34
|
+
|
35
|
+
:kibi => 2.0**10.0, :Ki => 2.0**10.0,
|
36
|
+
:mebi => 2.0**20.0, :Mi => 2.0**20.0,
|
37
|
+
:gibi => 2.0**30.0, :Gi => 2.0**30.0,
|
38
|
+
:tebi => 2.0**40.0, :Ti => 2.0**40.0,
|
39
|
+
:pebi => 2.0**50.0, :Pi => 2.0**50.0,
|
40
|
+
:exbi => 2.0**60.0, :Ei => 2.0**60.0,
|
41
|
+
:zebi => 2.0**70.0, :Zi => 2.0**70.0,
|
42
|
+
:yobi => 2.0**80.0, :Yi => 2.0**80.0
|
43
|
+
}
|
44
|
+
|
45
|
+
PRE_DEFINED_UNITS =
|
46
|
+
{
|
47
|
+
:absorbed_radiation_dose => {
|
48
|
+
:gray => 1.0, :grays => 1.0, :Gy => 1.0,
|
49
|
+
:rad => 1.0e-2, :rads => 1.0e-2
|
50
|
+
},
|
51
|
+
:angles => {
|
52
|
+
:radian => 1.0, :radians => 1.0,
|
53
|
+
:degree => Math::PI / 180.0, :degrees => Math::PI / 180.0,
|
54
|
+
:arcminute => Math::PI / 10800.0, :arcminutes => Math::PI / 10800.0,
|
55
|
+
:arcsecond => Math::PI / 648000.0, :arcseconds => Math::PI / 648000.0,
|
56
|
+
:mil => 9.817477e-4, :mils => 9.817477e-4,
|
57
|
+
:revolution => Math::PI * 2.0, :revolutions => Math::PI * 2.0,
|
58
|
+
:circle => Math::PI * 2.0, :circles => Math::PI * 2.0,
|
59
|
+
:right_angle => Math::PI / 2.0, :right_angles => Math::PI / 2.0,
|
60
|
+
:grad => Math::PI / 200.0, :grade => Math::PI / 200.0, :gradian => Math::PI / 200.0, :gon => Math::PI / 200.0, :grads => Math::PI / 200.0, :grades => Math::PI / 200.0, :gradians => Math::PI / 200.0, :gons => Math::PI / 200.0,
|
61
|
+
#unusual measurements
|
62
|
+
:furman => 9.58737992858887e-5, :furmans => 9.58737992858887e-5
|
63
|
+
},
|
64
|
+
:area => {
|
65
|
+
:square_meter => 1.0, :square_meters => 1.0, :square_metre => 1.0, :square_metres => 1.0,
|
66
|
+
:acre => 4046.85642, :acres => 4046.85642,
|
67
|
+
:are => 1.0e+2, :ares => 1.0e+2, :a => 1.0e+2,
|
68
|
+
:barn => 1.0e-28, :barns => 1.0e-28, :b => 1.0e-28,
|
69
|
+
:circular_mil => 5.067075e-10, :circular_mils => 5.067075e-10,
|
70
|
+
:hectare => 1.0e+4, :hectares => 1.0e+4, :ha => 1.0e+4,
|
71
|
+
:square_foot => 9.290304e-2, :square_feet => 9.290304e-2,
|
72
|
+
:square_inch => 6.4516e-4, :square_inches => 6.4516e-4,
|
73
|
+
:square_mile => 2.589988e+6, :square_miles => 2.589988e+6,
|
74
|
+
:square_yard => 0.83612736, :square_yards => 0.83612736
|
75
|
+
},
|
76
|
+
:capacitance => {
|
77
|
+
:farad => 1.0, :farads => 1.0, :F => 1.0,
|
78
|
+
:abfarad => 1.0e+9, :emu_of_capacitance => 1.0e+9, :abfarads => 1.0e+9, :emus_of_capacitance => 1.0e+9,
|
79
|
+
:statfarad => 1.112650e-12, :esu_of_capacitance => 1.112650e-12, :statfarads => 1.112650e-12, :esus_of_capacitance => 1.112650e-12
|
80
|
+
},
|
81
|
+
:density => {
|
82
|
+
:specific_gravity => 1, :sg => 1,
|
83
|
+
:brix => [Proc.new{ |d| -261.3 / (d - 261.3) }, Proc.new{ |d| 261.3 - (261.3 / d) }],
|
84
|
+
:plato => [Proc.new{ |d| -260.0 / (d - 260.0) }, Proc.new{ |d| 260.0 - (260.0 / d) }],
|
85
|
+
:baume => [Proc.new{ |d| -145.0 / (d - 145.0) }, Proc.new{ |d| 145.0 - (145.0 / d) }]
|
86
|
+
},
|
87
|
+
:distance => {
|
88
|
+
:meter => 1.0, :metres => 1.0, :meters => 1.0, :m => 1.0,
|
89
|
+
:fermi => 1.0e-15, :fermis => 1.0e-15,
|
90
|
+
:micron => 1.0e-6, :microns => 1.0e-6,
|
91
|
+
:chain => 20.1168, :chains => 20.1168,
|
92
|
+
:inch => 25.4e-3, :inches => 25.4e-3, :in => 25.4e-3,
|
93
|
+
:microinch => 2.54e-8, :microinches => 2.54e-8,
|
94
|
+
:mil => 2.54e-05, :mils => 2.54e-05,
|
95
|
+
:rod => 5.029210, :rods => 5.029210,
|
96
|
+
:league => 5556, :leagues => 5556,
|
97
|
+
:foot => 0.3048, :feet => 0.3048, :ft => 0.3048,
|
98
|
+
:yard => 0.9144, :yards => 0.9144, :yd => 0.9144,
|
99
|
+
:mile =>1609.344, :miles =>1609.344, :mi => 1609.344,
|
100
|
+
:astronomical_unit => 149.60e+9, :astronomical_units => 149.60e+9, :au => 149.60e+9, :ua => 149.60e+9,
|
101
|
+
:light_year => 9.461e+15, :light_years => 9.461e+15, :ly => 9.461e+15,
|
102
|
+
:parsec => 30.857e+15, :parsecs => 30.857e+15,
|
103
|
+
:nautical_mile => 1852.0, :nautical_miles => 1852.0,
|
104
|
+
:admirality_mile => 185.3184, :admirality_miles => 185.3184,
|
105
|
+
:fathom => 1.8288, :fathoms => 1.8288,
|
106
|
+
:cable_length => 185.2, :cable_lengths => 185.2,
|
107
|
+
:angstrom => 100.0e-12, :angstroms => 100.0e-12,
|
108
|
+
:pica => 4.233333e-3, :picas => 4.233333e-3,
|
109
|
+
:printer_pica => 4.217518e-3, :printer_picas => 4.217518e-3,
|
110
|
+
:point => 3.527778e-4, :points => 3.527778e-4,
|
111
|
+
:printer_point => 3.514598e-4, :printer_points => 3.514598e-4,
|
112
|
+
# unusual mesaurements
|
113
|
+
:empire_state_building => 449.0, :empire_state_buildings => 449.0,
|
114
|
+
:sears_tower => 519.0, :sears_towers => 519.0,
|
115
|
+
:seattle_space_needle => 184.0, :seattle_space_needles => 184.0, :space_needle => 184.0, :space_needles => 184.0,
|
116
|
+
:statue_of_liberty => 46.0, :statue_of_liberties => 46.0,
|
117
|
+
:washington_monument => 169.294, :washington_monuments => 169.294,
|
118
|
+
:eiffel_tower => 324.0, :eiffel_towers => 324.0,
|
119
|
+
:nelsons_column => 61.5, :nelsons_columns => 61.5,
|
120
|
+
:blackpool_tower => 158.0, :blackpool_towers => 158.0,
|
121
|
+
:big_ben => 96.3, :big_bens => 96.3, :clock_tower_of_the_palace_of_westminster => 96.3, :clock_towers_of_the_palace_of_westminster => 96.3,
|
122
|
+
:st_pauls_cathedral => 108.0, :st_pauls_cathedrals => 108.0,
|
123
|
+
:toronto_cn_tower => 553.0, :toronto_cn_towers => 553.0, :cn_tower => 553.0, :cn_towers => 553.0,
|
124
|
+
:circle_of_the_earth => 40075016.686, :equator => 40075016.686, :circles_of_the_earth => 40075016.686, :equators => 40075016.686,
|
125
|
+
:siriometer => 1.494838e+17, :siriometers => 1.494838e+17,
|
126
|
+
:football_field => 91.0, :football_fields => 91.0,
|
127
|
+
:length_of_a_double_decker_bus => 8.4, :height_of_a_double_decker_bus => 4.4,
|
128
|
+
:smoot => 1.7018, :smoots => 1.7018
|
129
|
+
},
|
130
|
+
:dose_equivalent => {
|
131
|
+
:sievert => 1.0, :sieverts => 1.0, :Si => 1.0,
|
132
|
+
:rem => 1.0e-2, :rems => 1.0e-2
|
133
|
+
},
|
134
|
+
:electric_charge => {
|
135
|
+
:coulomb => 1.0, :coulombs => 1.0, :C => 1.0,
|
136
|
+
:abcoulomb => 10.0, :abcoulombs => 10.0,
|
137
|
+
:ampere_hour => 3.6e+3, :ampere_hours => 3.6e+3,
|
138
|
+
:faraday => 9.648534e+4, :faradays => 9.648534e+4,
|
139
|
+
:franklin => 3.335641e-10, :franklins => 3.335641e-10, :Fr => 3.335641e-10,
|
140
|
+
:statcoulomb => 3.335641e-10, :statcoulombs => 3.335641e-10
|
141
|
+
},
|
142
|
+
:electric_conductance => {
|
143
|
+
:siemen => 1.0, :siemens => 1.0, :S => 1.0, :mho => 1.0,
|
144
|
+
:abmho => 1.0e+9, :absiemen => 1.0e+9, :absiemens => 1.0e+9,
|
145
|
+
:statmho => 1.112650e-12, :statsiemen => 1.112650e-12, :statsiemens => 1.112650e-12
|
146
|
+
},
|
147
|
+
:electrical_impedance => {
|
148
|
+
:ohm => 1.0, :ohms => 1.0,
|
149
|
+
:abohm => 1.0e-9, :emu_of_resistance => 1.0e-9, :abohms => 1.0e-9, :emus_of_resistance => 1.0e-9,
|
150
|
+
:statohm => 8.987552e+11, :esu_of_resistance => 8.987552e+11, :statohms => 8.987552e+11, :esus_of_resistance => 8.987552e+11
|
151
|
+
},
|
152
|
+
:electromotive_force => {
|
153
|
+
:volt => 1.0, :volts => 1.0, :V => 1.0,
|
154
|
+
:abvolt => 1.0e-8, :emu_of_electric_potential => 1.0e-8, :abvolts => 1.0e-8, :emus_of_electric_potential => 1.0e-8,
|
155
|
+
:statvolt => 2.997925e+2, :esu_of_electric_potential => 2.997925e+2, :statvolts => 2.997925e+2, :esus_of_electric_potential => 2.997925e+2
|
156
|
+
},
|
157
|
+
:energy => {
|
158
|
+
:joule => 1.0, :joules => 1.0, :J => 1.0, :watt_second => 1.0, :watt_seconds => 1.0,
|
159
|
+
:watt_hour => 3.6e+3, :watt_hours => 3.6e+3,
|
160
|
+
:ton_of_tnt => 4.184e+9, :tons_of_tnt => 4.184e+9,
|
161
|
+
:therm => 1.05506e+8, :therms => 1.05506e+8,
|
162
|
+
:us_therm => 1.054804e+8, :us_therms => 1.054804e+8,
|
163
|
+
:kilowatt_hour => 3.6e+6, :kilowatt_hours => 3.6e+6,
|
164
|
+
:kilocalorie => 4184.0, :kilocalories => 4184.0,
|
165
|
+
:calorie => 4.184, :calories => 4.184,
|
166
|
+
:mean_kilocalorie => 4190, :mean_kilocalories => 4190,
|
167
|
+
:mean_calorie => 4.190, :mean_calories => 4.190,
|
168
|
+
:it_kilocalorie => 4186.8, :it_kilocalories => 4186.8,
|
169
|
+
:it_calorie => 4.1868, :it_calories => 4.1868,
|
170
|
+
:foot_poundal => 4.214011e-2, :foot_poundals => 4.214011e-2,
|
171
|
+
:foot_pound_force => 1.355818,
|
172
|
+
:erg => 1.0e-7, :ergs => 1.0e-7,
|
173
|
+
:electronvolt => 1.602176e-19, :electronvolts => 1.602176e-19, :eV => 1.602176e-19,
|
174
|
+
:british_thermal_unit => 1.054350e+3, :british_thermal_units => 1.054350e+3,
|
175
|
+
:mean_british_thermal_unit => 1.05587e+3, :mean_british_thermal_units => 1.05587e+3,
|
176
|
+
:it_british_thermal_unit => 1.055056e+3, :it_british_thermal_units => 1.055056e+3,
|
177
|
+
#unusual measurements
|
178
|
+
:foe => 1e+44, :foes => 1e+44
|
179
|
+
},
|
180
|
+
:frequency => {
|
181
|
+
:hertz => 1.0, :hz => 1.0, :'Hz' => 1.0,
|
182
|
+
:revolutions_per_minute => 1/60.0, :rpm => 1/60.0,
|
183
|
+
:beats_per_minute => 1/60.0, :bpm => 1/60.0
|
184
|
+
},
|
185
|
+
:force => {
|
186
|
+
:newton => 1.0, :newtons => 1.0, :N => 1.0,
|
187
|
+
:dyne => 1.0e-5, :dynes => 1.0e-5, :dyn => 1.0e-5,
|
188
|
+
:kilogram_force => 9.80665, :kgf => 9.80665, :kilopond => 9.80665, :kiloponds => 9.80665, :kp => 9.80665,
|
189
|
+
:kip => 4.448222e+3, :kips => 4.448222e+3,
|
190
|
+
:ounce_force => 2.780139e-1, :ozf => 2.780139e-1,
|
191
|
+
:poundal => 1.382550e-1, :poundals => 1.382550e-1,
|
192
|
+
:pound_force => 4.448222, :lbf => 4.448222,
|
193
|
+
:ton_force => 8.896443e+3
|
194
|
+
},
|
195
|
+
:illuminance => {
|
196
|
+
:lux => 1.0, :lx => 1.0, :lumens_per_square_metre => 1.0, :lumens_per_square_meter => 1.0, :lumen_per_square_metre => 1.0, :lumen_per_square_meter => 1.0,
|
197
|
+
:phot => 1.0e+4, :phots => 1.0e+4, :ph => 1.0e+4,
|
198
|
+
:lumens_per_square_foot => 10.76391, :footcandle => 10.76391, :lumen_per_square_foot => 10.76391, :footcandles => 10.76391
|
199
|
+
},
|
200
|
+
:inductance => {
|
201
|
+
:henry => 1.0, :henrys => 1.0, :H => 1.0,
|
202
|
+
:abhenrys => 1.0e-9, :emus_of_inductance => 1.0e-9, :abhenry => 1.0e-9, :emu_of_inductance => 1.0e-9,
|
203
|
+
:stathenrys => 8.987552e+11, :esus_of_inductance => 8.987552e+11, :stathenry => 8.987552e+11, :esu_of_inductance => 8.987552e+11
|
204
|
+
},
|
205
|
+
:information_storage => {
|
206
|
+
:bit => 1.0, :bits => 1.0, :b => 1.0,
|
207
|
+
:byte => 8.0, :bytes => 8.0, :B => 8.0,
|
208
|
+
:nibbles => 4.0, :nybbles => 4.0
|
209
|
+
},
|
210
|
+
:luminous_flux => {
|
211
|
+
:lumen => 1.0, :lumens => 1.0, :lm => 1.0
|
212
|
+
},
|
213
|
+
:luminous_intensity => {
|
214
|
+
:candela => 1.0, :candelas => 1.0, :cd => 1.0
|
215
|
+
},
|
216
|
+
:magnetic_flux => {
|
217
|
+
:webers => 1.0, :Wb => 1.0,
|
218
|
+
:maxwells => 1.0e-8, :Mx => 1.0e-8,
|
219
|
+
:unit_poles => 1.256637e-7
|
220
|
+
},
|
221
|
+
:magnetic_inductance => {
|
222
|
+
:tesla => 1.0, :teslas => 1.0, :T => 1.0,
|
223
|
+
:gamma => 1.0e-9, :gammas => 1.0e-9,
|
224
|
+
:gauss => 1.0e-4, :Gs => 1.0e-4, :G => 1.0e-4
|
225
|
+
},
|
226
|
+
:mass => {
|
227
|
+
:gram => 1.0, :gramme => 1.0, :grams => 1.0, :grammes => 1.0, :g => 1.0,
|
228
|
+
:carat => 2.0e-1, :carats => 2.0e-1,
|
229
|
+
:ounce => 2.834952e+1, :ounces => 2.834952e+1, :oz => 2.834952e+1,
|
230
|
+
:pennyweight => 1.555174, :pennyweights => 1.555174, :dwt => 1.555174,
|
231
|
+
:pound => 453.59237, :pounds => 453.59237, :lb => 453.59237, :lbs => 453.59237,
|
232
|
+
:troy_pound => 373.2417, :apothecary_pound => 373.2417, :troy_pounds => 373.2417, :apothecary_pounds => 373.2417,
|
233
|
+
:slug => 14593.9029, :slugs => 14593.9029,
|
234
|
+
:assay_ton => 29.1667, :assay_tons => 29.1667, :AT => 29.1667,
|
235
|
+
:metric_ton => 1000000, :metric_tons => 1000000,
|
236
|
+
:ton => 907184.74, :tons => 907184.74, :short_tons => 907184.74,
|
237
|
+
#unusual measurements
|
238
|
+
:elephant => 5443108.44, :elephants => 5443108.44
|
239
|
+
},
|
240
|
+
:power => {
|
241
|
+
:watt => 1.0, :watts => 1.0, :W => 1.0,
|
242
|
+
:british_thermal_unit_per_hour => 2.928751e-1, :british_thermal_units_per_hour => 2.928751e-1,
|
243
|
+
:it_british_thermal_unit_per_hour => 2.930711e-1, :it_british_thermal_units_per_hour => 2.930711e-1,
|
244
|
+
:british_thermal_unit_per_second => 1.054350e+3, :british_thermal_units_per_second => 1.054350e+3,
|
245
|
+
:it_british_thermal_unit_per_second => 1.055056e+3, :it_british_thermal_units_per_second => 1.055056e+3,
|
246
|
+
:calorie_per_minute => 6.973333e-2, :calories_per_minute => 6.973333e-2,
|
247
|
+
:calorie_per_second => 4.184, :calories_per_second => 4.184,
|
248
|
+
:erg_per_second => 1.0e-7, :ergs_per_second => 1.0e-7,
|
249
|
+
:foot_pound_force_per_hour => 3.766161e-4,
|
250
|
+
:foot_pound_force_per_minute => 2.259697e-2,
|
251
|
+
:foot_pound_force_per_second => 1.355818,
|
252
|
+
:horsepower => 7.456999e+2,
|
253
|
+
:boiler_horsepower => 9.80950e+3,
|
254
|
+
:electric_horsepower => 7.46e+2,
|
255
|
+
:metric_horsepower => 7.354988e+2,
|
256
|
+
:uk_horsepower => 7.4570e+2,
|
257
|
+
:water_horsepower => 7.46043e+2,
|
258
|
+
:kilocalorie_per_minute => 6.973333*10, :kilocalories_per_minute => 6.973333*10,
|
259
|
+
:kilocalorie_per_second => 4.184e+3, :kilocalories_per_second => 4.184e+3,
|
260
|
+
:ton_of_refrigeration => 3.516853e+3, :tons_of_refrigeration => 3.516853e+3
|
261
|
+
},
|
262
|
+
:pressure => {
|
263
|
+
:pascal => 1.0, :pascals => 1.0, :Pa => 1.0,
|
264
|
+
:atmosphere => 1.01325e+5, :atmospheres => 1.01325e+5,
|
265
|
+
:technical_atmosphere => 9.80665e+4, :technical_atmospheres => 9.80665e+4,
|
266
|
+
:bar => 1.0e+5, :bars => 1.0e+5,
|
267
|
+
:centimeter_of_mercury => 1.333224e+3, :centimeters_of_mercury => 1.333224e+3,
|
268
|
+
:centimeter_of_water => 98.0665, :centimeters_of_water => 98.0665, :gram_force_per_square_centimeter => 98.0665,
|
269
|
+
:dyne_per_square_centimeter => 1.0e-1, :dynes_per_square_centimeter => 1.0e-1,
|
270
|
+
:foot_of_mercury => 4.063666e+4, :feet_of_mercury => 4.063666e+4,
|
271
|
+
:foot_of_water => 2.989067e+3, :feet_of_water => 2.989067e+3,
|
272
|
+
:inch_of_mercury => 3.386389e+3, :inches_of_mercury => 3.386389e+3,
|
273
|
+
:inch_of_water => 2.490889e+2, :inches_of_water => 2.490889e+2,
|
274
|
+
:kilogram_force_per_square_centimeter => 9.80665e+4,
|
275
|
+
:kilogram_force_per_square_meter => 9.80665,
|
276
|
+
:kilogram_force_per_square_millimeter => 9.80665e+6,
|
277
|
+
:kip_per_square_inch => 6.894757e+6, :kips_per_square_inch => 6.894757e+6, :ksi => 6.894757e+6,
|
278
|
+
:millibar => 1.0e+2, :mbar => 1.0e+2, :millibars => 1.0e+2, :mbars => 1.0e+2,
|
279
|
+
:millimeter_of_mercury => 1.333224e+2, :millimeters_of_mercury => 1.333224e+2,
|
280
|
+
:millimeter_of_water => 9.80665, :millimeters_of_water => 9.80665,
|
281
|
+
:poundal_per_square_foot => 1.488164, :poundals_per_square_foot => 1.488164,
|
282
|
+
:pound_force_per_square_foot => 47.88026,
|
283
|
+
:pound_force_per_square_inch => 6.894757e+3, :psi => 6.894757e+3,
|
284
|
+
:torr => 1.333224e+2, :torrs => 1.333224e+2
|
285
|
+
},
|
286
|
+
:radioactivity => {
|
287
|
+
:becquerel => 1.0, :becquerels => 1.0, :Bq => 1.0,
|
288
|
+
:curie => 3.7e+10, :curies => 3.7e+10, :Ci => 3.7e+10
|
289
|
+
},
|
290
|
+
:temperature => {
|
291
|
+
:kelvin => 1.0, :K => 1.0,
|
292
|
+
|
293
|
+
:celsius => [Proc.new{ |t| t + 273.15 }, Proc.new{ |t| t - 273.15 }], :centrigrade => [Proc.new{ |t| t + 273.15 }, Proc.new{ |t| t - 273.15 }],
|
294
|
+
:degree_celsius => [Proc.new{ |t| t + 273.15 }, Proc.new{ |t| t - 273.15 }], :degree_centrigrade => [Proc.new{ |t| t + 273.15 }, Proc.new{ |t| t - 273.15 }],
|
295
|
+
:degrees_celsius => [Proc.new{ |t| t + 273.15 }, Proc.new{ |t| t - 273.15 }], :degrees_centrigrade => [Proc.new{ |t| t + 273.15 }, Proc.new{ |t| t - 273.15 }],
|
296
|
+
:fahrenheit => [Proc.new{ |t| (t + 459.67) * (5.0/9.0) }, Proc.new{ |t| t * (9.0/5.0) - 459.67 }],
|
297
|
+
:degree_fahrenheit => [Proc.new{ |t| (t + 459.67) * (5.0/9.0) }, Proc.new{ |t| t * (9.0/5.0) - 459.67 }],
|
298
|
+
:degrees_fahrenheit => [Proc.new{ |t| (t + 459.67) * (5.0/9.0) }, Proc.new{ |t| t * (9.0/5.0) - 459.67 }],
|
299
|
+
:rankine => 1.8, :rankines => 1.8
|
300
|
+
},
|
301
|
+
:time => {
|
302
|
+
:second => 1.0, :seconds => 1.0, :s => 1.0,
|
303
|
+
:minute => 60.0, :minutes => 60.0, :min => 60.0,
|
304
|
+
:sidereal_minute => 5.983617, :sidereal_minutes => 5.983617,
|
305
|
+
:hour => 3600.0, :hours => 3600.0, :hr => 3600.0, :h => 3600.0,
|
306
|
+
:sidereal_hour => 3.590170e+3, :sidereal_hours => 3.590170e+3,
|
307
|
+
:day => 86400.0, :days => 86400.0,
|
308
|
+
:sidereal_day => 8.616409e+4, :sidereal_days => 8.616409e+4,
|
309
|
+
:shake => 1.0e-8, :shakes => 1.0e-8,
|
310
|
+
:year => 3.1536e+7, :years => 3.1536e+7,
|
311
|
+
:sidereal_year => 3.155815e+7, :sidereal_years => 3.155815e+7,
|
312
|
+
:tropical_year => 3.155693e+7, :tropical_years => 3.155693e+7,
|
313
|
+
#unusual measurements
|
314
|
+
:jiffy => 0.01, :jiffies => 0.01,
|
315
|
+
:microfortnight => 1.2096, :microfortnights => 1.2096,
|
316
|
+
:megaannum => 3.1536e+16, :Ma => 3.1536e+16, :megaannums => 3.1536e+16,
|
317
|
+
:galactic_year => 7.884e+18, :galactic_years => 7.884e+18, :GY => 7.884e+18
|
318
|
+
},
|
319
|
+
:volume => {
|
320
|
+
:litre => 1.0, :liter => 1.0, :litres => 1.0, :liters => 1.0, :l => 1.0, :L => 1.0,
|
321
|
+
:barrel => 1.589873e+2, :barrels => 1.589873e+2,
|
322
|
+
:bushel => 3.523907e+1, :bushels => 3.523907e+1,
|
323
|
+
:cubic_meter => 1000.0, :cubic_meters => 1000.0,
|
324
|
+
:cup => 2.365882e-1, :cups => 2.365882e-1,
|
325
|
+
:imperial_fluid_ounce => 0.0284130742, :imperial_fluid_ounces => 0.0284130742,
|
326
|
+
:ounce => 0.0295735296, :ounces => 0.0295735296, :fluid_ounce => 0.0295735296, :fluid_ounces => 0.0295735296,
|
327
|
+
:imperial_gallon => 4.54609, :imperial_gallons => 4.54609,
|
328
|
+
:gallon => 3.785412, :gallons => 3.785412, :gals => 3.785412, :Gals => 3.785412,
|
329
|
+
:imperial_gill => 1.420653e-1, :imperial_gills => 1.420653e-1,
|
330
|
+
:gill => 1.182941e-1, :gills => 1.182941e-1, :gi => 1.182941e-1,
|
331
|
+
:pint => 5.506105e-1, :pints => 5.506105e-1,
|
332
|
+
:liquid_pint => 4.731765e-1, :liquid_pints => 4.731765e-1,
|
333
|
+
:quart => 1.101221, :quarts => 1.101221,
|
334
|
+
:liquid_quart => 9.463529e-1, :liquid_quarts => 9.463529e-1,
|
335
|
+
:tablespoon => 0.0147867648, :tablespoons => 0.0147867648,
|
336
|
+
:teaspoon => 0.00492892159, :teaspoons => 0.00492892159,
|
337
|
+
#unusual measurements
|
338
|
+
:sydharb => 5.0e+11, :sydharbs => 5.0e+11
|
339
|
+
}
|
340
|
+
}
|
341
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module Metamorphosis
|
4
|
+
class Engine
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
attr_reader :registry
|
8
|
+
|
9
|
+
def numeric_to_unit_value(numeric, unit_name)
|
10
|
+
exponent, unit_symbol = @parser.parse(unit_name)
|
11
|
+
return nil unless @registry.include?(unit_symbol)
|
12
|
+
UnitValue.new(unit_symbol, numeric, exponent)
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
reset!
|
17
|
+
end
|
18
|
+
|
19
|
+
def reset!
|
20
|
+
@registry = UnitRegistry.new
|
21
|
+
@parser = PrefixParser.new(DEFAULT_PREFIXES, @registry)
|
22
|
+
end
|
23
|
+
|
24
|
+
def common_unit_category(source, dest)
|
25
|
+
source_categories = @registry.unit_categories(source)
|
26
|
+
dest_categories = @registry.unit_categories(dest)
|
27
|
+
|
28
|
+
category = (source_categories & dest_categories).first
|
29
|
+
end
|
30
|
+
|
31
|
+
def convert_to(dest_unit_name, source)
|
32
|
+
return source if dest_unit_name.to_sym == source.unit_symbol
|
33
|
+
|
34
|
+
exponent, dest_unit_symbol = @parser.parse(dest_unit_name)
|
35
|
+
return unless @registry.include?(dest_unit_symbol)
|
36
|
+
|
37
|
+
category = common_unit_category(source.unit_symbol, dest_unit_symbol)
|
38
|
+
unless category
|
39
|
+
raise IncompatibleUnitsError,
|
40
|
+
"Cannot convert from #{source.unit_symbol} to #{dest_unit_symbol}"
|
41
|
+
end
|
42
|
+
|
43
|
+
value = to_base_value(category, source)
|
44
|
+
|
45
|
+
from_base_value(category, dest_unit_symbol, value, exponent)
|
46
|
+
end
|
47
|
+
|
48
|
+
def from_base_value(category, dest_unit_symbol, value, exponent)
|
49
|
+
conversion_factor = @registry.conversion_factor(category, dest_unit_symbol)
|
50
|
+
if conversion_factor.is_a?(Array)
|
51
|
+
new_unit_value = conversion_factor[1].call(value)
|
52
|
+
else
|
53
|
+
new_unit_value = value / (exponent * conversion_factor)
|
54
|
+
end
|
55
|
+
UnitValue.new(dest_unit_symbol, new_unit_value)
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_base_value(category, source_unit)
|
59
|
+
conversion_factor = @registry.conversion_factor(category, source_unit.unit_symbol)
|
60
|
+
if(conversion_factor.is_a?(Array))
|
61
|
+
conversion_factor[0].call(source_unit.value) * source_unit.exponent
|
62
|
+
else
|
63
|
+
source_unit.to_f * conversion_factor
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def register_unit(category, symbols, value)
|
68
|
+
value = value.is_a?(UnitValue) ? to_base_value(category, value) : value
|
69
|
+
symbols = Array(symbols)
|
70
|
+
symbols.each do |unit_symbol|
|
71
|
+
@registry.register(category, unit_symbol, value)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.engine
|
78
|
+
Engine.instance
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.register_predefined_units
|
82
|
+
PRE_DEFINED_UNITS.each do |category, units|
|
83
|
+
units.each do |unit_symbol, value|
|
84
|
+
engine.register_unit(category, unit_symbol, value)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.reset!
|
90
|
+
engine.reset!
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.register_unit(category, symbols, value)
|
94
|
+
engine.register_unit(category, symbols, value)
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Metamorphosis
|
2
|
+
class PrefixParser
|
3
|
+
attr_reader :prefixes
|
4
|
+
|
5
|
+
def initialize(prefixes, available_units)
|
6
|
+
@prefixes = prefixes
|
7
|
+
@available_units = available_units
|
8
|
+
end
|
9
|
+
|
10
|
+
# Given a known set of unit names, returns the prefix value,
|
11
|
+
# and the base unit name
|
12
|
+
def parse(unit_text)
|
13
|
+
unit_text = unit_text.to_s
|
14
|
+
@prefixes.each do |prefix, value|
|
15
|
+
unit = parse_unit(unit_text, prefix)
|
16
|
+
next unless unit
|
17
|
+
|
18
|
+
return [value, unit]
|
19
|
+
end
|
20
|
+
[1.0, unit_text.to_sym]
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
#############################################
|
25
|
+
private
|
26
|
+
|
27
|
+
def parse_unit(unit_text, prefix)
|
28
|
+
md = /^#{prefix}(.+)/.match(unit_text)
|
29
|
+
return unless md
|
30
|
+
unit = md[1].to_sym
|
31
|
+
|
32
|
+
@available_units.include?(unit) ? unit : nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Metamorphosis
|
2
|
+
class UnitRegistry
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@categories = Hash.new{|h,k| h[k] = {} }
|
6
|
+
@unit_category_lookup = Hash.new{|h,k| h[k] = Set.new }
|
7
|
+
end
|
8
|
+
|
9
|
+
def register(category, unit, conversion)
|
10
|
+
category_symbol = category.to_sym
|
11
|
+
unit_symbol = unit.to_sym
|
12
|
+
@categories[category_symbol][unit_symbol] = conversion
|
13
|
+
@unit_category_lookup[unit_symbol] << category_symbol
|
14
|
+
end
|
15
|
+
|
16
|
+
def category_names
|
17
|
+
@categories.keys
|
18
|
+
end
|
19
|
+
|
20
|
+
def unit_categories(unit)
|
21
|
+
unit_symbol = unit.is_a?(UnitValue) ? unit.unit_symbol : unit.to_sym
|
22
|
+
@unit_category_lookup[unit_symbol]
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
def conversion_factor(category, unit)
|
27
|
+
@categories[category.to_sym][unit]
|
28
|
+
end
|
29
|
+
|
30
|
+
def include?(unit)
|
31
|
+
@unit_category_lookup.include?(unit.to_sym)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Metamorphosis
|
2
|
+
class UnitValue
|
3
|
+
include Comparable
|
4
|
+
|
5
|
+
attr_reader :unit_symbol, :value, :exponent
|
6
|
+
|
7
|
+
def initialize(unit_symbol, value, exponent = 1.0)
|
8
|
+
@unit_symbol = unit_symbol.to_sym
|
9
|
+
@value = value
|
10
|
+
@exponent = exponent.to_f
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
"#{self.to_f} #{unit_symbol}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_f
|
18
|
+
@exponent * @value
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_i
|
22
|
+
to_f.to_i
|
23
|
+
end
|
24
|
+
|
25
|
+
def <=>(other_unit)
|
26
|
+
unless other_unit.is_a?(UnitValue) || other_unit.is_a?(Numeric)
|
27
|
+
raise ArgumentError,
|
28
|
+
"Unable to compare #{self.to_s} with #{other_unit.class}"
|
29
|
+
end
|
30
|
+
|
31
|
+
# Assume numeric values are of the same unit type
|
32
|
+
return self.to_f <=> other_unit if other_unit.is_a?(Numeric)
|
33
|
+
|
34
|
+
# Convert the unit if they're not the same unit already
|
35
|
+
unless @unit_symbol == other_unit.unit_symbol
|
36
|
+
other_unit = other_unit.to(@unit_symbol)
|
37
|
+
end
|
38
|
+
|
39
|
+
self.to_f <=> other_unit.to_f
|
40
|
+
end
|
41
|
+
|
42
|
+
def to(unit_symbol = nil)
|
43
|
+
return self unless unit_symbol
|
44
|
+
Metamorphosis.engine.convert_to(unit_symbol, self)
|
45
|
+
end
|
46
|
+
alias_method :as, :to
|
47
|
+
|
48
|
+
def method_missing method_name, *args, &block
|
49
|
+
self.to(method_name) ||
|
50
|
+
super( method_name, *args, &block )
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
data/lib/numeric.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems' unless defined? Gem
|
2
|
+
require File.dirname(__FILE__) + "/lib/metamorphosis/version"
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "metamorphosis"
|
5
|
+
s.version = Metamorphosis::VERSION
|
6
|
+
s.authors = ["Ryan Stawarz"]
|
7
|
+
s.email = "rstawarz@wegowise.com"
|
8
|
+
s.homepage = "http://github.com/wegowise/metamorphosis"
|
9
|
+
s.summary = "A library for enabling conversions between units"
|
10
|
+
s.description = "A library for enabling conversions between units"
|
11
|
+
s.add_development_dependency('rspec')
|
12
|
+
s.required_rubygems_version = ">= 1.3.6"
|
13
|
+
s.files = Dir.glob(%w[{lib,spec}/**/*.rb bin/* [A-Z]*.{txt,rdoc,md} ext/**/*.{rb,c}]) + %w{metamorphosis.gemspec}
|
14
|
+
s.license = 'MIT'
|
15
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Metamorphosis::Engine do
|
4
|
+
|
5
|
+
let!(:engine){ Metamorphosis::Engine.instance }
|
6
|
+
|
7
|
+
before{ Metamorphosis.register_predefined_units }
|
8
|
+
after { Metamorphosis.reset! }
|
9
|
+
|
10
|
+
describe "#numeric_to_unit_value" do
|
11
|
+
it "Creates a UnitValue from a numeric value and a unit name" do
|
12
|
+
engine.numeric_to_unit_value(42.0, 'J').
|
13
|
+
should == Metamorphosis::UnitValue.new(:J, 42.0)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "Creates a UnitValue from a numeric value and a unit name with a prefix" do
|
17
|
+
val = engine.numeric_to_unit_value(42.0, 'kJ')
|
18
|
+
val.should == Metamorphosis::UnitValue.new(:J, 42.0, 1_000)
|
19
|
+
val.to_f.should == 42_000
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns nil when the unit_name is not recognized" do
|
23
|
+
engine.numeric_to_unit_value(1.0, 'junk').should be_nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#convert_to" do
|
28
|
+
it "converts 16 ounces to cups" do
|
29
|
+
engine.convert_to(:cups, 16.ounces).to_f.
|
30
|
+
should be_within(0.000001).of(2)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "converts 73 degress F to celsius" do
|
34
|
+
engine.convert_to(:celsius, 73.degree_fahrenheit).to_f.
|
35
|
+
should be_within(0.0001).of(22.7778)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "converts btu's to kilowatt_hour" do
|
39
|
+
engine.convert_to(:kilowatt_hours, 1054.350.british_thermal_units).
|
40
|
+
to_f.should be_within(0.000001).of(0.3087927)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "convert joules's to therms" do
|
44
|
+
engine.convert_to(:therms, 1.J).to_f.
|
45
|
+
should be_within(0.0001).of(1/1.05506e+8)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "converts to the same unit" do
|
49
|
+
engine.convert_to(:therms, 44.therms).to_f.
|
50
|
+
should == 44
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#to_base_value" do
|
55
|
+
it "converts units into base unit values" do
|
56
|
+
engine.to_base_value(:energy, 1.british_thermal_units).
|
57
|
+
should == 1_054.35
|
58
|
+
end
|
59
|
+
|
60
|
+
it "uses the first proc to convert to the base value when provided" do
|
61
|
+
engine.to_base_value(:temperature, 1.3.celsius).
|
62
|
+
should == 274.45
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#from_base_values" do
|
67
|
+
it "converts from base values" do
|
68
|
+
engine.from_base_value(:energy, :british_thermal_units, 1_054.35, 1.0).
|
69
|
+
should == 1.british_thermal_units
|
70
|
+
end
|
71
|
+
|
72
|
+
it "converts from base values using the last proc when provided" do
|
73
|
+
engine.from_base_value(:temperature, :celsius, 274.45, 1.0).to_f.
|
74
|
+
should be_within(0.00000000001).of(1.3)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Incompatible type checking (i.e. area to volume
|
79
|
+
it "raises an Error when the unit types are not compatible" do
|
80
|
+
expect{ engine.convert_to(:square_meter, 16.ounces) }.
|
81
|
+
to raise_error(Metamorphosis::IncompatibleUnitsError)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "will register multiple units symbosl to the same value" do
|
85
|
+
engine.register_unit(:stuff, [:value1a, :value1b], 1.0)
|
86
|
+
engine.register_unit(:stuff, [:value2c, :value2d], 2.0)
|
87
|
+
|
88
|
+
1.value1b.value1a.to_f.should == 1.value1a.to_f
|
89
|
+
1.value1a.should == 1.value1b
|
90
|
+
1.value2c.value1a.to_f.should == 2.0
|
91
|
+
1.value2c.should == 2.value1a
|
92
|
+
1.value2c.should == 1.value2d
|
93
|
+
1.value2d.should == 2.value1b
|
94
|
+
end
|
95
|
+
|
96
|
+
it "#register_units allows units to be defined based on other units" do
|
97
|
+
Metamorphosis.reset!
|
98
|
+
Metamorphosis.register_unit(:energy, :btu, 1.0)
|
99
|
+
Metamorphosis.register_unit(:energy, :therms, 100_000.btu)
|
100
|
+
Metamorphosis.register_unit(:energy, :kwh, 0.03413.therms)
|
101
|
+
1.kwh.to.btu.to_f.should == 3413.0
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Metamorphosis::PrefixParser do
|
4
|
+
let!(:available_units) {Metamorphosis::SI_UNITS }
|
5
|
+
let!(:prefixes) { Metamorphosis::DEFAULT_PREFIXES }
|
6
|
+
let!(:parser) {Metamorphosis::PrefixParser.new(prefixes, available_units)}
|
7
|
+
|
8
|
+
[:meter, :joule].each do |unit|
|
9
|
+
Metamorphosis::DEFAULT_PREFIXES.each do |prefix, value|
|
10
|
+
new_unit = "#{prefix}#{unit}"
|
11
|
+
it "parses #{new_unit}as [#{value}, #{unit}]" do
|
12
|
+
parser.parse(new_unit).should == [value, unit.to_sym]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should parse kJ" do
|
18
|
+
parser.parse("kJ").should == [1000.0, :J]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return the unit with value of 1.0 for unknown prefix" do
|
22
|
+
parser.parse("crazystuff").should == [1.0, :crazystuff]
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should return the unit with value of 1.0 for unknown unit" do
|
26
|
+
parser.parse("kilojunk").should == [1.0, :kilojunk]
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should allow prefixes to be overridden" do
|
30
|
+
prefixes = { :yotta => 2**80, :Y => 2**80,
|
31
|
+
:zetta => 2**70, :Z => 2**70,
|
32
|
+
:exa => 2**60, :E => 2**60,
|
33
|
+
:peta => 2**50, :P => 2**50,
|
34
|
+
:tera => 2**40, :T => 2**40,
|
35
|
+
:giga => 2**30, :G => 2**30,
|
36
|
+
:mega => 2**20, :M => 2**20,
|
37
|
+
:kilo => 2**10, :k => 2**10 }
|
38
|
+
parser = Metamorphosis::PrefixParser.new(prefixes, [:byte])
|
39
|
+
parser.parse("kbyte").should == [1024, :byte]
|
40
|
+
|
41
|
+
parser.parse("Mbyte").should == [1048576, :byte]
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Metamorphosis::UnitRegistry do
|
4
|
+
|
5
|
+
let!(:registry) { Metamorphosis::UnitRegistry.new }
|
6
|
+
let!(:subject) { registry }
|
7
|
+
|
8
|
+
before do
|
9
|
+
registry.register(:wegowise, :btu, 1)
|
10
|
+
registry.register(:wegowise, :therms, 100_000)
|
11
|
+
registry.register(:other, :btu, 22)
|
12
|
+
registry.register(:junk, :whatchamakalit, 0.0000001)
|
13
|
+
end
|
14
|
+
|
15
|
+
its(:category_names) { should match_array [:wegowise, :other, :junk] }
|
16
|
+
|
17
|
+
it "keeps different conversion factors for units across categories" do
|
18
|
+
registry.conversion_factor(:wegowise, :btu).
|
19
|
+
should_not == registry.conversion_factor(:other, :btu)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns the set of categories a unit belongs to" do
|
23
|
+
registry.unit_categories(:btu).to_a.should match_array [:wegowise, :other]
|
24
|
+
registry.unit_categories(:therms).to_a.should == [:wegowise]
|
25
|
+
end
|
26
|
+
|
27
|
+
it "tracks conversion factors for units" do
|
28
|
+
registry.conversion_factor(:wegowise, :btu).should == 1
|
29
|
+
registry.conversion_factor(:wegowise, :therms).should == 100_000
|
30
|
+
registry.conversion_factor(:other, :btu).should == 22
|
31
|
+
end
|
32
|
+
|
33
|
+
it "tracks which units have been registered" do
|
34
|
+
registry.include?(:btu).should be_true
|
35
|
+
registry.include?(:therms).should be_true
|
36
|
+
registry.include?(:joules).should be_false
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Metamorphosis::UnitValue do
|
4
|
+
|
5
|
+
before{ Metamorphosis.register_predefined_units }
|
6
|
+
after { Metamorphosis.reset! }
|
7
|
+
|
8
|
+
let!(:unit) { Metamorphosis::UnitValue.new('therms', 1.3, 1_000) }
|
9
|
+
subject{ unit }
|
10
|
+
|
11
|
+
its(:unit_symbol){ should == :therms }
|
12
|
+
its(:exponent){ should == 1_000 }
|
13
|
+
its(:value){ should == 1.3 }
|
14
|
+
its(:to_s){ should == '1300.0 therms' }
|
15
|
+
its(:to_f){ should == 1300.0 }
|
16
|
+
|
17
|
+
# Comparisons between the same unit
|
18
|
+
it{ should be == Metamorphosis::UnitValue.new(:therms, 1_300) }
|
19
|
+
it{ should be > Metamorphosis::UnitValue.new(:therms, 1_290) }
|
20
|
+
it{ should be < Metamorphosis::UnitValue.new(:therms, 1_310) }
|
21
|
+
|
22
|
+
# Comparisons between different units
|
23
|
+
it{ should be > Metamorphosis::UnitValue.new(:J, 1_000) }
|
24
|
+
it{ should be == Metamorphosis::UnitValue.new(:J, 1.05506e+8 * 1_300) }
|
25
|
+
it{ should be < Metamorphosis::UnitValue.new(:J, 1.05506e+8 * 1_400) }
|
26
|
+
|
27
|
+
# Should not compare units that are not alike (i.e. energy vs. distance)
|
28
|
+
it{ should_not eq(Metamorphosis::UnitValue.new(:meters, 100)) }
|
29
|
+
|
30
|
+
it "compares like units" do
|
31
|
+
Metamorphosis::UnitValue.new('therms', 85.30320550490019).should ==
|
32
|
+
Metamorphosis::UnitValue.new('kilowatt_hour', 2_500)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Don't compare non unit like things
|
36
|
+
it{ should_not be == :x }
|
37
|
+
|
38
|
+
it "raises ArgumentError comparing non numeric/UnitValues with UnitValue" do
|
39
|
+
expect{ unit <=> :x }.to raise_error(ArgumentError)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Assume numeric values are of the same unit
|
43
|
+
it { should be == 1_300 }
|
44
|
+
|
45
|
+
|
46
|
+
it "returns itself when to/as method receives no parameters" do
|
47
|
+
unit.to.should === unit
|
48
|
+
unit.as.should === unit
|
49
|
+
end
|
50
|
+
|
51
|
+
it "delegates conversion to the Metamorphosis::Engine" do
|
52
|
+
Metamorphosis.engine.should_receive(:convert_to).with(:J, unit)
|
53
|
+
unit.to(:J)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "delegates missing methods to the Metamorphosis::Engine" do
|
57
|
+
Metamorphosis.engine.should_receive(:convert_to).with(:J, unit).
|
58
|
+
and_return("cooking with fire!")
|
59
|
+
unit.to(:J).should == "cooking with fire!"
|
60
|
+
end
|
61
|
+
|
62
|
+
it "is a good method_missing citizen when Metamorphosis doesn't know how
|
63
|
+
to convert to the given unit" do
|
64
|
+
Metamorphosis.engine.should_receive(:convert_to).with(:J, unit).
|
65
|
+
and_return(nil)
|
66
|
+
expect{ unit.J }.to raise_error(NoMethodError)
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Metamorphosis do
|
4
|
+
it "Exposes Metamorphosis::Engine as 'engine'" do
|
5
|
+
Metamorphosis.engine.should === Metamorphosis::Engine.instance
|
6
|
+
end
|
7
|
+
|
8
|
+
it "registers the units defined as constants" do
|
9
|
+
Metamorphosis.register_predefined_units
|
10
|
+
1.respond_to?(:kwh)
|
11
|
+
1.respond_to?(:kilowatt_hour)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "exposes 'register_unit' from engine" do
|
15
|
+
Metamorphosis.engine.should_receive(:register_unit).with(:a, :b, :c)
|
16
|
+
Metamorphosis.register_unit(:a, :b, :c)
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Numeric do
|
4
|
+
|
5
|
+
it "delegates missing method calls to the Metamorphosis::Engine" do
|
6
|
+
engine = Metamorphosis::Engine.instance
|
7
|
+
engine.should_receive(:numeric_to_unit_value).with(1.3, :J).
|
8
|
+
and_return('eureka!')
|
9
|
+
|
10
|
+
1.3.J.should == 'eureka!'
|
11
|
+
end
|
12
|
+
|
13
|
+
it "raises a method not found exception when the engine returns an empty result" do
|
14
|
+
engine = Metamorphosis::Engine.instance
|
15
|
+
engine.should_receive(:numeric_to_unit_value).with(1.3, :J).
|
16
|
+
and_return(nil)
|
17
|
+
expect{ 1.3.J }.to raise_error(NoMethodError)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
9
|
+
config.run_all_when_everything_filtered = true
|
10
|
+
config.filter_run :focus
|
11
|
+
|
12
|
+
# Run specs in random order to surface order dependencies. If you find an
|
13
|
+
# order dependency and want to debug it, you can fix the order by providing
|
14
|
+
# the seed, which is printed after each run.
|
15
|
+
# --seed 1234
|
16
|
+
config.order = 'random'
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'metamorphosis'
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: metamorphosis
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ryan Stawarz
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-11-13 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !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: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: A library for enabling conversions between units
|
31
|
+
email: rstawarz@wegowise.com
|
32
|
+
executables: []
|
33
|
+
extensions: []
|
34
|
+
extra_rdoc_files: []
|
35
|
+
files:
|
36
|
+
- lib/metamorphosis/constants.rb
|
37
|
+
- lib/metamorphosis/engine.rb
|
38
|
+
- lib/metamorphosis/errors.rb
|
39
|
+
- lib/metamorphosis/prefix_parser.rb
|
40
|
+
- lib/metamorphosis/unit_registry.rb
|
41
|
+
- lib/metamorphosis/unit_value.rb
|
42
|
+
- lib/metamorphosis/version.rb
|
43
|
+
- lib/metamorphosis.rb
|
44
|
+
- lib/numeric.rb
|
45
|
+
- spec/lib/metamorphosis/engine_spec.rb
|
46
|
+
- spec/lib/metamorphosis/prefix_parser_spec.rb
|
47
|
+
- spec/lib/metamorphosis/unit_registry_spec.rb
|
48
|
+
- spec/lib/metamorphosis/unit_value_spec.rb
|
49
|
+
- spec/lib/metamorphosis_spec.rb
|
50
|
+
- spec/lib/numeric_spec.rb
|
51
|
+
- spec/spec_helper.rb
|
52
|
+
- LICENSE.txt
|
53
|
+
- README.md
|
54
|
+
- metamorphosis.gemspec
|
55
|
+
homepage: http://github.com/wegowise/metamorphosis
|
56
|
+
licenses:
|
57
|
+
- MIT
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ! '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ! '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 1.3.6
|
74
|
+
requirements: []
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.8.24
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: A library for enabling conversions between units
|
80
|
+
test_files: []
|