Editing Module:Test

Jump to navigation Jump to search

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.

Latest revision Your text
Line 1: Line 1:
DefInfo = {}
+
-- redefine the print function to use mw.log
local wiki = {}
+
print = mw.log
  
local function runTime()
+
---------------
  return string.format("%i", os.clock() * 1000)
+
-- load data --
end
+
---------------
  
------------------------------------------------------------------
+
-- wiki environment --
-- deal with differences between MediaWiki and dev environments --
 
------------------------------------------------------------------
 
  
if mw then
+
local Biomes = mw.loadData('Module:Test/data/biomes')
 +
--local Buildings = mw.loadData('Module:Test/data/buildings')
 +
local Races = mw.loadData('Module:Test/data/races')
  
  log = mw.log
+
-- dev environment --
  logObject = mw.logObject
 
  
  local timeDataStart = runTime()
+
--local Biomes = loadfile("./data/BiomeDefs.lua")()
 
+
--local Buildings = loadfile("./data/ThingDefs_Buildings.lua")()
  Data  = mw.loadData('Module:Test/data')
+
--local Races = loadfile("./data/ThingDefs_Races.lua")()
  
  local timeDataEnd = runTime()
+
-- aggregate the categories --
  log(string.format('@%ims, data loaded in %ims', timeDataEnd, timeDataEnd - timeDataStart))
 
  
  Util  = require("Module:Test/lib/util")
+
local data = {}
  Search = require("Module:Test/lib/search")
+
data["Biomes"] = Biomes
  VF    = require("Module:Test/data/virtual")
+
--data["Buildings"] = Buildings
 +
data["Races"] = Races
  
  log(string.format('@%ims, modules loaded', runTime()))
+
------------------------
 +
-- pretty print table --
 +
------------------------
  
else
+
--[[ procedure: tprint ]]--
  
  logDevStore = {}
+
function tprint (tbl, indent)
 
+
   if not indent then indent = 0 end
  log = function(str)
+
  for k, v in pairs(tbl) do
    table.insert(logDevStore, str)
+
    formatting = string.rep("  ", indent) .. k .. ": "
   end
+
     if type(v) == "table" then
 
+
      print(formatting)
  logObject = function(obj, prefix)
+
       tprint(v, indent+1)
     if prefix then
+
    elseif type(v) == 'boolean' then
      assert(type(prefix) == "string")
+
      print(formatting .. tostring(v))
       table.insert(logDevStore, prefix .. " = " .. Inspect(obj))
 
 
     else
 
     else
       table.insert(logDevStore, Inspect(obj))
+
       print(formatting .. v)
 
     end
 
     end
 
   end
 
   end
 +
end
  
  function pp(tbl, title) -- pretty print tables
+
-----------------------------
    Util.hl(title)
+
-- small utility functions --
    print(Inspect(tbl))
+
-----------------------------
  end
 
  
  local timeDataStart = runTime()
+
--[[ function: shallowcopy ]]--
  
  Data    = require "data/data"
+
function shallowcopy(original_table)
 +
    local orig_type = type(original_table)
 +
    local copy
 +
    if orig_type == 'table' then
 +
        copy = {}
 +
        for orig_key, orig_value in pairs(original_table) do
 +
            copy[orig_key] = orig_value
 +
        end
 +
    else -- number, string, boolean, etc
 +
        copy = original_table
 +
    end
 +
    return copy
 +
end
  
  local timeDataEnd = runTime()
+
--[[ function: reverse_numeric_table ]]--
  log(string.format('@%ims, data loaded in %ims', timeDataEnd, timeDataEnd - timeDataStart))
 
  
  Util    = require "lib/util"
+
function reverse_numeric_table(tbl)
  Search  = require "lib/search"
+
    local reversed_table = {}
  Inspect = require "lib/inspect"
+
    local length = #tbl
  VF      = require "data/virtual"
+
    for i,v in ipairs(tbl) do
 +
        reversed_table[length + 1 - i] = v
 +
    end
 +
    return reversed_table
 +
end
  
  log(string.format('@%ims, modules loaded', runTime()))
+
--[[ function: count ]]--
  
 +
-- '#' operator seems to work for numerically indexed tables so it can be used instead
 +
-- this count function counts all the keys (of any type)
 +
local function count(tbl, key_type)
 +
  local length = 0;
 +
  for k,v in pairs(tbl) do
 +
    if key_type then
 +
      if type(k) == key_type then
 +
        length = length + 1
 +
      end
 +
    else
 +
      length = length + 1
 +
    end
 +
  end
 +
  return length
 
end
 
end
  
