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

Материал из ЧТМ
Перейти к навигации Перейти к поиску
Версия 0.3
Версия 1.0, работает и для искомой страницы, и как чистый движок, всё тщательно протестировано
 
(не показано 9 промежуточных версий этого же участника)
Строка 1: Строка 1:
-- =====================================================
-- =====================================================
-- Модуль:Significance (калькулятор значимости игроков)
-- Модуль:Significance (калькулятор значимости игроков)
-- Версия 0.3
-- Версия 1.0
-- =====================================================
-- =====================================================
local Significance = {}
local Significance = {}
Строка 9: Строка 9:
local Megarating = require('Module:Megarating')
local Megarating = require('Module:Megarating')


-- Вспомогательная функция (Галочки)
-- ==========================================
local function mark(condition)
-- РУЧНЫЕ ИСКЛЮЧЕНИЯ (Особые случаи)
     return condition and '<span style="color:green;">✅ Да</span>' or '<span style="color:red;">❌ Нет</span>'
-- ==========================================
local SPECIAL_CASES = {
    ["Амид"] = "[[ЦАР-КИР2026|о.случай]]",
    ["Губа"] = "[[Финал ЧТМ-2014#Дополнительное время|о.случай]]",
    ["Другой Очкан"] = "[[ДОМ-АФГ2018#Серия пенальти|о.случай]]",
    ["Рамиз"] = "[[ДОМ-АФГ2018#Серия пенальти|о.случай]]",
}
 
-- =====================================================
-- API ДВИЖКА (Для использования во внешних "Монстрах")
-- =====================================================
 
-- 1. Выдает пустую "болванку" (схему) для нового игрока
function Significance.createPlayerStruct(name)
     return {
        name = name,
        tournaments_played = 0, top5 = 0, top10 = 0,
        matches_total = 0, goals = {total=0}, assists = {total=0}, mvp = {is_mvp=0},
        megarating = {final_goals=0, final_assists=0},
        awards = {
            golden_spheres=0, other_spheres=0, golden_shoes=0, other_shoes=0,
            golden_assistants=0, other_assistants=0, best_goalies=0,
            superchamps=0, titles=0, finals_played=0
        }
    }
end
end


-- Утилита для слияния статов
-- 2. Вливает статистику из БД одного года в общую копилку игрока
local function merge_stats(target, source)
function Significance.mergeStats(target, source)
    -- Эта функция дублирует логику слияния из Harvester,
    -- чтобы собирать ГрандСтатс из кусочков годов.
    -- Упрощенный вариант только для того, что нам нужно для Значимости
     target.matches_total = (target.matches_total or 0) + (source.matches_total or 0)
     target.matches_total = (target.matches_total or 0) + (source.matches_total or 0)
     target.goals.total = (target.goals.total or 0) + (source.goals.total or 0)
     target.goals.total = (target.goals.total or 0) + (source.goals.total or 0)
Строка 28: Строка 49:
      
      
     if source.awards then
     if source.awards then
        if not target.awards then target.awards = {golden_spheres=0, other_spheres=0, golden_boots=0, other_boots=0, golden_assistants=0, other_assistants=0, best_goalies=0, superchamps=0, titles=0, finals_played=0} end
         target.awards.golden_spheres = target.awards.golden_spheres + (source.awards.golden_spheres or 0)
         target.awards.golden_spheres = target.awards.golden_spheres + source.awards.golden_spheres
         target.awards.other_spheres = target.awards.other_spheres + (source.awards.other_spheres or 0)
         target.awards.other_spheres = target.awards.other_spheres + source.awards.other_spheres
         target.awards.golden_shoes = target.awards.golden_shoes + (source.awards.golden_shoes or 0)
         target.awards.golden_boots = target.awards.golden_boots + source.awards.golden_boots
         target.awards.other_shoes = target.awards.other_shoes + (source.awards.other_shoes or 0)
         target.awards.other_boots = target.awards.other_boots + source.awards.other_boots
         target.awards.golden_assistants = target.awards.golden_assistants + (source.awards.golden_assistants or 0)
         target.awards.golden_assistants = target.awards.golden_assistants + source.awards.golden_assistants
         target.awards.other_assistants = target.awards.other_assistants + (source.awards.other_assistants or 0)
         target.awards.other_assistants = target.awards.other_assistants + source.awards.other_assistants
         target.awards.best_goalies = target.awards.best_goalies + (source.awards.best_goalies or 0)
         target.awards.best_goalies = target.awards.best_goalies + source.awards.best_goalies
         target.awards.superchamps = target.awards.superchamps + (source.awards.superchamps or 0)
         target.awards.superchamps = target.awards.superchamps + source.awards.superchamps
         target.awards.titles = target.awards.titles + (source.awards.titles or 0)
         target.awards.titles = target.awards.titles + source.awards.titles
         target.awards.finals_played = target.awards.finals_played + (source.awards.finals_played or 0)
         target.awards.finals_played = target.awards.finals_played + source.awards.finals_played
     end
     end
end
end


-- ==========================================
-- 3. ЧИСТЫЙ КАЛЬКУЛЯТОР. Принимает заполненную структуру, возвращает уровень значимости.
-- СУПЕР-ЦИКЛ (Вся сборка в ОДИН проход)
function Significance.evaluatePlayer(p_stats)
-- ==========================================
    local aw = p_stats.awards
    local sum_awards = aw.other_spheres + aw.golden_shoes + aw.other_shoes + aw.best_goalies
    local any_award_exist = (sum_awards > 0) or (aw.golden_spheres > 0)
 
    -- 1. МАКСИМАЛЬНАЯ
    local m_c1 = (aw.golden_spheres >= 1)
    local m_c2 = (aw.titles >= 2 or aw.superchamps >= 1)
    local m_c3 = (p_stats.goals.total >= 75 or p_stats.assists.total >= 50 or p_stats.mvp.is_mvp >= 20)
    local m_c4 = (p_stats.megarating.final_goals >= 2 or p_stats.megarating.final_assists >= 3 or aw.finals_played >= 4)
    local m_c5 = (sum_awards >= 4)
    local m_c6 = (p_stats.top5 >= 2 or p_stats.top10 >= 4)
    if m_c1 and ((m_c1 and 1 or 0) + (m_c2 and 1 or 0) + (m_c3 and 1 or 0) + (m_c4 and 1 or 0) + (m_c5 and 1 or 0) + (m_c6 and 1 or 0)) >= 4 then return "Максимальная" end
 
    -- 2. ВЫСОКАЯ
    local h_score = (any_award_exist and 1 or 0) + ((aw.titles >= 1) and 1 or 0) + ((p_stats.goals.total >= 40 or p_stats.assists.total >= 25 or p_stats.mvp.is_mvp >= 10) and 1 or 0) + ((p_stats.megarating.final_goals >= 1 or p_stats.megarating.final_assists >= 2 or aw.finals_played >= 3) and 1 or 0) + ((p_stats.tournaments_played >= 6) and 1 or 0) + ((p_stats.top5 >= 1 or p_stats.top10 >= 3) and 1 or 0)
    if h_score >= 4 then return "Высокая" end
 
    -- 3. СРЕДНЯЯ
    local a_score = (any_award_exist and 1 or 0) + ((aw.titles >= 1) and 1 or 0) + ((p_stats.goals.total >= 20 or p_stats.assists.total >= 15 or p_stats.mvp.is_mvp >= 5) and 1 or 0) + ((p_stats.megarating.final_goals >= 1 or p_stats.megarating.final_assists >= 2 or aw.finals_played >= 3) and 1 or 0) + ((p_stats.tournaments_played >= 4) and 1 or 0) + ((p_stats.top5 >= 1 or p_stats.top10 >= 2) and 1 or 0)
    if a_score >= 2 then return "Средняя" end
 
    -- 4. НИЖЕ СРЕДНЕГО
    local main_score = ((p_stats.goals.total >= 10) and 1 or 0) + ((aw.titles >= 1 or aw.finals_played >= 2) and 1 or 0) + ((p_stats.tournaments_played >= 3) and 1 or 0) + ((p_stats.mvp.is_mvp >= 3) and 1 or 0) + ((p_stats.assists.total >= 8) and 1 or 0) + ((p_stats.megarating.final_goals >= 1 or p_stats.megarating.final_assists >= 1) and 1 or 0) + ((p_stats.top10 >= 1) and 1 or 0)
    local sub_score = ((p_stats.goals.total >= 5) and 1 or 0) + ((aw.finals_played >= 1) and 1 or 0) + ((p_stats.tournaments_played >= 2) and 1 or 0) + ((p_stats.mvp.is_mvp >= 2) and 1 or 0) + ((p_stats.assists.total >= 4) and 1 or 0)
    if main_score >= 1 or sub_score >= 2 then return "Ниже среднего" end
 
    -- 5. НИЗКАЯ
    local l_score = ((p_stats.goals.total >= 1) and 1 or 0) + ((aw.finals_played >= 1) and 1 or 0) + ((p_stats.tournaments_played >= 3) and 1 or 0) + ((p_stats.mvp.is_mvp >= 1) and 1 or 0) + ((p_stats.assists.total >= 2) and 1 or 0) + ((p_stats.matches_total >= 10) and 1 or 0)
    if l_score >= 1 or SPECIAL_CASES[p_stats.name] then return "Низкая" end
 
    return "Случайный прохожий"
