Модуль:Участники финального турнира
Модуль для автоматического формирования таблицы участников финального турнира. Может работать как в полностью автоматическом, так и в полуавтоматическом режиме.
Полностью автоматический режим
{{#invoke:TournamentParticipants|main|prefix=Код_турнира|year=Год}}
Или просто:
{{#invoke:TournamentParticipants|main|Код_турнира|Год}}
Например:
{{#invoke:TournamentParticipants|main|prefix=ЧТМ|year=2046}}
или:
{{#invoke:TournamentParticipants|main|ЧТМ|2046}}
Оба варианта идентичны. Модуль сам найдёт всех участников и подсчитает для каждого общее количество участий в финальном турнире.
Полуавтоматический режим
{{#invoke:TournamentParticipants|main|prefix=Код_турнира|year=Год|teams=Список через запятую}}
Или просто:
{{#invoke:TournamentParticipants|main|Код_турнира|Год|Список через запятую}}
Этот вариант можно применять в тех случаях, когда квалификация уже состоялась, а финальный турнир ещё не стартовал и массива для него в БД в принципе нет.
Например:
{{#invoke:TournamentParticipants|main|prefix=ЧТМ|year=2046|teams=ДОМ, МОН, КИР, ИНД, СЕН, ТЕР}}
или:
{{#invoke:TournamentParticipants|main|ЧТМ|2046|ДОМ, МОН, КИР, ИНД, СЕН, ТЕР}}
Пожалуйста, добавляйте категории на страницу документации.
local p = {}
-- Подключаем базу команд
local teams_module = require("Модуль:Data/Teams")
-- Список годов, которые по структуре БД точно не существуют
local SKIP_YEARS = {
[2007] = true,
[2008] = true,
[2011] = true,
[2012] = true,
[2016] = true
}
-- Вспомогательная функция: вытаскивает все уникальные команды из таблицы турнира
local function extract_teams(tournament_data)
local teams_set = {}
for _, stage_data in pairs(tournament_data) do
if stage_data.type == "group" and stage_data.standings then
for _, row in ipairs(stage_data.standings) do
teams_set[row[1]] = true
end
elseif stage_data.type == "knockout" and stage_data.matches then
for _, row in ipairs(stage_data.matches) do
teams_set[row[1]] = true
teams_set[row[2]] = true
end
end
end
return teams_set
end
-- Вспомогательная функция: ищет победителя турнира (действующего чемпиона)
local function get_champion(tournament_data)
for stage_name, stage_data in pairs(tournament_data) do
-- Ищем финал (отсекаем четверть- и полуфиналы)
if stage_name:match("Final$") and not stage_name:match("Semifinal$") and not stage_name:match("Quarterfinal$") then
if stage_data.matches and stage_data.matches[1] then
local m = stage_data.matches[1]
local t1, t2 = m[1], m[2]
local c1, c2
-- Индексы ячеек цвета зависят от количества раундов
if stage_data.number_of_rounds == 2 then
c1, c2 = m[10], m[11]
else
c1, c2 = m[8], m[9]
end
-- Оптимизация: определяем победителя по зелёному цвету ячейки ("G")
if c1 == "G" then return t1 end
if c2 == "G" then return t2 end
end
end
end
return nil
end
function p.main(frame)
local args = frame.args[1] and frame.args or frame:getParent().args
local prefix = args[1] or args.prefix
local target_year = tonumber(args[2] or args.year)
if not prefix or not target_year then
return '<strong class="error">Ошибка: не указан префикс турнира или год.</strong>'
end
local target_tournament = prefix .. "_" .. target_year .. "_Final"
-- Хранилища для данных
local participants = {}
local appearances = {}
local champion_code = nil
local champion_found = false
-- === 1 ПРОХОД ПО БАЗАМ ДАННЫХ ===
for y = target_year, 2006, -1 do
if not SKIP_YEARS[y] then
local success, year_db = pcall(require, "Модуль:Data/Tournaments/" .. y)
if success and year_db then
local t_data = year_db[prefix .. "_" .. y .. "_Final"]
if t_data then
local unique_teams = extract_teams(t_data)
if y == target_year then
-- Фиксируем состав участников целевого турнира
for code in pairs(unique_teams) do
participants[code] = true
appearances[code] = 1
end
else
-- Считаем прошлые участия ТОЛЬКО для команд-участниц заданного года
for code in pairs(unique_teams) do
if participants[code] then
appearances[code] = appearances[code] + 1
end
end
-- Ищем действующего чемпиона в самом свежем предыдущем турнире
if not champion_found then
champion_code = get_champion(t_data)
champion_found = true
end
end
end
end
end
end
if next(participants) == nil then
return "В базе данных за " .. target_year .. " год турнир " .. target_tournament .. " не найден или не имеет участников."
end
-- === ПОДГОТОВКА ДАННЫХ ===
local list = {}
for code in pairs(participants) do
local team_info = teams_module.getTeam(code)
local short_name = team_info and team_info.short or code
local full_name = team_info and team_info.full or code
table.insert(list, {
code = code,
short = short_name,
full = full_name,
apps = appearances[code] or 1,
is_champ = (code == champion_code)
})
end
-- Чемпион идёт первым, остальные по алфавиту
table.sort(list, function(a, b)
if a.is_champ ~= b.is_champ then
return a.is_champ
end
return a.short < b.short
end)
-- === ОТРИСОВКА HTML ТАБЛИЦЫ ===
local root = mw.html.create('table')
:addClass('article-table')
:attr('border', '1')
:attr('cellspacing', '1')
:attr('cellpadding', '1')
:css('width', '500px')
local num_teams = #list
local rows_count = math.ceil(num_teams / 2)
for r = 1, rows_count do
local tr = root:tag('tr')
for col = 1, 2 do
local idx = (r - 1) * 2 + col
local team = list[idx]
if team then
-- ИСправлено здесь: используем team.short вместо team.code для формирования файла
tr:tag('td')
:attr('align', 'center')
:css('white-space', 'nowrap')
:wikitext(string.format('[[Файл:%s.jpg|50x100px]]', team.short))
-- Формируем умную ссылку на команду (Полное имя | Короткое имя)
local link = (team.full == team.short) and string.format('[[%s]]', team.short)
or string.format('[[%s|%s]]', team.full, team.short)
tr:tag('td')
:attr('align', 'center')
:css('white-space', 'nowrap')
:wikitext(string.format("'''%s''' (%d)", link, team.apps))
else
-- Добиваем пустые ячейки, если количество команд нечётное
tr:tag('td'):wikitext('')
tr:tag('td'):wikitext('')
end
end
end
local header = "''(В скобках — общее количество участий в финальных турнирах)''"
return header .. "\n" .. tostring(root)
end
return p