Модуль:Cron/GenerateStats/doc: различия между версиями

Материал из ЧТМ
Перейти к навигации Перейти к поиску
Нет описания правки
Нет описания правки
 
(не показана 1 промежуточная версия этого же участника)
Строка 2: Строка 2:
{{С*|prefix=Модуль:|format=ul|PlayerStats|PlayerAchievements|Автоматическая статистика}}
{{С*|prefix=Модуль:|format=ul|PlayerStats|PlayerAchievements|Автоматическая статистика}}
* [[Служебная:Развёртка шаблонов]] ({{Параметр|#invoke:Cron/GenerateStats{{!}}main}}
* [[Служебная:Развёртка шаблонов]] ({{Параметр|#invoke:Cron/GenerateStats{{!}}main}}
* [[Модуль:Data/GrandStats.json]]
<markdown>**Модуль:Cron/GenerateStats** представляет собой служебный скрипт на языке Lua (Scribunto) для ЧТМ Вики, предназначенный для агрегации, расчёта и кэширования полной статистической базы данных проекта.
Основная задача модуля — собрать данные обо всех сыгранных матчах, игроках, командах и наградах за все сезоны, провести ресурсоёмкие вычисления (такие как расчёт игровых серий, вычисление лидеров, распределение медалей и интеграция рейтинга) и экспортировать финальный структурированный результат в формате **JSON**. Полученный JSON-кэш используется другими модулями для быстрой отрисовки страниц и таблиц без повторного обхода всей базы данных при каждом просмотре.
---
### 1. Зависимости модуля
Для работы скрипт импортирует следующие компоненты:
* **`Module:Config`** — содержит общую конфигурацию проекта (список сезонов `years`, настройки эры матчей `eras`, правила для плей-офф и корректировки).
* **`Module:Data/Teams`** — справочник футбольных/спортивных команд.
* **`Module:StatEngine/Pure`** — базовый движок сбора статистики. Метод `Harvester.run_all_time` производит первичный обход баз данных матчей.
* **`Module:StatEngine/TournamentAwards`** — логика определения лучших игроков турниров, распределения номинаций (лучший бомбардир, ассистент) и обработки игровых дней (matchdays).
* **`Module:Megarating`** — предоставляет исторические данные рейтинга игроков через метод `get_public_history()`.
* **`Module:StatEngine/StreaksCore`** — специализированный компонент для вычисления последовательных серий (голевых, беспроигрышных, вратарских "сухих" и т. д.).
* **`Module:Автоматическая статистика`** — содержит метаданные и структуру строк (`row_defs`) для формирования индивидуальных профилей игроков.
---
### 2. Внутренние (вспомогательные) функции
* **`plural(n, w1, w2, w5)`** 
  Реализует алгоритм русской локализации числительных (согласование существительных с числами). 
  * *Параметры*: `n` (число), `w1` ("день"), `w2` ("дня"), `w5` ("дней"). 
  * *Возвращает*: соответствующую форму слова в зависимости от значения `n`.
* **`date_diff(date1, date2)`** 
  Вычисляет разницу во времени между двумя датами в формате `YYYY-MM-DD`. 
  * *Возвращает*:
    1. Количество дней (число) для сравнения интервалов.
    2. Текстовое представление разницы на русском языке (например, `"1 год 2 месяца 5 дней"`).
* **`apply_adj(s, m, v)`** 
  Применяет ручные корректировки показателей игрока, если данные за старые периоды неполные или требуют точечного исправления. 
  * *Параметры*: `s` — таблица статистики игрока, `m` — идентификатор метрики (например, `"goals"`, `"clean_sheets"`), `v` — числовое значение корректировки (прибавляется к текущему).
---
### 3. Алгоритм работы `Cron.main`
При вызове функции `Cron.main(frame)` выполняются следующие шаги:
#### Шаг 3.1. Загрузка и первичный сбор данных
1. Из `Module:Config` считывается массив активных сезонов. Скрипт поочерёдно загружает модули данных вида `Module:Data/<Год>` через безопасный вызов `pcall`.
2. Функция `StatEngine.Harvester.run_all_time` собирает агрегированную сырую статистику по игрокам, командам и их связкам (`GrandStats`).
#### Шаг 3.2. Применение ручных корректировок
* На основе конфигурационных параметров `Config.award_adjustments` и индивидуальных настроек метрик `Config.metrics` вносятся исправления в показатели игроков за конкретные годы (например, добавляются голы или ассисты, не зафиксированные в стандартных протоколах).
#### Шаг 3.3. Поматчевый хронологический анализ
* Все матчи из всех сезонных баз данных объединяются в плоский список и сортируются строго по дате и ID матча.
* Происходит последовательный обход матчей с помощью `StreaksEngine` для расчёта игровых серий.
* Накапливаются данные о дебютных матчах игроков (`navbox_data.debuts`).
* Для сезонов начиная с 2022 года формируется детальная поматчевая история игрока (`player_matches_list`), включающая:
  * Статус (старт/замена, роль вратаря или полевого).
  * Забитые мячи (включая тип: головой, автогол, с пенальти).
  * Голевые передачи.
  * Участие в сериях послематчевых пенальти и отражённые удары.
  * События матча (карточки, выносы из пустых ворот и т.д.).
* Фиксируются перерывы в карьере игроков (вычисляется наибольший интервал без матчей через `date_diff`).
* Выявляются победители турниров, обладатели индивидуальных наград финалов (Золотой мяч, Золотая бутса, лучший ассистент, приз Эльнура и др.).
#### Шаг 3.4. Анализ игровых дней (Matchdays)
* Для сезонов с 2022 года с помощью `TournamentAwards.evaluateMatchdayPrizes` рассчитываются индивидуальные достижения игроков в рамках отдельных туров/игровых дней (призы за MVP тура, лучший вратарь, результативность и т.д.). Эти данные суммируются в профилях игроков.
#### Шаг 3.5. Определение лидеров сезона и распределение медалей
* По каждой метрике из списка автоматической статистики определяется список лидеров за каждый год.
* С помощью `TournamentAwards.getGenericMetric` рассчитываются "медали" (золотые, серебряные, бронзовые, деревянные) для игроков как за отдельные сезоны, так и в суммарном рейтинге за всё время. Медали присваивают игрокам соответствующие цветовые маркеры (`color`).
#### Шаг 3.6. Интеграция рейтинга
* Данные о динамике Мегарейтинга (`mr_hist`) распределяются по годам в профили игроков.
#### Шаг 3.7. Подсчёт глобальных рекордов
* Вычисляются максимальные (или минимальные для GAA) показатели среди всех игроков:
  * За всю историю проекта (`PA_GlobalRecords.AllTime`).
  * В рамках одного конкретного турнира (`PA_GlobalRecords.PerTournament`).
#### Шаг 3.8. Минимизация размера JSON
* Для снижения нагрузки на парсер MediaWiki производится очистка структуры данных. Из таблиц игроков удаляются пустые поля, неиспользуемые годы и метрики, у которых все показатели (значение, числитель, знаменатель, медали) равны нулю.
#### Шаг 3.9. Сериализация и вывод
* Собранная таблица `ExportData` преобразуется в JSON-строку при помощи встроенной функции `mw.text.jsonEncode` и возвращается вызывающей стороне.
---
### 4. Структура экспортируемого JSON-кэша
Финальный JSON содержит две основные ветки: `Global` (глобальные метаданные) и `Players` (индивидуальные профили).</markdown>
<syntaxhighlight lang="json" line>
{
  "Global": {
    "navbox_data": {
      "champs": { "2022": ["Игрок А", "Игрок Б"], "2023": [...] },
      "superchamps": [ [2022, "Игрок А"] ],
      "zshar": [ [2022, "Игрок Б"] ],
      "zbashmak": [ [2022, "Игрок В", 15, "TEAM_CODE"] ],
      "elnur": [],
      "final_goals": { "Игрок А": 5 },
      "final_assists": { "Игрок Б": 3 },
      "loyalty": [ [2022, "Игрок А", "Команда Х"] ],
      "debuts": { "Игрок А": 2021 },
      "champ_counts": { "Игрок А": 3 },
      "global_goals": { "Игрок А": 120 },
      "team_matches": { "2022": { "Игрок А": { "TEAM_CODE": 10 } } }
    },
    "PA_GlobalRecords": {
      "AllTime": { "goals": 150, "max_streaks_goals": 8, "...": 0 },
      "PerTournament": { "goals": 25, "...": 0 }
    },
    "PA_CustomStats": {
      "club100": [ { "name": "Игрок А", "year": 2022 } ],
      "stadiums": { "Стадион 1": { "Игрок А": 45 } },
      "finals": { "2022": { "goals_count": {}, "superchampions": [], "...": "" } }
    },
    "PA_Leaders": {
      "goals": { "2022": ["Игрок А"], "2023": ["Игрок Б", "Игрок В"] }
    },
    "PA_TeamLeaders": {
      "TEAM_CODE": { "players": ["Игрок А"], "goals": 80 }
    },
    "PA_StadiumLeaders": {
      "Стадион 1": { "players": ["Игрок А"], "goals": 45 }
    },
    "PA_ShoeTeams": { "2022": { "Игрок А": "TEAM_CODE" } },
    "PA_AssistTeams": { "2022": { "Игрок Б": "TEAM_CODE" } }
  },
  "Players": {
    "Имя Игрока": {
      "name": "Имя Игрока",
      "AS_compiled": {
        "played_years": { "2022": true, "2023": true },
        "last_played_year": 2023,
        "played_before_2022": false,
        "metrics": {
          "goals": {
            "total_val": 42,
            "total_num": 0, "total_den": 0, "color": "gold",
            "years": {
              "2022": { "val": 20, "num": 0, "den": 0, "color": "silver" },
              "2023": { "val": 22, "num": 0, "den": 0, "color": "gold" }
            }
          }
        },
        "player_matches_list": [
          {
            "year": 2022, "num_hist": 123, "date": "2022-05-12", "stage": "Группа",
            "team1": "Команда А", "team2": "Команда Б", "score1": 3, "score2": 1,
            "role_team": 1, "goals": 2, "assists": 1, "is_mvp": true, "events": ["Гол головой"]
          }
        ]
      },
      "PA_Player": {
        "goals": 42, "matches": 50, "champs": 2, "champs_years": [2022, 2023],
        "max_streaks": { "goals": 5, "unbeaten": 12 },
        "tournaments": {
          "2022": { "goals": 20, "matches": 24, "playoff_goals": 4 }
        }
      },
      "mr_history": { "total_pct": 74.5, "years": { "2022": { "pct": 72.0, "pts": 150 } } }
    }
  }
}
</syntaxhighlight>
<markdown>---
### 5. Использование в других модулях
Чтобы получить доступ к сгенерированной статистике без повторного обсчёта, другие Lua-скрипты используют декодирование JSON-строки, возвращаемой данным модулем.
**Пример интеграции в стороннем модуле:**</markdown>
<syntaxhighlight lang="lua" line>
local CronStats = require('Module:Cron/GenerateStats')
local p = {}
function p.showPlayerGoals(frame)
    -- Получаем кэш в формате JSON
    local raw_json = CronStats.main(frame)
    local data = mw.text.jsonDecode(raw_json)
   
    local player_name = frame.args[1] or "Герыч"
    local player_data = data.Players[player_name]
   
    if player_data and player_data.PA_Player then
        return player_name .. " забил всего голов: " .. tostring(player_data.PA_Player.goals)
    else
        return "Игрок не найден или у него нет статистики."
    end
end
return p
</syntaxhighlight>
----
----
<includeonly>''Пожалуйста, добавляйте категории на страницу [[/doc|документации]]''.</includeonly>{{Doc/end}}
<includeonly>''Пожалуйста, добавляйте категории на страницу [[/doc|документации]]''.</includeonly>{{Doc/end}}

Текущая версия от 21:33, 4 июня 2026

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

Модуль:Cron/GenerateStats представляет собой служебный скрипт на языке Lua (Scribunto) для ЧТМ Вики, предназначенный для агрегации, расчёта и кэширования полной статистической базы данных проекта.

Основная задача модуля — собрать данные обо всех сыгранных матчах, игроках, командах и наградах за все сезоны, провести ресурсоёмкие вычисления (такие как расчёт игровых серий, вычисление лидеров, распределение медалей и интеграция рейтинга) и экспортировать финальный структурированный результат в формате JSON. Полученный JSON-кэш используется другими модулями для быстрой отрисовки страниц и таблиц без повторного обхода всей базы данных при каждом просмотре.


1. Зависимости модуля

Для работы скрипт импортирует следующие компоненты:

  • Module:Config — содержит общую конфигурацию проекта (список сезонов years, настройки эры матчей eras, правила для плей-офф и корректировки).
  • Module:Data/Teams — справочник футбольных/спортивных команд.
  • Module:StatEngine/Pure — базовый движок сбора статистики. Метод Harvester.run_all_time производит первичный обход баз данных матчей.
  • Module:StatEngine/TournamentAwards — логика определения лучших игроков турниров, распределения номинаций (лучший бомбардир, ассистент) и обработки игровых дней (matchdays).
  • Module:Megarating — предоставляет исторические данные рейтинга игроков через метод get_public_history().
  • Module:StatEngine/StreaksCore — специализированный компонент для вычисления последовательных серий (голевых, беспроигрышных, вратарских "сухих" и т. д.).
  • Module:Автоматическая статистика — содержит метаданные и структуру строк (row_defs) для формирования индивидуальных профилей игроков.

2. Внутренние (вспомогательные) функции

  • plural(n, w1, w2, w5)
    Реализует алгоритм русской локализации числительных (согласование существительных с числами).

    • Параметры: n (число), w1 ("день"), w2 ("дня"), w5 ("дней").
    • Возвращает: соответствующую форму слова в зависимости от значения n.
  • date_diff(date1, date2)
    Вычисляет разницу во времени между двумя датами в формате YYYY-MM-DD.

    • Возвращает:
      1. Количество дней (число) для сравнения интервалов.
      2. Текстовое представление разницы на русском языке (например, "1 год 2 месяца 5 дней").
  • apply_adj(s, m, v)
    Применяет ручные корректировки показателей игрока, если данные за старые периоды неполные или требуют точечного исправления.

    • Параметры: s — таблица статистики игрока, m — идентификатор метрики (например, "goals", "clean_sheets"), v — числовое значение корректировки (прибавляется к текущему).

3. Алгоритм работы Cron.main

При вызове функции Cron.main(frame) выполняются следующие шаги:

Шаг 3.1. Загрузка и первичный сбор данных

  1. Из Module:Config считывается массив активных сезонов. Скрипт поочерёдно загружает модули данных вида Module:Data/<Год> через безопасный вызов pcall.
  2. Функция StatEngine.Harvester.run_all_time собирает агрегированную сырую статистику по игрокам, командам и их связкам (GrandStats).

Шаг 3.2. Применение ручных корректировок

  • На основе конфигурационных параметров Config.award_adjustments и индивидуальных настроек метрик Config.metrics вносятся исправления в показатели игроков за конкретные годы (например, добавляются голы или ассисты, не зафиксированные в стандартных протоколах).

Шаг 3.3. Поматчевый хронологический анализ

  • Все матчи из всех сезонных баз данных объединяются в плоский список и сортируются строго по дате и ID матча.
  • Происходит последовательный обход матчей с помощью StreaksEngine для расчёта игровых серий.
  • Накапливаются данные о дебютных матчах игроков (navbox_data.debuts).
  • Для сезонов начиная с 2022 года формируется детальная поматчевая история игрока (player_matches_list), включающая:
    • Статус (старт/замена, роль вратаря или полевого).
    • Забитые мячи (включая тип: головой, автогол, с пенальти).
    • Голевые передачи.
    • Участие в сериях послематчевых пенальти и отражённые удары.
    • События матча (карточки, выносы из пустых ворот и т.д.).
  • Фиксируются перерывы в карьере игроков (вычисляется наибольший интервал без матчей через date_diff).
  • Выявляются победители турниров, обладатели индивидуальных наград финалов (Золотой мяч, Золотая бутса, лучший ассистент, приз Эльнура и др.).

Шаг 3.4. Анализ игровых дней (Matchdays)

  • Для сезонов с 2022 года с помощью TournamentAwards.evaluateMatchdayPrizes рассчитываются индивидуальные достижения игроков в рамках отдельных туров/игровых дней (призы за MVP тура, лучший вратарь, результативность и т.д.). Эти данные суммируются в профилях игроков.

Шаг 3.5. Определение лидеров сезона и распределение медалей

  • По каждой метрике из списка автоматической статистики определяется список лидеров за каждый год.
  • С помощью TournamentAwards.getGenericMetric рассчитываются "медали" (золотые, серебряные, бронзовые, деревянные) для игроков как за отдельные сезоны, так и в суммарном рейтинге за всё время. Медали присваивают игрокам соответствующие цветовые маркеры (color).

Шаг 3.6. Интеграция рейтинга

  • Данные о динамике Мегарейтинга (mr_hist) распределяются по годам в профили игроков.

Шаг 3.7. Подсчёт глобальных рекордов

  • Вычисляются максимальные (или минимальные для GAA) показатели среди всех игроков:
    • За всю историю проекта (PA_GlobalRecords.AllTime).
    • В рамках одного конкретного турнира (PA_GlobalRecords.PerTournament).

Шаг 3.8. Минимизация размера JSON

  • Для снижения нагрузки на парсер MediaWiki производится очистка структуры данных. Из таблиц игроков удаляются пустые поля, неиспользуемые годы и метрики, у которых все показатели (значение, числитель, знаменатель, медали) равны нулю.

Шаг 3.9. Сериализация и вывод

  • Собранная таблица ExportData преобразуется в JSON-строку при помощи встроенной функции mw.text.jsonEncode и возвращается вызывающей стороне.

4. Структура экспортируемого JSON-кэша

Финальный JSON содержит две основные ветки: Global (глобальные метаданные) и Players (индивидуальные профили).

{
  "Global": {
    "navbox_data": {
      "champs": { "2022": ["Игрок А", "Игрок Б"], "2023": [...] },
      "superchamps": [ [2022, "Игрок А"] ],
      "zshar": [ [2022, "Игрок Б"] ],
      "zbashmak": [ [2022, "Игрок В", 15, "TEAM_CODE"] ],
      "elnur": [],
      "final_goals": { "Игрок А": 5 },
      "final_assists": { "Игрок Б": 3 },
      "loyalty": [ [2022, "Игрок А", "Команда Х"] ],
      "debuts": { "Игрок А": 2021 },
      "champ_counts": { "Игрок А": 3 },
      "global_goals": { "Игрок А": 120 },
      "team_matches": { "2022": { "Игрок А": { "TEAM_CODE": 10 } } }
    },
    "PA_GlobalRecords": {
      "AllTime": { "goals": 150, "max_streaks_goals": 8, "...": 0 },
      "PerTournament": { "goals": 25, "...": 0 }
    },
    "PA_CustomStats": {
      "club100": [ { "name": "Игрок А", "year": 2022 } ],
      "stadiums": { "Стадион 1": { "Игрок А": 45 } },
      "finals": { "2022": { "goals_count": {}, "superchampions": [], "...": "" } }
    },
    "PA_Leaders": {
      "goals": { "2022": ["Игрок А"], "2023": ["Игрок Б", "Игрок В"] }
    },
    "PA_TeamLeaders": {
      "TEAM_CODE": { "players": ["Игрок А"], "goals": 80 }
    },
    "PA_StadiumLeaders": {
      "Стадион 1": { "players": ["Игрок А"], "goals": 45 }
    },
    "PA_ShoeTeams": { "2022": { "Игрок А": "TEAM_CODE" } },
    "PA_AssistTeams": { "2022": { "Игрок Б": "TEAM_CODE" } }
  },
  "Players": {
    "Имя Игрока": {
      "name": "Имя Игрока",
      "AS_compiled": {
        "played_years": { "2022": true, "2023": true },
        "last_played_year": 2023,
        "played_before_2022": false,
        "metrics": {
          "goals": {
            "total_val": 42,
            "total_num": 0, "total_den": 0, "color": "gold",
            "years": {
              "2022": { "val": 20, "num": 0, "den": 0, "color": "silver" },
              "2023": { "val": 22, "num": 0, "den": 0, "color": "gold" }
            }
          }
        },
        "player_matches_list": [
          {
            "year": 2022, "num_hist": 123, "date": "2022-05-12", "stage": "Группа",
            "team1": "Команда А", "team2": "Команда Б", "score1": 3, "score2": 1,
            "role_team": 1, "goals": 2, "assists": 1, "is_mvp": true, "events": ["Гол головой"]
          }
        ]
      },
      "PA_Player": {
        "goals": 42, "matches": 50, "champs": 2, "champs_years": [2022, 2023],
        "max_streaks": { "goals": 5, "unbeaten": 12 },
        "tournaments": {
          "2022": { "goals": 20, "matches": 24, "playoff_goals": 4 }
        }
      },
      "mr_history": { "total_pct": 74.5, "years": { "2022": { "pct": 72.0, "pts": 150 } } }
    }
  }
}


5. Использование в других модулях

Чтобы получить доступ к сгенерированной статистике без повторного обсчёта, другие Lua-скрипты используют декодирование JSON-строки, возвращаемой данным модулем.

Пример интеграции в стороннем модуле:

local CronStats = require('Module:Cron/GenerateStats')

local p = {}

function p.showPlayerGoals(frame)
    -- Получаем кэш в формате JSON
    local raw_json = CronStats.main(frame)
    local data = mw.text.jsonDecode(raw_json)
    
    local player_name = frame.args[1] or "Герыч"
    local player_data = data.Players[player_name]
    
    if player_data and player_data.PA_Player then
        return player_name .. " забил всего голов: " .. tostring(player_data.PA_Player.goals)
    else
        return "Игрок не найден или у него нет статистики."
    end
end

return p