Module:GymLeaderLineup
Documentation for this module may be created at Module:GymLeaderLineup/doc
local p = {}
local DATA_FORMAT = 'CSV with header'
local function nonEmpty(s)
if s == nil then return nil end
s = mw.text.trim(tostring(s))
if s == '' then return nil end
return s
end
local function splitList(s)
if not nonEmpty(s) then return {} end
local out = {}
for _, part in ipairs(mw.text.split(s, ',')) do
out[#out + 1] = mw.text.trim(part)
end
return out
end
local pokemonRowsCache = nil
local function pokemonRows()
if pokemonRowsCache then return pokemonRowsCache end
local csvData = mw.ext.externalData.getExternalData{
url = 'https://wiki.pokemonrevolution.net/index.php?title=Special:GetData/PokemonRawList',
format = DATA_FORMAT,
data = { name = 'Name', type1 = 'Type1', type2 = 'Type2' },
}
pokemonRowsCache = {}
if csvData then
for _, row in ipairs(csvData) do
if nonEmpty(row.name) then
pokemonRowsCache[row.name] = row
end
end
end
return pokemonRowsCache
end
local moveRowsCache = nil
local function moveRows()
if moveRowsCache then return moveRowsCache end
local csvData = mw.ext.externalData.getExternalData{
url = 'https://wiki.pokemonrevolution.net/index.php?title=Special:GetData/RawMovesList',
format = DATA_FORMAT,
data = {
name = 'Name', type = 'Type', category = 'Category',
power = 'Power', accuracy = 'Accuracy', broken = 'Broken', typeless = 'Typeless',
},
}
moveRowsCache = {}
if csvData then
for _, row in ipairs(csvData) do
if nonEmpty(row.name) then
moveRowsCache[row.name] = row
end
end
end
return moveRowsCache
end
local megaCache = {}
local function megaByName(name)
if megaCache[name] == nil then
local ok, values = pcall(function()
return mw.ext.externalData.getFileData{
source = 'data',
['file name'] = 'RawMegaPokemonList.csv',
format = DATA_FORMAT,
filters = 'Name=' .. name,
data = 'name=Name,type1=Type1,type2=Type2',
}
end)
megaCache[name] = (ok and values and values.name ~= nil) and values or false
end
return megaCache[name] or nil
end
local typeColorCache = {}
local function typeColor(frame, pokeType)
pokeType = nonEmpty(pokeType) or 'Normal'
if not typeColorCache[pokeType] then
typeColorCache[pokeType] = {
base = frame:expandTemplate{ title = pokeType .. ' color' },
light = frame:expandTemplate{ title = pokeType .. ' color light' },
dark = frame:expandTemplate{ title = pokeType .. ' color dark' },
}
end
return typeColorCache[pokeType]
end
local catColorCache = {}
local function categoryColor(frame, category)
category = nonEmpty(category) or 'Status'
if not catColorCache[category] then
catColorCache[category] = frame:expandTemplate{ title = category .. ' color' }
end
return catColorCache[category]
end
local function fileExists(frame, fileName)
return frame:callParserFunction('#ifexist', 'File:' .. fileName, 'Y', '') == 'Y'
end
local function moveRowHtml(frame, moveName, primaryType, secondaryType)
moveName = mw.text.trim(moveName)
local m = moveRows()[moveName] or {}
local mtype = nonEmpty(m.type) or 'Normal'
local category = nonEmpty(m.category) or 'Status'
local typeless = m.typeless or 'N'
local nameStyle = ''
if category ~= 'Status' and typeless == 'N' and (mtype == primaryType or mtype == secondaryType) then
nameStyle = nameStyle .. 'font-weight: bold; '
end
if m.broken == 'Y' then
nameStyle = nameStyle .. 'font-style: italic;'
end
return '<tr style="background-color:#FFFFFF; color:#000000;">' ..
'<td><span style="' .. nameStyle .. '">[[' .. moveName .. ']]</span></td>' ..
'<td style="background-color: #' .. typeColor(frame, mtype).base .. ';">[[' .. mtype ..
'_(type)|<span style="color:#FFFFFF;">' .. mtype .. '</span>]]</td>' ..
'<td style="background-color:#' .. categoryColor(frame, category) .. ';">[[' .. category ..
' Moves|<span style="color:#FFFFFF;">' .. category .. '</span>]]</td>' ..
'<td>' .. (nonEmpty(m.power) or '—') .. '</td>' ..
'<td>' .. (nonEmpty(m.accuracy) or '') .. '</td></tr>'
end
local function slotHtml(frame, name, isMega, sprite, moves, cell, border)
local data = isMega and megaByName(name) or pokemonRows()[name]
local type1 = data and nonEmpty(data.type1) or 'Normal'
local type2 = data and nonEmpty(data.type2) or nil
local spriteFile = nonEmpty(sprite) or ((isMega and 'Mega_' or '') .. name .. '_Front_Sprite')
local displayName = (isMega and 'Mega ' or '') .. '[[' .. name .. ']]'
local colors = typeColor(frame, type1)
local moveRowsHtml = {}
for _, moveName in ipairs(moves) do
if nonEmpty(moveName) then
moveRowsHtml[#moveRowsHtml + 1] = moveRowHtml(frame, moveName, type1, type2)
end
end
return '<tr><td style="background-color:' .. border .. '; border-radius: 25px; padding: 5px;">' ..
'<table width="100%" style="text-align: center; padding: 5px;">' ..
'<tr><td colspan="5"><div style="background-color:#' .. colors.light .. '; border-radius: 25px; ' ..
'border: 3px solid #' .. colors.dark .. '; padding: 3px; margin: auto auto; width: 30%;">' ..
'[[File:' .. spriteFile .. '.png]]' ..
'<div style="background-color:#FFFFFF; border-radius: 25px; border: 3px solid #' .. colors.dark ..
'; padding: 3px; margin: auto auto; margin-top: 5px; width: 45%;">' .. displayName .. '</div>' ..
'</div></td></tr>' ..
'<tr><td colspan="5"><table class="collapsible collapsed" style="width: 100%; text-align: center; padding: 4px;">' ..
'<tr style="background-color: ' .. cell .. '; color:' .. border .. ';">' ..
'<th>Move</th><th>Type</th><th>Category</th><th>Base Power</th><th>Accuracy</th></tr>' ..
table.concat(moveRowsHtml) ..
'</table></td></tr>' ..
'</table></td></tr>'
end
-- When no Theme is given and no outer template has bridged in Trichrome-style
-- colors, pick the lineup's own most common primary type as the theme
-- (e.g. an all-Normal team) rather than falling back to plain white/black.
local function inferTheme(lineup, megaFlags)
local counts, order = {}, {}
for i, name in ipairs(lineup) do
local isMega = (tonumber(megaFlags[i]) or 0) > 0
local data = isMega and megaByName(name) or pokemonRows()[name]
local t = data and nonEmpty(data.type1)
if t then
if not counts[t] then
counts[t] = 0
order[#order + 1] = t
end
counts[t] = counts[t] + 1
end
end
local best, bestCount = nil, 0
for _, t in ipairs(order) do
if counts[t] > bestCount then
best, bestCount = t, counts[t]
end
end
return best
end
function p.main(frame)
local parent = frame:getParent()
local pargs = (parent and parent.args) or frame.args
local iargs = frame.args
local headerName = nonEmpty(pargs.NPC) or nonEmpty(iargs.Leader) or ''
local lineup = splitList(pargs.Lineup)
local megaFlags = splitList(pargs.Mega)
if #megaFlags == 0 then
megaFlags = { '0', '0', '0', '0', '0', '0' }
end
local background, cell, border
local theme = nonEmpty(pargs.Theme)
local hasBridgedColors = nonEmpty(iargs.Background) or nonEmpty(iargs.Cell) or nonEmpty(iargs.Border)
if not theme and not hasBridgedColors then
theme = inferTheme(lineup, megaFlags)
end
if theme then
background = '#' .. frame:expandTemplate{ title = theme .. ' color' }
cell = '#' .. frame:expandTemplate{ title = theme .. ' color light' }
border = '#' .. frame:expandTemplate{ title = theme .. ' color dark' }
else
-- Falls back to whatever Trichrome-style vars an outer template already
-- set; Lua can't read #var: directly, so the template bridges them in
-- as invoke arguments.
background = nonEmpty(iargs.Background) or '#FFFFFF'
cell = nonEmpty(iargs.Cell) or '#FFFFFF'
border = nonEmpty(iargs.Border) or '#000000'
end
local slots = {}
for i, name in ipairs(lineup) do
if nonEmpty(name) then
local isMega = (tonumber(megaFlags[i]) or 0) > 0
local moves = splitList(pargs['Moves' .. (i - 1)])
local sprite = pargs['Sprite' .. (i - 1)]
slots[#slots + 1] = slotHtml(frame, name, isMega, sprite, moves, cell, border)
end
end
local headerIcon = ''
if headerName ~= '' and fileExists(frame, headerName .. '.png') then
headerIcon = '<tr><td>[[File:' .. headerName .. '.png]]</td></tr>'
end
return '<table align="center" style="width: 75%; max-width: 100%; background-color:' .. background ..
'; border: 5px solid ' .. border .. '; border-radius: 25px; padding: 5px;">' ..
'<tr><td colspan="6"><table style="margin: auto auto; width: 35%; text-align: center; ' ..
'border-radius: 25px; border: 3px solid ' .. border .. '; padding: 5px; background-color:' .. cell ..
'; color:' .. border .. '; font-weight: bold;">' ..
headerIcon .. '<tr><td>' .. headerName .. '</td></tr></table></td></tr>' ..
table.concat(slots) ..
'<tr><td style="background-color: ' .. cell .. '; border: 1px solid ' .. border .. '; border-radius: 25px;">' ..
'<ul>' ..
"<li>'''Emboldened''' moves avail from a STAB bonus when deployed by that Pokémon.</li>" ..
"<li>''Italicized'' moves are functionally broken; see their individualized pages for more information.</li>" ..
'</ul></td></tr></table>'
end
return p