Module:Dv

-- Usage: use the Template:Dv

-- override values in table dst with values of table src, or adds them local function merge(dst, src) for k, v in pairs(src) do   if type(dst[k]) == 'table' and type(v) == 'table' then dst[k] = merge(dst[k], v)   else dst[k] = v   end end return dst end

local function deepcopy(orig) if type(orig) == 'table' then local copy = {} for k, v in pairs(orig) do     copy[deepcopy(k)] = deepcopy(v) end return copy end return orig end

local function createVardefines(t, f, prefix) for k, v in pairs(t) do   if type(v) == 'table' then f:callParserFunction('#vardefine:' .. (prefix == '' and prefix or prefix .. '/') .. k, 'table') createVardefines(v, f, (prefix == '' and prefix or prefix .. '/') .. k)   else f:callParserFunction('#vardefine:' .. (prefix == '' and prefix or prefix .. '/') .. k, v)   end end end

local function getNodeWithInheritanceSolved(creature, aliases, data) -- solve alias if aliases[creature] ~= nil then creature = aliases[creature] end -- query initial node local node = data[creature] if node == nil then return nil end -- return the node if it does not inherit from anything else if node.inherits == nil or node.inherits == '' then return node end -- node inherits information from another. retrieve it with its inheritance -- solved. local inherits = node.inherits local parentNode = getNodeWithInheritanceSolved(inherits, aliases, data) -- return initial node if parent has not been found if parentNode == nil then return node end -- merge initial node into a copy of parent return merge(deepcopy(parentNode), node) end

local p = {}

function p.data(f) local args = f:getParent.args -- expects one or more non-named arguments in the template, the /-separated path to the data if args[1] == nil then return 'arguments expected, see documentation of Template:Dv' end -- concat all non-named arguments (args is not a real table, deepcopy creates one) local path = table.concat(deepcopy(args), '/')

-- remove non-word characters except / then lowercase path = path:gsub('[^%w/]', ''):lower

local folders = {} -- list of path parts for part in path:gmatch("[^/]+") do   table.insert(folders, part) end

-- separate creature name from the rest of the path local creature = table.remove(folders, 1)

-- load alias table local aliases = mw.loadData('Module:dv/aliases')

-- select an alternative table based on path local dataTableName = 'dv/data' local tableOverrides = { ["colorization"] = "dv/paintRegions", } if tableOverrides[folders[1]] ~= nil then dataTableName = tableOverrides[folders[1]] table.remove(folders, 1) end -- retrieve the database local data = mw.loadData('Module:' .. dataTableName)

-- search the creature and solve inheritance automatically local node = getNodeWithInheritanceSolved(creature, aliases, data) if node == nil then return '' -- 'creature data not found: ' .. creature end

-- apply overrides from other section of 'data' if type(node.overridewith) == 'string' and data[node.overridewith] ~= nil then node = merge(node, data[node.overridewith]) end

-- search data for path for _,f in ipairs(folders) do   if node[f] ~= nil then node = node[f] else return '' -- no data available for given path end end

if type(node) == 'table' then if args.defineVars ~= nil then createVardefines(node, f, args.defineVars) return 'variables defined' end return 'path not specific enough: ' .. path -- given path leads to a folder instead of a value end return node end

return p