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

Module:Team: Difference between revisions

From eSportsAmaze
No edit summary
No edit summary
Line 1: Line 1:
local p = {} -- THIS LINE IS CRITICAL. DO NOT DELETE.
local p = {}
local cargo = mw.ext.cargo
local cargo = mw.ext.cargo
local html = mw.html
local html = mw.html


-- Helper: Currency Formatter
-- ============================================================
-- HELPER FUNCTIONS
-- ============================================================
 
-- Currency Formatter (Styled for the new design)
local function formatCurrency(amount)
local function formatCurrency(amount)
     if not amount then return "0" end
     if not amount then return "0" end
     return '<span class="indian-currency">' .. amount .. '</span>'
    -- Adds the Indian Rupee symbol class/formatting
     return '<span class="indian-currency">' .. amount .. '</span>'
end
end


-- Helper: Logo Logic (Light/Dark/Shield)
-- New Logo Logic (Matches Tournament Infobox Style)
local function getLogo(teamName, image, imageDark)
local function getInfoboxLogo(teamName, image, imageDark)
     local lightFile = (image ~= "" and image) or (teamName .. '.png')
     local lightFile = (image ~= "" and image) or (teamName .. '.png')
     local darkFile = (imageDark ~= "" and imageDark) or (teamName .. '_dark.png')
     local darkFile = (imageDark ~= "" and imageDark) or (teamName .. '_dark.png')
Line 17: Line 22:
     local hasDark = mw.title.new('File:' .. darkFile).exists
     local hasDark = mw.title.new('File:' .. darkFile).exists
      
      
     local container = html.create('div'):addClass('infobox-image')
    -- Use .fib-image container (Same as Tournaments)
     local container = html.create('div'):addClass('fib-image')
      
      
     -- Light Mode
     -- Light Mode Image
     local lDiv = container:tag('div'):addClass('logo-lightmode')
     local lSpan = container:tag('span'):addClass('logo-lightmode')
     if hasLight then
     if hasLight then  
         lDiv:wikitext('[[File:' .. lightFile .. '|200px]]')
         lSpan:wikitext('[[File:' .. lightFile .. '|220px]]')  
     else
     else  
         lDiv:wikitext('[[File:Shield_team.png|200px]]')
         lSpan:wikitext('[[File:Shield_team.png|180px]]')  
     end
     end
      
      
     -- Dark Mode
     -- Dark Mode Image
     local dDiv = container:tag('div'):addClass('logo-darkmode')
     local dSpan = container:tag('span'):addClass('logo-darkmode')
     if hasDark then
     if hasDark then  
         dDiv:wikitext('[[File:' .. darkFile .. '|200px]]')
         dSpan:wikitext('[[File:' .. darkFile .. '|220px]]')  
     elseif hasLight then
     elseif hasLight then  
         dDiv:wikitext('[[File:' .. lightFile .. '|200px]]')
         dSpan:wikitext('[[File:' .. lightFile .. '|220px]]')  
     else
     else  
         dDiv:wikitext('[[File:Shield_team_dark.png|200px]]')
         dSpan:wikitext('[[File:Shield_team_dark.png|180px]]')  
     end
     end
      
      
     return container
     return tostring(container)
end
end


-- Helper: Add Row
-- ============================================================
local function addRow(container, label, value)
-- MAIN 1: TEAM INFOBOX (UPDATED TO FLAT DESIGN)
    if value and value ~= "" then
-- ============================================================
        container:tag('div'):addClass('infobox-row')
            :tag('div'):addClass('infobox-label'):wikitext(label):done()
            :tag('div'):addClass('infobox-data'):wikitext(value):done()
    end
end
 
