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

Module:Statistics: Difference between revisions

From eSportsAmaze
No edit summary
No edit summary
Line 32: Line 32:
     wwcd = "🥇", place_2 = "🥈", place_3 = "🥉", top_5 = "Top 5", top_8 = "Top 8", place_low = "> 8th",
     wwcd = "🥇", place_2 = "🥈", place_3 = "🥉", top_5 = "Top 5", top_8 = "Top 8", place_low = "> 8th",
     g_0 = "0", g_1_5 = "1–5", g_6_10 = "6–10", g_11_15 = "11–15", g_16_20 = "16–20", g_20_plus = "20+",
     g_0 = "0", g_1_5 = "1–5", g_6_10 = "6–10", g_11_15 = "11–15", g_16_20 = "16–20", g_20_plus = "20+",
    -- New Columns
     shortname = "Short Name", avg_er = "Avg ER", avg_mr = "Avg MR", avg_rn = "Avg Rn"
     shortname = "Short Name", avg_er = "Avg ER", avg_mr = "Avg MR", avg_rn = "Avg Rn"
}
}
Line 92: Line 91:
             colKeys = {"rank", "player", "team", "matches_played", "finishes", "damage"}
             colKeys = {"rank", "player", "team", "matches_played", "finishes", "damage"}
         else  
         else  
            -- Updated Team Defaults: Added the 4 new columns
             colKeys = {"rank", "team", "matches_played", "total_pts", "wwcd"}  
             colKeys = {"rank", "team", "matches_played", "total_pts", "wwcd", "avg_er", "avg_mr", "avg_rn"}  
         end
         end
     else
     else
Line 104: Line 102:
         local cleanK = k:match("^%s*(.-)%s*$")
         local cleanK = k:match("^%s*(.-)%s*$")
         if cleanK ~= "rank" then table.insert(queryFields, cleanK) end
         if cleanK ~= "rank" then table.insert(queryFields, cleanK) end
    end
   
    -- Important: Always fetch shortname for Team Stats (for mobile switch)
    if type == "team" then
        table.insert(queryFields, "shortname")
     end
     end
      
      
Line 120: Line 113:
     -- 4. Execute Query
     -- 4. Execute Query
     local table_name = (type == "player") and "Player_Stats" or "Team_Stats"
     local table_name = (type == "player") and "Player_Stats" or "Team_Stats"
    -- Ensure "team" and "shortname" (if team stats) are part of SELECT even if not in display
     local selectString = table.concat(queryFields, ",") .. ", team"
     local selectString = table.concat(queryFields, ",") .. ", team"
      
      
Line 135: Line 127:
     -- 5. Build Table
     -- 5. Build Table
     local root = html.create('div'):addClass('stats-table-wrapper')
     local root = html.create('div'):addClass('stats-table-wrapper')
    -- Re-use 'standings-card-table' class if you want the existing CSS sticky behavior,
    -- but 'flat-data-table' was used previously. We adhere to the Sticky CSS classes.
     local tbl = root:tag('table'):addClass('flat-data-table sortable')
     local tbl = root:tag('table'):addClass('flat-data-table sortable')
      
      
Line 147: Line 137:
         local label = HEADERS[cleanKey] or cleanKey:upper()
         local label = HEADERS[cleanKey] or cleanKey:upper()
          
          
        -- Center Align Headers
         local th = trHead:tag('th'):wikitext(label):css("text-align", "center")
         local th = trHead:tag('th'):wikitext(label):css("text-align", "center")
          
          
Line 157: Line 148:
             th:addClass('sticky-col sticky-2')
             th:addClass('sticky-col sticky-2')
         elseif type == "player" and cleanKey == "team" then
         elseif type == "player" and cleanKey == "team" then
            -- Sticky 3 usually has width 60px in CSS. We override it for Team Name.
             th:addClass('sticky-col sticky-3'):css('min-width', '150px'):css('z-index', '11')
             th:addClass('sticky-col sticky-3'):css('min-width', '150px'):css('z-index', '11')
         end
         end
Line 169: Line 159:
             local cell = tr:tag('td')
             local cell = tr:tag('td')
              
              
             -- STICKY COLUMN CLASSES
             -- Sticky Column Classes
             if cleanKey == "rank" then
             if cleanKey == "rank" then
                 cell:addClass('sticky-col sticky-1')
                 cell:addClass('sticky-col sticky-1')
Line 180: Line 170:
             end
             end


             -- CONTENT LOGIC
             -- Content Logic
             if cleanKey == "rank" then
             if cleanKey == "rank" then
                 cell:wikitext(i .. '.'):css("font-weight", "bold"):css("text-align", "center")
                 cell:wikitext(i .. '.'):css("font-weight", "bold"):css("text-align", "center")
