Unit conversion

This commit is contained in:
Dan Elbert 2016-01-15 16:09:34 -06:00
parent faf1d20f17
commit 5f955564fb
2 changed files with 48 additions and 8 deletions

View File

@ -48,6 +48,20 @@ module UnitConversion
unit.compatible_with? Unitwise(1, 'g/ml')
end
def volume?(unit)
unit.compatible_with? Unitwise(1, 'ml')
end
def mass?(unit)
unit.compatible_with? Unitwise(1, 'g')
end
def get_density(str)
unit = parse(str)
raise UnknownUnitError, "#{str} expected to be a density" unless density?(unit)
unit
end
def normalize_unit_names(unit_description)
unit_description.downcase.gsub(/[a-z]+/) do |match|
UNIT_ALIAS_MAP[match] || match
@ -71,7 +85,7 @@ module UnitConversion
end
end
def convert(quantity, factor, input_unit, output_unit)
def convert(quantity, factor, input_unit, output_unit, density = nil)
value = get_value(quantity)
factor = get_value(factor)
@ -80,23 +94,36 @@ module UnitConversion
factor = factor.to_d(10)
end
input_unit = normalize_unit_names(input_unit)
output_unit = normalize_unit_names(output_unit)
converted = value * factor
original = Unitwise(value, input_unit)
scaled = original * factor
input_unit = normalize_unit_names(input_unit) unless input_unit.nil?
output_unit = normalize_unit_names(output_unit) unless output_unit.nil?
converted = scaled.convert_to output_unit
if input_unit && output_unit && input_unit != output_unit
in_unit = Unitwise(1, input_unit)
out_unit = Unitwise(1, output_unit)
unit = Unitwise(converted, input_unit)
if volume?(in_unit) && mass?(out_unit)
unit_density = get_density(density)
unit = unit * unit_density
elsif mass?(in_unit) && volume?(out_unit)
unit_density = get_density(density)
unit = unit / unit_density
end
converted = unit.convert_to(output_unit).value
end
if value.is_a? Rational
rational_val = converted.value.to_r.rationalize(0.001)
rational_val = converted.to_r.rationalize(0.001)
if rational_val.denominator == 1
rational_val.to_i.to_s
else
rational_val.to_s
end
else
"%g" % ("%.3f" % converted.value)
"%g" % ("%.3f" % converted)
end
end

View File

@ -40,11 +40,24 @@ RSpec.describe UnitConversion do
expect(UnitConversion.convert('2.0', '1', 'tablespoon', 'cup')).to eq '0.125'
end
it 'scales odd units without conversion' do
expect(UnitConversion.convert('1/2', '2', 'slices', 'slices')).to eq '1'
expect(UnitConversion.convert('4', '1/8', nil, nil)).to eq '1/2'
end
it 'converts and scales' do
expect(UnitConversion.convert('1/2', '2', 'cup', 'tbsp')).to eq '16'
expect(UnitConversion.convert('2.0', '1 1/2', 'tablespoon', 'cup')).to eq '0.188'
expect(UnitConversion.convert('2', '1 1/2', 'tablespoon', 'cup')).to eq '3/16'
end
it 'converts from volume to mass' do
expect(UnitConversion.convert('5', '1', 'cup', 'ounce', '5 oz/c')).to eq '25'
end
it 'converts from mass to volume' do
expect(UnitConversion.convert('25', '1', 'ounce', 'cup', '5 oz/c')).to eq '5'
end
end
describe '.parse' do