Модуль:Bracket
Перейти к навигации
Перейти к поиску
Для документации этого модуля может быть создана страница Модуль:Bracket/doc
-- Модуль:Bracket
-- Турнирная сетка на выбывание: 2–5 этапов, 1–N игр на этапе,
-- матч за 3-е место, даты, места, свои названия этапов.
local p = {}
-- Стандартные названия этапов по количеству этапов
local defaultNames = {
[2] = { "Полуфиналы", "Финал" },
[3] = { "Четвертьфиналы", "Полуфиналы", "Финал" },
[4] = { "1/8 финала", "Четвертьфиналы", "Полуфиналы", "Финал" },
[5] = { "1/16 финала", "1/8 финала", "Четвертьфиналы", "Полуфиналы", "Финал" },
}
local function preproc(frame, s)
if s == nil then return nil end
s = mw.text.trim(s)
if s == "" then return nil end
return frame:preprocess(s)
end
local function isYes(s)
s = s and mw.ustring.lower(mw.text.trim(s)) or ""
return s == "yes" or s == "да" or s == "1" or s == "true"
end
-- Рендер одной игры. prefix: "r1m2" (этап 1, игра 2) или "third"
local function matchHtml(frame, prefix, args)
local function prm(name) return preproc(frame, args[prefix .. name]) end
local t1, t2 = prm("team1"), prm("team2")
local s1, s2 = prm("team1score"), prm("team2score")
local n1, n2 = prm("team1note"), prm("team2note")
local date, venue = prm("date"), prm("venue")
local winner = prm("winner")
if not (t1 or t2 or s1 or s2) then return nil end
-- Победитель: явно или по числовому счёту
if winner ~= "1" and winner ~= "2" then
local a, b = tonumber(s1), tonumber(s2)
if a and b then
if a > b then winner = "1"
elseif b > a then winner = "2"
else winner = nil end
else
winner = nil
end
end
local meta = ""
if date or venue then
local parts = {}
if date then parts[#parts + 1] = '<span class="bracket-date">' .. date .. '</span>' end
if venue then parts[#parts + 1] = '<span class="bracket-venue">' .. venue .. '</span>' end
meta = '<div class="bracket-matchmeta">' .. table.concat(parts, " — ") .. '</div>'
end
local function row(t, s, note, isWinner)
local cls = "bracket-team"
if isWinner then cls = cls .. " bracket-winner" end
local nameCell = t or " "
if note then
nameCell = nameCell .. ' <span class="bracket-note">(' .. note .. ')</span>'
end
return '<tr class="' .. cls .. '"><td class="bracket-name">' .. nameCell ..
'</td><td class="bracket-score">' .. (s or "") .. '</td></tr>'
end
return meta ..
'<table class="bracket-matchteams">' ..
row(t1, s1, n1, winner == "1") ..
row(t2, s2, n2, winner == "2") ..
'</table>'
end
function p.main(frame)
local args = frame:getParent().args
local n = tonumber(mw.text.trim(args.rounds or ""))
if not n or n < 2 or n > 5 then
error("Bracket: параметр «rounds» должен быть числом от 2 до 5")
end
local out = {}
local function w(s) out[#out + 1] = s end
w('<div class="bracket"><div class="bracket-inner">')
for r = 1, n do
local title = preproc(frame, args["r" .. r .. "name"]) or defaultNames[n][r]
-- Собираем игры этапа
local matches = {}
local m = 1
while m <= 32 do
local html = matchHtml(frame, "r" .. r .. "m" .. m, args)
if not html then break end
matches[#matches + 1] = html
m = m + 1
end
local c = #matches
w('<div class="bracket-round">')
w('<div class="bracket-roundtitle">' .. title .. '</div>')
w('<div class="bracket-roundbody">')
-- Ведущий разделитель (для вертикального центрирования)
w('<div class="bracket-gap"></div>')
for i = 1, c do
local html = matches[i]
local cls = "bracket-match"
if r < n then
if c == 1 or (i % 2 == 1 and i == c) then
cls = cls .. " bracket-m-solo"
elseif i % 2 == 1 then
cls = cls .. " bracket-m-up"
else
cls = cls .. " bracket-m-lo"
end
end
w('<div class="bracket-slot"><div class="' .. cls .. '">' .. html .. '</div></div>')
if i < c then
local gcls = "bracket-gap"
if r < n and i % 2 == 1 then
gcls = gcls .. " bracket-gapline"
end
w('<div class="' .. gcls .. '"></div>')
end
end
w('<div class="bracket-gap"></div>')
w('</div></div>')
end
w('</div>') -- /bracket-inner
if isYes(args.thirdplace) then
local html = matchHtml(frame, "third", args)
local t = preproc(frame, args.thirdname) or "Матч за третье место"
w('<div class="bracket-third">')
w('<div class="bracket-roundtitle bracket-thirdtitle">' .. t .. '</div>')
w(html or "")
w('</div>')
end
w('</div>')
return table.concat(out)
end
return p