Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Module:Standings: Difference between revisions

From eSportsAmaze
Created page with "local p = {} function p.main(frame) local args = frame:getParent().args local tournament = args.tournament or "" local stage = args.stage or "" local group = args.group or "" local qlimit = tonumber(args.qlimit) or tonumber(frame:callParserFunction('#var', 'qlimit')) or 8 local estart = tonumber(args.estart) or tonumber(frame:callParserFunction('#var', 'estart')) or 13 -- Query Cargo Data local tables = "StageStandings" local fields = "team, teamshort, matchesplayed, w..."
 
No edit summary
 
(36 intermediate revisions by the same user not shown)
Line 1: Line 1:
local p = {}
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
local function getTrophyIcon()
return '🏆'
end
local function buildLogo(teamName, tData, mData)
local lightFile = "Shield_team.png"
local darkFile = "Shield_team_dark.png"
if tData and tData.image and tData.image ~= "" then
lightFile = tData.image
darkFile = (tData.image_dark and tData.image_dark ~= "") and tData.image_dark or lightFile
elseif mData then
if mData.image and mData.image ~= "" then lightFile = mData.image else lightFile = teamName .. ".png" end
if mData.image_dark and mData.image_dark ~= "" then darkFile = mData.image_dark else darkFile = lightFile end
end
local container = html.create('span'):addClass('team-logo-wrapper')
container:tag('span'):addClass('logo-lightmode'):wikitext('[[File:' .. lightFile .. '|30px|link=|class=team-logo]]')
container:tag('span'):addClass('logo-darkmode'):wikitext('[[File:' .. darkFile .. '|30px|link=|class=team-logo]]')
return tostring(container)
end


function p.main(frame)
function p.main(frame)
local args = frame:getParent().args
local args = frame:getParent().args
local tournament = args.tournament or ""
local stage = args.stage or ""
local group = args.group or ""
local qlimit = tonumber(args.qlimit) or tonumber(frame:callParserFunction('#var', 'qlimit')) or 8
local estart = tonumber(args.estart) or tonumber(frame:callParserFunction('#var', 'estart')) or 13


-- Query Cargo Data
local tournament = args.tournament or mw.title.getCurrentTitle().text
local tables = "StageStandings"
local stage = args.stage
local fields = "team, teamshort, matchesplayed, wwcd, placepts, elimpts, totalpts, lastmatchrank"
local group = args.group
local queryArgs = {
local showgroup = (args.showgroup == 'true')
where = "tournament = '" .. tournament .. "' AND stage = '" .. stage .. "'",
 
orderBy = "totalpts DESC, wwcd DESC, placepts DESC, elimpts DESC, lastmatchrank ASC"
local matchlistStr = args.matchlist
}
local matchNumbers = {}
if matchlistStr and matchlistStr ~= "" then
local parts = mw.text.split(matchlistStr, ",")
for _, v in ipairs(parts) do
table.insert(matchNumbers, tonumber(mw.text.trim(v)))
end
else
local numMatches = tonumber(args.matches) or 6
local startMatch = tonumber(args.startmatch) or 1
local endMatch = startMatch + numMatches - 1
for i = startMatch, endMatch do
table.insert(matchNumbers, i)
end
end
 
local qtext = args.qtext
local q2text = args.q2text
local q3text = args.q3text
local etext = args.etext
local dtext = args.dtext
local ntext = args.ntext
 
local whereParts = {}
table.insert(whereParts, "tournament='" .. sqlEscape(tournament) .. "'")
if stage and stage ~= "" then table.insert(whereParts, "stage='" .. sqlEscape(stage) .. "'") end
if group and group ~= "" then table.insert(whereParts, "groupname='" .. sqlEscape(group) .. "'") end


if group ~= "" then
local rCols = ""
queryArgs.where = queryArgs.where .. " AND groupname = '" .. group .. "'"
for i=1,30 do rCols = rCols .. ", r" .. i end
 
local results = cargo.query("StageStandings",
"team, teamshort, groupname, totalpts, matchesplayed, wwcd, placepts, elimpts, result" .. rCols,
{
where = table.concat(whereParts, " AND "),
orderBy = "totalpts DESC, wwcd DESC, placepts DESC, elimpts DESC, lastmatchrank ASC",
limit = 100
})
 
if not results or #results == 0 then return html.create('div'):wikitext('No data found.'):css('color', 'red') end
 
local teamListQuoted = {}
for _, row in ipairs(results) do table.insert(teamListQuoted, "'" .. sqlEscape(row.team) .. "'") end
local teamSql = table.concat(teamListQuoted, ",")
 
