Sha256: 29503db2fa8f97100d780569e6a7cd215443d17d88019ca962243ce8bad312c8

Contents?: true

Size: 1.62 KB

Versions: 10

Compression:

Stored size: 1.62 KB

Contents

class Measured::ConversionTable

  def initialize(units)
    @units = units
  end

  def to_h
    table = {}

    @units.map{|u| u.name}.each do |to_unit|
      to_table = {to_unit => BigDecimal("1")}

      table.each do |from_unit, from_table|
        to_table[from_unit] = find_conversion(to: from_unit, from: to_unit)
        from_table[to_unit] = find_conversion(to: to_unit, from: from_unit)
      end

      table[to_unit] = to_table
    end

    table
  end

  private

  def find_conversion(to:, from:)
    conversion = find_direct_conversion(to: to, from: from) || find_tree_traversal_conversion(to: to, from: from)

    raise Measured::UnitError, "Cannot find conversion path from #{ from } to #{ to }." unless conversion

    conversion
  end

  def find_direct_conversion(to:, from:)
    @units.each do |unit|
      return unit.conversion_amount if unit.name == from && unit.conversion_unit == to
    end

    @units.each do |unit|
      return unit.inverse_conversion_amount if unit.name == to && unit.conversion_unit == from
    end

    nil
  end

  def find_tree_traversal_conversion(to:, from:)
    traverse(from: from, to: to, unit_names: @units.map{|u| u.name }, amount: BigDecimal("1"))
  end

  def traverse(from:, to:, unit_names:, amount:)
    unit_names = unit_names - [from]

    unit_names.each do |name|
      if conversion = find_direct_conversion(from: from, to: name)
        if name == to
          return amount * conversion
        else
          result = traverse(from: name, to: to, unit_names: unit_names, amount: amount * conversion)
          return result if result
        end
      end
    end

    nil
  end

end

Version data entries

10 entries across 10 versions & 1 rubygems

Version Path
measured-0.0.11 lib/measured/conversion_table.rb
measured-0.0.10 lib/measured/conversion_table.rb
measured-0.0.9 lib/measured/conversion_table.rb
measured-0.0.8 lib/measured/conversion_table.rb
measured-0.0.7 lib/measured/conversion_table.rb
measured-0.0.6 lib/measured/conversion_table.rb
measured-0.0.4 lib/measured/conversion_table.rb
measured-0.0.3 lib/measured/conversion_table.rb
measured-0.0.2 lib/measured/conversion_table.rb
measured-0.0.1 lib/measured/conversion_table.rb