Editing Module:Utils

From Eco - English Wiki

Your changes will be displayed to readers once an authorized user accepts them. (help)

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 publish the changes below to finish undoing the edit.

Latest revision Your text
Line 1: Line 1:
local p = {}
local p = {}


--- Trims and parses the args into a table, then returns the table
-- Trims and parses the args into a table, then returns the table
-- @author User:Avaren
function p.normaliseArgs(frame)
function p.normaliseArgs(frame)
local origArgs = frame:getParent().args
    local origArgs = frame:getParent().args
local args = {}
    local args = {}


for k, v in pairs(origArgs) do
    for k, v in pairs(origArgs) do
v = mw.text.trim(tostring(v))
        v = mw.text.trim(tostring(v))
if v ~= '' then
        if v ~= '' then
args[k] = v
            args[k] = v
end
        end
end
    end


return args
    return args
end
end


--- Get path to icon file.
-- @author User:Avaren
function p.checkImage(name, too_expensive)
function p.checkImage(name, too_expensive)
local icon = name:gsub('%s+', '') .. '_Icon.png'
    local icon = name:gsub('%s+', '') .. '_Icon.png'
if too_expensive then
    if too_expensive then
return icon
        return icon
end
    end


if mw.title.makeTitle('File', icon).file.exists then
    if mw.title.makeTitle('File', icon).file.exists then
return icon
        return icon
else
    else
return 'NoIcon.png'
        return 'NoImage.png'
end
    end
end
end


function p.itemId(name)
return name:gsub('%s+', '') .. 'Item'
end
--- Check if <code>item</code> is in given <code>array</code>.
-- @param item Item to look for
-- @param #table array Table to check
-- @return #bool <code>true</code> if <code>item</code> is in <code>array</code>
-- @author User:Avaren
local function in_array(item, array)
local function in_array(item, array)
-- Should only use on short arrays
    -- Should only use on short arrays
local set = {}
    local set = {}
for _, l in ipairs(array) do
    for _, l in ipairs(array) do
set[l] = true
        set[l] = true
end
    end
return set[item] ~= nil
    return set[item] ~= nil
end
end


--- Calculate the length of a table by iterating over every item in it.
---@param name string
--
---@param size string|nil
-- <code>mw.LoadData</code> prevents <code>#tbl</code> from working correctly.
---@param bg string|nil
-- @param #table tbl Table to calculate the length of
---@param border string|nil
-- @return #number Length of the table.
---@param too_expensive boolean|nil
-- @author User:Avaren
function p.build_icon(name, size, bg, border, too_expensive)
function p.tableLen(tbl)
    -- Size options are iconNormal or iconRecipe - 64px or 44px - defaults to iconNormal
local count = 0
for _, v in ipairs(tbl) do
if v == nil then
return count
end
count = count + 1
end
return count
end


--- Check if <code>value</code> is not <code>nil</code> and return it or if it is <code>nil</code> fall back to <code>default</code>.
    local L = require('Module:Localization') -- local import
-- @param value Value to check
-- @param default Value to fall back to
-- @return <code>value</code> if it is not <code>nil</code>
-- @return <code>default</code> if <code>value</code> is <code>nil</code>
-- @author User:Demian
-- @see valueOrDash
-- @see formatNilToYesNo
-- @see formatBoolToYesNo
function p.valueOrDefault(value, default)
return nil == value and default or value
end


--- Check if <code>value</code> is not <code>nil</code> and return it or if it is <code>nil</code> fall back to the em-dash (—).
    if not size then
--
        size = 'iconNormal'
-- The em-dash (—) is commonly used represent a missing, not applicable (N/A), or a negative ("no") value with just a single character.
    end
-- @param value Value to check
    local icon_bg
-- @return <code>value</code> if it is not <code>nil</code>
    local icon_border
-- @return #string "—" if <code>value</code> is <code>nil</code>
-- @author User:Demian
-- @see valueOrDefault
function p.valueOrDash(value)
return nil == value and "—" or value
end


