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

Module:PlayerDashboard: Difference between revisions

From eSportsAmaze
Created page with "-- Module:PlayerDashboard -- Full-width player dashboard. Reads all data from existing Cargo tables. -- No changes to any existing module or template needed. local p = {} local cargo = mw.ext.cargo local html = mw.html local lang = mw.getContentLanguage() local function esc(s) if not s then return "" end return s:gsub("\\","\\\\"):gsub("'","\\'") end local function fmtCurrency(n) if not n or n == 0 then return "—" end local s = tostring(math.fl..."
 
No edit summary
Line 262: Line 262:
             tr:tag('div'):addClass('pd-team-logo')
             tr:tag('div'):addClass('pd-team-logo')
                 :wikitext((h.team or "?"):sub(1,3):upper())
                 :wikitext((h.team or "?"):sub(1,3):upper())
             tr:tag('div'):addClass('pd-team-name'):wikitext('[['..(h.teamor"")..']]')
             tr:tag('div'):addClass('pd-team-name'):wikitext('[['.. (h.team or "") ..']]')
             tr:tag('div'):addClass('pd-team-dates')
             tr:tag('div'):addClass('pd-team-dates')
                 :wikitext(fmtDate(h.join_date) .. ' – ' ..
                 :wikitext(fmtDate(h.join_date) .. ' – ' ..

Revision as of 03:07, 7 March 2026

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

-- Module:PlayerDashboard
-- Full-width player dashboard. Reads all data from existing Cargo tables.
-- No changes to any existing module or template needed.

local p     = {}
local cargo = mw.ext.cargo
local html  = mw.html
local lang  = mw.getContentLanguage()

local function esc(s)
    if not s then return "" end
    return s:gsub("\\","\\\\"):gsub("'","\\'")
end

local function fmtCurrency(n)
    if not n or n == 0 then return "—" end
    local s = tostring(math.floor(n))
    local l3 = s:sub(-3)
    local rest = s:sub(1,-4)
    local fmt = rest:reverse():gsub("(%d%d)","%1,"):reverse()
    if fmt ~= "" then l3 = "," .. l3 end
    return "₹ " .. fmt .. l3
end

local function fmtDate(d)
    if not d or d == "" then return "?" end
    return lang:formatDate("M y", d)
end

local function statusColor(s)
    s = (s or ""):lower()
    if s == "active"   then return "#22c55e", "rgba(34,197,94,.15)",  "rgba(34,197,94,.3)"  end
    if s == "inactive" then return "#f59e0b", "rgba(245,158,11,.15)", "rgba(245,158,11,.3)" end
    if s == "retired"  then return "#94a3b8", "rgba(148,163,184,.15)","rgba(148,163,184,.3)"end
    if s == "banned"   then return "#ef4444", "rgba(239,68,68,.15)",   "rgba(239,68,68,.3)"  end
    return "#94a3b8", "rgba(148,163,184,.15)", "rgba(148,163,184,.3)"
end

function p.main(frame)
    local pageName   = mw.title.getCurrentTitle().text
    local sqlPage    = esc(pageName)

    -- ── 1. Fetch player row from Players table ──────────────
    local pRows = cargo.query("Players",
        "id,real_name,image,current_team,nationality,status,game,birth_date,role," ..
        "instagram,youtube,twitter,discord,facebook",
        { where = "_pageName='" .. sqlPage .. "'", limit = 1 })
    local pl = (pRows and #pRows > 0) and pRows[1] or {}
    local displayName = pl.id or mw.title.getCurrentTitle().subpageText

    -- ── 2. Krafton rank ─────────────────────────────────────
    local rankVal = "Unranked"
    local rRows = cargo.query("Krafton_Rankings", "rank", {
        where = string.format("(name='%s' OR name='%s') AND type='Player'",
            sqlPage, esc(displayName)), limit = 1 })
    if rRows and #rRows > 0 then rankVal = "#" .. rRows[1].rank end

    -- ── 3. Earnings ──────────────────────────────────────────
    local indEarnings, teamEarnings = 0, 0
    local pWhere = string.format("(player='%s' OR player='%s')", sqlPage, esc(displayName))
    local eRows = cargo.query("PrizeMoney", "SUM(prize)=total", { where = pWhere })
    if eRows and #eRows > 0 then indEarnings = tonumber(eRows[1].total) or 0 end

    local participation = cargo.query("Tournament_Teams", "tournament,team", {
        where = string.format(
            "p1='%s' OR p1='%s' OR p2='%s' OR p2='%s' OR " ..
            "p3='%s' OR p3='%s' OR p4='%s' OR p4='%s' OR " ..
            "p5='%s' OR p5='%s' OR p6='%s' OR p6='%s'",
            sqlPage,esc(displayName), sqlPage,esc(displayName),
            sqlPage,esc(displayName), sqlPage,esc(displayName),
            sqlPage,esc(displayName), sqlPage,esc(displayName)),
        limit = 500 })

    if participation and #participation > 0 then
        local conds = {}
        for _, r in ipairs(participation) do
            if r.tournament and r.team then
                table.insert(conds, string.format(
                    "(tournament='%s' AND team='%s')", esc(r.tournament), esc(r.team)))
            end
        end
        if #conds > 0 then
            local tPrizes = cargo.query("PrizeMoney", "SUM(prize)=team_total", {
                where = "("..table.concat(conds," OR ")..")" ..
                        " AND (player='' OR player IS NULL)" })
            if tPrizes and #tPrizes > 0 then
                teamEarnings = tonumber(tPrizes[1].team_total) or 0
            end
        end
    end
    local totalEarnings = indEarnings + teamEarnings

    -- ── 4. Team history ──────────────────────────────────────
    local teamHist = cargo.query("Player_Former_Teams",
        "team,join_date,leave_date",
        { where = "player_id='"..sqlPage.."'", orderBy="join_date DESC", limit=15 })
    if #teamHist == 0 then
        teamHist = cargo.query("Player_Former_Teams",
            "team,join_date,leave_date",
            { where="player_id='"..esc(displayName).."'", orderBy="join_date DESC", limit=15 })
    end

    -- ── 5. Tournament history ─────────────────────────────────
    -- For each tournament the player appeared in, find their team's
    -- final placement from StageStandings and prize from PrizeMoney
    local tournHistory = {}
    local seenTournStage = {}

    if participation and #participation > 0 then
        local tournTeamConds = {}
        for _, r in ipairs(participation) do
            if r.tournament and r.team then
                table.insert(tournTeamConds, string.format(
                    "(tournament='%s' AND team='%s')", esc(r.tournament), esc(r.team)))
            end
        end
        if #tournTeamConds > 0 then
            local standings = cargo.query("StageStandings",
                "tournament,stage,team,totalpts,wwcd,elimpts,result",
                { where = table.concat(tournTeamConds," OR "),
                  orderBy = "tournament DESC", limit = 200 })

            for _, row in ipairs(standings) do
                local key = row.tournament .. "|" .. row.team
                -- Keep only the last stage per tournament per team (Finals > Semis > etc.)
                if not seenTournStage[key] then
                    seenTournStage[key] = true
                    -- Get rank within that stage
                    local rankRows = cargo.query("StageStandings",
                        "COUNT(team)=cnt",
                        { where = string.format(
                            "tournament='%s' AND stage='%s' AND totalpts >= %s",
                            esc(row.tournament), esc(row.stage),
                            tonumber(row.totalpts) or 0) })
                    local place = (rankRows and #rankRows > 0)
                        and (tonumber(rankRows[1].cnt) or 99) or 99

                    -- Prize for this tournament + team
                    local prizeRows = cargo.query("PrizeMoney", "SUM(prize)=total", {
                        where = string.format(
                            "tournament='%s' AND team='%s' AND (player='' OR player IS NULL)",
                            esc(row.tournament), esc(row.team)) })
                    local prize = (prizeRows and #prizeRows > 0)
                        and (tonumber(prizeRows[1].total) or 0) or 0

                    table.insert(tournHistory, {
                        tournament = row.tournament,
                        stage      = row.stage,
                        team       = row.team,
                        place      = place,
                        result     = row.result or "",
                        prize      = prize
                    })
                end
            end
        end
    end

    -- ── Build HTML ────────────────────────────────────────────
    local sc, sbg, sborder = statusColor(pl.status)
    local initials = displayName:sub(1,2):upper()

    local root = html.create('div'):addClass('pd-dashboard')

    -- ── HERO ─────────────────────────────────────────────────
    local hero = root:tag('div'):addClass('pd-hero')

    local photoDiv = hero:tag('div'):addClass('pd-hero-photo')
    if pl.image and pl.image ~= "" then
        photoDiv:wikitext('[[File:'..pl.image..'|120px|link=]]')
    else
        photoDiv:wikitext(initials)
    end

    local heroInfo = hero:tag('div'):addClass('pd-hero-info')
    heroInfo:tag('div'):addClass('pd-hero-name'):wikitext(displayName)
    if pl.real_name and pl.real_name ~= "" then
        heroInfo:tag('div'):addClass('pd-hero-realname'):wikitext(pl.real_name)
    end

    local tags = heroInfo:tag('div'):addClass('pd-hero-tags')
    if pl.status and pl.status ~= "" then
        tags:tag('span'):addClass('pd-tag')
            :css('color', sc):css('background', sbg):css('border', '1px solid '..sborder)
            :wikitext('● ' .. pl.status)
    end
    if pl.role and pl.role ~= "" then
        tags:tag('span'):addClass('pd-tag pd-tag-role'):wikitext(pl.role)
    end
    if pl.game and pl.game ~= "" then
        tags:tag('span'):addClass('pd-tag pd-tag-game'):wikitext(pl.game)
    end
    if pl.nationality and pl.nationality ~= "" then
        tags:tag('span'):addClass('pd-tag pd-tag-nat'):wikitext(pl.nationality)
    end

    if rankVal ~= "Unranked" then
        heroInfo:tag('div'):addClass('pd-rank-chip')
            :tag('span'):wikitext('Krafton Rank'):done()
            :tag('b'):wikitext(rankVal)
    end

    if totalEarnings > 0 then
        local heroRight = hero:tag('div'):addClass('pd-hero-right')
        heroRight:tag('div'):addClass('pd-earnings-label'):wikitext('Approx. Earnings')
        heroRight:tag('div'):addClass('pd-earnings-val'):wikitext(fmtCurrency(totalEarnings))
        local bd = heroRight:tag('div'):addClass('pd-earnings-breakdown')
        bd:tag('div'):addClass('pd-earn-sub')
            :tag('div'):addClass('pd-earn-sub-label'):wikitext('Team'):done()
            :tag('div'):addClass('pd-earn-sub-val'):wikitext(fmtCurrency(teamEarnings))
        bd:tag('div'):addClass('pd-earn-sub')
            :tag('div'):addClass('pd-earn-sub-label'):wikitext('Individual'):done()
            :tag('div'):addClass('pd-earn-sub-val'):wikitext(fmtCurrency(indEarnings))
    end

    -- ── BODY ─────────────────────────────────────────────────
    local body = root:tag('div'):addClass('pd-body')

    -- Left panel
    local left = body:tag('div'):addClass('pd-left')
    left:tag('div'):addClass('pd-section-title'):wikitext('Player Info')

    local function infoRow(label, val, link)
        if not val or val == "" then return end
        local row = left:tag('div'):addClass('pd-info-row')
        row:tag('span'):addClass('pd-info-label'):wikitext(label)
        local vspan = row:tag('span'):addClass('pd-info-val')
        if link then vspan:wikitext('[['..val..']]')
        else vspan:wikitext(val) end
    end

    infoRow('Real Name',   pl.real_name)
    infoRow('Born',        pl.birth_date and lang:formatDate("d F Y", pl.birth_date))
    infoRow('Nationality', pl.nationality)
    infoRow('Role',        pl.role)
    infoRow('Current Team',pl.current_team, true)
    infoRow('Game',        pl.game)
    infoRow('Krafton Rank',rankVal ~= "Unranked" and rankVal or nil)

    -- Socials
    local socials = {
        {k='instagram', file='Icon_instagram.png', base='https://instagram.com/'},
        {k='twitter',   file='Icon_twitter.png',   base='https://twitter.com/'},
        {k='youtube',   file='Icon_youtube.png',   base='https://youtube.com/'},
        {k='discord',   file='Icon_discord.png',   base='https://discord.gg/'},
        {k='facebook',  file='Icon_facebook.png',  base='https://facebook.com/'},
    }
    local socialDiv = left:tag('div'):addClass('pd-socials')
    for _, s in ipairs(socials) do
        local v = pl[s.k]
        if v and v ~= "" then
            local url = v:match("^https?://") and v or (s.base .. v)
            socialDiv:wikitext('[[File:'..s.file..'|24px|link='..url..'|class=social-img]]')
        end
    end

    -- Team history
    if #teamHist > 0 then
        left:tag('div'):addClass('pd-section-title pd-section-title-gap'):wikitext('Team History')
        for _, h in ipairs(teamHist) do
            local tr = left:tag('div'):addClass('pd-team-row')
            tr:tag('div'):addClass('pd-team-logo')
                :wikitext((h.team or "?"):sub(1,3):upper())
            tr:tag('div'):addClass('pd-team-name'):wikitext('[['.. (h.team or "") ..']]')
            tr:tag('div'):addClass('pd-team-dates')
                :wikitext(fmtDate(h.join_date) .. ' – ' ..
                    (h.leave_date and h.leave_date ~= ""
                        and fmtDate(h.leave_date) or 'Now'))
        end
    end

    -- Right panel — tournament history
    local right = body:tag('div'):addClass('pd-right')
    right:tag('div'):addClass('pd-section-title'):wikitext('Tournament History')

    if #tournHistory > 0 then
        local tbl = right:tag('table'):addClass('pd-tourn-table')
        local hdr = tbl:tag('tr')
        for _, h in ipairs({'Tournament','Team','Stage','Place','Result','Prize'}) do
            hdr:tag('th'):wikitext(h)
        end
        for _, t in ipairs(tournHistory) do
            local tr    = tbl:tag('tr')
            local place = t.place
            local placeClass = place == 1 and 'pd-place-chip place-1'
                             or place == 2 and 'pd-place-chip place-2'
                             or place == 3 and 'pd-place-chip place-3'
                             or 'pd-place-chip place-other'
            local res = (t.result or ""):lower()
            local resBadge = res == 'q' and '<span class="pd-result-q">Qualified</span>'
                           or res == 'e' and '<span class="pd-result-e">Eliminated</span>'
                           or ""

            tr:tag('td'):wikitext('[['..t.tournament..']]')
            tr:tag('td'):wikitext('[['..t.team..']]')
            tr:tag('td'):wikitext(t.stage or "—")
            tr:tag('td'):tag('span'):addClass(placeClass):wikitext(tostring(place))
            tr:tag('td'):wikitext(resBadge)
            tr:tag('td'):addClass(t.prize > 0 and 'pd-prize-cell' or 'pd-prize-none')
                :wikitext(t.prize > 0 and fmtCurrency(t.prize) or "—")
        end
    else
        right:tag('div'):addClass('pd-empty')
            :wikitext('No tournament data found for this player.')
    end

    -- Stats placeholder (ready for future)
    right:tag('div'):addClass('pd-stats-placeholder')
        :tag('b'):wikitext('📊 Performance Stats'):done()
        :wikitext('Coming soon — per-match stats will appear here once Player_Stats data is available.')

    return tostring(root)
end

return p