Difference between revisions of "Module:Test/lib/search"

From RimWorld Wiki
Jump to navigation Jump to search
(Created page with "local Search = {} --------------- -- conductor -- --------------- -- sibling_key: optional, deprecate function Search.conductor(query, tbl, sibling_key) local f_name = "fin...")
 
(bugfix)
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
local Search = {}
+
local search = {}
  
 
---------------
 
---------------
 
-- conductor --
 
-- conductor --
 
---------------
 
---------------
-- sibling_key: optional, deprecate
+
-- ancestry functionality (commented out)
function Search.conductor(query, tbl, sibling_key)
+
-- sibling_key: optional, deprecate the whole thing (commented out)
  local f_name = "find"
 
  assert(query, string.format("bad argument #1 to '%s' (argument missing, search query)", f_name))
 
  assert(tbl, string.format("bad argument #2 to '%s' (argument missing, table to search through)", f_name))
 
  
   Search.state = {
+
-- 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"] = {},
 
     ["args"] = {},
 
     ["queried"] = {}
 
     ["queried"] = {}
 
   }
 
   }
   Search.ancestors = {}
+
--~   search.ancestors = {}
 
 
  Search.state.args.query = query
 
  Search.state.args.table = tbl
 
  Search.state.args.sibling_key = sibling_key
 
  
   local result
+
   search.state.args.query = query
 +
  search.state.args.table = tbl
 +
--~  search.state.args.sibling_key = sibling_key
  
   if not sibling_key then
+
   local result = search.find(query, tbl)
    result = Search.find_first(query, tbl)
 
  else
 
    result = Search.find_sibling(query, sibling_key, tbl)
 
  end
 
  
 
   if result then
 
   if result then
     Search.generate_anscestry_of_last_search(result)
+
--~     search.generate_anscestry_of_last_search(result)
     result.ancestors = Search.ancestors
+
--~     result.ancestors = search.ancestors
 
     return result
 
     return result
 
   end
 
   end
Line 38: Line 39:
 
-- ancestry --
 
-- ancestry --
 
--------------
 
--------------
function Search.generate_anscestry_of_last_search(quad)
+
--~ function search.generate_anscestry_of_last_search(quad)
   quad = quad or {}
+
--~   quad = quad or {}
  
   for _,v in ipairs(Search.state.queried) do
+
--~   for _,v in ipairs(search.state.queried) do
     if v.value == quad.parent.value then
+
--~     if v.value == quad.parent.table then
       table.insert(Search.ancestors, quad.parent.key)
+
--~       table.insert(search.ancestors, quad.parent.key)
       Search.generate_anscestry_of_last_search(v, Search.state.queried, ancestors)
+
--~       search.generate_anscestry_of_last_search(v, search.state.queried, ancestors)
     elseif not quad.parent.key then return nil
+
--~     elseif not quad.parent.key then return nil
     end
+
--~     end
   end
+
--~   end
end
+
--~ end
  
 
----------------------
 
----------------------
 
-- search_condition --
 
-- search_condition --
 
----------------------
 
----------------------
function Search.search_condition(query, key, value)
+
-- 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
 
   local condition = false
  
   if query[1] and query[2] then
+
   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]
 
     condition = key == query[1] and value == query[2]
 
   elseif query[1] then
 
   elseif query[1] then
Line 62: Line 66:
 
   elseif query[2] then
 
   elseif query[2] then
 
     condition = value == query[2]
 
     condition = value == query[2]
  elseif type(query) == "string" then
 
    condition = key == query
 
 
   end
 
   end
  
Line 70: Line 72:
  
 
----------------
 
----------------
-- find_first --
+
-- find first --
 
----------------
 
----------------
function Search.find_first(query, tbl, tbl_key)
+
function search.find(query, tbl, parentKey)
   local subtables = {}
+
   local children = {}
  
   for k,v in pairs(tbl) do
+
   for k,v in pairs(tbl) do -- search through children that are not tables
  
 
     local quad = {
 
     local quad = {
Line 81: Line 83:
 
       value = v,
 
       value = v,
 
       parent = {
 
       parent = {
         key = tbl_key,
+
         key = parentKey,
         value = tbl
+
         table = tbl
 
       }
 
       }
 
     }
 
     }
  
     -- I do this to be able to generate ancestry for the searh
+
--~     -- needed to generate ancestry
     table.insert(Search.state.queried, quad)
+
--~     table.insert(search.state.queried, quad)
  
     if Search.search_condition(query, k, v) then
+
     if search.search_condition(query, k, v) then
 
       return quad
 
       return quad
 
     elseif type(v) == "table" then
 
     elseif type(v) == "table" then
       table.insert(subtables, k)
+
       table.insert(children, k)
 
     end
 
     end
  
 
   end
 
   end
  
  -- By doing it like this it will first search through all of the children and after that
+
   for _,childK in ipairs(children) do -- search through child tables
  -- descend into grandchildren.
+
     local found = search.find(query, tbl[childK], childK)
   for _,k in ipairs(subtables) do
+
     if found then return found end
    local f = Search.find_first(query, tbl[k], k)
 
    if f then return f
 
    end
 
  end
 
end
 
 
 
------------------
 
-- find_sibling --
 
------------------
 
function Search.find_sibling(query, sibling_key, tbl, tbl_key)
 
  local subtables = {}
 
 
 
  for k,v in pairs(tbl) do
 
 
 
    local quad = {
 
      key = k,
 
      value = v,
 
      parent = {
 
        key = tbl_key,
 
        value = tbl
 
      }
 
    }
 
 
 
    -- I do this to be able to generate ancestry for the searh
 
    table.insert(Search.state.queried, quad)
 
 
 
    if Search.search_condition(query, k, v) and tbl[sibling_key] then
 
      local sibling_quad = {
 
        key = sibling_key,
 
        value = tbl[sibling_key],
 
        parent = {
 
          key = tbl_key,
 
          value = tbl
 
        }
 
      }
 
      table.insert(Search.state.queried, sibling_quad)
 
      return sibling_quad
 
    elseif type(v) == "table" then
 
      table.insert(subtables, k)
 
    end
 
 
 
  end
 
 
 
  -- By doing it like this it will first search through all of the children and after that
 
  -- descend into grandchildren.
 
  for _,k in ipairs(subtables) do
 
     local f = Search.find_sibling(query, sibling_key, tbl[k], k)
 
     if f then return f
 
    end
 
 
   end
 
   end
 
end
 
end
  
return Search
+
return search -- return module

Revision as of 15:25, 9 May 2021


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 --
----------------
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
      return quad
    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