Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.
Revision as of 08:07, 28 January 2026 by Esportsamaze (talk | contribs)

Documentation for this module may be created at Module:Player/doc

local p = {}
local cargo = mw.ext.cargo
local html = mw.html

-- ============================================================
-- HELPER FUNCTIONS
-- ============================================================

-- Currency Formatter
local function formatCurrency(amount)
    if not amount then return "0" end
    local n = tonumber(amount) or 0
    local formatted = tostring(n):reverse():gsub("(%d%d%d)(%d%d%d)","%1,%2"):reverse()
    return '<span class="indian-currency">₹ ' .. formatted .. '</span>'
end

-- Social Icons
local function getSocials(args)
    local container = html.create('div'):addClass('fib-socials')
    local hasSocials = false
    local platforms = {
        {arg='instagram', file='Icon_instagram.png'},
        {arg='twitter',   file='Icon_twitter.png'},
        {arg='youtube',   file='Icon_youtube.png'},
        {arg='discord',   file='Icon_discord.png'},
        {arg='facebook',  file='Icon_facebook.png'}
    }
    for _, p in ipairs(platforms) do
        if args[p.arg] and args[p.arg] ~= "" then
            hasSocials = true
            container:wikitext('[[File:' .. p.file .. '|24px|link=' .. args[p.arg] .. '|class=social-img]]')
        end
    end
    if hasSocials then return tostring(container) else return "" end
end

-- Get Rank
local function getKraftonRank(fullPageName)
    local results = cargo.query("Krafton_Rankings", "rank", { where = "name = '" .. fullPageName:gsub("'", "\\'") .. "' AND type='Player'", limit = 1 })
    if #results > 0 then return "#" .. results[1].rank else return "Unranked" end
end