-----------------------
+
--[[ function: find_key_name_of_value ]]--
-- private functions --
+
local function find_key_name_of_value(value, tbl)
-----------------------
+
  for k,v in pairs(tbl) do
 +
    if v == value then return k end
 +
  end
 +
end
  
function DefInfo.vardefine(name, value, frame)
+
--[[ function: search_table_recursive ]]--
  assert(name, "vardefine: missing argument #1 (variable to definePrefix)")
 
  assert(type(name) == "string", string.format("vardefine: bad argument #1 (string expected, got %s)", type(name)))
 
  assert(value, "vardefine: missing argument #2 (value to assign)")
 
  assert(type(value) == "string" or type(value) == "number" or type(value) =="boolean", string.format("vardefine: bad argument #2 (string, number or boolean expected, got %s)", type(value)))
 
  assert(frame, "vardefine: 'frame' missing")
 
  frame:callParserFunction('#vardefine', name, value)
 
end
 
  
function DefInfo.expandDef(def, runMe)
+
-- returns the value found by first occurrence of a key within a table (recursive)
  if not runMe then return nil end
+
local function search_table_recursive(key, tbl)
  local vFuncs = VF
+
   for k, v in pairs(tbl) do
   for fName,func in pairs(vFuncs) do
+
     if k == key then return v
     if func(def) then
+
    elseif type(v) == "table" then
       log(string.format('@%ims, expandDef: %s expanded with %s', runTime(), def.defName, fName))
+
       local found = search_table_recursive(key, v)
 +
      if found then return found end
 
     end
 
     end
 
   end
 
   end
 
end
 
end
  
function DefInfo.mergeParents(baseDef, ignoreKeys)
+
--[[ function: find_parent_table ]]--
  local ancestorIDs = {}
 
  local mergedDef = {}
 
  local def = baseDef
 
  
   while def._.ParentName do
+
-- returns the parent table of an element specified by key, value (recursive)
     local parentID = def._.DefCategory .. ":" .. def._.ParentName
+
local function find_parent_table(key, value, tbl)
    table.insert(ancestorIDs, parentID)
+
   for k, v in pairs(tbl) do
     def = Data[parentID]
+
     if k == key and v == value then return tbl
 +
    elseif type(v) == "table" then
 +
      local found = find_parent_table(key, value, v)
 +
      if found then return found end
 +
     end
 
   end
 
   end
 +
end
  
  ancestorIDs = Util.table.reverse(ancestorIDs)
+
--[[ procedure: vardefine ]]--
  table.insert(ancestorIDs, baseDef._.DefCategory .. ":" .. baseDef.defName)
 
  
   for _,parentID in ipairs(ancestorIDs) do
+
local function vardefine(var_name, var_value)
    Util.table.overwrite(mergedDef, Data[parentID], ignoreKeys)
+
  local fName = "vardefine"
   end
+
   assert(var_name, string.format("bad argument #1 to '%s' (argument missing, name of variable to define)", fName))
 +
  assert(var_name == "string", string.format("bad argument #1 to '%s' (string expected, got %s)", fName, type(var_name)))
 +
  assert(var_value, string.format("bad argument #2 to '%s' (argument missing, value to assign to variable)", fName))
 +
   assert(var_value == "string" or var_value == "number", string.format("bad argument #2 to '%s' (string or number expected, got %s)", fName, type(var_value)))
  
   return mergedDef
+
   frame:callParserFunction('#vardefine', var_name, var_value)
 
end
 
end
  
function DefInfo.getDef(defID, expandVF)
+
--[[ procedure: overwrite_first_table_with_second ]]--
  if expandVF ~= false then expandVF = true end
 
  
  local ignoreKeys = {"Abstract", "Name", "ParentName"}
+
local function overwrite_first_table_with_second(first_table, second_table, ignore_keys)
   local baseDef
+
   ignore_keys = ignore_keys or {}
  local def
 
  
   if not defID then return nil end
+
   for k,v in pairs(second_table) do
 +
    local ignore = false
  
  for _,def in pairs(Data) do
+
    for _, ignored_key in ipairs(ignore_keys) do
    if def.defName == defID then
+
      if k == ignored_key then ignore = true end
      baseDef = def
+
    end
      break
+
 
     elseif string.upper(def.label or '') == string.upper(defID) then
+
     if not ignore then
       baseDef = def
+
      if type(v) == "table" then
       break
+
        if type(first_table[k]) == "table" then
 +
          overwrite_first_table_with_second(first_table[k], v)
 +
        else
 +
          first_table[k] = {}
 +
          overwrite_first_table_with_second(first_table[k], v)
 +
        end
 +
       else
 +
        first_table[k] = v
 +
       end
 
     end
 
     end
 
   end
 
   end
 +