--- Check if <code>value</code> is not <code>nil</code> and return "Yes" or "No".
    local item_data = mw.loadData('Module:ItemData')
-- @param value Value to check
    local item = item_data.items[name]
-- @return #string "Yes" if <code>value</code> is not <code>nil</code>
    local image
-- @return #string "No" if <code>value</code> is <code>nil</code>
    if item then
-- @author User:Demian
        if item['group'] == L.t('Skill Books') then
-- @see valueOrDefault
            image = 'SkillBook.png'
-- @usage formatNilToYesNo("Hello") == "Yes"
            icon_bg = 'iconGold'
-- @usage formatNilToYesNo(nil) == "No"
        elseif item['group'] == L.t('Skill Scrolls') then
function p.formatNilToYesNo(value)
            image = 'Skill Scroll'
-- TODO: Support i18n.
            icon_bg = 'iconGold'
return nil == value and "No" or "Yes"
            -- Attempt to generate skill page
end
        elseif in_array(L.t('Basic  Research'), item['tagGroups']) then
            image = string.sub(item['untranslated'], 1, -7):gsub('%s+', '') .. '_Icon.png'
            icon_bg = 'paperBasic'
        elseif in_array(L.t('Advanced  Research'), item['tagGroups']) then
            image = string.sub(item['untranslated'], 1, -10):gsub('%s+', '') .. '_Icon.png'
            icon_bg = 'paperAdvanced'
        elseif in_array(L.t('Modern  Research'), item['tagGroups']) then
            image = string.sub(item['untranslated'], 1, -8):gsub('%s+', '') .. '_Icon.png'
            icon_bg = 'paperModern'
        else
            image = p.checkImage(item['untranslated'], too_expensive)
        end
        if not bg and not icon_bg then
            if item['group'] == L.t('Food') then
                icon_bg = 'iconGreen'
            elseif item['carried'] == L.t('Hands') then
                icon_bg = 'iconBrown'
            end
        end
    else
        image = p.checkImage(name, too_expensive)
    end


--- Check if <code>value</code> <em>evaluates</em> as <code>true</code> and return "Yes" or "No".
    if not icon_bg then
-- @param value Value to evaluate. Does not have to be a bool.
        icon_bg = 'iconBlue'
-- @return #string "Yes" if <code>value</code> evaluates as <code>true</code>
    end
-- @return #string "No" if <code>value</code> evaluates as <code>false</code>
-- @author User:Demian
-- @see valueOrDefault
-- @usage formatBoolToYesNo("") == true
-- @usage formatBoolToYesNo(123) == true
-- @usage formatBoolToYesNo(nil) == false
function p.formatBoolToYesNo(value)
-- TODO: Support i18n.
return value and "Yes" or "No"
end


--- Format the input values into a string representing the range between the values.
    if border then
--
        icon_border = border
-- Returning an an empty string intended to ease concatenation with other strings.
    else
-- The en-dash (–) (instead of the hyphen-minus "-") is the appropriate character to signify a range of values.
        icon_border = 'borderBlue'
-- @param #number min Minimum value (left side)
    end
-- @param #number max Maximum value (right side)
-- @param #number default Default value in case of an error (only value).
-- @param #string valueFormat Format string used with <code>mw.ustring.format</code>.
-- @return #string "<code>min</code>–<code>max</code>" if <code>min < max</code>
-- @return #string "<code>default</code>" formatted with <code>valueFormat</code> if <code>min == max</code> or <code>min > max</code> and <code>default ~= nil</code>
-- @return #string "" (empty string) if either <code>min</code> <strong>or</strong> <code>max</code> do not convert to a numerical value
-- @return #nil <code>nil</code> if <code>min == max</code> or <code>min > max</code> and <code>default == nil</code>
-- @author User:Demian
function p.toRangeString(min, max, default, valueFormat)
min = tonumber(p.valueOrDefault(min, nil))
max = tonumber(p.valueOrDefault(max, nil))
default = tonumber(p.valueOrDefault(default, nil))


