module Asciimath2UnitsML class Conv 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 Dim2D = { "dim_L" => U2D["m"], "dim_M" => U2D["g"], "dim_T" => U2D["s"], "dim_I" => U2D["A"], "dim_Theta" => U2D["K"], "dim_N" => U2D["mol"], "dim_J" => U2D["cd"], "dim_phi" => U2D["deg"], }.freeze def units2dimensions(units) norm = decompose_units(units) return units2dimensions_dim_input(norm) if norm[0][:dim] 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 units2dimensions_dim_input(norm) norm.map do |u| { dimension: Dim2D[u[:dim]][:dimension], exponent: u[:exponent] || 1, id: u[:dim], symbol: Dim2D[u[:dim]][:symbol] } end.sort { |a, b| Dim2D[a[:id]][:order] <=> Dim2D[b[:id]][: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.dig(d[:unit], :symbol) || Dim2D.dig(d[:id], :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 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) <<~XML #{unit(units, origtext, normtext, dims, name)} #{prefix(units)} #{dimension(normtext)} #{dimension_components(dims)} #{quantity(normtext, quantity)} XML end end end