end
 
 
-- =====================================================
-- ВНУТРЕННИЙ ФУНКЦИОНАЛ ДЛЯ ОТРИСОВКИ СТРАНИЦЫ
-- =====================================================
 
local function get_plural_players(count)
    local d10 = count % 10
    local d100 = count % 100
    if d10 == 1 and d100 ~= 11 then return count .. " игрок"
    elseif d10 >= 2 and d10 <= 4 and (d100 < 10 or d100 >= 20) then return count .. " игрока"
    else return count .. " игроков" end
end
 
local function cell(text, is_main, is_sub)
    local bg = ""
    if is_main then bg = Config.styles.lightgreen
    elseif is_sub then bg = Config.styles.palegoldenrod end
    return { text = tostring(text), style = Config.styles.center_nowrap .. bg }
end
 
local _grand_cache = nil
local _grand_cache = nil


local function build_master_database()
local function build_master_database()
     if _grand_cache then return _grand_cache end
     if _grand_cache then return _grand_cache end
   
     local GrandStats = {}
     local GrandStats = {}
     local latest_year = Config.years[#Config.years]
     local latest_year = Config.years[#Config.years]
Строка 59: Строка 130:
          
          
         if success and type(year_db) == "table" then
         if success and type(year_db) == "table" then
            -- 1. ЗАПУСКАЕМ КОМБАЙН (ОДИН РАЗ!)
             local year_stats = StatEngine.Harvester.run(year_db, {need_players = true})
             local year_stats = StatEngine.Harvester.run(year_db, {need_players = true})
           
            -- 2. СЛИВАЕМ В ОБЩИЙ КОТЕЛ ИГРОКА
             for p_name, p_data in pairs(year_stats.Players) do
             for p_name, p_data in pairs(year_stats.Players) do
                 if not GrandStats[p_name] then
                 if not GrandStats[p_name] then
                     GrandStats[p_name] = {
                    -- ИСПОЛЬЗУЕМ СОБСТВЕННЫЙ API
                        name = p_name, tournaments_played = 0, top5 = 0, top10 = 0,
                     GrandStats[p_name] = Significance.createPlayerStruct(p_name)
                        matches_total = 0, goals = {total=0}, assists = {total=0}, mvp = {is_mvp=0},
                        megarating = {final_goals=0, final_assists=0},
                        awards = {golden_spheres=0, other_spheres=0, golden_boots=0, other_boots=0, golden_assistants=0, other_assistants=0, best_goalies=0, superchamps=0, titles=0, finals_played=0}
                    }
                 end
                 end
                 GrandStats[p_name].tournaments_played = GrandStats[p_name].tournaments_played + 1
                 GrandStats[p_name].tournaments_played = GrandStats[p_name].tournaments_played + 1
                 merge_stats(GrandStats[p_name], p_data)
                 -- ИСПОЛЬЗУЕМ СОБСТВЕННЫЙ API
                Significance.mergeStats(GrandStats[p_name], p_data)
             end
             end
              
              
            -- 3. ЗАПУСКАЕМ ДВИЖОК МЕГАРЕЙТИНГА И СРАЗУ ЗАБИРАЕМ ТОП-10
             if is_finished then
             if is_finished then
                 local mr_list = Megarating.evaluate_raw_stats(year, year_db, year_stats.Players)
                 local mr_list = Megarating.evaluate_raw_stats(year, year_db, year_stats.Players)
                 local spheres = Megarating.get_spheres_from_db(year_db)
                 local spheres = Megarating.get_spheres_from_db(year_db)
               
                 if #mr_list > 0 then
                 if #mr_list > 0 then
                     table.sort(mr_list, function(a, b) return Megarating.compare_players_public(a, b, year, spheres) end)
                     table.sort(mr_list, function(a, b) return Megarating.compare_players_public(a, b, year, spheres) end)
                   
                     local current_rank = 1
                     local current_rank = 1
                     for i, p in ipairs(mr_list) do
                     for i, p in ipairs(mr_list) do
                         if i > 1 then
                         if i > 1 and p.total_points ~= mr_list[i-1].total_points then current_rank = i end
                            -- Проверяем на идеальное равенство тайбрейкера, чтобы не давать 6-е место тому, кто делит 5-е
                            if p.total_points ~= mr_list[i-1].total_points then current_rank = i end
                        end
                       
                         if current_rank <= 10 then
                         if current_rank <= 10 then
                             if GrandStats[p.name] then
                             if GrandStats[p.name] then
                                 GrandStats[p.name].top10 = GrandStats[p.name].top10 + 1
                                 GrandStats[p.name].top10 = GrandStats[p.name].top10 + 1
                                 if current_rank <= 5 then
                                 if current_rank <= 5 then GrandStats[p.name].top5 = GrandStats[p.name].top5 + 1 end
                                    GrandStats[p.name].top5 = GrandStats[p.name].top5 + 1
                                end
                             end
                             end
                         else
                         else break end
                            break -- Дальше Топ-10 нам для Значимости не нужно
                        end
                     end
                     end
                 end
                 end
Строка 106: Строка 160:
         end
         end
     end
     end
   
     _grand_cache = GrandStats
     _grand_cache = GrandStats
     return _grand_cache
     return _grand_cache
end
end


-- ==========================================
-- (Тут идёт функция build_tier_table без изменений)
-- ОЦЕНКА ОДНОГО ИГРОКА ИЗ СОБРАННОЙ БАЗЫ
local function build_tier_table(tier, list)
-- ==========================================
    if #list == 0 then return "" end
function Significance.evaluate_player(p_stats)
    local html
    local logs = {}
 
    local function log_cat(title) table.insert(logs, "\n=== " .. title .. " ===") end
    for _, p in ipairs(list) do
    local function log_item(text) table.insert(logs, text) end
        local aw = p.awards
        local g = p.goals.total
        local a = p.assists.total
        local m = p.mvp.is_mvp
        local fg = p.megarating.final_goals
        local fa = p.megarating.final_assists
        local fp = aw.finals_played
        local tp = p.tournaments_played
        local t5 = p.top5
        local t10 = p.top10
       
        -- Группировка наград для вывода
        local all_shoes = aw.golden_shoes + aw.other_shoes
        local all_spheres = aw.golden_spheres + aw.other_spheres
        local other_spheres = aw.other_spheres
        local goalies = aw.best_goalies
       
        local sum_aw = other_spheres + all_shoes + goalies
        local sum_all_aw = all_spheres + all_shoes + goalies
       
        if tier == "Максимальная" then
            if not html then html = Config.builder.start({"Игрок", "ЗШ", "Ч/СЧ", "Г/П/MVP", "ГФ/ПФ/УФ", "Ш/Б/В", "М5/М10"}) end
            local c1 = aw.golden_spheres >= 1
            local c2 = aw.titles >= 2 or aw.superchamps >= 1
            local c3 = g >= 75 or a >= 50 or m >= 20
            local c4 = fg >= 2 or fa >= 3 or fp >= 4
            local c5 = sum_aw >= 4
            local str_awards = other_spheres .. " / " .. all_shoes .. " / " .. goalies
            local c6 = t5 >= 2 or t10 >= 4
            Config.builder.row(html, {
                "'''[[" .. p.name .. "]]'''",
                cell(aw.golden_spheres, c1), cell(aw.titles .. " / " .. aw.superchamps, c2),
                cell(g .. " / " .. a .. " / " .. m, c3), cell(fg .. " / " .. fa .. " / " .. fp, c4),
                cell(str_awards, c5), cell(t5 .. " / " .. t10, c6)
            })
 
        elseif tier == "Высокая" or tier == "Средняя" then
            if not html then html = Config.builder.start({"Игрок", "Ш/Б/В", "Ч", "Г/П/MVP", "ГФ/ПФ/УФ", "ФТ", "М5/М10"}) end
            local c1 = sum_all_aw >= 1
            local c2 = aw.titles >= 1
            local c3, c4, c5, c6
            if tier == "Высокая" then
                c3 = g >= 40 or a >= 25 or m >= 10
                c4 = fg >= 1 or fa >= 2 or fp >= 3
                c5 = tp >= 6
                c6 = t5 >= 1 or t10 >= 3
            else
                c3 = g >= 20 or a >= 15 or m >= 5
                c4 = fg >= 1 or fa >= 2 or fp >= 3
                c5 = tp >= 4
                c6 = t5 >= 1 or t10 >= 2
            end
            local str_awards = all_spheres .. " / " .. all_shoes .. " / " .. goalies
            Config.builder.row(html, {
                "'''[[" .. p.name .. "]]'''",
                cell(str_awards, c1), cell(aw.titles, c2),
                cell(g .. " / " .. a .. " / " .. m, c3), cell(fg .. " / " .. fa .. " / " .. fp, c4),
                cell(tp, c5), cell(t5 .. " / " .. t10, c6)
            })
 
        elseif tier == "Ниже среднего" then
            if not html then html = Config.builder.start({"Игрок", "Г", "Ч/Ф", "ФТ", "MVP", "П", "ГФ/ПФ", "М10"}) end
            local cg_m, cg_s = g >= 10, g >= 5
            local ccf_m, ccf_s = (aw.titles >= 1 or fp >= 2), fp >= 1
            local cft_m, cft_s = tp >= 3, tp >= 2
            local cm_m, cm_s = m >= 3, m >= 2
            local cp_m, cp_s = a >= 8, a >= 4
            local cgf_m = fg >= 1 or fa >= 1
            local ct10_m = t10 >= 1
            Config.builder.row(html, {
                "'''[[" .. p.name .. "]]'''",
                cell(g, cg_m, cg_s and not cg_m), cell(aw.titles .. " / " .. fp, ccf_m, ccf_s and not ccf_m),
                cell(tp, cft_m, cft_s and not cft_m), cell(m, cm_m, cm_s and not cm_m),
                cell(a, cp_m, cp_s and not cp_m), cell(fg .. " / " .. fa, cgf_m), cell(t10, ct10_m)
            })
 
        elseif tier == "Низкая" then
            if not html then html = Config.builder.start({"Игрок", "Г", "Ф", "ФТ", "MVP", "П", "М", "О.случай"}) end
            local cg = g >= 1; local cf = fp >= 1; local cft = tp >= 3
            local cmvp = m >= 1; local cp = a >= 2; local cm = p.matches_total >= 10
            local sp = SPECIAL_CASES[p.name]
            local csp = sp ~= nil
            Config.builder.row(html, {
                "'''[[" .. p.name .. "]]'''",
                cell(g, cg), cell(fp, cf), cell(tp, cft),
                cell(m, cmvp), cell(a, cp), cell(p.matches_total, cm),
                cell(sp or "", csp)
            })
        end
    end
    return html and tostring(html) or ""
end


    local aw = p_stats.awards
-- (Тут идёт таблица TEXT_BLOCKS и ORDER без изменений)
     local sum_awards = aw.other_spheres + aw.golden_boots + aw.other_boots + aw.best_goalies
local TEXT_BLOCKS = {
    local any_award_exist = (sum_awards > 0) or (aw.golden_spheres > 0)
     ["Максимальная"] = [=[== Максимальная значимость ==


    log_cat("ДОСЬЕ: " .. p_stats.name)
Критерии:
    log_item("Турниров: " .. p_stats.tournaments_played .. " | Матчей: " .. p_stats.matches_total .. " | Финалов: " .. aw.finals_played)
# Минимум один [[Золотой Шар]].
    log_item("Голы: " .. p_stats.goals.total .. " (в финалах: " .. p_stats.megarating.final_goals .. ")")
# Минимум два титула чемпиона третьего мира или одно [[суперчемпион]]ство.
    log_item("Ассисты: " .. p_stats.assists.total .. " (в финалах: " .. p_stats.megarating.final_assists .. ")")
# [[Голы|Забито]] не менее 75 голов, [[Передачи|отдано]] не менее 50 подтверждённых голевых передач или не менее 20 признаний [[Список лучших игроков всех матчей ЧТМ|игроком матча]].
    log_item("MVP: " .. p_stats.mvp.is_mvp)
# Забито хотя бы два гола в финале, отданы хотя бы три голевые передачи в финале или принято участие минимум в четырёх финалах.
    log_item("Титулы: " .. aw.titles .. " | Суперчемпионства: " .. aw.superchamps)
# Минимум четыре любых [[Золотой Шар|Шара]] (кроме Золотого), любых [[Золотой Башмак|Башмака]] или титула [[Приз имени Эльнура|лучшего вратаря]] (все призы суммируются).
    log_item("Золотых шаров: " .. aw.golden_spheres .. " | Других призов (для суммы): " .. sum_awards)
# Минимум два вхождения в пятёрку [[мегарейтинг]]а или четыре — в десятку.
    log_item("В топ-5: " .. p_stats.top5 .. " | В топ-10: " .. p_stats.top10)
Для получения максимальной значимости необходимо удовлетворять минимум четырём критериям из шести, при этом '''наличие Золотого Шара является обязательным'''.]=],


     -- 1. МАКСИМАЛЬНАЯ
     ["Высокая"] = [=[== Высокая значимость ==
    log_cat("Проверка: Максимальная")
Критерии:
    local m_c1 = (aw.golden_spheres >= 1); log_item(mark(m_c1) .. " 1. Обязательно: Минимум один Золотой Шар")
# Минимум один любой [[Золотой Шар|Шар]], любой [[Золотой Башмак|Башмак]] или титул [[Приз имени Эльнура|лучшего вратаря]].
    local m_c2 = (aw.titles >= 2 or aw.superchamps >= 1); log_item(mark(m_c2) .. " 2. Минимум два титула или одно суперчемпионство")
# Завоёван хотя бы один титул чемпиона третьего мира.
    local m_c3 = (p_stats.goals.total >= 75 or p_stats.assists.total >= 50 or p_stats.mvp.is_mvp >= 20); log_item(mark(m_c3) .. " 3. Голы >= 75 ИЛИ ассисты >= 50 ИЛИ MVP >= 20")
# [[Голы|Забито]] не менее 40 голов, [[Передачи|отдано]] не менее 25 подтверждённых голевых передач или не менее 10 признаний [[Список лучших игроков всех матчей ЧТМ|игроком матча]].
    local m_c4 = (p_stats.megarating.final_goals >= 2 or p_stats.megarating.final_assists >= 3 or aw.finals_played >= 4); log_item(mark(m_c4) .. " 4. В финале: голы >= 2 ИЛИ ассисты >= 3 ИЛИ сыграно финалов >= 4")
# Забит хотя бы один гол в финале, отданы хотя бы две голевые передачи в финале или принято участие минимум в трёх финалах.
    local m_c5 = (sum_awards >= 4); log_item(mark(m_c5) .. " 5. Минимум 4 любых Шара (кр. золотого), Башмака или Вратаря")
# Участие минимум в шести [[Список участий в финальных турнирах|финальных турнирах ЧТМ]].
    local m_c6 = (p_stats.top5 >= 2 or p_stats.top10 >= 4); log_item(mark(m_c6) .. " 6. Мегарейтинг: топ-5 >= 2 ИЛИ топ-10 >= 4")
# Минимум одно вхождение в пятёрку [[мегарейтинг]]а или три — в десятку.
    local m_score = (m_c1 and 1 or 0) + (m_c2 and 1 or 0) + (m_c3 and 1 or 0) + (m_c4 and 1 or 0) + (m_c5 and 1 or 0) + (m_c6 and 1 or 0)
Для получения высокой значимости необходимо удовлетворять минимум четырём критериям из шести.]=],
    log_item("Итого критериев: " .. m_score .. "/6")
    if m_c1 and m_score >= 4 then return "Максимальная", table.concat(logs, "\n") end


     -- 2. ВЫСОКАЯ
     ["Средняя"] = [=[== Средняя значимость ==
    log_cat("Проверка: Высокая")
Критерии:
    local h_c1 = any_award_exist; log_item(mark(h_c1) .. " 1. Минимум один любой Шар, Башмак или титул лучшего вратаря")
# Минимум один любой [[Золотой Шар|Шар]], любой [[Золотой Башмак|Башмак]] или титул [[Приз имени Эльнура|лучшего вратаря]].
    local h_c2 = (aw.titles >= 1); log_item(mark(h_c2) .. " 2. Завоёван хотя бы один титул")
# Завоёван хотя бы один титул чемпиона третьего мира.
    local h_c3 = (p_stats.goals.total >= 40 or p_stats.assists.total >= 25 or p_stats.mvp.is_mvp >= 10); log_item(mark(h_c3) .. " 3. Голы >= 40 ИЛИ ассисты >= 25 ИЛИ MVP >= 10")
# [[Голы|Забито]] не менее 20 голов, [[Передачи|отдано]] не менее 15 подтверждённых голевых передач или не менее 5 признаний [[Список лучших игроков всех матчей ЧТМ|игроком матча]].
    local h_c4 = (p_stats.megarating.final_goals >= 1 or p_stats.megarating.final_assists >= 2 or aw.finals_played >= 3); log_item(mark(h_c4) .. " 4. В финале: голы >= 1 ИЛИ ассисты >= 2 ИЛИ сыграно финалов >= 3")
# Забит хотя бы один гол в финале, отданы хотя бы две голевые передачи в финале или принято участие минимум в трёх финалах.
    local h_c5 = (p_stats.tournaments_played >= 6); log_item(mark(h_c5) .. " 5. Участие минимум в 6 турнирах")
# Участие минимум в четырёх [[Список участий в финальных турнирах|финальных турнирах ЧТМ]].
    local h_c6 = (p_stats.top5 >= 1 or p_stats.top10 >= 3); log_item(mark(h_c6) .. " 6. Мегарейтинг: топ-5 >= 1 ИЛИ топ-10 >= 3")
# Минимум одно вхождение в пятёрку [[мегарейтинг]]а или два — в десятку.
    local h_score = (h_c1 and 1 or 0) + (h_c2 and 1 or 0) + (h_c3 and 1 or 0) + (h_c4 and 1 or 0) + (h_c5 and 1 or 0) + (h_c6 and 1 or 0)
Для получения средней значимости необходимо удовлетворять минимум минимум двум критериям из шести.]=],
    log_item("Итого критериев: " .. h_score .. "/6")
    if h_score >= 4 then return "Высокая", table.concat(logs, "\n") end


     -- 3. СРЕДНЯЯ
     ["Ниже среднего"] = [=[== Ниже среднего ==
    log_cat("Проверка: Средняя")
Критерии:
    local a_c1 = any_award_exist; log_item(mark(a_c1) .. " 1. Минимум один любой Шар, Башмак или титул лучшего вратаря")
# [[Голы|Забито]] не менее 10 (основной показатель) или 5 (дополнительный) голов.
    local a_c2 = (aw.titles >= 1); log_item(mark(a_c2) .. " 2. Завоёван хотя бы один титул")
# Завоёван хотя бы один титул чемпиона третьего мира или участие минимум в двух (основной) или одном (дополнительный) финале.
    local a_c3 = (p_stats.goals.total >= 20 or p_stats.assists.total >= 15 or p_stats.mvp.is_mvp >= 5); log_item(mark(a_c3) .. " 3. Голы >= 20 ИЛИ ассисты >= 15 ИЛИ MVP >= 5")
# Участие минимум в трёх (основной) или двух (дополнительный) финальных турнирах ЧТМ.
    local a_c4 = (p_stats.megarating.final_goals >= 1 or p_stats.megarating.final_assists >= 2 or aw.finals_played >= 3); log_item(mark(a_c4) .. " 4. В финале: голы >= 1 ИЛИ ассисты >= 2 ИЛИ сыграно финалов >= 3")
# Признание [[Список лучших игроков всех матчей ЧТМ|игроком матча]] не менее трёх (основной показатель) или двух (дополнительный) раз.
    local a_c5 = (p_stats.tournaments_played >= 4); log_item(mark(a_c5) .. " 5. Участие минимум в 4 турнирах")
# [[Передачи|Отдано]] не менее 8 (основной показатель) или 4 (дополнительный) подтверждённых голевых передач.
    local a_c6 = (p_stats.top5 >= 1 or p_stats.top10 >= 2); log_item(mark(a_c6) .. " 6. Мегарейтинг: топ-5 >= 1 ИЛИ топ-10 >= 2")
# Забит хотя бы один гол или отдана хотя бы одна голевая передача в финале (основной показатель).
    local a_score = (a_c1 and 1 or 0) + (a_c2 and 1 or 0) + (a_c3 and 1 or 0) + (a_c4 and 1 or 0) + (a_c5 and 1 or 0) + (a_c6 and 1 or 0)
# Минимум одно вхождение в десятку [[мегарейтинг]]а.
    log_item("Итого критериев: " .. a_score .. "/6")
Необходимо соответствовать хотя бы одному из критериев в первом случае и хотя бы двум во втором.]=],
    if a_score >= 2 then return "Средняя", table.concat(logs, "\n") end


     -- 4. НИЖЕ СРЕДНЕГО
     ["Низкая"] = [=[== Низкая ==
    log_cat("Проверка: Ниже среднего")
Критерии:
    local b_m1 = (p_stats.goals.total >= 10); local b_s1 = (p_stats.goals.total >= 5); log_item("1. Голы: " .. mark(b_m1) .. " осн (>=10) | " .. mark(b_s1) .. " доп (>=5)")
# [[Голы|Забит]] хотя бы один гол.
    local b_m2 = (aw.titles >= 1 or aw.finals_played >= 2); local b_s2 = (aw.finals_played >= 1); log_item("2. Титул или Финалы: " .. mark(b_m2) .. " осн (титул/финалы>=2) | " .. mark(b_s2) .. " доп (финалы>=1)")
# Участие минимум в одном финале.
    local b_m3 = (p_stats.tournaments_played >= 3); local b_s3 = (p_stats.tournaments_played >= 2); log_item("3. Турниры: " .. mark(b_m3) .. " осн (>=3) | " .. mark(b_s3) .. " доп (>=2)")
# Участие минимум в трёх финальных турнирах ЧТМ.
    local b_m4 = (p_stats.mvp.is_mvp >= 3); local b_s4 = (p_stats.mvp.is_mvp >= 2); log_item("4. MVP: " .. mark(b_m4) .. " осн (>=3) | " .. mark(b_s4) .. " доп (>=2)")
# Признание [[Список лучших игроков всех матчей ЧТМ|игроком матча]] хотя бы один раз.
    local b_m5 = (p_stats.assists.total >= 8); local b_s5 = (p_stats.assists.total >= 4); log_item("5. Ассисты: " .. mark(b_m5) .. " осн (>=8) | " .. mark(b_s5) .. " доп (>=4)")
# [[Передачи|Отданы]] хотя бы две подтверждённые голевые передачи.
    local b_m6 = (p_stats.megarating.final_goals >= 1 or p_stats.megarating.final_assists >= 1); log_item("6. В финале гол или пас: " .. mark(b_m6) .. " осн")
# [[Матчи|Сыграно]] не менее 10 подтверждённых матчей.
    local b_m7 = (p_stats.top10 >= 1); log_item("7. Мегарейтинг Топ-10: " .. mark(b_m7) .. " осн")
Необходимо соответствовать хотя бы одному из критериев. В указанных дополнительно особых случаях возможно присвоение этого уровня случайным игрокам, хоть чем-то запомнившимся.]=],
    local main_score = (b_m1 and 1 or 0) + (b_m2 and 1 or 0) + (b_m3 and 1 or 0) + (b_m4 and 1 or 0) + (b_m5 and 1 or 0) + (b_m6 and 1 or 0) + (b_m7 and 1 or 0)
    local sub_score = (b_s1 and 1 or 0) + (b_s2 and 1 or 0) + (b_s3 and 1 or 0) + (b_s4 and 1 or 0) + (b_s5 and 1 or 0)
    log_item("Итого: Основных: " .. main_score .. ", Дополнительных: " .. sub_score)
    if main_score >= 1 or sub_score >= 2 then return "Ниже среднего", table.concat(logs, "\n") end


     -- 5. НИЗКАЯ
     ["Случайный прохожий"] = [=[== Случайный прохожий ==
    log_cat("Проверка: Низкая")
Случайные люди, приходившие играть один-два раза в проходных матчах и абсолютно ничем не запомнившиеся.]=]
    local l_c1 = (p_stats.goals.total >= 1); log_item(mark(l_c1) .. " 1. Забит хотя бы 1 гол")
}
    local l_c2 = (aw.finals_played >= 1); log_item(mark(l_c2) .. " 2. Участие в финале")
    local l_c3 = (p_stats.tournaments_played >= 3); log_item(mark(l_c3) .. " 3. Участие в 3 турнирах")
    local l_c4 = (p_stats.mvp.is_mvp >= 1); log_item(mark(l_c4) .. " 4. Признание MVP")
    local l_c5 = (p_stats.assists.total >= 2); log_item(mark(l_c5) .. " 5. Ассисты >= 2")
    local l_c6 = (p_stats.matches_total >= 10); log_item(mark(l_c6) .. " 6. Сыграно >= 10 матчей")
    local l_score = (l_c1 and 1 or 0) + (l_c2 and 1 or 0) + (l_c3 and 1 or 0) + (l_c4 and 1 or 0) + (l_c5 and 1 or 0) + (l_c6 and 1 or 0)
    log_item("Итого критериев: " .. l_score)
    if l_score >= 1 then return "Низкая", table.concat(logs, "\n") end


    -- 6. СЛУЧАЙНЫЙ ПРОХОЖИЙ
local ORDER = {"Максимальная", "Высокая", "Средняя", "Ниже среднего", "Низкая", "Случайный прохожий"}
    log_cat("Проверка: Случайный прохожий")
    log_item("Не выполнил ни одного критерия низкого уровня.")
    return "Случайный прохожий", table.concat(logs, "\n")
end


-- ==========================================
function Significance.drawAll(frame)
-- ОТЛАДОЧНЫЙ ВЫВОД
-- ==========================================
function Significance.test_player(frame)
    local target_player = frame.args.player or "Диман"
   
     local db = build_master_database()
     local db = build_master_database()
     local p_stats = db[target_player]
     local bins = { ["Максимальная"]={}, ["Высокая"]={}, ["Средняя"]={}, ["Ниже среднего"]={}, ["Низкая"]={}, ["Случайный прохожий"]={} }
 
    for _, p_stats in pairs(db) do
        -- ИСПОЛЬЗУЕМ СОБСТВЕННЫЙ API
        local level = Significance.evaluatePlayer(p_stats)
        table.insert(bins[level], p_stats)
    end
      
      
     if not p_stats then return "Игрок '" .. target_player .. "' не найден в БД." end
     for _, list in pairs(bins) do table.sort(list, function(a, b) return a.name < b.name end) end
      
 
     local level, log_text = Significance.evaluate_player(p_stats)
     local out = {}
   
     for _, tier in ipairs(ORDER) do
    local result = "== Результат оценки: " .. target_player .. " ==\n"
        local list = bins[tier]
    result = result .. "'''Присвоенный уровень: " .. level .. "'''\n\n"
        table.insert(out, TEXT_BLOCKS[tier])
    result = result .. log_text
       
      
        if tier == "Случайный прохожий" then
     return frame:preprocess(result)
            table.insert(out, "\n'''Точное число игроков неизвестно:'''")
            local links = {}
            for _, p in ipairs(list) do table.insert(links, "[[" .. p.name .. "]]") end
            table.insert(out, table.concat(links, ", ") .. ".")
        else
            table.insert(out, "\n'''" .. get_plural_players(#list) .. ":'''")
            table.insert(out, build_tier_table(tier, list))
        end
        table.insert(out, "")
     end
 
     return frame:preprocess(Config.styles.wiki_templates .. "\n" .. table.concat(out, "\n"))
end
end


return Significance
return Significance

Текущая версия от 19:46, 27 апреля 2026

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

Модуль значимости игроков. Работает как для искомой страницы, полностью её собирая, так и как чистый движок в составе других модулей.

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

{{#invoke:Significance|drawAll}}


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

-- =====================================================
-- Модуль:Significance (калькулятор значимости игроков)
-- Версия 1.0
-- =====================================================
local Significance = {}

local Config = require('Module:Config')
local StatEngine = require('Module:StatEngine')
local Megarating = require('Module:Megarating')

-- ==========================================
-- РУЧНЫЕ ИСКЛЮЧЕНИЯ (Особые случаи)
-- ==========================================
local SPECIAL_CASES = {
    ["Амид"] = "[[ЦАР-КИР2026|о.случай]]",
    ["Губа"] = "[[Финал ЧТМ-2014#Дополнительное время|о.случай]]",
    ["Другой Очкан"] = "[[ДОМ-АФГ2018#Серия пенальти|о.случай]]",
    ["Рамиз"] = "[[ДОМ-АФГ2018#Серия пенальти|о.случай]]",
}

-- =====================================================
-- API ДВИЖКА (Для использования во внешних "Монстрах")
-- =====================================================

-- 1. Выдает пустую "болванку" (схему) для нового игрока
function Significance.createPlayerStruct(name)
    return {
        name = name, 
        tournaments_played = 0, top5 = 0, top10 = 0,
        matches_total = 0, goals = {total=0}, assists = {total=0}, mvp = {is_mvp=0},
        megarating = {final_goals=0, final_assists=0},
        awards = {
            golden_spheres=0, other_spheres=0, golden_shoes=0, other_shoes=0, 
            golden_assistants=0, other_assistants=0, best_goalies=0, 
            superchamps=0, titles=0, finals_played=0
        }
    }
end

-- 2. Вливает статистику из БД одного года в общую копилку игрока
function Significance.mergeStats(target, source)
    target.matches_total = (target.matches_total or 0) + (source.matches_total or 0)
    target.goals.total = (target.goals.total or 0) + (source.goals.total or 0)
    target.assists.total = (target.assists.total or 0) + (source.assists.total or 0)
    target.mvp.is_mvp = (target.mvp.is_mvp or 0) + (source.mvp.is_mvp or 0)
    
    target.megarating.final_goals = (target.megarating.final_goals or 0) + (source.megarating.final_goals or 0)
    target.megarating.final_assists = (target.megarating.final_assists or 0) + (source.megarating.final_assists or 0)
    
    if source.awards then
        target.awards.golden_spheres = target.awards.golden_spheres + (source.awards.golden_spheres or 0)
        target.awards.other_spheres = target.awards.other_spheres + (source.awards.other_spheres or 0)
        target.awards.golden_shoes = target.awards.golden_shoes + (source.awards.golden_shoes or 0)
        target.awards.other_shoes = target.awards.other_shoes + (source.awards.other_shoes or 0)
        target.awards.golden_assistants = target.awards.golden_assistants + (source.awards.golden_assistants or 0)
        target.awards.other_assistants = target.awards.other_assistants + (source.awards.other_assistants or 0)
        target.awards.best_goalies = target.awards.best_goalies + (source.awards.best_goalies or 0)
        target.awards.superchamps = target.awards.superchamps + (source.awards.superchamps or 0)
        target.awards.titles = target.awards.titles + (source.awards.titles or 0)
        target.awards.finals_played = target.awards.finals_played + (source.awards.finals_played or 0)
    end
end

-- 3. ЧИСТЫЙ КАЛЬКУЛЯТОР. Принимает заполненную структуру, возвращает уровень значимости.
function Significance.evaluatePlayer(p_stats)
    local aw = p_stats.awards
    local sum_awards = aw.other_spheres + aw.golden_shoes + aw.other_shoes + aw.best_goalies
    local any_award_exist = (sum_awards > 0) or (aw.golden_spheres > 0)

    -- 1. МАКСИМАЛЬНАЯ
    local m_c1 = (aw.golden_spheres >= 1)
    local m_c2 = (aw.titles >= 2 or aw.superchamps >= 1)
    local m_c3 = (p_stats.goals.total >= 75 or p_stats.assists.total >= 50 or p_stats.mvp.is_mvp >= 20)
    local m_c4 = (p_stats.megarating.final_goals >= 2 or p_stats.megarating.final_assists >= 3 or aw.finals_played >= 4)
    local m_c5 = (sum_awards >= 4)
    local m_c6 = (p_stats.top5 >= 2 or p_stats.top10 >= 4)
    if m_c1 and ((m_c1 and 1 or 0) + (m_c2 and 1 or 0) + (m_c3 and 1 or 0) + (m_c4 and 1 or 0) + (m_c5 and 1 or 0) + (m_c6 and 1 or 0)) >= 4 then return "Максимальная" end

    -- 2. ВЫСОКАЯ
    local h_score = (any_award_exist and 1 or 0) + ((aw.titles >= 1) and 1 or 0) + ((p_stats.goals.total >= 40 or p_stats.assists.total >= 25 or p_stats.mvp.is_mvp >= 10) and 1 or 0) + ((p_stats.megarating.final_goals >= 1 or p_stats.megarating.final_assists >= 2 or aw.finals_played >= 3) and 1 or 0) + ((p_stats.tournaments_played >= 6) and 1 or 0) + ((p_stats.top5 >= 1 or p_stats.top10 >= 3) and 1 or 0)
    if h_score >= 4 then return "Высокая" end

    -- 3. СРЕДНЯЯ
    local a_score = (any_award_exist and 1 or 0) + ((aw.titles >= 1) and 1 or 0) + ((p_stats.goals.total >= 20 or p_stats.assists.total >= 15 or p_stats.mvp.is_mvp >= 5) and 1 or 0) + ((p_stats.megarating.final_goals >= 1 or p_stats.megarating.final_assists >= 2 or aw.finals_played >= 3) and 1 or 0) + ((p_stats.tournaments_played >= 4) and 1 or 0) + ((p_stats.top5 >= 1 or p_stats.top10 >= 2) and 1 or 0)
    if a_score >= 2 then return "Средняя" end

    -- 4. НИЖЕ СРЕДНЕГО
    local main_score = ((p_stats.goals.total >= 10) and 1 or 0) + ((aw.titles >= 1 or aw.finals_played >= 2) and 1 or 0) + ((p_stats.tournaments_played >= 3) and 1 or 0) + ((p_stats.mvp.is_mvp >= 3) and 1 or 0) + ((p_stats.assists.total >= 8) and 1 or 0) + ((p_stats.megarating.final_goals >= 1 or p_stats.megarating.final_assists >= 1) and 1 or 0) + ((p_stats.top10 >= 1) and 1 or 0)
    local sub_score = ((p_stats.goals.total >= 5) and 1 or 0) + ((aw.finals_played >= 1) and 1 or 0) + ((p_stats.tournaments_played >= 2) and 1 or 0) + ((p_stats.mvp.is_mvp >= 2) and 1 or 0) + ((p_stats.assists.total >= 4) and 1 or 0)
    if main_score >= 1 or sub_score >= 2 then return "Ниже среднего" end

    -- 5. НИЗКАЯ
    local l_score = ((p_stats.goals.total >= 1) and 1 or 0) + ((aw.finals_played >= 1) and 1 or 0) + ((p_stats.tournaments_played >= 3) and 1 or 0) + ((p_stats.mvp.is_mvp >= 1) and 1 or 0) + ((p_stats.assists.total >= 2) and 1 or 0) + ((p_stats.matches_total >= 10) and 1 or 0)
    if l_score >= 1 or SPECIAL_CASES[p_stats.name] then return "Низкая" end

    return "Случайный прохожий"
end


-- =====================================================
-- ВНУТРЕННИЙ ФУНКЦИОНАЛ ДЛЯ ОТРИСОВКИ СТРАНИЦЫ
-- =====================================================

local function get_plural_players(count)
    local d10 = count % 10
    local d100 = count % 100
    if d10 == 1 and d100 ~= 11 then return count .. " игрок"
    elseif d10 >= 2 and d10 <= 4 and (d100 < 10 or d100 >= 20) then return count .. " игрока"
    else return count .. " игроков" end
end

local function cell(text, is_main, is_sub)
    local bg = ""
    if is_main then bg = Config.styles.lightgreen
    elseif is_sub then bg = Config.styles.palegoldenrod end
    return { text = tostring(text), style = Config.styles.center_nowrap .. bg }
end

local _grand_cache = nil

local function build_master_database()
    if _grand_cache then return _grand_cache end
    local GrandStats = {}
    local latest_year = Config.years[#Config.years]
    local is_latest_finished = Config.is_latest_finished

    for _, year in ipairs(Config.years) do
        local is_finished = (year ~= latest_year) or is_latest_finished
        local success, year_db = pcall(require, 'Module:Data/' .. year)
        
        if success and type(year_db) == "table" then
            local year_stats = StatEngine.Harvester.run(year_db, {need_players = true})
            for p_name, p_data in pairs(year_stats.Players) do
                if not GrandStats[p_name] then
                    -- ИСПОЛЬЗУЕМ СОБСТВЕННЫЙ API
                    GrandStats[p_name] = Significance.createPlayerStruct(p_name)
                end
                GrandStats[p_name].tournaments_played = GrandStats[p_name].tournaments_played + 1
                -- ИСПОЛЬЗУЕМ СОБСТВЕННЫЙ API
                Significance.mergeStats(GrandStats[p_name], p_data)
            end
            
            if is_finished then
                local mr_list = Megarating.evaluate_raw_stats(year, year_db, year_stats.Players)
                local spheres = Megarating.get_spheres_from_db(year_db)
                if #mr_list > 0 then
                    table.sort(mr_list, function(a, b) return Megarating.compare_players_public(a, b, year, spheres) end)
                    local current_rank = 1
                    for i, p in ipairs(mr_list) do
                        if i > 1 and p.total_points ~= mr_list[i-1].total_points then current_rank = i end
                        if current_rank <= 10 then
                            if GrandStats[p.name] then
                                GrandStats[p.name].top10 = GrandStats[p.name].top10 + 1
                                if current_rank <= 5 then GrandStats[p.name].top5 = GrandStats[p.name].top5 + 1 end
                            end
                        else break end
                    end
                end
            end
        end
    end
    _grand_cache = GrandStats
    return _grand_cache
end

-- (Тут идёт функция build_tier_table без изменений)
local function build_tier_table(tier, list)
    if #list == 0 then return "" end
    local html

    for _, p in ipairs(list) do
        local aw = p.awards
        local g = p.goals.total
        local a = p.assists.total
        local m = p.mvp.is_mvp
        local fg = p.megarating.final_goals
        local fa = p.megarating.final_assists
        local fp = aw.finals_played
        local tp = p.tournaments_played
        local t5 = p.top5
        local t10 = p.top10
        
        -- Группировка наград для вывода
        local all_shoes = aw.golden_shoes + aw.other_shoes
        local all_spheres = aw.golden_spheres + aw.other_spheres
        local other_spheres = aw.other_spheres
        local goalies = aw.best_goalies
        
        local sum_aw = other_spheres + all_shoes + goalies
        local sum_all_aw = all_spheres + all_shoes + goalies
        
        if tier == "Максимальная" then
            if not html then html = Config.builder.start({"Игрок", "ЗШ", "Ч/СЧ", "Г/П/MVP", "ГФ/ПФ/УФ", "Ш/Б/В", "М5/М10"}) end
            local c1 = aw.golden_spheres >= 1
            local c2 = aw.titles >= 2 or aw.superchamps >= 1
            local c3 = g >= 75 or a >= 50 or m >= 20
            local c4 = fg >= 2 or fa >= 3 or fp >= 4
            local c5 = sum_aw >= 4
            local str_awards = other_spheres .. " / " .. all_shoes .. " / " .. goalies
            local c6 = t5 >= 2 or t10 >= 4
            Config.builder.row(html, {
                "'''[[" .. p.name .. "]]'''",
                cell(aw.golden_spheres, c1), cell(aw.titles .. " / " .. aw.superchamps, c2),
                cell(g .. " / " .. a .. " / " .. m, c3), cell(fg .. " / " .. fa .. " / " .. fp, c4),
                cell(str_awards, c5), cell(t5 .. " / " .. t10, c6)
            })

        elseif tier == "Высокая" or tier == "Средняя" then
            if not html then html = Config.builder.start({"Игрок", "Ш/Б/В", "Ч", "Г/П/MVP", "ГФ/ПФ/УФ", "ФТ", "М5/М10"}) end
            local c1 = sum_all_aw >= 1
            local c2 = aw.titles >= 1
            local c3, c4, c5, c6
            if tier == "Высокая" then
                c3 = g >= 40 or a >= 25 or m >= 10
                c4 = fg >= 1 or fa >= 2 or fp >= 3
                c5 = tp >= 6
                c6 = t5 >= 1 or t10 >= 3
            else
                c3 = g >= 20 or a >= 15 or m >= 5
                c4 = fg >= 1 or fa >= 2 or fp >= 3
                c5 = tp >= 4
                c6 = t5 >= 1 or t10 >= 2
            end
            local str_awards = all_spheres .. " / " .. all_shoes .. " / " .. goalies
            Config.builder.row(html, {
                "'''[[" .. p.name .. "]]'''",
                cell(str_awards, c1), cell(aw.titles, c2),
                cell(g .. " / " .. a .. " / " .. m, c3), cell(fg .. " / " .. fa .. " / " .. fp, c4),
                cell(tp, c5), cell(t5 .. " / " .. t10, c6)
            })

        elseif tier == "Ниже среднего" then
            if not html then html = Config.builder.start({"Игрок", "Г", "Ч/Ф", "ФТ", "MVP", "П", "ГФ/ПФ", "М10"}) end
            local cg_m, cg_s = g >= 10, g >= 5
            local ccf_m, ccf_s = (aw.titles >= 1 or fp >= 2), fp >= 1
            local cft_m, cft_s = tp >= 3, tp >= 2
            local cm_m, cm_s = m >= 3, m >= 2
            local cp_m, cp_s = a >= 8, a >= 4
            local cgf_m = fg >= 1 or fa >= 1
            local ct10_m = t10 >= 1
            Config.builder.row(html, {
                "'''[[" .. p.name .. "]]'''",
                cell(g, cg_m, cg_s and not cg_m), cell(aw.titles .. " / " .. fp, ccf_m, ccf_s and not ccf_m),
                cell(tp, cft_m, cft_s and not cft_m), cell(m, cm_m, cm_s and not cm_m),
                cell(a, cp_m, cp_s and not cp_m), cell(fg .. " / " .. fa, cgf_m), cell(t10, ct10_m)
            })

        elseif tier == "Низкая" then
            if not html then html = Config.builder.start({"Игрок", "Г", "Ф", "ФТ", "MVP", "П", "М", "О.случай"}) end
            local cg = g >= 1; local cf = fp >= 1; local cft = tp >= 3
            local cmvp = m >= 1; local cp = a >= 2; local cm = p.matches_total >= 10
            local sp = SPECIAL_CASES[p.name]
            local csp = sp ~= nil
            Config.builder.row(html, {
                "'''[[" .. p.name .. "]]'''",
                cell(g, cg), cell(fp, cf), cell(tp, cft),
                cell(m, cmvp), cell(a, cp), cell(p.matches_total, cm),
                cell(sp or "", csp)
            })
        end
    end
    return html and tostring(html) or ""
end

-- (Тут идёт таблица TEXT_BLOCKS и ORDER без изменений)
local TEXT_BLOCKS = {
    ["Максимальная"] = [=[== Максимальная значимость ==

Критерии:
# Минимум один [[Золотой Шар]].
# Минимум два титула чемпиона третьего мира или одно [[суперчемпион]]ство.
# [[Голы|Забито]] не менее 75 голов, [[Передачи|отдано]] не менее 50 подтверждённых голевых передач или не менее 20 признаний [[Список лучших игроков всех матчей ЧТМ|игроком матча]].
# Забито хотя бы два гола в финале, отданы хотя бы три голевые передачи в финале или принято участие минимум в четырёх финалах.
# Минимум четыре любых [[Золотой Шар|Шара]] (кроме Золотого), любых [[Золотой Башмак|Башмака]] или титула [[Приз имени Эльнура|лучшего вратаря]] (все призы суммируются).
# Минимум два вхождения в пятёрку [[мегарейтинг]]а или четыре — в десятку.
Для получения максимальной значимости необходимо удовлетворять минимум четырём критериям из шести, при этом '''наличие Золотого Шара является обязательным'''.]=],

    ["Высокая"] = [=[== Высокая значимость ==
Критерии:
# Минимум один любой [[Золотой Шар|Шар]], любой [[Золотой Башмак|Башмак]] или титул [[Приз имени Эльнура|лучшего вратаря]].
# Завоёван хотя бы один титул чемпиона третьего мира.
# [[Голы|Забито]] не менее 40 голов, [[Передачи|отдано]] не менее 25 подтверждённых голевых передач или не менее 10 признаний [[Список лучших игроков всех матчей ЧТМ|игроком матча]].
# Забит хотя бы один гол в финале, отданы хотя бы две голевые передачи в финале или принято участие минимум в трёх финалах.
# Участие минимум в шести [[Список участий в финальных турнирах|финальных турнирах ЧТМ]].
# Минимум одно вхождение в пятёрку [[мегарейтинг]]а или три — в десятку.
Для получения высокой значимости необходимо удовлетворять минимум четырём критериям из шести.]=],

    ["Средняя"] = [=[== Средняя значимость ==
Критерии:
# Минимум один любой [[Золотой Шар|Шар]], любой [[Золотой Башмак|Башмак]] или титул [[Приз имени Эльнура|лучшего вратаря]].
# Завоёван хотя бы один титул чемпиона третьего мира.
# [[Голы|Забито]] не менее 20 голов, [[Передачи|отдано]] не менее 15 подтверждённых голевых передач или не менее 5 признаний [[Список лучших игроков всех матчей ЧТМ|игроком матча]].
# Забит хотя бы один гол в финале, отданы хотя бы две голевые передачи в финале или принято участие минимум в трёх финалах.
# Участие минимум в четырёх [[Список участий в финальных турнирах|финальных турнирах ЧТМ]].
# Минимум одно вхождение в пятёрку [[мегарейтинг]]а или два — в десятку.
Для получения средней значимости необходимо удовлетворять минимум минимум двум критериям из шести.]=],

    ["Ниже среднего"] = [=[== Ниже среднего ==
Критерии:
# [[Голы|Забито]] не менее 10 (основной показатель) или 5 (дополнительный) голов.
# Завоёван хотя бы один титул чемпиона третьего мира или участие минимум в двух (основной) или одном (дополнительный) финале.
# Участие минимум в трёх (основной) или двух (дополнительный) финальных турнирах ЧТМ.
# Признание [[Список лучших игроков всех матчей ЧТМ|игроком матча]] не менее трёх (основной показатель) или двух (дополнительный) раз.
# [[Передачи|Отдано]] не менее 8 (основной показатель) или 4 (дополнительный) подтверждённых голевых передач.
# Забит хотя бы один гол или отдана хотя бы одна голевая передача в финале (основной показатель).
# Минимум одно вхождение в десятку [[мегарейтинг]]а.
Необходимо соответствовать хотя бы одному из критериев в первом случае и хотя бы двум во втором.]=],

    ["Низкая"] = [=[== Низкая ==
Критерии:
# [[Голы|Забит]] хотя бы один гол.
# Участие минимум в одном финале.
# Участие минимум в трёх финальных турнирах ЧТМ.
# Признание [[Список лучших игроков всех матчей ЧТМ|игроком матча]] хотя бы один раз.
# [[Передачи|Отданы]] хотя бы две подтверждённые голевые передачи.
# [[Матчи|Сыграно]] не менее 10 подтверждённых матчей.
Необходимо соответствовать хотя бы одному из критериев. В указанных дополнительно особых случаях возможно присвоение этого уровня случайным игрокам, хоть чем-то запомнившимся.]=],

    ["Случайный прохожий"] = [=[== Случайный прохожий ==
Случайные люди, приходившие играть один-два раза в проходных матчах и абсолютно ничем не запомнившиеся.]=]
}

local ORDER = {"Максимальная", "Высокая", "Средняя", "Ниже среднего", "Низкая", "Случайный прохожий"}

function Significance.drawAll(frame)
    local db = build_master_database()
    local bins = { ["Максимальная"]={}, ["Высокая"]={}, ["Средняя"]={}, ["Ниже среднего"]={}, ["Низкая"]={}, ["Случайный прохожий"]={} }

    for _, p_stats in pairs(db) do
        -- ИСПОЛЬЗУЕМ СОБСТВЕННЫЙ API
        local level = Significance.evaluatePlayer(p_stats)
        table.insert(bins[level], p_stats)
    end
    
    for _, list in pairs(bins) do table.sort(list, function(a, b) return a.name < b.name end) end

    local out = {}
    for _, tier in ipairs(ORDER) do
        local list = bins[tier]
        table.insert(out, TEXT_BLOCKS[tier])
        
        if tier == "Случайный прохожий" then
            table.insert(out, "\n'''Точное число игроков неизвестно:'''")
            local links = {}
            for _, p in ipairs(list) do table.insert(links, "[[" .. p.name .. "]]") end
            table.insert(out, table.concat(links, ", ") .. ".")
        else
            table.insert(out, "\n'''" .. get_plural_players(#list) .. ":'''")
            table.insert(out, build_tier_table(tier, list))
        end
        table.insert(out, "")
    end

    return frame:preprocess(Config.styles.wiki_templates .. "\n" .. table.concat(out, "\n"))
end

return Significance