lib/asciimath2unitsml/conv.rb in asciimath2unitsml-0.3.3 vs lib/asciimath2unitsml/conv.rb in asciimath2unitsml-0.4.0

- old
+ new

@@ -1,10 +1,12 @@ require "asciimath" require "nokogiri" require "htmlentities" require "yaml" require "rsec" +require_relative "read" +require_relative "dimensions" require_relative "string" require_relative "parse" require_relative "render" require_relative "unit" require_relative "validate" @@ -17,10 +19,11 @@ def initialize(options = {}) @dimensions_id = read_yaml("../unitsdb/dimensions.yaml") .each_with_object({}) do |(k, v), m| m[k.to_s] = UnitsDB::Dimension.new(k, v) end + @dimensions = flip_name_and_symbols(@dimensions_id) @prefixes_id = read_yaml("../unitsdb/prefixes.yaml") .each_with_object({}) do |(k, v), m| m[k] = UnitsDB::Prefix.new(k, v) end @prefixes = flip_name_and_symbol(@prefixes_id) @@ -31,14 +34,14 @@ @units_id = read_yaml("../unitsdb/units.yaml") .each_with_object({}) do |(k, v), m| m[k.to_s] = UnitsDB::Unit.new(k.to_s, v) end @units = flip_name_and_symbols(@units_id) - @symbols = @units.each_with_object({}) do |(_k, v), m| + @symbols = @units.merge(@dimensions).each_with_object({}) do |(_k, v), m| v.symbolids.each { |x| m[x] = v.symbols_hash[x] } end - @parser = parser + @parser, @dim_parser = parsers @multiplier = multiplier(options[:multiplier] || "\u22c5") end def float_to_display(float) float.to_f.round(1).to_s.sub(/\.0$/, "") @@ -57,74 +60,21 @@ </Prefix> XML end.join("\n") end - def dimension_components(dims) - return if dims.nil? || dims.empty? - - <<~XML - <Dimension xmlns='#{UNITSML_NS}' xml:id="#{dim_id(dims)}"> - #{dims.map { |u| dimension1(u) }.join("\n")} - </Dimension> - XML - end - - U2D = { - "m" => { dimension: "Length", order: 1, symbol: "L" }, - "g" => { dimension: "Mass", order: 2, symbol: "M" }, - "kg" => { dimension: "Mass", order: 2, symbol: "M" }, - "s" => { dimension: "Time", order: 3, symbol: "T" }, - "A" => { dimension: "ElectricCurrent", order: 4, symbol: "I" }, - "K" => { dimension: "ThermodynamicTemperature", order: 5, - symbol: "Theta" }, - "degK" => { dimension: "ThermodynamicTemperature", order: 5, - symbol: "Theta" }, - "mol" => { dimension: "AmountOfSubstance", order: 6, symbol: "N" }, - "cd" => { dimension: "LuminousIntensity", order: 7, symbol: "J" }, - "deg" => { dimension: "PlaneAngle", order: 8, symbol: "Phi" }, - }.freeze - - def units2dimensions(units) - norm = decompose_units(units) - return if norm.any? do |u| - u[:unit] == "unknown" || u[:prefix] == "unknown" || u[:unit].nil? - end - - norm.map do |u| - { dimension: U2D[u[:unit]][:dimension], - unit: u[:unit], - exponent: u[:exponent] || 1, - symbol: U2D[u[:unit]][:symbol] } - end.sort { |a, b| U2D[a[:unit]][:order] <=> U2D[b[:unit]][:order] } - end - - def dimension1(dim) - %(<#{dim[:dimension]} symbol="#{dim[:symbol]}" - powerNumerator="#{float_to_display(dim[:exponent])}"/>) - end - - def dim_id(dims) - return nil if dims.nil? || dims.empty? - - dimhash = dims.each_with_object({}) { |h, m| m[h[:dimension]] = h } - dimsvector = %w(Length Mass Time ElectricCurrent ThermodynamicTemperature - AmountOfSubstance LuminousIntensity PlaneAngle) - .map { |h| dimhash.dig(h, :exponent) }.join(":") - id = @dimensions_id&.values&.select { |d| d.vector == dimsvector } - &.first&.id and return id.to_s - "D_" + dims.map do |d| - U2D[d[:unit]][:symbol] + - (d[:exponent] == 1 ? "" : float_to_display(d[:exponent])) - end.join("") - end - def decompose_units(units) gather_units(units_only(units).map { |u| decompose_unit(u) }.flatten) end def gather_units(units) + if units[0][:dim] then gather_dimensions(units) + else gather_units1(units) + end + end + + def gather_units1(units) units.sort_by { |a| a[:unit] }.each_with_object([]) do |k, m| if m.empty? || m[-1][:unit] != k[:unit] then m << k else m[-1] = { prefix: combine_prefixes( @@ -136,16 +86,28 @@ } end end end + def gather_dimensions(units) + units.sort_by { |a| a[:dim] }.each_with_object([]) do |k, m| + if m.empty? || m[-1][:dim] != k[:dim] then m << k + else + m[-1] = { + dim: m[-1][:dim], + exponent: (k[:exponent]&.to_f || 1) + + (m[-1][:exponent]&.to_f || 1), + } + end + end + end + # treat g not kg as base unit: we have stripped the prefix k in parsing # reduce units down to basic units def decompose_unit(u) - if u[:unit].nil? then u - elsif u[:unit] == "g" then u - elsif @units[u[:unit]].system_type == "SI_base" then u + if u[:unit].nil? || u[:unit] == "g" || + @units[u[:unit]].system_type == "SI_base" then u elsif !@units[u[:unit]].si_derived_bases { prefix: u[:prefix], unit: "unknown", exponent: u[:exponent] } else @units[u[:unit]].si_derived_bases.each_with_object([]) do |k, m| prefix = if !k[:prefix].nil? && !k[:prefix].empty? @@ -190,28 +152,9 @@ dim = %( dimensionURL="##{@units[normtext].dimension}") <<~XML <Quantity xmlns='#{UNITSML_NS}' xml:id="#{id}"#{dim} quantityType="base"> #{quantityname(id)} </Quantity> - XML - end - - def dimid2dimensions(normtext) - @dimensions_id[normtext].keys.map do |k| - { dimension: k, - symbol: U2D.values.select { |v| v[:dimension] == k }.first[:symbol], - exponent: @dimensions_id[normtext].exponent(k) } - end - end - - def dimension(normtext) - return unless @units[normtext]&.dimension - - dims = dimid2dimensions(@units[normtext]&.dimension) - <<~XML - <Dimension xmlns='#{UNITSML_NS}' xml:id="#{@units[normtext]&.dimension}"> - #{dims.map { |u| dimension1(u) }.join("\n")} - </Dimension> XML end def unitsml(units, origtext, normtext, quantity, name) dims = units2dimensions(units)