Module:BGMIHub: Difference between revisions
From eSportsAmaze
More actions
Esportsamaze (talk | contribs) No edit summary |
Esportsamaze (talk | contribs) No edit summary |
||
| Line 359: | Line 359: | ||
-- Player rankings | -- Player rankings | ||
local pRankCol = rankCols:tag('div'):addClass('hub-rank-col') | local pRankCol = rankCols:tag('div'):addClass('hub-rank-col') | ||
pRankCol:tag('div'):addClass('hub-rank-col-title'):wikitext(' | pRankCol:tag('div'):addClass('hub-rank-col-title'):wikitext('Top Players') | ||
local pTbl = pRankCol:tag('table'):addClass('hub-rank-table') | local pTbl = pRankCol:tag('table'):addClass('hub-rank-table') | ||
local ph = pTbl:tag('tr') | local ph = pTbl:tag('tr') | ||
Revision as of 05:22, 9 March 2026
Documentation for this module may be created at Module:BGMIHub/doc
-- ================================================================
-- Module:BGMIHub v1
-- Sections:
-- 1. Hero Banner — live stats (tournaments, prize pool, teams, players)
-- 2. Tournaments — upcoming/ongoing + recent results
-- 3. Teams — active teams sorted by Krafton rank
-- 4. Rankings — top players + top teams by Krafton rank
-- 5. Prize Money — top 10 teams + top 10 players by earnings
-- ================================================================
local p = {}
local cargo = mw.ext.cargo
local html = mw.html
-- ── Helpers ──────────────────────────────────────────────────────
local function esc(s)
if not s then return "" end
return s:gsub("\\","\\\\"):gsub("'","\\'")
end
local function clean(s)
if not s then return nil end
local c = s:gsub("[\r\n]",""):gsub("^%s*(.-)%s*$","%1")
return c ~= "" and c or nil
end
local function fmtCurrency(n)
if not n or n == 0 then return "—" end
local num = math.floor(tonumber(n) or 0)
local s = tostring(num)
if #s <= 3 then return "₹ " .. s end
local result = s:sub(-3)
local rem = s:sub(1,-4)
while #rem > 2 do result = rem:sub(-2)..","..result; rem = rem:sub(1,-3) end
return "₹ " .. rem .. "," .. result
end
local function fmtNumber(n)
-- Simple comma formatting for integers
local num = math.floor(tonumber(n) or 0)
local s = tostring(num)
local result = ""
local len = #s
for i = 1, len do
if i > 1 and (len - i + 1) % 3 == 0 then result = result .. "," end
result = result .. s:sub(i,i)
end
return result
end
local function getTierClass(tier)
if not tier then return "tier-def" end
local t = tier:lower()
if t:find("s") and t:find("tier") then return "tier-s" end
if t:find("a") and t:find("tier") then return "tier-a" end
if t:find("b") and t:find("tier") then return "tier-b" end
if t:find("c") and t:find("tier") then return "tier-c" end
return "tier-def"
end
local GAME = "BGMI"
-- ── Section header builder ────────────────────────────────────────
local function sectionHeader(parent, icon, title, subtitle)
local hdr = parent:tag('div'):addClass('hub-section-header')
local hl = hdr:tag('div'):addClass('hub-section-hl')
hl:tag('span'):addClass('hub-section-icon'):wikitext(icon)
hl:tag('h2'):addClass('hub-section-title'):wikitext(title)
if subtitle then
hdr:tag('div'):addClass('hub-section-sub'):wikitext(subtitle)
end
end
-- ── Main ─────────────────────────────────────────────────────────
function p.main(frame)
-- ════════════════════════════════════════════════════════════
-- DATA FETCHING
-- ════════════════════════════════════════════════════════════
-- 1. Hero stats
local totalTeamsRows = cargo.query("Teams","COUNT(name)=n",
{where="game='"..GAME.."' AND status='Active'", limit=1})
local totalTeams = (totalTeamsRows and #totalTeamsRows>0)
and (tonumber(totalTeamsRows[1].n) or 0) or 0
local totalPlayersRows = cargo.query("Players","COUNT(id)=n",
{where="game='"..GAME.."' AND status='Active'", limit=1})
local totalPlayers = (totalPlayersRows and #totalPlayersRows>0)
and (tonumber(totalPlayersRows[1].n) or 0) or 0
local totalTournsRows = cargo.query("Tournaments","COUNT(name)=n",
{where="game='"..GAME.."'", limit=1})
local totalTourns = (totalTournsRows and #totalTournsRows>0)
and (tonumber(totalTournsRows[1].n) or 0) or 0
local totalPrizeRows = cargo.query("PrizeMoney","SUM(prize)=total",
{where="player='' OR player IS NULL", limit=1})
local totalPrize = (totalPrizeRows and #totalPrizeRows>0)
and (tonumber(totalPrizeRows[1].total) or 0) or 0
-- 2. Tournaments — ongoing/upcoming (end_date >= today or no end_date)
local today = os.date("%Y-%m-%d")
local upcomingRows = cargo.query("Tournaments",
"name,tier,start_date,end_date,prize_pool,image,image_dark,type,location",
{ where = "game='"..GAME.."' AND (end_date>='"..today.."' OR end_date IS NULL OR end_date='')",
orderBy= "start_date ASC",
limit = 6 })
upcomingRows = upcomingRows or {}
-- 3. Tournaments — recent results (completed, end_date < today)
local recentRows = cargo.query("Tournaments",
"name,tier,end_date,prize_pool,winner,runner_up,image,image_dark",
{ where = "game='"..GAME.."' AND end_date<'"..today.."' AND end_date!=''",
orderBy= "end_date DESC",
limit = 8 })
recentRows = recentRows or {}
-- 4. Active teams with Krafton rank
local teamRows = cargo.query("Teams",
"name,display_name,short_code,image,image_dark,country,status",
{ where = "game='"..GAME.."' AND status='Active'",
orderBy= "name ASC",
limit = 50 })
teamRows = teamRows or {}
-- Fetch Krafton ranks for teams
local teamRankMap = {}
local allTeamRankRows = cargo.query("Krafton_Rankings","name,rank",
{where="type='Team'", limit=100})
if allTeamRankRows then
for _,r in ipairs(allTeamRankRows) do
teamRankMap[r.name] = tonumber(r.rank) or 999
end
end
-- Sort teams by Krafton rank
table.sort(teamRows, function(a,b)
local ra = teamRankMap[a.name] or 999
local rb = teamRankMap[b.name] or 999
return ra < rb
end)
-- 5. Player Krafton rankings (top 10)
local playerRankRows = cargo.query("Krafton_Rankings","name,rank",
{where="type='Player'", orderBy="rank ASC", limit=10})
playerRankRows = playerRankRows or {}
-- Fetch player details for ranked players
local rankedPlayerNames = {}
for _,r in ipairs(playerRankRows) do
table.insert(rankedPlayerNames,"'"..esc(r.name).."'")
end
local playerDetailMap = {}
if #rankedPlayerNames>0 then
local pdRows = cargo.query("Players","id,real_name,current_team,image,_pageName",
{where="id IN ("..table.concat(rankedPlayerNames,",")..")", limit=20})
if pdRows then
for _,d in ipairs(pdRows) do
playerDetailMap[d.id]={
real_name=d.real_name, team=d.current_team,
image=d.image, link=d._pageName
}
end
end
end
-- 6. Team earnings leaderboard (top 8)
local teamEarnRows = cargo.query("PrizeMoney","team,SUM(prize)=total",
{ where = "player='' OR player IS NULL",
groupBy = "team",
orderBy = "total DESC",
limit = 8 })
teamEarnRows = teamEarnRows or {}
-- 7. Player earnings leaderboard (top 8)
local playerEarnRows = cargo.query("PrizeMoney","player,SUM(prize)=total",
{ where = "player!='' AND player IS NOT NULL",
groupBy = "player",
orderBy = "total DESC",
limit = 8 })
playerEarnRows = playerEarnRows or {}
-- Fetch player IDs for earnings leaderboard
local earnPlayerNames = {}
for _,r in ipairs(playerEarnRows) do
if r.player and r.player~="" then
table.insert(earnPlayerNames,"'"..esc(r.player).."'")
end
end
local earnPlayerMap = {}
if #earnPlayerNames>0 then
local epRows = cargo.query("Players","id,real_name,current_team,_pageName",
{where="_pageName IN ("..table.concat(earnPlayerNames,",")..")", limit=20})
if epRows then
for _,d in ipairs(epRows) do
earnPlayerMap[d._pageName]={
id=d.id, real_name=d.real_name,
team=d.current_team, link=d._pageName
}
end
end
end
-- ════════════════════════════════════════════════════════════
-- RENDER
-- ════════════════════════════════════════════════════════════
local root = html.create('div'):addClass('hub-root')
-- ════ 1. HERO ════════════════════════════════════════════════
local hero = root:tag('div'):addClass('hub-hero')
local heroInner = hero:tag('div'):addClass('hub-hero-inner')
-- Left: title + description
local heroLeft = heroInner:tag('div'):addClass('hub-hero-left')
heroLeft:tag('div'):addClass('hub-hero-game-tag'):wikitext('ESPORTS WIKI')
heroLeft:tag('h1'):addClass('hub-hero-title'):wikitext('BGMI')
heroLeft:tag('div'):addClass('hub-hero-full'):wikitext('Battlegrounds Mobile India')
heroLeft:tag('div'):addClass('hub-hero-desc')
:wikitext('The complete resource for competitive BGMI — teams, players, tournaments and prize money all in one place.')
-- Right: live stat cards
local stats = heroInner:tag('div'):addClass('hub-hero-stats')
local function statCard(val, label, icon)
local card = stats:tag('div'):addClass('hub-stat-card')
card:tag('div'):addClass('hub-stat-icon'):wikitext(icon)
card:tag('div'):addClass('hub-stat-val'):wikitext(val)
card:tag('div'):addClass('hub-stat-label'):wikitext(label)
end
statCard(tostring(totalTourns), 'Tournaments', '🏟')
statCard(tostring(totalTeams), 'Active Teams', '🛡')
statCard(tostring(totalPlayers), 'Active Players', '🎮')
statCard(fmtCurrency(totalPrize),'Prize Distributed','💰')
-- ════ 2. TOURNAMENTS ═════════════════════════════════════════
local tourns = root:tag('div'):addClass('hub-section')
sectionHeader(tourns, '', 'Tournaments', 'Ongoing, upcoming and recent results')
-- Upcoming / Ongoing
if #upcomingRows>0 then
tourns:tag('div'):addClass('hub-sub-title'):wikitext('Ongoing & Upcoming')
local tGrid = tourns:tag('div'):addClass('hub-tourn-grid')
for _,t in ipairs(upcomingRows) do
local card = tGrid:tag('div'):addClass('hub-tourn-card')
-- Tier ribbon
local tier = t.tier or ""
if tier~="" then
card:tag('div'):addClass('hub-tourn-tier')
:tag('span'):addClass('tier-badge '..getTierClass(tier)):wikitext(tier)
end
-- Logo
local lightL = (t.image and t.image~="") and t.image or "Tournament_Placeholder.png"
local darkL = (t.image_dark and t.image_dark~="") and t.image_dark or lightL
local logoW = card:tag('div'):addClass('hub-tourn-logo')
logoW:wikitext("[[File:"..lightL.."|60px|link=|class=logo-lightmode]]")
logoW:wikitext("[[File:"..darkL .."|60px|link=|class=logo-darkmode]]")
-- Info
local info = card:tag('div'):addClass('hub-tourn-info')
info:tag('div'):addClass('hub-tourn-name')
:wikitext("[["..t.name.."|"..t.name.."]]")
-- Dates
local dateStr = ""
if t.start_date and t.start_date~="" then
dateStr = t.start_date
if t.end_date and t.end_date~="" then
dateStr = dateStr.." → "..t.end_date
end
end
if dateStr~="" then
info:tag('div'):addClass('hub-tourn-dates'):wikitext(dateStr)
end
-- Prize + location row
local meta = info:tag('div'):addClass('hub-tourn-meta')
if t.prize_pool and tonumber(t.prize_pool) and tonumber(t.prize_pool)>0 then
meta:tag('span'):addClass('hub-tourn-prize')
:wikitext('💰 '..fmtCurrency(tonumber(t.prize_pool)))
end
if t.location and t.location~="" then
meta:tag('span'):addClass('hub-tourn-loc'):wikitext('📍 '..t.location)
end
-- Live badge if ongoing
if t.start_date and t.start_date<=today
and (not t.end_date or t.end_date=="" or t.end_date>=today) then
card:tag('div'):addClass('hub-live-badge'):wikitext('LIVE')
end
end
end
-- Recent Results
if #recentRows>0 then
tourns:tag('div'):addClass('hub-sub-title hub-sub-title-gap'):wikitext('Recent Results')
local tbl = tourns:tag('table'):addClass('hub-results-table')
local hdr = tbl:tag('tr')
hdr:tag('th'):wikitext('Date')
hdr:tag('th'):wikitext('Tier')
hdr:tag('th'):wikitext('Tournament')
hdr:tag('th'):wikitext('🥇 Winner')
hdr:tag('th'):wikitext('🥈 Runner-up')
hdr:tag('th'):css('text-align','right'):wikitext('Prize Pool')
for _,t in ipairs(recentRows) do
local tr = tbl:tag('tr')
tr:tag('td'):addClass('ac-date'):wikitext(t.end_date or "—")
local tierTd = tr:tag('td'):addClass('ac-tier')
if t.tier and t.tier~="" then
tierTd:tag('span'):addClass('tier-badge '..getTierClass(t.tier)):wikitext(t.tier)
else tierTd:wikitext("—") end
tr:tag('td'):css('font-weight','600'):wikitext("[["..t.name.."]]")
tr:tag('td'):wikitext(t.winner and t.winner~="" and "[["..t.winner.."]]" or "—")
tr:tag('td'):wikitext(t.runner_up and t.runner_up~="" and "[["..t.runner_up.."]]" or "—")
tr:tag('td'):addClass('ac-prize')
:wikitext(tonumber(t.prize_pool) and tonumber(t.prize_pool)>0
and fmtCurrency(tonumber(t.prize_pool)) or "—")
end
end
-- ════ 3. TEAMS ═══════════════════════════════════════════════
local teamsSection = root:tag('div'):addClass('hub-section')
sectionHeader(teamsSection, '🛡', 'Teams',
'Active BGMI organisations, sorted by Krafton rank')
local teamGrid = teamsSection:tag('div'):addClass('hub-team-grid')
for _,t in ipairs(teamRows) do
local card = teamGrid:tag('div'):addClass('hub-team-card')
local rank = teamRankMap[t.name]
-- Rank badge
if rank and rank<999 then
card:tag('div'):addClass('hub-team-rank'):wikitext('#'..rank)
end
-- Logo
local lightL=(t.image and t.image~="") and t.image or "Shield_team.png"
local darkL =(t.image_dark and t.image_dark~="") and t.image_dark or lightL
local logoW = card:tag('div'):addClass('hub-team-logo')
logoW:wikitext("[[File:"..lightL.."|48px|link="..t.name.."|class=logo-lightmode]]")
logoW:wikitext("[[File:"..darkL .."|48px|link="..t.name.."|class=logo-darkmode]]")
-- Name
local dispName = (t.display_name and t.display_name~="")
and t.display_name or t.name
card:tag('div'):addClass('hub-team-name')
:wikitext("[["..t.name.."|"..dispName.."]]")
if t.short_code and t.short_code~="" then
card:tag('div'):addClass('hub-team-tag'):wikitext(t.short_code)
end
end
-- ════ 4. RANKINGS ════════════════════════════════════════════
local rankSection = root:tag('div'):addClass('hub-section hub-rankings')
sectionHeader(rankSection, '', 'Krafton Rankings', 'Official BGMI rankings')
local rankCols = rankSection:tag('div'):addClass('hub-rank-cols')
-- Player rankings
local pRankCol = rankCols:tag('div'):addClass('hub-rank-col')
pRankCol:tag('div'):addClass('hub-rank-col-title'):wikitext('Top Players')
local pTbl = pRankCol:tag('table'):addClass('hub-rank-table')
local ph = pTbl:tag('tr')
ph:tag('th'):wikitext('Rank')
ph:tag('th'):wikitext('Player')
ph:tag('th'):wikitext('Team')
for _,r in ipairs(playerRankRows) do
local d = playerDetailMap[r.name] or {}
local tr = pTbl:tag('tr')
-- Rank with medal for top 3
local rankTd = tr:tag('td'):addClass('hub-rank-num')
local medal = r.rank=="1" and "🥇" or r.rank=="2" and "🥈"
or r.rank=="3" and "🥉" or nil
if medal then rankTd:wikitext(medal)
else rankTd:tag('span'):addClass('hub-rank-badge'):wikitext('#'..r.rank) end
local link = d.link or r.name
tr:tag('td'):css('font-weight','700')
:wikitext("[["..link.."|"..r.name.."]]")
tr:tag('td'):addClass('hub-rank-team')
:wikitext(d.team and d.team~="" and "[["..d.team.."]]" or "—")
end
-- Team rankings
local tRankCol = rankCols:tag('div'):addClass('hub-rank-col')
tRankCol:tag('div'):addClass('hub-rank-col-title'):wikitext('🛡 Top Teams')
local tTbl = tRankCol:tag('table'):addClass('hub-rank-table')
local th2 = tTbl:tag('tr')
th2:tag('th'):wikitext('Rank')
th2:tag('th'):wikitext('Team')
-- Show top 10 teams by rank
local topTeams = {}
for _,t in ipairs(teamRows) do
if teamRankMap[t.name] and teamRankMap[t.name]<999 then
table.insert(topTeams,t)
end
if #topTeams>=10 then break end
end
for _,t in ipairs(topTeams) do
local rank = teamRankMap[t.name]
local tr = tTbl:tag('tr')
local rankTd = tr:tag('td'):addClass('hub-rank-num')
local medal = rank==1 and "🥇" or rank==2 and "🥈"
or rank==3 and "🥉" or nil
if medal then rankTd:wikitext(medal)
else rankTd:tag('span'):addClass('hub-rank-badge'):wikitext('#'..rank) end
local dispName=(t.display_name and t.display_name~="") and t.display_name or t.name
tr:tag('td'):css('font-weight','700')
:wikitext("[["..t.name.."|"..dispName.."]]")
end
-- ════ 5. PRIZE LEADERBOARD ═══════════════════════════════════
local prizeSection = root:tag('div'):addClass('hub-section')
sectionHeader(prizeSection, '', 'Prize Money Leaderboard',
'All-time earnings from recorded tournaments')
local prizeCols = prizeSection:tag('div'):addClass('hub-rank-cols')
-- Team earnings
local teCol = prizeCols:tag('div'):addClass('hub-rank-col')
teCol:tag('div'):addClass('hub-rank-col-title'):wikitext('🛡 Top Teams')
local teTbl = teCol:tag('table'):addClass('hub-rank-table')
local teh = teTbl:tag('tr')
teh:tag('th'):wikitext('#')
teh:tag('th'):wikitext('Team')
teh:tag('th'):css('text-align','right'):wikitext('Earnings')
for i,r in ipairs(teamEarnRows) do
local tr = teTbl:tag('tr')
tr:tag('td'):addClass('hub-rank-num'):wikitext(tostring(i))
tr:tag('td'):css('font-weight','700')
:wikitext(r.team and r.team~="" and "[["..r.team.."]]" or "—")
tr:tag('td'):addClass('ac-prize'):wikitext(fmtCurrency(tonumber(r.total) or 0))
end
-- Player earnings
local peCol = prizeCols:tag('div'):addClass('hub-rank-col')
peCol:tag('div'):addClass('hub-rank-col-title'):wikitext('Top Players')
local peTbl = peCol:tag('table'):addClass('hub-rank-table')
local peh = peTbl:tag('tr')
peh:tag('th'):wikitext('#')
peh:tag('th'):wikitext('Player')
peh:tag('th'):css('text-align','right'):wikitext('Earnings')
for i,r in ipairs(playerEarnRows) do
local d = earnPlayerMap[r.player] or {}
local dispId = d.id or (r.player or ""):gsub("^.*/","")
local link = d.link or r.player or ""
local tr = peTbl:tag('tr')
tr:tag('td'):addClass('hub-rank-num'):wikitext(tostring(i))
tr:tag('td'):css('font-weight','700')
:wikitext(link~="" and "[["..link.."|"..dispId.."]]" or dispId)
tr:tag('td'):addClass('ac-prize'):wikitext(fmtCurrency(tonumber(r.total) or 0))
end
return tostring(root)
end
return p