Modul:Turnierplan
aus Wikipedia, der freien Enzyklopädie
Vorlagenprogrammierung | Diskussionen | Lua | Unterseiten | ||
Modul | Deutsch
|
Modul: | Dokumentation |
Diese Seite enthält Code in der Programmiersprache Lua. Einbindungszahl Cirrus
Modul zur Erstellung kompletter Turnierpläne.
Beispiele
{{#invoke:Turnierplan|bracket|runden=2}}
Halbfinale | Finale | |||||||
{{#invoke:Turnierplan|bracket|reseed=ja|runden=3 |n1= |n2= |n3= |n4= |n5= |n6= |n7=}}
Viertelfinale | Halbfinale | Finale | |||||||||||
1 | |||||||||||||
4 | |||||||||||||
5 | |||||||||||||
2 | |||||||||||||
7 | |||||||||||||
3 | |||||||||||||
6 | |||||||||||||
|
„Reseeding“: In jeder Runde spielt das höchstgesetzte Team zu Hause gegen das niedrigste, das zweithöchste zu Hause gegen das zweitniedrigste und so weiter. Die hellblauen Linien entsprechen dem Fall, in dem jeweils das Heimteam gewinnt. |
local footnotes = {}
local rounds = {}
local nameWidth = '12em'
local function notNilStr(s)
if s == nil then return '' end
return s
end
local function fillRounds(runden)
if type(runden) == "string" then
runden = tonumber(runden)
end
if type(runden) == "number" then
for i = 1, runden do
rounds[i] = 'Runde ' .. i
end
else
rounds = runden
end
end
local function setBracketSize(bracket)
if bracket.branch[0].sizeU == 0 then
bracket.sizeO = math.max(bracket.branch[1].sizeO - 1, 3)
bracket.sizeU = math.max(bracket.branch[1].sizeU + 1, 3)
elseif bracket.branch[1].sizeO == 0 then
bracket.sizeO = bracket.branch[0].sizeO + 1
bracket.sizeU = math.max(bracket.branch[0].sizeU - 1, 3)
else
bracket.sizeO = bracket.branch[0].size()
bracket.sizeU = bracket.branch[1].size()
end
if bracket.header ~= nil then
bracket.sizeO = math.max(bracket.sizeO, 5)
end
if bracket.footer ~= nil then
bracket.sizeU = math.max(bracket.sizeU, 5)
end
end
local function addFootnote(fn)
local count = 1
while footnotes[count] ~= nil do
if footnotes[count] == fn then return count end
count = count + 1
end
footnotes[count] = fn
return count
end
local function parseScore(input)
local score = {}
score.num = tonumber(mw.ustring.match(input, "^%s*(%d+)"))
local fn = mw.ustring.match(input, "^%d+%*(.*)%s*$")
if fn ~= nil then
if fn == '' then fn = 'nach Verlängerung' end
local index = addFootnote(fn)
score.text = '<sup><span style="visibility:hidden;">' .. index .. '</span></sup>' .. score.num ..
'<span class="reference"><sup id="FN_tp' .. index .. '_v">[[#FN_tp' .. index ..
'|' .. index .. ']]</sup></span>'
else score.text = score.num end
return score
end
local function fillScore(bracket, score)
if score == nil then return end
local hs = parseScore(mw.ustring.match(score,"^(.+)[:-]"))
local as = parseScore(mw.ustring.match(score,"[:-](.+)$"))
if hs ~= nil and as ~= nil then
if hs.num > as.num then
bracket.branch[0].win = true
bracket.key = bracket.branch[0].key
elseif hs.num < as.num then
bracket.branch[1].win = true
bracket.key = bracket.branch[1].key
end
bracket.branch[0].score = hs.text
bracket.branch[1].score = as.text
end
end
local function fillBranch(branch, args)
if branch.key == nil then
return
end
branch.name = branch.key
if args[branch.key] ~= nil then
branch.name = args[branch.key]
end
branch.seed = args['seed_' .. branch.key]
end
local function bracketDetails(kind, key, args, round)
local kindKey = key .. string.sub(kind, 1, 1)
if args[kindKey] == nil then
if args[kind .. round] ~= nil then
kindKey = kind .. round
else
return nil
end
end
details = {}
details.text = args[kindKey]
if args[kindKey .. 's'] ~= nil then
details.style = args[kindKey .. 's']
else
details.style = args[kind .. '-style']
end
return details
end
local function fillBracket(bracket, args)
local b0, b1 = bracket.branch[0], bracket.branch[1]
local key = notNilStr(b0.key) .. '-' .. notNilStr(b1.key)
fillScore(bracket, args[key])
bracket.header = bracketDetails('header', key, args, bracket.round)
bracket.footer = bracketDetails('footer', key, args, bracket.round)
setBracketSize(bracket)
fillBranch(bracket, args)
end
local function createBranch()
local branch = {}
function branch.size()
return branch.sizeO + branch.sizeU
end
return branch
end
local function atomBranch(key, args, i)
local branch = createBranch()
branch.key = key
branch.sizeO = 1 - i
branch.sizeU = i
branch.round = 0
branch.link = args[key .. '_l']
fillBranch(branch, args)
return branch
end
local function branchesToBracket(upper, lower, args, round)
local bracket = createBranch()
bracket.branch = {}
bracket.branch[0] = upper
bracket.branch[1] = lower
if round == nil then round = math.max(upper.round, lower.round) + 1 end
bracket.round = round
fillBracket(bracket, args)
return bracket
end
local function buildBracket(args, round, spot)
local branch = {}
for i = 0, 1 do
local entry = 'r' .. round .. '_' .. spot+i
local key = args[entry]
if key ~= nil then
branch[i] = atomBranch(key, args, i)
elseif round == tonumber(args.runden) then
args[entry] = ''
branch[i] = atomBranch(entry, args, i)
else
branch[i] = buildBracket(args, round + 1, 2*(spot+i))
end
end
return branchesToBracket(branch[0], branch[1], args, round + 1)
end
local function reseedColumn(t, p, args, branch)
local l, i = p - 1, 0
local reseed = false
while t <= l do
local j = 2 * p - i - 1
local bracket
local ziel = p + t
if branch[2 * p + j] == nil then
bracket = branch[2 * p + i]
else
bracket = branchesToBracket(branch[2 * p + i], branch[2 * p + j], args)
if reseed then bracket.key, bracket.seed, bracket.name = nil, nil, nil end
if bracket.branch[1].win then
ziel = p + l
t, l = t - 1, l - 1
elseif not bracket.branch[0].win and t < l then
reseed = true
local re = '\n{|\n|-\n|style="height:.2ex; width:1.2em; border-top:3px solid #CAD2EE"|\n|}\n'
if footnotes[re] == nil then
footnotes[re] = '„Reseeding“: In jeder Runde spielt das höchstgesetzte Team zu Hause gegen das niedrigste, das zweithöchste zu Hause gegen das zweitniedrigste und so weiter. Die hellblauen Linien entsprechen dem Fall, in dem jeweils das Heimteam gewinnt.'
end
end
end
bracket.reseed = reseed
branch[ziel] = bracket
t = t + 1
i = i + 1
end
end
local function buildReseedBracket(args)
local branch = {}
local j = math.pow(2, args.runden)
for i = 1, j do
local key = args['n' .. i]
if key ~= nil then
if key == '' then key = 'n' .. i end
if args['seed_' .. key] == nil then args['seed_' .. key] = i end
branch[j + i - 1] = atomBranch(key, args, math.floor((2 * i - 1)/j))
else
branch[j + i - 1] = nil
end
end
for i = args.runden - 1, 0, -1 do
reseedColumn(0, math.pow(2, i), args, branch)
end
return branch[1]
end
-- print bracket methods
local function printBox(seed, name, score, border, weight)
local ret = {}
local sty0 = '|rowspan="2" style="background:#'
local sty1 = '; border-style:solid; border-color:#AAAAAA; '
table.insert(ret, sty0..'EAECF0;'..border..' 0 1px 1px'..sty1..'text-align:center; padding:0 0.6em"| '..seed..'\n')
table.insert(ret, sty0..'F8F9FB;'..border..' 1px 1px 1px'..sty1..weight..'padding-left:0.4em"| '..name..'\n')
table.insert(ret, sty0..'F8F9FB;'..border..' 1px 1px 0'..sty1..weight..'text-align:center; padding:0 0.6em"| '..score..'\n')
return table.concat(ret)
end
local function printContent(content)
if content == nil or content == '' then
return content
end
if type(content) == "string" then
return '|rowspan="2" colspan="3" style="font-size:90%; vertical-align:bottom; padding:.2ex .5em .2ex .5em"| ' .. content .. '\n'
end
if content.text ~= nil then
local ret = '|rowspan="2" colspan="3"'
if content.style ~= nil then ret = ret .. ' style="' .. content.style .. '"' end
return ret .. '| ' .. content.text .. '\n'
end
local seed = notNilStr(content.seed)
local name = notNilStr(content.name)
if content.link ~= nil then name = '[[' .. content.link .. '|' .. name .. ']]' end
local score = notNilStr(content.score)
local weight = ''
if content.win then weight = 'font-weight:bold; ' end
return printBox(seed, name, score, ' border-width:' .. content.top, weight)
end
local function straightLine(ret, x, y, color)
ret[x][y] = 'colspan="2" style="border-bottom:2px solid' .. color .. '"'
ret[x][y + 1] = 'colspan="2" style="border-top:1px solid' .. color .. '"'
end
local function connectLine(ret, x, y, d, wid, pos, th, z, color)
local fullColor = ''
if color ~= '' then fullColor = ' border-color:' .. string.sub(color, 2, -1) end
ret[x][y] = 'rowspan="' .. d .. '" style="border-width:' .. wid .. ' 0; border-style:solid;' .. fullColor .. '"| ||rowspan="' .. d .. '" style="border-' .. pos .. ':3px solid' .. color .. '"'
ret[x][z] = 'style="border-' .. pos .. ':' .. th .. 'px solid' .. color .. '"| |'
for i = 1, d-1 do
ret[x][y+i] = ''
end
end
local function bracketPos(pos, p0, p1, header)
if p0 ~= nil and p1 ~= nil then
return math.floor((p0+p1)/2)
elseif p0 ~= nil then
return p0 + 1
elseif p1 ~= nil then
return p1 - 1
elseif header ~= nil then
return pos + 5
else
return pos + 3
end
end
local function printLines(ma, branch, x, y1)
if branch.branch == nil then
return
end
local color = ''
if branch.reseed then
color = ' #CAD2EE'
end
local y0 = branch.pos
if y0 == y1 then
straightLine(ma, x, y1 - 1, color)
elseif y0 < y1 then
connectLine(ma, x, y0, y1 - y0, '1px 3px 0', 'bottom', 2, y0 - 1, color)
else
connectLine(ma, x, y1, y0 - y1, '0 3px 2px', 'top', 1, y0, color)
end
end
local function insertContentInMatrix(ma, x, y, h, content)
if content == nil then
return
end
ma[x][y] = content
for i = 1, h - 1 do
ma[x][y + i] = ''
end
end
local function printBranch(ma, bracket, round, pos)
if bracket.branch == nil then
return ma
end
ma = printBranch(ma, bracket.branch[0], round-1, pos)
if bracket.branch[0].sizeU == 0 then
posOs = bracket.sizeO + 1 - bracket.branch[1].sizeO
else
posOs = bracket.branch[0].size()
end
ma = printBranch(ma, bracket.branch[1], round-1, pos + posOs)
bracket.pos = bracketPos(pos, bracket.branch[0].pos, bracket.branch[1].pos, bracket.header)
local x = 2 * round - 2
insertContentInMatrix(ma, x, bracket.pos-4, 2, bracket.header)
insertContentInMatrix(ma, x, bracket.pos+2, 2, bracket.footer)
bracket.branch[0].top = '1px'
insertContentInMatrix(ma, x, bracket.pos-2, 2, bracket.branch[0])
bracket.branch[1].top = '0'
insertContentInMatrix(ma, x, bracket.pos, 2, bracket.branch[1])
printLines(ma, bracket.branch[0], 2 * round - 3, bracket.pos - 1)
printLines(ma, bracket.branch[1], 2 * round - 3, bracket.pos + 1)
return ma
end
local function tableHeader(x, class)
local tab = {}
table.insert(tab, '{| ' .. class .. ' style="font-size:90%"\n')
table.insert(tab, '|-\n|\n')
for i = 1, x do
table.insert(tab, '|style="width:2em"| ||style="width:' .. nameWidth .. '"| ||style="width:3em"|\n')
table.insert(tab, '|style="width:1em"| ||style="width:.8em"|\n')
end
table.insert(tab, '|style="width:2em"| ||style="width:' .. nameWidth .. '"| ||style="width:3em"|\n')
return tab
end
local function matrixToTable(ma, x, y, tab)
for j = 0, y do
table.insert(tab, '|-\n|style="height:1.6ex"|\n')
for i = 0, 2*x, 2 do
if ma[i][j] == nil then
table.insert(tab, '|colspan="3"|\n')
else
table.insert(tab, printContent(ma[i][j]))
end
if ma[i+1] == nil or ma[i+1][j] == '' then
elseif ma[i+1][j] == nil then
table.insert(tab, '|colspan="2"|\n')
else
table.insert(tab, '|' .. ma[i+1][j] .. '|\n')
end
end
end
table.insert(tab, '|}\n')
return table.concat(tab)
end
local tp = {}
function tp.processArgs(args)
fillRounds(args.runden)
for i = 1, table.getn(rounds) do
if args['rd' .. i] ~= nil then
rounds[i] = args['rd' .. i]
elseif rounds[i] ~= 'Runde ' .. i then
elseif table.getn(rounds) == i + 3 then
rounds[i] = 'Achtelfinale'
elseif table.getn(rounds) == i + 2 then
rounds[i] = 'Viertelfinale'
elseif table.getn(rounds) == i + 1 then
rounds[i] = 'Halbfinale'
elseif table.getn(rounds) == i then
rounds[i] = 'Finale'
if args.finale ~= nil then rounds[i] = args.finale end
end
end
if args.width ~= nil then nameWidth = args.width end
if args.nameWidth ~= nil then nameWidth = args.nameWidth end
end
function tp.buildBracket(args)
if args.reseed then
return buildReseedBracket(args)
end
return buildBracket(args, 1, 0)
end
function tp.branchesToBracket(upper, lower, args)
return branchesToBracket(upper, lower, args)
end
function tp.footnoteTable()
if not next(footnotes) then
return ''
end
local ret = '\n<div style="border-bottom:1px solid #777777; margin-top:2ex; margin-bottom:.5ex; width:7em"></div><div style="padding-left:0.7em">\n'
ret = ret .. '\{| border="0" cellspacing="0" style="font-size:81%"\n'
for i, fn in pairs(footnotes) do
ret = ret .. '|-\n|style="text-align:right"| '
if type(i) == "number" then
ret = ret .. '[[#FN_tp' .. i .. '_v|<sup id="FN_tp' .. i
.. '" style="display:inline-block; min-width:0.5em">' .. i .. '</sup>]]'
else
ret = ret .. i
end
ret = ret .. ' || ' .. fn .. '\n'
end
return ret .. '|}</div>'
end
function tp.bracketToTable(bracket)
local content = {}
local x = table.getn(rounds)
for i = 0, 2 * (x - 1) do
content[i] = {}
end
for i = 0, 2 * (x - 1), 2 do
content[i][0] = {}
content[i][0].style = 'text-align:center; border:1px solid; background:#EAECF0; padding:.2ex .5em .2ex .5em'
content[i][0].text = rounds[i/2 + 1]
content[i][1] = ''
end
content = printBranch(content, bracket, x, 2)
local tab = tableHeader(x - 1, 'border="0" cellpadding="0" cellspacing="0"')
return matrixToTable(content, x - 1, bracket.size(), tab)
end
function tp.bracket(frame)
tp.processArgs(frame.args)
local bracket = tp.buildBracket(frame.args)
local tabB = tp.bracketToTable(bracket)
local tabF = tp.footnoteTable()
return tabB .. tabF
end
return tp