Модуль:Significance

Материал из ЧТМ
Перейти к навигации Перейти к поиску
Документация Документация

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

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

{{#invoke:Significance|drawAll}}


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

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

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

-- Вспомогательная функция (Галочки)
local function mark(condition)
    return condition and '<span style="color:green;">✅ Да</span>' or '<span style="color:red;">❌ Нет</span>'
end

-- Утилита для слияния статов
local function merge_stats(target, source)
    -- Эта функция дублирует логику слияния из Harvester, 
    -- чтобы собирать ГрандСтатс из кусочков годов.
    -- Упрощенный вариант только для того, что нам нужно для Значимости
    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
        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
        target.awards.other_spheres = target.awards.other_spheres + source.awards.other_spheres
        target.awards.golden_boots = target.awards.golden_boots + source.awards.golden_boots
        target.awards.other_boots = target.awards.other_boots + source.awards.other_boots
        target.awards.golden_assistants = target.awards.golden_assistants + source.awards.golden_assistants
        target.awards.other_assistants = target.awards.other_assistants + source.awards.other_assistants
        target.awards.best_goalies = target.awards.best_goalies + source.awards.best_goalies
        target.awards.superchamps = target.awards.superchamps + source.awards.superchamps
        target.awards.titles = target.awards.titles + source.awards.titles
        target.awards.finals_played = target.awards.finals_played + source.awards.finals_played
    end
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
            -- 1. ЗАПУСКАЕМ КОМБАЙН (ОДИН РАЗ!)
            local year_stats = StatEngine.Harvester.run(year_db, {need_players = true})
            
            -- 2. СЛИВАЕМ В ОБЩИЙ КОТЕЛ ИГРОКА
            for p_name, p_data in pairs(year_stats.Players) do
                if not GrandStats[p_name] then
                    GrandStats[p_name] = {
                        name = p_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_boots=0, other_boots=0, golden_assistants=0, other_assistants=0, best_goalies=0, superchamps=0, titles=0, finals_played=0}
                    }
                end
                GrandStats[p_name].tournaments_played = GrandStats[p_name].tournaments_played + 1
                merge_stats(GrandStats[p_name], p_data)
            end
            
            -- 3. ЗАПУСКАЕМ ДВИЖОК МЕГАРЕЙТИНГА И СРАЗУ ЗАБИРАЕМ ТОП-10
            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 then
                            -- Проверяем на идеальное равенство тайбрейкера, чтобы не давать 6-е место тому, кто делит 5-е
                            if p.total_points ~= mr_list[i-1].total_points then current_rank = i end
                        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 -- Дальше Топ-10 нам для Значимости не нужно
                        end
                    end
                end
            end
        end
    end
    
    _grand_cache = GrandStats
    return _grand_cache
end

-- ==========================================
-- ОЦЕНКА ОДНОГО ИГРОКА ИЗ СОБРАННОЙ БАЗЫ
-- ==========================================
function Significance.evaluate_player(p_stats)
    local logs = {}
    local function log_cat(title) table.insert(logs, "\n=== " .. title .. " ===") end
    local function log_item(text) table.insert(logs, text) end

    local aw = p_stats.awards
    local sum_awards = aw.other_spheres + aw.golden_boots + aw.other_boots + aw.best_goalies
    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 .. ")")
    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")
    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")
    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. Минимум один любой Шар, Башмак или титул лучшего вратаря")
    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 турнирах")
    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) .. " осн")
    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. СЛУЧАЙНЫЙ ПРОХОЖИЙ
    log_cat("Проверка: Случайный прохожий")
    log_item("Не выполнил ни одного критерия низкого уровня.")
    return "Случайный прохожий", table.concat(logs, "\n")
end

-- ==========================================
-- ОТЛАДОЧНЫЙ ВЫВОД
-- ==========================================
function Significance.test_player(frame)
    local target_player = frame.args.player or "Диман"
    
    local db = build_master_database()
    local p_stats = db[target_player]
    
    if not p_stats then return "Игрок '" .. target_player .. "' не найден в БД." end
    
    local level, log_text = Significance.evaluate_player(p_stats)
    
    local result = "== Результат оценки: " .. target_player .. " ==\n"
    result = result .. "'''Присвоенный уровень: " .. level .. "'''\n\n"
    result = result .. log_text
    
    return frame:preprocess(result)
end

return Significance