Module:Core

From Lifecraft Wiki
Revision as of 14:29, 27 March 2025 by Draculea8302 (talk | contribs) (Created page with " local Utils = {} -- * Function functions :V function Utils.id(...) return ... end function Utils.second(_, x) return x end -- * Number functions. function Utils.round(x) return math.floor(x + 0.5) end function Utils.divMod(x, y) return math.floor(x / y), x % y end -- * Collection functions. function Utils.isize(xs) local r = 0 for _ in ipairs(xs) do r = r + 1 end return r end function Utils.size(xs) local r = 0 for _ in pairs(xs) do r = r + 1...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

local Utils = {}

-- * Function functions :V

function Utils.id(...) return ... end

function Utils.second(_, x)

   return x

end

-- * Number functions.

function Utils.round(x) return math.floor(x + 0.5) end

function Utils.divMod(x, y) return math.floor(x / y), x % y end

-- * Collection functions.

function Utils.isize(xs) local r = 0 for _ in ipairs(xs) do r = r + 1 end return r end

function Utils.size(xs) local r = 0 for _ in pairs(xs) do r = r + 1 end return r end

function Utils.removekey(xs, k) local e = xs[k] xs[k] = nil return e end

function Utils.isArray(xs) for k, _ in pairs(xs) do return k == 1 end return true end

function Utils.findBy(xs, p)

   if Utils.isArray(xs) then

for k, v in ipairs(xs) do

           if p(v, k) then

return v, k end

       end
   else

for k, v in pairs(xs) do if p(v, k) then return v, k end

       end
   end

return nil end

function Utils.find(tbl, v_, k_) for _, v in pairs(tbl) do if k_ and v and v[k_] == v_ or not k_ and v == v_ then return v end end return false end

function Utils.includes(tbl, v_, k_) for _, v in pairs(tbl) do if k_ and v and v[k_] == v_ or not k_ and v == v_ then return true end end return false end

function Utils.map(tbl, fn) local result = {} for k, v in pairs(tbl) do table.insert(result, fn(v, k)) end return result end

function Utils.filter(tbl, pred) local result = {} for k, v in pairs(tbl) do if pred(v, k) then table.insert(result, v) end end return result end

function Utils.first(tbl)

   for k, v in pairs(tbl) do
       return k, v
   end

end

function Utils.keys(tbl) local result = {} for k, _ in pairs(tbl) do table.insert(result, k) end return result end

function Utils.values(tbl) local result = {} for _, v in pairs(tbl) do table.insert(result, v) end return result end

function Utils.ifind(arr, v_) for i, v in ipairs(arr) do if v == v_ then return i end end return false end

function Utils.ifindBy(arr, p) for i, v in ipairs(arr) do if p(v) then return v, i end end return false end

function Utils.imax(arr, def)

   local maxValue
   local maxIndex

for i, v in ipairs(arr) do if not maxValue or v > maxValue then maxValue = v maxIndex = i end end return maxValue or def end

function Utils.imin(arr, def)

   local minValue
   local minIndex

for i, v in ipairs(arr) do if not minValue or v < minValue then minValue = v minIndex = i end end return minValue or def end

function Utils.imap(arr, fn) local result = {} for i, v in ipairs(arr) do table.insert(result, fn(v, i)) end return result end

function Utils.ifilter(arr, pred) local result = {} for i, v in ipairs(arr) do if pred(v, i) then table.insert(result, v) end end return result end

function Utils.ifirst(arr)

   for k, v in ipairs(arr) do
       return k, v
   end

end

function Utils.ilast(arr) return arr[#arr] end

function Utils.insertNew(arr, el)

   if not Utils.find(arr, el) then
       table.insert(arr, el)
   end

end

function Utils.concat(arr1, arr2)

   for i = 1, #arr2 do
       arr1[#arr1 + 1] = arr2[i]
   end
   return arr1

end

Utils.join = table.concat

function Utils.ijoin(arr, sep)

   sep = sep or ""
   return table.concat(arr, sep)

end

function Utils.joinLines(arr)

 return table.concat(arr, "\n")

end

function Utils.icopy(arr)

   return Utils.imap(arr, function(v) return v end)

end

function Utils.sort(tbl, f)

   table.sort(tbl, f)
   return tbl

end

function Utils.isort(arr, f)

   local result = Utils.icopy(arr)
   table.sort(result, f)
   return result

end

function Utils.isum(arr, result)

   result = result or 0
   for _, v in ipairs(arr) do
       result = result + (v or 0)
   end
   return result

end

-- * Number functions.

function Utils.round(x)

   return x % 2 ~= 0.5 and math.floor(x + 0.5) or x - 0.5

end

-- * String functions.

function Utils.pad(s, n, c)

   c = c or " "
   n = n or 0
   s = tostring(s) or ""
   return #s < n and string.rep(c, n - #s) .. s or s

end

function Utils.trim(s)

   return string.gsub(s, "^%s*(.-)%s*$", "%1")

end

function Utils.startsWith(s, ss)

   return string.sub(s, 1, string.len(ss)) == ss

end

-- Capitalize each word in a string. function Utils.capitalize(s)

   s = s:gsub("(%s)(%l)", function(a, b) return a .. string.upper(b) end)
   s = s:gsub("^(%l)", function(a) return string.upper(a) end)
   return s

end

-- * Wikitext/HTML functions.

function Utils.category(name)

   return "" .. "Category:" .. name .. ""

end

function Utils.red(s)

   return Utils.format{[[${s}]], s = s}

end

-- * Calling arbitrary Lua functions using #invoke.

-- Used to call Formatting:tooltip in Template:Tooltip, mainly because Lua code properly escapes characters, -- so that span's title attribute always works. function Utils.method(frame) local m = require("Module:" .. frame.args[1]) local f = frame.args[2] local args = {} for k, v in ipairs(frame.args) do if type(k) == "number" and k >= 3 and type(v) == "string" then table.insert(args, v) end end return m[f](m, unpack(args)) end

-- * Frame functions.

local getArgs = require("Module:GetArgs")

-- Unused. function Utils.getContext(frame)

   local frame1 = frame:getParent()
   if frame1 then
       local frame2 = frame1:getParent()
       if frame2 then
           return { pagename = frame2:getTitle(), args = getArgs{ frame = frame2 } }
       else
           return { pagename = frame1:getTitle(), args = getArgs{ frame = frame1 } }
       end
   else
       return { pagename = frame:getTitle(), args = getArgs{ frame = frame } }
   end

end

-- getParent -> getArgs function Utils.getParentArgs(frame)

   local frame1 = frame:getParent()
   if frame1 then
       return getArgs{ frame = frame1 }
   else
       return nil
   end

end

-- getArgs + getParent -> getArgs, "implicit" args can be defined in the template (e.g. pagename=Module:Core) -- "explicit" args are user defined. function Utils.getTemplateArgs(frame)

   local frame1 = frame:getParent()
   if frame1 then
       return { implicit = getArgs{ frame = frame }, explicit = getArgs{ frame = frame1 } }
   else
       return { implicit = getArgs{ frame = frame }, explicit = {} }
   end

end

function Utils.requireModule(name)

   local success, data = pcall(function () return require(string.format("Module:%s", name)) end)
   -- module without return (or empty, nil, false, true return) gives success = true, data = true
   if data == true then
       return false, nil
   else
       return success, data
   end

end

function Utils.loadData(name)

   local success, data = pcall(function () return mw.loadData(string.format("Module:%s", name)) end)
   -- TODO: ???
   if data == true then
       return false, nil
   else
       return success, data
   end

end

-- * Testing functions.

function Utils.debugPrint(x, i)

   i = i or 0
   if type(x) == "table" then
       for k, v in pairs(x) do
           mw.log(
               string.rep("  ", i) .. tostring(k) .. " : " .. type(k) .. " = " ..
               (type(v) == "table" and "table" or tostring(v) .. " : " .. type(v))
           )
           if type(v) == "table" then
               Utils.debugPrint(v, i + 1)
           end
       end
   else
       mw.log(tostring(x) .. " : " .. type(x))
   end

end

local function showValue(v)

   return type(v) == "string" and string.format('"%s"', v) or type(v) == "function" and '"function"' or tostring(v)

end

function Utils.js(x, i)

   i = i or 0
   local r = ""
   if type(x) == "table" then
       r = "{\n"
       for k, v in pairs(x) do
           if type(v) == "table" then
               r = r .. string.rep("  ", i + 1) .. tostring(k) .. ": " .. Utils.js(v, i + 1)
           else
               r = r .. string.rep("  ", i + 1) .. tostring(k) .. ": " .. showValue(v) .. ",\n"
           end
       end
       r = r .. string.rep("  ", i) .. (i == 0 and "}\n" or "},\n")
   else
       return showValue(x)
   end
   return r

end

function Utils.registerFormatTests(obj, tests, fn)

   obj.run_format_tests = function()
       for _, test in ipairs(tests) do
           local result = obj.format(nil, test)
           mw.log(fn and fn(result) or result)
       end
   end

end

function Utils.registerTableTests(obj, tests, fn)

   obj.run_table_tests = function()
       for _, test in ipairs(tests) do
           local result = obj:Table(test)
           mw.log(fn and fn(result) or result)
       end
   end

end

function Utils.test(obj, desc, fn)

   obj.test = function()
       mw.log(desc)
       fn(obj)
       mw.log("ok")
   end

end

Utils.log = mw.log

function Utils.format(s, lookup) if not lookup then lookup = s s = lookup[1] table.remove(lookup, 1) end return (string.gsub(s, '${([^%.%!%:%}%[%]]+)%[?([^%.%!%:%}%]]*)%]?%.?([^%!%:%}]*)!?([^%:%}]?):?([^%}]*)}', function(name, element, attribute, conversion, format_spec) --local start_of_value, end_of_value, value = string.find(x, '^${(.-)[[.!:}]') --local start_of_access, end_of_access, access = string.find(x, '^${.-%[(.-)%][!:}]') --if not access then -- start_of_access, end_of_access, access = string.find(x, '^${[^:]-%.(.-)[!:}]') --end --local start_of_conversion, end_of_conversion, conversion = string.find(x, '^${.-!(.)[:}]') --local start_of_format_spec, end_of_format_spec, format_spec = string.find(x, ':(.*)}$')

local value = lookup[name] if string.len(element) > 0 then value = value[element] elseif string.len(attribute) > 0 then value = value[attribute] end

if string.len(conversion) > 0 then if conversion == 's' then value = tostring(value) end end

if string.len(format_spec) > 0 then local start_of_sign, end_of_sign, sign = string.find(format_spec, '([+%- ])') local start_of_width, end_of_width, width, comma, precision, option = string.find(format_spec, '(%d*)(,?)([.0-9]*)([bcdeEfFgGnosxX%%]?)$') precision = string.sub(precision, 2) local number = tonumber(value) if #width > 0 then if number then value = string.format(string.format(number % 1 ~= 0 and "%%0%s.%sf" or "%%0%sd", width, #precision > 0 and precision or 0), number) end value = string.format(string.format("%%0%ss", width), value) elseif #precision > 0 and number then value = string.format(string.format("%%0%s.%sf", width, precision), number) end if sign then if number and number > 0 then if sign == "+" then value = "+" .. value elseif sign == " " then value = " " .. value end end end end

return value end)) end

function Utils.split(string, separator, max_split, plain) assert(separator ~= ) assert(max_split == nil or max_split >= 1)

local default_separator = false

local result = {}

if not separator or separator == then separator = '%s+' plain = false string = mw.text.trim(string) if string == then return result end end

max_split = max_split or -1

local item_index, start_index = 1, 1 local separator_start, separator_end = mw.ustring.find(string, separator, start_index, plain) while separator_start and max_split ~= 0 do result[item_index] = mw.ustring.sub(string, start_index, separator_start - 1) item_index = item_index + 1 start_index = separator_end + 1 separator_start, separator_end = mw.ustring.find(string, separator, start_index, plain) max_split = max_split - 1 end result[item_index] = mw.ustring.sub(string, start_index)

return result end

Utils.romanizable = {'zh-hans', 'zh-hant', 'zh-cn', 'zh-tw', 'zh-hk', 'zh-sg', 'zh-mo', 'zh-my', 'ja', 'ko', 'vi'}

Utils.normalization_table = {[' '] = ' ', ['~'] = '~', ['!'] = '!', ['?'] = '?'}

-- checks if string is set and if it's non-empty function Utils.isset(target)

 return target ~= nil and target ~= ""

end

--[[ simulates the (a ? b : c) notation of C/C++ and PHP languages.

    Similar to  from parser functions. ]]

function Utils.cv(a, b, c)

 if a then return b else return c end

end

--slices a table to return another table containing values within a certain range --source: http://snippets.luacode.org/snippets/Table_Slice_116 function Utils.sliceTable (values,i1,i2)

   local res = {}
   local n = #values
   -- default values for range
   i1 = i1 or 1
   i2 = i2 or n
   if i2 < 0 then
       i2 = n + i2 + 1
   elseif i2 > n then
       i2 = n
   end
   if i1 < 1 or i1 > n then
       return {}
   end
   local k = 1
   for i = i1,i2 do
       res[k] = values[i]
       k = k + 1
   end
   return res

end

-- checks if a given page exists function Utils.exists(page)

 if not Utils.isset(page) then return false end
 return mw.getCurrentFrame():preprocess('0') == '1'

end

--[[ Tries to get contents of a page with given name.

    If the function fails it returns nil (page doesn't exist or can't be loaded)
    On success it returns the contents of page (it can be be partially preprocessed, so watch out for parser markers). ]]

function Utils.getPage(name)

 if not Utils.isset(name) then return nil end
 local frame = mw.getCurrentFrame()
 -- do a safe call to catch possible errors, like "template doesn't exist"
 local stat,page = pcall(frame.expandTemplate, frame, {title = ':' .. name})
 if not stat then
   -- TODO: 'page' contains the error message. Do some debugging?
   return nil
 end
 return page

end

function Utils.stripTags(text)

 if Utils.isset(text) then
   local tmp
   repeat
     tmp = text

-- a pair of tags, like ...

     text = string.gsub(text, '<%s*(%w+).->(.-)<%s*/%s*%1%s*>', '%2')
     -- closed tag, like 
text = string.gsub(text, '<%s*%w+%s*/%s*>', ) until tmp == text end return text

end

--[[ Sort table and remove repeating elements.

    Since tbl is passed as reference, any changes in it will affect the passed table. ]]

function Utils.trunkTable(tbl)

 table.sort(tbl)
 local last
 local redo
 repeat
   redo = false
   last = nil
   for k,v in pairs(tbl) do
     if v ~= last then
       last = v
     else
       table.remove(tbl, k)
       redo = true
       break
     end
   end
 until not redo

end

--[[ Checks if a given value is among the elements of a table and returns its index.

     Returns nil if it can't find it. ]]

function Utils.isInTable(tbl, val)

 for k,v in pairs(tbl) do
   if v == val then return k end
 end
 return nil

end

--Compare 'n' elements in two tables, starting from 's1' in first table and 's2' in second table. function Utils.partialTableCompare(t1, t2, s1, s2, n)

 if n < 1 then return true end -- basically there's nothing to compare, so no differences were found
 for i = 0,(n-1) do
   -- Note that nil values are also valid.
   if t1[s1+i] ~= t2[s2+i] then return false end
 end
 return true

end

-- naming based on "Navbox" elements Utils.main_colors = {

 game = {border = '#A88580', title = '#FFC9C2', above = '#FFD1CA', group = '#FFD9D2', subgroup = '#FFE1DA', dark = '#FFEEE8', background = '#FFF4EE'};
 music = {border = '#A8A077', title = '#FFF3B4', above = '#FFF6C0', group = '#FFF7C8', subgroup = '#FFF8D0', dark = '#FFFBE4', background = '#FFFBEE'};
 printwork = {border = '#9298A8', title = '#DDE6FF', above = '#E1E7FF', group = '#E6E9FF', subgroup = '#EAECFF', dark = '#EDF2FF', background = '#F4F9FF'};

}

-- function for easy adding of styles to html tags function Utils.addStyle(tbl, val)

 if Utils.isset(val) then
   local av = tostring(val):gsub("^%s*(.-)%s*$", "%1")
   if string.sub(av, -1) ~= ';' then av = av .. ';' end
   tbl[#tbl+1] = av
 end

end

return Utils