local teamInfo = {}
if cargo and cargo.query then
local tResults = cargo.query("Tournament_Teams", "team, display_name, image, image_dark", { where = "tournament='" .. sqlEscape(tournament) .. "'", limit = 100 })
for _, row in ipairs(tResults) do teamInfo[row.team:lower()] = row end
end
end


local results = mw.ext.cargo.query(tables, fields, queryArgs)
local masterInfo = {}
if #teamListQuoted > 0 and cargo and cargo.query then
local mResults = cargo.query("Teams", "name, image, image_dark", { where = "name IN (" .. teamSql .. ")", limit = 100 })
for _, row in ipairs(mResults) do masterInfo[row.name:lower()] = row end
end


-- Build the Table
local container = html.create('div')
local root = mw.html.create('table')
root:addClass('match-card-table standings-table')
:css('width', '100%')
:css('border-collapse', 'collapse')


-- Header Row
local legend = container:tag('div'):addClass('standings-legend')
local header = root:tag('tr')
local function addLegendItem(colorCode, text, className)
header:tag('th'):css('width', '40px'):css('text-align', 'center'):wikitext('#')
if text and text ~= "" then
header:tag('th'):css('text-align', 'left'):wikitext('Team')
local item = legend:tag('div'):addClass('legend-item')
header:tag('th'):css('width', '50px'):css('text-align', 'center'):wikitext('MP')
item:tag('span'):addClass('legend-color ' .. className)
header:tag('th'):css('width', '50px'):css('text-align', 'center'):wikitext('WWCD')
item:tag('span'):addClass('legend-text'):wikitext(text)
header:tag('th'):addClass('nomobile'):css('width', '60px'):css('text-align', 'center'):wikitext('Place')
end
header:tag('th'):css('width', '60px'):css('text-align', 'center'):wikitext('Elims')
end
header:tag('th'):css('width', '70px'):css('text-align', 'center'):wikitext('Total')
addLegendItem('#28a745', qtext, 'qual-q'); addLegendItem('#007bff', q2text, 'qual-q2'); addLegendItem('#6f42c1', q3text, 'qual-q3')
addLegendItem('#dc3545', etext, 'qual-e'); addLegendItem('#343a40', dtext, 'qual-d'); addLegendItem('#adb5bd', ntext, 'qual-n')
 
local wrapper = container:tag('div'):addClass('standings-wrapper')
local tbl = wrapper:tag('table'):addClass('standings-card-table')
 
if showgroup then tbl:addClass('has-group-col') end
 
local header = tbl:tag('tr')
header:tag('th'):wikitext('#'):addClass('sticky-col sticky-1')
header:tag('th'):wikitext('TEAM'):addClass('sticky-col sticky-2')
 
if showgroup then header:tag('th'):wikitext('GRP'):addClass('grp-sticky') end
 
header:tag('th'):wikitext('M'):addClass('pc-only pc-sticky-1')
header:tag('th'):wikitext('WWCD'):addClass('pc-only pc-sticky-2')
header:tag('th'):wikitext('PLACE'):addClass('pc-only pc-sticky-3')
header:tag('th'):wikitext('ELIMS'):addClass('pc-only pc-sticky-4')
 
header:tag('th'):wikitext('M'):addClass('mobile-only')
header:tag('th'):wikitext('W'):addClass('mobile-only')
header:tag('th'):wikitext('P'):addClass('mobile-only')
header:tag('th'):wikitext('E'):addClass('mobile-only')
 
header:tag('th'):wikitext('PTS'):addClass('sticky-col sticky-3')
 
for _, mNum in ipairs(matchNumbers) do header:tag('th'):wikitext('M' .. mNum):addClass('match-col') end
 
if #matchNumbers == 0 then header:tag('th'):addClass('match-col') end


-- Data Rows
for i, row in ipairs(results) do
for i, row in ipairs(results) do
local rowclass = "qual-mid"
if i <= qlimit then
rowclass = "qual-yes"
elseif i >= estart then
rowclass = "qual-no"
end


local tr = root:tag('tr')
local tr = tbl:tag('tr'):addClass('standings-row')
tr:addClass('match-card-row ' .. rowclass)
 