-- ============================================================
-- MAIN 1: PLAYER INFOBOX (ROSTER-AWARE EARNINGS)
-- ============================================================
function p.infobox(frame)
    local args = frame:getParent().args
    
    -- Variables
    local fullPageName = mw.title.getCurrentTitle().text -- Players/Jonathan
    local displayName = args.id or mw.title.getCurrentTitle().subpageText -- Jonathan
    local image = args.image or ""
    
    local root = html.create('div'):addClass('flat-infobox')
    
    -- 1. Header
    root:tag('div'):addClass('fib-header')
        :tag('div'):addClass('fib-title'):wikitext(displayName)
    
    -- 2. Image
    local imgContainer = root:tag('div'):addClass('fib-image')
    if image ~= "" then
        imgContainer:wikitext('[[File:' .. image .. '|250px]]')
    else
        imgContainer:wikitext('[[File:Player_Placeholder.png|200px|link=]]')
    end
    
    -- [[ 3. ADVANCED EARNINGS CALCULATION ]]
    local totalEarnings = 0
    
    -- Escape names for SQL safety
    local sqlNameFull = fullPageName:gsub("'", "\\'")
    local sqlNameShort = displayName:gsub("'", "\\'")
    
    -- PART A: INDIVIDUAL AWARDS (Directly assigned to player in PrizeMoney)
    -- Logic: player field is NOT empty
    if cargo and cargo.query then
        local pWhere = string.format("(player = '%s' OR player = '%s')", sqlNameFull, sqlNameShort)
        local pResults = cargo.query("PrizeMoney", "SUM(prize)=total", { where = pWhere })
        if pResults and #pResults > 0 and pResults[1].total then
            totalEarnings = totalEarnings + (tonumber(pResults[1].total) or 0)
        end
    end
    
    -- PART B: TEAM WINNINGS (Verified via Roster)
    -- Logic: Join PrizeMoney (PM) with Tournament_Teams (TT)
    -- We verify the player was in p1, p2... p6 for that specific tournament & team.
    -- We filter PM to only include rows where 'player' is empty (Team Prize) to avoid double counting Part A.
    if cargo and cargo.query then
        local tables = "PrizeMoney=PM, Tournament_Teams=TT"
        local fields = "SUM(PM.prize)=roster_total"
        local joinOn = "PM.tournament = TT.tournament AND PM.team = TT.team"
        
        -- The WHERE clause checks if player is in any roster slot
        local rosterCheck = string.format(
            "(TT.p1='%s' OR TT.p1='%s' OR TT.p2='%s' OR TT.p2='%s' OR TT.p3='%s' OR TT.p3='%s' OR TT.p4='%s' OR TT.p4='%s' OR TT.p5='%s' OR TT.p5='%s' OR TT.p6='%s' OR TT.p6='%s')",
            sqlNameFull, sqlNameShort, sqlNameFull, sqlNameShort, sqlNameFull, sqlNameShort, 
            sqlNameFull, sqlNameShort, sqlNameFull, sqlNameShort, sqlNameFull, sqlNameShort
        )
        
        -- Combine: (Player in Roster) AND (Prize is for Team)
        local whereClause = rosterCheck .. " AND (PM.player='' OR PM.player IS NULL)"
        
        local tResults = cargo.query(tables, fields, { joinOn = joinOn, where = whereClause })
        
        if tResults and #tResults > 0 and tResults[1].roster_total then
            totalEarnings = totalEarnings + (tonumber(tResults[1].roster_total) or 0)
        end
    end

    -- 4. Status & Rank Grid
    local statusColor = "#333"
    local statusText = args.status or "Active"
    if args.status then
        local s = args.status:lower()
        if s == "active" then statusColor = "#16a34a"
        elseif s == "inactive" or s == "banned" or s == "retired" then statusColor = "#dc2626"
        end
    end
    
    local grid1 = root:tag('div'):addClass('fib-grid')
    grid1:tag('div'):addClass('fib-cell'):tag('div'):addClass('fib-label-sm'):wikitext('Status'):done():tag('div'):addClass('fib-value-sm'):css('color', statusColor):wikitext(statusText):done()
    grid1:tag('div'):addClass('fib-cell'):tag('div'):addClass('fib-label-sm'):wikitext('Krafton Rank'):done():tag('div'):addClass('fib-value-sm'):wikitext(getKraftonRank(fullPageName)):done()

    -- 5. Role & Nation Grid
    local grid2 = root:tag('div'):addClass('fib-grid')
    grid2:tag('div'):addClass('fib-cell'):tag('div'):addClass('fib-label-sm'):wikitext('Nationality'):done():tag('div'):addClass('fib-value-sm'):wikitext(args.nationality or 'India'):done()
    grid2:tag('div'):addClass('fib-cell'):tag('div'):addClass('fib-label-sm'):wikitext('Role'):done():tag('div'):addClass('fib-value-sm'):wikitext(args.role or 'Player'):done()

    -- 6. Earnings (Highlight)
    if totalEarnings > 0 then
        root:tag('div'):addClass('fib-prize')
            :tag('div'):addClass('fib-label-sm'):wikitext('Total Winnings'):done()
            :tag('div'):addClass('fib-prize-val'):wikitext(formatCurrency(totalEarnings)):done()
    end
    
    -- 7. Info List
    local list = root:tag('div'):addClass('fib-list')
    local function addRow(label, value)
        if value and value ~= "" then
            list:tag('div'):addClass('fib-row'):tag('div'):addClass('fib-label'):wikitext(label):done():tag('div'):addClass('fib-data'):wikitext(value):done()
        end
    end
    
    addRow('Real Name', args.real_name)
    addRow('Born', args.birth_date)
    if args.current_team then
        addRow('Current Team', '[[' .. args.current_team .. ']]') 
    end
    addRow('Game', args.game or "BGMI")

    -- 8. Team History (Revised Visuals)
    local history = cargo.query("Player_Former_Teams", "team, join_date, leave_date", { 
        where = "player_id = '" .. fullPageName:gsub("'", "\\'") .. "'",
        orderBy = "join_date DESC",
        limit = 10 
    })
    
    if #history > 0 then
        list:tag('div')
            :addClass('fib-header')
            :css('font-size','0.95em')
            :css('padding','10px')
            :css('margin-top','15px')
            :css('border-radius','6px')
            :wikitext('Team History')
        
        local histTable = list:tag('table')
            :css('width','100%')
            :css('font-size','0.9em')
            :css('border-collapse','collapse')
            :css('margin-top','5px')
        
        for _, hRow in ipairs(history) do
            local tr = histTable:tag('tr'):css('border-bottom','1px solid #e2e8f0')
            tr:tag('td')
                :css('padding','8px 4px')
                :css('font-weight','600')
                :wikitext('[[' .. hRow.team .. ']]')
            
            local dates = (hRow.join_date and mw.getContentLanguage():formatDate('M y', hRow.join_date) or '?') .. ' – ' .. (hRow.leave_date and mw.getContentLanguage():formatDate('M y', hRow.leave_date) or 'Now')
            tr:tag('td')
                :css('text-align','right')
                :css('padding','8px 4px')
                :css('color','#64748b')
                :wikitext(dates)
        end
    else
        -- Fallback for Short Name history
        local historyShort = cargo.query("Player_Former_Teams", "team, join_date, leave_date", { 
            where = "player_id = '" .. displayName:gsub("'", "\\'") .. "'",
            orderBy = "join_date DESC",
            limit = 10 
        })
        if #historyShort > 0 then
            list:tag('div'):addClass('fib-header'):css('font-size','0.95em'):css('padding','10px'):css('margin-top','15px'):css('border-radius','6px'):wikitext('Team History')
            local histTable = list:tag('table'):css('width','100%'):css('font-size','0.9em'):css('border-collapse','collapse'):css('margin-top','5px')
            for _, hRow in ipairs(historyShort) do
                local tr = histTable:tag('tr'):css('border-bottom','1px solid #e2e8f0')
                tr:tag('td'):css('padding','8px 4px'):css('font-weight','600'):wikitext('[[' .. hRow.team .. ']]')
                local dates = (hRow.join_date and mw.getContentLanguage():formatDate('M y', hRow.join_date) or '?') .. ' – ' .. (hRow.leave_date and mw.getContentLanguage():formatDate('M y', hRow.leave_date) or 'Now')
                tr:tag('td'):css('text-align','right'):css('padding','8px 4px'):css('color','#64748b'):wikitext(dates)
            end
        end
    end

    -- 9. Socials
    root:wikitext(getSocials(args))

    return tostring(root)
