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

Материал из ЧТМ
Перейти к навигации Перейти к поиску
Нет описания правки
Нет описания правки
Строка 320: Строка 320:
         if prefix and parsed_yr and t_type then
         if prefix and parsed_yr and t_type then
             local rus_prefix = PREFIXES[prefix] or prefix
             local rus_prefix = PREFIXES[prefix] or prefix
             local type_suffix = t_type == "Final" and "" or "(отборочный турнир)"
             if t_type == "Final" then
             display_name = string.format("%s %s (%s)", rus_prefix, parsed_yr, type_suffix)
                -- Финал: выводим просто название и год без скобок
                display_name = string.format("%s %s", rus_prefix, parsed_yr)
             else
                -- Отбор: выводим название, год и суффикс в строго одинарных скобках
                display_name = string.format("%s %s (отборочный турнир)", rus_prefix, parsed_yr)
            end
         end
         end
          
          

Версия от 21:00, 27 мая 2026

Инструкция

Этот скрипт не перезаписывает базу сам, он выступает в роли "переводчика". Он читает старый Lua и выдаёт вам готовый текст, который Cargo поймёт.

Действие 1: Конвертация финальных матчей ЧТМ (Подробных)

  1. Создайте любую черновую страницу (например, Песочница_Cargo).
  2. Напишите там следующий код и нажмите «Предварительный просмотр»: {{#invoke:CargoConverter|runDetailed|2046}} (Вместо 2046 ставьте нужный год).
  3. Прямо в окне предпросмотра вы увидите огромный блок текста, начинающийся с <pre>. Внутри будут тысячи готовых строчек вида {{TWC_Match|...}}, {{TWC_Lineups|...}}.
  4. Выделите этот текст, скопируйте его.
  5. Создайте страницу, где эти данные будут жить вечно (например, Данные:2046_Финал) и вставьте туда скопированный текст. Сохраните. База Cargo проглотила матчи!

Действие 2: Конвертация сеток турниров

  1. Возвращаетесь в Песочницу.
  2. Теперь вызываете вторую функцию: {{#invoke:CargoConverter|runTournaments|2046}}
  3. Снова "Предварительный просмотр". Теперь скрипт прочитает Модуль:Data/Tournaments/2046, разобьёт 2-матчевые противостояния на два отдельных матча (с пометками _L1 и _L2), расставит поля и цвета.
  4. Копируете выданный текст.
  5. Создаёте страницу (например, Данные:2046_Турниры) и вставляете текст туда. Сохраняете. Cargo проглотил сетки!

Действие 3: Заполняем Справочник Команд (TWC_Teams)

  1. Зайдите в вашу Песочницу.
  2. Вставьте вызов: {{#invoke:CargoConverter|runTeams}}
  3. Сделайте «Предварительный просмотр». Скрипт выдаст стройную таблицу вызовов {{TWC_Teams|...}} для всех стран из словаря.
  4. Скопируйте этот текст.
  5. Создайте страницу Данные:Команды_БД (или любое удобное вам название), вставьте текст туда и сохраните.
  6. Сделайте на ней «нулевую правку» (сохраните пустой), чтобы запустить запись в Cargo [1.1.6, 1.2.6]. Справочник команд заполнен!

Действие 4: Заполняем Справочник Турниров (TWC_Tournaments)

  1. В Песочнице напишите: {{#invoke:CargoConverter|runTournamentsList}}
  2. Нажмите «Предварительный просмотр». Модуль сам прошерстит файлы за 2006, 2009, 2010... 2048 годы, соберёт все когда-либо существовавшие турниры и сгенерирует красивый список вызовов {{TWC_Tournaments|...}}.
  3. Скопируйте результат.
  4. Создайте страницу Данные:Турниры_БД, вставьте текст туда и сохраните.
  5. Сделайте «нулевую правку» [1.1.6, 1.2.6]. Метаданные турниров записаны!

(Конечно, вы можете вставлять оба результата на одну большую страницу Данные:2046, если захотите — Cargo не против).


local p = {}

-- Вспомогательная функция для безопасного вывода
local function safe(val)
    if val == nil then return "" end
    if type(val) == "boolean" then return val and "1" or "0" end
    return tostring(val)
end

-- Функция умной сортировки Match ID (с учётом чисел)
local function get_sorted_match_ids(data)
    local keys = {}
    for k in pairs(data) do
        table.insert(keys, k)
    end
    
    table.sort(keys, function(a, b)
        -- Извлекаем год и номер матча (например, "2046" и "3" из "2046-03")
        local ya, na = string.match(a, "^(%d+)-(%d+)")
        local yb, nb = string.match(b, "^(%d+)-(%d+)")
        
        if ya and yb and na and nb then
            local tya, tna = tonumber(ya), tonumber(na)
            local tyb, tnb = tonumber(yb), tonumber(nb)
            if tya ~= tyb then
                return tya < tyb
            else
                return tna < tnb
            end
        end
        return a < b -- если формат другой, сортируем просто по алфавиту
    end)
    
    return keys
end

-- =========================================================
-- 1. КОНВЕРТЕР ПОДРОБНЫХ МАТЧЕЙ (из Модуль:Data/Год)
-- =========================================================
function p.runDetailed(frame)
    local year = frame.args[1] or "2046"
    local data = mw.loadData('Модуль:Data/' .. year)
    local out = {}
    
    local tourn_id = "ЧТМ_" .. year .. "_Final"
    
    -- Получаем отсортированный список ключей
    local sorted_keys = get_sorted_match_ids(data)
    
    for _, match_id in ipairs(sorted_keys) do
        local m = data[match_id]
        
        -- 1. Базовый матч
        table.insert(out, string.format(
            "{{TWC_Matches|MatchID=%s|TournamentID=%s|Stage=%s|GroupLetter=%s|Tour=%s|RealDate=%s|Matchday=%s|NumHist=%s|Team1=%s|Team2=%s|Score1=%s|Score2=%s|AET=%s|ShootoutScore1=%s|ShootoutScore2=%s|Stadium=%s|Players1=%s|Players2=%s|Gates=%s|ThrowIns=%s|Halfs=%s|HalfTime=%s|ExtraTime=%s|ET_Halfs=%s|ET_HalfTime=%s|SubsRules=%s|Chg1_Score=%s|Chg1_Min=%s|Chg1_Pl1=%s|Chg1_Pl2=%s|Chg2_Score=%s|Chg2_Min=%s|Chg2_Pl1=%s|Chg2_Pl2=%s|Chg3_Score=%s|Chg3_Min=%s|Chg3_Pl1=%s|Chg3_Pl2=%s|Video=%s|VkVideo=%s|ReviewUrl=%s|VkReviewUrl=%s|ReviewTime=%s|WikiLink=%s|Comment=%s}}",
            safe(match_id), safe(tourn_id), safe(m.stage), safe(m.letter), safe(m.tour), safe(m.date), safe(m.matchday), safe(m.num_hist),
            safe(m.team1), safe(m.team2), safe(m.score1), safe(m.score2), safe(m.aet), safe(m.shootout_score1), safe(m.shootout_score2), safe(m.stadium),
            safe(m.players1), safe(m.players2), safe(m.gates), safe(m.throw_ins), safe(m.halfs), safe(m.half_time),
            safe(m.extra_time), safe(m.et_halfs), safe(m.et_half_time), safe(m.subs_rules),
            safe(m.changed_format_score), safe(m.changed_format_min), safe(m.changed_players_team1), safe(m.changed_players_team2),
            safe(m.changed_format2_score), safe(m.changed_format2_min), safe(m.changed_players2_team1), safe(m.changed_players2_team2),
            safe(m.changed_format3_score), safe(m.changed_format3_min), safe(m.changed_players3_team1), safe(m.changed_players3_team2),
            safe(m.video), safe(m.vk_video), safe(m.review_url), safe(m.vk_review_url), safe(m.review_time), safe(m.wikilink), safe(m.comment)
        ))
        
        -- 2. Составы (TWC_Lineups)
        local function parse_squad(sq, t_idx)
            if not sq then return end
            if sq.starters then
                for _, pl in ipairs(sq.starters) do
                    local is_cap = (pl == sq.captain)
                    local is_gk = (pl == sq.full_match_goalie)
                    table.insert(out, string.format("{{TWC_Lineups|MatchID=%s|Player=%s|TeamIndex=%s|Role=starter|IsCaptain=%s|IsFullMatchGoalie=%s}}", match_id, pl, t_idx, safe(is_cap), safe(is_gk)))
                end
            end
            if sq.substitutes then
                for _, pl in ipairs(sq.substitutes) do
                    table.insert(out, string.format("{{TWC_Lineups|MatchID=%s|Player=%s|TeamIndex=%s|Role=sub|IsCaptain=0|IsFullMatchGoalie=0}}", match_id, pl, t_idx))
                end
            end
        end
        parse_squad(m.squad1, 1)
        parse_squad(m.squad2, 2)
        parse_squad(m.neutral_gk, 0)
        
        -- 3. Голы (TWC_Goals)
        if m.goals then
            for _, g in ipairs(m.goals) do
                table.insert(out, string.format("{{TWC_Goals|MatchID=%s|TeamIndex=%s|Scorer=%s|OwnScorer=%s|Assist=%s|ScoreAfter=%s|Minute=%s|GoalType1=%s|GoalType2=%s|IsET=%s|Fouler=%s}}",
                match_id, safe(g.team), safe(g.scorer), safe(g.own_scorer), safe(g.assist), safe(g.score), safe(g.min), safe(g.goal_type), safe(g.goal_type2), safe(g.et_goal), safe(g.fouler)))
            end
        end
        
        -- 4. Замены (TWC_Subs)
        if m.subs then
            for _, s in ipairs(m.subs) do
                table.insert(out, string.format("{{TWC_Subs|MatchID=%s|TeamIndex=%s|PlayerOut=%s|PlayerIn=%s|ScoreAfter=%s|Minute=%s}}",
                match_id, safe(s.team), safe(s.player_out), safe(s.player_in), safe(s.score), safe(s.min)))
            end
        end
        
        -- 5. Карточки (TWC_Cards)
        if m.cards then
            for _, c in ipairs(m.cards) do
                table.insert(out, string.format("{{TWC_Cards|MatchID=%s|TeamIndex=%s|Player=%s|Color=%s|ScoreAfter=%s|Minute=%s|IsReturned=%s|ReturnScore=%s|ReturnMin=%s|Reason=%s}}",
                match_id, safe(c.team), safe(c.player), safe(c.color), safe(c.score), safe(c.min), safe(c.returned), safe(c.return_score), safe(c.return_min), safe(c.reason)))
            end
        end
        
        -- 6. Промахи пенальти и Выносы
        if m.missed_pens then
            for _, p in ipairs(m.missed_pens) do
                table.insert(out, string.format("{{TWC_MissedPens|MatchID=%s|TeamIndex=%s|Taker=%s|Result=%s|Goalie=%s|Fouler=%s|ScoreAfter=%s|Minute=%s}}", match_id, safe(p.team), safe(p.taker), safe(p.result), safe(p.goalie), safe(p.fouler), safe(p.score), safe(p.min)))
            end
        end
        if m.clearances then
            for _, cl in ipairs(m.clearances) do
                table.insert(out, string.format("{{TWC_Clearances|MatchID=%s|TeamIndex=%s|Player=%s|ScoreAfter=%s|Minute=%s}}", match_id, safe(cl.team), safe(cl.player), safe(cl.score), safe(cl.min)))
            end
        end
        
        -- 6.5 Серия пенальти (TWC_Shootouts)
        if m.shootout then
            for _, sh in ipairs(m.shootout) do
                table.insert(out, string.format("{{TWC_Shootouts|MatchID=%s|Num=%s|TeamIndex=%s|Taker=%s|Goalie=%s|Result=%s|ScoreAfter=%s}}",
                match_id, safe(sh.num), safe(sh.team), safe(sh.taker), safe(sh.goalie), safe(sh.result), safe(sh.score_after)))
            end
        end
        
        -- 7. Награды и MVP
        if m.mvp and m.mvp.player then
            table.insert(out, string.format("{{TWC_Awards|ContextID=%s|AwardType=MVP|Player=%s|TeamIndex=%s|Role=%s}}", match_id, safe(m.mvp.player), safe(m.mvp.team), safe(m.mvp.role)))
        end
        
        -- Призы турнира
        local awards_map = {golden_sphere="GoldenSphere", silver_sphere="SilverSphere", bronze_sphere="BronzeSphere", wooden_sphere="WoodenSphere", elnur_award="ElnurAward", best_goal="BestGoal", golden_shoe="GoldenShoe", silver_shoe="SilverShoe", bronze_shoe="BronzeShoe", wooden_shoe="WoodenShoe", golden_assistant="GoldenAssistant", silver_assistant="SilverAssistant", bronze_assistant="BronzeAssistant", wooden_assistant="WoodenAssistant", superchampions="Superchampion"}
        
        for k, v in pairs(awards_map) do
            if m[k] then
                if type(m[k]) == "table" then
                    for _, p in ipairs(m[k]) do
                        table.insert(out, string.format("{{TWC_Awards|ContextID=%s|AwardType=%s|Player=%s}}", tourn_id, v, p))
                    end
                else
                    table.insert(out, string.format("{{TWC_Awards|ContextID=%s|AwardType=%s|Player=%s}}", tourn_id, v, m[k]))
                end
            end
        end
        
        table.insert(out, "") -- пустая строка для разделения матчей
    end
    
    return "<pre><nowiki>\n" .. table.concat(out, "\n") .. "\n</nowiki></pre>"
end

-- =========================================================
-- 2. КОНВЕРТЕР ТУРНИРОВ (из Модуль:Data/Tournaments/Год)
-- =========================================================
function p.runTournaments(frame)
    local year = frame.args[1] or "2046"
    local data = mw.loadData('Модуль:Data/Tournaments/' .. year)
    local out = {}
    
    -- Сортируем названия турниров по алфавиту
    local sorted_tournaments = {}
    for t_name in pairs(data) do
        table.insert(sorted_tournaments, t_name)
    end
    table.sort(sorted_tournaments)
    
    for _, tourn_name in ipairs(sorted_tournaments) do
        local stages = data[tourn_name]
        table.insert(out, string.format("=== %s ===", tourn_name))
        
        -- Сортируем стадии турнира по алфавиту
        local sorted_stages = {}
        for s_name in pairs(stages) do
            table.insert(sorted_stages, s_name)
        end
        table.sort(sorted_stages)
        
        for _, stage_name in ipairs(sorted_stages) do
            local stage_data = stages[stage_name]
            
            -- 1. Итоговые таблицы групп
            if stage_data.standings then
                for pos, st in ipairs(stage_data.standings) do
                    table.insert(out, string.format("{{TWC_StageTeams|TournamentID=%s|Stage=%s|Team=%s|Position=%s|ColorCode=%s}}",
                    safe(tourn_name), safe(stage_name), safe(st[1]), pos, safe(st[2])))
                end
            end
            
            -- 2. Матчи турнира
            if stage_data.matches then
                for i, m in ipairs(stage_data.matches) do
                    local base_match_id = tourn_name .. "_" .. stage_name .. "_M" .. i
                    
                    if stage_data.type == "group" then
                        table.insert(out, string.format("{{TWC_Matches|MatchID=%s|TournamentID=%s|Stage=%s|Team1=%s|Team2=%s|Score1=%s|Score2=%s|FieldAdvantage=%s}}",
                        base_match_id, safe(tourn_name), safe(stage_name), safe(m[1]), safe(m[2]), safe(m[3]), safe(m[4]), safe(m[5])))
                        
                    elseif stage_data.type == "knockout" then
                        if stage_data.number_of_rounds == 1 then
                            local aet = (m[5] == "aet")
                            table.insert(out, string.format("{{TWC_Matches|MatchID=%s|TournamentID=%s|Stage=%s|Team1=%s|Team2=%s|Score1=%s|Score2=%s|AET=%s|ShootoutScore1=%s|ShootoutScore2=%s|Color1=%s|Color2=%s|FieldAdvantage=%s}}",
                            base_match_id, safe(tourn_name), safe(stage_name), safe(m[1]), safe(m[2]), safe(m[3]), safe(m[4]), safe(aet), safe(m[6]), safe(m[7]), safe(m[8]), safe(m[9]), safe(m[10])))
                        else
                            -- Первый матч
                            table.insert(out, string.format("{{TWC_Matches|MatchID=%s_L1|TournamentID=%s|Stage=%s|Team1=%s|Team2=%s|Score1=%s|Score2=%s|FieldAdvantage=1}}",
                            base_match_id, safe(tourn_name), safe(stage_name), safe(m[1]), safe(m[2]), safe(m[3]), safe(m[4])))
                            
                            -- Второй матч
                            local aet = (m[7] == "aet")
                            table.insert(out, string.format("{{TWC_Matches|MatchID=%s_L2|TournamentID=%s|Stage=%s|Team1=%s|Team2=%s|Score1=%s|Score2=%s|AET=%s|ShootoutScore1=%s|ShootoutScore2=%s|Color1=%s|Color2=%s|FieldAdvantage=2}}",
                            base_match_id, safe(tourn_name), safe(stage_name), safe(m[2]), safe(m[1]), safe(m[6]), safe(m[5]), safe(aet), safe(m[9]), safe(m[8]), safe(m[11]), safe(m[10]))) 
                        end
                    end
                end
            end
            table.insert(out, "")
        end
    end
    
    return "<pre><nowiki>\n" .. table.concat(out, "\n") .. "\n</nowiki></pre>"
end

-- =========================================================
-- 3. КОНВЕРТЕР СПРАВОЧНИКА КОМАНД (в TWC_Teams)
-- =========================================================
function p.runTeams(frame)
    local teams_mod = require('Модуль:Data/Teams')
    local raw = teams_mod.raw_data
    if not raw then
        return "<span style='color:red; font-weight:bold;'>Ошибка:</span> Не удалось получить raw_data из Модуль:Data/Teams.\n" ..
               "Убедитесь, что добавили строку <pre>M.raw_data = raw_data</pre> в самый конец Модуль:Data/Teams перед return M."
    end
    
    local out = {}
    
    -- Сортируем коды по алфавиту
    local sorted_codes = {}
    for code in pairs(raw) do
        table.insert(sorted_codes, code)
    end
    table.sort(sorted_codes)
    
    local CONFS = {
        [1] = "Америка",
        [2] = "Африка",
        [3] = "Евразия",
        [4] = "Океания"
    }
    
    for _, code in ipairs(sorted_codes) do
        local data = raw[code]
        local short_name = data[1]
        local full_name = data[2] or short_name
        local conf_num = data[3] -- сохраняем число (1, 2, 3, 4) для Confederation=Integer
        local cases = data[4] or {}
        local name_gen = cases.gen or full_name
        local name_loc = cases.loc or full_name
        local twc = data.twc -- Булево значение (active в ЧТМ сейчас)
        
        table.insert(out, string.format("{{TWC_Teams|Code=%s|ShortName=%s|FullName=%s|Confederation=%s|NameGen=%s|NameLoc=%s|IsActive=%s}}",
            safe(code), safe(short_name), safe(full_name), safe(conf_num), safe(name_gen), safe(name_loc), safe(twc)))
    end
    
    return "<pre><nowiki>\n" .. table.concat(out, "\n") .. "\n</nowiki></pre>"
end

-- =========================================================
-- 4. КОНВЕРТЕР СПРАВОЧНИКА ТУРНИРОВ (в TWC_Tournaments)
-- =========================================================
function p.runTournamentsList(frame)
    local config = require('Модуль:Config')
    local years = config.all_years
    local out = {}
    
    local PREFIXES = {
        ["ЧТМ"] = "Чемпионат третьего мира",
        ["КАм"] = "Кубок Америки",
        ["КАф"] = "Кубок Африки",
        ["КЕв"] = "Кубок Евразии",
        ["КОк"] = "Кубок Океании",
        ["ККо"] = "Кубок Конфедераций",
        ["КФе"] = "Кубок Федерации",
        ["ЛНа"] = "Лига Наций",
        ["КЕвропы"] = "Кубок Европы",
        ["КЮжАм"] = "Кубок Южной Америки",
        ["ЧЧМ"] = "Чемпионат четвёртого мира",
        ["КУб"] = "Кубок Убогих"
    }
    
    -- Собираем уникальные ID турниров со всех доступных файлов лет
    local tournaments = {}
    
    for _, yr in ipairs(years) do
        local success, year_data = pcall(mw.loadData, 'Модуль:Data/Tournaments/' .. yr)
        if success and year_data then
            for tourn_id, _ in pairs(year_data) do
                tournaments[tourn_id] = yr
            end
        end
    end
    
    -- Сортируем турниры по имени
    local sorted_tourn = {}
    for tourn_id in pairs(tournaments) do
        table.insert(sorted_tourn, tourn_id)
    end
    table.sort(sorted_tourn)
    
    for _, tourn_id in ipairs(sorted_tourn) do
        local yr = tournaments[tourn_id]
        
        -- Парсим префикс, год и тип из ID (поддерживает и ЧТМ_2046_Final, и КУб2030_Final)
        local prefix, parsed_yr, t_type = string.match(tourn_id, "^([%aА-Яа-яёЁ]+)_*(%d+)_*(%a+)")
        
        local display_name = tourn_id -- фоллбэк
        if prefix and parsed_yr and t_type then
            local rus_prefix = PREFIXES[prefix] or prefix
            if t_type == "Final" then
                -- Финал: выводим просто название и год без скобок
                display_name = string.format("%s %s", rus_prefix, parsed_yr)
            else
                -- Отбор: выводим название, год и суффикс в строго одинарных скобках
                display_name = string.format("%s %s (отборочный турнир)", rus_prefix, parsed_yr)
            end
        end
        
        table.insert(out, string.format("{{TWC_Tournaments|TournamentID=%s|TournamentName=%s|Year=%s|Type=%s}}",
            safe(tourn_id), safe(display_name), safe(yr), safe(t_type)))
    end
    
    return "<pre><nowiki>\n" .. table.concat(out, "\n") .. "\n</nowiki></pre>"
end

return p