Dead by Daylight Wiki
Esplora
Pagina principale
Tutte le pagine
Mappe interattive
Navigation
Pagina principale
Portale comunità
Ultime modifiche
Una pagina a caso
Bacheca amministr.
Regole Wiki
Guida allo Stile
Community
Forum Ufficiale del Gioco
Supporto Tecnico
Segnalazione Bug
Discord Ufficiale del Gioco
Discord Ufficiale della Wiki
Gamepedia
Supporto Gamepedia
Segnala pub. inap.
Wiki di aiuto (inglese)
Contattaci
FANDOM
Giochi
Film
TV
Wiki
Esplora le wiki
Wiki della Community
Crea una wiki
Non hai un account?
Iscriviti
Accedi
FANDOM
Explore
Current Wiki
Crea una wiki
Non hai un account?
Iscriviti
Accedi
Accedi
Iscriviti
Dead by Daylight Wiki
1 952
pagine
Esplora
Pagina principale
Tutte le pagine
Mappe interattive
Navigation
Pagina principale
Portale comunità
Ultime modifiche
Una pagina a caso
Bacheca amministr.
Regole Wiki
Guida allo Stile
Community
Forum Ufficiale del Gioco
Supporto Tecnico
Segnalazione Bug
Discord Ufficiale del Gioco
Discord Ufficiale della Wiki
Gamepedia
Supporto Gamepedia
Segnala pub. inap.
Wiki di aiuto (inglese)
Contattaci
Modifica di
Modulo:Utils
Ritorna alla pagina
Modifica sorgente
Cronologia
Discussione (0)
Modifica pagina
Modulo:Utils
Attenzione:
non hai effettuato l'accesso. Se effettuerai delle modifiche il tuo indirizzo IP sarà visibile pubblicamente. Se
accedi
o
crei un'utenza
, le tue modifiche saranno attribuite al tuo nome utente, insieme ad altri benefici.
Controllo anti-spam.
NON
riempirlo!
local p = {} local mathOps = require("Module:MathOps") local str = require("Module:Strings") local frame = mw.getCurrentFrame() local _brigtnessTreshold = 0.36 local _isValidFileNameCounter = 0 local _colorOrder = {2, 6, 8, 4, 3, 10, 11, 12, 14, 15, 21, 22, 25, 26, 9, 27, 28, 29, 13, 31, 32} local strings = { --genders, not currently used male = "Maschile", female = "Femminile", transmale = "Maschio Trans", transfemale = "Femmina Trans", nonhuman = "Non applicabile (non umano)", undefined = "Non definito", --charNotFound = "Character not found!", patch = "Patch", tabberHeaderNotFound = "Intestazione non trovata", category = "Categoria", --used for [[Category:...]] boxTypeNotFound = b("La casella dinamica è priva di tipo!"), notSpecified = "notSpecified", --used in IconLink for assemble machine function clrTestString = "Una stringa estremamente lunga che serve come stringa di prova per il testo colorato automatico e ordinato che mette in risalto i valori importanti sul nostro bellissimo wiki di Dead by Daylight. Per questo test consideriamo solo parole di 3 o più caratteri.", notEnoughColors = "nessun altro colore in ordine", } p.strings = strings local months = { January = "Gennaio", February = "Febbraio", March = "Marzo", April = "Aprile", May = "Maggio", June = "Giugno", July = "Luglio", August = "Agosto", September = "Settembre", October = "Ottobre", November = "Novembre", December = "Dicembre" } local days = { Monday = "Lunedì", Tuesday = "Martedì", Wednesday = "Mercoledì", Thursday = "Giovedì", Friday = "Venerdì", Saturday = "Sabato", Sunday = "Domenica" } ---------------------------------------------- p.timeFormat1 = "%d.%m.%Y" -- 5.9.2022 p.timeContants = { second = 1, minute = 60, --in seconds hour = 3600, day = 86400, week = 604800 } local timeContants = p.timeContants --Bridge to Language Module, as more appropriate place to have this function function p.lang() return require("Module:Languages").lang() end --If params will be passed {...} then index should equals 0, so this list will be passeb back: ((index == 0 and params.args) or params) function p.resolveParameter(param, index, returnCanBeNil) local retArg if type(param) == "table" then retArg = ((index == 0 and param.args) or (param.args and param.args[(index or 1)] and p.replaceSpecialCharacters(param.args[(index or 1)]))) or nil end --if parameter is passed from wiki, not other function if retArg == nil and type(param) == "table" and param.args ~= nil and next(param.args) == nil and not returnCanBeNil then retArg = getParamOrPageName() end --param.args ~= nil and next(param.args): this means that params.args is not nil but empty table if retArg == nil and not returnCanBeNil then retArg = getParamOrPageName(param) end --if parameter was passed directly or not at all if retArg ~= nil and type(param) == "string" then retArg = p.replaceSpecialCharacters(retArg) end --final processing return retArg end function getParamOrPageName(param) if param and (type(param) ~= types.table or (type(param) == types.table and not param.args)) then return param else local pageName = pageName or mw.title.getCurrentTitle().text local pageParts = string.split(pageName, '/') -- remove page suffixes such as language codes if #pageParts > 1 then _unofficialLang = pageParts[#pageParts] return pageParts[#pageParts - 1] --take second to last part of page name end return pageParts[1] --if there is no other part than the name itself end end --translates string containing #1# #2# ... to individual strings (resp. words) contained in dyntable function p.getDynamicString(dynTable, templateString) --dynTable = {"Testing Chapter", nil, "DLC Str World", nil, 999}; --templateString = "Retracted #1# #2# #3# #4# #5# #6# #7# #8#" local skipList = {skip = {}, spans = {}} local spanRegex = "(<span .-</span>)" --mostly clr case local spanSkipRegex = "&&span" --it needs to use a DIFFERENT symbol than hashtag (#) as the style of spans can contain one due to colorhex colour value local skipRegex = "#(.-)#" --skip anything inside hashtags if type(dynTable) == types.string then --is parameter is string then just split it dynTable = string.split(dynTable) elseif type(dynTable) == types.table then local tmp = {} local skipCounter = 1 local spanCounter = 1 for i, el in pairs(dynTable) do if el:find(spanRegex) then --if you find any spans to skip then ... for m in el:gmatch(spanRegex) do --let's find spans (and pull them out) to skip them with splitting by "space" table.insert(skipList.spans, m) el = el:gsub(m, spanSkipRegex .. spanCounter) spanCounter = spanCounter + 1 end end --finding any strings DOES NOT need to be first as span regex WILL NOT create elements matching this regex if el:find(skipRegex) then --if you find any string to skip then ... for m in el:gmatch(skipRegex) do table.insert(skipList.skip, m) el = el:gsub(skip(m:gsub('%W','%%%1')), "#skip" .. skipCounter) --We have to escape special characters as the string is being used as a pattern and for an instance "[[ ]]" are magic chars for LUA patterns skipCounter = skipCounter + 1 end end table.insert(tmp, string.split(tostring(el))) --if parameter is table, split all strings inside end dynTable = table.flatten(tmp) --format from table.insert is {{"splitted", "string"}, {"splitted", "another", "string"}}, so it's needed to be flattened --mw.log(mw.dumpObject(dynTable)) end if templateString then for m in templateString:gmatch("#(%d+)#") do --replace all #1# occurences local currentRegexString = "#" .. tonumber(m) .. "#" if tonumber(m) <= #dynTable then templateString = templateString:gsub(currentRegexString, dynTable[tonumber(m)]) else templateString = templateString:gsub(currentRegexString, cstr.empty) --remove all remaining marks end end else templateString = table.join(dynTable, space) end templateString = string.trim(templateString) --lg(templateString) for m in templateString:gmatch("#skip(%d)") do --now we put spans back into string local currentRegexString = "#skip" .. tonumber(m) templateString = templateString:gsub(currentRegexString, skipList.skip[tonumber(m)]) end for m in templateString:gmatch(spanSkipRegex .. "(%d)") do --now we put spans back into string local currentRegexString = spanSkipRegex .. tonumber(m) templateString = templateString:gsub(currentRegexString, skipList.spans[tonumber(m)]) end --mw.log(templateString) return templateString end -------------------------------------------------------------------------------- function p.getCount(subject) local list subject = p.resolveParameter(subject) --if you have another list just add it into a list then call appropriate function if subject == "map" then return p.getMapsCount() elseif subject == "realm" then list = realms elseif subject == "killer" then list = killers elseif subject == "survivor" then list = survivors elseif subject == "dlc" then list = dlcs elseif subject == "chapter" then return p.getCountDlcType(1) elseif subject == "paragraph" then return p.getCountDlcType(2) elseif subject == "clothing" then return p.getCountDlcType(3) elseif subject == "ost" then return p.getCountDlcType(4) elseif subject == "character" then return p.getCountDlcType(5) elseif subject == "ccy" then return getCountCCY(true) elseif subject == "ccy-gc" then return getCountCCY(true) --redundant option to keep convention elseif subject == "ccy-rc" then return getCountCCY(false) elseif subject == "killerPerk" then return getPerksCount('K') elseif subject == "survPerk" then return getPerksCount('S') else return 0 end local x = 0 for _, item in ipairs(list) do if item.skip or item.retired then x = x + 1 end end return #list - x end function p.getMapsCount() local data = require("Module:Datatable") local result = 0 for _, map in ipairs(data.maps) do if not (map.skip or map.retired) then if map.variations then for _, var in ipairs(map.variations) do if not (map.skip or map.retired) then result = result + 1 end end else result = result + 1 end end end return result end function p.getCountDlcType(type) local count = 0 for _, dlc in ipairs(dlcs) do if dlc.category == type and not dlc.skip then count = count + 1 end end return count end function getPerksCount(charType) local perks = mw.loadData("Module:Datatable/Perks" .. p.lang()).perks local count = 0 for _, perk in ipairs(perks) do if perk.charType == charType and not perk.unused then count = count + 1 end end return count end function getCountCCY(gc) local list = ccy local i = 0 while list[i + 1] and list[i + 1].gc == gc do i = i + 1 end return i end function isRealCcy(ccyId) local data = require("Module:Datatable" .. p.lang()) for _, currency in ipairs(data.ccy) do if currency.id == ccyId then return not currency.gc end end return false end function p.getCcyById(id) for _, currCcy in ipairs(ccy) do if currCcy.id == id then return currCcy end end return nil end function p.getMaxId(tab) result = 0 for _, item in ipairs(tab) do result = (item.id > result and item.id) or result end return result end -- Function allowing for consistent treatment of boolean-like wikitext input. -- It works similarly to the template {{yesno}}. function p.bool(val, default) -- If your wiki uses non-ascii characters for any of "yes", "no", etc., you -- should replace "val:lower()" with "mw.ustring.lower(val)" in the -- following line. val = type(val) == 'string' and val:lower() or val if val == nil then return nil elseif val == true or val == 'yes' or val == 'y' or val == 'true' or val == 't' or val == 'on' or tonumber(val) == 1 then return true elseif val == false or val == 'no' or val == 'n' or val == 'false' or val == 'f' or val == 'off' or tonumber(val) == 0 then return false else return default end end --Example usage: --amount = 1333444.1 --print(format_num(amount,2)) --print(format_num(amount,-2,"US$")) --amount = -22333444.5634 --print(format_num(amount,2,"$")) --print(format_num(amount,2,"$","()")) --print(format_num(amount,3,"$","NEG ")) --Output: --1,333,444.10 --US$1,333,400 ---$22,333,444.56 --($22,333,444.56) --NEG $22,333,444.563 function p.formatNum(amount, decimal, prefix, neg_prefix) return p.format_num(amount, decimal, prefix, neg_prefix) end function p.format_num(amount, decimal, prefix, neg_prefix) local str_amount, formatted, famount, remain decimal = decimal or 2 -- default 2 decimal places neg_prefix = neg_prefix or "-" -- default negative sign famount = math.abs(mathOps.round(amount,decimal)) famount = math.floor(famount) remain = mathOps.round(math.abs(amount) - famount, decimal) -- comma to separate the thousands formatted = p.commaFormat(famount) -- attach the decimal portion if (decimal > 0) then remain = string.sub(tostring(remain),3) formatted = formatted .. "." .. remain .. string.rep("0", decimal - string.len(remain)) end -- attach prefix string e.g '$' formatted = (prefix or "") .. formatted -- if value is negative then format accordingly if (amount<0) then if (neg_prefix=="()") then formatted = "("..formatted ..")" else formatted = neg_prefix .. formatted end end return formatted end function p.commaFormat(amount) local formatted = amount while true do formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2') if (k==0) then break end end return formatted end --Converting Arabic numbers to Roman function p.toRomanNumerals(s) local numbers = { 1, 5, 10, 50, 100, 500, 1000 } local chars = { "I", "V", "X", "L", "C", "D", "M" } s = tonumber(s) if not s or s ~= s then return false end if s == math.huge then return false end s = math.floor(s) if s <= 0 then return s end local ret = cstr.empty for i = #numbers, 1, -1 do local num = numbers[i] while s - num >= 0 and s > 0 do ret = ret .. chars[i] s = s - num end for j = 1, i - 1 do local n2 = numbers[j] if s - (num - n2) >= 0 and s < num and s > 0 and num - n2 ~= n2 then ret = ret .. chars[j] .. chars[i] s = s - (num - n2) break end end end return ret end --Converting Roman numbers to Arabic function ToNumeral(roman) local Num = { ["M"] = 1000, ["D"] = 500, ["C"] = 100, ["L"] = 50, ["X"] = 10, ["V"] = 5, ["I"] = 1 } local numeral = 0 local i = 1 local strlen = string.len(roman) while i < strlen do local z1, z2 = Num[ string.sub(roman,i,i) ], Num[ string.sub(roman,i+1,i+1) ] if z1 < z2 then numeral = numeral + ( z2 - z1 ) i = i + 2 else numeral = numeral + z1 i = i + 1 end end if i <= strlen then numeral = numeral + Num[ string.sub(roman,i,i) ] end return numeral end function resolveNameWithRomanNumbers(str) local index = string.find(str, " [^ ]*$") + 1 local romanNumber = (string.sub(str, index)) local result if string.match(romanNumber, "[MDCLXVI]+$") then --finding ONLY Roman letters in last "word" result = str else result = str end return result end function p.capitalizeName(str) return p.CapitalizeName(str) end function p.CapitalizeName(str) --deprecated name --mw.log(string.gsub(" "..str, "[%s%-]%a", string.upper):sub(2)) --return string.gsub(" "..str, "[%s%-]%a", string.upper):sub(2) --original version return string.gsub(" "..str:lower(), "[%s%-]%a", string.upper):sub(2) end function p.firstLetterLower(str) return p.FirstLetterLower(str) end function p.FirstLetterLower(str) --deprecated name return str:sub(1, 1):lower() .. str:sub(2) end function p.firstLetterUpper(str) return p.FirstLetterUpper(str) end function p.FirstLetterUpper(str) --deprecated name return str:sub(1,1):upper() .. str:sub(2) end --[[function p.fixDiacritics(str) local letterSequences = { ["195"] = {fix = "â", sequence = {"162"}} } local fixedSeqsOffset = 0 local currentLen = #str + fixedSeqsOffset local i = 1 while i <= currentLen do local ascii = tostring(string.byte(str:sub(i,i)) or 0) for startSequence, seqData in pairs(letterSequences) do if ascii == startSequence then local foundSequence = true for j, seqCode in ipairs(seqData.sequence) do local seqAscii = tostring(string.byte(str:sub(i+j,i+j))) if seqAscii ~= seqCode then foundSequence = false break end end if foundSequence then fixedSeqsOffset = i - (i + #seqData.sequence) currentLen = #str + fixedSeqsOffset -- #seqData.sequence + 1 = number of ascii codes that needs to be replaced, the sequence list + the initial ascii code, i.e. the key value from letterSequences str = str:sub(1, i - 1) .. seqData.fix .. str:sub(i + #seqData.sequence + 1) end end end i = i + 1 end return str end]] function p.RemoveSpecialCharacters(str, full, replaceDiacritics) str = string.gsub(str, "'", "") str = string.gsub(str, "®", "") str = string.gsub(str, "™", "") str = string.gsub(str, ":", "") str = string.gsub(str, "!", "") --perks str = string.gsub(str, "?", "") --achievements str = string.gsub(str, "/", "") --achievements str = string.gsub(str, "%&", "And") --probably can be changed to lower: "and" if replaceDiacritics then str = p.replaceDiacritics(str, full) end return str end function p.replaceDiacritics(str, full) --Diacritics specialLettersLight = { ["A"] = {"À", "Á", "Â", "Ã", "Ä"}, ["a"] = {"à", "á", "â", "ã", "ä"}, ["e"] = {"è", "é", "ê", "ë", "ě"}, ["O"] = {"Ò", "Ó", "Ô", "Õ", "Ö"}, ["o"] = {"ò", "ó", "ô", "õ", "ö"} } specialLetters = { ["A"] = {"À", "Á", "Â", "Ã", "Ä"}, ["a"] = {"à", "á", "â", "ã", "ä"}, ["E"] = {"È", "É", "Ê", "Ë", "Ě"}, ["e"] = {"è", "é", "ê", "ë", "ě"}, ["I"] = {"Ì", "Í", "Î", "Ñ", "Ï"}, ["i"] = {"ì", "í", "î", "ñ", "ï"}, ["O"] = {"Ò", "Ó", "Ô", "Õ", "Ö"}, ["o"] = {"ò", "ó", "ô", "õ", "ö"}, ["U"] = {"Ù", "Ú", "Û", "Ů", "Ü"}, ["u"] = {"ù", "ú", "û", "ů", "ü"}, ["Y"] = { "Ý", "Ÿ"}, ["y"] = { "ý", "ÿ"} } --Originally it was grouped by set [ÀÁ], however there is some sort of bug there that makes it not working --str = string.gsub(str, "[ÁÂ]", "A") --if debugRun then mw.log(mw.dumpObject(specialLetters)) end for letter, row in pairs(((full and specialLetters) or specialLettersLight)) do for _, special in ipairs(row) do str = string.replace(str, special, letter) end end return str end function p.replaceSpecialCharacters(name) local charList = { ["'"] = ''', ["&"] = '&' } if name == nil then error("Name parameter is empty, but it shouldnt?") end for repl, sChar in pairs(charList) do name = string.gsub(tostring(name), sChar, repl) end return name end function p.pageExists(name) return (not name == cstr.empty) or mw.title.new(name).exists end function p.isValidFileName(name, extension) extension = extension or "png" name = p.RemoveSpecialCharacters(name) _isValidFileNameCounter = _isValidFileNameCounter + 1 mw.log("Counter:" .. tostring(_isValidFileNameCounter) .. ' - ' .. cstr.media .. name .. dot .. extension) return not (name == cstr.empty or not mw.title.new(cstr.media .. name .. dot .. extension).exists) end function p.resolveFileName(str, keepSpaces, removeDiacritics) keepSpaces = keepSpaces or false local result = "" result = string.lower(str) --mw.log(result) result = p.RemoveSpecialCharacters(result, keepSpaces, removeDiacritics) --mw.log(result) result = p.capitalizeName(result) if not keepSpaces then result = string.gsub(result, "[ ]", "") end --In future if there will be needed replace charactere such as "é" just add another substitution --mw.log(result) return result end function p.resolveImageName(name) if mw.title.new(cstr.media .. name .. dot .. cstr.png).exists then return name .. dot .. cstr.png end if mw.title.new(cstr.media .. name .. dot .. cstr.jpg).exists then return name .. dot .. cstr.jpg end if mw.title.new(cstr.media .. name .. dot .. cstr.gif).exists then return name .. dot .. cstr.gif end return name .. dot .. cstr.png end function p.GetDisplayName(item) return (item.tName or item.name) end function p.IconLink(icon, pageLink, displayText, background) local result = cstr.empty background = background or p.resolveParameter(icon, "bg", true) or p.resolveParameter(icon, 4, true) background = p.bool(background == nil or background) displayText = displayText or p.resolveParameter(icon, 3, true) pageLink = pageLink or p.resolveParameter(icon, 2, true) local linkless = p.resolveParameter(icon, "linkless", true) or pageLink == "linkless" --linkless as a second parameter should be deprecated icon = p.resolveParameter(icon) local iconObject, pluralType = p.getIconObject(icon) if pluralType then --if automatic plural is detected, then links should redirect to singular form pageLink = pageLink or iconObject.name displayText = icon --since automatic plurals don't imitate 3-parameters scenario we have to set the display text to be same as the first parameter (icon) end local iconFile = iconObject.iconFile local filename = cstr.file .. iconFile .. tl .. "link=" .. (pageLink or icon) local text = (displayText and pageLink and pageLink .. tl .. displayText) or pageLink or icon --cstr.empty --local boxDesc = cstr.empty if pageLink == "img" then text = cstr.empty filename = cstr.file .. iconFile .. tl .. "link=" .. icon end if not linkless and text ~= cstr.empty then text = link(text) --boxDesc = getBoxDescription(pageLink or icon) //hover box, currently disabled elseif linkless or pageLink == "linkless" then text = (displayText or icon) end local imageFile if background and iconObject.assembly then local loLogic = require("Module:Loadout" .. p.lang()) --this needs to (should) be done sophisticated way local imgType = (iconObject.iconFile:lower():find("addon") and "addon") or (iconObject.iconFile:lower():find("items") and "item") or (iconObject.iconFile:lower():find("favors") and "offering") or (iconObject.iconFile:lower():find("powers") and "power") or (iconObject.iconFile:lower():find("perks") and "perk") or strings.notSpecified --if iconObject.iconFile:lower():find("favors") then imgType = "offering" end local loObj = (loLogic["get" .. p.capitalizeName(imgType) .. "ByName"] and loLogic["get" .. p.capitalizeName(imgType) .. "ByName"](icon)) or nil imageFile = p.assembleImage(imgType, icon, 32, {rarity = (loObj and loObj.rarity) or 1, iconLink = true}) else imageFile = link(filename, "64px") --iconObject.ilRes or "32px") end local tooltipText = link(filename, "96px", "link=") --result = '<span class = "wrap-span pcView" style = "display:none;"><span class="box-span">' .. boxDesc .. '</span>' .. text .. file .. '</span>' local padding = p.getPaddingsFromIcon(iconObject) result = text .. '<span class = "iconLink" style = "vertical-align: middle; padding: ' .. padding.top .. space .. padding.right .. space .. padding.bottom .. space .. padding.left .. '">' .. '<span style = "display:none; width:' .. (iconObject.ilRes or "32px") .. semi .. 'max-height: ' .. (iconObject.ilRes or "32px") .. '" class = "pcView pcIconLink">' .. p.tooltip(imageFile, tooltipText, true, true, true) .. '</span>' .. '<span class = "mobileView mobileIconLink">' .. link(filename, iconObject.ilRes or "32px") .. '</span>' .. '</span>' --mw.log(result) return result --return frame:expandTemplate{title = "IconLink", args = {icon, pageLink, displayText} } end function p.loadoutIconLink(icon, pageLink, displayText, params) displayText = displayText or p.resolveParameter(icon, "displayText", true) or p.resolveParameter(icon, 3, true) pageLink = pageLink or p.resolveParameter(icon, "link", true) or p.resolveParameter(icon, 2, true) icon = p.resolveParameter(icon, "icon", true) or p.resolveParameter(icon, 1, true) or icon local info = { displayText = displayText or pageLink or icon, link = pageLink or icon, icon = icon } local iconObject, pluralType = p.getIconObject(info.icon) local filename = cstr.file .. iconObject.iconFile .. tl .. "link=" .. (info.link or info.icon) local tooltipText = link(filename, "96px", "link=") --default tooltip if iconObject.iconFile:lower():find("perk") then local loLogic = require("Module:Loadout" .. p.lang()) tooltipText = loLogic.getPerkPageTable(params.perk) or "WIP/Error:" .. params.perk.name end local imageFile = link(filename, "64px") local padding = p.getPaddingsFromIcon(iconObject) local result = link(info.displayText, info.link) .. '<span class = "iconLink" style = "vertical-align: middle; padding: ' .. padding.top .. space .. padding.right .. space .. padding.bottom .. space .. padding.left .. '">' .. '<span style = "display:none; width:' .. (iconObject.ilRes or "32px") .. semi .. 'max-height: ' .. (iconObject.ilRes or "32px") .. '" class = "pcView pcIconLink">' .. p.tooltip(imageFile, tooltipText, true, true, true) .. '</span>' .. --'<span class = "mobileView mobileIconLink">' .. link(filename, iconObject.ilRes or "32px") .. '</span>' .. '</span>' return result end function p.getPaddingsFromIcon(icon) return { top = icon.paddingTop or 0, right = icon.paddingRight or 0, bottom = icon.paddingBottom or 0, left = icon.paddingLeft or 0 } end function getBoxDescription(icon) --curently disabled local ic = p.getIconObject(icon) local result = cstr.empty if ic.category == "Perks" then result = '<h3>' .. icon .. '</h3><hr>'-- .. prkz.getPerkDescriptionByName(perk.name) end return result end function p.resolveTextColorByBackground(hexBgColor) if(type(hexBgColor) == "table") then hexBgColor = hexBgColor.args[1] end local red = tonumber(string.sub(hexBgColor, 1, 2), 16) local green = tonumber(string.sub(hexBgColor, 3, 4), 16) local blue = tonumber(string.sub(hexBgColor, 3, 4), 16) local darkness = (0.299 * red + 0.587 * green + 0.114 * blue) / 255 --mw.log("Red: " .. red .." \t\tor\t Blue: " .. blue .. " | Green: " .. green) --mw.log(darkness) if(darkness < _brigtnessTreshold) then return "white" else return "black" end end function p.getPageTitle() return mw.title.getCurrentTitle().text end --------------------------------------------------------------------------------- function p.getSumOfSizes(row) local result = 0 local i = 1 while row[i] do result = result + row[i][1] -- hardcoded first variable in table i = i + 1 end return result end --[[ function compSize(row1, row2) local sum1 = row1.size local sum2 = row2.size if(type(sum1) == "table") then sum1 = p.getSumOfSizes(sum1) --converting back from table to number end if(type(sum2) == "table") then sum2 = p.getSumOfSizes(sum2) end if sum1 > sum2 then return true elseif sum1 < sum2 then return false else if row1.realm < row2.realm then return true elseif row1.realm > row2.realm then return false else return resolveNameWithRomanNumbers(row1.name) < resolveNameWithRomanNumbers(row2.name) end end end ]] function compName(row1, row2) if row1.diacritics then if row2.diacritics then return p.RemoveSpecialCharacters(row1.name, true, true) < p.RemoveSpecialCharacters(row2.name, true, true) else return p.RemoveSpecialCharacters(row1.name, true, true) < row2.name end elseif row2.diacritics then return row1.name < p.RemoveSpecialCharacters(row2.name, true, true) end return row1.name < row2.name end function compFilename(row1, row2) return row1.filename < row2.filename end function compInt(row1, row2) -- 1, 2, 3 return row1 < row2 end function compIntReversed(row1, row2) -- 3, 2, 1 return row1 > row2 end function compIntDesc(row1, row2) -- 3, 2, 1 return row1 > row2 end function compLevel(row1, row2) return row1.level < row2.level end function compDlcCategory(row1, row2) if row1.category == row2.category then return row1.id < row2.id end return row1.category < row2.category end function compId(row1, row2) return row1.id < row2.id end function compRealCcyFirst(row1, row2) ccy1 = isRealCcy(row1.ccy) ccy2 = isRealCcy(row2.ccy) if (ccy1 and ccy2) or (not ccy1 and not ccy2) then --TRUE and TRUE or FALSE and FALSE return row1.ccy < row2.ccy elseif ccy1 and not ccy2 then --TRUE and FALSE return true else return false end end function compCharsKillersFirst(row1, row2) char1 = row1.power ~= nil char2 = row2.power ~= nil if (char1 and char2) or (not char1 and not char2) then --TRUE and TRUE or FALSE and FALSE return row1.id < row2.id elseif char1 and not char2 then --TRUE and FALSE return true else return false end end function rarityAndName(row1, row2) if row1.rarity and row2.rarity and row1.rarity < row2.rarity then return true elseif row1.rarity and row2.rarity and row1.rarity > row2.rarity then return false elseif row1.pieces and row2.pieces then local row1Name = cstr.empty local row2Name = cstr.empty for _, piece in pairs(row1.pieces) do row1Name = piece.name break end for _, piece in pairs(row2.pieces) do row2Name = piece.name break end return row1Name < row2Name else return compName(row1, row2) end end function p.sortByKeys(tableList) --only int, TODO check key type via pairs() fc local result = {} local orderedKeys = table.keys(tableList) p.sortTable(orderedKeys, true) for _, key in pairs(orderedKeys) do result[key] = tableList[key] end return result end function p.sortByRDate(tableList, reversed) table.sort(tableList, function (row1, row2) if p.toTimestamp(row1.rDate) < p.toTimestamp(row2.rDate) then if reversed then return false else return true end end end ) return tableList end function p.sortMapsBySize() --deprecated? local m = require("Module:Datatable" .. p.lang()) --mw.log(mw.dumpObject(maps)) table.sort(maps,compSize) --mw.log(mw.dumpObject(maps)) end function p.sortItemsByName(tableList) table.sort(tableList, compName) end function p.sortItemsBycompFilename(tableList) --used for charms (as perk object is not retrieved, only cosData record) table.sort(tableList, compFilename) end function p.sortTable(tableList, reversed) if reversed then table.sort(tableList, compIntReversed) else table.sort(tableList, compInt) end end function p.sortTableDesc(tableList) table.sort(tableList, compIntDesc) end function p.sortDlcByCategory(tableList) table.sort(tableList, compDlcCategory) end function p.sortPerksByLevel(tableList) table.sort(tableList, compLevel) end function p.sortTableById(tableList) table.sort(tableList, compId) end function p.sortRealCcyFirst(tableList) table.sort(tableList, compRealCcyFirst) end function p.sortCharsKillersFirst(tableList) table.sort(tableList, compCharsKillersFirst) end function p.sortCosmeticsByRarityAndName(tableList) table.sort(tableList, rarityAndName) end --------------------------------------------------------------------------------- -- Time functions -- function p.today() return os.time(os.date("!*t")) end function p.getYear(stamp) return p.getTimeAspect(stamp, "year") end function p.getMonth(stamp) return p.getTimeAspect(stamp, "month") end function p.getDay(stamp) return p.getTimeAspect(stamp, "day") end function p.getHour(stamp) return p.getTimeAspect(stamp, "hour") end function p.getMinute(stamp) return p.getTimeAspect(stamp, "minute") end function p.getSecond(stamp) return p.getTimeAspect(stamp, "second") end function p.getWeekday(stamp) return p.getTimeAspect(stamp, "weekday") end function p.getTimeAspect(stamp, aspect) --aspect being selected time portion if type(stamp) ~= 'number' then stamp = p.toTimestamp(stamp) end local tag = '%c' if aspect == "year" then tag = '%Y' elseif aspect == "month" then tag = '%m' elseif aspect == "day" then tag = '%d' elseif aspect == "hour" then tag = '%H' elseif aspect == "minute" then tag = '%M' elseif aspect == "second" then tag = '%S' elseif aspect == "weekday" then tag = '%w' end local result = os.date(tag, stamp) return (aspect == "weekday" and tonumber(result)) or result end function p.addTime(portion, amount, stamp) stamp = stamp or 0 if type(stamp) ~= 'number' then stamp = p.toTimestamp(stamp) end local multiplier = timeContants[portion] stamp = stamp + (amount * multiplier) return stamp end function p.getTimeDiff(timestamp1, timestamp2) --First parameter is first in timeline, Second Parameter is later one return os.difftime(timestamp2, timestamp1) end function p.getTimeDiffFormatting(seconds, unit) return seconds / timeContants[unit] end function p.toTimestamp(datestamp) if type(datestamp) == 'string' then datestamp = p.GetDatetime(datestamp) end return os.time(datestamp) --if datestamp = nil, os.time() returns current datetime stamp end function p.toDate(timestamp, timeFormat) return os.date(timeFormat or '%d %B %Y', timestamp) --21 October 2021 end function p.resolveDateTime(datetime, skipDay) --with weekday local matchYear = "^(..)%.(..)%.(%d%d%d%d)$" local matchMonth = "^(..)%.(%d%d)%.(....)$" local matchDay = "^(%d%d)%.(..)%.(....)$" local year, month, day, dayName = false local rDate = os.time(p.GetDatetime(datetime)) if string.find(datetime, matchYear) then year = os.date("%Y", rDate) end if string.find(datetime, matchMonth) then month = os.date("%B", rDate) end if string.find(datetime, matchDay) then day = os.date("%d", rDate) dayName = os.date("%A", rDate) end --(day and month) is to avoid showing a day as the function sets the month to January (first month) by default, if the month is not provided --day part: ((day and month and day .. space) or cstr.empty) --month part: ((month and months[month] .. space) or cstr.empty) --year part: year --dayName part: ((day and month and not skipDay and space .. brackets(days[dayName])) or cstr.empty) return ((day and month and day .. space) or cstr.empty) .. ((month and months[month] .. space) or cstr.empty) .. year .. ((day and month and not skipDay and space .. brackets(days[dayName])) or cstr.empty) end function p.isFullDateTime(datestamp) return p.IsFullDateTime(datestamp) end function p.IsFullDateTime(datestamp) local day, month, year = datestamp:match("^(..)%.(..)%.(....)$") if month == "##" or day == "##" or year == "####" then return false end return true end --convertToTimeVersion = normally, return table counts as 1.1.1970 (with day = 1, month = 1 and year = 1970). --But if we want to have time stamp (like remaining time) these default values add 1 day, 1 month and 1970 years to the countdown table (Time stamp version table) function p.GetDatetime(datestamp, convertToTimeVersion) local result = {} if type(datestamp) == types.string then local day, month, year, hour, min, sec = datestamp:match("^(..)%.(..)%.(%d%d%d%d) ?(%d?%d?):?(%d?%d?):?(%d?%d?)$") if month == "##" then month = 1 result.fakeMonth = true end if day == "##" then day = 1 result.fakeDay = true end result.year = tonumber(year) result.month = tonumber(month) result.day = tonumber(day) result.hour = tonumber((hour ~= cstr.empty and hour) or 0) result.min = tonumber((min ~= cstr.empty and min) or 0) result.sec = tonumber((sec ~= cstr.empty and sec) or 0) result.timestamp = p.toTimestamp(result) local tempDateObj = os.date("!*t", os.time(result)) result.yday = tempDateObj.yday --year day included result.wday = p.correctWeekday(tempDateObj).wday --weekDay included result.week = p.getWeekNumber(result.timestamp) result.quarter = math.ceil(result.month / 3) result.dst = tempDateObj.isdst elseif type(datestamp) == types.number then result = os.date("!*t", datestamp) if(convertToTimeVersion) then result.day = result.day - 1 --we have to subtract it, not set it, as the datetime stamp can reach to days and months result.month = result.month - 1 result.year = result.year - 1970 end result = p.correctWeekday(result) result.timestamp = datestamp end return result end --.wday is indexed 1 - 7, Sunday being 1 => https://www.lua.org/manual/5.3/manual.html#:~:text=wday%20(weekday%2C%201%E2%80%937%2C%20Sunday%20is%C2%A01) --%w starts 0 - 6, Sunday being 0 => https://www.lua.org/pil/22.1.html#:~:text=%25w,6%20%3D%20Sunday%2DSaturday%5D --following row synchronises the convention with '%w' and shifting it to 1 - 7 starting Monday, as for the rest of Wiki function p.correctWeekday(datetable) datetable.wday = (datetable.wday == 1 and 7) or datetable.wday - 1 return datetable end --ISO: https://en.wikipedia.org/wiki/ISO_week_date --If 1 January is on a Monday, Tuesday, Wednesday or Thursday, it is in W01. If it is on a Friday, it is part of W53 of the previous year. --If it is on a Saturday, it is part of the last week of the previous year which is numbered W52 in a common year and W53 in a leap year. --If it is on a Sunday, it is part of W52 of the previous year. function p.getWeekNumber(dateStamp) --in milliseconds, os.time() firstWeekDayOfYear = tonumber(os.date("%w", os.time({year = os.date("%Y", dateStamp), month = 1, day = 1}))) firstWeekOfYear = tonumber(os.date("%W", os.time({year = os.date("%Y", dateStamp), month = 1, day = 1}))) -- ATTENTION as per description above some years have first week 01 -- because all first weeks of year that starts with Sunday, Saturday, Friday or Thursday must be shifted if firstWeekDayOfYear > 0 and firstWeekDayOfYear < 4 and firstWeekOfYear == 0 then return tonumber(os.date("%W", dateStamp)) + 1 else return tonumber(os.date("%W", dateStamp)) end end function p.getDatePart(datestamp, part) local day, month, year = datestamp:match("^(..)%.(..)%.(....)$") if year == "####" then month = false end if month == "##" then month = false end if day == "##" then day = false end if part == "day" then return day elseif part == "month" then return month elseif part == "year" then return year end end -------------------------------------------------------------------------------- function p.regularReplace(reggedString, regexTable) local result = cstr.empty for key, value in pairs(regexTable) do reggedString = reggedString:gsub(key, value) end return reggedString end function p.getIcon(icon) return p.getIconObject(icon).iconFile end function p.getIconObject(icon) icon = p.resolveParameter(icon) local icons = mw.loadData("Module:Datatable/Icons" .. p.lang()).icons --mw.loadData local pluralRegex = "^(.+)s$" local plural2Regex = "^(.+)es$" local plural3Regex = "^(.+)ies$" local plural = icon:match(pluralRegex) local plural2 = icon:match(plural2Regex) --Toolboxes => Toolbox local plural3 = icon:match(plural3Regex) --Bodies => Bod local result = getIconElement(icons, icon, true) if result then return result elseif plural and icons[plural] ~= nil then --Pallets => Pallet return getIconElement(icons, plural), 1 elseif plural2 and icons[plural2] ~= nil then --Toolboxes => Toolbox return getIconElement(icons, plural2), 2 elseif plural3 and icons[plural3 .. "y"] ~= nil then --Bodies => Body return getIconElement(icons, plural3 .. "y"), 3 else return getIconElement(icons, icon) end end function getIconElement(icons, icon, returnNil) if type(icons[icon]) == types.table then local result = table.copy(icons[icon]) result.name = icon return result elseif returnNil then return nil elseif icons[icon] == nil then return icons["Unknown QuestionMark"] or icons[1] else return getIconElement(icons, icons[icon]) end end --************************* survivors & killers ******************************-- function p.getCharacterById(id, charTable) for _, character in ipairs(charTable) do if character.id == id then return character end end end function p.getCharacter(object) local data = require("Module:Datatable" .. p.lang()) if object.killer or object.charType == 'K' then return p.getCharacterById(object.killer or object.character, data.killers) else return p.getCharacterById(object.survivor or object.character, data.survivors) end end --function returns appropriate character name that should be compatible with IL. --IL itself is not executed to have option to customise the IL call function p.resolveCharacterIconLinkName(owner) return (owner and owner.multiName and owner.realName) or (not p.isKiller(owner) and owner.shortName) or owner.name or false end function p.resolveCharacterPortraitFileName(character, maxId) local fileConst = "_charPreview_portrait" local isKiller = p.isKiller(character) local unknownChar = (isKiller and "UnknownKiller") or "UnknownSurvivor" local fileName fileName = p.getFileNameFromTableById(character.id, (isKiller and killerImages) or survivorImages, "preview") --get custom name from table if fileName == cstr.empty or not p.isValidFileName(fileName) then --K/S{ID}_charPreview_portrait fileName = p.getCharacterIdentifier(character) .. fileConst end if (maxId and (character.id >= maxId - 1 and not p.isValidFileName(fileName)) or (not maxId and not p.isValidFileName(fileName))) then --File not Found; maxId - 1 to consider last two characters, not only the last one fileName = unknownChar .. fileConst end --mw.log(fileName) return fileName end function p.getCharacterIdentifier(character) return ((p.isKiller(character) and 'K') or 'S') .. string.format("%02d", character.id) end function p.getFileNameFromTableById(id, fileTable, field) --mw.log(id) for j, sImage in ipairs(fileTable) do if sImage.id == id and sImage[field] ~= nil then return sImage[field] end end return cstr.empty end --Not currently used function p.resolveGender(abbr) if abbr == 'M' then return strings.male elseif abbr == 'F' then return strings.female elseif abbr == 'N' then return strings.nonhuman elseif abbr == 'M/F' then return strings.male .. comma .. strings.female elseif abbr == 'F/M' then return strings.female .. comma .. strings.male elseif abbr == 'TM' then return strings.transmale elseif abbr == 'TF' then return strings.transfemale else return strings.undefined end end --classes in form: "sortable, class2, class3 ,..." function p.wrapBasicTable(content, classes, styles, skipNtl) return '{| class = ' .. quotes('wikitable' .. ((classes and space .. p.getTableClasses(classes)) or cstr.empty)) .. ((styles and space .. 'style = ' .. quotes(styles)) or cstr.empty) .. nl .. (not skipNtl and ntl .. nl or cstr.empty) .. content ..'|}' end function p.wrapTable(content, classes, styles, skipNtl) return (classes and '{| class = ' .. quotes((p.getTableClasses(classes))) or cstr.empty) .. ((styles and space .. 'style = ' .. quotes(styles)) or cstr.empty) .. nl .. (not skipNtl and ntl .. nl or cstr.empty) .. content ..'|}' end function p.getTableClasses(classes) classes = p.resolveParameter(classes, 1) local unknownClass = "unknownClass" if not classes then return unknownClass end if type(classes) == "string" then classes = classes:gsub(", ", space):gsub(",", space) else --todo type(classes) == "table" return unknownClass end return classes end function p.getCharacterByName(name) name = name or p.resolveParameter(name) local str = require("Module:Datatable" .. p.lang()) for _, surv in ipairs(survivors) do if surv.shortName == name or surv.name == name then local survivor = table.copy(surv) survivor.isKiller = false return survivor end end for _, killer in ipairs(killers) do if killer.shortName == name or killer.realName == name or the(killer) .. killer.name == name or killer.name == name then local klr = table.copy(killer) klr.isKiller = true return klr end end return nil end --deprecated function p.getCharsByDlc(dlc, charType) local data = require("Module:Datatable" .. p.lang()) local result = {} local listTable = (charType == 'S' and data.survivors) or (charType == nil and data.survivors) or data.killers --if the charType is not set then set the table by default to survivors for _, character in ipairs(listTable) do if character.dlc == dlc.id then result[#result + 1] = character end end if charType ~= nil then --if the charType is set, we need loop through only one table. Otherwise charType wasn't set in order to retrieve both types of characters from DLC return result end for _, character in ipairs(data.killers) do --since the default table is survivor, we can hardcode killer table as a second table if character.dlc == dlc.id then result[#result + 1] = character end end return result end function p.getCharacterFirstName(character) character = p.resolveParameter(character) if not character.name then character = p.getCharacterByName(character) end local regex = '([^ ]*) ?' --%a doesn't consider diacritics such as É (for instance: Élodie) local isKiller = p.isKiller(character) local text = (isKiller and character.name) or character.shortName or character.name --if the char is killer then use their name, otherwise it's survivor, thus use shortName or name if isKiller then return text end --if it's killer, then their nickname is already what it's supposed to return if regex and text:gmatch(regex) then for m in text:gmatch(regex) do return m --return first occurence before potential space, otherwise return whole string end end return "Name not found" end function p.replaceLastSpaceByNBSP(text) -- Non Breakable SPace local lastCharSpaceRegex = "^(.+) $" local regex = "^(.+) (.+)$" --should pick last space(?) text = text:gsub(lastCharSpaceRegex, "%1" .. nbspC):gsub(regex, "%1" .. nbspC .. "%2") return text end function p.isCharacterKiller(character) return p.isKiller(character) end function p.isKiller(character) local character = p.resolveParameter(character) return character.radius ~= nil end function p.getPossessiveName(character, params, fullName) local langs = require("Module:Languages") params = params or {link = p.bool(p.resolveParameter(character, "link", true)) or false} params.fullName = fullName or p.bool(p.resolveParameter(character, "fullName", true)) or false if not character.name then character = p.getCharacterByName(p.resolveParameter(character)) end params.firstName = p.getCharacterFirstName(character) return langs.evaluatePossessive(character, params) end --[[ function p.getDativeName(character, params) params = params or {link = p.bool(p.resolveParameter(character, "link", true)) or false} if not character.name then character = p.getCharacterByName(p.resolveParameter(character)) end if _language ~= "en" then return langs["dative_" .. _language](character, params) .. firstName end return firstName end ]] function p.clr(color, text) text = text or p.resolveParameter(color, 2, true) color = p.resolveParameter(color) return clr(color, text) --return frame:expandTemplate{title = "clr", args = {color, text}} end function p.biclr(color, text) return i(p.clr(color, text)) end function p.ibclr(color, text) return i(p.clr(color, text)) end --Colour Ordered function p.clro(text, reset) reset = reset or p.bool(p.resolveParameter(text, 2, true)) or false text = p.resolveParameter(text, 1) if not p.bool(frame:callParserFunction("#varexists:colorOrderCounter")) or reset then frame:callParserFunction("#vardefine:colorOrderCounter", 1 ) end local order = tonumber(frame:callParserFunction("#var:colorOrderCounter")) % (#_colorOrder + 1) --making list infinite by going back order = (order == 0 and 1) or order --adjusting an index from order = #colorOrder => 0 + 1 = 1 frame:callParserFunction("#vardefine:colorOrderCounter", order + 1 ) return ((text ~= nil and text ~= cstr.empty) and b(clr(_colorOrder[order], text))) or clr(_colorOrder[order], text) end --Colour Ordered Reset function p.clror(text) return p.clro(text, true) end function p.clroTest() local words = string.split(strings.clrTestString, space) local result = cstr.empty local clrOffset = 0 for i, word in ipairs(words) do if #word <= 2 then clrOffset = clrOffset - 1 end local clrIndex = i + clrOffset local color = _colorOrder[clrIndex] result = result .. (#word > 2 and p.tooltip(((i == 1 and p.clror(word)) or p.clro(word)), "order: " .. clrIndex .. br .. "colour: " .. color, true, true) or word) .. (clrIndex < #_colorOrder and space or cstr.empty) if clrIndex == #_colorOrder then break end end return result .. ((#words > #_colorOrder and "...") or (#words < #_colorOrder and dot .. space .. brackets(strings.notEnoughColors)) or cstr.empty) end function p.bclr(color, text) return b(p.clr(color, text)) end function clr(color, text) local result = 'inherit' --CSS value, don't change it --mw.log(tonumber(color, 10)) color = tonumber(color, 10) or color:lower() --if the string is int then convert it to integer if color == 1 or color == "brown" then result = "ab713c" elseif color == "1bg" then result = "5d4533" elseif color == 2 or color == "yellow" then result = "e8c252" elseif color == "2bg" then result = "d7ad2f" elseif color == 3 or color == "green" then result = "199b1e" elseif color == "3bg" then result = "0f791f" elseif color == 4 or color == "purple" then result = "ac3ee3" elseif color == "4bg" then result = "672d7f" elseif color == 5 or color == "pink" then result = "ff0955" elseif color == "5bg" then result = "cf0b45" elseif color == 6 or color == "orange" then result = "ff8800" elseif color == "6bg" then result = "ff5300" elseif color == 7 or color == "grey" then result = "808080" elseif color == 8 or color == "red" then result = "d41c1c" elseif color == 9 or color == "beige" then result = "e7cda2" elseif color == 10 or color == "blue" then result = "0e98ff" elseif color == 11 or color == "violet" then result = "b91a9b" elseif color == "11bg" then result = "800080" elseif color == 12 or color == "light blue" then result = "9bb0bf" elseif color == "12bg" then result = "9bb0bf" elseif color == 13 or color == "faded jade" then result = "418284" elseif color == 14 or color == "gold" then result = "ffa800" elseif color == "14bg" then result = "ffa800" elseif color == 15 or color == "fuchsia" then result = "ec0dea" elseif color == "15bg" then result = "b30ad2" elseif color == 16 or color == "white" then result = "ffffff" elseif color == 17 or color == "vomit green" then result = "8ad672" elseif color == 18 or color == "blood red" then result = "900a0a" elseif color == 19 or color == "bright red" then result = "ff0000" elseif color == 20 or color == "silver" then result = "b5afb0" elseif color == 21 or color == "turquoise" then result = "37d1c0" elseif color == 22 or color == "cinnamon" then result = "b74004" elseif color == 23 or color == "black" then result = "000000" elseif color == 24 or color == "wiki gold" then result = "b7a269" elseif color == 25 or color == "bronze" then result = "c2593a" elseif color == 26 or color == "chartreuse" then result = "b6fa36" elseif color == 27 or color == "screamin' green" then result = "63ef98" elseif color == 28 or color == "lavender" then result = "b57edc" elseif color == 29 or color == "aquamarine" then result = "7fffd4" elseif color == 30 or color == "ultramarine" then result = "120a8f" elseif color == 31 or color == "olive" then result = "808000" elseif color == 32 or color == "pale rose" then result = "f5bfd9" end if text ~= nil and text ~= cstr.empty then result = '<span class="luaClr clr clr' .. color .. '" style="color: ' .. ((result ~= 'inherit' and '#') or cstr.empty) .. result .. ';">' .. text .. '</span>' end return result end --calls for Strings function Syntax Highlight function p.sh(value, lang, inline) inline = p.bool(inline or p.resolveParameter(value, 3, true)) lang = lang or p.resolveParameter(value, 2, true) value = p.resolveParameter(value) return sh(value, lang, inline) end --text = text containing a tooltip --tooltip = tooltip content --iconless = true/false whether the (i) icon should appear after the text containing tooltip (default false) --borderless = true/false whether underline should be shown (default false) function p.tooltip(text, tooltip, iconless, borderless, pcViewOnly) borderless = borderless or p.resolveParameter(text, 4, true) or p.resolveParameter(text, "borderless", true) iconless = p.bool(iconless or p.resolveParameter(text, 3, true) or (p.resolveParameter(text, "tooltip") and p.resolveParameter(text, 2, true)) or p.resolveParameter(text, "iconless")) tooltip = tooltip or p.resolveParameter(text, 2, true) or p.resolveParameter(text, "tooltip") text = p.resolveParameter(text) local containsLink = p.containsLink(tooltip) return '<span class = "tooltip' .. ((containsLink and space .. 'linkIncluded') or cstr.empty) .. ((borderless and space .. 'borderless') or cstr.empty) .. '">' .. '<span class="tooltipBaseText' .. ((iconless and space .. 'iconless') or cstr.empty) .. '">' .. text .. '</span>'.. (((tooltip ~= nil and tooltip ~= cstr.empty) and '<span class = "tooltiptext">' .. ((not pcViewOnly and '<span class = "mobileView"> (</span>') or cstr.empty) .. --if it's mobile view then apply add brackets... '<span class="tooltipTextWrapper">' .. tooltip .. '</span>' .. ((not pcViewOnly and '<span class = "mobileView">) </span>') or cstr.empty) .. '</span>') or cstr.empty) .. '</span>' end function p.containsLink(text) local regex = '%[%[.-%]%]' local rawRegex = '?%&%#91;%&%#91;.-%&%#93;%&%#93;' if string.match(text, regex) or string.match(text, rawRegex) then --we want to return boolean, not the index return true else return false end end function p.ptb(content, title, patch) return ptb( p.resolveParameter(content), title or p.resolveParameter(content, 2, true), patch or p.resolveParameter(content, 3, true) ) end function ptb(content, title, patch) title = title or p.resolveParameter(content, 2, true) patch = patch or p.resolveParameter(content, 3, true) if not patch or p.isPatchLive(patch) then return content else return dynamicBox(content, title, "ptb") end end function p.deletedBox(content, title, patch) return deletedBox( p.resolveParameter(content), title or p.resolveParameter(content, 2, true), patch or p.resolveParameter(content, 3, true) ) end function deletedBox(content, title, patch) local result = dynamicBox(content, title, "deletedBox") patch = (patch and string.trim(patch)) or nil if patch and not p.isPatchLive(patch) then --result = includeonly(result) .. noinclude(category("DeleteBox Remove Lists", "Remove List " .. patch)) result = result .. category("DeleteBox Remove Lists", "DeleteBox List for " .. patch) end return result --no further logic so redirecting straight to dynamic box end function p.wipBox(content, title, patch) return wipBox( p.resolveParameter(content), title or p.resolveParameter(content, 2, true), patch or p.resolveParameter(content, 3, true) ) end function wipBox(content, title, patch) local result = dynamicBox(content, title, "wipBox") return result --no further logic so redirecting straight to dynamic box end function dynamicBox(content, title, boxType) title = title or p.resolveParameter(content, 2, true) boxType = boxType or p.resolveParameter(content, 3, true) if not boxType then return strings.boxTypeNotFound end return '<div class = "dynamicBox ' .. boxType .. '">' .. ((title and '<div class = "dynamicTitle ' .. boxType .. '">' .. title .. '</div>' ) or cstr.empty) .. '<div class = "dynamicContent ' .. boxType .. '">' .. content .. '</div>' .. '</div>' end function p.isPatchLive(patchParam) local patch = p.getPatch(patchParam) --dLog(((patchParam and "[" .. patchParam .. ((not patch and " - Not Found") or cstr.empty) .. "]") or cstr.empty) .. " isPatchLive: " .. (patch and (p.IsFullDateTime(patch.rDate) and tostring(p.dateHasPassed(p.GetDatetime(patch.rDate)))) or tostring(false))) return patch and (p.IsFullDateTime(patch.rDate) and p.dateHasPassed(p.GetDatetime(patch.rDate))) or false end function p.isCharacterLive(character) if character.dlc then local dlcM = require("Module:DLCs") local dlc = dlcM.getCharacterMainDlc(character) return (dlc == nil) or p.IsFullDateTime(dlc.rDate) and p.dateHasPassed(dlc.rDate) end return false end function p.getPatch(patch) local data = require("Module:Datatable" .. p.lang()) for _, patchObj in ipairs(data.patches) do if patchObj.patch == patch then return patchObj end end end function p.getLatestPatch() return require("Module:Datatable" .. p.lang()).latestPatch.patch end --timestamp = {year = 2022, month = 7, day = 19} --example format function p.dateHasPassed(timestamp) local currentDate = os.date("*t") --gives current timestamp: {year = 1998, month = 9, day = 16, yday = 259, wday = 4, hour = 23, min = 48, sec = 10, isdst = false} local releaseOffset = 60 * 60 * 15 --release hour 15:00 (server time is -2 hours from my current time) timestamp = p.standardiseDateObject(timestamp) --mw.log(os.difftime(os.time(timestamp) + releaseOffset, os.time(currentDate))) return os.difftime(os.time(timestamp) + releaseOffset, os.time(currentDate)) < 0 -- subtracting releaseOffset to adjust timing according to actual release hour end function p.isEventLive(element) --not element.event is to skip events from different tables, such as tomes return not (element.event or element.patch) and (element.rDate and p.dateHasPassed(element.rDate)) and (element.eDate == nil or not p.dateHasPassed(element.eDate)) or (element.patch and element.rDate and p.isFullDateTime(element.rDate) and p.dateHasPassed(element.rDate) and (element.eDate == nil or not p.dateHasPassed(element.eDate))) end function p.standardiseDateObject(dateObj) if type(dateObj) == types.table then --if we pass table, we need to check time values and populate them to 0 by default if not dateObj.hour then dateObj.hour = 0 end if not dateObj.min then dateObj.min = 0 end if not dateObj.sec then dateObj.sec = 0 end dateObj = os.time(dateObj) --we convert it to seconds constant (resp. variable) end dateObj = p.GetDatetime(dateObj) return dateObj end function p.resolvePatchList() local data = require("Module:Datatable" .. p.lang()) local result = cstr.empty local yearCounter = 0 local tempResult = cstr.empty for _, patch in ipairs(data.patches) do local patchDate = p.standardiseDateObject(patch.rDate) local suffixLink = getSuffixLink(patch) local suffixPatchName = getSuffixPatchName(patch) --in case of PTB we need to attach " (PTB)" suffix if yearCounter ~= patchDate.year then if yearCounter ~= 0 then result = result .. frame:callParserFunction{ name = '#tag', args = {"tabber", tempResult} } .. nl end tempResult = cstr.empty yearCounter = patchDate.year result = result .. "|-|" .. patchDate.year .. "=" .. nl end local patchNotes, result = pcall(function () return frame:expandTemplate{title = strings.patch .. space .. patch.patch .. suffixPatchName} end) if patchNotes and --[[not patch.ptb and]] patch ~= patches[#patches] then local patchVersions = string.split(patch.patch, '.') if patchVersions[3] ~= "0" then patchVersions[3] = "0" end for i = #patchVersions, 4 , -1 do --in case that patch contains anything else after last patch number let's remove it (example: "6.1.2 / 6.1.3") table.remove(patchVersions) end local patchLink = strings.patch .. space .. patch.patch .. suffixPatchName local patchLinkModified = strings.patch .. space .. table.concat(patchVersions, ".") tempResult = tempResult .. frame:expandTemplate{title = "!"}.. "-" .. frame:expandTemplate{title = "!"} .. patch.patch .. suffixPatchName .. "=" .. nl .. --creating individual patch tabs frame:expandTemplate{title = "(!"} .. space .. 'class = "wikitable"' .. nl .. "!" .. nl .. "==== " .. link(patchLinkModified .. ((suffixLink and suffixLink .. tl .. patchLink) or cstr.empty)) .. " - " .. p.toDate(os.time(patchDate)) .. " ====" .. nl .. --28 April 2022 frame:expandTemplate{title = "!-"} .. nl .. frame:expandTemplate{title = "!"} .. result .. nl .. frame:expandTemplate{title = "!)"} .. nl end end result = result .. frame:callParserFunction{ name = "#tag", args = {"tabber", tempResult} } .. nl --post loop aiditon for last year result = frame:extensionTag{name = 'tabber',content = result} return result end function getSuffixPatchName(patch) if patch.ptb then return " (PTB)" end return cstr.empty end function getSuffixLink(patch) local versions = string.split(patch.patch, '.') if versions[3] ~= "0" then return "#Hotfix " .. patch.patch elseif patch.ptb then return "#Public Test Build " .. patch.patch --patch needs to not contain "(PTB)" part end return nil end function p.getPatchLink(patch) local suffixLink = getSuffixLink(patch) local suffixPatchName = getSuffixPatchName(patch) --in case of PTB we need to attach " (PTB)" suffix local patchLink = strings.patch .. space .. patch.patch .. suffixPatchName local patchVersions = string.split(patch.patch, '.') if patchVersions[3] ~= "0" then patchVersions[3] = "0" end local patchLinkModified = strings.patch .. space .. table.concat(patchVersions, ".") return link(patchLinkModified .. ((suffixLink and suffixLink .. tl .. patchLink) or cstr.empty)) end --wt = wordTable function p.getWord(wt, index) local keys = table.keys(wt) local maxValue = table.max(keys) local minValue = table.min(keys) if index > maxValue then return wt[maxValue] end --if the index is higher than highest amount, return word of highest amount available if wt[index] then return wt[index] end -- if the index is exactly of plural count then return exact word on index if index < minValue then return wt[minValue] end --if index not found, it means it's lower than lowest amount in a word table for i, keyValue in ipairs(keys) do if index < keyValue then return wt[keys[i - 1]] --if the index is between two amounts(indexes) use the lower one end end end --{{header = 2022, content = "..."}, {}, ...} function p.getTabberFromTable(tabberTable) local result = cstr.empty for _, section in ipairs(tabberTable) do result = result .. nl .. '|-|' .. (section.header or strings.tabberHeaderNotFound) .. '=' .. nl .. section.content .. nl end result = frame:callParserFunction{ name = '#tag', args = {"tabber", result} } return result end function p.isTagPresent(el, searchedTag) if el.tags and #el.tags > 0 then for _, tag in ipairs(el.tags) do if string.lower(searchedTag) == string.lower(tag) then return true end end end return false end function p.yesNo(param, note, imgSize) imgSize = imgSize or p.resolveParameter(param, 3, true) or p.resolveParameter(param, "size", true) note = note or p.resolveParameter(param, 2, true) or p.resolveParameter(param, "note", true) param = p.resolveParameter(param, 1, true) or param local imageFilename = "Unknown QuestionMark.png" local tickClass = "unknown" local size = (imgSize or 32) .. "px" if p.bool(param) == true then imageFilename = "DBD_UI_Icon_CheckMark.png" tickClass = "tickYes" elseif p.bool(param) == false then imageFilename = "DBD_UI_Icon_X.png" tickClass = "tickNo" elseif param:lower() == "nan" then imageFilename = "NaN.png" tickClass = "tickNaN" end --lg(span(p.tooltip(span(file(imageFilename, size), tickClass),cstr.empty,true,true), "yesNo")) return span( p.tooltip( span(file(imageFilename, size), tickClass), note or cstr.empty, true, true ) , "yesNo") end --imgType: -- perk = perk with switching background -- sosPerk = teachable frame background --icon icon that is inside --imgSize currently not used, should be available for manually adjusting the size of image function p.assembleImage(imgType, icon, imgSize, params) local variousLogic = require("Module:Various") params = params or p.resolveParameter(imgType, 4, true) --not sure if table can be passed directly from wiki local rarity = p.resolveParameter(imgType, "rarity", true) local rarityNumber = tonumber(rarity) or (params and params.rarity and tonumber(params.rarity)) rarity = string.replace(((rarityNumber and (variousLogic.rarity[rarityNumber].techName or variousLogic.rarity[rarityNumber].name)) or (rarity or (params and params.rarity)) or variousLogic.rarity[1].techName or variousLogic.rarity[1].name):lower(), space, dash) --Common by default rarity = string.replace(rarity, "&", "and") imgSize = imgSize or p.resolveParameter(imgType, 3, true) or p.resolveParameter(imgType, "size", true) icon = icon or p.resolveParameter(imgType, 2, true) or p.resolveParameter(imgType, "icon", true) imgType = p.resolveParameter(imgType) local imgSizeStyle = (imgSize and ' style = "width: ' .. imgSize .. 'px; height: ' .. imgSize .. 'px;"') or cstr.empty local isIconLink = (params and params.iconLink == true) or false local align = (params and params.align and "float: " .. params.align .. semi) or cstr.empty if imgType == "sosPerk" then return '<div class = "game-element-container inline-flex">' .. '<div class = "game-element-bg-settings game-element-bg-settings-size-sos teachable-perk-element"' .. imgSizeStyle .. '></div>' .. '<div class = "game-element-bg-settings-size-sos game-element-imgObject absolute"' .. imgSizeStyle .. '>' .. file(p.getIcon(icon), "link=" .. icon) .. '</div>' .. '<div class = "game-element-bg-settings game-element-bg-settings-size-sos teachable-indicator-perk-element absolute"' .. imgSizeStyle .. '></div>' .. '</div>' elseif imgType == "perk" then return '<div class = "game-element-container flex">' .. '<div class = "game-element-bg-settings game-element-bg-settings-size-perk animate-perk-settings animate-perk-bg"' .. imgSizeStyle .. '></div> ' .. '<div class = "game-element-bg-settings game-element-bg-settings-size-perk animate-perk-settings animate-perk-level absolute"' .. imgSizeStyle .. '></div>' .. '<div class = "game-element-bg-settings-size-sos game-element-imgObject absolute"' .. imgSizeStyle .. '>' .. file(p.getIcon(icon), "link=" .. icon, "center") .. '</div>' .. '</div>' elseif table.contains({"addon", "item", "power", "offering"}, imgType) then --rarity = (rarity and variousLogic.rarity[rarity].name:lower()) or string.replace((params and (params.rarity and (tonumber(params.rarity) and variousLogic.rarity[params.rarity].name) or params.rarity) or variousLogic.rarity[1].name):lower(), space, dash) addonContainer = (imgType == "addon" and "addon-container") or cstr.empty imgSize = imgSize or 128 if isIconLink then return '<span class = "margin-auto" style = "max-width: ' .. imgSize .. 'px;' .. align ..'">' .. '<span class = "game-element-container ' .. addonContainer .. ' flex relative">' .. '<span class = "game-element-bg-settings game-element-bg-settings-size-perk ' .. rarity .. '-' .. (table.contains({"item", "offering"}, imgType) and imgType or "item") .. '-element" ' .. imgSizeStyle .. '></span>' .. ((imgType == "addon" and '<span class = "game-element-bg-settings game-element-bg-settings-size-perk addon-marker addon-marker-il absolute"></span>') or cstr.empty) .. '<span class = "game-element-bg-settings-size-sos absolute" ' .. imgSizeStyle .. '>' .. file(p.getIcon(icon), "link=" .. icon, "300px") .. '</span>' .. '</span>' .. '</span>' else return '<div class = "margin-auto" style = "max-width: ' .. imgSize .. 'px; scale: calc(' .. imgSize .. '/128); ' .. align ..'">' .. '<div class = "game-element-container ' .. addonContainer .. ' flex relative">' .. '<div class = "game-element-bg-settings game-element-bg-settings-size-perk ' .. rarity .. '-' .. (table.contains({"item", "offering"}, imgType) and imgType or "item") .. '-element"></div>' .. ((imgType == "addon" and '<div class = "game-element-bg-settings game-element-bg-settings-size-perk addon-marker absolute"></div>') or cstr.empty) .. '<div class = "game-element-bg-settings-size-sos absolute">' .. file(p.getIcon(icon), "link=" .. icon, "300px") .. '</div>' .. '</div>' .. '</div>' end end end function p.resolvePageHeader(params) return nil end return p
Oggetto:
Si prega di notare che tutti i contributi effetuati su Dead by Daylight Wiki sono considerati distribuiti sotto la CC BY-NC-SA
Annulla
Guida
(si apre in una nuova finestra)
Template utilizzato in questa pagina:
Modulo:Utils/man
(
modifica
)
Follow on IG
TikTok
Join Fan Lab