Class: Plurimath::Utility

Inherits:
Object
  • Object
show all
Defined in:
lib/plurimath/utility.rb

Constant Summary collapse

FONT_STYLES =
{
  "double-struck": Math::Function::FontStyle::DoubleStruck,
  "sans-serif": Math::Function::FontStyle::SansSerif,
  monospace: Math::Function::FontStyle::Monospace,
  fraktur: Math::Function::FontStyle::Fraktur,
  script: Math::Function::FontStyle::Script,
  normal: Math::Function::FontStyle::Normal,
  bold: Math::Function::FontStyle::Bold,
  mathfrak: Math::Function::FontStyle::Fraktur,
  mathcal: Math::Function::FontStyle::Script,
  mathbb: Math::Function::FontStyle::DoubleStruck,
  mathtt: Math::Function::FontStyle::Monospace,
  mathsf: Math::Function::FontStyle::SansSerif,
  mathrm: Math::Function::FontStyle::Normal,
  textrm: Math::Function::FontStyle::Normal,
  mathbf: Math::Function::FontStyle::Bold,
  textbf: Math::Function::FontStyle::Bold,
  bbb: Math::Function::FontStyle::DoubleStruck,
  cal: Math::Function::FontStyle::Script,
  bf: Math::Function::FontStyle::Bold,
  sf: Math::Function::FontStyle::SansSerif,
  tt: Math::Function::FontStyle::Monospace,
  fr: Math::Function::FontStyle::Fraktur,
  rm: Math::Function::FontStyle::Normal,
  cc: Math::Function::FontStyle::Script,
  ii: Math::Function::FontStyle::Italic,
  bb: Math::Function::FontStyle::Bold,
}.freeze
ALIGNMENT_LETTERS =
{
  c: "center",
  r: "right",
  l: "left",
}.freeze
UNARY_CLASSES =
%w[
  arccos
  arcsin
  arctan
  right
  sech
  sinh
  tanh
  cosh
  coth
  csch
  left
  max
  min
  sec
  sin
  deg
  det
  dim
  exp
  gcd
  glb
  lub
  tan
  cos
  cot
  csc
  ln
  lg
  f
  g
].freeze
MUNDER_CLASSES =
%w[
  ubrace
  obrace
  right
  max
  min
].freeze

Class Method Summary collapse

Class Method Details

.filter_table_data(table_data) ⇒ Object



140
141
142
143
144
145
146
147
148
149
# File 'lib/plurimath/utility.rb', line 140

def filter_table_data(table_data)
  table_data.each_with_index do |object, ind|
    if symbol_value(object, "-")
      table_data[ind] = Math::Formula.new(
        [object, table_data.delete_at(ind.next)],
      )
    end
  end
  table_data
end

.filter_values(array) ⇒ Object



208
209
210
211
212
213
214
215
216
217
# File 'lib/plurimath/utility.rb', line 208

def filter_values(array)
  return array unless array.is_a?(Array)

  array = array.flatten.compact
  if array.length > 1
    return Math::Formula.new(array)
  end

  array.first
end

.find_class_name(object) ⇒ Object



242
243
244
245
# File 'lib/plurimath/utility.rb', line 242

def find_class_name(object)
  new_object = object.value.first.parameter_one if object.is_a?(Math::Formula)
  get_class(new_object) unless new_object.nil?
end

.find_pos_chr(fonts_array, key) ⇒ Object



247
248
249
# File 'lib/plurimath/utility.rb', line 247

def find_pos_chr(fonts_array, key)
  fonts_array.find { |d| d.is_a?(Hash) && d[key] }
end

.frac_values(object) ⇒ Object



375
376
377
378
379
380
381
382
# File 'lib/plurimath/utility.rb', line 375

def frac_values(object)
  case object
  when Math::Formula
    object.value.any? { |d| symbol_value(d, ",") }
  when Array
    object.any? { |d| symbol_value(d, ",") }
  end
end

.get_class(text) ⇒ Object



163
164
165
166
167
168
# File 'lib/plurimath/utility.rb', line 163

