Module:Tournament: Difference between revisions
From eSportsAmaze
More actions
Esportsamaze (talk | contribs) No edit summary |
Esportsamaze (talk | contribs) No edit summary |
||
| Line 18: | Line 18: | ||
local formattedRest = rest:reverse():gsub("(%d%d)", "%1,"):reverse() | local formattedRest = rest:reverse():gsub("(%d%d)", "%1,"):reverse() | ||
if formattedRest:sub(1, 1) == "," then formattedRest = formattedRest:sub(2) end | if formattedRest:sub(1, 1) == "," then formattedRest = formattedRest:sub(2) end | ||
return currency .. " " .. formattedRest .. "," .. last3 | return '<span class="pz-prize">' .. currency .. " " .. formattedRest .. "," .. last3 .. '</span>' | ||
end | end | ||
| Line 33: | Line 33: | ||
end | end | ||
-- Helper: | -- Helper: Clean Title | ||
local function | local function getCleanTitle(pageLink) | ||
if not pageLink then return "" end | |||
local title = mw.title.new(pageLink) | |||
if title then return title.subpageText end | |||
return pageLink | |||
local | |||
if | |||
return | |||
end | end | ||
-- Helper: Social Icon Generator | -- Helper: Social Icon Generator (FIXED: Uses Wikitext Syntax) | ||
local function getSocials(args) | local function getSocials(args) | ||
local container = html.create('div'):addClass('fib-socials') | local container = html.create('div'):addClass('fib-socials') | ||
| Line 78: | Line 58: | ||
if args[p.arg] and args[p.arg] ~= "" then | if args[p.arg] and args[p.arg] ~= "" then | ||
hasSocials = true | hasSocials = true | ||
-- We use a span to wrap the icon inside the external link syntax | |||
-- Syntax: https://www.flaticon.com/free-icons/span | |||
container:wikitext('[' .. args[p.arg] .. ' <span class="fib-social-icon"><i class="' .. p.icon .. '"></i></span>]') | |||
end | end | ||
end | end | ||
if hasSocials then return tostring(container) else return "" end | if hasSocials then return tostring(container) else return "" end | ||
end | |||
-- Helper: Theme Aware Logo (For Lists/Homepage) | |||
local function getTourneyLogo(imageFile, darkImageFile) | |||
local container = html.create('div'):addClass('tr-event-logo') | |||
if imageFile and imageFile ~= "" then | |||
local darkFile = darkImageFile | |||
if not darkFile or darkFile == "" then | |||
local ext = imageFile:match("^.+(%..+)$") or ".png" | |||
local name = imageFile:gsub("%..+$", "") | |||
darkFile = name .. "_dark" .. ext | |||
end | |||
local hasDark = mw.title.new('File:' .. darkFile).exists | |||
container:tag('span'):addClass('logo-lightmode'):wikitext('[[File:' .. imageFile .. '|40px|link=]]') | |||
local dSpan = container:tag('span'):addClass('logo-darkmode') | |||
if hasDark then dSpan:wikitext('[[File:' .. darkFile .. '|40px|link=]]') else dSpan:wikitext('[[File:' .. imageFile .. '|40px|link=]]') end | |||
else | |||
container:wikitext('<i class="fa-solid fa-trophy" style="color:var(--text-muted); opacity:0.3;"></i>') | |||
end | |||
return tostring(container) | |||
end | |||
-- Helper: Theme Aware Logo (For Infobox) | |||
local function getInfoboxLogo(pageName, image, imageDark) | |||
local lightFile = (image ~= "" and image) or (pageName .. '.png') | |||
local darkFile = imageDark | |||
if not darkFile or darkFile == "" then | |||
local ext = lightFile:match("^.+(%..+)$") or ".png" | |||
local name = lightFile:gsub("%..+$", "") | |||
darkFile = name .. "_dark" .. ext | |||
end | |||
local hasLight = mw.title.new('File:' .. lightFile).exists | |||
local hasDark = mw.title.new('File:' .. darkFile).exists | |||
local container = html.create('div'):addClass('fib-image') | |||
local lSpan = container:tag('span'):addClass('logo-lightmode') | |||
if hasLight then lSpan:wikitext('[[File:' .. lightFile .. '|250px]]') else lSpan:wikitext('[[File:Shield_team.png|150px]]') end | |||
local dSpan = container:tag('span'):addClass('logo-darkmode') | |||
if hasDark then dSpan:wikitext('[[File:' .. darkFile .. '|250px]]') elseif hasLight then dSpan:wikitext('[[File:' .. lightFile .. '|250px]]') else dSpan:wikitext('[[File:Shield_team_dark.png|150px]]') end | |||
return tostring(container) | |||
end | end | ||
-- ============================================================ | -- ============================================================ | ||
-- MAIN 1: TOURNAMENT INFOBOX | -- MAIN 1: TOURNAMENT INFOBOX | ||
-- ============================================================ | -- ============================================================ | ||
function p.infobox(frame) | function p.infobox(frame) | ||
| Line 96: | Line 115: | ||
local page = args.name or mw.title.getCurrentTitle().text | local page = args.name or mw.title.getCurrentTitle().text | ||
local cleanName = mw.title.getCurrentTitle().subpageText | local cleanName = mw.title.getCurrentTitle().subpageText | ||
local prizeMoney = args.prize_pool or args.prizepool | local prizeMoney = args.prize_pool or args.prizepool | ||
if mw.ext.cargo and mw.ext.cargo.store then | if mw.ext.cargo and mw.ext.cargo.store then | ||
mw.ext.cargo.store('Tournaments', { | mw.ext.cargo.store('Tournaments', { | ||
| Line 121: | Line 138: | ||
next = args.next, | next = args.next, | ||
image = args.image, | image = args.image, | ||
image_dark = args.image_dark | image_dark = args.image_dark, | ||
instagram = args.instagram, | |||
twitter = args.twitter, | |||
youtube = args.youtube, | |||
discord = args.discord, | |||
facebook = args.facebook, | |||
website = args.website | |||
}) | }) | ||
end | end | ||
local root = html.create('div'):addClass('flat-infobox') | local root = html.create('div'):addClass('flat-infobox') | ||
local header = root:tag('div'):addClass('fib-header') | local header = root:tag('div'):addClass('fib-header') | ||
header:tag('div'):addClass('fib-title'):wikitext(args.name or cleanName) | header:tag('div'):addClass('fib-title'):wikitext(args.name or cleanName) | ||
-- | -- Logo comes AFTER title in the container, but visual order handled by DOM flow | ||
root:wikitext(getInfoboxLogo(page, args.image, args.image_dark)) | |||
local grid1 = root:tag('div'):addClass('fib-grid') | local grid1 = root:tag('div'):addClass('fib-grid') | ||
grid1:tag('div'):addClass('fib-cell') | grid1:tag('div'):addClass('fib-cell'):tag('div'):addClass('fib-label-sm'):wikitext('Event Tier'):done():tag('div'):addClass('fib-value-sm'):wikitext(args.tier or 'Unranked'):done() | ||
grid1:tag('div'):addClass('fib-cell'):tag('div'):addClass('fib-label-sm'):wikitext('Type'):done():tag('div'):addClass('fib-value-sm'):wikitext(args.type or 'Online'):done() | |||
grid1:tag('div'):addClass('fib-cell') | |||
local grid2 = root:tag('div'):addClass('fib-grid') | local grid2 = root:tag('div'):addClass('fib-grid') | ||
grid2:tag('div'):addClass('fib-cell') | grid2:tag('div'):addClass('fib-cell'):tag('div'):addClass('fib-label-sm'):wikitext('Mode'):done():tag('div'):addClass('fib-value-sm'):wikitext(args.mode or 'TBD'):done() | ||
grid2:tag('div'):addClass('fib-cell'):tag('div'):addClass('fib-label-sm'):wikitext('Location'):done():tag('div'):addClass('fib-value-sm'):wikitext(args.location or 'India'):done() | |||
grid2:tag('div'):addClass('fib-cell') | |||
if prizeMoney then | if prizeMoney then | ||
root:tag('div'):addClass('fib-prize') | root:tag('div'):addClass('fib-prize') | ||
| Line 160: | Line 170: | ||
end | end | ||
local list = root:tag('div'):addClass('fib-list') | local list = root:tag('div'):addClass('fib-list') | ||
local function addRow(label, value) | local function addRow(label, value) | ||
if value and value ~= "" then | if value and value ~= "" then | ||
list:tag('div'):addClass('fib-row') | list:tag('div'):addClass('fib-row'):tag('div'):addClass('fib-label'):wikitext(label):done():tag('div'):addClass('fib-data'):wikitext(value):done() | ||
end | end | ||
end | end | ||
| Line 177: | Line 183: | ||
addRow('Dates', formatDateRange(args.start_date, args.end_date)) | addRow('Dates', formatDateRange(args.start_date, args.end_date)) | ||
addRow('Device', args.device) | addRow('Device', args.device) | ||
if args.winner then addRow('Winner', "'''[[" .. args.winner .. "]]'''") end | |||
root:wikitext(getSocials(args)) | root:wikitext(getSocials(args)) | ||
-- | -- FIXED: Using FontAwesome Icons instead of File syntax for arrows | ||
if args.previous or args.next then | if args.previous or args.next then | ||
local nav = root:tag('div'):addClass('fib-nav') | local nav = root:tag('div'):addClass('fib-nav') | ||
local prevBtn = nav:tag('div'):addClass('fib-nav-btn prev') | local prevBtn = nav:tag('div'):addClass('fib-nav-btn prev') | ||
if args.previous and args.previous ~= "" then | if args.previous and args.previous ~= "" then | ||
prevBtn:wikitext(' | prevBtn:wikitext('[[' .. args.previous .. '|<i class="fa-solid fa-chevron-left"></i> Previous]]') | ||
else | else | ||
prevBtn:css('opacity', '0.3'):wikitext('Previous') | prevBtn:css('opacity', '0.3'):wikitext('<i class="fa-solid fa-chevron-left"></i> Previous') | ||
end | end | ||
local nextBtn = nav:tag('div'):addClass('fib-nav-btn next') | local nextBtn = nav:tag('div'):addClass('fib-nav-btn next') | ||
if args.next and args.next ~= "" then | if args.next and args.next ~= "" then | ||
nextBtn:wikitext('[[' .. args.next .. '|Next | nextBtn:wikitext('[[' .. args.next .. '|Next <i class="fa-solid fa-chevron-right"></i>]]') | ||
else | else | ||
nextBtn:css('opacity', '0.3'):wikitext('Next') | nextBtn:css('opacity', '0.3'):wikitext('Next <i class="fa-solid fa-chevron-right"></i>') | ||
end | end | ||
end | end | ||
| Line 210: | Line 210: | ||
-- ============================================================ | -- ============================================================ | ||
-- MAIN 2 | -- MAIN 2: LIST ROW (Tournaments Page) | ||
-- ============================================================ | -- ============================================================ | ||
function p.listRow(frame) | function p.listRow(frame) | ||
-- ... ( | local args = frame.args | ||
local page = args.Page or "" | |||
local name = getCleanTitle(page) | |||
local startDate = args.start_date or "" | |||
local endDate = args.end_date or "" | |||
local row = html.create('div'):addClass('tourney-row') | |||
row:tag('div'):addClass('tr-date'):wikitext(formatDateRange(startDate, endDate)) | |||
local info = row:tag('div'):addClass('tr-info') | |||
info:tag('div'):addClass('tr-name'):wikitext('[[' .. page .. '|' .. name .. ']]') | |||
if args.organizer then info:tag('div'):addClass('tr-org'):wikitext(args.organizer) end | |||
local winDiv = row:tag('div'):addClass('tr-winner mobile-hide') | |||
if args.winner and args.winner ~= "" then winDiv:wikitext("🏆 " .. args.winner) else winDiv:tag('span'):addClass('dim-text'):wikitext('-') end | |||
local prizeDiv = row:tag('div'):addClass('tr-prize') | |||
prizeDiv:wikitext(formatCurrency(args.prize_pool)) | |||
return tostring(row) | |||
end | end | ||
-- ============================================================ | |||
-- MAIN 3: LIST ROW MAIN (Homepage) | |||
-- ============================================================ | |||
function p.listRowMain(frame) | function p.listRowMain(frame) | ||
-- ... ( | local args = frame.args | ||
return | local page = args.Page or "" | ||
local name = getCleanTitle(page) | |||
local startDate = args.start_date or "" | |||
local endDate = args.end_date or "" | |||
local image = args.image or "" | |||
local imageDark = args.image_dark or "" | |||
local row = html.create('div'):addClass('tourney-row tr-compact') | |||
row:tag('div'):addClass('tr-date'):wikitext(formatDateRange(startDate, endDate)) | |||
row:tag('div'):addClass('tr-event-logo-col'):wikitext(getTourneyLogo(image, imageDark)) | |||
local info = row:tag('div'):addClass('tr-info') | |||
info:tag('div'):addClass('tr-name'):wikitext('[[' .. page .. '|' .. name .. ']]') | |||
if args.organizer then info:tag('div'):addClass('tr-org'):wikitext(args.organizer) end | |||
local prizeDiv = row:tag('div'):addClass('tr-prize') | |||
prizeDiv:wikitext(formatCurrency(args.prize_pool)) | |||
return tostring(row) | |||
end | end | ||
return p | return p | ||
Revision as of 14:03, 27 January 2026
Documentation for this module may be created at Module:Tournament/doc
local p = {}
local html = mw.html
local lang = mw.getContentLanguage()
-- ============================================================
-- HELPER FUNCTIONS
-- ============================================================
-- Helper: Currency Formatter
local function formatCurrency(amount)
if not amount or amount == "" or amount == "0" then return "TBD" end
local currency = "₹"
if string.find(amount, "%$") then currency = "$" end
local n = tostring(amount):gsub(",", ""):gsub("₹", ""):gsub("%$", "")
if #n <= 3 then return currency .. " " .. n end
local last3 = n:sub(-3)
local rest = n:sub(1, -4)
local formattedRest = rest:reverse():gsub("(%d%d)", "%1,"):reverse()
if formattedRest:sub(1, 1) == "," then formattedRest = formattedRest:sub(2) end
return '<span class="pz-prize">' .. currency .. " " .. formattedRest .. "," .. last3 .. '</span>'
end
-- Helper: Date Ranger
local function formatDateRange(startStr, endStr)
if not startStr or startStr == "" then return "TBA" end
if endStr and endStr ~= "" and endStr ~= startStr then
local s = lang:formatDate('d M', startStr)
local e = lang:formatDate('d M, Y', endStr)
return s .. " – " .. e
else
return lang:formatDate('d M, Y', startStr)
end
end
-- Helper: Clean Title
local function getCleanTitle(pageLink)
if not pageLink then return "" end
local title = mw.title.new(pageLink)
if title then return title.subpageText end
return pageLink
end
-- Helper: Social Icon Generator (FIXED: Uses Wikitext Syntax)
local function getSocials(args)
local container = html.create('div'):addClass('fib-socials')
local hasSocials = false
local platforms = {
{arg='instagram', icon='fa-brands fa-instagram'},
{arg='twitter', icon='fa-brands fa-x-twitter'},
{arg='youtube', icon='fa-brands fa-youtube'},
{arg='discord', icon='fa-brands fa-discord'},
{arg='facebook', icon='fa-brands fa-facebook'},
{arg='website', icon='fa-solid fa-globe'}
}
for _, p in ipairs(platforms) do
if args[p.arg] and args[p.arg] ~= "" then
hasSocials = true
-- We use a span to wrap the icon inside the external link syntax
-- Syntax: https://www.flaticon.com/free-icons/span
container:wikitext('[' .. args[p.arg] .. ' <span class="fib-social-icon"><i class="' .. p.icon .. '"></i></span>]')
end
end
if hasSocials then return tostring(container) else return "" end
end
-- Helper: Theme Aware Logo (For Lists/Homepage)
local function getTourneyLogo(imageFile, darkImageFile)
local container = html.create('div'):addClass('tr-event-logo')
if imageFile and imageFile ~= "" then
local darkFile = darkImageFile
if not darkFile or darkFile == "" then
local ext = imageFile:match("^.+(%..+)$") or ".png"
local name = imageFile:gsub("%..+$", "")
darkFile = name .. "_dark" .. ext
end
local hasDark = mw.title.new('File:' .. darkFile).exists
container:tag('span'):addClass('logo-lightmode'):wikitext('[[File:' .. imageFile .. '|40px|link=]]')
local dSpan = container:tag('span'):addClass('logo-darkmode')
if hasDark then dSpan:wikitext('[[File:' .. darkFile .. '|40px|link=]]') else dSpan:wikitext('[[File:' .. imageFile .. '|40px|link=]]') end
else
container:wikitext('<i class="fa-solid fa-trophy" style="color:var(--text-muted); opacity:0.3;"></i>')
end
return tostring(container)
end
-- Helper: Theme Aware Logo (For Infobox)
local function getInfoboxLogo(pageName, image, imageDark)
local lightFile = (image ~= "" and image) or (pageName .. '.png')
local darkFile = imageDark
if not darkFile or darkFile == "" then
local ext = lightFile:match("^.+(%..+)$") or ".png"
local name = lightFile:gsub("%..+$", "")
darkFile = name .. "_dark" .. ext
end
local hasLight = mw.title.new('File:' .. lightFile).exists
local hasDark = mw.title.new('File:' .. darkFile).exists
local container = html.create('div'):addClass('fib-image')
local lSpan = container:tag('span'):addClass('logo-lightmode')
if hasLight then lSpan:wikitext('[[File:' .. lightFile .. '|250px]]') else lSpan:wikitext('[[File:Shield_team.png|150px]]') end
local dSpan = container:tag('span'):addClass('logo-darkmode')
if hasDark then dSpan:wikitext('[[File:' .. darkFile .. '|250px]]') elseif hasLight then dSpan:wikitext('[[File:' .. lightFile .. '|250px]]') else dSpan:wikitext('[[File:Shield_team_dark.png|150px]]') end
return tostring(container)
end
-- ============================================================
-- MAIN 1: TOURNAMENT INFOBOX
-- ============================================================
function p.infobox(frame)
local args = frame:getParent().args
local page = args.name or mw.title.getCurrentTitle().text
local cleanName = mw.title.getCurrentTitle().subpageText
local prizeMoney = args.prize_pool or args.prizepool
if mw.ext.cargo and mw.ext.cargo.store then
mw.ext.cargo.store('Tournaments', {
_pageName = mw.title.getCurrentTitle().prefixedText,
name = args.name or cleanName,
series = args.series,
organizer = args.organizer,
sponsor = args.sponsor,
game = args.game or "BGMI",
mode = args.mode,
type = args.type,
tier = args.tier,
device = args.device,
location = args.location,
venue = args.venue,
prize_pool = prizeMoney,
start_date = args.start_date,
end_date = args.end_date,
winner = args.winner,
previous = args.previous,
next = args.next,
image = args.image,
image_dark = args.image_dark,
instagram = args.instagram,
twitter = args.twitter,
youtube = args.youtube,
discord = args.discord,
facebook = args.facebook,
website = args.website
})
end
local root = html.create('div'):addClass('flat-infobox')
local header = root:tag('div'):addClass('fib-header')
header:tag('div'):addClass('fib-title'):wikitext(args.name or cleanName)
-- Logo comes AFTER title in the container, but visual order handled by DOM flow
root:wikitext(getInfoboxLogo(page, args.image, args.image_dark))
local grid1 = root:tag('div'):addClass('fib-grid')
grid1:tag('div'):addClass('fib-cell'):tag('div'):addClass('fib-label-sm'):wikitext('Event Tier'):done():tag('div'):addClass('fib-value-sm'):wikitext(args.tier or 'Unranked'):done()
grid1:tag('div'):addClass('fib-cell'):tag('div'):addClass('fib-label-sm'):wikitext('Type'):done():tag('div'):addClass('fib-value-sm'):wikitext(args.type or 'Online'):done()
local grid2 = root:tag('div'):addClass('fib-grid')
grid2:tag('div'):addClass('fib-cell'):tag('div'):addClass('fib-label-sm'):wikitext('Mode'):done():tag('div'):addClass('fib-value-sm'):wikitext(args.mode or 'TBD'):done()
grid2:tag('div'):addClass('fib-cell'):tag('div'):addClass('fib-label-sm'):wikitext('Location'):done():tag('div'):addClass('fib-value-sm'):wikitext(args.location or 'India'):done()
if prizeMoney then
root:tag('div'):addClass('fib-prize')
:tag('div'):addClass('fib-label-sm'):wikitext('Total Prize Pool'):done()
:tag('div'):addClass('fib-prize-val'):wikitext(formatCurrency(prizeMoney)):done()
end
local list = root:tag('div'):addClass('fib-list')
local function addRow(label, value)
if value and value ~= "" then
list:tag('div'):addClass('fib-row'):tag('div'):addClass('fib-label'):wikitext(label):done():tag('div'):addClass('fib-data'):wikitext(value):done()
end
end
addRow('Series', args.series and '[[' .. args.series .. ']]')
addRow('Organizer', args.organizer)
addRow('Sponsors', args.sponsor)
addRow('Venue', args.venue)
addRow('Dates', formatDateRange(args.start_date, args.end_date))
addRow('Device', args.device)
if args.winner then addRow('Winner', "'''[[" .. args.winner .. "]]'''") end
root:wikitext(getSocials(args))
-- FIXED: Using FontAwesome Icons instead of File syntax for arrows
if args.previous or args.next then
local nav = root:tag('div'):addClass('fib-nav')
local prevBtn = nav:tag('div'):addClass('fib-nav-btn prev')
if args.previous and args.previous ~= "" then
prevBtn:wikitext('[[' .. args.previous .. '|<i class="fa-solid fa-chevron-left"></i> Previous]]')
else
prevBtn:css('opacity', '0.3'):wikitext('<i class="fa-solid fa-chevron-left"></i> Previous')
end
local nextBtn = nav:tag('div'):addClass('fib-nav-btn next')
if args.next and args.next ~= "" then
nextBtn:wikitext('[[' .. args.next .. '|Next <i class="fa-solid fa-chevron-right"></i>]]')
else
nextBtn:css('opacity', '0.3'):wikitext('Next <i class="fa-solid fa-chevron-right"></i>')
end
end
return tostring(root)
end
-- ============================================================
-- MAIN 2: LIST ROW (Tournaments Page)
-- ============================================================
function p.listRow(frame)
local args = frame.args
local page = args.Page or ""
local name = getCleanTitle(page)
local startDate = args.start_date or ""
local endDate = args.end_date or ""
local row = html.create('div'):addClass('tourney-row')
row:tag('div'):addClass('tr-date'):wikitext(formatDateRange(startDate, endDate))
local info = row:tag('div'):addClass('tr-info')
info:tag('div'):addClass('tr-name'):wikitext('[[' .. page .. '|' .. name .. ']]')
if args.organizer then info:tag('div'):addClass('tr-org'):wikitext(args.organizer) end
local winDiv = row:tag('div'):addClass('tr-winner mobile-hide')
if args.winner and args.winner ~= "" then winDiv:wikitext("🏆 " .. args.winner) else winDiv:tag('span'):addClass('dim-text'):wikitext('-') end
local prizeDiv = row:tag('div'):addClass('tr-prize')
prizeDiv:wikitext(formatCurrency(args.prize_pool))
return tostring(row)
end
-- ============================================================
-- MAIN 3: LIST ROW MAIN (Homepage)
-- ============================================================
function p.listRowMain(frame)
local args = frame.args
local page = args.Page or ""
local name = getCleanTitle(page)
local startDate = args.start_date or ""
local endDate = args.end_date or ""
local image = args.image or ""
local imageDark = args.image_dark or ""
local row = html.create('div'):addClass('tourney-row tr-compact')
row:tag('div'):addClass('tr-date'):wikitext(formatDateRange(startDate, endDate))
row:tag('div'):addClass('tr-event-logo-col'):wikitext(getTourneyLogo(image, imageDark))
local info = row:tag('div'):addClass('tr-info')
info:tag('div'):addClass('tr-name'):wikitext('[[' .. page .. '|' .. name .. ']]')
if args.organizer then info:tag('div'):addClass('tr-org'):wikitext(args.organizer) end
local prizeDiv = row:tag('div'):addClass('tr-prize')
prizeDiv:wikitext(formatCurrency(args.prize_pool))
return tostring(row)
end
return p