Модуль:Участники финального турнира
Модуль для автоматического формирования таблицы участников финального турнира. Может работать как в полностью автоматическом, так и в полуавтоматическом режиме.
Полностью автоматический режим
{{#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)
local manual_teams = args[3] or args.teams -- Новый параметр для ручного списка
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
local manual_mode = false
-- === ОБРАБОТКА РУЧНОГО СПИСКА (ЕСЛИ ЕСТЬ) ===
if manual_teams and manual_teams ~= "" then
manual_mode = true
-- Разбиваем список по запятой
for item in mw.text.gsplit(manual_teams, ",") do
local team_input = mw.text.trim(item)
if team_input ~= "" then
local code = mw.ustring.upper(team_input)
-- Проверяем, ввёл ли юзер код или название. Если название — получаем код.
if not teams_module.getTeam(code) then
local resolved_code = teams_module.getCode(team_input)
if resolved_code then code = resolved_code end
end
participants[code] = true
appearances[code] = 1 -- Засчитываем участие в будущем турнире
end
end
end
-- Если список задан вручную, начинаем сканировать БД с прошлого года
local start_year = manual_mode and (target_year - 1) or target_year
-- === 1 ПРОХОД ПО БАЗАМ ДАННЫХ ===
for y = start_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 not manual_mode and 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
-- Ячейка с флагом
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]]', 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