Модуль:Significance
[просмотр] [просмотр кода] [история] [обновить]
Модуль значимости игроков. Работает как для искомой страницы, полностью её собирая, так и как чистый движок в составе других модулей.
Использование
{{#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