end

-- ============================================================
-- MAIN 2: FORMER PLAYERS TABLE (For Team Pages)
-- ============================================================
function p.formerPlayers(frame)
    local args = frame:getParent().args
    local team = args.team or mw.title.getCurrentTitle().text
    
    local results = cargo.query("Player_Former_Teams, Players", "Player_Former_Teams.player_id=id, Players.real_name=Name, Player_Former_Teams.role=role, Player_Former_Teams.join_date=join_date, Player_Former_Teams.leave_date=leave_date", {
        joinOn = "Player_Former_Teams.player_id = Players._pageName",
        where = "Player_Former_Teams.team = '" .. team:gsub("'", "\\'") .. "' AND Player_Former_Teams.leave_date != ''",
        orderBy = "Player_Former_Teams.leave_date DESC"
    })
    
    local root = html.create('table'):addClass('wikitable flat-table sortable'):css('width','100%')
    local header = root:tag('tr')
    header:tag('th'):wikitext('ID'); header:tag('th'):wikitext('Name'); header:tag('th'):wikitext('Role'); header:tag('th'):wikitext('Duration')
    
    if #results > 0 then
        for _, row in ipairs(results) do
            local tr = root:tag('tr')
            tr:tag('td'):css('font-weight','bold'):wikitext('[[' .. row.id .. ']]')
            tr:tag('td'):wikitext(row.Name)
            tr:tag('td'):wikitext(row.role)
            local range = (row.join_date and mw.getContentLanguage():formatDate('M Y', row.join_date) or '?') .. ' – ' .. (row.leave_date and mw.getContentLanguage():formatDate('M Y', row.leave_date) or '?')
            tr:tag('td'):attr('data-sort-value', row.leave_date):wikitext(range)
        end
    else
        return '<div style="font-style:italic; color:#64748b; padding:10px;">No former players found for this team.</div>'
    end
    
    return tostring(root)
end

return p