Shared contains useful utilities.
On this Wiki, Shared is used in:
- Module:Acquisition
- Module:Ability
- Module:Arcane
- Module:Avionics
- Module:Cost
- Module:DamageTypes
- Module:Decorations
- Module:DropTables
- Module:Focus
- Module:Lua
- Module:Maximization
- Module:Missions
- Module:Mods
- Module:Stances
- Module:Tables
- Module:Version
- Module:Void
- Module:VoidByReward
- Module:Warframes
- Module:Weapons
Usage
Module
local p = {}
local shared = require('Module:Shared')
local function func(input)
-- ...
for i, v in shared.skpairs(table) do
-- ...
end
-- ...
end
Documentation
Package items
shared.getArgs(frame, options)
(function)- For getting frame or parent arguments
- Parameters:
frame
The input arguments (table)options
Options for getting the args (table)
- Returns: The arguments (table)
shared.skpairs(t, revert)
(function)- Iterator sorted by keys.
For example, if you had a table that looked something like
data = {["Cat"] = 5, ["Bat"] = 4, ["Hat"] = 7 }
You could do
for k, v in skpairs(data) do
And your loop would start with k="Bat", v=4 then go to k="Cat", v=5, and finally to k="Hat", v=7
Originally snagged this from Module:VoidByReward written by User:NoBrainz - Parameters:
t
(table)revert
Sort descending order instead (boolean)
- Returns: Sorted iterators (function)
- Created with Docbuntu
See Also
Code
--- '''Shared''' contains useful utilities.
-- <br /><br />
-- On this Wiki, Shared is used in:
-- * [[Module:Acquisition]]
-- * [[Module:Ability]]
-- * [[Module:Arcane]]
-- * [[Module:Avionics]]
-- * [[Module:Cost]]
-- * [[Module:DamageTypes]]
-- * [[Module:Decorations]]
-- * [[Module:DropTables]]
-- * [[Module:Focus]]
-- * [[Module:Lua]]
-- * [[Module:Maximization]]
-- * [[Module:Missions]]
-- * [[Module:Mods]]
-- * [[Module:Stances]]
-- * [[Module:Tables]]
-- * [[Module:Version]]
-- * [[Module:Void]]
-- * [[Module:VoidByReward]]
-- * [[Module:Warframes]]
-- * [[Module:Weapons]]
--
-- @module shared
-- @alias p
-- @author [[User:Falterfire|Falterfire]]
-- @attribution [[User:Cephalon Scientia|Cephalon Scientia]]
-- @attribution [[User:FINNER|FINNER]]
-- @attribution [[User:Gigamicro|Gigamicro]]
-- @attribution [[User:NoBrainz|NoBrainz]]
-- @image Panel.png
-- @require [[Module:Math]]
-- @require [[w:c:dev:Module:Arguments|Module:Arguments]]
-- @release stable
-- <nowiki>
local p = {}
-- Module Dependencies -------------------------------------------------------
local math = require('Module:Math');
local Args = require('Dev:Arguments');
--- For getting frame or parent arguments
-- @function p.getArgs
-- @param {table} frame The input arguments
-- @param {table} options Options for getting the args
-- @return {table} The arguments
function p.getArgs(frame, options)
if type(frame[1]) == 'table' and table.getn(frame) < 2 then frame = frame[1]; end
if type(options) ~= 'table' then options = {options}; end
local args = Args.getArgs(frame, options);
local tempArgs = {};
local str;
if options.replace then
for i, v in pairs(args) do
if type(i) ~= 'number' or type(v) ~= 'string' then tempArgs[i] = v;
else
str = '('..math.replace(v)..')';
if options.eval then tempArgs[i] = tonumber(math.eval(str));
else tempArgs[i] = str; end
end
end
args = tempArgs;
end
local j = 1;
tempArgs = {};
if options.noNil then
for i, v in pairs(args) do
if type(i) ~= 'number' then tempArgs[i] = v;
elseif v then tempArgs[j] = v; j = j + 1; end
end
args = tempArgs;
end
return args;
end
--- Iterator sorted by keys.<br />
-- For example, if you had a table that looked something like<br />
-- `data = {["Cat"] = 5, ["Bat"] = 4, ["Hat"] = 7 }`<br />
-- You could do<br />
-- `for k, v in skpairs(data) do`<br />
-- And your loop would start with k="Bat", v=4 then go to k="Cat", v=5,
-- and finally to k="Hat", v=7<br />
-- Originally snagged this from [[Module:VoidByReward]] written by [[User:NoBrainz]]
-- @function p.skpairs
-- @param {table} t
-- @param {boolean} revert Sort descending order instead
-- @return {function} Sorted iterators
function p.skpairs(t, revert)
local keys = {}
for k in pairs(t) do keys[#keys + 1] = k end
if revert ~= nil then
table.sort(keys, function(a, b) return a > b end)
else
table.sort(keys)
end
local i = 0
local iterator = function()
i = i + 1
local key = keys[i]
if key then
return key, t[key]
else
return nil
end
end
return iterator
end
--Loops through all the Relic types
--Comes up a surprising amount
--rework 11/9/2020 by u:gigamicro
function p.relicLoop()
return function(_, lastTier)
return ({ ['']='Lith', ['Lith']='Meso', ['Meso']='Neo', ['Neo']='Axi' })[lastTier]
end, _, ''
end
function p.consoleLoop()
return function(_, lastTier)
return ({['']='PC', ['PC']='PS4', ['PS4']='XB1', ['XB1']='NSW'})[lastTier]
end, _, ''
end
-- conveniently shifts BLAH to Blah
-- Handy when formatting data in ALL CAPS or all lower case
--Originally snagged this from Module:VoidByReward written by User:NoBrainz
--rework 11/9/2020 by u:gigamicro
function p.titleCase(s)
assert(type(s)=='string', 'Shared.titleCase: expected string, got '..type(s))
return ({ s:gsub("(%a)([%w_']*)", function(h,t) return h:upper()..t:lower() end ) })[1]--gsub also returns #matches; pruned
end
-- Returns the number of rows in a table
-- Originally snagged this from Module:VoidByReward written by User:NoBrainz
-- Note from User:Cephalon Scientia:
-- Length operator (#) doesn't work as expected for tables that have been
-- loaded into a module by mw.loadData().
-- Use this function to get all the rows in a table regardless of them
-- being keys, values, or tables
-- pre : table is a table with no explicit nil values
-- post: returns the size of table, ignoring keys with nil values and
-- nil values themselves
-- if table is not of type 'table' then return nil
function p.tableCount(table)
if (type(table) == 'table') then
local count = 0
for _ in pairs(table) do count = count + 1 end
return count
else
return nil
end
end
-- Returns the number of indexed elements in a table
-- pre : table is a table with no explicit nil values
-- post: returns the number of indexed elements in a table
-- if table is not of type 'table' then return nil
function p.indexCount(table)
if (type(table) == 'table') then
local count = 0
for _ in ipairs(table) do count = count + 1 end
return count
else
return nil
end
end
--Sorts theTable based on the listed column
function p.tableSort(theTable, sortCol, ascend)
local function sorter(r1, r2)
if(ascend) then
return r1[sortCol] < r2[sortCol]
else
return r1[sortCol] > r2[sortCol]
end
end
table.sort(theTable, sorter)
end
--Splits a string based on a sent in separating character
--For example calling splitString ("Lith V1 Relic", " ") would return {"Lith", "V1", "Relic"}
function p.splitString(inputstr, sep)
if sep == nil then
sep = "%s"
end
local t={}
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
table.insert(t, str)
end
return t
end
--Returns 'true' if a string starts with something
--For example calling startsWith ("Lith V1 Relic", "Lith") would return true
function p.startsWith(string1, start)
return string.sub(string1, 1, string.len(start)) == start
end
--Stolen from Stack Overflow
--Adds commas
function p.formatnum(number)
local i, j, minus, int, fraction = tostring(number):find('([-]?)(%d+)([.]?%d*)')
-- reverse the int-string and append a comma to all blocks of 3 digits
int = int:reverse():gsub("(%d%d%d)", "%1,")
-- reverse the int-string back remove an optional comma and put the
-- optional minus and fractional part back
return minus .. int:reverse():gsub("^,", "") .. fraction
end
function p.round(val, maxDigits, minDigits)
if(val == nil) then
return nil
else
if(type(maxDigits) == "table") then
minDigits = maxDigits[2]
maxDigits = maxDigits[1]
end
local result = val..""
local decimals = string.find(result, "%.")
if(decimals ~= nil ) then decimals = string.len(result) - decimals else decimals = 0 end
if(maxDigits ~= nil and decimals > maxDigits) then
result = tonumber(string.format("%."..maxDigits.."f", result))
elseif(minDigits ~= nil and decimals < minDigits) then
result = string.format("%."..minDigits.."f", result)
end
return result
end
end
--From http://lua-users.org/wiki/SimpleRound
function p.round2(num, numDecimalPlaces)
local mult = 10^(numDecimalPlaces or 0)
return math.floor(num * mult + 0.5) / mult
end
-- pre : List is a table or a string
-- Item is the element that is being searched
-- IgnoreCase is a boolean; if false, search is case-sensitive
-- post: returns a boolean; true if element exists in List, false otherwise
function p.contains(List, Item, IgnoreCase)
if (List == nil or Item == nil) then
return false
end
if(IgnoreCase == nil) then
IgnoreCase = false
end
if(type(List) == "table") then
for key, value in pairs(List) do
if (value == Item) then
return true
elseif (IgnoreCase and string.upper(value) == string.upper(Item)) then
return true
end
end
else
local start = string.find(List, Item)
return start ~= nil
end
return false
end
--Stolen from http://lua-users.org/wiki/StringTrim
--Trims whitespace. Not quite sure how it works.
--I know how it works
--replaces "^%s*(.-)%s*$" with "%1" in str
--^%s*(.-)%s*$ matches:
--^:beginning of string
--%s*:any number of spaces
--(.-):any number of any character, minimum possible, saved to %1
--%s* again
--$: end of string
--%1 inserts the content of the parentheses
--pretty simple if you know the meanings
--User:gigamicro
function p.trim(str)
return (str:gsub("^%s*(.-)%s*$", "%1"))
end
-- generic function that checks to see if a key exists in a given nested table
-- added by User:Cephalon Scientia
-- pre : table is a nested table
-- key is a string that represents a key name
-- length is a integer that represents the size of outer table;
-- if omitted, length is set to size of outer table
-- post: returns a boolean; true if key exists in table, false otherwise or
-- if key contains a nil value
function p.hasKey(table, key, length)
if (length == nil) then
length = p.tableCount(table)
end
-- iterating through outer table
for i = 1, length, 1 do
local elem = table[i] -- storing one of inner tables into a variable
if (elem[key] ~= nil) then
return true
end
end
return false
end
-- copies the contents of a variable; for copying tables recursively
-- source: http://lua-users.org/wiki/CopyTable
-- pre : orig is the original value
-- post: returns a copy of the original table if orig is of type
-- table, including all children tables but not metatables;
-- otherwise returns whatever is contained in orig
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[p.deepCopy(orig_key)] = p.deepCopy(orig_value)
end
-- cannot copy metatables of tables loaded in by mw.loadData();
-- stack overflow error if you uncomment the statement below
-- setmetatable(copy, p.deepCopy(getmetatable(orig)))
else -- number, string, boolean, etc
copy = orig
end
return copy
end
-- converts a float value into a percentage
function p.asPercent(val, digits)
return string.format("%."..(digits or 2).."f", (val or 0) * 100)..'%'
end
do--upk by [[User:gigamicro]], sanitizes any object to a string
local conversion = {
string=function(v)
v = v:gsub('\n','\\n'):gsub('%c',function(s) return '\\'..s:byte() end)
if not v:match"'" then
return "'"..v.."'"
elseif not v:match '"' then
return '"'..v..'"'
else
local n=0; while v:match(']'..(('='):rep(n))..']') do n=n+1 end; local s = (('='):rep(n)); return table.concat{'[',s,'[',v,']',s,']'}
end
end,
boolean=function(v) return v and 'true' or 'false' end,
number=function(v) return tostring(v) end,
table=function(v, linedepth)
local str = {'{'}
local index = 1
if linedepth and linedepth > 0 then table.insert(str, '\n') end
for k,val in pairs(v) do
--print (k, '(', type(val), ')')
if k==index then index=index+1 else table.insert(str, '['..p.upk(k)..'] = ') end
if v ~= val and k~='_G' and k~='loaded' then
table.insert(str, p.upk(val, linedepth and linedepth>0 and linedepth-1))
else
table.insert(str, '<repeat>')
end --print (k,'=',str[#str])
table.insert(str, ', ')
if linedepth and linedepth>0 then table.insert(str, '\n') end
end
table.insert(str,'}')
--if print then print (table.concat(str)) end
return table.concat(str)
end,
['function'] = function() return '<function>' end,--function()end' end,
['nil'] = function() return 'nil' end,
userdata = function() return '<userdata>' end,
thread = function() return '<thread>' end,
}
function p.upk(v, linedepth) return conversion[type(v)](v,linedepth) end--(conversion[type(v)..'e'] or function(v,ld) error(type(v)..' is not a recognized type') end)(v, linedepth or 0) end
end--upk
function p.Cache(frame)return p.upk(require(frame.args[1])[frame.args[2]][frame.args[3]])end
function p.unEscape(s)return(s:gsub('&#([%d]+);',function(n)return string.char(n+0) end))end
return p
Community content is available under CC-BY-SA unless otherwise noted.