Class: Quby::Compiler::Entities::LookupTables

Inherits:
Object
  • Object
show all
Defined in:
lib/quby/compiler/entities/lookup_tables.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ LookupTables

Returns a new instance of LookupTables.



7
8
9
# File 'lib/quby/compiler/entities/lookup_tables.rb', line 7

def initialize(path)
  @path = path
end

Class Method Details

.add_to_tree(tree, value, *path, level, *levels, compare, *compares) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/quby/compiler/entities/lookup_tables.rb', line 41

def self.add_to_tree(tree, (value, *path), (level, *levels), (compare, *compares))
  key = case compare
        when 'string' then value.to_s
        when 'float' then parse_float(value)
        when 'range' then create_range(value)
        end

  if levels.empty?
    return key
  end

  tree.merge! key => add_to_tree(tree[key] || {}, path, levels, compares)
end

.create_range(value) ⇒ Object



55
56
57
58
59
# File 'lib/quby/compiler/entities/lookup_tables.rb', line 55

def self.create_range(value)
  min, max = value.split(':').map { |val| parse_float(val) }
  fail 'Cannot create range between two equal values' if min == max
  (min...max)
end

.from_csv(levels:, compare:, data:) ⇒ Object

load csv data into a tree. each row is a path through the tree. String and float types are used to make an exact match. A range is always a range between two floats where the range is between the low value (inclusive) and the high value (exclusive), written as 4:5 (low:high). These boundaries can be given as floats or integers, but internally they are always treated as a floats. The low and high values of a range cannot be equal. Use minfinity or infinity to create infinite ranges.

Parameters:

  • compare (Array<String>)

    An array of lookup types (string, float or range) for each column

  • data (Array<Array<>>)

    The rows describing a path through the tree.



32
33
34
35
36
37
# File 'lib/quby/compiler/entities/lookup_tables.rb', line 32

def self.from_csv(levels:, compare:, data:)
  tree = data.each_with_object({}) do |row, tree|
    add_to_tree(tree, row, levels, compare)
  end
  {levels: levels, tree: tree}
end

.parse_float(value) ⇒ Object



61
62
63
64
65
66
67
# File 'lib/quby/compiler/entities/lookup_tables.rb', line 61

def self.parse_float(value)
  case value
  when 'infinity'  then Float::INFINITY
  when 'minfinity' then -Float::INFINITY
  else Float(value)
  end
end

Instance Method Details

#fetch(key) ⇒ Object



11
12
13
14
15
16
17
# File 'lib/quby/compiler/entities/lookup_tables.rb', line 11

def fetch(key)
  csv_path = File.join(@path, "#{key}.csv")
  data = CSV.read(csv_path, col_sep: ';', skip_blanks: true)
  headers = data.shift
  compare = data.shift
  self.class.from_csv(levels: headers, compare: compare, data: data)
end