end
  
  if not baseDef then return nil end
+
----------------------
 +
-- dataset specific --
 +
----------------------
  
  def = DefInfo.mergeParents(baseDef, ignoreKeys)
+
--[[ function: find_def_table ]]--
  
   DefInfo.expandDef(def, expandVF)
+
local function find_def_table(def)
 +
  -- hidden variables: data
 +
   for k1,v1 in pairs(data) do
 +
    if type(v1) == "table" then
 +
      for k2,v2 in pairs(v1) do
 +
        if k2 == def then return v2 end
 +
      end
 +
    end
 +
  end
 +
end
  
   return def
+
local function find_def_category_table(def)
 +
   for k1,v1 in pairs(data) do
 +
    if type(v1) == "table" then
 +
      for k2,v2 in pairs(v1) do
 +
        if k2 == def then return v1 end
 +
      end
 +
    end
 +
  end
 
end
 
end
  
local function setPrefix(tbl, parentKey)
+
--[[ function: merge_def_with_parents ]]--
  local mt = getmetatable(tbl) or {}
 
  
  for k,v in pairs(tbl) do
+
local function merge_def_with_parents(def, ignore_keys)
    local prefix = parentKey .. "_" .. k
+
   -- hidden variables: ParentName and global data
    if type(v) == 'table' then
 
      setPrefix(v, prefix)
 
    else
 
      mt[k] = prefix
 
    end
 
   end
 
  
   setmetatable(tbl, mt)
+
   local def_table = find_def_table(def)
end
+
  local def_category_table = find_def_category_table(def)
 +
  local parent_names = {}
 +
  local parent_name = def_table["ParentName"]
 +
  local parent_table = def_category_table[parent_name]
  
local function definePrefixed(tbl, frame)
+
   while parent_name do
   for k,v in pairs(tbl) do
+
     table.insert(parent_names, parent_name)
     if type(v) ~= 'table' then
+
    parent_name = parent_table["ParentName"]
      local mt = getmetatable(tbl)
+
    parent_table = def_category_table[parent_name]
      log(string.format('%s = %s', mt[k], tostring(v)))
 
      if mw then DefInfo.vardefine(mt[k], v, frame) end
 
    else
 
      definePrefixed(v, frame)
 
    end
 
 
   end
 
   end
end
 
  
----------------------
+
  local inheritance_chain = shallowcopy(reverse_numeric_table(parent_names))
-- public interface --
+
  table.insert(inheritance_chain, def)
----------------------
 
  
function wiki.count(frame)
+
  local merged = {}
   local query = wiki.query(frame)
+
   local chain_length = #inheritance_chain
   if type(wiki.queried) == 'table' then -- WARNING: checks a variable that is set in wiki.query (ugly)
+
   for i,v in ipairs(inheritance_chain) do
     return Util.table.count(wiki.queried)
+
     overwrite_first_table_with_second(merged, def_category_table[inheritance_chain[i]], ignore_keys)
 
   end
 
   end
 +
 +
  return merged
 
end
 
end
  
function wiki.query(frame)
+
--------------------------------
 +
-- publicly exposed functions --
 +
--------------------------------
 +
 
 +
local p = {}
  
   local argLen = Util.table.count(frame.args, "number") -- #frame.args won't work as expected, check the doc
+
function p.query(frame)
 +
   local fName = "query"
  
   if not frame.args['defName'] and not frame.args['label'] then
+
   if not (frame.args["defName"] or frame.args["label"]) then
     logObject(frame.args, string.format('query @ %ims: missing an identifying argument (defName or label)\nframe.args', runTime()))
+
     assert(frame.args["defName"], string.format("bad argument to '%s' (missing named argument 'defName' or 'label' needed to find a Def)", fName))
    return nil
 
 
   end
 
   end
  
   local def = DefInfo.getDef(frame.args['defName']) or DefInfo.getDef(frame.args['label'])
+
   local def_table
 
+
  local def_arg
  if not def then
+
  if frame.args["defName"] then
    logObject(frame.args, string.format("query @ %ims: Def not found\nframe.args", runTime()))
+
    def_table = find_def_table(frame.args["defName"])
     return nil
+
    if def_table then
 +
      def_arg = frame.args["defName"]
 +
      def_table = merge_def_with_parents(frame.args["defName"], {"ParentName", "Abstract"})
 +
     end
 
   end
 
   end
 
+
   if not def_table then
   if def and argLen == 0 then