Line 192: Line 182:
                     cell:wikitext(getTeamLogo(teamName)):css("text-align", "center")
                     cell:wikitext(getTeamLogo(teamName)):css("text-align", "center")
                 else
                 else
                     -- Team Stats: Logo + Name (with Mobile Switch)
                     -- Team Stats: Logo + Name (No shortname switching)
                    local shortName = row.shortname or teamName
                     cell:wikitext(getTeamLogo(teamName) .. '[[' .. teamName .. ']]')
                    local logo = getTeamLogo(teamName)
                        :css("text-align", "left")
                   
                        :css("white-space", "nowrap")
                    -- PC View (Full Name)
                     cell:tag('span'):addClass('pc-only'):wikitext(logo .. '[[' .. teamName .. ']]')
                    -- Mobile View (Short Name)
                    cell:tag('span'):addClass('mobile-only'):wikitext(logo .. '[[' .. teamName .. '|' .. shortName .. ']]')
                   
                    cell:css("text-align", "left"):css("white-space", "nowrap")
                 end
                 end



Revision as of 11:05, 31 January 2026

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

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

-- ============================================================
-- HELPER: Argument Fetcher
-- ============================================================
local function getArgs(frame)
    local args = {}
    for k, v in pairs(frame.args) do args[k] = v end
    if frame:getParent() then
        for k, v in pairs(frame:getParent().args) do args[k] = v end
    end
    return args
end

-- ============================================================
-- CONFIGURATION
-- ============================================================
local HEADERS = {
    rank = "#", team = "Team", player = "Player", matches_played = "Matches",
    finishes = "Finishes", fpm = "FPM", knocks = "Knocks", damage = "Damage",
    headshots = "Headshots", longest = "Longest", assists = "Assists",
    grenade_kills = "Grenade Fin", vehicle_kills = "Vehicle Fin", contribution = "Contrib %", 
    survival = "Surv. Time", healings = "Heals", revives = "Revives", damage_taken = "Dmg Recv",
    grenades_used = "Nades Used", smokes_used = "Smokes Used", utility_used = "Util Used",
    dist_drive = "Drive Dist", dist_walk = "Walk Dist", dist_total = "Total Dist",
    bluezone = "Bluezone Time", air_drops = "Air Drops",
    total_pts = "Total Pts", place_pts = "Place Pts", elims = "Elims",
    avg_place = "Avg Place", avg_place_pts = "Avg Place Pts", avg_elims = "Avg Elims", avg_total = "Avg Pts",
    wwcd = "🥇", place_2 = "🥈", place_3 = "🥉", top_5 = "Top 5", top_8 = "Top 8", place_low = "> 8th",
    g_0 = "0", g_1_5 = "1–5", g_6_10 = "6–10", g_11_15 = "11–15", g_16_20 = "16–20", g_20_plus = "20+",
    shortname = "Short Name", avg_er = "Avg ER", avg_mr = "Avg MR", avg_rn = "Avg Rn"
}

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

-- Smart Rounding (No decimals for integers, 2 decimals for floats)
local function formatNumber(val)
    if not val then return "" end
    local n = tonumber(val)
    if not n then return val end 
    
    if n == math.floor(n) then
        return math.floor(n)
    else
        return string.format("%.2f", n)
    end
end

local function getTeamLogo(teamName)
    if not teamName then return "" end
    local cleanName = teamName:gsub("'", "")
    local lightFile = cleanName .. '.png'
    local darkFile = cleanName .. '_dark.png'
    local hasLight = mw.title.new('File:' .. lightFile).exists
    local hasDark = mw.title.new('File:' .. darkFile).exists
    
    local html = ""
    if hasLight then html = html .. '[[File:' .. lightFile .. '|25px|link=' .. teamName .. '|class=logo-lightmode]]'
    else html = html .. '[[File:Shield_team.png|25px|link=' .. teamName .. '|class=logo-lightmode]]' end
    if hasDark then html = html .. '[[File:' .. darkFile .. '|25px|link=' .. teamName .. '|class=logo-darkmode]]'
    elseif hasLight then html = html .. '[[File:' .. lightFile .. '|25px|link=' .. teamName .. '|class=logo-darkmode]]'
    else html = html .. '[[File:Shield_team_dark.png|25px|link=' .. teamName .. '|class=logo-darkmode]]' end
    return html .. " "
end

