Module:Participant: Difference between revisions
From eSportsAmaze
More actions
Esportsamaze (talk | contribs) No edit summary |
Esportsamaze (talk | contribs) No edit summary |
||
| (4 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
local html = mw.html | local html = mw.html | ||
local cargo = mw.ext.cargo | local cargo = mw.ext.cargo | ||
local function sqlEscape(s) | |||
local function | if not s then return "" end | ||
return | s = s:gsub("\\", "\\\\") | ||
s = s:gsub("'", "\\'") | |||
return s | |||
end | end | ||
-- | -- HELPER: Smart Tournament Name Detection | ||
local function | local function getTournamentName(args) | ||
local | if args.tournament and args.tournament ~= "" then return args.tournament end | ||
local | local pageTitle = mw.title.getCurrentTitle().text | ||
local parts = mw.text.split(pageTitle, '/') | |||
if parts[2] == "Tournaments" and parts[3] then return parts[3] end | |||
return mw.title.getCurrentTitle().baseText | |||
end | |||
-- INTERNAL: Builds the HTML for a single card | |||
local function buildCard(data, seedOverride) | |||
local root = html.create('div'):addClass('roster-card') | local root = html.create('div'):addClass('roster-card') | ||
-- HEADER | -- HEADER | ||
local header = root:tag('div'):addClass('roster-header') | local header = root:tag('div'):addClass('roster-header') | ||
local headerContent = header:tag('div'):addClass('header-content') | local headerContent = header:tag('div'):addClass('header-content') | ||
-- Logo | -- LOGO LOGIC | ||
-- Priority: 1. Tournament Entry Custom Logo -> 2. Master DB Custom Logo -> 3. Master DB Default Name -> 4. Shield | |||
local lightLogo = "Shield_team.png" | |||
local darkLogo = "Shield_team_dark.png" | |||
-- Check Entry (Tournament specific) Override first | |||
if data.entryImg and data.entryImg ~= "" then | |||
lightLogo = data.entryImg | |||
darkLogo = (data.entryImgDark and data.entryImgDark ~= "") and data.entryImgDark or lightLogo | |||
-- Check Master DB | |||
elseif data.masterImg and data.masterImg ~= "" then | |||
lightLogo = data.masterImg | |||
darkLogo = (data.masterImgDark and data.masterImgDark ~= "") and data.masterImgDark or lightLogo | |||
end | |||
local logoDiv = headerContent:tag('div'):addClass('roster-logo') | local logoDiv = headerContent:tag('div'):addClass('roster-logo') | ||
logoDiv:tag('div'):addClass('logo-lightmode'):wikitext('[[File:' .. lightLogo .. '|link=]]') | |||
logoDiv:tag('div'):addClass('logo-darkmode'):wikitext('[[File:' .. darkLogo .. '|link=]]') | |||
-- NAME LOGIC | |||
local displayName = data.displayName | |||
if not displayName or displayName == "" then displayName = data.team end | |||
headerContent:tag('div'):addClass('roster-name'):wikitext('[[' .. data.team .. '|' .. displayName .. ']]') | |||
-- SEEDING | |||
local finalSeed = seedOverride | |||
if not finalSeed or finalSeed == "" then finalSeed = data.seeding end | |||
if finalSeed and finalSeed ~= "" then | |||
root:tag('div'):addClass('roster-subheader'):wikitext(finalSeed) | |||
end | end | ||
-- PLAYERS | -- PLAYERS | ||
local contentRows = root:tag('div'):addClass('roster-content-rows') | local contentRows = root:tag('div'):addClass('roster-content-rows') | ||
| Line 49: | Line 63: | ||
local playerCount = 0 | local playerCount = 0 | ||
for _, pl in ipairs(players) do if pl and pl ~= "" then playerCount = playerCount + 1 end end | for _, pl in ipairs(players) do if pl and pl ~= "" then playerCount = playerCount + 1 end end | ||
local playerInner = contentRows:tag('div'):addClass('roster-players-inner'):addClass('count-' .. playerCount) | local playerInner = contentRows:tag('div'):addClass('roster-players-inner'):addClass('count-' .. playerCount) | ||
for _, pl in ipairs(players) do | for _, pl in ipairs(players) do | ||
| Line 56: | Line 70: | ||
end | end | ||
end | end | ||
-- STAFF | -- STAFF | ||
if (data.coach and data.coach ~= "") or (data.analyst and data.analyst ~= "") then | if (data.coach and data.coach ~= "") or (data.analyst and data.analyst ~= "") then | ||
local staffInner = contentRows:tag('div'):addClass('roster-staff-inner') | local staffInner = contentRows:tag('div'):addClass('roster-staff-inner') | ||
if data.coach and data.coach ~= "" then | if data.coach and data.coach ~= "" then staffInner:tag('div'):addClass('roster-row staff'):wikitext('C: [[' .. data.coach .. ']]') end | ||
if data.analyst and data.analyst ~= "" then staffInner:tag('div'):addClass('roster-row staff'):wikitext('A: [[' .. data.analyst .. ']]') end | |||
if data.analyst and data.analyst ~= "" then | |||
end | end | ||
return tostring(root) | return tostring(root) | ||
end | end | ||
-- PUBLIC 1: | -- PUBLIC 1: ENTRY MODULE | ||
function p. | function p.entry(frame) | ||
local args = frame:getParent().args | |||
local count = tonumber(args.count) or 20 | |||
local tournamentName = getTournamentName(args) | |||
for i = 1, count do | for i = 1, count do | ||
local prefix = 't' .. i | local prefix = 't' .. i | ||
local team = args[prefix] | local team = args[prefix] | ||
if team and team ~= "" then | if team and team ~= "" then | ||
if cargo and cargo.store then | if cargo and cargo.store then | ||
cargo.store("Tournament_Teams", { | cargo.store("Tournament_Teams", { | ||
tournament = tournamentName, | tournament = tournamentName, | ||
team = team, | team = team, | ||
display_name = args[prefix .. 'name'], | |||
image = args[prefix .. 'img'], | |||
image_dark = args[prefix .. 'imgdark'], | |||
seeding = args[prefix .. 'seed'], | seeding = args[prefix .. 'seed'], | ||
p1 = args[prefix .. 'p1'], | p1 = args[prefix .. 'p1'], | ||
| Line 104: | Line 108: | ||
analyst = args[prefix .. 'a'] | analyst = args[prefix .. 'a'] | ||
}) | }) | ||
end | |||
end | |||
end | |||
return "<div style='display:none;'>Roster Data Saved Successfully.</div>" | |||
end | |||
-- PUBLIC 2: DISPLAY MODULE | |||
function p.display(frame) | |||
local args = frame:getParent().args | |||
local tournamentName = getTournamentName(args) | |||
local count = tonumber(args.count) or 24 | |||
-- 1. Gather Requested Teams | |||
local requestedTeams = {} | |||
local orderedRequests = {} | |||
for i = 1, count do | |||
local team = args['t' .. i] | |||
if team and team ~= "" then | |||
local cleanTeam = sqlEscape(team) | |||
table.insert(requestedTeams, "'" .. cleanTeam .. "'") | |||
table.insert(orderedRequests, { name = team, seed = args['t' .. i .. 'seed'] }) | |||
end | |||
end | |||
if #requestedTeams == 0 then return "" end | |||
local teamListSql = table.concat(requestedTeams, ", ") | |||
-- 2. MEMORY MAP A: Fetch Rosters (Tournament Specific) | |||
local rosterDb = {} | |||
if cargo and cargo.query then | |||
local rResults = cargo.query( | |||
"Tournament_Teams", | |||
"team, display_name, image, image_dark, seeding, p1, p2, p3, p4, p5, p6, coach, analyst", | |||
{ where = "tournament='" .. sqlEscape(tournamentName) .. "' AND team IN (" .. teamListSql .. ")", limit = count } | |||
) | |||
for _, row in ipairs(rResults) do | |||
rosterDb[row.team] = row | |||
end | |||
end | |||
-- 3. MEMORY MAP B: Fetch Master Logos (Global Teams Table) | |||
-- FIXED: We now query 'name' instead of '_pageName' to avoid underscore mismatches | |||
local masterDb = {} | |||
if cargo and cargo.query then | |||
local mResults = cargo.query( | |||
"Teams", | |||
"name, image, image_dark", | |||
{ where = "name IN (" .. teamListSql .. ")", limit = count } | |||
) | |||
for _, row in ipairs(mResults) do | |||
masterDb[row.name] = row | |||
end | |||
end | |||
-- 4. BUILD HTML | |||
local container = html.create('div') | |||
:addClass('participant-group-container') | |||
:css('display', 'flex') | |||
:css('flex-wrap', 'wrap') | |||
:css('gap', '15px') | |||
:css('justify-content', 'center') | |||
for _, req in ipairs(orderedRequests) do | |||
local teamName = req.name | |||
local rosterData = rosterDb[teamName] or { team = teamName } | |||
-- Merge Master Logos | |||
if masterDb[teamName] then | |||
-- 1. If DB has specific image set, use it | |||
if masterDb[teamName].image and masterDb[teamName].image ~= "" then | |||
rosterData.masterImg = masterDb[teamName].image | |||
else | |||
-- 2. If DB exists but field is blank, assume TeamName.png (Instead of Shield) | |||
rosterData.masterImg = teamName .. ".png" | |||
end | end | ||
-- | -- Dark Mode Logic | ||
if masterDb[teamName].image_dark and masterDb[teamName].image_dark ~= "" then | |||
rosterData.masterImgDark = masterDb[teamName].image_dark | |||
else | |||
rosterData.masterImgDark = rosterData.masterImg -- Fallback to light | |||
end | |||
end | end | ||
rosterData.entryImg = rosterData.image | |||
rosterData.entryImgDark = rosterData.image_dark | |||
rosterData.displayName = rosterData.display_name | |||
container:wikitext(buildCard(rosterData, req.seed)) | |||
end | end | ||
return | return tostring(container) | ||
end | end | ||
return p | return p | ||
Latest revision as of 02:13, 3 March 2026
Documentation for this module may be created at Module:Participant/doc
local p = {}
local html = mw.html
local cargo = mw.ext.cargo
local function sqlEscape(s)
if not s then return "" end
s = s:gsub("\\", "\\\\")
s = s:gsub("'", "\\'")
return s
end
-- HELPER: Smart Tournament Name Detection
local function getTournamentName(args)
if args.tournament and args.tournament ~= "" then return args.tournament end
local pageTitle = mw.title.getCurrentTitle().text
local parts = mw.text.split(pageTitle, '/')
if parts[2] == "Tournaments" and parts[3] then return parts[3] end
return mw.title.getCurrentTitle().baseText
end
-- INTERNAL: Builds the HTML for a single card
local function buildCard(data, seedOverride)
local root = html.create('div'):addClass('roster-card')
-- HEADER
local header = root:tag('div'):addClass('roster-header')
local headerContent = header:tag('div'):addClass('header-content')
-- LOGO LOGIC
-- Priority: 1. Tournament Entry Custom Logo -> 2. Master DB Custom Logo -> 3. Master DB Default Name -> 4. Shield
local lightLogo = "Shield_team.png"
local darkLogo = "Shield_team_dark.png"
-- Check Entry (Tournament specific) Override first
if data.entryImg and data.entryImg ~= "" then
lightLogo = data.entryImg
darkLogo = (data.entryImgDark and data.entryImgDark ~= "") and data.entryImgDark or lightLogo
-- Check Master DB
elseif data.masterImg and data.masterImg ~= "" then
lightLogo = data.masterImg
darkLogo = (data.masterImgDark and data.masterImgDark ~= "") and data.masterImgDark or lightLogo
end
local logoDiv = headerContent:tag('div'):addClass('roster-logo')
logoDiv:tag('div'):addClass('logo-lightmode'):wikitext('[[File:' .. lightLogo .. '|link=]]')
logoDiv:tag('div'):addClass('logo-darkmode'):wikitext('[[File:' .. darkLogo .. '|link=]]')
-- NAME LOGIC
local displayName = data.displayName
if not displayName or displayName == "" then displayName = data.team end
headerContent:tag('div'):addClass('roster-name'):wikitext('[[' .. data.team .. '|' .. displayName .. ']]')
-- SEEDING
local finalSeed = seedOverride
if not finalSeed or finalSeed == "" then finalSeed = data.seeding end
if finalSeed and finalSeed ~= "" then
root:tag('div'):addClass('roster-subheader'):wikitext(finalSeed)
end
-- PLAYERS
local contentRows = root:tag('div'):addClass('roster-content-rows')
local players = {data.p1, data.p2, data.p3, data.p4, data.p5, data.p6}
local playerCount = 0
for _, pl in ipairs(players) do if pl and pl ~= "" then playerCount = playerCount + 1 end end
local playerInner = contentRows:tag('div'):addClass('roster-players-inner'):addClass('count-' .. playerCount)
for _, pl in ipairs(players) do
if pl and pl ~= "" then
playerInner:tag('div'):addClass('roster-row player'):wikitext('[[' .. pl .. ']]')
end
end
-- STAFF
if (data.coach and data.coach ~= "") or (data.analyst and data.analyst ~= "") then
local staffInner = contentRows:tag('div'):addClass('roster-staff-inner')
if data.coach and data.coach ~= "" then staffInner:tag('div'):addClass('roster-row staff'):wikitext('C: [[' .. data.coach .. ']]') end
if data.analyst and data.analyst ~= "" then staffInner:tag('div'):addClass('roster-row staff'):wikitext('A: [[' .. data.analyst .. ']]') end
end
return tostring(root)
end
-- PUBLIC 1: ENTRY MODULE
function p.entry(frame)
local args = frame:getParent().args
local count = tonumber(args.count) or 20
local tournamentName = getTournamentName(args)
for i = 1, count do
local prefix = 't' .. i
local team = args[prefix]
if team and team ~= "" then
if cargo and cargo.store then
cargo.store("Tournament_Teams", {
tournament = tournamentName,
team = team,
display_name = args[prefix .. 'name'],
image = args[prefix .. 'img'],
image_dark = args[prefix .. 'imgdark'],
seeding = args[prefix .. 'seed'],
p1 = args[prefix .. 'p1'],
p2 = args[prefix .. 'p2'],
p3 = args[prefix .. 'p3'],
p4 = args[prefix .. 'p4'],
p5 = args[prefix .. 'p5'],
p6 = args[prefix .. 'p6'],
coach = args[prefix .. 'c'],
analyst = args[prefix .. 'a']
})
end
end
end
return "<div style='display:none;'>Roster Data Saved Successfully.</div>"
end
-- PUBLIC 2: DISPLAY MODULE
function p.display(frame)
local args = frame:getParent().args
local tournamentName = getTournamentName(args)
local count = tonumber(args.count) or 24
-- 1. Gather Requested Teams
local requestedTeams = {}
local orderedRequests = {}
for i = 1, count do
local team = args['t' .. i]
if team and team ~= "" then
local cleanTeam = sqlEscape(team)
table.insert(requestedTeams, "'" .. cleanTeam .. "'")
table.insert(orderedRequests, { name = team, seed = args['t' .. i .. 'seed'] })
end
end
if #requestedTeams == 0 then return "" end
local teamListSql = table.concat(requestedTeams, ", ")
-- 2. MEMORY MAP A: Fetch Rosters (Tournament Specific)
local rosterDb = {}
if cargo and cargo.query then
local rResults = cargo.query(
"Tournament_Teams",
"team, display_name, image, image_dark, seeding, p1, p2, p3, p4, p5, p6, coach, analyst",
{ where = "tournament='" .. sqlEscape(tournamentName) .. "' AND team IN (" .. teamListSql .. ")", limit = count }
)
for _, row in ipairs(rResults) do
rosterDb[row.team] = row
end
end
-- 3. MEMORY MAP B: Fetch Master Logos (Global Teams Table)
-- FIXED: We now query 'name' instead of '_pageName' to avoid underscore mismatches
local masterDb = {}
if cargo and cargo.query then
local mResults = cargo.query(
"Teams",
"name, image, image_dark",
{ where = "name IN (" .. teamListSql .. ")", limit = count }
)
for _, row in ipairs(mResults) do
masterDb[row.name] = row
end
end
-- 4. BUILD HTML
local container = html.create('div')
:addClass('participant-group-container')
:css('display', 'flex')
:css('flex-wrap', 'wrap')
:css('gap', '15px')
:css('justify-content', 'center')
for _, req in ipairs(orderedRequests) do
local teamName = req.name
local rosterData = rosterDb[teamName] or { team = teamName }
-- Merge Master Logos
if masterDb[teamName] then
-- 1. If DB has specific image set, use it
if masterDb[teamName].image and masterDb[teamName].image ~= "" then
rosterData.masterImg = masterDb[teamName].image
else
-- 2. If DB exists but field is blank, assume TeamName.png (Instead of Shield)
rosterData.masterImg = teamName .. ".png"
end
-- Dark Mode Logic
if masterDb[teamName].image_dark and masterDb[teamName].image_dark ~= "" then
rosterData.masterImgDark = masterDb[teamName].image_dark
else
rosterData.masterImgDark = rosterData.masterImg -- Fallback to light
end
end
rosterData.entryImg = rosterData.image
rosterData.entryImgDark = rosterData.image_dark
rosterData.displayName = rosterData.display_name
container:wikitext(buildCard(rosterData, req.seed))
end
return tostring(container)
end
return p