+
     def_table = find_parent_table(find_key_name_of_value(frame.args["label"], frame.args), frame.args["label"], data["Races"])
     logObject(def, string.format("['%s:%s'] @ %ims", def._.DefCategory, def.defName, runTime()))
+
    if def_table then
     return nil
+
      def_arg = frame.args["label"]
 +
      def_table = merge_def_with_parents(def_table["defName"], {"ParentName", "Abstract"})
 +
     end
 
   end
 
   end
  
   local processedDef = def
+
   assert(def_table, "Def not found")
  
   for i,arg in ipairs(frame.args) do -- arguments
+
   local numbered_args_length = count(frame.args, "number")
     arg = tonumber(arg) or arg -- frame.args are always strings on MediaWiki so convert back the numbers
+
  if numbered_args_length == 0 then
 +
     print("Table returned. Check the log.")
 +
    tprint(def_table)
 +
  else
  
     if i == argLen and frame.args["sibling"] then
+
     local filtered = def_table
       processedDef = Search.find({nil, frame.args["sibling"]} , processedDef)
+
    for i=1, numbered_args_length do
       if not processedDef then
+
      filtered = search_table_recursive(frame.args[i], filtered)
         logObject(frame.args, string.format("query @ %ims: bad argument 'sibling' ('%s' not found')\nframe.args", runTime(), frame.args["sibling"]))
+
      assert(frame.args[i], string.format("bad argument to '%s' (missing numeric argument #%i)", fName, i))
         return nil
+
       assert(filtered, string.format("'%s' not found in '%s'", frame.args[i], def_arg))
 +
       if filtered then
 +
         if (type(filtered) == "string" or type(filtered) == "number" or type(filtered) == "boolean") and (i < numbered_args_length) then
 +
          error(string.format("too many numeric arguments to '%s' ('%s' already found in '%s')", fName, frame.args[i], def_arg))
 +
         end
 
       else
 
       else
         processedDef = Search.meta.parent.table[arg]
+
         error(string.format("'%s' not found in '%s'", v, def_arg))
        if not processedDef then
 
          logObject(frame.args, string.format("query @ %ims: bad argument #%i ('%s' is not a sibling of '%s')", runTime(), i, arg, frame.args["sibling"]))
 
          return nil
 
        end
 
 
       end
 
       end
 
     end
 
     end
 
+
   
     if i < argLen or i == argLen and not frame.args["sibling"] then
+
     if type(filtered) == "table" then
       processedDef = Search.find(arg, processedDef)
+
       print("Table returned. Check the log.")
      if not processedDef then
+
       tprint(def_table)
        logObject(frame.args, string.format("query @ %ims: bad argument #%i ('%s' not found)\nframe.args", runTime(), i, frame.args[i]))
+
    else
        return nil
+
      return filtered
       else
 
        if type(processedDef) ~= 'table' and i < argLen then
 
          log(string.format("query @ %ims: warning Def ['%s'] argument #%i ('%s' returns a value, all extra arguments ignored)", runTime(), def['label'], i, frame.args[i]))
 
          return processedDef
 
        end
 
      end
 
 
     end
 
     end
  
  end -- for arguments
 
 
  if type(processedDef) == "table" then
 
    log(string.format("@%ims, query: table vardefined", runTime()))
 
    setPrefix(processedDef, frame.args[argLen])
 
    definePrefixed(processedDef, frame)
 
    wiki.queried = processedDef -- WARNING: sets a variable that is used in another function wiki.count (ugly)
 
    return nil
 
 
   end
 
   end
  
  log(string.format("@%ims, query: %s printed", runTime(), type(processedDef)))
 
  return processedDef
 
end
 
 
------------------------------------
 
-- simulate MediaWiki environment --
 
------------------------------------
 
 
if not mw then
 
  local simframe = { ["args"] = {} }
 
  simframe.args['label'] = 'ancient cryptosleep casket'
 
--~  simframe.args[1] = 'verbs'
 
--~  simframe.args[2] = 'label'
 
  wiki.query(simframe)
 
 
end
 
end
  
if not mw then
+
-------------
  Util.hl("DefInfo log")
+
-- logging --
  for _,v in ipairs(logDevStore) do
+
-------------
    print(v)
 
  end
 
end
 
  
------------
+
--mw.log("Module:DefInfo:os.clock() " .. os.clock()*1000 .. " ms")
-- return --
+
print("Module:DefInfo:os.clock() " .. os.clock()*1000 .. " ms")
------------
 
  
if mw then
+
return p
  return wiki
 
else
 
  return DefInfo
 
end
 

Please note that all contributions to RimWorld Wiki are considered to be released under the CC BY-SA 3.0 (see RimWorld Wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

Cancel Editing help (opens in new window)