-- ============================================================
-- MAIN GENERATOR
-- ============================================================
function p.main(frame)
    local args = getArgs(frame)
    local type = args.type or "player"
    local tournament = args.tournament 
    if not tournament or tournament == "" then
        tournament = mw.title.getCurrentTitle().text
    end

    local map = args.map or "All"
    local stage = args.stage
    local group = args.group
    
    -- 1. Determine Columns
    local colsInput = args.columns or ""
    local colKeys = {}
    if colsInput == "" then
        if type == "player" then 
            colKeys = {"rank", "player", "team", "matches_played", "finishes", "damage"}
        else 
            colKeys = {"rank", "team", "matches_played", "total_pts", "wwcd"} 
        end
    else
        colKeys = text.split(colsInput, ",")
    end
    
    -- 2. Query Fields
    local queryFields = {}
    for _, k in ipairs(colKeys) do
        local cleanK = k:match("^%s*(.-)%s*$")
        if cleanK ~= "rank" then table.insert(queryFields, cleanK) end
    end
    
    -- 3. Where Clause
    local whereParts = {}
    table.insert(whereParts, string.format("tournament='%s'", tournament:gsub("'", "\\'")))
    if map ~= "Any" then table.insert(whereParts, string.format("map='%s'", map:gsub("'", "\\'"))) end
    if stage and stage ~= "" then table.insert(whereParts, string.format("stage='%s'", stage:gsub("'", "\\'"))) end
    if group and group ~= "" then table.insert(whereParts, string.format("groupname='%s'", group:gsub("'", "\\'"))) end
    
    -- 4. Execute Query
    local table_name = (type == "player") and "Player_Stats" or "Team_Stats"
    local selectString = table.concat(queryFields, ",") .. ", team"
    
    local results = cargo.query(table_name, selectString, {
        where = table.concat(whereParts, " AND "),
        orderBy = (type == "player" and "finishes DESC" or "total_pts DESC"),
        limit = 100
    })
    
    if not results or #results == 0 then
        return '<div style="padding:20px; color:var(--text-muted); font-style:italic;">No statistics found for: ' .. table.concat(whereParts, " | ") .. '</div>'
    end
    
    -- 5. Build Table
    local root = html.create('div'):addClass('stats-table-wrapper')
    local tbl = root:tag('table'):addClass('flat-data-table sortable')
    
    tbl:css('width', '100%')
    
    -- Header Row
    local trHead = tbl:tag('tr')
    for _, key in ipairs(colKeys) do
        local cleanKey = key:match("^%s*(.-)%s*$")
        local label = HEADERS[cleanKey] or cleanKey:upper()
        
        -- Center Align Headers
        local th = trHead:tag('th'):wikitext(label):css("text-align", "center")
        
        -- Sticky Header Logic
        if cleanKey == "rank" then
            th:addClass('sticky-col sticky-1')
        elseif type == "team" and cleanKey == "team" then
            th:addClass('sticky-col sticky-2')
        elseif type == "player" and cleanKey == "player" then
            th:addClass('sticky-col sticky-2')
        elseif type == "player" and cleanKey == "team" then
            th:addClass('sticky-col sticky-3'):css('min-width', '150px'):css('z-index', '11')
        end
    end
    
    -- Data Rows
    for i, row in ipairs(results) do
        local tr = tbl:tag('tr')
        for _, key in ipairs(colKeys) do
            local cleanKey = key:match("^%s*(.-)%s*$")
            local cell = tr:tag('td')
            
            -- Sticky Column Classes
            if cleanKey == "rank" then
                cell:addClass('sticky-col sticky-1')
            elseif type == "team" and cleanKey == "team" then
                cell:addClass('sticky-col sticky-2')
            elseif type == "player" and cleanKey == "player" then
                cell:addClass('sticky-col sticky-2')
            elseif type == "player" and cleanKey == "team" then
                cell:addClass('sticky-col sticky-3'):css('min-width', '150px')
            end

            -- Content Logic
            if cleanKey == "rank" then
                cell:wikitext(i .. '.'):css("font-weight", "bold"):css("text-align", "center")
                
            elseif cleanKey == "team" then
                local teamName = row.team or ""
                cell:attr("data-sort-value", teamName)
                
                if type == "player" then
                    -- Player Stats: Just Logo
                    cell:wikitext(getTeamLogo(teamName)):css("text-align", "center")
                else
                    -- Team Stats: Logo + Name (No shortname switching)
                    cell:wikitext(getTeamLogo(teamName) .. '[[' .. teamName .. ']]')
                        :css("text-align", "left")
                        :css("white-space", "nowrap")
                end

            elseif cleanKey == "player" then
                cell:wikitext('[[' .. (row.player or "") .. ']]'):css("text-align", "left"):css("font-weight", "bold")
                
            else
                -- Numeric Data
                local rawVal = row[cleanKey]
                local formattedVal = formatNumber(rawVal)
                cell:wikitext(formattedVal):css("text-align", "center")
            end
        end
    end
    
    return tostring(root)
end

return p