Модуль:Автоматическая статистика: различия между версиями

Материал из ЧТМ
Перейти к навигации Перейти к поиску
Нет описания правки
Нет описания правки
Строка 178: Строка 178:
         local match_gear = " [[Файл:Gear icon.svg|12px|link=" .. url_matches .. "]] "
         local match_gear = " [[Файл:Gear icon.svg|12px|link=" .. url_matches .. "]] "
          
          
         local t_list = mw.html.create('table'):addClass('wikitable mw-collapsible mw-collapsed')
        -- Убираем класс mw-collapsed (свёрнуто), если главная таблица не выводится
        local list_classes = 'wikitable mw-collapsible'
        if show_main then list_classes = list_classes .. ' mw-collapsed' end
       
         local t_list = mw.html.create('table'):addClass(list_classes)
         t_list:tag('tr'):tag('th'):attr('colspan', '9'):wikitext((compiled_data.played_before_2022 and "Полный список матчей начиная с ЧТМ-2022" or "Полный список матчей") .. match_gear)
         t_list:tag('tr'):tag('th'):attr('colspan', '9'):wikitext((compiled_data.played_before_2022 and "Полный список матчей начиная с ЧТМ-2022" or "Полный список матчей") .. match_gear)
          
          
Строка 346: Строка 350:
     end
     end


    local out_str = Config.styles.wiki_templates
local out_str = Config.styles.wiki_templates
      
      
     -- Добавляем заголовок "== Статистика ==" только если выводится главная таблица
     -- Добавляем заголовок "== Статистика ==" только если выводится главная таблица
Строка 354: Строка 358:
      
      
     if show_matches then
     if show_matches then
        -- Если главной таблицы нет, то список матчей становится главным блоком, даём ему заголовок
        if not show_main then
            out_str = out_str .. "== Список матчей ==\n"
        end
         out_str = out_str .. html_list .. "\n"
         out_str = out_str .. html_list .. "\n"
     else
     else

Версия от 07:29, 4 июня 2026

Документация Документация

Модуль для шаблона {{Автоматическая статистика/разработка}}.

Подгружает на страницу игрока таблицу со статистикой, полный список матчей начиная с ЧТМ-2022 и навигационные шаблоны. Вызов:

{{#invoke:Автоматическая статистика|render|Диман|СГ=1|Год=2020|Качество=ИС|sortable=no}}

Для тяжёлых статей рекомендуется выносить список матчей на отдельную подстраницу.

Есть функция медалек, но она слишком тяжёлая, загружается гораздо медленнее. Просьба не использовать на страницах основного пространства, а только в тестовом режиме:

{{#invoke:Автоматическая статистика|render|Диман|СГ=1|Год=2020|Качество=ИС|sortable=no|medals=yes}}

Список передаваемых параметров

{{#invoke:Автоматическая статистика|render<!-- Запуск модуля
-->|Диман<!-- Имя игрока, обязательный параметр
-->|СГ=1<!-- Если статья заняла какое-то место в голосовании за статью года, то оно указывается
-->|Год=2020<!-- Год, когда происходило голосование
-->|Качество=ИС<!-- Избранная (ИС) или хорошая (ХС) статья
-->|sortable=no<!-- Отключает сортировку таблицы статистики, делая её более компактной (по умолчанию — no)
-->|medals=no<!-- Отключает медали в таблице статистики, значительно снижая нагрузку на сервер (по умолчанию — no)
-->|main_table=no<!-- Отключает расчёт и вывод таблицы статистики (по умолчанию — yes)
-->|matches_list=no<!-- Отключает расчёт и вывод полного списка матчей (по умолчанию — yes)
-->|matches_link=<!-- В случае отключения списка матчей необходимо задать ссылку на подстраницу.
-->|navboxes=no<!-- Отключает расчёт и вывод навигационных шаблонов (по умолчанию — yes)
-->}}
Пожалуйста, добавляйте категории на страницу документации.

-- ==========================================
-- Модуль:Автоматическая статистика 6.0
-- (Pure UI Render для PlayerStats)
-- ==========================================

local p = {}

local Config = require('Module:Config')
local Teams = require('Module:Data/Teams')

p.row_defs = {
    { id = "matches", title = "[[" .. "Матчи|<abbr title=\"Подсчитываются начиная с ЧТМ-2022\">Матчи</abbr>" .. "]]", era = 2022 },
    { id = "field_matches", title = "<abbr title=\"Подсчитываются начиная с ЧТМ-2022\">Матчи в поле</abbr>", era = 2022 },
    { id = "goals", title = "[[" .. "Список всех авторов голов на ЧТМ|Голы" .. "]]", era = 2006 },
    { id = "assists", title = "[[" .. "Передачи|<abbr title=\"Подсчитываются начиная с ЧТМ-2026\">Передачи</abbr>" .. "]]", era = 2026 },
    { id = "avg_goals", title = "[[" .. "Средняя результативность|<abbr title=\"Подсчитывается начиная с ЧТМ-2022\">Ср. результативность</abbr>" .. "]]", era = 2022, is_avg = true, num = "goals", den = "field_matches" },
    { id = "avg_assists", title = "<abbr title=\"Подсчитывается начиная с ЧТМ-2026\">Передачи (ср. за матч)</abbr>", era = 2026, is_avg = true, num = "assists", den = "field_matches" },
    { id = "mvp", title = "[[" .. "Игрок матча" .. "]]", era = 2006 },
    { id = "matchday_prizes", title = "[[" .. "Призы игровых дней|<abbr title=\"Подсчитываются начиная с ЧТМ-2022\">Призы игровых дней</abbr>" .. "]]", era = 2022 },
    { id = "matchday_places", title = "[[" .. "Призы игровых дней#Призовые места игровых дней|<abbr title=\"Подсчитываются начиная с ЧТМ-2022\">Призовые места игр. дней</abbr>" .. "]]", era = 2022 },
    { id = "plus_minus", title = "[[" .. "Показатель полезности|<abbr title=\"Подсчитывается начиная с ЧТМ-2022\">Показатель полезности</abbr>" .. "]]", era = 2022, is_pm = true },
    { id = "mega_tricks", title = "[[" .. "Мега-трики" .. "]]", era = 2006 },
    { id = "assist_mega_tricks", title = "[[" .. "Мега-трики голевых передач|<abbr title=\"Подсчитываются начиная с ЧТМ-2026\">Мега-трики голевых передач</abbr>" .. "]]", era = 2026 },
    { id = "head_goals", title = "[[" .. "Голы головой|<abbr title=\"Подсчитываются начиная с ЧТМ-2022\">Голы головой</abbr>" .. "]]", era = 2022 },
    { id = "heel_goals", title = "[[" .. "Голы пяточкой|<abbr title=\"Подсчитываются начиная с ЧТМ-2026\">Голы пяточкой</abbr>" .. "]]", era = 2026 },
    { id = "free_kick_goals", title = "[[" .. "Голы со штрафных|<abbr title=\"Подсчитываются начиная с ЧТМ-2026\">Голы со штрафных</abbr>" .. "]]", era = 2026 },
    { id = "clearances", title = "[[" .. "Выносы из пустых|<abbr title=\"Подсчитываются начиная с ЧТМ-2022\">Выносы из пустых</abbr>" .. "]]", era = 2022 },
    { id = "pens_scored", title = "[[" .. "Пенальти|Забитые пенальти" .. "]]", era = 2006 },
    { id = "pens_missed", title = "Незабитые пенальти", era = 2006 },
    { id = "pens_saved", title = "[[" .. "Список пенальти ЧТМ#Отбитые пенальти|Отбитые пенальти" .. "]]", era = 2006 },
    { id = "caused_pens", title = "[[" .. "Привезённые пенальти|<abbr title=\"Подсчитываются начиная с ЧТМ-2026\">Привезённые пенальти</abbr>" .. "]]", era = 2026 },
    { id = "mvp_goalie", title = "[[" .. "Игрок матча как вратарь" .. "]]", era = 2006 },
    { id = "goalie_goals", title = "<abbr title=\"Подсчитываются начиная с ЧТМ-2022\">[[" .. "Вратарские голы" .. "]]</abbr>", era = 2022 },
    { id = "clean_sheets", title = "[[" .. "Матчи на ноль" .. "]]", era = 2006 },
    { id = "yellow_cards", title = "<abbr title=\"Подсчитываются начиная с ЧТМ-2038\">[[" .. "Карточки|Жёлтые карточки" .. "]]</abbr>", era = 2038 },
    { id = "red_cards", title = "<abbr title=\"Подсчитываются начиная с ЧТМ-2038\">[[" .. "Карточки|Красные карточки" .. "]]</abbr>", era = 2038 },
    { id = "own_goals", title = "Автоголы", era = 2006 }
}

local function format_stage(st, let)
    if st == "Группа" then return "гр. " .. (let or "")
    elseif st == "Полуфинал" then return "1/2"
    elseif st == "За 3-е место" then return "за 3-е"
    elseif st == "Финал" then return "финал"
    end
    return st or ""
end

local function format_score(m)
    local s1, s2 = m.score1 or "0", m.score2 or "0"
    local sh1, sh2 = m.shootout1, m.shootout2
    if m.role_team == 2 then
        s1, s2 = m.score2 or "0", m.score1 or "0"
        sh1, sh2 = m.shootout2, m.shootout1
    end
    local txt = s1 .. ":" .. s2
    if m.aet then txt = txt .. "(ET)" end
    if sh1 and sh2 then txt = txt .. "(пен." .. sh1 .. ":" .. sh2 .. ")" end
    return txt
end

local function get_match_color(m)
    if not m.is_official then return "" end
    if m.role_team == 0 then return "lightgrey" end
    local is_t1 = (m.role_team == 1)
    local s1, s2 = tonumber(m.score1) or 0, tonumber(m.score2) or 0
    local win, loss, draw = false, false, false
    
    if m.shootout1 then
        draw = true
        if m.stage == "Финал" or m.stage == "финал" then
            local p1, p2 = tonumber(m.shootout1) or 0, tonumber(m.shootout2) or 0
            if (is_t1 and p1 > p2) or (not is_t1 and p2 > p1) then return "gold" else return "lightsalmon" end
        end
        return "palegoldenrod"
    else
        if s1 > s2 then win = is_t1; loss = not is_t1
        elseif s2 > s1 then win = not is_t1; loss = is_t1
        else draw = true end
        
        if m.stage == "Финал" or m.stage == "финал" then
            if win then return "gold" end
            if loss then return "lightsalmon" end
            return "palegoldenrod"
        end
        
        if draw then return "palegoldenrod" end
        if win then return "lightgreen" end
        return "lightsalmon"
    end
end

function p.build_ui(player_name, args, compiled_data)
    local sg_place = tonumber(args['СГ'] or args[2])
    local quality = args['Качество'] or args[3]
    local sg_year = args['Год'] or args['год'] or args['СГ_год'] or args[4] or "YYYY"

    local sortable = (args.sortable ~= "no")
    local show_main = (args.main_table ~= "no" and args.main_table ~= "0")
    local show_matches = (args.matches_list ~= "no" and args.matches_list ~= "0")
    local show_navboxes = (args.navboxes ~= "no" and args.navboxes ~= "0")
    local matches_link = args.matches_link

    local html_main = ""
    local html_list = ""
    local navs = {}

    if show_main then
        local classes = Config.styles.classes or "article-table ts-stickytableheader"
        if sortable then classes = classes .. " sortable" else classes = string.gsub(classes, "sortable", "") end
        local t_main = mw.html.create('table'):addClass(classes):attr('border', Config.styles.border or "1"):attr('cellspacing', Config.styles.cellspacing or "1"):attr('cellpadding', Config.styles.cellpadding or "1")

        local header_tr = t_main:tag('tr')
        header_tr:tag('th'):attr('scope', 'col'):cssText(Config.styles.header)
        for _, year in ipairs(Config.years) do
            local th = header_tr:tag('th'):attr('scope', 'col'):cssText(Config.styles.header)
            local text = "[[" .. year .. "|'" .. string.sub(tostring(year), 3, 4) .. "]]"
            if not compiled_data.played_years[year] then text = "<s>" .. text .. "</s>" end
            th:wikitext(text)
        end
        header_tr:tag('th'):attr('scope', 'col'):cssText(Config.styles.header):wikitext("ВСЕГО")

        for _, row in ipairs(p.row_defs) do
            local r_tr = t_main:tag('tr')
            r_tr:tag('td'):cssText("white-space:nowrap;text-align:center;"):wikitext(row.title)

            for _, year in ipairs(Config.years) do
                local td = r_tr:tag('td')
                local style = "white-space:nowrap;text-align:center;"
                
                if year < row.era then 
                    td:cssText(style .. Config.styles.header) 
                else
                    local m_data = compiled_data.metrics[row.id].years[year]
                    if m_data.color ~= "" then style = style .. m_data.color end
                    td:cssText(style)
                    
                    if compiled_data.played_years[year] then
                        local val_str = ""
                        if row.is_avg then 
                            val_str = (m_data.den > 0) and Config.utils.format_avg(m_data.num, m_data.den) or "0,00"
                        else 
                            val_str = tostring(m_data.val)
                            if row.is_pm and m_data.val > 0 then val_str = "+" .. val_str end 
                        end
                        td:wikitext(val_str)
                    end
                end
            end

            local td_tot = r_tr:tag('td')
            local style_tot = "white-space:nowrap;text-align:center;"
            if row.era > compiled_data.last_played_year then 
                td_tot:cssText(style_tot):wikitext("—") 
            else
                local m_tot = compiled_data.metrics[row.id]
                if m_tot.color and m_tot.color ~= "" then style_tot = style_tot .. m_tot.color end
                td_tot:cssText(style_tot)
                
                local tot_str = ""
                if row.is_avg then 
                    tot_str = (m_tot.total_den > 0) and Config.utils.format_avg(m_tot.total_num, m_tot.total_den) or "0,00"
                else 
                    tot_str = tostring(m_tot.total_val)
                    if row.is_pm and m_tot.total_val > 0 then tot_str = "+" .. tot_str end 
                end
                td_tot:wikitext("'''" .. tot_str .. "'''")
            end
        end
        html_main = tostring(t_main)
    end

    if show_matches and #compiled_data.player_matches_list > 0 then
        local pml = compiled_data.player_matches_list
        table.sort(pml, function(a, b) return a.num_hist < b.num_hist end)
        
        local url_matches = "https://thirdworldcup.ru/index.php?title=%D0%9F%D0%BE%D0%B4%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0:%D0%A0%D0%B0%D0%B7%D0%B2%D1%91%D1%80%D1%82%D0%BA%D0%B0_%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD%D0%BE%D0%B2/%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D0%BC%D0%B0%D1%82%D1%87%D0%B5%D0%B9&action=edit"
        local match_gear = " [[Файл:Gear icon.svg|12px|link=" .. url_matches .. "]] "
        
        -- Убираем класс mw-collapsed (свёрнуто), если главная таблица не выводится
        local list_classes = 'wikitable mw-collapsible'
        if show_main then list_classes = list_classes .. ' mw-collapsed' end
        
        local t_list = mw.html.create('table'):addClass(list_classes)
        t_list:tag('tr'):tag('th'):attr('colspan', '9'):wikitext((compiled_data.played_before_2022 and "Полный список матчей начиная с ЧТМ-2022" or "Полный список матчей") .. match_gear)
        
        local h_tr = t_list:tag('tr')
        local cols = {"№", "Настоящая<br>дата", "ЧТМ<br>(№ матча)", "Раунд", "Команда", "Соперник", "Счёт", "Статистика", "Дополнительно"}
        for _, col in ipairs(cols) do h_tr:tag('th'):attr('scope', 'col'):cssText(Config.styles.header):wikitext(col) end

        local counter = 1
        for _, m in ipairs(pml) do
            local tr = t_list:tag('tr')
            local bg_color = get_match_color(m)
            local style_td = "white-space:nowrap;text-align:center;" .. (bg_color ~= "" and ("background-color:" .. bg_color .. ";") or "")

            tr:tag('td'):cssText(style_td):wikitext(m.is_official and tostring(counter) or ""); if m.is_official then counter = counter + 1 end
            tr:tag('td'):cssText(style_td):wikitext(m.is_official and (m.date ~= "" and (m.date:sub(9,10).."."..m.date:sub(6,7).."."..m.date:sub(1,4)) or "") or "")
            tr:tag('td'):cssText(style_td):wikitext("[[" .. m.year .. "]] (" .. m.match_num_id .. ")")
            tr:tag('td'):cssText(style_td):wikitext(format_stage(m.stage, m.letter))

            local score_txt = format_score(m); if m.wikilink then score_txt = "'''[[" .. m.wikilink .. "|" .. score_txt .. "]]'''" end

            if m.role_team == 0 then
                tr:tag('td'):attr('colspan', '3'):cssText(style_td):wikitext("Вратарь ([[" .. Teams.getName(m.team1, 'short') .. "]] - [[" .. Teams.getName(m.team2, 'short') .. "]] - " .. score_txt .. ")")
            else
                tr:tag('td'):cssText(style_td):wikitext("[[" .. Teams.getName((m.role_team == 1) and m.team1 or m.team2, 'short') .. "]]")
                tr:tag('td'):cssText(style_td):wikitext("[[" .. Teams.getName((m.role_team == 1) and m.team2 or m.team1, 'short') .. "]]")
                tr:tag('td'):cssText(style_td):wikitext(score_txt)
            end

            local s_arr = {}
            if m.goals > 0 then table.insert(s_arr, "'''" .. (m.goals > 1 and m.goals or "") .. "Г'''") end
            if m.assists > 0 then table.insert(s_arr, "'''" .. (m.assists > 1 and m.assists or "") .. "П'''") end
            if m.is_mvp then table.insert(s_arr, "'''<u>MVP</u>'''") end
            tr:tag('td'):cssText(style_td):wikitext(table.concat(s_arr, ",&nbsp;"))
            tr:tag('td'):cssText(style_td):wikitext(#m.events > 0 and ("<small>" .. table.concat(m.events, "<br>") .. "</small>") or "<small></small>")
        end
        html_list = tostring(t_list)
    end

    if show_navboxes then
        local N = compiled_data.navbox_data
        
        local show_nav = {
            champs = (N.champ_counts[player_name] or 0) > 0, superchamps = false, zshar = false, zbashmak = false, elnur = false,
            final_goals = (N.final_goals[player_name] or 0) > 0, final_assists = (N.final_assists[player_name] or 0) > 0,
            club100 = (N.global_goals[player_name] or 0) >= 100, loyalty = false,
            org = (player_name == "Диман" or player_name == "Антон" or player_name == "Геныч")
        }
        local function has_p(lst) for _, i in ipairs(lst) do if i[2] == player_name then return true end end return false end
        show_nav.superchamps = has_p(N.superchamps); show_nav.zshar = has_p(N.zshar); show_nav.zbashmak = has_p(N.zbashmak); show_nav.elnur = has_p(N.elnur); show_nav.loyalty = has_p(N.loyalty)

        local function add_nav(args)
            local icon_td = args.noIcon and '<td style="vertical-align:middle; text-align:left; padding:0; display:none;"></td>' 
                or string.format('<td style="vertical-align:middle; text-align:left; padding:0; width:%s;">%s</td>', args.iconW or '30px', args.icon)
            
            local full_edit = mw.uri.encode("Шаблон:" .. args.editName, "PATH")
            local url_edit = "https://thirdworldcup.ru/index.php?title=" .. full_edit .. "&action=edit"
            local url_view = "https://thirdworldcup.ru/index.php/" .. full_edit
            
            local gear_img = "[[Файл:Gear icon.svg|12px|link=" .. url_view .. "]]"
            local edit_link = "[" .. url_edit .. ' <span title="Редактировать">&nbsp;' .. gear_img .. '&nbsp;</span>]'

            local html = string.format([[
<table style="clear:both; font-size:8pt; width:100%%; border-spacing:0; margin: 1px auto 1px auto;  background:%s;" data-collapsetext="скрыть" data-expandtext="показать" class="toccolours mw-collapsible mw-collapsed ">
     <tr style="color: #000000; background: %s; ">
      %s
      <th style="width:100%%; font-weight:bold; vertical-align:middle; text-align:center;"><div style="float:right; font-size:small; font-weight:normal;" class="plainlinks">%s</div><span style="font-size:140%%;">%s</span></th></tr>
     <tr>
      <td colspan="2" style="vertical-align:middle; text-align:center; padding:0;">
       <table style="width:100%%; background-color:transparent ">%s</table>
      </td>
     </tr>
</table>%s]], args.bg, args.bg, icon_td, edit_link, args.title, args.content, args.cat)
            table.insert(navs, html)
        end

        if show_nav.champs then
            local rows, v_years = {}, {}
            for y, _ in pairs(N.champs) do table.insert(v_years, y) end
            table.sort(v_years)
            
            local running_counts = {}
            for i, y in ipairs(v_years) do
                local p_list = N.champs[y]; table.sort(p_list)
                local fps = {}
                for _, p_name in ipairs(p_list) do
                    running_counts[p_name] = (running_counts[p_name] or 0) + 1
                    table.insert(fps, "[["..p_name.."]]" .. (running_counts[p_name] > 1 and " ("..running_counts[p_name]..")" or "")) 
                end
                table.insert(rows, string.format('<tr><td style="text-align:right; width:15%%; padding:0 0.5em; font-weight:bold; color: black; background: LightSteelBlue; ">[[Финал ЧТМ-%d|%d]]</td>\n<td style="text-align:left; padding:0 0.5em;   "><span style="font-size:120%%;">%s%s</span></td></tr>', y, y, table.concat(fps, "&nbsp;&bull; "), (i == #v_years and "" or "\n----")))
            end
            add_nav({bg='LightSteelBlue', icon='[[Файл:Star.png|30px|]]', editName='Игроки-чемпионы третьего мира', title='[[Список игроков-чемпионов третьего мира|Игроки-чемпионы третьего мира]]', cat='[[Категория:Игроки-чемпионы]]', content=table.concat(rows)})
        end

        local function flat_chron(list)
            local parts = {}
            for _, i in ipairs(list) do table.insert(parts, "[["..i[2].."]]&nbsp;([["..i[1].."]])") end
            return '<span style="font-size:120%;">' .. table.concat(parts, "&nbsp;&bull; ") .. '</span>'
        end

        if show_nav.superchamps then add_nav({bg='DarkGray', icon='[[Файл:Суперчемпион.png|30px|]]', editName='Суперчемпионы', title='[[Суперчемпион]]ы', cat='[[Категория:Суперчемпионы]]', content=flat_chron(N.superchamps)}) end
        if show_nav.zshar then add_nav({bg='PaleGreen', icon='[[Файл:ЗШар.png|30px|]]', editName='Лучшие игроки ЧТМ', title='[[Золотой Шар|Лучшие игроки ЧТМ]]', cat='[[Категория:Обладатели Золотого Шара]]', content=flat_chron(N.zshar)}) end

        if show_nav.zbashmak then
            local grp, sy, parts = {}, {}, {}
            for _, i in ipairs(N.zbashmak) do if not grp[i[1]] then grp[i[1]]={g=i[3], p={}} end; table.insert(grp[i[1]].p, {i[2], i[4]}) end
            for y in pairs(grp) do table.insert(sy, y) end; table.sort(sy)
            for _, y in ipairs(sy) do
                table.sort(grp[y].p, function(a,b) return a[1] < b[1] end); local ps = {}
                for _, pi in ipairs(grp[y].p) do table.insert(ps, "[["..pi[1].."]] ([["..y.."]], [["..(Teams.getName(pi[2], 'short') or pi[2]).."]])") end
                table.insert(parts, table.concat(ps, "; ") .. "&nbsp;—&nbsp;" .. grp[y].g)
            end
            add_nav({bg='palegoldenrod', icon='[[Файл:Золотой Башмак.png|42px|]]', iconW='42px', editName='Лучшие бомбардиры ЧТМ', title='[[Золотой Башмак|Лучшие бомбардиры ЧТМ]]', cat='[[Категория:Обладатели Золотого Башмака]]', content='<span style="font-size:120%;">' .. table.concat(parts, "&nbsp;&bull; ") .. '</span>'})
        end

        if show_nav.elnur then add_nav({bg='Gainsboro', icon='[[Файл:Приз имени Эльнура.png|16px|]]', iconW='16px', editName='Лучшие вратари ЧТМ', title='[[Приз имени Эльнура|Лучшие вратари ЧТМ]]', cat='[[Категория:Обладатели Приза имени Эльнура]]', content=flat_chron(N.elnur)}) end

        local function flat_actions(map)
            local l, p = {}, {}
            for n, c in pairs(map) do table.insert(l, {n, c}) end; table.sort(l, function(a,b) return a[1] < b[1] end)
            for _, i in ipairs(l) do table.insert(p, "[["..i[1].."]]&nbsp;("..i[2]..")") end
            return '<span style="font-size:120%;">' .. table.concat(p, "&nbsp;&bull; ") .. '</span>'
        end

        if show_nav.final_goals then add_nav({bg='IndianRed', icon='[[Файл:Kipsta ball.png|30px|]]', editName='Авторы голов в финале ЧТМ', title='Авторы голов в финале ЧТМ', cat='[[Категория:Авторы голов в финале]]', content=flat_actions(N.final_goals)}) end
        if show_nav.final_assists then add_nav({bg='tan', icon='[[Файл:Assist.png|30px|]]', editName='Авторы голевых передач в финале ЧТМ', title='Авторы голевых передач в финале ЧТМ', cat='[[Категория:Авторы голевых передач в финале]]', content=flat_actions(N.final_assists)}) end

        if show_nav.club100 then
            local pl = {}
            for p_name, g in pairs(N.global_goals) do if g >= 100 then table.insert(pl, p_name) end end; table.sort(pl)
            for i, p_name in ipairs(pl) do pl[i] = "[["..p_name.."]]" end
            add_nav({bg='plum', icon='[[Файл:Клуб 100.svg|30px|]]', editName='Клуб 100', title='[[Клуб 100]]', cat='[[Категория:Клуб 100]]', content='<span style="font-size:120%;">'..table.concat(pl, "&nbsp;&bull; ")..'</span>'})
        end

        if show_nav.loyalty then
            table.sort(N.loyalty, function(a,b) if a[1] ~= b[1] then return a[1] < b[1] end return a[2] < b[2] end); local pts = {}
            for _, i in ipairs(N.loyalty) do table.insert(pts, "[["..i[1].."]] — [["..i[2].."]] (''[["..(Teams.getName(i[3], 'short') or i[3]).."]]'')") end
            add_nav({bg='MediumAquamarine', noIcon=true, editName='Верность команде', title='Обладатели приза «[[Верность команде]]»', cat='[[Категория:Обладатели приза «Верность команде»]]', content='<span style="font-size:120%;">'..table.concat(pts, "&nbsp;&bull; ")..'</span>'})
        end

        local gens, g_rows = { {t="Первое поколение<br>(2006—2007)", l={}}, {t="Второе поколение<br>(2011—2013)", l={}}, {t="Третье поколение<br>(2020—<abbr title=\"настоящее время\" class=\"nowrap\">н.&thinsp;в.</abbr>)", l={}} }, {}
        for p_name, y in pairs(N.debuts) do if y <= 2018 then table.insert(gens[1].l, p_name) elseif y <= 2034 then table.insert(gens[2].l, p_name) else table.insert(gens[3].l, p_name) end end
        for i, g in ipairs(gens) do
            if #g.l > 0 then
                table.sort(g.l); local p_strs = {}
                for _, p_name in ipairs(g.l) do table.insert(p_strs, "[["..p_name.."]]"..string.rep("&#9733;", N.champ_counts[p_name] or 0)) end
                table.insert(g_rows, string.format('<tr><td style="text-align:right; width:15%%; padding:0 0.5em; font-weight:bold; color: black; background: Thistle; ">%s</td>\n<td style="text-align:left; padding:0 0.5em;   "><span style="font-size:120%%;">%s%s</span></td></tr>', g.t, table.concat(p_strs, "&nbsp;&bull; "), (i == #gens and "" or "\n----")))
            end
        end
        add_nav({bg='Thistle', icon='[[Файл:Logo.png|32px|]]', iconW='32px', editName='Игроки ЧТМ', title='Игроки ЧТМ', cat='[[Категория:Игроки]]', content=table.concat(g_rows)})

        if show_nav.org then table.insert(navs, '{{Организация ЧТМ}}') end
    end

    local function render_amboxes()
        local out = {}
        if sg_place == 1 then
            table.insert(out, '<indicator name="1">[[Файл:Лучшая статья года.png|36px|link=ЧТМ:Статьи года|Эта статья была признана лучшей статьёй ЧТМ Вики '..sg_year..' года]]</indicator>\n{{Ambox\n|id = 1-message\n|name  = Статья года\n|type  = good\n|image = [[Файл:Лучшая статья года.png|24px|link=ЧТМ:Статьи года|alt=✰]]\n|text  = Эта статья была признана \'\'\'[[ЧТМ Вики:Статьи года|лучшей статьёй]]\'\'\' ЧТМ Вики '..sg_year..' года.\n}}[[Категория:Лучшие статьи года]][[Категория:Статьи года]]')
        elseif sg_place and sg_place >= 2 and sg_place <= 10 then
            table.insert(out, '<indicator name="2">[[Файл:Статья года.png|32px|link=ЧТМ:Статьи года|Эта статья заняла '..sg_place..' место в голосовании за звание лучшей статьи '..sg_year..' года]]</indicator>\n{{Ambox\n|id = 2-message\n|name  = Статья года\n|type  = good\n|image = [[Файл:Статья года.png|24px|link=ЧТМ:Статьи года|alt=✰]]\n|text  = Эта статья заняла '..sg_place..' место в голосовании за звание \'\'\'[[ЧТМ Вики:Статьи года|лучшей статьи]]\'\'\' '..sg_year..' года.\n}}[[Категория:Статьи года]]')
        end
        if quality == 'ИС' then
            table.insert(out, '<indicator name="3">[[Файл:Skew star.png|28px|link=ЧТМ:Избранные статьи|Эта статья входит в число избранных статей ЧТМ Вики]]</indicator>\n{{Ambox\n|id = 3-message\n|name  = Избранная статья\n|type  = good\n|image = [[Файл:Skew star.png|24px|link=ЧТМ:Избранные статьи|alt=✰]]\n|text  = Эта статья входит в число [[ЧТМ:Избранные статьи|избранных статей]] ЧТМ Вики.\n}}[[Категория:Избранные статьи]]')
        elseif quality == 'ХС' then
            table.insert(out, '<indicator name="4">[[Файл:Blue star.png|28px|link=ЧТМ:Хорошие статьи|Эта статья входит в число хороших статей ЧТМ Вики]]</indicator>\n{{Ambox\n|id = 4-message\n|name  = Хорошая статья\n|type  = good\n|image = [[Файл:Blue star.png|24px|link=ЧТМ:Хорошие статьи|alt=✰]]\n|text  = Эта статья входит в число [[ЧТМ:Хорошие статьи|хороших статей]] ЧТМ Вики.\n}}[[Категория:Хорошие статьи]]')
        end
        return table.concat(out, "\n")
    end

	local out_str = Config.styles.wiki_templates
    
    -- Добавляем заголовок "== Статистика ==" только если выводится главная таблица
    if show_main then 
        out_str = out_str .. "== Статистика ==\n" .. html_main .. "\n" 
    end
    
    if show_matches then
        -- Если главной таблицы нет, то список матчей становится главным блоком, даём ему заголовок
        if not show_main then
            out_str = out_str .. "== Список матчей ==\n"
        end
        out_str = out_str .. html_list .. "\n"
    else
        local link_target = matches_link or "/Список матчей"
        out_str = out_str .. "'''[[" .. link_target .. "|Полный список матчей]]'''.\n"
    end
    
    out_str = out_str .. render_amboxes() .. "\n"
    if show_navboxes then out_str = out_str .. table.concat(navs, "\n") end
    
    return out_str
end

return p