-- MAIN 1: Team Infobox
function p.infobox(frame)
function p.infobox(frame)
     local args = frame:getParent().args
     local args = frame:getParent().args
     local team = args.name or mw.title.getCurrentTitle().text
     local team = args.name or mw.title.getCurrentTitle().text
      
      
     local root = html.create('div'):addClass('infobox')
    -- 1. Create Root with New Class
   
     local root = html.create('div'):addClass('flat-infobox')
    -- Header
    root:tag('div'):addClass('infobox-header'):wikitext(team)
   
    -- Logo
    root:node(getLogo(team, args.image, args.image_dark))
   
    -- Data Container
    local data = root:tag('div'):addClass('infobox-data-container')
      
      
     addRow(data, "Name", args.other_team)
     -- 2. Header
     addRow(data, "Short Code", args.short_code)
     root:tag('div'):addClass('fib-header')
    addRow(data, "Country", args.country)
        :tag('div'):addClass('fib-title'):wikitext(team)
      
      
     -- Status
     -- 3. Logo
     if args.status then
     root:wikitext(getInfoboxLogo(team, args.image, args.image_dark))
        local color = "#333"
        local s = args.status:lower()
        if s == "active" then color = "green"
        elseif s == "inactive" or s == "disbanded" then color = "red" end
       
        data:tag('div'):addClass('infobox-row')
            :tag('div'):addClass('infobox-label'):wikitext("Status"):done()
            :tag('div'):addClass('infobox-data'):css('font-weight','bold'):css('color', color):wikitext(args.status)
    end
      
      
    -- 4. Calculations (Rank & Earnings)
     -- Auto-Rank (Krafton Rankings)
     -- Auto-Rank (Krafton Rankings)
     local rankTables = "Krafton_Rankings"
     local rankTables = "Krafton_Rankings"
