Модуль:SimpleStats

Материал из ЧТМ
Перейти к навигации Перейти к поиску
Документация Документация
Модуль для вывода простых таблиц статистических данных за всю историю ЧТМ.

Использование

Для обычного вызова:

{{#invoke:SimpleStats|main|metric=goals}}

Если нужно отключить сортировку (по умолчанию она включена):

{{#invoke:SimpleStats|main|metric=assists|sortable=no}}

Полный список доступных показателей для вызова:

В параметр metric= можно подставлять абсолютно любой ключ из Config.metrics:

  1. Голы и виды мячей: goals (все голы), head_goals (головой), heel_goals (пяточкой), free_kick_goals (со штрафных), goalie_goals (вратарские), own_goals (автоголы).
  2. Передачи и выносы: assists (голевые передачи), clearances (выносы из пустых).
  3. Мульти-действия: mega_tricks (сумма хет-триков, покеров и т.д.), assist_mega_tricks (ассистентские мега-трики).
  4. Пенальти: pens_scored (забитые), pens_missed (незабитые), pens_saved (отбитые вратарем), caused_pens (привезенные пенальти).
  5. Вратари и карточки: clean_sheets (матчи на ноль), yellow_cards (ЖК), red_cards (КК).
  6. Награды и MVP: mvp, mvp_goalie, matchday_prizes (призы дня), matchday_places (попадания в тройку).
  7. Матчи и средние показатели: matches, field_matches, plus_minus, avg_goals (в среднем за матч), avg_assists.

Страницы, подгружающие модуль в чистом виде

Пожалуйста, добавляйте категории на страницу документации.

local p = {}
local Config = require('Module:Config')

function p.main(frame)
    -- Собираем аргументы
    local args = frame:getParent().args
    if frame.args[1] or frame.args.metric then
        for k, v in pairs(frame.args) do args[k] = v end
    end

    local metric_id = args[1] or args.metric
    if not metric_id or not Config.metrics[metric_id] then
        return "'''Ошибка:''' Не указан или не найден показатель (metric). Проверьте правильность названия."
    end

    local sortable = (args.sortable ~= 'no' and args.sortable ~= '0' and args.sortable ~= 'false')

    -- 1. Загружаем закэшированную JSON-базу
    local title = mw.title.new('Модуль:Data/GrandStats.json')
    if not title then return "'''Ошибка:''' Не удалось найти страницу с кэшем БД (Модуль:Data/GrandStats.json)." end
    
    local content = title:getContent()
    if not content then return "'''Ошибка:''' Страница кэша пуста." end
    
    local db = mw.text.jsonDecode(content)
    if not db or not db.Players then return "'''Ошибка:''' Неверный формат JSON-кэша." end

    -- 2. Достаём настройки показателя
    local m_config = Config.metrics[metric_id]
    local is_avg = m_config.is_average
    local start_year = m_config.start or 2006

    -- Формируем массив ТОЛЬКО тех годов, с которых ведётся статистика
    local valid_years = {}
    for _, y in ipairs(Config.years) do
        if y >= start_year then table.insert(valid_years, y) end
    end

    -- 3. Собираем игроков
    local players = {}
    for p_name, p_data in pairs(db.Players) do
        local m_data = p_data.AS_compiled.metrics[metric_id]
        if m_data then
            local p_tie = {
                name = p_name,
                total_val = m_data.total_val or 0,
                total_num = m_data.total_num or 0,
                total_den = m_data.total_den or 0,
                years = {}
            }
            
            for y_str, y_data in pairs(m_data.years or {}) do
                local y = tonumber(y_str)
                if is_avg then
                    p_tie.years[y] = { num = y_data.num, den = y_data.den }
                else
                    p_tie.years[y] = y_data.val
                end
            end

            local p_obj = {
                name = p_name,
                total_val = m_data.total_val or 0,
                total_num = m_data.total_num or 0,
                total_den = m_data.total_den or 0,
                color = m_data.color or "",
                years = {},
                played_years = p_data.AS_compiled.played_years or {},
                tie_data = p_tie
            }
            
            for y_str, y_data in pairs(m_data.years or {}) do
                p_obj.years[tonumber(y_str)] = y_data
            end
            
            table.insert(players, p_obj)
        end
    end

    -- 4. Сортируем (ЖЕЛЕЗНО по убыванию). 
    -- Передаём false в sort_asc: +216 будет выше, чем -95; а 10 красных карточек будут выше, чем 0.
    table.sort(players, function(a, b)
        return Config.tiebreaker(a.tie_data, b.tie_data, valid_years, is_avg, false)
    end)

    -- 5. Собираем шапку таблицы (теперь без лишних колонок)
    local cols = { "Место", "Игрок" }
    for _, y in ipairs(valid_years) do
        table.insert(cols, "[[" .. y .. "|'" .. string.sub(tostring(y), 3, 4) .. "]]")
    end
    table.insert(cols, "ВСЕГО")

    local html = Config.builder.start(cols)
    if not sortable then html:removeClass('sortable') end

    local totals = { val = 0, num = 0, den = 0, years = {} }
    for _, y in ipairs(valid_years) do totals.years[y] = { val = 0, num = 0, den = 0 } end

    -- 6. Строим строки игроков
    for i, p_obj in ipairs(players) do
        local row_cells = {}
        
        table.insert(row_cells, i)
        table.insert(row_cells, "[[" .. p_obj.name .. "]]")

        totals.val = totals.val + p_obj.total_val
        totals.num = totals.num + p_obj.total_num
        totals.den = totals.den + p_obj.total_den

        for _, y in ipairs(valid_years) do
            local y_data = p_obj.years[y]
            local played = p_obj.played_years[tostring(y)] or p_obj.played_years[y]
            local cell = { style = Config.styles.center_nowrap }
            
            if y_data then
                if y_data.color and y_data.color ~= "" then
                    cell.style = y_data.color .. " " .. Config.styles.center_nowrap
                end
                
                if is_avg then
                    cell.text = Config.utils.format_avg(y_data.num, y_data.den)
                    totals.years[y].num = totals.years[y].num + y_data.num
                    totals.years[y].den = totals.years[y].den + y_data.den
                else
                    cell.text = Config.utils.format_val(metric_id, y_data.val)
                    totals.years[y].val = totals.years[y].val + y_data.val
                end
            elseif played then
                cell.text = is_avg and "0,00" or "0"
            else
                cell.text = ""
            end
            
            table.insert(row_cells, cell)
        end

        local total_text = ""
        if is_avg then
            total_text = "'''" .. Config.utils.format_avg(p_obj.total_num, p_obj.total_den) .. "'''"
        else
            total_text = "'''" .. Config.utils.format_val(metric_id, p_obj.total_val) .. "'''"
        end
        
        local total_style = Config.styles.center_nowrap
        if p_obj.color and p_obj.color ~= "" then
            total_style = p_obj.color .. " " .. Config.styles.center_nowrap
        end
        table.insert(row_cells, { text = total_text, style = total_style })

        Config.builder.row(html, row_cells)
    end

    -- 7. Строим "Подвал" (Нижняя строчка) с учетом adjustments
    local adj_totals = (m_config.adjustments and m_config.adjustments.totals) or {}
    local extra_grand_total = adj_totals["total"] or 0

    local foot_cells = {}
    table.insert(foot_cells, { text = "'''ВСЕГО'''", colspan = 2, style = Config.styles.center_nowrap })
    
    for _, y in ipairs(valid_years) do
        -- Ищем бесхозные добавки для конкретного года (если есть)
        local y_adj = adj_totals[y] or adj_totals[tostring(y)] or 0
        extra_grand_total = extra_grand_total + y_adj

        local f_text = ""
        if is_avg then
            f_text = "'''" .. Config.utils.format_avg(totals.years[y].num, totals.years[y].den) .. "'''"
        else
            totals.years[y].val = totals.years[y].val + y_adj
            f_text = "'''" .. Config.utils.format_val(metric_id, totals.years[y].val) .. "'''"
        end
        table.insert(foot_cells, { text = f_text, style = Config.styles.center_nowrap })
    end

    -- Самая последняя ячейка
    local gt_text = ""
    if is_avg then
        gt_text = "'''" .. Config.utils.format_avg(totals.num, totals.den) .. "'''"
    else
        gt_text = "'''" .. Config.utils.format_val(metric_id, totals.val + extra_grand_total) .. "'''"
    end
    table.insert(foot_cells, { text = gt_text, style = Config.styles.center_nowrap })

    Config.builder.row(html, foot_cells)

    return frame:preprocess(Config.styles.wiki_templates .. tostring(html))
end

return p