Module:TeamBracket
跳到导航
跳到搜索
此模块用于实现比赛进程模板Template:16TeamBracket等的功能。
使用方法
{{#invoke: TeamBracket | teamBracket | rounds = | seed-width = | team-width = | score-width = | RD1 = | RD1-group1 = | RD1-seed1 = | RD1-team1 = | RD1-score1 = ... }}
参数用法
rounds –
比赛回合数。seed-width –
选手编号列宽度。(可不填)team-width –
选手列宽度。(可不填)score-width –
得分(比赛结果)宽度。(可不填)seeds –
当参数为no
时隐藏全部选手号码。compact –
当参数位yes
时,禁用全部小组名。RDn –
第“n”轮比赛名称。RDn-groupm –
第“n”轮第“m”小组名称。RDn-seedm –
“m”选手第“n”轮编号。RDn-teamm –
第“n”轮“m”选手名称。RDn-scorem –
“m”选手在第“n”轮比赛中的得分(比赛结果)。
参数含义
- seed-width
- 选手编号列宽度(不填时根据内容自适应)。对应值:
N [em/%/px]
auto
- team-width
- 选手名称列宽度(不填时根据内容自适应)。
- score-width
- 得分(比赛结果)列编号列宽度(不填时根据内容自适应)。
- RDn
- 每轮比赛的名字,默认值为:“m”强赛……“四分之一决赛”,“半决赛”,“决赛”,其中“m”为当前这轮比赛中队伍的总和。
- RDn-groupm
- 第n轮第第“m”小组名称。每轮比赛四队为一个小组。
- RDn-seedm
- 队伍m在第n轮的号码。在第一轮比赛中,默认值为锦标赛中惯用的队伍编号(第一轮赛时)。如果省略,除第1轮赛以外的Seed列都会被隐藏。如需隐藏第1轮比赛中队伍的号码,请不要设置第一轮赛中队伍的号码,并将Seeds参数设为“no”。“m”的值从1开始。
- RDn-teamm
- 队伍m在第n轮的名称。“m”的值从1开始。
- RDn-scorem
- ::队伍m在第n轮的得分(比赛结果)。“m”的值从1开始。
用例
无号码
{{#invoke: TeamBracket | teamBracket | rounds = 2 | RD1-seed1 = | RD1-seed2 = | RD1-seed3 = | RD1-seed4 = }}
半决赛 | 决赛 | ||||||||
分组
{{#invoke: TeamBracket | teamBracket | rounds = 3 | RD1-group1 = 1月4日 | RD1-group2 = 1月5日 | RD2-group1 = 1月6日 }}
四分之一决赛 | 半决赛 | 决赛 | ||||||||||||
1 | ||||||||||||||
8 | ||||||||||||||
1月4日 | ||||||||||||||
5 | ||||||||||||||
4 | ||||||||||||||
1月6日 | ||||||||||||||
3 | ||||||||||||||
6 | ||||||||||||||
1月5日 | ||||||||||||||
7 | ||||||||||||||
2 | ||||||||||||||
- --
- -- This module will implement {{TeamBracket}}
- --
- local p = {}
- local args
- local rounds
- local padding
- local hideSeeds
- local showSeeds
- local function getArgs(frame)
- local parent = frame:getParent();
- local args = parent.args;
- for k,v in pairs(frame.args) do
- args[k] = v
- end
- return args;
- end
- function getSeeds()
- local seeds = {1, 2}
- local count = 2
- local before = false
- for r = 2, rounds do
- local max = math.pow(2, r)
- for i = 1, count do
- local pos = i * 2
- if before then pos = pos - 1 end
- table.insert(seeds, pos, max - seeds[i * 2 - 1] + 1)
- before = not before
- end
- count = count * 2
- end
- return seeds
- end
- function addTableRow(tbl)
- return tbl:tag('tr')
- end
- function addBlank(row, width)
- local cell = row:tag('td')
- if width then
- cell:css('width', width)
- end
- return cell
- end
- 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
- 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
- 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
- function getTeamArg(round, type, team)
- return args[getTeamArgName(round, type, team)]
- end
- function getTeamArgName(round, type, team)
- return string.format('RD%d-%s' .. padding, round, type, team)
- end
- 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 "决赛"
- elseif roundFromLast == 2 then
- return "半决赛"
- elseif roundFromLast == 3 then
- return "四分之一决赛"
- else
- return math.pow(2, roundFromLast).."强赛"
- end
- end
- 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', '0')
- :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', '0')
- :css('border-bottom-width', '0')
- :css('padding', '0 2px')
- :wikitext(teamArg)
- :newline()
- if not showSeed and (not hideSeeds) then
- teamCell:attr('colspan', '2')
- end
- local scoreCell = row:tag('td')
- :css('text-align', 'center')
- :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', '0')
- :css('background-color', '#f9f9f9')
- :wikitext(getTeamArg(round, 'score', team))
- :newline()
- if not compact then
- if seedCell then
- seedCell:attr('rowspan', '2')
- :css('border-bottom-width', '1px')
- end
- scoreCell:attr('rowspan', '2')
- :css('border-bottom-width', '1px')
- teamCell:attr('rowspan', '2')
- :css('border-right-width', '1px')
- :css('border-bottom-width', '1px')
- else
- if not top then
- if seedCell then
- seedCell:css('border-bottom-width', '1px')
- end
- teamCell:css('border-bottom-width', '1px')
- scoreCell:css('border-bottom-width', '1px')
- end
- end
- end
- 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 height > 0 then
- blank = addBlank(rows[offset])
- :attr('colspan', hideSeeds and '4' or '5')
- :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
- 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 height > 0 then
- blank = addBlank(rows[offset])
- :attr('colspan', hideSeeds and '4' or '5')
- :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
- function renderGroups(rows, count, round)
- local roundFromLast = rounds - round + 1
- local groups = math.pow(2, roundFromLast - 2)
- local step = count / groups
- local group = 1
- 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', (hideSeeds and 4 or 5) * round - 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
- function renderTree(tbl, compact)
- -- create 3 or 1 rows for every team
- local count = math.pow(2, rounds) * (compact and 1 or 3)
- local rows = {}
- for i = 1, count do
- rows[i] = addTableRow(tbl)
- 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
- end
- function renderHeading(tbl, compact)
- local titleRow = addTableRow(tbl)
- local widthRow = addTableRow(tbl)
- for r = 1, rounds do
- addBlank(titleRow)
- addBlank(widthRow, r > 1 and '5px' or nil)
- titleRow:tag('td')
- :attr('colspan', hideSeeds and '2' or '3')
- :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 scoreCell = addBlank(widthRow, getWidth('score', '25px'))
- addBlank(titleRow)
- addBlank(widthRow, r < rounds and '5px' or nil)
- if compact then
- teamCell:css('height', '7px')
- else
- if seedCell then
- seedCell:wikitext(' ')
- end
- teamCell:wikitext(' ')
- scoreCell:wikitext(' ')
- 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'))
- -- set default seeds for round 1
- local seeds = getSeeds()
- local argname
- for i = 1, table.getn(seeds) do
- argname = getTeamArgName(1, 'seed', i)
- if not args[argname] then
- args[argname] = seeds[i]
- end
- end
- 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')
- if (args['nowrap'] and (args['nowrap'] == 'yes' or args['nowrap'] == 'y')) then
- tbl:css('white-space', 'nowrap')
- end
- if compact then
- tbl:css('font-size', '90%'):attr('cellpadding', '0')
- end
- renderHeading(tbl, compact)
- renderTree(tbl, compact)
- return tostring(tbl)
- end
- return p