if nil ~= min and nil ~= max then
    if size == 'iconNormal' then
if min < max then
        icon_container = 'iconContainer'
return mw.ustring.format(mw.ustring.format("%s–%s", valueFormat, valueFormat), min, max)
    else
elseif nil == default then
        icon_container = 'iconContainerSmall'
return nil
    end
else
return mw.ustring.format(valueFormat, default)
end
end


return ""
    local file = '[[File:' .. image .. '|frameless|class=' .. size .. ' ' .. icon_bg .. ']]'
    return '<div class="' .. icon_container .. '"><div class="iconStack">' .. file .. '</div><div class="iconBorder ' .. icon_border .. '" style="position:absolute;"></div></div>'
end
end


--- Get all keys from <code>tbl</code> and sort them in alphabetical order.
function p.Icon(frame)
-- @param #table tbl Table to get keys from
    args = p.normaliseArgs(frame)
-- @return #table Input table keys in alphabetical order.
    return p.build_icon(args.name, args.size, args.bg, args.border, args.too_expensive)
-- @author User:Demian
-- @see getSortedValues
function p.getSortedKeys(tbl)
local sorted = {}
 
for key in pairs(tbl) do
table.insert(sorted, key)
end
 
table.sort(sorted)
 
return sorted
end
end


--- Get all values from <code>tbl</code> and sort them in alphabetical order.
-- mw.LoadData prevents #table from working correctly
-- @param #table tbl Table to get values from
function p.tableLen(tbl)
-- @return #table Input table values in alphabetical order.
    local count = 0
-- @author User:Demian
    for _, v in ipairs(tbl) do
-- @see getSortedKeys
        if v == nil then
function p.getSortedValues(tbl)
            return count
local sorted = {}
        end
 
        count = count + 1
for _, value in ipairs(tbl) do
table.insert(sorted, value)
end
 
table.sort(sorted)
 
return sorted
end
 
--- Split <code>str</code> by the given character.
-- @param #string str String to split
-- @param #string separator String that separates values in <code>str</code>. May optionally be surrounded by 1 <em>whitespace</em> character by default.
-- @return #table Table of strings that were split from <code>str</code>.
-- @author User:Demian
-- @usage splitString("hello, world", ",") == {"hello", "world"}
function p.splitString(str, separator)
local tbl = {}
 
for token in mw.ustring.gmatch(str, mw.ustring.format("%%s?([^%s]+)%%s?", separator)) do
table.insert(tbl, token)
end
 
return tbl
end
 
--- Sort items in the given list of values <code>str</code> separated with <code>separator</code> and return them as a single string.
-- @param #string str String with values separated by <code>separator</code>
-- @param #string separator String that separates values in <code>str</code>
-- @param #string joiner String used to join sorted values from <code>str</code>.
-- @return #string <code>str</code> with items sorted in alphabetical order.
-- @author User:Demian
-- @usage sortListString("Dog,Ape, Cat", ",", ";") == "Ape;Cat;Dog"
function p.sortListString(str, separator, joiner)
-- Split string by commas.
-- Sort items.
-- Rejoin into string.
return table.concat(p.getSortedValues(p.splitString(str, separator)), joiner)
end
 
--- Check if a page with the title "<code>name</code> (<code>disambiguationTitle</code>)" exists in the database and return that page title, otherwise return "<code>name</code>".
--
-- Use sparingly as this uses a comparatively slow MediaWiki function p.to check if a page exists.
--
-- Using this function p.will create a new entry in the <code>Special:WantedPages</code> list.
-- Be careful when calling this function p.and do not pass garbage into its parameters so you do not clog up that list.
-- This is a long-standing issue with MediaWiki that has not yet been solved, and may not be possible to solve without an architectural change to the software.
-- @param #string name Name of a page.
-- @param #string disambiguationTitle Disambiguation clarifier in a page title.
-- @return #string "<code>name</code> (<code>disambiguationTitle</code>)"
-- @return #string "<code>name</code>"
-- @author User:Demian
function p.getDirectPageName(name, disambiguationTitle)
-- Try to get the actual end page instead of the disambiguation page if it exists.
-- E.g. Salmon has "Salmon (animal)" and "Salmon (item)" as well as the "Salmon" disambiguation page between these two.
local directPage = mw.ustring.format("%s (%s)", name, disambiguationTitle)
return mw.title.new(directPage).exists and directPage or name
end
 
