Difference between revisions of "Module:TeamBracket-Tennis"
Jump to navigation
Jump to search
blackwiki>Frietjes |
blackwiki>Frietjes |
||
| Line 11: | Line 11: | ||
local sets = {} | local sets = {} | ||
local padding | local padding | ||
| + | local hideSeeds | ||
local showSeeds | local showSeeds | ||
| − | local | + | local hideHeadings |
local showThird | local showThird | ||
local offsetThird | local offsetThird | ||
| Line 23: | Line 24: | ||
args[k] = v | args[k] = v | ||
end | end | ||
| + | |||
| + | -- fix non-standard args | ||
| + | local r = tonumber(args.rounds) or 2 | ||
| + | local unpad = (math.pow(2, r) < 10) | ||
| + | local rdstr = 'RD' .. tostring(r) | ||
| + | local rdp1str = 'RD' .. tostring(r+1) | ||
| + | for k,v in pairs(args) do | ||
| + | if type(k) == 'string' then | ||
| + | -- strip leading zeros if fewer than 10 teams | ||
| + | if unpad then | ||
| + | if k:find('^RD[0-9]%-[a-z][a-z]*0') then | ||
| + | args[mw.ustring.gsub(k, '^(RD[0-9]%-[a-z][a-z]*)0', '%1')] = v | ||
| + | tcats = tcats .. '[[Category:Pages using a tennis bracket with deprecated syntax|P]]' | ||
| + | end | ||
| + | end | ||
| + | -- fix non-uniform specification of 3rd | ||
| + | if k:find('^' .. rdp1str .. '%-[a-z][a-z]*0*[12]') then | ||
| + | args[mw.ustring.gsub(k, '^' .. rdp1str .. '(%-[a-z][a-z]*)0*([12])', '3rd%1%2')] = v | ||
| + | tcats = tcats .. '[[Category:Pages using a tennis bracket with deprecated syntax|3]]' | ||
| + | elseif k:find('^' .. rdstr .. '%-[a-z][a-z]*0*3') then | ||
| + | args[mw.ustring.gsub(k, '^' .. rdstr .. '(%-[a-z][a-z]*)0*3', '3rd%11')] = v | ||
| + | tcats = tcats .. '[[Category:Pages using a tennis bracket with deprecated syntax|3]]' | ||
| + | elseif k:find('^' .. rdstr .. '%-[a-z][a-z]*0*4') then | ||
| + | args[mw.ustring.gsub(k, '^' .. rdstr .. '(%-[a-z][a-z]*)0*4', '3rd%12')] = v | ||
| + | tcats = tcats .. '[[Category:Pages using a tennis bracket with deprecated syntax|3]]' | ||
| + | elseif k:find('^group[0-9]') then | ||
| + | tcats = tcats .. '[[Category:Pages using a tennis bracket with deprecated syntax|G]]' | ||
| + | end | ||
| + | end | ||
| + | end | ||
| + | |||
return args; | return args; | ||
end | end | ||
| − | function parseSets(s) | + | local function parseSets(s) |
s = mw.text.split((s or '5') .. '/', '[%s]*/[%s]*') | s = mw.text.split((s or '5') .. '/', '[%s]*/[%s]*') | ||
local n = showThird and (rounds + 1) or (rounds) | local n = showThird and (rounds + 1) or (rounds) | ||
| Line 40: | Line 72: | ||
end | end | ||
| − | + | local function addTableRow(tbl) | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | function addTableRow(tbl) | ||
return tbl:tag('tr') | return tbl:tag('tr') | ||
end | end | ||
| − | function addBlank(row, width) | + | local function addBlank(row, width) |
local cell = row:tag('td') | local cell = row:tag('td') | ||
if width then | if width then | ||
| Line 69: | Line 84: | ||
end | end | ||
| − | function addPath(rows, index, round, top, left) | + | local function addPath(rows, index, round, top, left) |
local prop = top and 'border-bottom-width' or 'border-top-width' | local prop = top and 'border-bottom-width' or 'border-top-width' | ||
if left and round == 1 then | if left and round == 1 then | ||
| Line 88: | Line 103: | ||
end | end | ||
| − | function addCompactPath(rows, index, round, top, left) | + | local function addCompactPath(rows, index, round, top, left) |
local prop = top and 'border-bottom-width' or 'border-top-width' | local prop = top and 'border-bottom-width' or 'border-top-width' | ||
if left and round == 1 then | if left and round == 1 then | ||
| Line 105: | Line 120: | ||
end | end | ||
| − | function getWidth(param, default) | + | local function getWidth(param, default) |
local arg = args[param .. '-width'] | local arg = args[param .. '-width'] | ||
if not arg or string.len(arg) == 0 then | if not arg or string.len(arg) == 0 then | ||
| Line 116: | Line 131: | ||
end | end | ||
| − | function getShadeArg(round, team, s) | + | local function getTeamArgName(round, type, team) |
| + | if round > rounds then | ||
| + | return string.format('3rd-%s%01d', type, team) | ||
| + | else | ||
| + | return string.format('RD%d-%s' .. padding, round, type, team) | ||
| + | end | ||
| + | end | ||
| + | |||
| + | local function getShadeArg(round, team, s) | ||
local argname = getTeamArgName(round, 'shade', team) .. (s and ('-' .. s) or '') | local argname = getTeamArgName(round, 'shade', team) .. (s and ('-' .. s) or '') | ||
local value = args[argname] | local value = args[argname] | ||
| Line 125: | Line 148: | ||
end | end | ||
| − | function getScoreArg(round, team, s) | + | local function getScoreArg(round, team, s) |
local argname = getTeamArgName(round, 'score', team) .. (s and ('-' .. s) or '') | local argname = getTeamArgName(round, 'score', team) .. (s and ('-' .. s) or '') | ||
local value = args[argname] | local value = args[argname] | ||
| Line 134: | Line 157: | ||
end | end | ||
| − | function getTeamArg(round, type, team) | + | local function getTeamArg(round, type, team) |
local argname = getTeamArgName(round, type, team) | local argname = getTeamArgName(round, type, team) | ||
local value = args[argname] | local value = args[argname] | ||
| Line 146: | Line 169: | ||
end | end | ||
| − | + | local function getRoundName(round) | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | function getRoundName(round) | ||
local name = args['RD' .. round] | local name = args['RD' .. round] | ||
if name and string.len(name) > 0 then | if name and string.len(name) > 0 then | ||
| Line 171: | Line 186: | ||
end | end | ||
| − | function renderTeam(row, round, team, top, compact) | + | local function renderTeam(row, round, team, top, compact) |
local seedCell | local seedCell | ||
local seedArg = getTeamArg(round, 'seed', team) | local seedArg = getTeamArg(round, 'seed', team) | ||
| Line 178: | Line 193: | ||
team % 2 == 0 and team - 1 or team + 1) | team % 2 == 0 and team - 1 or team + 1) | ||
-- show seed if seed is defined for either or both | -- show seed if seed is defined for either or both | ||
| − | local showSeed = seedArg and string.len(seedArg) > 0 | + | local showSeed = showSeeds |
| − | or pairSeedArg and string.len(pairSeedArg) > 0 | + | or (seedArg and string.len(seedArg) > 0) |
| − | if showSeed and | + | or (pairSeedArg and string.len(pairSeedArg) > 0) |
| + | if showSeed and (not hideSeeds) then | ||
seedCell = row:tag('td') | seedCell = row:tag('td') | ||
:css('text-align', 'center') | :css('text-align', 'center') | ||
| Line 211: | Line 227: | ||
:wikitext(teamArg) | :wikitext(teamArg) | ||
:newline() | :newline() | ||
| − | if not showSeed and | + | if not showSeed and (not hideSeeds) then |
teamCell:attr('colspan', '2') | teamCell:attr('colspan', '2') | ||
end | end | ||
| Line 232: | Line 248: | ||
end | end | ||
| − | function renderRound(rows, count, r) | + | local function renderRound(rows, count, r) |
local teams = math.pow(2, rounds - r + 1) | local teams = math.pow(2, rounds - r + 1) | ||
local step = count / teams | local step = count / teams | ||
| Line 253: | Line 269: | ||
if height > 0 then | if height > 0 then | ||
blank = addBlank(rows[offset]) | blank = addBlank(rows[offset]) | ||
| − | :attr('colspan', tonumber( | + | :attr('colspan', tonumber(hideSeeds and '3' or '4') + sets[r]) |
:attr('rowspan', height) | :attr('rowspan', height) | ||
:css('border-color', 'black') | :css('border-color', 'black') | ||
| Line 275: | Line 291: | ||
end | end | ||
| − | function renderCompactRound(rows, count, r) | + | local function renderCompactRound(rows, count, r) |
local teams = math.pow(2, rounds - r + 1) | local teams = math.pow(2, rounds - r + 1) | ||
local step = count / teams | local step = count / teams | ||
| Line 292: | Line 308: | ||
if height > 0 then | if height > 0 then | ||
blank = addBlank(rows[offset]) | blank = addBlank(rows[offset]) | ||
| − | :attr('colspan', tonumber( | + | :attr('colspan', tonumber(hideSeeds and '3' or '4') + sets[r]) |
:css('border-color', 'black') | :css('border-color', 'black') | ||
:css('border-style', 'solid') | :css('border-style', 'solid') | ||
| Line 314: | Line 330: | ||
end | end | ||
| − | function renderGroups(rows, count, round) | + | local function renderGroups(rows, count, round) |
local roundFromLast = rounds - round + 1 | local roundFromLast = rounds - round + 1 | ||
local groups = math.pow(2, roundFromLast - 2) | local groups = math.pow(2, roundFromLast - 2) | ||
| Line 322: | Line 338: | ||
for r = 1,round do | for r = 1,round do | ||
| − | offset = offset + ( | + | offset = offset + (hideSeeds and 3 or 4) + sets[r] |
end | end | ||
for i = step / 2, count, step do | for i = step / 2, count, step do | ||
| Line 341: | Line 357: | ||
end | end | ||
| − | function renderThird(rows, count, compact) | + | local function renderThird(rows, count, compact) |
local k = offsetThird | local k = offsetThird | ||
local row = rows[k] | local row = rows[k] | ||
| Line 347: | Line 363: | ||
--if (offsetThird < count) then | --if (offsetThird < count) then | ||
--blank = addBlank(row) | --blank = addBlank(row) | ||
| − | --blank:attr('colspan', tonumber( | + | --blank:attr('colspan', tonumber(hideSeeds and '3' or '4') + sets[1]) |
--end | --end | ||
blank = addBlank(row) | blank = addBlank(row) | ||
row:tag('td') | row:tag('td') | ||
| − | :attr('colspan', tonumber( | + | :attr('colspan', tonumber(hideSeeds and '1' or '2') + sets[rounds + 1]) |
:css('text-align', 'center') | :css('text-align', 'center') | ||
:css('border', '1px solid #aaa') | :css('border', '1px solid #aaa') | ||
| Line 367: | Line 383: | ||
end | end | ||
| − | function renderTree(tbl, compact) | + | local function renderTree(tbl, compact) |
-- create 3 or 1 rows for every team | -- create 3 or 1 rows for every team | ||
local count = math.pow(2, rounds) * (compact and 1 or 3) | local count = math.pow(2, rounds) * (compact and 1 or 3) | ||
| Line 390: | Line 406: | ||
if (rounds > 1) then | if (rounds > 1) then | ||
local blank = addBlank(rows[i]) | local blank = addBlank(rows[i]) | ||
| − | blank:attr('colspan', tonumber( | + | blank:attr('colspan', tonumber(hideSeeds and '3' or '4') + sets[1]) |
if compact and (rounds > 2) then | if compact and (rounds > 2) then | ||
blank = addBlank(rows[i]) | blank = addBlank(rows[i]) | ||
| − | blank:attr('colspan', tonumber( | + | blank:attr('colspan', tonumber(hideSeeds and '3' or '4') + sets[1]) |
end | end | ||
end | end | ||
| Line 417: | Line 433: | ||
end | end | ||
| − | function renderHeading(tbl, compact) | + | local function renderHeading(tbl, compact) |
| − | local titleRow = addTableRow( | + | local titleRow = addTableRow((not hideHeadings) and tbl or mw.html.create('table')) |
local widthRow = addTableRow(tbl) | local widthRow = addTableRow(tbl) | ||
for r = 1, rounds do | for r = 1, rounds do | ||
| Line 424: | Line 440: | ||
addBlank(widthRow, r > 1 and '5px' or '1px') | addBlank(widthRow, r > 1 and '5px' or '1px') | ||
titleRow:tag('td') | titleRow:tag('td') | ||
| − | :attr('colspan', tonumber( | + | :attr('colspan', tonumber(hideSeeds and '1' or '2') + sets[r]) |
:css('text-align', 'center') | :css('text-align', 'center') | ||
:css('border', '1px solid #aaa') | :css('border', '1px solid #aaa') | ||
| Line 431: | Line 447: | ||
:newline() | :newline() | ||
local seedCell | local seedCell | ||
| − | if | + | if (not hideSeeds) then |
seedCell = addBlank(widthRow, getWidth('seed', '25px')) | seedCell = addBlank(widthRow, getWidth('seed', '25px')) | ||
end | end | ||
| Line 461: | Line 477: | ||
local teams = math.pow(2, rounds) | local teams = math.pow(2, rounds) | ||
padding = '%0' .. (teams < 10 and 1 or 2) .. 'd' | padding = '%0' .. (teams < 10 and 1 or 2) .. 'd' | ||
| − | + | local compact = (args['compact'] and (args['compact'] == 'yes' or args['compact'] == 'y')) | |
| − | + | hideSeeds = (args['seeds'] and (args['seeds'] == 'no' or args['seeds'] == 'n')) | |
| − | + | showSeeds = (args['seeds'] and (args['seeds'] == 'yes' or args['seeds'] == 'y')) | |
| − | + | hideHeadings = (args['headings'] and (args['headings'] == 'no' or args['headings'] == 'n')) | |
| − | + | showThird = (args['3rd'] and args['3rd'] ~= '') | |
| − | |||
| − | |||
| − | |||
| − | showThird = | ||
| − | |||
| − | |||
| − | |||
parseSets(args.sets) | parseSets(args.sets) | ||
| − | -- | + | -- create the table |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
local tbl = mw.html.create('table') | local tbl = mw.html.create('table') | ||
:css('border-style', 'none') | :css('border-style', 'none') | ||
| Line 493: | Line 493: | ||
:attr('cellpadding', '0') | :attr('cellpadding', '0') | ||
| − | if args['nowrap'] and args['nowrap'] | + | if (args['nowrap'] and (args['nowrap'] == 'yes' or args['nowrap'] == 'y')) then |
tbl:css('white-space', 'nowrap') | tbl:css('white-space', 'nowrap') | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
end | end | ||
renderHeading(tbl, compact) | renderHeading(tbl, compact) | ||
renderTree(tbl, compact) | renderTree(tbl, compact) | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
return tostring(tbl) .. tcats | return tostring(tbl) .. tcats | ||
end | end | ||
return p | return p | ||
Revision as of 21:15, 18 April 2017
| 40px | This Lua module is used on 19,000+ pages and changes may be widely noticed. Test changes in the module's /sandbox or /testcases subpages. Consider discussing changes at Wikipedia talk:High-risk templates before implementing them.
Transclusion count updated automatically (see documentation). |
| 40x40px | This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
This template implements a variant of Module:TeamBracket for tennis tournaments. It is a generic visual representation of the tournament bracket. For common usage, use the templates in Category:Tennis tournament bracket templates.
Usage
{{#invoke: TeamBracket-Tennis | teamBracket
| rounds =
| sets =
| seeds = <!-- yes / no / or blank -->
| compact = <!-- yes / no / or blank -->
| nowrap = <!-- yes / no / or blank -->
| seed-width =
| team-width =
| score-width =
| RD1 =
| RD1-seed1 =
| RD1-team1 =
| RD1-score1-1 =
| RD1-score1-2 =
| RD1-score1-3 =
}}
Parameter list
The parameters are as follows:
seed-width –the width of the cells for seeds.team-width –the width of the cells for team names.score-width –the width of the cells for scores.compact –set toyesfor compact formatseeds –set tonoto omit seed cells, andyesto always show seed cellsnowrap –set toyesto prevent lines from wrappingbyes –set to1,2, ... to specify the maximum round number with byesheadings –set tonoto omit the column headings
RDn –The name of round n.RDn-seedm –The seed of team m in round n.RDn-teamm –The name of team m in round n.RDn-scorem-s –The score of set s for team m in round n.RDn-groupm –Label for the mth group in round n.
Examples
{{#invoke: TeamBracket-Tennis | teamBracket
| rounds = 2
| sets = 3
| RD1-seed1 = '''1'''
| RD1-seed2 = 4
| RD1-team1 = '''John'''
| RD1-team2 = Declan
| RD1-score1-1 = '''6'''
| RD1-score2-1 = 0
| RD1-score1-2 = 3
| RD1-score2-2 = '''6'''
| RD1-score1-3 = '''7'''
| RD1-score2-3 = 6
| RD1-seed3 = 2
| RD1-seed4 = 3
| RD1-team3 = Barry
| RD1-team4 = Steve
| RD2-seed1 = 1
| RD2-team1 = John
}}
| Semifinals | Finals | ||||||||||||
| 1 | John | 6 | 3 | 7 | |||||||||
| 4 | Declan | 0 | 6 | 6 | |||||||||
| 1 | John | ||||||||||||
| 2 | Barry | ||||||||||||
| 3 | Steve | ||||||||||||
Templates using this module
- {{2TeamBracket-Tennis3}}
- {{2TeamBracket-Tennis5}}
- {{2TeamBracket-Tennis7}}
- {{2TeamBracket-Tennis9}}
- {{2TeamBracket-Compact-Tennis3}}
- {{2TeamBracket-Compact-Tennis5}}
- {{4TeamBracket-Tennis3}}
- {{4TeamBracket-Tennis5}}
- {{4TeamBracket-Tennis35}}
- {{4TeamBracket-Tennis3-with third}}
- {{4TeamBracket-Tennis35-with third}}
- {{4TeamBracket-Tennis5-with 3rd}}
- {{4TeamBracket-Tennis7-with 3rd}}
- {{4TeamBracket-Compact-Tennis3}}
- {{4TeamBracket-Compact-Tennis7}}
- {{8TeamBracket-Tennis3}}
- {{8TeamBracket-Tennis5}}
- {{8TeamBracket-Tennis35}}
- {{8TeamBracket-Tennis353}}
- {{8TeamBracket-Tennis355}}
- {{8TeamBracket-Tennis3-with third}}
- {{8TeamBracket-Tennis5-with third}}
- {{8TeamBracket-Tennis35-with third}}
- {{8TeamBracket-Compact-Tennis7}}
- {{16TeamBracket-Tennis3}}
- {{16TeamBracket-Tennis5}}
- {{16TeamBracket-Tennis5777}}
- {{16TeamBracket-Compact-Tennis3}}
- {{16TeamBracket-Compact-Tennis5}}
- {{16TeamBracket-Compact-Tennis35}}
- {{16TeamBracket-Compact-Tennis7}}
- {{16TeamBracket-Compact-Tennis3355}}
- {{16TeamBracket-Compact-Tennis3555}}
- {{16TeamBracket-Compact-Tennis3-with 3rd}}
- {{16TeamBracket-Compact-Tennis7-with 3rd}}
- {{32TeamBracket-Tennis3}}
- {{32TeamBracket-Tennis5}}
--
-- This module implements
-- {{4TeamBracket-Tennis3}}, {{4TeamBracket-Tennis5}}
-- {{8TeamBracket-Tennis3}}, {{8TeamBracket-Tennis5}}, {{8TeamBracket-Tennis35}}
-- {{16TeamBracket-Tennis3}}
--
local p = {}
local args
local rounds
local sets = {}
local padding
local hideSeeds
local showSeeds
local hideHeadings
local showThird
local offsetThird
local tcats = ''
local function getArgs(frame)
local parent = frame:getParent();
local args = parent.args;
for k,v in pairs(frame.args) do
args[k] = v
end
-- fix non-standard args
local r = tonumber(args.rounds) or 2
local unpad = (math.pow(2, r) < 10)
local rdstr = 'RD' .. tostring(r)
local rdp1str = 'RD' .. tostring(r+1)
for k,v in pairs(args) do
if type(k) == 'string' then
-- strip leading zeros if fewer than 10 teams
if unpad then
if k:find('^RD[0-9]%-[a-z][a-z]*0') then
args[mw.ustring.gsub(k, '^(RD[0-9]%-[a-z][a-z]*)0', '%1')] = v
tcats = tcats .. '[[Category:Pages using a tennis bracket with deprecated syntax|P]]'
end
end
-- fix non-uniform specification of 3rd
if k:find('^' .. rdp1str .. '%-[a-z][a-z]*0*[12]') then
args[mw.ustring.gsub(k, '^' .. rdp1str .. '(%-[a-z][a-z]*)0*([12])', '3rd%1%2')] = v
tcats = tcats .. '[[Category:Pages using a tennis bracket with deprecated syntax|3]]'
elseif k:find('^' .. rdstr .. '%-[a-z][a-z]*0*3') then
args[mw.ustring.gsub(k, '^' .. rdstr .. '(%-[a-z][a-z]*)0*3', '3rd%11')] = v
tcats = tcats .. '[[Category:Pages using a tennis bracket with deprecated syntax|3]]'
elseif k:find('^' .. rdstr .. '%-[a-z][a-z]*0*4') then
args[mw.ustring.gsub(k, '^' .. rdstr .. '(%-[a-z][a-z]*)0*4', '3rd%12')] = v
tcats = tcats .. '[[Category:Pages using a tennis bracket with deprecated syntax|3]]'
elseif k:find('^group[0-9]') then
tcats = tcats .. '[[Category:Pages using a tennis bracket with deprecated syntax|G]]'
end
end
end
return args;
end
local function parseSets(s)
s = mw.text.split((s or '5') .. '/', '[%s]*/[%s]*')
local n = showThird and (rounds + 1) or (rounds)
for r=1,n do
if s[r] ~= nil and s[r] ~= '' and tonumber(s[r]) then
sets[r] = tonumber(s[r])
elseif sets[r-1] then
sets[r] = sets[r-1]
else
sets[r] = 5
end
end
end
local function addTableRow(tbl)
return tbl:tag('tr')
end
local function addBlank(row, width)
local cell = row:tag('td')
if width then
cell:css('width', width)
end
return cell
end
local function addPath(rows, index, round, top, left)
local prop = top and 'border-bottom-width' or 'border-top-width'
if left and round == 1 then
addBlank(rows[index]):css('height', '7px')
addBlank(rows[index + 1]):css('height', '7px')
return nil
else
local cell = addBlank(rows[index])
:attr('rowspan', '2')
:css('border-width', '0')
:css('border-style', 'solid')
:css('border-color', 'black')
if left or round < rounds and not left then
cell:css(prop, '2px')
end
return cell
end
end
local function addCompactPath(rows, index, round, top, left)
local prop = top and 'border-bottom-width' or 'border-top-width'
if left and round == 1 then
addBlank(rows[index])
return nil
else
local cell = addBlank(rows[index])
:css('border-width', '0')
:css('border-style', 'solid')
:css('border-color', 'black')
if left or round < rounds and not left then
cell:css(prop, '2px')
end
return cell
end
end
local function getWidth(param, default)
local arg = args[param .. '-width']
if not arg or string.len(arg) == 0 then
arg = default
end
if tonumber(arg) ~= nil then
arg = arg .. 'px'
end
return arg
end
local function getTeamArgName(round, type, team)
if round > rounds then
return string.format('3rd-%s%01d', type, team)
else
return string.format('RD%d-%s' .. padding, round, type, team)
end
end
local function getShadeArg(round, team, s)
local argname = getTeamArgName(round, 'shade', team) .. (s and ('-' .. s) or '')
local value = args[argname]
if not value or string.len(value) == 0 then
return '#f9f9f9'
end
return value
end
local function getScoreArg(round, team, s)
local argname = getTeamArgName(round, 'score', team) .. (s and ('-' .. s) or '')
local value = args[argname]
if not value or string.len(value) == 0 then
return ''
end
return value
end
local function getTeamArg(round, type, team)
local argname = getTeamArgName(round, type, team)
local value = args[argname]
if not value or string.len(value) == 0 then
return ''
end
if mw.ustring.find(value, '[%s]*<[%s/]*[Bb][Rr][%s/]*>[%s ]*&[Nn][Bb][Ss][Pp];[%s]*') then
tcats = '[[Category:Pages using a tennis bracket with nbsp]]'
end
return mw.ustring.gsub(value, '[%s]*<[%s/]*[Bb][Rr][%s/]*>[%s ]*&[Nn][Bb][Ss][Pp];[%s]*', '<br/>')
end
local function getRoundName(round)
local name = args['RD' .. round]
if name and string.len(name) > 0 then
return name
end
local roundFromLast = rounds - round + 1
if roundFromLast == 1 then
return "Finals"
elseif roundFromLast == 2 then
return "Semifinals"
elseif roundFromLast == 3 then
return "Quarterfinals"
else
return "Round of " .. math.pow(2, roundFromLast)
end
end
local function renderTeam(row, round, team, top, compact)
local seedCell
local seedArg = getTeamArg(round, 'seed', team)
-- seed value for the paired team
local pairSeedArg = getTeamArg(round, 'seed',
team % 2 == 0 and team - 1 or team + 1)
-- show seed if seed is defined for either or both
local showSeed = showSeeds
or (seedArg and string.len(seedArg) > 0)
or (pairSeedArg and string.len(pairSeedArg) > 0)
if showSeed and (not hideSeeds) then
seedCell = row:tag('td')
:css('text-align', 'center')
:css('background-color', '#f2f2f2')
:css('border-color', '#aaa')
:css('border-style', 'solid')
:css('border-top-width', '1px')
:css('border-left-width', '1px')
:css('border-right-width', '1px')
:css('border-bottom-width', top and '0' or '1px')
:attr('rowspan', (not compact) and '2' or nil)
:wikitext(seedArg)
:newline()
end
local teamArg = getTeamArg(round, 'team', team)
if not teamArg or string.len(teamArg) == 0 then
teamArg = ' '
end
local teamCell = row:tag('td')
:css('background-color', '#f9f9f9')
:css('border-color', '#aaa')
:css('border-style', 'solid')
:css('border-top-width', '1px')
:css('border-left-width', '1px')
:css('border-right-width', '1px')
:css('border-bottom-width', top and '0' or '1px')
:css('padding', '0 2px')
:attr('rowspan', (not compact) and '2' or nil)
:wikitext(teamArg)
:newline()
if not showSeed and (not hideSeeds) then
teamCell:attr('colspan', '2')
end
local scoreCells = {}
for s = 1, sets[round] do
scoreCells[s] = row:tag('td')
:css('text-align', 'center')
:css('border-color', '#aaa')
:css('border-style', 'solid')
:css('border-top-width', '1px')
:css('border-left-width', '0')
:css('border-right-width', '1px')
:css('border-bottom-width', top and '0' or '1px')
:css('background-color', getShadeArg(round, team, s))
:attr('rowspan', (not compact) and '2' or nil)
:wikitext(getScoreArg(round, team, s))
:newline()
end
end
local function renderRound(rows, count, r)
local teams = math.pow(2, rounds - r + 1)
local step = count / teams
local topTeam = true -- is top row in match-up
local topPair = true -- is top match-up in pair of match-ups
local team = 1
for i = 1, count, step do
local offset, height, blank
-- leave room for groups for teams other than first and last
if team == 1 or team == teams then
offset = topTeam and i or i + 2
height = step - 2
else
offset = topTeam and i + 1 or i + 2
height = step - 3
end
if showThird and (r == rounds) and (not topTeam) then
height = 0
end
if height > 0 then
blank = addBlank(rows[offset])
:attr('colspan', tonumber(hideSeeds and '3' or '4') + sets[r])
:attr('rowspan', height)
:css('border-color', 'black')
:css('border-style', 'solid')
:css('border-width', '0')
end
-- add bracket
local j = topTeam and i + step - 2 or i
-- add left path
addPath(rows, j, r, topTeam, true)
renderTeam(rows[j], r, team, topTeam, false)
local rightPath = addPath(rows, j, r, topTeam, false)
if not topTeam then topPair = not topPair end
if not topPair and r < rounds then
if blank then blank:css('border-right-width', '2px') end
rightPath:css('border-right-width', '2px')
end
team = team + 1
topTeam = not topTeam
end
end
local function renderCompactRound(rows, count, r)
local teams = math.pow(2, rounds - r + 1)
local step = count / teams
local topTeam = true -- is top row in match-up
local topPair = true -- is top match-up in pair of match-ups
local team = 1
for i = 1, count, step do
local offset, height, blank
-- empty space above or below
local offset = topTeam and i or i + 1
local height = step - 1
if showThird and (r == rounds) and (not topTeam) then
height = 0
end
if height > 0 then
blank = addBlank(rows[offset])
:attr('colspan', tonumber(hideSeeds and '3' or '4') + sets[r])
:css('border-color', 'black')
:css('border-style', 'solid')
:css('border-width', '0')
:attr('rowspan', height)
end
-- add bracket
local j = topTeam and i + step - 1 or i
-- add left path
addCompactPath(rows, j, r, topTeam, true)
renderTeam(rows[j], r, team, topTeam, true)
local rightPath = addCompactPath(rows, j, r, topTeam, false)
if not topTeam then topPair = not topPair end
if not topPair and r < rounds then
if blank then blank:css('border-right-width', '2px') end
rightPath:css('border-right-width', '2px')
end
team = team + 1
topTeam = not topTeam
end
end
local function renderGroups(rows, count, round)
local roundFromLast = rounds - round + 1
local groups = math.pow(2, roundFromLast - 2)
local step = count / groups
local group = 1
local offset = 0
for r = 1,round do
offset = offset + (hideSeeds and 3 or 4) + sets[r]
end
for i = step / 2, count, step do
local name = 'RD' .. round .. '-group' .. group
addBlank(rows[i]):css('height', '7px')
addBlank(rows[i + 1]):css('height', '7px')
addBlank(rows[i])
:attr('rowspan', '2')
:attr('colspan', offset - 1)
:css('text-align', 'center')
:css('border-color', 'black')
:css('border-style', 'solid')
:css('border-width', '0 2px 0 0')
:wikitext(args[name])
:newline()
group = group + 1
end
end
local function renderThird(rows, count, compact)
local k = offsetThird
local row = rows[k]
local blank
--if (offsetThird < count) then
--blank = addBlank(row)
--blank:attr('colspan', tonumber(hideSeeds and '3' or '4') + sets[1])
--end
blank = addBlank(row)
row:tag('td')
:attr('colspan', tonumber(hideSeeds and '1' or '2') + sets[rounds + 1])
:css('text-align', 'center')
:css('border', '1px solid #aaa')
:css('background-color', '#f2f2f2')
:attr('rowspan', compact and 1 or 2)
:wikitext(args['3rd'])
:newline()
k = k + (compact and 2 or 3)
for i = 1,2 do
row = rows[k]
blank = addBlank(row)
renderTeam(row, rounds + 1, i, (i == 1) and true or false, compact)
k = k + (compact and 1 or 2)
end
end
local function renderTree(tbl, compact)
-- create 3 or 1 rows for every team
local count = math.pow(2, rounds) * (compact and 1 or 3)
local offsetcount = 2 * (compact and 1 or 3) + (compact and 2 or 3)
local rows = {}
offsetThird = (compact and 1 or 3) * (math.pow(2, rounds) - math.pow(2, rounds-3)) - (compact and 2 or 4)
if rounds < 4 then
offsetThird = compact and 8 or 17
if rounds < 3 then
offsetThird = compact and 6 or 10
if rounds < 2 then
offsetThird = compact and 4 or 6
end
end
end
for i = 1, count do
rows[i] = addTableRow(tbl)
end
if showThird then
for i = (count+1), (offsetcount + offsetThird) do
rows[i] = addTableRow(tbl)
if (rounds > 1) then
local blank = addBlank(rows[i])
blank:attr('colspan', tonumber(hideSeeds and '3' or '4') + sets[1])
if compact and (rounds > 2) then
blank = addBlank(rows[i])
blank:attr('colspan', tonumber(hideSeeds and '3' or '4') + sets[1])
end
end
end
end
if not compact then
-- fill rows with groups
for r = 1, rounds - 1 do
renderGroups(rows, count, r)
end
end
-- fill rows with bracket
for r = 1, rounds do
if compact then
renderCompactRound(rows, count, r)
else
renderRound(rows, count, r)
end
end
if showThird then
renderThird(rows, count, compact)
end
end
local function renderHeading(tbl, compact)
local titleRow = addTableRow((not hideHeadings) and tbl or mw.html.create('table'))
local widthRow = addTableRow(tbl)
for r = 1, rounds do
addBlank(titleRow)
addBlank(widthRow, r > 1 and '5px' or '1px')
titleRow:tag('td')
:attr('colspan', tonumber(hideSeeds and '1' or '2') + sets[r])
:css('text-align', 'center')
:css('border', '1px solid #aaa')
:css('background-color', '#f2f2f2')
:wikitext(getRoundName(r))
:newline()
local seedCell
if (not hideSeeds) then
seedCell = addBlank(widthRow, getWidth('seed', '25px'))
end
local teamCell = addBlank(widthRow, getWidth('team', '150px'))
local scoreCells = {}
for s = 1, sets[r] do
scoreCells[s] = addBlank(widthRow, getWidth('score', '12px'))
end
addBlank(titleRow)
addBlank(widthRow, r < rounds and '5px' or '1px')
if compact then
teamCell:css('height', '7px')
else
if seedCell then
seedCell:wikitext(' ')
end
teamCell:wikitext(' ')
for s = 1, sets[r] do
scoreCells[s]:wikitext(' ')
end
end
end
end
function p.teamBracket(frame)
args = getArgs(frame)
rounds = tonumber(args.rounds) or 2
local teams = math.pow(2, rounds)
padding = '%0' .. (teams < 10 and 1 or 2) .. 'd'
local compact = (args['compact'] and (args['compact'] == 'yes' or args['compact'] == 'y'))
hideSeeds = (args['seeds'] and (args['seeds'] == 'no' or args['seeds'] == 'n'))
showSeeds = (args['seeds'] and (args['seeds'] == 'yes' or args['seeds'] == 'y'))
hideHeadings = (args['headings'] and (args['headings'] == 'no' or args['headings'] == 'n'))
showThird = (args['3rd'] and args['3rd'] ~= '')
parseSets(args.sets)
-- create the table
local tbl = mw.html.create('table')
:css('border-style', 'none')
:css('font-size', '90%')
:css('margin', '1em 2em 1em 1em')
:css('border-collapse', 'separate')
:css('border-spacing', '0')
:attr('cellpadding', '0')
if (args['nowrap'] and (args['nowrap'] == 'yes' or args['nowrap'] == 'y')) then
tbl:css('white-space', 'nowrap')
end
renderHeading(tbl, compact)
renderTree(tbl, compact)
return tostring(tbl) .. tcats
end
return p