Module:Sandbox/S.A. Julio Explained

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

1 and last_two_digits ~= 11 then return n .. 'st' elseif last_digit

2 and last_two_digits ~= 12 then return n .. 'nd' elseif last_digit

3 and last_two_digits ~= 13 then return n .. 'rd' else return n .. 'th' endend

-- 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 manualBold1 = team1:find("") and not (team1:gsub("", ""):match("^%s*$")) team1 = team1:gsub("", "") end if team2 and type(team2)

'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 manualColor1 = team1:find("") and not (team1:gsub("", ""):match("^%s*$")) team1 = team1:gsub("", "") end if team2 and type(team2)

'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

'NT' and ((not team1 or team1:match("^%s*$")) or (not team2 or team2:match("^%s*$"))) then -- Skip further processing if either team name is effectively empty return team1, team2, team1Winner, team2Winner, manualBold, manualColor end

-- 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

'WNT' or args.type

'MNT') and 'NT' or (args.type or 'club') -- Set default match type to 'club' local isWNT = args.type

'WNT' -- Track if WNT was set local flagTemplate, flagParam1 local noFlagIcons = false local fillBlanks = args.fill_blanks and (args.fill_blanks

'y' or args.fill_blanks

'yes' or args.fill_blanks

'1' or args.fill_blanks

'true')

-- 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

'NT' then flagTemplate = 'fb' -- Default to for NT/MNT matches else flagTemplate = 'fbaicon' -- Default to for club matches end end

if args.flag and (flagTemplate

'n' or flagTemplate

'no' or flagTemplate

'0' or flagTemplate

'false' or flagTemplate

'null' or flagTemplate

'none' or flagTemplate

'noflag') then noFlagIcons = true -- Hide flag icons for club matches if matchType

'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

'NT' and (flagTemplate ~= 'fb' and flagTemplate ~= 'fbw') then if not templateExists(flagTemplate) or not templateExists(flagTemplate .. '-rt') then flagTemplate = isWNT and 'fbw' or 'fb' end elseif not noFlagIcons and flagTemplate ~= 'fbaicon' then if not templateExists(flagTemplate) then flagTemplate = 'fbaicon' end end

local legs = (args.legs

'1' or args.legs

'n' or args.legs

'no' or args.legs

'false' or args.legs

'null' or args.legs

'none' or args.legs

'single' 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

'y' or args.bold_winner

'yes' or args.bold_winner

'1' or args.bold_winner

'true') local colorWinner = args.color_winner and (args.color_winner

'y' or args.color_winner

'yes' or args.color_winner

'1' or args.color_winner

'true')

local tableClass = 'wikitable' local tableStyle = 'text-align: center;' if args.collapsed and (args.collapsed

'y' or args.collapsed

'yes' or args.collapsed

'1' or args.collapsed

'true') then tableClass = 'wikitable mw-collapsible mw-collapsed' tableStyle = 'width: 100%; text-align: center;' end if args.nowrap and (args.nowrap

'y' or args.nowrap

'yes' or args.nowrap

'1' 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

'y' or args.h_a

'yes' or args.h_a

'1' or args.h_a

'true') and 'Home' or 'Team 1' local defaultTeam2 = (args.h_a

'y' or args.h_a

'yes' or args.h_a

'1' 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

0 and 'Score' or expandTemplate(frame, 'Abbrlink',)) header:tag('th'):css('text-align', 'left'):css('width', teamWidth):wikitext(args['team2'] or defaultTeam2)

-- 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

'y' or args.leg_prefix

'yes' or args.leg_prefix

'1' 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

'NT' and 3 or (noFlagIcons and 3 or 5)) + legs -- Determine the step size based on the match type and presence of flag icons local i = 1 while anyParameterPresent(i, step, args) do local rowIndex = math.floor((i - 1) / step) + 1 local headingParam = args['heading' .. rowIndex] -- Add a heading above a given row in the table if headingParam then local headingRow = table:tag('tr') headingRow:tag('td') :attr('colspan', colCount) :css('text-align', 'center') :css('background', 'whitesmoke') :wikitext('' .. headingParam .. '') end

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

'NT' then -- Check if team parameter beings with an asterick instead of a country code, indicating a string will be displayed instead of national team flag team1 = args[i] if team1 and team1:match("^%s*%*") then team1 = team1:gsub("^%s*%*", "") team1Asterick = true else team1, team1Variant = processIcon(args[i]) end aggregateScore = args[i+1] team2 = args[i+2] if team2 and team2:match("^%s*%*") then team2 = team2:gsub("^%s*%*", "") team2Asterick = true else team2, team2Variant = processIcon(args[i+2]) 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 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

"" then team1Text = team1Text .. '

' end if not team2Icon or team2Icon

"" then team2Text = '

' .. team2Text end 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) end

-- Add columns for each leg score if applicable if legs > 0 then for leg = 1, legs do local legIndex = i + 4 + leg + (matchType

'NT' and -2 or (noFlagIcons and -2 or 0)) local legScore = args[legIndex] if legScore ~= "null" then row:tag('td'):css('text-align', 'center'):css('width', scoreWidth):wikitext(legScore) end end end

i = i + step end

return tostring(root)end

return p