--- Create a wikilink with [[square brackets]] from parameters.
-- @param #string pageName The actual name of a page to create a link to
-- @param #string displayText Text to display as a clickable link instead of the page name. If <code>nil</code>, <code>pageName</code> is displayed instead.
-- @param #bool twoLineDisplayText Force the <em>last word</em> of <code>displayText</code> on the next line
-- @return #string "[[<code>name</code>|<code>displayText</code>]]" if <code>displayText</code> is not <code>nil</code>
-- @return #string "[[<code>name</code>]]" if <code>displayText</code> is <code>nil</code> or the same string as <code>name</code>
-- @author User:Demian
function p.formatWikilink(pageName, displayText, twoLineDisplayText)
local finalDisplayText = p.valueOrDefault(displayText, pageName)
 
if twoLineDisplayText then
local lastSpaceIdx = mw.ustring.find(finalDisplayText, " [^ ]*$")
 
if nil ~= lastSpaceIdx then
finalDisplayText = mw.ustring.format("%s<br>%s", mw.ustring.sub(finalDisplayText, 0, lastSpaceIdx-1), mw.ustring.sub(finalDisplayText, lastSpaceIdx+1))
end
end
 
if pageName == finalDisplayText then
return mw.ustring.format("[[%s]]", pageName)
else
return mw.ustring.format("[[%s|%s]]", pageName, finalDisplayText)
end
end
 
--- Add thousands separator to given number and use custom decimal point.
--
-- Extension:NumberFormat is more extensive, but more cumbersome to use and also not installed at the moment.
-- @param #string number Number to format. Is processed as a string regardless of type.
-- @param #string thousandsSeparator String to place between each set of 3 digits. Default: " "
-- @param #string decimalPoint String to place between the whole and fractional part of the number. Default: "."
-- @return #string <code>number</code> with the specified thousands separator and decimal point.
-- @return #string <code>number</code> unchanged if it contained 1 or more characters that are <strong>not</strong> a: digit, one of ".,-", a space.
-- @author User:Demian
-- @usage formatNumber(-1234567.89) = "-1 234 567.89"
-- @usage formatNumber("1234567,89", ".", "_") = "1,234,567_89"
function p.formatNumber(number, thousandsSeparator, decimalPoint)
-- Default separator to space.
if nil == thousandsSeparator then
thousandsSeparator = " "
end
 
-- Default point to period.
if nil == decimalPoint then
decimalPoint = "."
end
 
-- We're dealing with formatting a string here.
local numberString = tostring(number)
 
-- Check if the input number is reasonable.
-- Does NOT check for multiple instance of each character.
-- E.g. Inputting something like 123-456.789 will lead to incorrect results.
-- I can't handle every edge case: garbage in, garbage out.
-- The user has to have some responsibility in inputting reasonable numbers.
if mw.ustring.find(numberString, "[^%d%.%-, ]") then
return number
end
 
-- Split input into parts.
-- 1st group: MAY start with a "-".
-- 2nd group: MUST contain 1 or more digits-
-- 3rd group: MAY start with with one of ".,"
-- 3rd group: MAY have 0 or more digits.
local _, _, minus, digits, fraction = mw.ustring.find(tostring(numberString), "(-?)(%d+)([%.,]?%d*)")
 
-- Reverse the string of digits.
-- Append the thousands separator after (before when reversed again) each set of 3 digits.
digits = mw.ustring.gsub(string.reverse(digits), "(%d%d%d)", mw.ustring.format("%%1%s", thousandsSeparator))
 
