parsley/lib/unit_conversion/conversions.rb

144 lines
3.9 KiB
Ruby
Raw Normal View History

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?
2016-02-27 20:23:14 -06:00
value_unit = value_unit.convert('oz').auto_unit.change_formatter(RationalFormatter.new)
2016-02-27 20:12:41 -06:00
elsif value_unit.volume?
2016-02-27 20:23:14 -06:00
value_unit = value_unit.convert('cup').auto_unit.change_formatter(RationalFormatter.new)
2016-02-27 20:12:41 -06:00
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
end