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: | ||
− | + | -- redefine the print function to use mw.log | |
− | + | print = mw.log | |
− | + | --------------- | |
− | + | -- load data -- | |
− | + | --------------- | |
− | -- | + | -- wiki environment -- |
− | |||
− | |||
− | + | local Biomes = mw.loadData('Module:Test/data/biomes') | |
+ | --local Buildings = mw.loadData('Module:Test/data/buildings') | ||
+ | local Races = mw.loadData('Module:Test/data/races') | ||
− | + | -- dev environment -- | |
− | |||
− | + | --local Biomes = loadfile("./data/BiomeDefs.lua")() | |
− | + | --local Buildings = loadfile("./data/ThingDefs_Buildings.lua")() | |
− | + | --local Races = loadfile("./data/ThingDefs_Races.lua")() | |
− | + | -- aggregate the categories -- | |
− | |||
− | + | local data = {} | |
− | + | data["Biomes"] = Biomes | |
− | + | --data["Buildings"] = Buildings | |
+ | data["Races"] = Races | ||
− | + | ------------------------ | |
+ | -- pretty print table -- | ||
+ | ------------------------ | ||
− | + | --[[ procedure: tprint ]]-- | |
− | + | function tprint (tbl, indent) | |
− | + | if not indent then indent = 0 end | |
− | + | for k, v in pairs(tbl) do | |
− | + | formatting = string.rep(" ", indent) .. k .. ": " | |
− | end | + | if type(v) == "table" then |
− | + | print(formatting) | |
− | + | tprint(v, indent+1) | |
− | if | + | elseif type(v) == 'boolean' then |
− | + | print(formatting .. tostring(v)) | |
− | |||
else | else | ||
− | + | print(formatting .. v) | |
end | end | ||
end | end | ||
+ | end | ||
− | + | ----------------------------- | |
− | + | -- small utility functions -- | |
− | + | ----------------------------- | |
− | |||
− | + | --[[ function: shallowcopy ]]-- | |
− | + | 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 | ||
− | + | --[[ function: reverse_numeric_table ]]-- | |
− | |||
− | + | function reverse_numeric_table(tbl) | |
− | + | local reversed_table = {} | |
− | + | local length = #tbl | |
− | + | for i,v in ipairs(tbl) do | |
+ | reversed_table[length + 1 - i] = v | ||
+ | end | ||
+ | return reversed_table | ||
+ | end | ||
− | + | --[[ 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 ]]-- |
− | + | 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 | + | --[[ function: search_table_recursive ]]-- |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | function | + | -- returns the value found by first occurrence of a key within a table (recursive) |
− | + | local function search_table_recursive(key, tbl) | |
− | + | for k, v in pairs(tbl) do | |
− | for | + | if k == key then return v |
− | if | + | elseif type(v) == "table" then |
− | + | local found = search_table_recursive(key, v) | |
+ | if found then return found end | ||
end | end | ||
end | end | ||
end | end | ||
− | function | + | --[[ function: find_parent_table ]]-- |
− | |||
− | |||
− | |||
− | + | -- returns the parent table of an element specified by key, value (recursive) | |
− | + | local function find_parent_table(key, value, tbl) | |
− | + | for k, v in pairs(tbl) do | |
− | + | 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 | ||
− | + | --[[ procedure: vardefine ]]-- | |
− | |||
− | + | local function vardefine(var_name, var_value) | |
− | + | local fName = "vardefine" | |
− | + | 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))) | ||
− | + | frame:callParserFunction('#vardefine', var_name, var_value) | |
end | end | ||
− | + | --[[ procedure: overwrite_first_table_with_second ]]-- | |
− | |||
− | + | local function overwrite_first_table_with_second(first_table, second_table, ignore_keys) | |
− | + | ignore_keys = ignore_keys or {} | |
− | |||
− | + | for k,v in pairs(second_table) do | |
+ | local ignore = false | ||
− | + | for _, ignored_key in ipairs(ignore_keys) do | |
− | + | if k == ignored_key then ignore = true end | |
− | + | end | |
− | + | ||
− | + | if not ignore then | |
− | + | if type(v) == "table" then | |
− | + | 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 | ||
− | + | ---------------------- | |
+ | -- dataset specific -- | ||
+ | ---------------------- | ||
− | + | --[[ function: find_def_table ]]-- | |
− | + | 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 | + | 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 | ||
− | + | --[[ function: merge_def_with_parents ]]-- | |
− | |||
− | + | local function merge_def_with_parents(def, ignore_keys) | |
− | + | -- hidden variables: ParentName and global data | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | local def_table = find_def_table(def) | |
− | + | 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] | ||
− | + | while parent_name do | |
− | + | table.insert(parent_names, parent_name) | |
− | + | parent_name = parent_table["ParentName"] | |
− | + | parent_table = def_category_table[parent_name] | |
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
− | |||
− | + | local inheritance_chain = shallowcopy(reverse_numeric_table(parent_names)) | |
− | + | table.insert(inheritance_chain, def) | |
− | |||
− | + | local merged = {} | |
− | local | + | local chain_length = #inheritance_chain |
− | + | for i,v in ipairs(inheritance_chain) do | |
− | + | overwrite_first_table_with_second(merged, def_category_table[inheritance_chain[i]], ignore_keys) | |
end | end | ||
+ | |||
+ | return merged | ||
end | end | ||
− | + | -------------------------------- | |
+ | -- publicly exposed functions -- | ||
+ | -------------------------------- | ||
+ | |||
+ | local p = {} | ||
− | local | + | function p.query(frame) |
+ | local fName = "query" | ||
− | if not frame.args[ | + | if not (frame.args["defName"] or frame.args["label"]) then |
− | + | assert(frame.args["defName"], string.format("bad argument to '%s' (missing named argument 'defName' or 'label' needed to find a Def)", fName)) | |
− | |||
end | end | ||
− | local | + | local def_table |
− | + | local def_arg | |
− | + | if frame.args["defName"] then | |
− | + | def_table = find_def_table(frame.args["defName"]) | |
− | + | 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_table = find_parent_table(find_key_name_of_value(frame.args["label"], frame.args), frame.args["label"], data["Races"]) |
− | + | if def_table then | |
− | + | def_arg = frame.args["label"] | |
+ | def_table = merge_def_with_parents(def_table["defName"], {"ParentName", "Abstract"}) | ||
+ | end | ||
end | end | ||
− | + | assert(def_table, "Def not found") | |
− | + | local numbered_args_length = count(frame.args, "number") | |
− | + | if numbered_args_length == 0 then | |
+ | print("Table returned. Check the log.") | ||
+ | tprint(def_table) | ||
+ | else | ||
− | + | local filtered = def_table | |
− | + | for i=1, numbered_args_length do | |
− | if | + | filtered = search_table_recursive(frame.args[i], filtered) |
− | + | assert(frame.args[i], string.format("bad argument to '%s' (missing numeric argument #%i)", fName, i)) | |
− | + | 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 | ||
− | + | error(string.format("'%s' not found in '%s'", v, def_arg)) | |
− | |||
− | |||
− | |||
− | |||
end | end | ||
end | end | ||
− | + | ||
− | if | + | if type(filtered) == "table" then |
− | + | print("Table returned. Check the log.") | |
− | + | tprint(def_table) | |
− | + | else | |
− | + | return filtered | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
− | + | ------------- | |
− | + | -- logging -- | |
− | + | ------------- | |
− | |||
− | |||
− | |||
− | -- | + | --mw.log("Module:DefInfo:os.clock() " .. os.clock()*1000 .. " ms") |
− | + | print("Module:DefInfo:os.clock() " .. os.clock()*1000 .. " ms") | |
− | |||
− | + | return p | |
− | |||
− | |||
− | |||
− |