Module:Breeding
Jump to navigation
Jump to search
This module is used in the Template:Breeding. It stores breeding data, and displays it on the page for the end user to see.
Cargo Store Information:
- Stores Breeding information into the PalBreeding Table.
- Subpages
local argsUtil = require("Module:ArgsUtil")
local cargoUtil = require("Module:CargoUtil")
local html = mw.html
local p = {}
local function isBlank(v)
return v == nil or mw.text.trim(tostring(v)) == ""
end
local function trim(v)
return mw.text.trim(tostring(v or ""))
end
local function toNumber(v)
if isBlank(v) then return nil end
return tonumber(trim(v))
end
local function split(str, sep)
local out = {}
str = tostring(str or "")
sep = sep or ";"
for part in mw.text.gsplit(str, sep, true) do
part = trim(part)
if part ~= "" then
table.insert(out, part)
end
end
return out
end
local function normalizeGender(g)
g = trim(g):lower()
if g == "" then return nil end
if g == "m" or g == "male" or g == "♂" then return "M" end
if g == "f" or g == "female" or g == "♀" then return "F" end
return nil
end
local function formatGenderRatio(maleProbability, genderRatioText)
local mp = toNumber(maleProbability)
if mp ~= nil then
if mp < 0 then mp = 0 end
if mp > 100 then mp = 100 end
local f = 100 - mp
return string.format("%d:%d", f, mp)
end
genderRatioText = trim(genderRatioText)
if genderRatioText ~= "" then
return mw.text.nowiki(genderRatioText)
end
return ""
end
local function makeEggDisplay(eggName, eggLink)
eggName = trim(eggName)
eggLink = trim(eggLink)
if eggName == "" then
return ""
end
local file = string.format("%s_icon.png", eggName)
local linkTarget = eggLink ~= "" and eggLink or eggName
local img = string.format("[[File:%s|80px|link=%s]]", file, linkTarget)
local label = string.format("'''[[%s|%s]]'''", linkTarget, mw.text.nowiki(eggName))
return img .. "<br/>" .. label
end
local function titleCase(s)
s = trim(s)
if s == "" then return "" end
return (mw.ustring.gsub(mw.ustring.lower(s), "(%a)([%w']*)", function(a, b)
return mw.ustring.upper(a) .. b
end))
end
local function getEggParts(eggName)
eggName = titleCase(eggName)
if eggName == "" then
return nil, nil
end
local size = "Regular"
if eggName:find("^Large%s+") then
size = "Large"
eggName = trim(eggName:gsub("^Large%s+", ""))
elseif eggName:find("^Huge%s+") then
size = "Huge"
eggName = trim(eggName:gsub("^Huge%s+", ""))
end
local eggType = eggName:match("^(%w+)%s+Egg$")
if not eggType then
eggType = eggName:match("^(%w+)")
end
eggType = titleCase(eggType or "")
if eggType == "" then
eggType = nil
end
return eggType, size
end
local function buildEggCategoriesWikitext(eggName)
local eggType, size = getEggParts(eggName)
if not eggType and not size then
return ""
end
local cats = {}
if eggType then
table.insert(cats,
string.format("[[Category:Pals Hatched From %s Eggs]]", eggType)
)
end
if size then
table.insert(cats,
string.format("[[Category:Pals Hatched From %s Eggs]]", size)
)
end
return table.concat(cats)
end
local function buildTopTable(breedingRankText, genderRatioText, eggNameText, eggDisplay, combiDuplicatePriority)
local breedingRank = trim(breedingRankText)
if breedingRank == "" then breedingRank = "Unknown" end
local genderRatio = trim(genderRatioText)
if genderRatio == "" then genderRatio = "Unknown" end
local dupPriority = trim(combiDuplicatePriority)
if dupPriority == "" then dupPriority = "Unknown" end
local eggName = trim(eggNameText)
if eggName == "" then eggName = "Unknown" end
local hasEgg = not isBlank(eggDisplay)
local tbl = html.create("table"):addClass("wikitable")
if hasEgg then
local tr1 = tbl:tag("tr")
tr1:tag("th")
:attr("rowspan", "3")
:css("text-align", "center")
:css("vertical-align", "middle")
:css("width", "140px")
:wikitext(eggDisplay)
tr1:tag("th"):wikitext("Breeding Rank")
tr1:tag("td"):wikitext(mw.text.nowiki(breedingRank))
local tr2 = tbl:tag("tr")
tr2:tag("th"):wikitext("Gender Ratio (F:M)")
tr2:tag("td"):wikitext(mw.text.nowiki(genderRatio))
local tr3 = tbl:tag("tr")
tr3:tag("th"):wikitext("Breeding Duplicate Priority")
tr3:tag("td"):wikitext(mw.text.nowiki(dupPriority))
else
local tr1 = tbl:tag("tr")
tr1:tag("th"):wikitext("Breeding Rank")
tr1:tag("td"):wikitext(mw.text.nowiki(breedingRank))
local tr2 = tbl:tag("tr")
tr2:tag("th"):wikitext("Gender Ratio (F:M)")
tr2:tag("td"):wikitext(mw.text.nowiki(genderRatio))
local tr3 = tbl:tag("tr")
tr3:tag("th"):wikitext("Breeding Duplicate Priority")
tr3:tag("td"):wikitext(mw.text.nowiki(dupPriority))
local tr4 = tbl:tag("tr")
tr4:tag("th"):wikitext("Egg")
tr4:tag("td"):wikitext("Unknown")
end
return tbl
end
local function parsePalWithGender(text)
text = trim(text)
if text == "" then
return nil, nil
end
local name, gender = text:match("^(.-)%s*%((.-)%)%s*$")
if name then
name = trim(name)
gender = normalizeGender(gender)
if name ~= "" then
return name, gender
end
end
return text, nil
end
local function parseBreedingCombos(text)
local combos = {}
text = trim(text)
if text == "" then
return combos
end
for _, row in ipairs(split(text, ";")) do
local left, childText = row:match("^(.-)%s*=%s*(.-)%s*$")
if left and childText then
local p1Text, p2Text = left:match("^(.-)%s*%+%s*(.-)$")
if p1Text and p2Text then
local p1Name, p1Gender = parsePalWithGender(p1Text)
local p2Name, p2Gender = parsePalWithGender(p2Text)
local childName, childGender = parsePalWithGender(childText)
if p1Name and p2Name and childName then
table.insert(combos, {
parent1Name = p1Name,
parent1Gender = p1Gender,
parent2Name = p2Name,
parent2Gender = p2Gender,
childName = childName,
childGender = childGender
})
end
end
end
end
return combos
end
local function renderPalCard(container, palName, gender, role)
local card = container:tag("div")
:addClass("module-card")
:addClass("module-breeding-card")
:addClass("module-breeding-card-" .. role)
:attr("data-pal", tostring(palName):lower())
card:tag("div")
:addClass("module-card-image")
:wikitext(string.format(
"[[File:%s_icon.png|frameless|link=%s]]",
palName,
palName
))
local nameText = not isBlank(gender)
and string.format("[[%s]] (%s)", palName, gender)
or string.format("[[%s]]", palName)
card:tag("div")
:addClass("module-card-banner-top")
:tag("span")
:addClass("module-card-banner-top-text")
:wikitext(nameText)
return card
end
local function renderBreedingCombos(combos)
if not combos or #combos == 0 then
return nil
end
local root = html.create("div")
:addClass("module-breeding-combos")
:cssText(
"display:flex;" ..
"flex-direction:column;" ..
"gap:12px;"
)
for _, c in ipairs(combos) do
local wrap = root:tag("div")
:addClass("module-breeding-combo-row")
:cssText(
"display:flex;" ..
"align-items:center;" ..
"gap:10px;" ..
"flex-wrap:wrap;"
)
renderPalCard(wrap, c.parent1Name, c.parent1Gender, "parent1")
wrap:tag("div")
:addClass("module-breeding-combo-sep")
:cssText(
"font-size:32px;" ..
"font-weight:800;" ..
"line-height:1;" ..
"min-width:22px;" ..
"text-align:center;" ..
"align-self:center;"
)
:wikitext("+")
:done()
renderPalCard(wrap, c.parent2Name, c.parent2Gender, "parent2")
wrap:tag("div")
:addClass("module-breeding-combo-sep")
:cssText(
"font-size:32px;" ..
"font-weight:800;" ..
"line-height:1;" ..
"min-width:22px;" ..
"text-align:center;" ..
"align-self:center;"
)
:wikitext("=")
:done()
renderPalCard(wrap, c.childName, c.childGender, "child")
end
return root
end
function p.main(frame)
local args = argsUtil.merge()
local title = mw.title.getCurrentTitle()
local palName = trim(args.palName)
if palName == "" then
palName = title.text
end
local breedingRankRaw = args.breedingRank or args.breeding_rank
local breedingRankNum = toNumber(breedingRankRaw)
local breedingRankText = trim(breedingRankRaw)
local maleProbability = args.maleProbability or args.male_probability
local genderRatioText = formatGenderRatio(maleProbability, args.genderRatio or args.gender_ratio)
local eggName = args.palEgg or args.egg
local eggDisplay = makeEggDisplay(eggName, args.eggLink or args.egg_link)
local combiDuplicatePriority = args.combi_duplicate_priority
local combos = parseBreedingCombos(args.uniqueCombos or args.unique_combos or "")
local isUniqueCombo = (#combos > 0)
local out = html.create("div")
if title.namespace == 0 then
cargoUtil.storeRow("PalBreeding", {
palName = palName,
breedingRank = breedingRankNum and tostring(breedingRankNum) or nil,
maleProbability = toNumber(maleProbability) and tostring(toNumber(maleProbability)) or nil,
isUniqueCombo = isUniqueCombo and "1" or "0",
palEgg = (trim(eggName) ~= "" and trim(eggName) or nil),
combiDuplicatePriority = (trim(combiDuplicatePriority) ~= "" and trim(combiDuplicatePriority) or nil),
})
out:wikitext(buildEggCategoriesWikitext(eggName))
end
out:node(buildTopTable(
breedingRankText,
genderRatioText,
eggName,
eggDisplay,
combiDuplicatePriority
))
local combosNode = renderBreedingCombos(combos)
if combosNode then
out:tag("h3"):wikitext("Unique Breeding Combinations")
out:node(combosNode)
end
return tostring(out)
end
return p