2016-02-02 15:48:20 -06:00
|
|
|
module UnitConversion
|
|
|
|
|
|
|
|
class Conversion
|
|
|
|
end
|
|
|
|
|
|
|
|
class ScaleConversion < Conversion
|
|
|
|
def initialize(parsed_factor)
|
|
|
|
@factor = parsed_factor
|
|
|
|
end
|
|
|
|
|
|
|
|
def convert(value_unit)
|
|
|
|
value = @factor.value * value_unit.value.value
|
|
|
|
ValueUnit.for(value, value_unit.unit, value_unit.formatter)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class ConvertConversion < Conversion
|
|
|
|
def initialize(parsed_unit, density_unit_value = nil)
|
|
|
|
@target_unit = parsed_unit
|
|
|
|
|
|
|
|
raise UnknownUnitError, "#{density_unit_value} is not a density" if density_unit_value && !density_unit_value.density?
|
|
|
|
@density = density_unit_value
|
|
|
|
end
|
|
|
|
|
|
|
|
def convert(value_unit)
|
|
|
|
|
|
|
|
input = value_unit.unitwise
|
|
|
|
|
|
|
|
if value_unit.volume? && @target_unit.mass?
|
|
|
|
raise MissingDensityError, "Cannot convert #{value_unit.unit} to #{@target_unit} without density" unless @density
|
|
|
|
input = input * @density.unitwise
|
|
|
|
elsif value_unit.mass? && @target_unit.volume?
|
|
|
|
raise MissingDensityError, "Cannot convert #{value_unit.unit} to #{@target_unit} without density" unless @density
|
|
|
|
input = input / @density.unitwise
|
|
|
|
end
|
|
|
|
|
|
|
|
input = input.convert_to @target_unit.unit
|
|
|
|
|
|
|
|
formatter = @target_unit.metric? ? DecimalFormatter.new : value_unit.formatter
|
|
|
|
|
|
|
|
ValueUnit.for(input.value, @target_unit, formatter)
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class AutoUnitConversion < Conversion
|
|
|
|
|
|
|
|
def convert(value_unit)
|
|
|
|
|
|
|
|
unless known_auto_unit?(value_unit.unit)
|
|
|
|
return value_unit
|
|
|
|
end
|
|
|
|
|
|
|
|
value = value_unit.raw_value
|
|
|
|
unit = value_unit.unit.unit
|
|
|
|
new_unit = unit
|
|
|
|
|
|
|
|
unit_orders = UNIT_ORDERS.values.detect { |orders| orders.include?(unit.to_sym) }
|
|
|
|
unit_range = UNIT_RANGES[unit.to_sym]
|
|
|
|
|
|
|
|
if value < unit_range.first
|
|
|
|
unit_orders = unit_orders.reverse
|
|
|
|
end
|
|
|
|
|
|
|
|
idx = unit_orders.index(new_unit.to_sym)
|
|
|
|
|
|
|
|
while !unit_range.include?(value) && idx < (unit_orders.length - 1)
|
|
|
|
idx += 1
|
|
|
|
next_unit = unit_orders[idx]
|
|
|
|
value = Unitwise(value, new_unit).convert_to(next_unit).value
|
|
|
|
new_unit = next_unit.to_s
|
|
|
|
unit_range = UNIT_RANGES[new_unit.to_sym]
|
|
|
|
end
|
|
|
|
|
|
|
|
ValueUnit.for(value, new_unit, value_unit.formatter)
|
|
|
|
end
|
|
|
|
|
|
|
|
def known_auto_unit?(unit)
|
|
|
|
unit && UNIT_ORDERS.values.flatten.include?(unit.unit.to_sym)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-02-27 20:12:41 -06:00
|
|
|
class MetricUnitConversion < Conversion
|
|
|
|
def convert(value_unit)
|
|
|
|
if value_unit.unit && !value_unit.unit.metric?
|
|
|
|
if value_unit.mass?
|
|
|
|
value_unit = value_unit.convert('g').auto_unit
|
|
|
|
elsif value_unit.volume?
|
|
|
|
value_unit = value_unit.convert('ml').auto_unit
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
value_unit
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class StandardUnitConversion < Conversion
|
|
|
|
def convert(value_unit)
|
|
|
|
if value_unit.unit && value_unit.unit.metric?
|
|
|
|
if value_unit.mass?
|
|
|
|
value_unit = value_unit.convert('oz').auto_unit
|
|
|
|
elsif value_unit.volume?
|
|
|
|
value_unit = value_unit.convert('cup').auto_unit
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
value_unit
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class VolumeUnitConversion < Conversion
|
|
|
|
def initialize(density_unit_value)
|
|
|
|
raise UnknownUnitError, "#{density_unit_value} is not a density" if !density_unit_value.density?
|
|
|
|
@density = density_unit_value
|
|
|
|
end
|
|
|
|
|
|
|
|
def convert(value_unit)
|
|
|
|
if value_unit.mass?
|
|
|
|
unit = value_unit.unit.metric? ? 'ml' : 'cup'
|
|
|
|
value_unit.convert(unit, @density).auto_unit
|
|
|
|
else
|
|
|
|
value_unit
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class MassUnitConversion < Conversion
|
|
|
|
def initialize(density_unit_value)
|
|
|
|
raise UnknownUnitError, "#{density_unit_value} is not a density" if !density_unit_value.density?
|
|
|
|
@density = density_unit_value
|
|
|
|
end
|
|
|
|
|
|
|
|
def convert(value_unit)
|
|
|
|
if value_unit.volume?
|
|
|
|
unit = value_unit.unit.metric? ? 'g' : 'oz'
|
|
|
|
value_unit.convert(unit, @density).auto_unit
|
|
|
|
else
|
|
|
|
value_unit
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-02-02 15:48:20 -06:00
|
|
|
end
|