local res = (row.result or ''):lower()
local statusClass = 'qual-default'
local tooltip = ''
if res == 'q' then statusClass = 'qual-q'; tooltip = qtext or 'Qualified'
elseif res == 'q2' then statusClass = 'qual-q2'; tooltip = q2text or 'Qualified'
elseif res == 'q3' then statusClass = 'qual-q3'; tooltip = q3text or 'Qualified'
elseif res == 'e' then statusClass = 'qual-e'; tooltip = etext or 'Eliminated'
elseif res == 'd' then statusClass = 'qual-d'; tooltip = dtext or 'Disqualified'
elseif res == 'n' then statusClass = 'qual-n'; tooltip = ntext or 'Inactive' end
 
tr:tag('td'):wikitext(i .. '.'):addClass('sticky-col sticky-1 ' .. statusClass):attr('title', tooltip)
 
local tData = teamInfo[row.team:lower()]
local mData = masterInfo[row.team:lower()]
local displayName = row.team
if tData and tData.display_name and tData.display_name ~= "" then displayName = tData.display_name end
 
local teamCell = tr:tag('td'):addClass('sticky-col sticky-2 team-name-cell')
teamCell:wikitext(buildLogo(row.team, tData, mData))
teamCell:tag('span'):addClass('pc-only'):wikitext('[[' .. row.team .. '|' .. displayName .. ']]')
teamCell:tag('span'):addClass('mobile-only'):wikitext('[[' .. row.team .. '|' .. (row.teamshort or displayName) .. ']]')
 
if showgroup then tr:tag('td'):wikitext(row.groupname or '-'):addClass('text-center font-weight-bold grp-sticky') end
 
tr:tag('td'):wikitext(row.matchesplayed):addClass('pc-only pc-sticky-1')
tr:tag('td'):wikitext(row.wwcd):addClass('pc-only pc-sticky-2')
tr:tag('td'):wikitext(row.placepts):addClass('pc-only pc-sticky-3')
tr:tag('td'):wikitext(row.elimpts):addClass('pc-only pc-sticky-4')
 
tr:tag('td'):wikitext(row.matchesplayed):addClass('mobile-only text-center')
tr:tag('td'):wikitext(row.wwcd):addClass('mobile-only text-center')
tr:tag('td'):wikitext(row.placepts):addClass('mobile-only text-center')
tr:tag('td'):wikitext(row.elimpts):addClass('mobile-only text-center')
 
tr:tag('td'):wikitext(row.totalpts):addClass('sticky-col sticky-3 total-points-cell')
 
for _, m in ipairs(matchNumbers) do
local raw = row['r' .. m]
local cell = tr:tag('td'):addClass('match-cell')


-- Rank Cell
if raw and raw ~= "" then
tr:tag('td'):addClass('rank-cell'):wikitext('')
local mRank, mPts
if raw:find(";") then local parts = mw.text.split(raw, ";"); mRank = tonumber(parts[1]); mPts = tonumber(parts[2]) else mPts = tonumber(raw) end


-- Team Cell
if mRank == 0 then cell:wikitext('-'):addClass('dim-text')
local teamCell = tr:tag('td'):addClass('team-cell')
elseif mRank == 1 then cell:wikitext(getTrophyIcon() .. ' <b>' .. (mPts or '') .. '</b>'):addClass('match-win')
teamCell:tag('span'):addClass('nomobile'):wikitext('[[' .. row.team .. ']]')
else cell:wikitext(mPts); if mRank then cell:tag('sub'):wikitext(mRank):addClass('pc-only') end end
teamCell:tag('span'):addClass('mobile-only'):wikitext('[[' .. row.team .. '|' .. row.teamshort .. ']]')


-- Data Cells
if mPts and mPts >= 15 and mRank ~= 0 then cell:addClass('high-score') end
tr:tag('td'):css('text-align', 'center'):wikitext(row.matchesplayed)
else cell:wikitext('-'):addClass('dim-text') end
tr:tag('td'):css('text-align', 'center'):wikitext(row.wwcd)
tr:tag('td'):addClass('nomobile'):css('text-align', 'center'):wikitext(row.placepts)
tr:tag('td'):css('text-align', 'center'):wikitext(row.elimpts)
tr:tag('td'):addClass('total-cell'):wikitext(row.totalpts)
end
end


return tostring(root)
if #matchNumbers == 0 then tr:tag('td'):addClass('match-cell') end
 
end
return tostring(container)
end
end


return p
return p

Latest revision as of 02:24, 3 March 2026

Documentation for this module may be created at Module:Standings/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

local function getTrophyIcon()
return '🏆'
end

local function buildLogo(teamName, tData, mData)
local lightFile = "Shield_team.png"
local darkFile = "Shield_team_dark.png"