def get_class(text)
  text = text.to_s.split("_").map(&:capitalize).join
  Object.const_get(
    "Plurimath::Math::Function::#{text}",
  )
end

.get_table_class(text) ⇒ Object



151
152
153
154
155
# File 'lib/plurimath/utility.rb', line 151

def get_table_class(text)
  Object.const_get(
    "Plurimath::Math::Function::Table::#{text.to_s.capitalize}",
  )
end

.join_attr_value(attrs, value) ⇒ Object



317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
# File 'lib/plurimath/utility.rb', line 317

def join_attr_value(attrs, value)
  if value.any?(String)
    new_value = mathml_unary_classes(value)
    array_value = Array(new_value)
    attrs.nil? ? array_value : join_attr_value(attrs, array_value)
  elsif attrs.nil?
    value
  elsif attrs.is_a?(Math::Function::Menclose)
    attrs.parameter_two = filter_values(value)
    attrs
  elsif attrs.is_a?(Math::Function::Fenced)
    attrs.parameter_two = value.compact
    attrs
  elsif attrs.is_a?(Math::Function::FontStyle)
    attrs.parameter_one = filter_values(value)
    attrs
  elsif attrs.is_a?(Math::Function::Color)
    color_value = filter_values(value)
    if attrs.parameter_two
      attrs.parameter_two.parameter_one = color_value
    else
      attrs.parameter_two = color_value
    end
    attrs
  elsif ["solid", "none"].include?(attrs.split.first.downcase)
    table_separator(attrs.split, value)
  end
end

.left_right_objects(paren, function) ⇒ Object



411
412
413
414
415
416
417
418
# File 'lib/plurimath/utility.rb', line 411

def left_right_objects(paren, function)
  paren = if paren.to_s.match?(/\\{|\\}/)
            paren.to_s.gsub(/\\/, "")
          else
            Latex::Constants::LEFT_RIGHT_PARENTHESIS[paren.to_sym]
          end
  get_class(function).new(paren)
end

.mathml_unary_classes(text_array) ⇒ Object



274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/plurimath/utility.rb', line 274

def mathml_unary_classes(text_array)
  return [] if text_array.empty?

  compacted = text_array.compact
  string = if compacted.count == 1
             compacted.first
           else
             compacted.join
           end
  return string unless string.is_a?(String)

  classes = Mathml::Constants::CLASSES
  unicode = string_to_html_entity(string)
  symbol  = Mathml::Constants::UNICODE_SYMBOLS[unicode.strip.to_sym]
  if classes.include?(symbol&.strip)
    get_class(symbol.strip).new
  elsif classes.any?(string&.strip)
    get_class(string.strip).new
  else
    Math::Symbol.new(unicode)
  end
end

.multiscript(values) ⇒ Object



346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
# File 'lib/plurimath/utility.rb', line 346

def multiscript(values)
  values.slice_before("mprescripts").map do |value|
    base_value   = value.shift
    part_val     = value.partition.with_index { |_, i| i.even? }
    first_value  = part_val[0].empty? ? nil : filter_values(part_val[0])
    second_value = part_val[1].empty? ? nil : filter_values(part_val[1])
    if base_value.to_s.include?("mprescripts")
      [first_value, second_value]
    else
      Math::Function::PowerBase.new(
        base_value,
        first_value,
        second_value,
      )
    end
  end
end

.nary_fonts(nary) ⇒ Object



232
233
234
235
236
237
238
239
240
# File 'lib/plurimath/utility.rb', line 232

def nary_fonts(nary)
  narypr = nary.first.flatten.compact
  subsup = narypr.any?("undOvr") ? "underover" : "power_base"
  get_class(subsup).new(
    Math::Symbol.new(narypr.any?(Hash) ? narypr.first[:chr] : ""),
    nary[1],
    nary[2],
  )
end

.organize_options(table_data, column_align) ⇒ Object



108
109
110
111
112
113
114
# File 'lib/plurimath/utility.rb', line 108