Line 87: Line 70:
     local rankResult = cargo.query(rankTables, rankFields, rankArgs)
     local rankResult = cargo.query(rankTables, rankFields, rankArgs)
     local rankVal = (#rankResult > 0) and ("#" .. rankResult[1].rank) or "Unranked"
     local rankVal = (#rankResult > 0) and ("#" .. rankResult[1].rank) or "Unranked"
    addRow(data, "Krafton Rank", rankVal)
   
    -- Sponsors (Convert commas to newlines)
    if args.sponsors then
        local sponsorList = args.sponsors:gsub(",", "<br>")
        data:tag('div'):addClass('infobox-row')
            :tag('div'):addClass('infobox-label'):wikitext("Sponsors"):done()
            :tag('div'):addClass('infobox-data'):css('text-align','right'):css('line-height','1.4em'):wikitext(sponsorList)
    end
      
      
     -- Total Earnings (Auto-Sum)
     -- Total Earnings (Auto-Sum)
Line 103: Line 77:
     local prizeResult = cargo.query(prizeTables, prizeFields, prizeArgs)
     local prizeResult = cargo.query(prizeTables, prizeFields, prizeArgs)
     local earnings = (#prizeResult > 0 and prizeResult[1].total) or "0"
     local earnings = (#prizeResult > 0 and prizeResult[1].total) or "0"
    addRow(data, "Total Earnings", formatCurrency(earnings))
      
      
     -- Socials
     -- Status Color Logic
    local statusColor = "#333"
    local statusText = args.status or "Active"
    if args.status then
        local s = args.status:lower()
        if s == "active" then statusColor = "#16a34a" -- Green
        elseif s == "inactive" or s == "disbanded" then statusColor = "#dc2626" -- Red
        end
    end
 
    -- 5. GRID 1: Status & Rank
    local grid1 = root:tag('div'):addClass('fib-grid')
   
    -- Cell: Status
    grid1:tag('div'):addClass('fib-cell')
        :tag('div'):addClass('fib-label-sm'):wikitext('Status'):done()
        :tag('div'):addClass('fib-value-sm'):css('color', statusColor):wikitext(statusText):done()
       
    -- Cell: Rank
    grid1:tag('div'):addClass('fib-cell')
        :tag('div'):addClass('fib-label-sm'):wikitext('Krafton Rank'):done()
        :tag('div'):addClass('fib-value-sm'):wikitext(rankVal):done()
 
    -- 6. GRID 2: Country & Tag
    local grid2 = root:tag('div'):addClass('fib-grid')
   
    -- Cell: Country
    grid2:tag('div'):addClass('fib-cell')
        :tag('div'):addClass('fib-label-sm'):wikitext('Country'):done()
        :tag('div'):addClass('fib-value-sm'):wikitext(args.country or 'TBD'):done()
       
    -- Cell: Short Code
    grid2:tag('div'):addClass('fib-cell')
        :tag('div'):addClass('fib-label-sm'):wikitext('Tag'):done()
        :tag('div'):addClass('fib-value-sm'):wikitext(args.short_code or '-'):done()
 
    -- 7. Earnings Section (Highlighted)
    if earnings and earnings ~= "0" then
        root:tag('div'):addClass('fib-prize')
            :tag('div'):addClass('fib-label-sm'):wikitext('Total Earnings'):done()
            :tag('div'):addClass('fib-prize-val'):wikitext(formatCurrency(earnings)):done()
    end
   
    -- 8. Info List
    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('Full Name', args.other_team)
    if args.sponsors then
        addRow('Sponsors', args.sponsors:gsub(",", "<br>"))
    end
   
    -- 9. Social Media (Using styled container)
     if args.instagram or args.twitter or args.youtube then
     if args.instagram or args.twitter or args.youtube then
         data:tag('div'):addClass('infobox-header'):css('font-size','1em'):css('margin-top','10px'):css('border-radius','6px'):wikitext('Social Media')
         local socialDiv = root:tag('div'):addClass('fib-socials')
         local socialRow = data:tag('div'):addClass('infobox-row'):css('justify-content','center'):css('gap','10px')
       
         if args.instagram then socialRow:wikitext('[' .. args.instagram .. ' Instagram]') end
        -- Since current data uses text links (e.g., [url Name]), we render them simply
         if args.twitter then socialRow:wikitext('[' .. args.twitter .. ' X]') end
         -- If you update data to just be URLs later, we can add icons here.
         if args.youtube then socialRow:wikitext('[' .. args.youtube .. ' YouTube]') end
         if args.instagram then socialDiv:wikitext('<span style="font-weight:bold;">[' .. args.instagram .. ' IG]</span>') end
         if args.twitter then socialDiv:wikitext('<span style="font-weight:bold;">[' .. args.twitter .. ' X]</span>') end
         if args.youtube then socialDiv:wikitext('<span style="font-weight:bold;">[' .. args.youtube .. ' YT]</span>') end
     end
     end


Line 117: Line 150:
end
end


-- MAIN 2: Automatic Tournament History
-- ============================================================
-- MAIN 2: AUTOMATIC TOURNAMENT HISTORY (Preserved)
-- ============================================================
function p.history(frame)
function p.history(frame)
     local args = frame:getParent().args
     local args = frame:getParent().args
     local team = args.team or mw.title.getCurrentTitle().subpageText
     local team = args.team or mw.title.getCurrentTitle().subpageText
      
      
     -- Query StageStandings to see where this team played
     -- Query StageStandings
     local tables = "StageStandings"
     local tables = "StageStandings"
     local fields = "tournament, stage, totalpts, matchesplayed, wwcd, elimpts, lastmatchrank, result"
     local fields = "tournament, stage, totalpts, matchesplayed, wwcd, elimpts, lastmatchrank, result"
     local queryArgs = {
     local queryArgs = {
         where = "team = '" .. team .. "'",
         where = "team = '" .. team .. "'",
         orderBy = "tournament DESC", -- Most recent first
         orderBy = "tournament DESC",
         limit = 50
         limit = 50
     }
     }
Line 137: Line 172:
      
      
     if #results > 0 then
     if #results > 0 then
        -- Uses your 'modern-history-table' CSS class
         local tbl = root:tag('table'):addClass('modern-history-table')
         local tbl = root:tag('table'):addClass('modern-history-table')
          
          
Line 153: Line 189:
             local tr = tbl:tag('tr')
             local tr = tbl:tag('tr')
              
              
             -- Color code result (Qualified/Eliminated)
             -- Color code result
             local res = (row.result or ""):lower()
             local res = (row.result or ""):lower()
             if res == "q" or res == "qualified" then tr:css('background-color', '#E9FFF0') -- Greenish
             if res == "q" or res == "qualified" then tr:css('background-color', '#E9FFF0') -- Greenish
Line 174: Line 210:
end
end


-- MAIN 3: Active Roster Table
-- ============================================================
-- MAIN 3: ACTIVE ROSTER TABLE (Preserved)
-- ============================================================
function p.activeRoster(frame)
function p.activeRoster(frame)
     local args = frame:getParent().args
     local args = frame:getParent().args
     local team = args.team or mw.title.getCurrentTitle().subpageText
     local team = args.team or mw.title.getCurrentTitle().subpageText
      
      
     -- Query the Players table
     -- Query Players
     local tables = "Players"
     local tables = "Players"
     local fields = "id, real_name, role, nationality, image"
     local fields = "id, real_name, role, nationality, image"
Line 193: Line 231:
         :css('width', '100%')
         :css('width', '100%')
         :css('text-align', 'center')
         :css('text-align', 'center')
        :css('margin-top', '0px')
          
          
    -- Table Header
     local header = root:tag('tr')
     local header = root:tag('tr')
     header:tag('th'):wikitext('ID')
     header:tag('th'):wikitext('ID')
Line 207: Line 243:
              
              
             -- Cell 1: ID with Image
             -- Cell 1: ID with Image
             local idCell = tr:tag('td')
             local idCell = tr:tag('td'):css('text-align', 'left'):css('font-weight', 'bold')
                :css('text-align', 'left')
                :css('font-weight', 'bold')
               
             if row.image and row.image ~= "" then
             if row.image and row.image ~= "" then
                 idCell:wikitext('[[File:' .. row.image .. '|30px|link=' .. row.id .. ']] ')
                 idCell:wikitext('[[File:' .. row.image .. '|30px|link=' .. row.id .. ']] ')
Line 216: Line 249:
             idCell:wikitext('[[' .. row.id .. ']]')
             idCell:wikitext('[[' .. row.id .. ']]')
              
              
            -- Cell 2: Real Name
             tr:tag('td'):wikitext(row.real_name)
             tr:tag('td'):wikitext(row.real_name)
           
            -- Cell 3: Role
             tr:tag('td'):wikitext(row.role)
             tr:tag('td'):wikitext(row.role)
           
            -- Cell 4: Nationality
             tr:tag('td'):wikitext(row.nationality)
             tr:tag('td'):wikitext(row.nationality)
         end
         end
     else
     else
         local tr = root:tag('tr')
         root:tag('tr'):tag('td'):attr('colspan', '4'):wikitext('No players currently listed for this team.')
        tr:tag('td'):attr('colspan', '4'):wikitext('No players currently listed for this team.')
     end
     end
      
      

Revision as of 06:55, 28 January 2026

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

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

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

-- Currency Formatter (Styled for the new design)
local function formatCurrency(amount)
    if not amount then return "0" end
    -- Adds the Indian Rupee symbol class/formatting
    return '<span class="indian-currency">₹ ' .. amount .. '</span>'
end

-- New Logo Logic (Matches Tournament Infobox Style)
local function getInfoboxLogo(teamName, image, imageDark)
    local lightFile = (image ~= "" and image) or (teamName .. '.png')
    local darkFile = (imageDark ~= "" and imageDark) or (teamName .. '_dark.png')
    
    local hasLight = mw.title.new('File:' .. lightFile).exists
    local hasDark = mw.title.new('File:' .. darkFile).exists
    
    -- Use .fib-image container (Same as Tournaments)
    local container = html.create('div'):addClass('fib-image')
    
    -- Light Mode Image
    local lSpan = container:tag('span'):addClass('logo-lightmode')
    if hasLight then 
        lSpan:wikitext('[[File:' .. lightFile .. '|220px]]') 
    else 
        lSpan:wikitext('[[File:Shield_team.png|180px]]') 
    end
    
    -- Dark Mode Image
    local dSpan = container:tag('span'):addClass('logo-darkmode')
    if hasDark then 
        dSpan:wikitext('[[File:' .. darkFile .. '|220px]]') 
    elseif hasLight then 
        dSpan:wikitext('[[File:' .. lightFile .. '|220px]]') 
    else 
        dSpan:wikitext('[[File:Shield_team_dark.png|180px]]') 
    end
    
    return tostring(container)
end

-- ============================================================
-- MAIN 1: TEAM INFOBOX (UPDATED TO FLAT DESIGN)
-- ============================================================
function p.infobox(frame)
    local args = frame:getParent().args
    local team = args.name or mw.title.getCurrentTitle().text
    
    -- 1. Create Root with New Class
    local root = html.create('div'):addClass('flat-infobox')
    
    -- 2. Header
    root:tag('div'):addClass('fib-header')
        :tag('div'):addClass('fib-title'):wikitext(team)
    
    -- 3. Logo
    root:wikitext(getInfoboxLogo(team, args.image, args.image_dark))
    
    -- 4. Calculations (Rank & Earnings)
    -- Auto-Rank (Krafton Rankings)
    local rankTables = "Krafton_Rankings"
    local rankFields = "rank"
    local rankArgs = { where = "name = '" .. team .. "' AND type='Team'", limit = 1 }
    local rankResult = cargo.query(rankTables, rankFields, rankArgs)
    local rankVal = (#rankResult > 0) and ("#" .. rankResult[1].rank) or "Unranked"
    
    -- Total Earnings (Auto-Sum)
    local prizeTables = "Tournament_Prizes"
    local prizeFields = "SUM(money)=total"
    local prizeArgs = { where = "recipient = '" .. team .. "'" }
    local prizeResult = cargo.query(prizeTables, prizeFields, prizeArgs)
    local earnings = (#prizeResult > 0 and prizeResult[1].total) or "0"
    
    -- Status Color Logic
    local statusColor = "#333"
    local statusText = args.status or "Active"
    if args.status then
        local s = args.status:lower()
        if s == "active" then statusColor = "#16a34a" -- Green
        elseif s == "inactive" or s == "disbanded" then statusColor = "#dc2626" -- Red
        end
    end

    -- 5. GRID 1: Status & Rank
    local grid1 = root:tag('div'):addClass('fib-grid')
    
    -- Cell: Status
    grid1:tag('div'):addClass('fib-cell')
         :tag('div'):addClass('fib-label-sm'):wikitext('Status'):done()
         :tag('div'):addClass('fib-value-sm'):css('color', statusColor):wikitext(statusText):done()
         
    -- Cell: Rank
    grid1:tag('div'):addClass('fib-cell')
         :tag('div'):addClass('fib-label-sm'):wikitext('Krafton Rank'):done()
         :tag('div'):addClass('fib-value-sm'):wikitext(rankVal):done()

    -- 6. GRID 2: Country & Tag
    local grid2 = root:tag('div'):addClass('fib-grid')
    
    -- Cell: Country
    grid2:tag('div'):addClass('fib-cell')
         :tag('div'):addClass('fib-label-sm'):wikitext('Country'):done()
         :tag('div'):addClass('fib-value-sm'):wikitext(args.country or 'TBD'):done()
         
    -- Cell: Short Code
    grid2:tag('div'):addClass('fib-cell')
         :tag('div'):addClass('fib-label-sm'):wikitext('Tag'):done()
         :tag('div'):addClass('fib-value-sm'):wikitext(args.short_code or '-'):done()

    -- 7. Earnings Section (Highlighted)
    if earnings and earnings ~= "0" then
        root:tag('div'):addClass('fib-prize')
            :tag('div'):addClass('fib-label-sm'):wikitext('Total Earnings'):done()
            :tag('div'):addClass('fib-prize-val'):wikitext(formatCurrency(earnings)):done()
    end
    
    -- 8. Info List
    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('Full Name', args.other_team)
    if args.sponsors then
        addRow('Sponsors', args.sponsors:gsub(",", "<br>"))
    end
    
    -- 9. Social Media (Using styled container)
    if args.instagram or args.twitter or args.youtube then
        local socialDiv = root:tag('div'):addClass('fib-socials')
        
        -- Since current data uses text links (e.g., [url Name]), we render them simply
        -- If you update data to just be URLs later, we can add icons here.
        if args.instagram then socialDiv:wikitext('<span style="font-weight:bold;">[' .. args.instagram .. ' IG]</span>') end
        if args.twitter then socialDiv:wikitext('<span style="font-weight:bold;">[' .. args.twitter .. ' X]</span>') end
        if args.youtube then socialDiv:wikitext('<span style="font-weight:bold;">[' .. args.youtube .. ' YT]</span>') end
    end

    return tostring(root)
end

-- ============================================================
-- MAIN 2: AUTOMATIC TOURNAMENT HISTORY (Preserved)
-- ============================================================
function p.history(frame)
    local args = frame:getParent().args
    local team = args.team or mw.title.getCurrentTitle().subpageText
    
    -- Query StageStandings
    local tables = "StageStandings"
    local fields = "tournament, stage, totalpts, matchesplayed, wwcd, elimpts, lastmatchrank, result"
    local queryArgs = {
        where = "team = '" .. team .. "'",
        orderBy = "tournament DESC",
        limit = 50
    }
    
    local results = cargo.query(tables, fields, queryArgs)
    
    local root = html.create('div')
    root:wikitext('== Tournament Statistics ==')
    
    if #results > 0 then
        -- Uses your 'modern-history-table' CSS class
        local tbl = root:tag('table'):addClass('modern-history-table')
        
        -- Header
        local thead = tbl:tag('thead'):tag('tr')
        thead:tag('th'):wikitext('Tournament')
        thead:tag('th'):wikitext('Stage')
        thead:tag('th'):wikitext('Rank')
        thead:tag('th'):wikitext('MP')
        thead:tag('th'):wikitext('WWCD')
        thead:tag('th'):wikitext('Elims')
        thead:tag('th'):wikitext('Pts')
        
        -- Rows
        for _, row in ipairs(results) do
            local tr = tbl:tag('tr')
            
            -- Color code result
            local res = (row.result or ""):lower()
            if res == "q" or res == "qualified" then tr:css('background-color', '#E9FFF0') -- Greenish
            elseif res == "e" or res == "eliminated" then tr:css('background-color', '#FFE9E9') -- Reddish
            end
            
            tr:tag('td'):css('font-weight','bold'):wikitext('[[' .. row.tournament .. ']]')
            tr:tag('td'):wikitext(row.stage)
            tr:tag('td'):css('font-weight','bold'):css('text-align','center'):wikitext('#' .. (row.lastmatchrank or '?'))
            tr:tag('td'):css('text-align','center'):wikitext(row.matchesplayed)
            tr:tag('td'):css('text-align','center'):wikitext(row.wwcd)
            tr:tag('td'):css('text-align','center'):wikitext(row.elimpts)
            tr:tag('td'):css('text-align','center'):css('font-weight','800'):wikitext(row.totalpts)
        end
    else
        root:wikitext("''No tournament data found for this team.''")
    end
    
    return tostring(root)
end

-- ============================================================
-- MAIN 3: ACTIVE ROSTER TABLE (Preserved)
-- ============================================================
function p.activeRoster(frame)
    local args = frame:getParent().args
    local team = args.team or mw.title.getCurrentTitle().subpageText
    
    -- Query Players
    local tables = "Players"
    local fields = "id, real_name, role, nationality, image"
    local queryArgs = {
        where = "current_team = '" .. team .. "'",
        orderBy = "role ASC, id ASC"
    }
    
    local results = cargo.query(tables, fields, queryArgs)
    
    local root = html.create('table')
    root:addClass('wikitable flat-table sortable')
        :css('width', '100%')
        :css('text-align', 'center')
        
    local header = root:tag('tr')
    header:tag('th'):wikitext('ID')
    header:tag('th'):wikitext('Name')
    header:tag('th'):wikitext('Role')
    header:tag('th'):wikitext('Nationality')
    
    if #results > 0 then
        for _, row in ipairs(results) do
            local tr = root:tag('tr')
            
            -- Cell 1: ID with Image
            local idCell = tr:tag('td'):css('text-align', 'left'):css('font-weight', 'bold')
            if row.image and row.image ~= "" then
                idCell:wikitext('[[File:' .. row.image .. '|30px|link=' .. row.id .. ']] ')
            end
            idCell:wikitext('[[' .. row.id .. ']]')
            
            tr:tag('td'):wikitext(row.real_name)
            tr:tag('td'):wikitext(row.role)
            tr:tag('td'):wikitext(row.nationality)
        end
    else
        root:tag('tr'):tag('td'):attr('colspan', '4'):wikitext('No players currently listed for this team.')
    end
    
    return tostring(root)
end

return p