Module:Tournoi
Aller à la navigation
Aller à la recherche
Ce modèle permet de représenter un tournoi à élimination simple. Il est copié du module TeamBracket de Wikipédia.
Usage
{{#invoke: Tournoi | tournoi
| manches =
| graine-largeur =
| equipe-largeur =
| score-largeur =
| manche1 =
| manche1-groupe1 =
| manche1-graine1 =
| manche1-équipe1 =
| manche1-score1 =
...
}}
Liste des paramètres
Les paramètres sont les suivants:
graine-largeur –la largeur des cellules pour les graines.équipe-largeur –la largeur des cellules pour les noms d'équipes.score-largeur –la largeur des cellules pour les scores.graines –mettre ànonpour masquer toutes les graines.compact –mettre àouipour un tournoi compact et la désactivation des groupes.
manchen –Le nom de la manche n.manchen-groupem –Le nom du groupe m à la manche n.manchen-grainem –La graine de l'équipe m à la manche n.manchen-équipem –Le nom de l'équipe m à la manche n.manchen-scorem –Le score de l'équipe m à la manche n.
Descriptions des paramètres
- graine-largeur
- La largeur des cellules de graines en CSS. Exemples :
N [em/%/px]auto
- équipe-largeur
- La largeur des cellules de noms d'équipes en CSS.
- score-largeur
- La largeur des cellules de score en CSS.
- manchen
- Le nom de la manche n. Par défaut "mèmes de finale", ..., "Quarts de finale", "Demi-finales", et "Finale", où m est le nombre d'équipes dans la manche.
- manchen-groupem
- Le nom du groupe m à la manche n. Pour chaque manche, chaque ensemble de quatre équipes est classifiée comme un groupe.
- manchen-grainem
- La graine de l'équipe m à la manche n. À la manche 1, cette valeur vaut par défaut l'allocation de graine conventionnelle pour les tournois. Si omis, la cellule est masquée. Pour masquer une cellule à la manche 1, la valeur doit explicitement être vide. m est la position comblée de 0.
- manchen-équipem
- Le nom de l'équipe m à la manche n. m est la position comblée de 0.
- manchen-scorem
- Le score de l'équipe m à la manche n. m est la position comblée de 0.
Exemples
Sans graine
{{#invoke: Tournoi | tournoi
| manches = 2
| manche1-graine1 =
| manche1-graine2 =
| manche1-graine3 =
| manche1-graine4 =
}}
| Demi-finales | Finale | ||||||||
Groupes
{{#invoke: Tournoi | tournoi
| autograines = oui
| manches = 4
| scores = non
| manche1-groupe1 = Pacific
| manche1-groupe2 = Mountain
| manche2-groupe1 = West
}}
| 16ème de finale | Quarts de finale | Demi-finales | Finale | ||||||||||||
| 1 | |||||||||||||||
| 16 | |||||||||||||||
| Pacific | |||||||||||||||
| 9 | |||||||||||||||
| 8 | |||||||||||||||
| West | |||||||||||||||
| 5 | |||||||||||||||
| 12 | |||||||||||||||
| Mountain | |||||||||||||||
| 13 | |||||||||||||||
| 4 | |||||||||||||||
| 3 | |||||||||||||||
| 14 | |||||||||||||||
| 11 | |||||||||||||||
| 6 | |||||||||||||||
| 7 | |||||||||||||||
| 10 | |||||||||||||||
| 15 | |||||||||||||||
| 2 | |||||||||||||||
--
-- This module will implement {{Tournoi}}
--
local p = {}
local args
local rounds
local padding
local hideColspanModifier = 0
local hideSeeds
local showSeeds
local hideScores
local tracking = ''
local WIDTH_NAME = 'largeur'
local ROUND_NAME = 'manche'
local ROUNDS_NAME = 'manches'
local COMPACT_NAME = 'compact'
local AUTOSEEDS_NAME = 'autograines'
local SEEDS_NAME = 'graines'
local SEED_NAME = 'graine'
local TEAM_NAME = 'équipe'
local SCORES_NAME = 'scores'
local SCORE_NAME = 'score'
local GROUP_NAME = 'groupe'
local YES_VALUE = 'oui'
local Y_VALUE = 'o'
local NO_VALUE = 'non'
local N_VALUE = 'n'
local FINALS_LABEL = 'Finale'
local SEMIFINALS_LABEL = 'Demi-finales'
local QUARTERFINALS_LABEL = 'Quarts de finale'
local ROUNDOF_LABEL = '%d<sup>ème</sup> de finale'
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_NAME]
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(ROUND_NAME .. '%d-%s' .. padding, round, type, team)
end
function getRoundName(round)
local name = args[ROUND_NAME .. round]
if name and string.len(name) > 0 then
return name
end
local roundFromLast = rounds - round + 1
if roundFromLast == 1 then
return FINALS_LABEL
elseif roundFromLast == 2 then
return SEMIFINALS_LABEL
elseif roundFromLast == 3 then
return QUARTERFINALS_LABEL
else
return string.format(ROUNDOF_LABEL, math.pow(2, roundFromLast))
end
end
function renderTeam(row, round, team, top, compact)
local scoreCell
local seedCell
local seedArg = getTeamArg(round, SEED_NAME, team)
-- seed value for the paired team
local pairSeedArg = getTeamArg(round, SEED_NAME,
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_NAME, 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', '0')
:css('padding', '0 2px')
:wikitext(teamArg)
:newline()
if not showSeed and (not hideSeeds) then
teamCell:attr('colspan', '2')
end
if (not hideScores) then
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', '0')
:css('border-right-width', '1px')
:css('border-bottom-width', '0')
:css('background-color', '#f9f9f9')
:wikitext(getTeamArg(round, SCORE_NAME, team))
:newline()
end
if not compact then
if seedCell then
seedCell:attr('rowspan', '2')
:css('border-bottom-width', '1px')
end
if scoreCell then
scoreCell:attr('rowspan', '2')
:css('border-bottom-width', '1px')
end
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')
if scoreCell then
scoreCell:css('border-bottom-width', '1px')
end
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
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', hideColspanModifier + 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
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', hideColspanModifier + 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 = ROUND_NAME .. round .. '-' .. GROUP_NAME .. group
addBlank(rows[i]):css('height', '7px')
addBlank(rows[i + 1]):css('height', '7px')
addBlank(rows[i])
:attr('rowspan', '2')
:attr('colspan', (hideColspanModifier + 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', hideColspanModifier + 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_NAME, '25px'))
end
local teamCell = addBlank(widthRow, getWidth(TEAM_NAME, '150px'))
local scoreCell
if not hideScores then
scoreCell = addBlank(widthRow, getWidth(SCORE_NAME, '25px'))
end
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(' ')
if scoreCell then
scoreCell:wikitext(' ')
end
end
end
end
function p.tournoi(frame)
local getArgs = require('Module:Arguments').getArgs
args = getArgs(frame, {trim = false, removeBlanks = false})
-- exit early if this section is not to be transcluded
if args['section'] and args['transcludesection']
and args['section'] ~= args['transcludesection'] then return ''
end
rounds = tonumber(args[ROUNDS_NAME]) or 2
local teams = math.pow(2, rounds)
padding = '%0' .. (teams < 10 and 1 or 2) .. 'd'
local compact = (args[COMPACT_NAME] and (args[COMPACT_NAME] == YES_VALUE or args[COMPACT_NAME] == Y_VALUE))
local autoSeeds = (args[AUTOSEEDS_NAME] and (args[AUTOSEEDS_NAME] == YES_VALUE or args[AUTOSEEDS_NAME] == Y_VALUE))
hideSeeds = (args[SEEDS_NAME] and (args[SEEDS_NAME] == NO_VALUE or args[SEEDS_NAME] == N_VALUE))
showSeeds = (args[SEEDS_NAME] and (args[SEEDS_NAME] == YES_VALUE or args[SEEDS_NAME] == Y_VALUE))
hideScores = (args[SCORES_NAME] and (args[SCORES_NAME] == NO_VALUE or args[SCORES_NAME] == N_VALUE))
if hideSeeds then
hideColspanModifier = hideColspanModifier - 1
end
if hideScores then
hideColspanModifier = hideColspanModifier - 1
end
if autoSeeds then
-- set default seeds for round 1
local seeds = getSeeds()
for i = 1, table.getn(seeds) do
local argname = getTeamArgName(1, SEED_NAME, i)
if not args[argname] then
args[argname] = seeds[i]
end
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_VALUE or args['nowrap'] == Y_VALUE)) 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) .. tracking
end
return p