Unit conversion
This commit is contained in:
parent
faf1d20f17
commit
5f955564fb
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user