Module:Statistics: Difference between revisions
From eSportsAmaze
More actions
Esportsamaze (talk | contribs) No edit summary |
Esportsamaze (talk | contribs) No edit summary |
||
| (10 intermediate revisions by 2 users not shown) | |||
| Line 3: | Line 3: | ||
local html = mw.html | local html = mw.html | ||
local text = mw.text | local text = mw.text | ||
local function sqlEscape(s) | |||
if not s then return "" end | |||
s = s:gsub("\\", "\\\\") | |||
s = s:gsub("'", "\\'") | |||
return s | |||
end | |||
-- ============================================================ | -- ============================================================ | ||
| Line 88: | Line 95: | ||
local whereParts = {} | local whereParts = {} | ||
table.insert(whereParts, string.format("tournament='%s'", tournament | table.insert(whereParts, string.format("tournament='%s'", sqlEscape(tournament))) | ||
if map ~= "Any" then table.insert(whereParts, string.format("map='%s'", map | if map ~= "Any" then table.insert(whereParts, string.format("map='%s'", sqlEscape(map))) end | ||
if stage and stage ~= "" then table.insert(whereParts, string.format("stage='%s'", stage | if stage and stage ~= "" then table.insert(whereParts, string.format("stage='%s'", sqlEscape(stage))) end | ||
if group and group ~= "" then table.insert(whereParts, string.format("groupname='%s'", group | if group and group ~= "" then table.insert(whereParts, string.format("groupname='%s'", sqlEscape(group))) end | ||
local table_name = (type == "player") and "Player_Stats" or "Team_Stats" | local table_name = (type == "player") and "Player_Stats" or "Team_Stats" | ||
| Line 103: | Line 110: | ||
if not results or #results == 0 then | if not results or #results == 0 then | ||
return '<div style="padding:20px; color:var(--text-muted); font-style:italic;">No statistics | return '<div style="padding:20px; color:var(--text-muted); font-style:italic;">No statistics available yet for this tournament.</div>' | ||
end | end | ||
| Line 120: | Line 127: | ||
th:addClass('sticky-col sticky-1') | th:addClass('sticky-col sticky-1') | ||
elseif type == "team" and cleanKey == "team" then | elseif type == "team" and cleanKey == "team" then | ||
-- TEAM STATS | -- TEAM STATS (PC): Width 220px to fit long names | ||
th:addClass('sticky-col sticky-2'):css('width', ' | th:addClass('sticky-col sticky-2'):css('width', '220px'):css('min-width', '220px'):css('max-width', '220px') | ||
elseif type == "player" and cleanKey == "player" then | elseif type == "player" and cleanKey == "player" then | ||
-- PLAYER STATS: | -- PLAYER STATS (PC): Width 180px for player names | ||
th:addClass('sticky-col sticky-2'):css('width', ' | th:addClass('sticky-col sticky-2'):css('width', '180px'):css('min-width', '180px'):css('max-width', '180px') | ||
end | end | ||
end | end | ||
| Line 140: | Line 144: | ||
cell:addClass('sticky-col sticky-1') | cell:addClass('sticky-col sticky-1') | ||
elseif type == "team" and cleanKey == "team" then | elseif type == "team" and cleanKey == "team" then | ||
cell:addClass('sticky-col sticky-2'):css('width', '220px'):css('min-width', '220px'):css('max-width', '220px') | |||
cell:addClass('sticky-col sticky-2'):css('width', ' | |||
elseif type == "player" and cleanKey == "player" then | elseif type == "player" and cleanKey == "player" then | ||
cell:addClass('sticky-col sticky-2'):css('width', '180px'):css('min-width', '180px'):css('max-width', '180px') | |||
cell:addClass('sticky-col sticky-2'):css('width', ' | |||
end | end | ||
Latest revision as of 02:22, 3 March 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
local function sqlEscape(s)
if not s then return "" end
s = s:gsub("\\", "\\\\")
s = s:gsub("'", "\\'")
return s
end
-- ============================================================
-- 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+"
}
-- ============================================================
-- HELPER FUNCTIONS
-- ============================================================
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
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
local queryFields = {}
for _, k in ipairs(colKeys) do
local cleanK = k:match("^%s*(.-)%s*$")
if cleanK ~= "rank" then table.insert(queryFields, cleanK) end
end
local whereParts = {}
table.insert(whereParts, string.format("tournament='%s'", sqlEscape(tournament)))
if map ~= "Any" then table.insert(whereParts, string.format("map='%s'", sqlEscape(map))) end
if stage and stage ~= "" then table.insert(whereParts, string.format("stage='%s'", sqlEscape(stage))) end
if group and group ~= "" then table.insert(whereParts, string.format("groupname='%s'", sqlEscape(group))) end
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 available yet for this tournament.</div>'
end
local root = html.create('div'):addClass('stats-table-wrapper')
local tbl = root:tag('table'):addClass('flat-data-table sortable')
tbl:css('width', 'auto')
local trHead = tbl:tag('tr')
for _, key in ipairs(colKeys) do
local cleanKey = key:match("^%s*(.-)%s*$")
local label = HEADERS[cleanKey] or cleanKey:upper()
local th = trHead:tag('th'):wikitext(label):css("text-align", "center"):css("white-space", "nowrap")
if cleanKey == "rank" then
th:addClass('sticky-col sticky-1')
elseif type == "team" and cleanKey == "team" then
-- TEAM STATS (PC): Width 220px to fit long names
th:addClass('sticky-col sticky-2'):css('width', '220px'):css('min-width', '220px'):css('max-width', '220px')
elseif type == "player" and cleanKey == "player" then
-- PLAYER STATS (PC): Width 180px for player names
th:addClass('sticky-col sticky-2'):css('width', '180px'):css('min-width', '180px'):css('max-width', '180px')
end
end
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')
if cleanKey == "rank" then
cell:addClass('sticky-col sticky-1')
elseif type == "team" and cleanKey == "team" then
cell:addClass('sticky-col sticky-2'):css('width', '220px'):css('min-width', '220px'):css('max-width', '220px')
elseif type == "player" and cleanKey == "player" then
cell:addClass('sticky-col sticky-2'):css('width', '180px'):css('min-width', '180px'):css('max-width', '180px')
end
if cleanKey == "rank" then
cell:wikitext(i .. '.'):css("font-weight", "bold"):css("text-align", "center"):css("white-space", "nowrap"):css("padding", "5px 0")
elseif cleanKey == "team" then
local teamName = row.team or ""
cell:attr("data-sort-value", teamName)
if type == "player" then
cell:wikitext(getTeamLogo(teamName)):css("text-align", "center")
else
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
cell:wikitext(formatNumber(row[cleanKey])):css("text-align", "center")
end
end
end
return tostring(root)
end
return p