local p =
-- Function to parse and expand a template with given parameterslocal function expandTemplate(frame, templateName, params) return frame:expandTemplateend
local function templateExists(templateName) local title = mw.title.new('Template:' .. templateName) return title and title.existsend
-- Function to process country codes and variants OR youth team flag templates and age level, dividing parameters by the "+" signlocal function processIcon(iconString) if not iconString or iconString:match("^%s*$") then return nil, nil -- Return nil for both iconCode and variant if the input is empty or only whitespace elseif iconString:find('+') then local parts = mw.text.split(iconString, '+', true) local iconCode = parts[1] local variant = parts[2] return iconCode, variant else return iconString, nil -- Return the input string as iconCode if no "+" is present endend
-- Function to determine the correct ordinal suffix for a given number for the headinglocal function ordinal(n) local last_digit = n % 10 local last_two_digits = n % 100 if last_digit
2 and last_two_digits ~= 12 then return n .. 'nd' elseif last_digit
-- Function to clean and process the aggregate score for comparisonlocal function cleanScore(score) -- Return an empty string if score is nil or empty to avoid errors if not score or score:match("^%s*$") then return end
-- Function to replace wiki links with their display text or link text local function replaceLink(match) local pipePos = match:find("|") if pipePos then return match:sub(pipePos + 1, -3) -- Return text after the '|' else return match:sub(3, -3) -- Return text without the brackets end end
-- Replace wiki links score = score:gsub("%[%[.-%]%]", replaceLink)
-- Remove MediaWiki's unique placeholder sequences for references score = score:gsub('"`UNIQ.-QINU`"', )
-- Remove superscript tags and their contents score = score:gsub('
-- Convert dashes to a standard format score = score:gsub('[–—―‒−]', '-')
-- Strip all characters except numbers, dashes and parentheses return score:gsub('[^0-9%-]+', )end
-- Function to determine the winner based on scores within parentheses (first) or regular format (second)local function determineWinner(cleanScore, matchType, team1, team2, boldWinner, colorWinner) local team1Winner, team2Winner = false, false local score1, score2 local manualBold = false local manualColor = false
-- Handling for manual bolding if team1 and type(team1)
'string' then manualBold2 = team2:find("") and not (team2:gsub("", ""):match("^%s*$")) team2 = team2:gsub("", "") end
if manualBold1 then team1Winner = true manualBold = true end if manualBold2 then team2Winner = true manualBold = true end
-- Handling for manual coloring if team1 and type(team1)
'string' then manualColor2 = team2:find("") and not (team2:gsub("", ""):match("^%s*$")) team2 = team2:gsub("", "") end
if manualColor1 then if not team1Winner then team1Winner = true end manualColor = true end if manualColor2 then if not team2Winner then team2Winner = true end manualColor = true end
-- Additional check for empty team names in NT matches if matchType
-- Regular winner determination logic if manual bolding or coloring is not conclusive if not team1Winner and not team2Winner and (boldWinner or colorWinner) then local parenthetical = cleanScore:match('%((%d+%-+%d+)%)') local outsideParenthetical = cleanScore:match('^(%d+%-+%d+)') if parenthetical then score1, score2 = parenthetical:match('(%d+)%-+(%d+)') elseif outsideParenthetical then score1, score2 = outsideParenthetical:match('(%d+)%-+(%d+)') end
if score1 and score2 then team1Winner = tonumber(score1) > tonumber(score2) team2Winner = tonumber(score1) < tonumber(score2) end end
return team1, team2, team1Winner, team2Winner, manualBold, manualColorend
-- Function to check if any parameter in a given row is non-nil and non-emptylocal function anyParameterPresent(startIndex, step, args) for index = startIndex, startIndex + step - 1 do if args[index] and args[index]:match("^%s*(.-)%s*$") ~= "" then return true end end return falseend
-- Main function that processes input and returns the wikitablefunction p.main(frame) local args = require'Module:Arguments'.getArgs(frame,) local root = mw.html.create local matchType = (args.type
'MNT') and 'NT' or (args.type or 'club') -- Set default match type to 'club' local isWNT = args.type
'y' or args.fill_blanks
'1' or args.fill_blanks
-- Process flag parameter to determine flag template and variant if args.flag and args.flag:find('+') then flagTemplate, flagParam1 = processIcon(args.flag) -- Process flag icons with variants else if args.flag then flagTemplate = args.flag elseif isWNT then flagTemplate = 'fbw' -- Default to for WNT matches elseif matchType
if args.flag and (flagTemplate
'no' or flagTemplate
'false' or flagTemplate
'none' or flagTemplate
'NT' then flagTemplate = isWNT and 'fbw' or 'fb' -- Set flagTemplate to "fbw"/"fb", as disabling flags is not allowed for NT flagParam1 = false end end
-- Check if flagTemplate exists and adjust if necessary if matchType
local legs = (args.legs
'n' or args.legs
'false' or args.legs
'none' or args.legs
'one') and 0 or tonumber(args.legs) or 2 local teamWidth = (tonumber(args['team_width']) and args['team_width'] .. 'px') or '250px' local scoreWidth = (tonumber(args['score_width']) and args['score_width'] .. 'px') or '80px' local boldWinner = args.bold_winner and (args.bold_winner
'yes' or args.bold_winner
'true') local colorWinner = args.color_winner and (args.color_winner
'yes' or args.color_winner
'true')
local tableClass = 'wikitable' local tableStyle = 'text-align: center;' if args.collapsed and (args.collapsed
'yes' or args.collapsed
'true') then tableClass = 'wikitable mw-collapsible mw-collapsed' tableStyle = 'width: 100%; text-align: center;' end if args.nowrap and (args.nowrap
'yes' or args.nowrap
'true') then tableStyle = tableStyle .. ' white-space: nowrap;' end
-- Create the table element local table = root:tag('table') :addClass(tableClass) :cssText(tableStyle) if args.id then table:attr('id', args.id) -- Optional id parameter to allow anchor to table end
-- Add a caption to table if the "caption" parameter is passed if args.caption then table:tag('caption'):wikitext(args.caption) end
-- Count number of columns local colCount = 3 + legs
-- Add a title row above column headings if the "title" parameter is passed if args.title then local titleRow = table:tag('tr') titleRow:tag('th') :attr('colspan', colCount) :css('text-align', 'center') :wikitext(args.title) end
-- Create the header row with team and score columns local header = table:tag('tr') local defaultTeam1 = (args.h_a
'yes' or args.h_a
'true') and 'Home' or 'Team 1' local defaultTeam2 = (args.h_a
'yes' or args.h_a
'true') and 'Away' or 'Team 2' header:tag('th'):css('text-align', 'right'):css('width', teamWidth):wikitext(args['team1'] or defaultTeam1) header:tag('th'):css('width', scoreWidth):wikitext(args['aggregate'] or legs
-- Add columns for each leg if applicable if legs > 0 then for leg = 1, legs do local legHeading
-- Check if "legN" parameter is present if args['leg' .. leg] then legHeading = args['leg' .. leg] else -- Check if "leg_prefix" parameter is present if args.leg_prefix then -- Check if leg_prefix is y, yes, 1, or true if args.leg_prefix
'yes' or args.leg_prefix
'true' then legHeading = 'Leg ' .. leg else legHeading = args.leg_prefix .. ' ' .. leg end -- Check if "leg_suffix" parameter is present and does not equal y, yes, 1, or true elseif args.leg_suffix and args.leg_suffix ~= 'y' and args.leg_suffix ~= 'yes' and args.leg_suffix ~= '1' and args.leg_suffix ~= 'true' then legHeading = ordinal(leg) .. ' ' .. args.leg_suffix else legHeading = ordinal(leg) .. ' leg' end end
header:tag('th'):css('width', scoreWidth):wikitext(legHeading) end end
local step = (matchType
local row = table:tag('tr') local team1, aggregateScore, team2 local team1Winner, team2Winner, manualBold, manualColor = false, false, false, false local team1Asterick, team2Asterick = false, false
-- Process rows for national team matches if matchType
-- Clean the aggregate score local cleanAggregate = cleanScore(aggregateScore) -- Determine the winning team on aggregate team1, team2, team1Winner, team2Winner, manualBold, manualColor = determineWinner(cleanAggregate, matchType, team1, team2, boldWinner, colorWinner) -- Add background-color for winning team if set by user local team1Style = team1Winner and ((colorWinner or manualColor) and 'background-color: #CCFFCC;' or ) .. 'text-align: right;' or 'text-align: right;' local team2Style = team2Winner and ((colorWinner or manualColor) and 'background-color: #CCFFCC;' or ) .. 'text-align: left;' or 'text-align: left;' -- Generate text to display for each team local team1Text, team2Text if flagParam1 then -- Check whether youth team flag template with age level is used team1Text = (not team1Asterick and team1 ~= "" and team1 ~= nil) and (expandTemplate(frame, flagTemplate .. '-rt',)) or team1 team2Text = (not team2Asterick and team2 ~= "" and team2 ~= nil) and (expandTemplate(frame, flagTemplate,)) or team2 else -- Use standard national team flag template without age level team1Text = (not team1Asterick and team1 ~= "" and team1 ~= nil) and (expandTemplate(frame, flagTemplate .. '-rt',)) or team1 team2Text = (not team2Asterick and team2 ~= "" and team2 ~= nil) and (expandTemplate(frame, flagTemplate,)) or team2 end -- When set by user, adds blank flags when string is used for a team instead of national team flag template if fillBlanks then if team1Asterick then team1Text = team1Text .. '
' end if team2Asterick then team2Text = ' ' .. team2Text end end -- Create rows for aggregate score and team names, bolded if set by user row:tag('td'):cssText(team1Style):wikitext((team1Winner and (boldWinner or manualBold)) and '' .. team1Text .. '' or team1Text) row:tag('td'):css('text-align', 'center'):css('width', scoreWidth):wikitext(aggregateScore) row:tag('td'):cssText(team2Style):wikitext((team2Winner and (boldWinner or manualBold)) and '' .. team2Text .. '' or team2Text) else -- Process rows for club matches team1 = args[i] if noFlagIcons then -- Remove use of flag icons if set by user aggregateScore = args[i+1] team2 = args[i+2] else team1Icon, team1Variant = processIcon(args[i+1]) aggregateScore = args[i+2] team2 = args[i+3] team2Icon, team2Variant = processIcon(args[i+4]) end -- Clean the aggregate score local cleanAggregate = cleanScore(aggregateScore) -- Determine the winning team on aggregate team1, team2, team1Winner, team2Winner, manualBold, manualColor = determineWinner(cleanAggregate, matchType, team1, team2, boldWinner, colorWinner) -- Add background-color for winning team if set by user local team1Style = team1Winner and ((colorWinner or manualColor) and 'background-color: #CCFFCC;' or ) .. 'text-align: right;' or 'text-align: right;' local team2Style = team2Winner and ((colorWinner or manualColor) and 'background-color: #CCFFCC;' or ) .. 'text-align: left;' or 'text-align: left;' -- Generate text, and flags (if not disabled), to display for each team local team1Text = noFlagIcons and team1 or (team1Icon ~= "" and team1Icon ~= nil) and (team1 .. ' ' .. expandTemplate(frame, flagTemplate,)) or team1 local team2Text = noFlagIcons and team2 or (team2Icon ~= "" and team2Icon ~= nil) and (expandTemplate(frame, flagTemplate,) .. ' ' .. team2) or team2 -- When set by user, adds blank flags when country code parameter is left blank if fillBlanks then if not noFlagIcons then if not team1Icon or team1Icon-- Add columns for each leg score if applicable if legs > 0 then for leg = 1, legs do local legIndex = i + 4 + leg + (matchType
i = i + step end
return tostring(root)end
return p