Module:Utils

local p = {}

--dumps a table, useful for debugging function p.tdump(o) if type(o) == 'table' then local s = '{ ' for k,v in pairs(o) do 			if type(k) ~= 'number' then k = '"'..k..'"' end s = s .. '['..k..'] = ' .. p.tdump(v) .. ',' 		end return s .. '} ' 	else return tostring(o) end end

--returns an iterator over the sorted table. Can be used like this: for name, value in pairsByKeys(table) do --t: the table to sort --f: the function to use to sort the table. If nil then a natural sort is performed function p.pairsByKeys (t, f)   local a = {} for n in pairs(t) do        table.insert(a, n)     end table.sort(a, f)   local i = 0      -- iterator variable local iter = function   -- iterator function i = i + 1 if a[i] == nil then return nil else return a[i], t[a[i]] end end return iter end

--returns a deep copy of the given table function p.deepcopy(orig) local orig_type = type(orig) local copy if orig_type == 'table' then copy = {} for orig_key, orig_value in next, orig, nil do           copy[deepcopy(orig_key)] = deepcopy(orig_value) end setmetatable(copy, deepcopy(getmetatable(orig))) else -- number, string, boolean, etc copy = orig end return copy end

--makes a shallow copy of added to base function p.merge(base, added) for added_key, added_value in pairs(added) do		base[added_key]=added_value end end

--                                             --  --   Functions for dealing with arguments   -- --                                             --

--argDefs is assumed to be a table in the form of --argDefs={ --    = { --       isNumeric=, (if not set, then default is false) --       path={, , } (if not set, then argName is used as default path. If set to {} (empty) then no value is retrieved. Can also be set to a single string or number for convenience's sake) --       doc= (if not set, then default is empty string) --   } --}

--REMEMBER: It's better to use a special argument for the name of the player module from which info will be loaded instead of using the same argument as the one for the player name. --If you don't, the value loeaded from the player module will always be overwriten by the name argument.

--Loads args from frame.args and returns args --If argDefs says an arg is numeric, then it is converted before being added to the args --If args is not provided it is created --If args is provided then the values in it will be replaced if non-null values exist in the args --If frame or argDefs is not provided then an error is thrown function p.argsFromFrame(frame, args, argDefs) mw.log('argsFromFrame [frame=' .. p.tdump(frame) .. ', args=' .. p.tdump(args) .. ', argDefs=' .. p.tdump(argDefs) .. ']') if(args == nil) then mw.log('nil args provided, creating empty') args = {} end if(frame == nil) then error('frame not provided', 2) end if(argDefs == nil) then error('argDefs not provided', 2) end for argName, argInfo in pairs(argDefs) do mw.log('argsFromFrame processing [argName=' .. tostring(argName) .. ', argInfo=' .. p.tdump(argInfo) .. ']') local argStatus, argError = pcall(function		       mw.log('checking frame.args[' .. tostring(argName) .. ']=' .. p.tdump(frame.args[argName]))				if(frame.args[argName] ~= nil) then					if(argInfo.isNumeric) then --nil is false in lua						local converted = tonumber(frame.args[argName])						if(converted == nil) then						   error('tonumber failed [argName=' .. tostring(argName) .. ', currVal=' .. p.tdump(frame.args[argName]) .. ', argInfo=' .. p.tdump(argInfo) .. ']')						end						args[argName]=converted					else						args[argName]=frame.args[argName]					end				end		   end) mw.log('argsFromFrame finished processing [argStatus=' .. tostring(argStatus) .. ', argError=' .. tostring(argError) .. ']') if(not argStatus) then error('argsFromFrame arg processing failed [argName=' .. tostring(argName) .. ', argInfo=' .. p.tdump(argInfo) .. ', argError=' .. argError .. ']') end end mw.log('done argsFromFrame [args=' .. p.tdump(args) .. ']') return args end

--Loads args from player data and returns args --If argDefs says an arg is numeric, then it is converted before being added to the args --If a name is not provided then no operation is performed on the args (beyond creating them, if necessary) --If args is not provided it is created --If args is provided then the values in it will be replaced if non-null values exist in the loaded args --If argDefs is not provided then an error is thrown function p.argsFromPlayer(name, args, argDefs) mw.log('argsFromPlayer [name=' .. p.tdump(name) .. ', args=' .. p.tdump(args) .. ', argDefs=' .. p.tdump(argDefs) .. ']') if(args == nil) then mw.log('nil args provided, creating empty') args = {} end if(name == nil) then mw.log('no name provided, returning given args [args=' .. p.tdump(args) .. ']') return args end local player = require('Module:Players').getPlayer(name) mw.log('got player [player=' .. p.tdump(player) .. ']') if(player == nil) then mw.log('player not found, returning given args [args=' .. p.tdump(args) .. ']') return args end if(argDefs == nil) then error('argDefs not provided', 2) end --Else, if we got all the necessary stuff, try to load variables from the player for argName, argInfo in pairs(argDefs) do mw.log('argsFromPlayer processing [argName=' .. tostring(argName) .. ', argInfo=' .. p.tdump(argInfo) .. ']') local argStatus, argError = pcall(function		       local currVal=nil				--If no path provided, then assume the path is the name of the argument				if(argInfo.path == nil) then				    mw.log('nil path, checking player[' .. tostring(argName) .. ']=' .. p.tdump(player[argName]))				   currVal=player[argName]				elseif(type(argInfo.path) ~= 'table') then				    mw.log('non-table path, checking player[' .. tostring(argInfo.path) .. ']=' .. p.tdump(player[argInfo.path]))				   currVal=player[argInfo.path]				else					--Else, if a path is provided, use it to retrieve the value					currVal = player					mw.log('using path [argInfo.path=' .. p.tdump(argInfo.path) .. ']')					for index, pathPart in ipairs(argInfo.path) do						--If we reached a null value, break						mw.log('advancing in path [pathPart=' .. p.tdump(pathPart) .. ', currVal=' .. p.tdump(currVal) .. ']')						if(currVal==nil) then						   mw.log('encountered nil, stopped advancing')							break						end						--Else continue further down the path						currVal=currVal[pathPart]						mw.log('advanced [currVal=' .. p.tdump(currVal) .. ']')					end				end				--If the path wasn't empty and the value retrieved wasn't null, then use the retrieved value				mw.log('final value [currVal=' .. p.tdump(currVal) .. ']')				if(currVal ~= player and currVal ~= nil) then					if(argInfo.isNumeric) then --nil is false in lua					   mw.log('convert and set args[' .. tostring(argName) .. ']=' .. p.tdump(currVal))					   local converted = tonumber(currVal)					    if(converted == nil) then					        error('tonumber failed [argName=' .. tostring(argName) .. ', currVal=' .. p.tdump(currVal) .. ', argInfo=' .. p.tdump(argInfo) .. ']')					   end					    mw.log('set converted args[' .. tostring(argName) .. ']=' .. p.tdump(converted))						args[argName]=converted					else						mw.log('set args[' .. tostring(argName) .. ']=' .. p.tdump(currVal))						args[argName]=currVal					end				end			end) mw.log('argsFromPlayer finished processing [argStatus=' .. tostring(argStatus) .. ', argError=' .. tostring(argError) .. ']') if(not argStatus) then error('argsFromPlayer arg processing failed [argName=' .. tostring(argName) .. ', argInfo=' .. p.tdump(argInfo) .. ', argError=' .. argError .. ']') end end mw.log('done argsFromPlayer [args=' .. p.tdump(args) .. ']') return args end

return p