def organize_options(table_data, column_align)
  return column_align if column_align.length <= 1

  align = [column_align&.shift]
  table_data.insert(0, *column_align)
  align
end

.organize_table(array, column_align: nil, options: nil) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/plurimath/utility.rb', line 79

def organize_table(array, column_align: nil, options: nil)
  table = []
  table_data = []
  table_row = []
  table_separators = ["&", "\\\\"].freeze
  organize_options(array, column_align) if options
  string_columns = column_align&.map(&:value)
  array.each do |data|
    if data.is_a?(Math::Symbol) && table_separators.include?(data.value)
      table_row << Math::Function::Td.new(filter_table_data(table_data).compact)
      table_data = []
      if data.value == "\\\\"
        organize_tds(table_row.flatten, string_columns.dup, options)
        table << Math::Function::Tr.new(table_row)
        table_row = []
      end
      next
    end
    table_data << data
  end
  table_row << Math::Function::Td.new(table_data.compact) if table_data
  unless table_row.nil? || table_row.empty?
    organize_tds(table_row.flatten, string_columns.dup, options)
    table << Math::Function::Tr.new(table_row)
  end
  table_separator(string_columns, table, symbol: "|") unless column_align.nil? || column_align.empty?
  table
end

.organize_tds(tr_array, column_align, options) ⇒ Object



129
130
131
132
133
134
135
136
137
138
# File 'lib/plurimath/utility.rb', line 129

def organize_tds(tr_array, column_align, options)
  return tr_array if column_align.nil? || column_align.empty?

  column_align.reject! { |string| string == "|" }
  column_align = column_align * tr_array.length if options
  tr_array.map.with_index do |td, ind|
    columnalign = ALIGNMENT_LETTERS[column_align[ind]&.to_sym]
    td.parameter_two = { columnalign: columnalign } if columnalign
  end
end

.ox_element(node, attributes: [], namespace: "") ⇒ Object



170
171
172
173
174
175
176
177
178
# File 'lib/plurimath/utility.rb', line 170

def ox_element(node, attributes: [], namespace: "")
  namespace = "#{namespace}:" unless namespace.empty?

  element = Ox::Element.new("#{namespace}#{node}")
  attributes&.each do |attr_key, attr_value|
    element[attr_key] = attr_value
  end
  element
end

.pr_element(main_tag, wi_tag = false, namespace: "") ⇒ Object



200
201
202
203
204
205
206
# File 'lib/plurimath/utility.rb', line 200

def pr_element(main_tag, wi_tag = false, namespace: "")
  tag_name = "#{main_tag}Pr"
  ox_element(
    tag_name,
    namespace: namespace,
  ) << rpr_element(wi_tag: wi_tag)
end

.rpr_element(wi_tag: false) ⇒ Object



180
181
182
183
184
185
186
187
188
189
190
# File 'lib/plurimath/utility.rb', line 180

def rpr_element(wi_tag: false)
  rpr_element = ox_element("rPr", namespace: "w")
  attributes = { "w:ascii": "Cambria Math", "w:hAnsi": "Cambria Math" }
  rpr_element << ox_element(
    "rFonts",
    namespace: "w",
    attributes: attributes,
  )
  rpr_element << ox_element("i", namespace: "w") if wi_tag
  rpr_element
end

.string_to_html_entity(string) ⇒ Object



297
298
299
300
# File 'lib/plurimath/utility.rb', line 297

def string_to_html_entity(string)
  entities = HTMLEntities.new
  entities.encode(string, :hexadecimal)
end

.sub_sup_method?(sub_sup) ⇒ Boolean

Returns:

  • (Boolean)


157
158
159
160
161
# File 'lib/plurimath/utility.rb', line 157

def sub_sup_method?(sub_sup)
  if sub_sup.methods.include?(:class_name)
    Html::Constants::SUB_SUP_CLASSES.value?(sub_sup.class_name.to_sym)
  end
end

.symbol_object(value) ⇒ Object



394
395
396
397
398
399
400
401
# File 'lib/plurimath/utility.rb', line 394