if tData and tData.image and tData.image ~= "" then
lightFile = tData.image
darkFile = (tData.image_dark and tData.image_dark ~= "") and tData.image_dark or lightFile
elseif mData then
if mData.image and mData.image ~= "" then lightFile = mData.image else lightFile = teamName .. ".png" end
if mData.image_dark and mData.image_dark ~= "" then darkFile = mData.image_dark else darkFile = lightFile end
end

local container = html.create('span'):addClass('team-logo-wrapper')
container:tag('span'):addClass('logo-lightmode'):wikitext('[[File:' .. lightFile .. '|30px|link=|class=team-logo]]')
container:tag('span'):addClass('logo-darkmode'):wikitext('[[File:' .. darkFile .. '|30px|link=|class=team-logo]]')
return tostring(container)
end

function p.main(frame)
local args = frame:getParent().args

local tournament = args.tournament or mw.title.getCurrentTitle().text
local stage = args.stage
local group = args.group
local showgroup = (args.showgroup == 'true')

local matchlistStr = args.matchlist
local matchNumbers = {}
if matchlistStr and matchlistStr ~= "" then
local parts = mw.text.split(matchlistStr, ",")
for _, v in ipairs(parts) do
table.insert(matchNumbers, tonumber(mw.text.trim(v)))
end
else
local numMatches = tonumber(args.matches) or 6
local startMatch = tonumber(args.startmatch) or 1
local endMatch = startMatch + numMatches - 1
for i = startMatch, endMatch do
table.insert(matchNumbers, i)
end
end

local qtext = args.qtext
local q2text = args.q2text
local q3text = args.q3text
local etext = args.etext
local dtext = args.dtext
local ntext = args.ntext

local whereParts = {}
table.insert(whereParts, "tournament='" .. sqlEscape(tournament) .. "'")
if stage and stage ~= "" then table.insert(whereParts, "stage='" .. sqlEscape(stage) .. "'") end
if group and group ~= "" then table.insert(whereParts, "groupname='" .. sqlEscape(group) .. "'") end

local rCols = ""
for i=1,30 do rCols = rCols .. ", r" .. i end

local results = cargo.query("StageStandings", 
"team, teamshort, groupname, totalpts, matchesplayed, wwcd, placepts, elimpts, result" .. rCols, 
{
where = table.concat(whereParts, " AND "),
orderBy = "totalpts DESC, wwcd DESC, placepts DESC, elimpts DESC, lastmatchrank ASC",
limit = 100
})

if not results or #results == 0 then return html.create('div'):wikitext('No data found.'):css('color', 'red') end

local teamListQuoted = {}
for _, row in ipairs(results) do table.insert(teamListQuoted, "'" .. sqlEscape(row.team) .. "'") end
local teamSql = table.concat(teamListQuoted, ",")

local teamInfo = {}
if cargo and cargo.query then
local tResults = cargo.query("Tournament_Teams", "team, display_name, image, image_dark", { where = "tournament='" .. sqlEscape(tournament) .. "'", limit = 100 })
for _, row in ipairs(tResults) do teamInfo[row.team:lower()] = row end
end

local masterInfo = {}
if #teamListQuoted > 0 and cargo and cargo.query then
local mResults = cargo.query("Teams", "name, image, image_dark", { where = "name IN (" .. teamSql .. ")", limit = 100 })
for _, row in ipairs(mResults) do masterInfo[row.name:lower()] = row end
end

local container = html.create('div')

local legend = container:tag('div'):addClass('standings-legend')
local function addLegendItem(colorCode, text, className)
if text and text ~= "" then
local item = legend:tag('div'):addClass('legend-item')
item:tag('span'):addClass('legend-color ' .. className)
item:tag('span'):addClass('legend-text'):wikitext(text)
end
end
addLegendItem('#28a745', qtext, 'qual-q'); addLegendItem('#007bff', q2text, 'qual-q2'); addLegendItem('#6f42c1', q3text, 'qual-q3')
addLegendItem('#dc3545', etext, 'qual-e'); addLegendItem('#343a40', dtext, 'qual-d'); addLegendItem('#adb5bd', ntext, 'qual-n')

local wrapper = container:tag('div'):addClass('standings-wrapper')
local tbl = wrapper:tag('table'):addClass('standings-card-table')

if showgroup then tbl:addClass('has-group-col') end

local header = tbl:tag('tr')
header:tag('th'):wikitext('#'):addClass('sticky-col sticky-1')
header:tag('th'):wikitext('TEAM'):addClass('sticky-col sticky-2')

if showgroup then header:tag('th'):wikitext('GRP'):addClass('grp-sticky') end

