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

Module:Participant: Difference between revisions

From eSportsAmaze
No edit summary
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 -- Load Cargo module
local cargo = mw.ext.cargo


-- Helper: Check file existence
local function sqlEscape(s)
local function fileExists(filename)
     if not s then return "" end
     return mw.title.new('File:' .. filename).exists
    s = s:gsub("\\", "\\\\")
    s = s:gsub("'", "\\'")
    return s
end
end


-- INTERNAL: The logic to build ONE card (Pure HTML)
-- HELPER: Smart Tournament Name Detection
local function buildCard(data)
local function getTournamentName(args)
     local team = data.team or ""
    if args.tournament and args.tournament ~= "" then return args.tournament end
     local seeding = data.seeding or ""
     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')
     local lightFile = team .. '.png'
     logoDiv:tag('div'):addClass('logo-lightmode'):wikitext('[[File:' .. lightLogo .. '|link=]]')
    local darkFile = team .. '_dark.png'
     logoDiv:tag('div'):addClass('logo-darkmode'):wikitext('[[File:' .. darkLogo .. '|link=]]')
   
 
    local lDiv = logoDiv:tag('div'):addClass('logo-lightmode')
    -- NAME LOGIC
    lDiv:wikitext(fileExists(lightFile) and ('[[File:'..lightFile..'|link=]]') or '[[File:Shield_team.png|link=]]')
    local displayName = data.displayName
      
     if not displayName or displayName == "" then displayName = data.team end
    local dDiv = logoDiv:tag('div'):addClass('logo-darkmode')
    headerContent:tag('div'):addClass('roster-name'):wikitext('[[' .. data.team .. '|' .. displayName .. ']]')
    if fileExists(darkFile) then
 
        dDiv:wikitext('[[File:'..darkFile..'|link=]]')
     -- SEEDING
     elseif fileExists(lightFile) then
    local finalSeed = seedOverride
        dDiv:wikitext('[[File:'..lightFile..'|link=]]')
    if not finalSeed or finalSeed == "" then finalSeed = data.seeding end
     else
    if finalSeed and finalSeed ~= "" then
         dDiv:wikitext('[[File:Shield_team_dark.png|link=]]')
         root:tag('div'):addClass('roster-subheader'):wikitext(finalSeed)
     end
     end
   
 
    -- Name
    headerContent:tag('div'):addClass('roster-name'):wikitext('[[' .. team .. ']]')
   
    -- Seeding
    if seeding ~= "" then
        root:tag('div'):addClass('roster-subheader'):wikitext(seeding)
    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
            staffInner:tag('div'):addClass('roster-row staff'):wikitext('C: [[' .. data.coach .. ']]')
         if data.analyst and data.analyst ~= "" then staffInner:tag('div'):addClass('roster-row staff'):wikitext('A: [[' .. data.analyst .. ']]') end
        end
         if data.analyst and data.analyst ~= "" then
            staffInner:tag('div'):addClass('roster-row staff'):wikitext('A: [[' .. data.analyst .. ']]')
        end
     end
     end
   
 
     return tostring(root)
     return tostring(root)
end
end


-- PUBLIC 1: Single Card (Old usage - Display Only)
-- PUBLIC 1: ENTRY MODULE
function p.card(frame)
function p.entry(frame)
     return buildCard(frame:getParent().args)
     local args = frame:getParent().args
end
    local count = tonumber(args.count) or 20
    local tournamentName = getTournamentName(args)


-- PUBLIC 2: Group (New usage - Store + Display)
function p.group(frame)
    local args = frame:getParent().args
    local count = tonumber(args.count) or 4
    local tournamentName = args.tournament or mw.title.getCurrentTitle().text
   
    local output = ""
   
     for i = 1, count do
     for i = 1, count do
         local prefix = 't' .. i -- e.g., t1, t2, t3
         local prefix = 't' .. i
         local team = args[prefix]
         local team = args[prefix]
       
         if team and team ~= "" then
         if team and team ~= "" then
            -- 1. Store in Cargo (Using Native Lua function)
             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
              
              
             -- 2. Build HTML
             -- Dark Mode Logic
             local cardData = {
             if masterDb[teamName].image_dark and masterDb[teamName].image_dark ~= "" then
                team = team,
                 rosterData.masterImgDark = masterDb[teamName].image_dark
                seeding = args[prefix .. 'seed'],
            else
                p1 = args[prefix .. 'p1'],
                 rosterData.masterImgDark = rosterData.masterImg -- Fallback to light
                p2 = args[prefix .. 'p2'],
             end
                 p3 = args[prefix .. 'p3'],
                p4 = args[prefix .. 'p4'],
                p5 = args[prefix .. 'p5'],
                p6 = args[prefix .. 'p6'],
                 coach = args[prefix .. 'c'],
                analyst = args[prefix .. 'a']
            }
             output = output .. buildCard(cardData)
         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 output
     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