Module:PrizePool: Difference between revisions
From eSportsAmaze
More actions
Esportsamaze (talk | contribs) No edit summary |
Esportsamaze (talk | contribs) No edit summary |
||
| (11 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
local _id_counter = 0 | |||
local html = mw.html | local html = mw.html | ||
local cargo = mw.ext.cargo | local cargo = mw.ext.cargo | ||
-- | -- ============================================================ | ||
local function | -- HELPER: Number Formatters | ||
-- ============================================================ | |||
-- Indian Format (1,00,000) | |||
local function formatINR(amount) | |||
if not amount then return "0" end | |||
local n = tostring(math.floor(tonumber(amount) or 0)) | |||
if #n <= 3 then return n end | |||
local last3 = n:sub(-3) | |||
local rest = n:sub(1, -4) | |||
-- Indian format: group remaining digits in pairs (from right) | |||
local formattedRest = rest:reverse():gsub("(%d%d)", "%1,"):reverse():gsub("^,", "") | |||
return formattedRest .. "," .. last3 | |||
end | |||
-- Standard Format (100,000) - For USD, Yen, etc. | |||
local function formatStd(amount) | |||
if not amount then return "0" end | if not amount then return "0" end | ||
local | local n = tostring(math.floor(tonumber(amount) or 0)) | ||
return n:reverse():gsub("(%d%d%d)", "%1,"):reverse():gsub("^,", "") | |||
end | |||
if ( | |||
-- ============================================================ | |||
-- HELPER: Dual Currency Display & Calc | |||
-- ============================================================ | |||
-- Returns: { displayHTML, valueForDatabase (INR) } | |||
local function processMoney(amount, currency, rate) | |||
if not amount or amount == "" or amount == "0" then | |||
return { display = "TBD", dbValue = 0 } | |||
end | |||
local val = 0 | |||
local r = tonumber(rate) or 1 | |||
local symbol = currency or "₹" | |||
if type(amount) == "string" then | |||
val = tonumber((amount:gsub(",", ""))) or 0 | |||
else | |||
val = tonumber(amount) or 0 | |||
end | |||
-- Case 1: Input is INR (Primary = INR, Secondary = USD) | |||
if symbol == "₹" or symbol == "INR" or symbol == "Rs" then | |||
local inrVal = val | |||
local usdVal = val * r -- Rate should be e.g. 0.011 | |||
local mainStr = "₹ " .. formatINR(inrVal) | |||
local subStr = "" | |||
if r ~= 1 then | |||
subStr = '<br><small style="color:var(--text-muted); font-size:0.85em;">≈ $ ' .. formatStd(usdVal) .. '</small>' | |||
end | |||
return { | |||
display = '<span class="pz-val">' .. mainStr .. subStr .. '</span>', | |||
dbValue = inrVal | |||
} | |||
-- Case 2: Input is Foreign (Primary = Foreign, Secondary = INR) | |||
else | |||
local localVal = val | |||
local inrVal = val * r -- Rate should be e.g. 90 (1 Unit = 90 INR) | |||
local mainStr = symbol .. " " .. formatStd(localVal) | |||
local subStr = '<br><small style="color:var(--text-muted); font-size:0.85em;">≈ ₹ ' .. formatINR(inrVal) .. '</small>' | |||
return { | |||
display = '<span class="pz-val">' .. mainStr .. subStr .. '</span>', | |||
dbValue = inrVal | |||
} | |||
end | end | ||
end | end | ||
-- Helper: Get Logo | -- Helper: Get Logo | ||
local function getLogo(teamName) | local function getLogo(teamName) | ||
if not teamName or teamName == "" then return "" end | if not teamName or teamName == "" or teamName == "TBD" then return "" end | ||
local clean = teamName:gsub("'", "") | local clean = teamName:gsub("'", "") | ||
local light = clean .. '.png' | local light = clean .. '.png' | ||
| Line 42: | Line 106: | ||
function p.main(frame) | function p.main(frame) | ||
local args = frame:getParent().args | local args = frame:getParent().args | ||
-- Global Settings | |||
local currency = args.currency or "₹" | local currency = args.currency or "₹" | ||
local tournamentName = args.tournament or mw.title.getCurrentTitle(). | local rate = tonumber(args.rate) or 1 | ||
local tournamentName = args.tournament or mw.title.getCurrentTitle().subpageText | |||
-- PRE-CHECK: Are there any awards? | |||
local hasAnyAwards = false | |||
for i = 1, 20 do | |||
if args['award_' .. i] and args['award_' .. i] ~= "" then | |||
hasAnyAwards = true | |||
break | |||
end | |||
end | |||
-- Unique IDs for Toggling | |||
_id_counter = _id_counter + 1 | |||
local uniqueID = "pp-" .. _id_counter | |||
local idContent = 'content-' .. uniqueID | |||
local idBtnShow = 'btn-show-' .. uniqueID | |||
local idBtnHide = 'btn-hide-' .. uniqueID | |||
local grid = html.create('div'):addClass('prize-section-grid') | local grid = html.create('div'):addClass('prize-section-grid') | ||
-- Adjust grid columns if no awards (Full width ranking) | |||
if not hasAnyAwards then | |||
grid:css('grid-template-columns', '1fr') | |||
end | |||
-- ========================================== | -- ========================================== | ||
-- COLUMN 1: RANKINGS | -- COLUMN 1: RANKINGS (TEAMS) | ||
-- ========================================== | -- ========================================== | ||
local colRank = grid:tag('div'):addClass('prize-col-rank') | local colRank = grid:tag('div'):addClass('prize-col-rank') | ||
| Line 58: | Line 146: | ||
local rankCount = 0 | local rankCount = 0 | ||
for i = 1, 64 do | for i = 1, 64 do | ||
if args['team_'..i] and args['team_'..i] ~= "" then rankCount = rankCount + 1 end | if (args['team_'..i] and args['team_'..i] ~= "") or (args['prize_'..i] and args['prize_'..i] ~= "") then | ||
rankCount = rankCount + 1 | |||
end | |||
end | end | ||
local collapseLimit = | local collapseLimit = 10 | ||
local isCollapsible = (rankCount > collapseLimit) | local isCollapsible = (rankCount > collapseLimit) | ||
local hiddenDiv = nil | local hiddenDiv = nil | ||
if isCollapsible then | if isCollapsible then | ||
hiddenDiv = html.create('div') | hiddenDiv = html.create('div') | ||
:addClass('mw-collapsible mw-collapsed') | :addClass('mw-collapsible mw-collapsed') | ||
:attr('id', 'mw-customcollapsible- | :attr('id', 'mw-customcollapsible-' .. idContent) | ||
end | end | ||
| Line 77: | Line 165: | ||
local place = args['place_'..i] or (i .. '.') | local place = args['place_'..i] or (i .. '.') | ||
local team = args['team_'..i] | local team = args['team_'..i] | ||
local | local rawPrize = args['prize_'..i] | ||
local seed = args['seed_'..i] | local seed = args['seed_'..i] | ||
if team and team ~= "" then | if (team and team ~= "") or (rawPrize and rawPrize ~= "") then | ||
hasRankData = true | hasRankData = true | ||
-- | -- Process Money (Display + DB Value) | ||
if cargo and cargo.store then | local moneyData = processMoney(rawPrize, currency, rate) | ||
-- DATABASE STORE (Always store INR value) | |||
if team and team ~= "" and cargo and cargo.store then | |||
cargo.store('PrizeMoney', { | cargo.store('PrizeMoney', { | ||
tournament = tournamentName, | tournament = tournamentName, | ||
placement = i, | placement = i, | ||
team = team, | team = team, | ||
prize = | prize = moneyData.dbValue, -- STORES INR | ||
award = '' | award = '' | ||
}) | }) | ||
end | end | ||
local targetContainer = rankList | local targetContainer = rankList | ||
if isCollapsible and i > | if isCollapsible and i > collapseLimit then | ||
targetContainer = hiddenDiv | targetContainer = hiddenDiv | ||
end | end | ||
local row = targetContainer:tag('div'):addClass('prize-row') | local row = targetContainer:tag('div'):addClass('prize-row') | ||
local rankClass = 'rank-other' | local rankClass = 'rank-other' | ||
local rankIcon = place | local rankIcon = place | ||
| Line 113: | Line 201: | ||
row:tag('div'):addClass('pz-rank'):wikitext(rankIcon) | row:tag('div'):addClass('pz-rank'):wikitext(rankIcon) | ||
local teamDiv = row:tag('div'):addClass('pz-team') | local teamDiv = row:tag('div'):addClass('pz-team') | ||
-- | if team and team ~= "" then | ||
teamDiv:wikitext(getLogo(team)) | |||
teamDiv:wikitext('[[' .. team .. ']]') | |||
else | |||
teamDiv:wikitext('TBD'):css('color', 'var(--text-muted)'):css('font-weight', 'normal') | |||
end | |||
local infoDiv = row:tag('div'):addClass('pz-info') | local infoDiv = row:tag('div'):addClass('pz-info') | ||
if | |||
infoDiv:tag(' | -- Prize Display | ||
if rawPrize and rawPrize ~= "" then | |||
infoDiv:tag('div'):addClass('pz-prize'):wikitext(moneyData.display) | |||
end | end | ||
if seed and seed ~= "" then | if seed and seed ~= "" then | ||
infoDiv:tag('span'):addClass('pz-seed'):wikitext(seed) | infoDiv:tag('span'):addClass('pz-seed'):wikitext(seed) | ||
| Line 129: | Line 223: | ||
end | end | ||
if not hasRankData then | if not hasRankData then | ||
rankList:tag('div'):addClass('prize-empty') | rankList:tag('div'):addClass('prize-empty') | ||
| Line 135: | Line 228: | ||
else | else | ||
if isCollapsible then | if isCollapsible then | ||
rankList:wikitext(tostring(hiddenDiv)) | rankList:wikitext(tostring(hiddenDiv)) | ||
-- | local toggleTargets = 'mw-customtoggle-' .. idContent .. ' mw-customtoggle-' .. idBtnShow .. ' mw-customtoggle-' .. idBtnHide | ||
colRank:tag('div') | |||
:attr('id', 'mw-customcollapsible-' .. idBtnShow) | |||
:addClass('prize-show-more mw-collapsible ' .. toggleTargets) | |||
:wikitext('View Full Distribution <i class="fa-solid fa-chevron-down"></i>') | |||
colRank:tag('div') | colRank:tag('div') | ||
:addClass('prize-show-more mw- | :attr('id', 'mw-customcollapsible-' .. idBtnHide) | ||
:wikitext(' | :addClass('prize-show-more mw-collapsible mw-collapsed ' .. toggleTargets) | ||
:wikitext('Show Less <i class="fa-solid fa-chevron-up"></i>') | |||
end | end | ||
end | end | ||
-- ========================================== | -- ========================================== | ||
-- COLUMN 2: SPECIAL AWARDS | -- COLUMN 2: SPECIAL AWARDS (Conditionally Rendered) | ||
-- ========================================== | -- ========================================== | ||
local colAward = grid:tag('div'):addClass('prize-col-award') | if hasAnyAwards then | ||
local colAward = grid:tag('div'):addClass('prize-col-award') | |||
colAward:tag('div'):addClass('prize-header'):wikitext('Special Awards') | |||
local awardList = colAward:tag('div'):addClass('prize-list') | |||
for i = 1, 20 do | |||
local awardName = args['award_'..i] | |||
local winner = args['award_'..i..'_winner'] | |||
local team = args['award_'..i..'_team'] | |||
local rawPrize = args['award_'..i..'_prize'] | |||
if awardName and awardName ~= "" then | |||
local moneyData = processMoney(rawPrize, currency, rate) | |||
if (winner or team) and cargo and cargo.store then | |||
cargo.store('PrizeMoney', { | |||
tournament = tournamentName, | |||
placement = '', | |||
team = team or '', | |||
player = winner or '', | |||
prize = moneyData.dbValue, -- STORES INR | |||
award = awardName | |||
}) | |||
end | |||
local row = awardList:tag('div'):addClass('award-row') | |||
local info = row:tag('div'):addClass('award-info') | |||
info:tag('div'):addClass('award-name'):wikitext(awardName) | |||
winDiv:wikitext(getLogo(team)) | local winDiv = info:tag('div'):addClass('award-winner') | ||
if winner and winner ~= "" then | |||
if team and team ~= "" then winDiv:wikitext(getLogo(team)) end | |||
winDiv:wikitext('[[' .. winner .. ']]') | |||
elseif team and team ~= "" then | |||
winDiv:wikitext(getLogo(team)) | |||
winDiv:wikitext('[[' .. team .. ']]') | |||
else | |||
winDiv:wikitext("TBD"):css('color', 'var(--text-muted)'):css('font-weight', 'normal') | |||
end | |||
if rawPrize and rawPrize ~= "" then | |||
row:tag('div'):addClass('award-prize'):wikitext(moneyData.display) | |||
end | |||
end | end | ||
end | end | ||
end | end | ||
Latest revision as of 14:36, 12 March 2026
Documentation for this module may be created at Module:PrizePool/doc
local p = {}
local _id_counter = 0
local html = mw.html
local cargo = mw.ext.cargo
-- ============================================================
-- HELPER: Number Formatters
-- ============================================================
-- Indian Format (1,00,000)
local function formatINR(amount)
if not amount then return "0" end
local n = tostring(math.floor(tonumber(amount) or 0))
if #n <= 3 then return n end
local last3 = n:sub(-3)
local rest = n:sub(1, -4)
-- Indian format: group remaining digits in pairs (from right)
local formattedRest = rest:reverse():gsub("(%d%d)", "%1,"):reverse():gsub("^,", "")
return formattedRest .. "," .. last3
end
-- Standard Format (100,000) - For USD, Yen, etc.
local function formatStd(amount)
if not amount then return "0" end
local n = tostring(math.floor(tonumber(amount) or 0))
return n:reverse():gsub("(%d%d%d)", "%1,"):reverse():gsub("^,", "")
end
-- ============================================================
-- HELPER: Dual Currency Display & Calc
-- ============================================================
-- Returns: { displayHTML, valueForDatabase (INR) }
local function processMoney(amount, currency, rate)
if not amount or amount == "" or amount == "0" then
return { display = "TBD", dbValue = 0 }
end
local val = 0
local r = tonumber(rate) or 1
local symbol = currency or "₹"
if type(amount) == "string" then
val = tonumber((amount:gsub(",", ""))) or 0
else
val = tonumber(amount) or 0
end
-- Case 1: Input is INR (Primary = INR, Secondary = USD)
if symbol == "₹" or symbol == "INR" or symbol == "Rs" then
local inrVal = val
local usdVal = val * r -- Rate should be e.g. 0.011
local mainStr = "₹ " .. formatINR(inrVal)
local subStr = ""
if r ~= 1 then
subStr = '<br><small style="color:var(--text-muted); font-size:0.85em;">≈ $ ' .. formatStd(usdVal) .. '</small>'
end
return {
display = '<span class="pz-val">' .. mainStr .. subStr .. '</span>',
dbValue = inrVal
}
-- Case 2: Input is Foreign (Primary = Foreign, Secondary = INR)
else
local localVal = val
local inrVal = val * r -- Rate should be e.g. 90 (1 Unit = 90 INR)
local mainStr = symbol .. " " .. formatStd(localVal)
local subStr = '<br><small style="color:var(--text-muted); font-size:0.85em;">≈ ₹ ' .. formatINR(inrVal) .. '</small>'
return {
display = '<span class="pz-val">' .. mainStr .. subStr .. '</span>',
dbValue = inrVal
}
end
end
-- Helper: Get Logo
local function getLogo(teamName)
if not teamName or teamName == "" or teamName == "TBD" then return "" end
local clean = teamName:gsub("'", "")
local light = clean .. '.png'
local dark = clean .. '_dark.png'
local container = html.create('span')
if mw.title.new('File:' .. light).exists then
container:wikitext('[[File:' .. light .. '|link=|class=logo-lightmode]]')
else
container:wikitext('[[File:Shield_team.png|link=|class=logo-lightmode]]')
end
if mw.title.new('File:' .. dark).exists then
container:wikitext('[[File:' .. dark .. '|link=|class=logo-darkmode]]')
elseif mw.title.new('File:' .. light).exists then
container:wikitext('[[File:' .. light .. '|link=|class=logo-darkmode]]')
else
container:wikitext('[[File:Shield_team_dark.png|link=|class=logo-darkmode]]')
end
return tostring(container)
end
function p.main(frame)
local args = frame:getParent().args
-- Global Settings
local currency = args.currency or "₹"
local rate = tonumber(args.rate) or 1
local tournamentName = args.tournament or mw.title.getCurrentTitle().subpageText
-- PRE-CHECK: Are there any awards?
local hasAnyAwards = false
for i = 1, 20 do
if args['award_' .. i] and args['award_' .. i] ~= "" then
hasAnyAwards = true
break
end
end
-- Unique IDs for Toggling
_id_counter = _id_counter + 1
local uniqueID = "pp-" .. _id_counter
local idContent = 'content-' .. uniqueID
local idBtnShow = 'btn-show-' .. uniqueID
local idBtnHide = 'btn-hide-' .. uniqueID
local grid = html.create('div'):addClass('prize-section-grid')
-- Adjust grid columns if no awards (Full width ranking)
if not hasAnyAwards then
grid:css('grid-template-columns', '1fr')
end
-- ==========================================
-- COLUMN 1: RANKINGS (TEAMS)
-- ==========================================
local colRank = grid:tag('div'):addClass('prize-col-rank')
colRank:tag('div'):addClass('prize-header'):wikitext('Prize Pool Distribution')
local rankList = colRank:tag('div'):addClass('prize-list')
local hasRankData = false
local rankCount = 0
for i = 1, 64 do
if (args['team_'..i] and args['team_'..i] ~= "") or (args['prize_'..i] and args['prize_'..i] ~= "") then
rankCount = rankCount + 1
end
end
local collapseLimit = 10
local isCollapsible = (rankCount > collapseLimit)
local hiddenDiv = nil
if isCollapsible then
hiddenDiv = html.create('div')
:addClass('mw-collapsible mw-collapsed')
:attr('id', 'mw-customcollapsible-' .. idContent)
end
for i = 1, 64 do
local place = args['place_'..i] or (i .. '.')
local team = args['team_'..i]
local rawPrize = args['prize_'..i]
local seed = args['seed_'..i]
if (team and team ~= "") or (rawPrize and rawPrize ~= "") then
hasRankData = true
-- Process Money (Display + DB Value)
local moneyData = processMoney(rawPrize, currency, rate)
-- DATABASE STORE (Always store INR value)
if team and team ~= "" and cargo and cargo.store then
cargo.store('PrizeMoney', {
tournament = tournamentName,
placement = i,
team = team,
prize = moneyData.dbValue, -- STORES INR
award = ''
})
end
local targetContainer = rankList
if isCollapsible and i > collapseLimit then
targetContainer = hiddenDiv
end
local row = targetContainer:tag('div'):addClass('prize-row')
local rankClass = 'rank-other'
local rankIcon = place
if i == 1 then rankClass = 'rank-1'; rankIcon = '🥇' end
if i == 2 then rankClass = 'rank-2'; rankIcon = '🥈' end
if i == 3 then rankClass = 'rank-3'; rankIcon = '🥉' end
row:addClass(rankClass)
row:tag('div'):addClass('pz-rank'):wikitext(rankIcon)
local teamDiv = row:tag('div'):addClass('pz-team')
if team and team ~= "" then
teamDiv:wikitext(getLogo(team))
teamDiv:wikitext('[[' .. team .. ']]')
else
teamDiv:wikitext('TBD'):css('color', 'var(--text-muted)'):css('font-weight', 'normal')
end
local infoDiv = row:tag('div'):addClass('pz-info')
-- Prize Display
if rawPrize and rawPrize ~= "" then
infoDiv:tag('div'):addClass('pz-prize'):wikitext(moneyData.display)
end
if seed and seed ~= "" then
infoDiv:tag('span'):addClass('pz-seed'):wikitext(seed)
end
end
end
if not hasRankData then
rankList:tag('div'):addClass('prize-empty')
:wikitext('<i class="fa-solid fa-trophy"></i><br>Prize Pool TBD')
else
if isCollapsible then
rankList:wikitext(tostring(hiddenDiv))
local toggleTargets = 'mw-customtoggle-' .. idContent .. ' mw-customtoggle-' .. idBtnShow .. ' mw-customtoggle-' .. idBtnHide
colRank:tag('div')
:attr('id', 'mw-customcollapsible-' .. idBtnShow)
:addClass('prize-show-more mw-collapsible ' .. toggleTargets)
:wikitext('View Full Distribution <i class="fa-solid fa-chevron-down"></i>')
colRank:tag('div')
:attr('id', 'mw-customcollapsible-' .. idBtnHide)
:addClass('prize-show-more mw-collapsible mw-collapsed ' .. toggleTargets)
:wikitext('Show Less <i class="fa-solid fa-chevron-up"></i>')
end
end
-- ==========================================
-- COLUMN 2: SPECIAL AWARDS (Conditionally Rendered)
-- ==========================================
if hasAnyAwards then
local colAward = grid:tag('div'):addClass('prize-col-award')
colAward:tag('div'):addClass('prize-header'):wikitext('Special Awards')
local awardList = colAward:tag('div'):addClass('prize-list')
for i = 1, 20 do
local awardName = args['award_'..i]
local winner = args['award_'..i..'_winner']
local team = args['award_'..i..'_team']
local rawPrize = args['award_'..i..'_prize']
if awardName and awardName ~= "" then
local moneyData = processMoney(rawPrize, currency, rate)
if (winner or team) and cargo and cargo.store then
cargo.store('PrizeMoney', {
tournament = tournamentName,
placement = '',
team = team or '',
player = winner or '',
prize = moneyData.dbValue, -- STORES INR
award = awardName
})
end
local row = awardList:tag('div'):addClass('award-row')
local info = row:tag('div'):addClass('award-info')
info:tag('div'):addClass('award-name'):wikitext(awardName)
local winDiv = info:tag('div'):addClass('award-winner')
if winner and winner ~= "" then
if team and team ~= "" then winDiv:wikitext(getLogo(team)) end
winDiv:wikitext('[[' .. winner .. ']]')
elseif team and team ~= "" then
winDiv:wikitext(getLogo(team))
winDiv:wikitext('[[' .. team .. ']]')
else
winDiv:wikitext("TBD"):css('color', 'var(--text-muted)'):css('font-weight', 'normal')
end
if rawPrize and rawPrize ~= "" then
row:tag('div'):addClass('award-prize'):wikitext(moneyData.display)
end
end
end
end
return tostring(grid)
end
return p