def symbol_object(value)
  value = case value
          when "" then "{:"
          when "" then ":}"
          else value
          end
  Math::Symbol.new(value)
end

.symbol_value(object, value) ⇒ Object



262
263
264
# File 'lib/plurimath/utility.rb', line 262

def symbol_value(object, value)
  object.is_a?(Math::Symbol) && object.value.include?(value)
end

.table_options(table_data) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/plurimath/utility.rb', line 116

def table_options(table_data)
  rowline = ""
  table_data.map do |tr|
    if symbol_value(tr&.parameter_one&.first&.parameter_one&.first, "&#x23af;")
      rowline += "solid "
    else
      rowline += "none "
    end
  end
  options = { rowline: rowline.strip } if rowline.include?("solid")
  options || {}
end

.table_separator(separator, value, symbol: "solid") ⇒ Object



302
303
304
305
306
307
308
309
310
311
312
313
314
315
# File 'lib/plurimath/utility.rb', line 302

def table_separator(separator, value, symbol: "solid")
  sep_symbol = Math::Function::Td.new([Math::Symbol.new("|")])
  separator&.each_with_index do |sep, ind|
    next unless sep == symbol

    value.map do |val|
      val.parameter_one.insert((ind + 1), sep_symbol) if symbol == "solid"
      val.parameter_one.insert(ind, sep_symbol) if symbol == "|"
      (val.parameter_one[val.parameter_one.index(nil)] = Math::Function::Td.new([])) rescue nil
      val
    end
  end
  value
end

.table_td(object) ⇒ Object



384
385
386
387
388
389
390
391
392
# File 'lib/plurimath/utility.rb', line 384

def table_td(object)
  new_object = case object
               when Math::Function::Td
                 object
               else
                 Math::Function::Td.new([object])
               end
  Array(new_object)
end

.td_value(td_object) ⇒ Object



266
267
268
269
270
271
272
# File 'lib/plurimath/utility.rb', line 266

def td_value(td_object)
  if td_object.is_a?(String) && td_object.empty?
    return Math::Function::Text.new(nil)
  end

  td_object
end

.td_values(objects, slicer) ⇒ Object



251
252
253
254
255
256
257
258
259
260
# File 'lib/plurimath/utility.rb', line 251

def td_values(objects, slicer)
  sliced = objects.slice_when { |object, _| symbol_value(object, slicer) }
  tds = sliced.map do |slice|
    Math::Function::Td.new(
      slice.delete_if { |d| symbol_value(d, slicer) }.compact,
    )
  end
  tds << Math::Function::Td.new([]) if symbol_value(objects.last, slicer)
  tds
end

.text_classes(text) ⇒ Object



219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/plurimath/utility.rb', line 219

def text_classes(text)
  return nil if text.empty?

  text = filter_values(text) unless text.is_a?(String)
  if text.scan(/[[:digit:]]/).length == text.length
    Math::Number.new(text)
  elsif text.match?(/[a-zA-Z]/)
    Math::Function::Text.new(text)
  else
    Math::Symbol.new(text)
  end
end

.unfenced_value(object) ⇒ Object



364
365
366
367
368
369
370
371
372
373
# File 'lib/plurimath/utility.rb', line 364

def unfenced_value(object)
  case object
  when Math::Function::Fenced
    filter_values(object.parameter_two)
  when Array
    filter_values(object)
  else
    object
  end
end

.update_nodes(element, nodes) ⇒ Object



192
193
194
195
196
197
198
# File 'lib/plurimath/utility.rb', line 192

def update_nodes(element, nodes)
  nodes&.each do |node|
    next update_nodes(element, node) if node.is_a?(Array)
    element << node unless node.nil?
  end
  element
end

.validate_left_right(fields = []) ⇒ Object



403
404
405
406
407
408
409
# File 'lib/plurimath/utility.rb', line 403

def validate_left_right(fields = [])
  fields.each do |field|
    if field.is_a?(Math::Formula) && field.value.first.is_a?(Math::Function::Left)
      field.left_right_wrapper = true
    end
  end
end