-- Replace the existing decimal separator with the specified one.
if "" ~= fraction then
fraction = mw.ustring.format("%s%s",decimalPoint, mw.ustring.sub(fraction, 2))
end
 
-- Reverse the string of digits back to the original direction.
-- If the string digits starts with the thousands separator, remove the separator.
-- Add the optional minus in front and the optional fractional part at the back.
-- Need to remember to escape the thousandsSeparator, it could be "." which would translate to "any character"!
return mw.ustring.format("%s%s%s", minus, mw.ustring.gsub(string.reverse(digits), mw.ustring.format("^%%s", thousandsSeparator), ""), fraction)
end
 
--- Check if the string is empty or <code>nil</code>.
-- @param #string str String to check
-- @return #bool <code>true</code> if <code>str</code> is <code>nil</code> or an empty string ("").
-- @author User:Demian
function p.isEmpty(str)
return nil == str or "" == str
end
 
function p.mapColour(colourName)
    local foreground = "white"
    local background = "#1165AF"
 
    mw.log(colourName)
 
    colour_map = {
        ["aliceblue"] = "f0f8ff",
        ["antiquewhite"] = "faebd7",
        ["aqua"] = "00ffff",
        ["aquamarine"] = "7fffd4",
        ["azure"] = "f0ffff",
        ["beige"] = "f5f5dc",
        ["bisque"] = "ffe4c4",
        ["black"] = "000000",
        ["blanchedalmond"] = "ffebcd",
        ["blue"] = "0000ff",
        ["blueviolet"] = "8a2be2",
        ["brown"] = "a52a2a",
        ["burlywood"] = "deb887",
        ["cadetblue"] = "5f9ea0",
        ["chartreuse"] = "7fff00",
        ["chocolate"] = "d2691e",
        ["coral"] = "ff7f50",
        ["cornflowerblue"] = "6495ed",
        ["cornsilk"] = "fff8dc",
        ["crimson"] = "dc143c",
        ["cyan"] = "00ffff",
        ["darkblue"] = "00008b",
        ["darkcyan"] = "008b8b",
        ["darkgoldenrod"] = "b8860b",
        ["darkgray"] = "a9a9a9",
        ["darkgreen"] = "006400",
        ["darkkhaki"] = "bdb76b",
        ["darkmagenta"] = "8b008b",
        ["darkolivegreen"] = "556b2f",
        ["darkorange"] = "ff8c00",
        ["darkorchid"] = "9932cc",
        ["darkred"] = "8b0000",
        ["darksalmon"] = "e9967a",
        ["darkseagreen"] = "8fbc8f",
        ["darkslateblue"] = "483d8b",
        ["darkslategray"] = "2f4f4f",
        ["darkturquoise"] = "00ced1",
        ["darkviolet"] = "9400d3",
        ["deeppink"] = "ff1493",
        ["deepskyblue"] = "00bfff",
        ["dimgray"] = "696969",
        ["dodgerblue"] = "1e90ff",
        ["feldspar"] = "d19275",
        ["firebrick"] = "b22222",
        ["floralwhite"] = "fffaf0",
        ["forestgreen"] = "228b22",
        ["fuchsia"] = "ff00ff",
        ["gainsboro"] = "dcdcdc",
        ["ghostwhite"] = "f8f8ff",
        ["gold"] = "ffd700",
        ["goldenrod"] = "daa520",
        ["gray"] = "808080",
        ["green"] = "008000",
        ["greenyellow"] = "adff2f",
        ["honeydew"] = "f0fff0",
        ["hotpink"] = "ff69b4",
        ["indianred "] = "cd5c5c",
        ["indigo "] = "4b0082",
        ["ivory"] = "fffff0",
        ["khaki"] = "f0e68c",
        ["lavender"] = "e6e6fa",
        ["lavenderblush"] = "fff0f5",
        ["lawngreen"] = "7cfc00",
        ["lemonchiffon"] = "fffacd",
        ["lightblue"] = "add8e6",
        ["lightcoral"] = "f08080",
        ["lightcyan"] = "e0ffff",
        ["lightgoldenrodyellow"] = "fafad2",
        ["lightgrey"] = "d3d3d3",
        ["lightgreen"] = "90ee90",
        ["lightpink"] = "ffb6c1",
        ["lightsalmon"] = "ffa07a",
        ["lightseagreen"] = "20b2aa",
        ["lightskyblue"] = "87cefa",
        ["lightslateblue"] = "8470ff",
        ["lightslategray"] = "778899",
        ["lightsteelblue"] = "b0c4de",
        ["lightyellow"] = "ffffe0",
        ["lime"] = "00ff00",
        ["limegreen"] = "32cd32",
        ["linen"] = "faf0e6",
        ["magenta"] = "ff00ff",
        ["maroon"] = "800000",
        ["mediumaquamarine"] = "66cdaa",
        ["mediumblue"] = "0000cd",
        ["mediumorchid"] = "ba55d3",
        ["mediumpurple"] = "9370d8",
        ["mediumseagreen"] = "3cb371",
        ["mediumslateblue"] = "7b68ee",
        ["mediumspringgreen"] = "00fa9a",
        ["mediumturquoise"] = "48d1cc",
        ["mediumvioletred"] = "c71585",
        ["midnightblue"] = "191970",
        ["mintcream"] = "f5fffa",
        ["mistyrose"] = "ffe4e1",
        ["moccasin"] = "ffe4b5",
        ["navajowhite"] = "ffdead",
        ["navy"] = "000080",
        ["oldlace"] = "fdf5e6",
        ["olive"] = "808000",
        ["olivedrab"] = "6b8e23",
        ["orange"] = "ffa500",
        ["orangered"] = "ff4500",
        ["orchid"] = "da70d6",
        ["palegoldenrod"] = "eee8aa",
        ["palegreen"] = "98fb98",
        ["paleturquoise"] = "afeeee",
        ["palevioletred"] = "d87093",
        ["papayawhip"] = "ffefd5",
        ["peachpuff"] = "ffdab9",
        ["peru"] = "cd853f",
        ["pink"] = "ffc0cb",
        ["plum"] = "dda0dd",
        ["powderblue"] = "b0e0e6",
        ["purple"] = "800080",
        ["red"] = "ff0000",
        ["rosybrown"] = "bc8f8f",
        ["royalblue"] = "4169e1",
        ["saddlebrown"] = "8b4513",
        ["salmon"] = "fa8072",
        ["sandybrown"] = "f4a460",
        ["seagreen"] = "2e8b57",
        ["seashell"] = "fff5ee",
        ["sienna"] = "a0522d",
        ["silver"] = "c0c0c0",
        ["skyblue"] = "87ceeb",
        ["slateblue"] = "6a5acd",
        ["slategray"] = "708090",
        ["snow"] = "fffafa",
        ["springgreen"] = "00ff7f",
        ["steelblue"] = "4682b4",
        ["tan"] = "d2b48c",
        ["teal"] = "008080",
        ["thistle"] = "d8bfd8",
        ["tomato"] = "ff6347",
        ["turquoise"] = "40e0d0",
        ["violet"] = "ee82ee",
        ["violetred"] = "d02090",
        ["wheat"] = "f5deb3",
        ["white"] = "ffffff",
        ["whitesmoke"] = "f5f5f5",
        ["yellow"] = "ffff00",
        ["yellowgreen"] = "9acd32"
    }
 
    colour_found = colour_map[colourName:lower()]
    if colour_found ~= nil then
        background = '#' .. colour_found
     end
     end
 
     return count
     return foreground, background
end
end


return p
return p
Please note that all contributions to Eco - English Wiki are considered to be released under the CC BY-NC-SA 4.0 (see Eco:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

To protect the wiki against automated edit spam, we kindly ask you to solve the following hCaptcha:

Cancel Editing help (opens in new window)

Template used on this page: