Module:Test/lib/search

From RimWorld Wiki
Jump to navigation Jump to search

local search = {}

---------------
-- conductor --
---------------
-- ancestry functionality (commented out)
-- sibling_key: optional, deprecate the whole thing (commented out)

-- Possible query combinations:
--   query: {key, value}
--   query: {key, nil}
--   query: {nil, value}
--   query: key (string or number)
function search.conductor(query, tbl)
  assert(query, "conductor: missing argument #1 (query)")
  assert(tbl, "conductor: missing argument #2 (table to search through)")
  assert(type(tbl) == 'table', string.format("conductor: bad argument #2 (table expected, got %s)", type(tbl)))

  search.state = {
    ["args"] = {},
    ["queried"] = {}
  }
--~   search.ancestors = {}

  search.state.args.query = query
  search.state.args.table = tbl
--~   search.state.args.sibling_key = sibling_key

  local result = search.find(query, tbl)

  if result then
--~     search.generate_anscestry_of_last_search(result)
--~     result.ancestors = search.ancestors
    return result
  end
end

--------------
-- ancestry --
--------------
--~ function search.generate_anscestry_of_last_search(quad)
--~   quad = quad or {}

--~   for _,v in ipairs(search.state.queried) do
--~     if v.value == quad.parent.table then
--~       table.insert(search.ancestors, quad.parent.key)
--~       search.generate_anscestry_of_last_search(v, search.state.queried, ancestors)
--~     elseif not quad.parent.key then return nil
--~     end
--~   end
--~ end

----------------------
-- search_condition --
----------------------
-- note: if I want to search for true/false, will need to change this up a bit
function search.search_condition(query, key, value)
  local condition = false

  if type(query) == 'string' or type(query) == 'number' then
    condition = key == query
  elseif query[1] and query[2] then
    condition = key == query[1] and value == query[2]
  elseif query[1] then
    condition = key == query[1]
  elseif query[2] then
    condition = value == query[2]
  end

  return condition
end

----------------
-- find first --
----------------
search.meta = {}
function search.find(query, tbl, parentKey)
  local children = {}

  for k,v in pairs(tbl) do -- search through children that are not tables

    local quad = {
      key = k,
      value = v,
      parent = {
        key = parentKey,
        table = tbl
      }
    }

--~     -- needed to generate ancestry
--~     table.insert(search.state.queried, quad)

    if search.search_condition(query, k, v) then
      search.meta = quad
      return v
    elseif type(v) == "table" then
      table.insert(children, k)
    end

  end

  for _,childK in ipairs(children) do -- search through child tables
    local found = search.find(query, tbl[childK], childK)
    if found then return found end
  end
end

return search -- return module