Модуль:SimpleStats
[просмотр] [просмотр кода] [история] [обновить]
| Этот модуль реализован на основе базы данных Lua, Cron-скрипта и кэширования JSON. |
Использование
Для обычного вызова:
{{#invoke:SimpleStats|main|metric=goals}}
Если нужно отключить сортировку (по умолчанию она включена):
{{#invoke:SimpleStats|main|metric=assists|sortable=no}}
Полный список доступных показателей для вызова:
В параметр metric= можно подставлять абсолютно любой ключ из Config.metrics:
- Голы и виды мячей:
goals(все голы),head_goals(головой),heel_goals(пяточкой),free_kick_goals(со штрафных),goalie_goals(вратарские),own_goals(автоголы). - Передачи и выносы:
assists(голевые передачи),clearances(выносы из пустых). - Мульти-действия:
mega_tricks(сумма хет-триков, покеров и т.д.),assist_mega_tricks(ассистентские мега-трики). - Пенальти:
pens_scored(забитые),pens_missed(незабитые),pens_saved(отбитые вратарем),caused_pens(привезенные пенальти). - Вратари и карточки:
clean_sheets(матчи на ноль),yellow_cards(ЖК),red_cards(КК). - Награды и MVP:
mvp,mvp_goalie,matchday_prizes(призы дня),matchday_places(попадания в тройку). - Матчи и средние показатели:
matches,field_matches,plus_minus,avg_goals(в среднем за матч),avg_assists.
Страницы, подгружающие модуль в чистом виде
- Голы головой —
{{#invoke:SimpleStats|main|metric=head_goals}} - Голы пяточкой —
{{#invoke:SimpleStats|main|metric=heel_goals}} - Голы со штрафных —
{{#invoke:SimpleStats|main|metric=free_kick_goals}} - Вратарские голы —
{{#invoke:SimpleStats|main|metric=goalie_goals}} - Передачи —
{{#invoke:SimpleStats|main|metric=assists}} - Выносы из пустых —
{{#invoke:SimpleStats|main|metric=clearances}} - Матчи на ноль —
{{#invoke:SimpleStats|main|metric=clean_sheets}} - Показатель полезности —
{{#invoke:SimpleStats|main|metric=plus_minus}}
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