header:tag('th'):wikitext('M'):addClass('pc-only pc-sticky-1')
header:tag('th'):wikitext('WWCD'):addClass('pc-only pc-sticky-2')
header:tag('th'):wikitext('PLACE'):addClass('pc-only pc-sticky-3')
header:tag('th'):wikitext('ELIMS'):addClass('pc-only pc-sticky-4')

header:tag('th'):wikitext('M'):addClass('mobile-only')
header:tag('th'):wikitext('W'):addClass('mobile-only')
header:tag('th'):wikitext('P'):addClass('mobile-only') 
header:tag('th'):wikitext('E'):addClass('mobile-only')

header:tag('th'):wikitext('PTS'):addClass('sticky-col sticky-3')

for _, mNum in ipairs(matchNumbers) do header:tag('th'):wikitext('M' .. mNum):addClass('match-col') end

if #matchNumbers == 0 then header:tag('th'):addClass('match-col') end

for i, row in ipairs(results) do

local tr = tbl:tag('tr'):addClass('standings-row')

local res = (row.result or ''):lower()
local statusClass = 'qual-default'
local tooltip = '' 
if res == 'q' then statusClass = 'qual-q'; tooltip = qtext or 'Qualified'
elseif res == 'q2' then statusClass = 'qual-q2'; tooltip = q2text or 'Qualified'
elseif res == 'q3' then statusClass = 'qual-q3'; tooltip = q3text or 'Qualified'
elseif res == 'e' then statusClass = 'qual-e'; tooltip = etext or 'Eliminated'
elseif res == 'd' then statusClass = 'qual-d'; tooltip = dtext or 'Disqualified'
elseif res == 'n' then statusClass = 'qual-n'; tooltip = ntext or 'Inactive' end

tr:tag('td'):wikitext(i .. '.'):addClass('sticky-col sticky-1 ' .. statusClass):attr('title', tooltip)

local tData = teamInfo[row.team:lower()]
local mData = masterInfo[row.team:lower()]
local displayName = row.team
if tData and tData.display_name and tData.display_name ~= "" then displayName = tData.display_name end

local teamCell = tr:tag('td'):addClass('sticky-col sticky-2 team-name-cell')
teamCell:wikitext(buildLogo(row.team, tData, mData))
teamCell:tag('span'):addClass('pc-only'):wikitext('[[' .. row.team .. '|' .. displayName .. ']]')
teamCell:tag('span'):addClass('mobile-only'):wikitext('[[' .. row.team .. '|' .. (row.teamshort or displayName) .. ']]')

if showgroup then tr:tag('td'):wikitext(row.groupname or '-'):addClass('text-center font-weight-bold grp-sticky') end

tr:tag('td'):wikitext(row.matchesplayed):addClass('pc-only pc-sticky-1')
tr:tag('td'):wikitext(row.wwcd):addClass('pc-only pc-sticky-2')
tr:tag('td'):wikitext(row.placepts):addClass('pc-only pc-sticky-3')
tr:tag('td'):wikitext(row.elimpts):addClass('pc-only pc-sticky-4')

tr:tag('td'):wikitext(row.matchesplayed):addClass('mobile-only text-center')
tr:tag('td'):wikitext(row.wwcd):addClass('mobile-only text-center')
tr:tag('td'):wikitext(row.placepts):addClass('mobile-only text-center')
tr:tag('td'):wikitext(row.elimpts):addClass('mobile-only text-center')

tr:tag('td'):wikitext(row.totalpts):addClass('sticky-col sticky-3 total-points-cell')

for _, m in ipairs(matchNumbers) do
local raw = row['r' .. m]
local cell = tr:tag('td'):addClass('match-cell')

if raw and raw ~= "" then
local mRank, mPts
if raw:find(";") then local parts = mw.text.split(raw, ";"); mRank = tonumber(parts[1]); mPts = tonumber(parts[2]) else mPts = tonumber(raw) end

if mRank == 0 then cell:wikitext('-'):addClass('dim-text')
elseif mRank == 1 then cell:wikitext(getTrophyIcon() .. ' <b>' .. (mPts or '') .. '</b>'):addClass('match-win')
else cell:wikitext(mPts); if mRank then cell:tag('sub'):wikitext(mRank):addClass('pc-only') end end

if mPts and mPts >= 15 and mRank ~= 0 then cell:addClass('high-score') end
else cell:wikitext('-'):addClass('dim-text') end
end

if #matchNumbers == 0 then tr:tag('td'):addClass('match-cell') end

end
return tostring(container)
end

return p