Модуль:GeneratePlayerPages

Версія від 10:55, 1 грудня 2025, створена Admin (обговорення | внесок) (Створена сторінка: local p = {} -- ================================================ -- УТИЛІТИ -- ================================================ local function get_table_from_page(page_name) local title = mw.title.new(page_name) if not title or not title.exists then return nil end local content = title:getContent() if not content then return nil end local table_start = mw.ustring.find(content, "{|") local table_end = mw.ustring.fi...)
(різн.) ← Попередня версія | Поточна версія (різн.) | Новіша версія → (різн.)

Документацію для цього модуля можна створити у Модуль:GeneratePlayerPages/документація

local p = {}

-- ================================================
-- УТИЛІТИ
-- ================================================

local function get_table_from_page(page_name)
    local title = mw.title.new(page_name)
    if not title or not title.exists then return nil end
    
    local content = title:getContent()
    if not content then return nil end
    
    local table_start = mw.ustring.find(content, "{|")
    local table_end = mw.ustring.find(content, "|}", table_start)
    
    if not table_start or not table_end then return nil end
    
    return mw.ustring.sub(content, table_start, table_end + 1)
end

local function get_page_content(page_name)
    local title = mw.title.new(page_name)
    if not title or not title.exists then return nil end
    return title:getContent()
end

local function parse_table_rows(table_content)
    local rows = {}
    for row in mw.ustring.gmatch(table_content, "|-\n(.-)\n|-") do
        table.insert(rows, row)
    end
    local last_row = mw.ustring.match(table_content, "|-\n(.-)%s*|}")
    if last_row then table.insert(rows, last_row) end
    return rows
end

local function parse_row_cells(row)
    local cells = {}
    row = mw.ustring.gsub(row, "^%s*|%s*", "")
    for cell in mw.ustring.gmatch(row, "([^|]+)") do
        local trimmed = mw.text.trim(cell)
        if trimmed ~= "" then table.insert(cells, trimmed) end
    end
    return cells
end

local function clean_wikilinks(text)
    if not text then return nil end
    text = mw.ustring.gsub(text, "%[%[([^%]|]+)|([^%]]+)%]%]", "%2")
    text = mw.ustring.gsub(text, "%[%[([^%]]+)%]%]", "%1")
    return mw.text.trim(text)
end

local function find_player_data(table_content, player_name)
    if not table_content then return nil end
    
    local escaped = mw.ustring.gsub(player_name, "([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1")
    local player_pattern = "%[%[" .. escaped .. "%]%]"
    
    local rows = parse_table_rows(table_content)
    
    for _, row in ipairs(rows) do
        if mw.ustring.find(row, player_pattern) then
            return parse_row_cells(row)
        end
    end
    
    return nil
end

local function get_all_players()
    local table_content = get_table_from_page("Гравці")
    if not table_content then return nil end
    
    local rows = parse_table_rows(table_content)
    local players = {}
    
    for _, row in ipairs(rows) do
        local cells = parse_row_cells(row)
        if #cells >= 2 then
            local player_name = clean_wikilinks(cells[2])
            if player_name then
                table.insert(players, player_name)
            end
        end
    end
    
    return players
end

-- ================================================
-- ГЕНЕРАЦІЯ ТИТУЛІВ
-- ================================================

local tournament_dates = {
    ["Women's Closed Cup I"] = "15.03.2023",
    ["Men's Closed Cup I"] = "05.04.2023",
    ["Combined Closed Cup I"] = "21.04.2023",
    ["Score Open Battle I"] = "07.05.2023",
    ["Women's Closed Cup II"] = "11.05.2023",
    ["Men's Closed Cup II"] = "27.05.2023",
    ["Combined Closed Cup II"] = "02.06.2023",
    ["Score Open Battle II"] = "17.06.2023",
    ["Mafia Closed Cup I"] = "12.11.2023",
    ["Mafia Closed Cup I Online"] = "28.01.2024",
    ["My Closest Circle I"] = "01.01.2023",
    ["Get Names 01"] = "08.10.2023",
    ["Get Names 02"] = "03.12.2023",
    ["Get Names 03"] = "10.03.2024",
    ["Get Names 04"] = "27.04.2024",
    ["Get Names 05"] = "14.07.2024",
    ["Get Names 06"] = "21.07.2024",
    ["Get Names 07"] = "08.09.2024",
    ["Get Names 08"] = "19.09.2024",
    ["Get Names 09"] = "29.09.2024",
    ["Перший сезон (фінал)"] = "09.09.2023",
    ["Перший сезон (рейтинг)"] = "09.09.2023",
    ["Другий сезон (фінал)"] = "28.10.2023",
    ["Другий сезон (рейтинг)"] = "28.10.2023",
    ["Третій сезон (фінал)"] = "23.12.2023",
    ["Третій сезон (рейтинг)"] = "23.12.2023",
    ["Четвертий сезон (фінал)"] = "10.02.2024",
    ["Четвертий сезон (рейтинг)"] = "10.02.2024",
    ["П'ятий сезон (фінал)"] = "06.04.2024",
    ["П'ятий сезон (рейтинг)"] = "06.04.2024",
    ["Шостий сезон (фінал)"] = "11.05.2024",
    ["Шостий сезон (рейтинг)"] = "11.05.2024",
    ["Сьомий сезон (фінал)"] = "06.07.2024",
    ["Сьомий сезон (рейтинг)"] = "06.07.2024",
    ["Восьмий сезон (фінал)"] = "10.08.2024",
    ["Восьмий сезон (рейтинг)"] = "10.08.2024",
    ["Дев'ятий сезон (фінал)"] = "28.09.2024",
    ["Дев'ятий сезон (рейтинг)"] = "28.09.2024",
    ["Фінал Року"] = "13.10.2024"
}

local function get_medal_icon(value)
    if not value or value == "" or value == " " then return nil end
    value = mw.text.trim(value)
    
    if value == "" then return nil
    elseif value == "1" then return "Gold.png"
    elseif value == "2" then return "Silver.png"
    elseif value == "3" then return "Bronze.png"
    elseif value == "4" then return "Finalist.png"
    elseif value == "S" or mw.ustring.match(value, "^S%d") then return "Star.png"
    else return nil
    end
end

local function to_roman(num)
    local romans = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}
    return romans[tonumber(num)] or num
end

local function get_tournament_display_name(header_name)
    local season_num = mw.ustring.match(header_name, "([А-Яа-яЁёІіЇїЄєҐґ']+) сезон %(фінал%)")
    if not season_num then
        season_num = mw.ustring.match(header_name, "([А-Яа-яЁёІіЇїЄєҐґ']+) сезон %(рейтинг%)")
    end
    
    if season_num then
        local season_map = {
            ["Перший"] = 1, ["Другий"] = 2, ["Третій"] = 3,
            ["Четвертий"] = 4, ["П'ятий"] = 5, ["Шостий"] = 6,
            ["Сьомий"] = 7, ["Восьмий"] = 8, ["Дев'ятий"] = 9
        }
        
        local season_number = season_map[season_num]
        if season_number then
            local roman = to_roman(season_number)
            local type_text = mw.ustring.find(header_name, "фінал") and "Фінал" or "Рейтинг"
            local clean_name = mw.ustring.gsub(header_name, "%s*%(фінал%)%s*", "")
            clean_name = mw.ustring.gsub(clean_name, "%s*%(рейтинг%)%s*", "")
            clean_name = mw.text.trim(clean_name)
            
            return string.format("%s сезон. %s.", roman, type_text), clean_name
        end
    end
    
    return header_name, header_name
end

local function get_player_row_with_headers(page_title, player_name)
    local table_content = get_table_from_page(page_title)
    if not table_content then return nil end
    
    local first_row = mw.ustring.match(table_content, "{|[^\n]*\n!(.-)[\n]")
    local headers = {}
    
    if first_row then
        for header in mw.ustring.gmatch(first_row, "([^|]+)") do
            local trimmed = mw.text.trim(header)
            if trimmed ~= "" then
                table.insert(headers, trimmed)
            end
        end
    end
    
    if #headers == 0 then return nil end
    
    local cells = find_player_data(table_content, player_name)
    if not cells then return nil end
    
    return {headers = headers, cells = cells}
end

local function generate_titles(player_name)
    local titles_data = get_player_row_with_headers("Титули", player_name)
    if not titles_data then return "* ''Відсутні''" end
    
    local prize_data = get_player_row_with_headers("Призові", player_name)
    if not prize_data then return "* ''Помилка: не знайдено призові''" end
    
    local results = {}
    
    for i = 2, #titles_data.cells do
        local cell_value = titles_data.cells[i]
        local header = titles_data.headers[i]
        local prize_value = prize_data.cells[i]
        
        if cell_value and cell_value ~= "" and cell_value ~= "-" and header then
            local medal = get_medal_icon(cell_value)
            
            if medal then
                local prize_amount = "0 ₴"
                
                if prize_value and prize_value ~= "" and prize_value ~= "-" then
                    prize_value = mw.ustring.gsub(prize_value, "₴", "")
                    prize_value = mw.text.trim(prize_value)
                    if prize_value ~= "0" then
                        prize_amount = prize_value .. " ₴"
                    end
                end
                
                local date = tournament_dates[header] or "01.01.2023"
                local display_name, page_name = get_tournament_display_name(header)
                
                table.insert(results, {
                    date = date,
                    medal = medal,
                    display = display_name,
                    page = page_name,
                    prize = prize_amount
                })
            end
        end
    end
    
    if #results == 0 then return "* ''Відсутні''" end
    
    -- Генеруємо вікікод таблиці
    local output = {}
    table.insert(output, "{| class=\"wikitable sortable\" style=\"font-size: 14.5px;\"")
    table.insert(output, "|-")
    table.insert(output, "! style=\"\" | Дата")
    table.insert(output, "! style=\"text-align: left;\" | Місце і турнір")
    table.insert(output, "! style=\"text-align: left;\" | Приз")
    
    for _, result in ipairs(results) do
        table.insert(output, "|-")
        table.insert(output, string.format(
            "| style=\"width:80px; text-align:center;\" | %s\n| style=\"text-align:left; padding-left:10px;\" | [[File:%s|20px|link=]] [[%s|%s]]\n| style=\"text-align:right;\" | %s",
            result.date,
            result.medal,
            result.page,
            result.display,
            result.prize
        ))
    end
    
    table.insert(output, "|}")
    
    return table.concat(output, "\n")
end

-- ================================================
-- ГЕНЕРАЦІЯ ЦІКАВИХ ФАКТІВ
-- ================================================

local pages_to_search = {
    "Перший сезон", "Другий сезон", "Третій сезон", "Четвертий сезон",
    "П'ятий сезон", "Шостий сезон", "Сьомий сезон", "Восьмий сезон",
    "Дев'ятий сезон", "Mafia Closed Circle", "Ten's Games", "Alternatywa",
    "Майстерня Стратегічного Саморозвитку", "Get Names 01", "Get Names 02",
    "Get Names 03", "Get Names 04", "Get Names 05", "Get Names 06",
    "Get Names 07", "Get Names 08", "Get Names 09", "Women's Closed Cup I",
    "Women's Closed Cup II", "Men's Closed Cup I", "Men's Closed Cup II",
    "Combined Closed Cup I", "Combined Closed Cup II", "Score Open Battle I",
    "Score Open Battle II", "Mafia Closed Cup I", "Mafia Closed Cup I Online",
    "My Closest Circle I", "Фінал Року"
}

local function get_facts_section(page_title)
    local content = get_page_content(page_title)
    if not content then return nil end
    
    local section_start = mw.ustring.find(content, "==%s*[Цц]ікаві%s*[Фф]акти%s*==")
    if not section_start then return nil end
    
    local section_end = mw.ustring.find(content, "\n==[^=]", section_start + 1)
    
    local section_content
    if section_end then
        section_content = mw.ustring.sub(content, section_start, section_end - 1)
    else
        section_content = mw.ustring.sub(content, section_start)
    end
    
    return section_content
end

local function fact_contains_player(fact, player_name)
    local escaped_name = mw.ustring.gsub(player_name, "([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1")
    local pattern1 = "%[%[" .. escaped_name .. "%]%]"
    local pattern2 = "%[%[" .. escaped_name .. "|[^%]]+%]%]"
    
    return mw.ustring.find(fact, pattern1) or mw.ustring.find(fact, pattern2)
end

local function extract_facts(section_content)
    local facts = {}
    for fact in mw.ustring.gmatch(section_content, "%*[^\n]+") do
        table.insert(facts, fact)
    end
    return facts
end

local function generate_facts(player_name)
    local result_parts = {}
    
    for _, page_title in ipairs(pages_to_search) do
        local section = get_facts_section(page_title)
        
        if section then
            local facts = extract_facts(section)
            local player_facts = {}
            
            for _, fact in ipairs(facts) do
                if fact_contains_player(fact, player_name) then
                    table.insert(player_facts, fact)
                end
            end
            
            if #player_facts > 0 then
                table.insert(result_parts, string.format("==== %s ====", page_title))
                for _, fact in ipairs(player_facts) do
                    table.insert(result_parts, fact)
                end
                table.insert(result_parts, "")
            end
        end
    end
    
    if #result_parts == 0 then
        return "''Цікавих фактів не знайдено''"
    end
    
    return table.concat(result_parts, "\n")
end

-- ================================================
-- ГЕНЕРАЦІЯ ПОВНОГО КОДУ ГРАВЦЯ
-- ================================================

function p.generate_single_player(frame)
    local player_name = frame.args.player or frame.args[1]
    
    if not player_name or player_name == "" then
        return "Помилка: Не вказано ім'я гравця"
    end
    
    -- Збираємо базові дані
    local stats = find_player_data(get_table_from_page("Статистика"), player_name)
    local player_info = find_player_data(get_table_from_page("Гравці"), player_name)
    local foundation = find_player_data(get_table_from_page("Фундація"), player_name)
    local prize_pool = find_player_data(get_table_from_page("Призовий_фонд"), player_name)
    local finalist = find_player_data(get_table_from_page("Фіналіст"), player_name)
    
    -- FOTY Rating
    local foty_rating = "—"
    local content = get_page_content("Період")
    if content then
        local foty_section = mw.ustring.match(content, "==+%s*Фінал Року%s*==+(.-)\n==")
        if not foty_section then
            foty_section = mw.ustring.match(content, "==+%s*Фінал Року%s*==+(.*)")
        end
        
        if foty_section then
            local table_start = mw.ustring.find(foty_section, "{|")
            local table_end = mw.ustring.find(foty_section, "|}", table_start)
            
            if table_start and table_end then
                local table_content = mw.ustring.sub(foty_section, table_start, table_end + 1)
                local foty_cells = find_player_data(table_content, player_name)
                
                if foty_cells and #foty_cells >= 3 then
                    local place = mw.text.trim(foty_cells[1])
                    local rating = mw.text.trim(foty_cells[3])
                    rating = mw.ustring.gsub(rating, "<span[^>]*>", "")
                    rating = mw.ustring.gsub(rating, "</span>", "")
                    rating = mw.ustring.gsub(rating, "[^%d%-]", "")
                    rating = mw.text.trim(rating)
                    
                    if rating and rating ~= "" then
                        foty_rating = rating .. " (" .. place .. " місце)"
                    end
                end
            end
        end
    end
    
    -- Дата
    local date_added = "Лише Бог знає"
    if player_info and #player_info >= 3 then
        local raw_date = player_info[3]
        if raw_date and raw_date ~= "" and raw_date ~= "-" then
            local day, month, year = mw.ustring.match(raw_date, "(%d+)%.(%d+)%.(%d+)")
            if day and month and year then
                local end_date = os.time({year=2024, month=12, day=1})
                local start_date = os.time({year=tonumber(year), month=tonumber(month), day=tonumber(day)})
                local days_diff = math.floor((end_date - start_date) / 86400)
                date_added = string.format("%s (%d днів)", raw_date, days_diff)
            end
        end
    end
    
    -- Recruiter
    local recruiter = "Не вказано"
    if player_info and #player_info >= 2 then
        local raw = mw.text.trim(player_info[2])
        if raw ~= "Відсутній" and raw ~= "-" and raw ~= "" then
            recruiter = raw
        end
    end
    
    -- Генеруємо титули
    local titles_code = generate_titles(player_name)
    
    -- Генеруємо факти
    local facts_code = generate_facts(player_name)
    
    -- Генеруємо повний код
    local output = {}
    
    -- Шаблон
    table.insert(output, "{{MCC Player New")
    table.insert(output, "| nickname = " .. player_name)
    
    if stats and #stats >= 5 then
        table.insert(output, "| games = " .. (stats[2] or "0"))
        table.insert(output, "| wins = " .. (stats[3] or "0"))
        table.insert(output, "| losses = " .. (stats[4] or "0"))
        table.insert(output, "| winrate = " .. (stats[5] or "0"))
    else
        table.insert(output, "| games = 0")
        table.insert(output, "| wins = 0")
        table.insert(output, "| losses = 0")
        table.insert(output, "| winrate = 0")
    end
    
    table.insert(output, "| foty_rating = " .. foty_rating)
    table.insert(output, "| recruiter = " .. recruiter)
    table.insert(output, "| date_added = " .. date_added)
    
    if foundation and #foundation >= 2 then
        local found = mw.ustring.gsub(foundation[2] or "0", "[^%d]", "")
        table.insert(output, "| foundation = " .. found)
    else
        table.insert(output, "| foundation = 0")
    end
    
    if prize_pool and #prize_pool >= 2 then
        local prize = mw.ustring.gsub(prize_pool[2] or "0", "[^%d]", "")
        table.insert(output, "| prize_pool = " .. prize)
    else
        table.insert(output, "| prize_pool = 0")
    end
    
    if finalist and #finalist >= 2 then
        local fin = mw.ustring.gsub(finalist[2] or "0", "[^%d]", "")
        table.insert(output, "| finalist = " .. fin)
    else
        table.insert(output, "| finalist = 0")
    end
    
    table.insert(output, "}}")
    table.insert(output, "")
    table.insert(output, "''[Тут додай опис гравця]''")
    table.insert(output, "")
    
    -- Сезони
    table.insert(output, "== Сезони ==")
    table.insert(output, "{{#invoke:FetchData|season_achievements|player=" .. player_name .. "}}")
    table.insert(output, "")
    
    -- Титули
    table.insert(output, "== Нагороди в MCC ==")
    table.insert(output, titles_code)
    table.insert(output, "")
    
    -- Записи ігор
    table.insert(output, "== Записи ігор ({{#invoke:FetchData|games_count_records|player=" .. player_name .. "}}) ==")
    table.insert(output, "{{#invoke:FetchData|player_games|player=" .. player_name .. "}}")
    table.insert(output, "")
    
    -- Цікаві факти
    table.insert(output, "== Цікаві факти ==")
    table.insert(output, facts_code)
    
    return "<pre>" .. table.concat(output, "\n") .. "</pre>"
end

-- Генерувати для всіх гравців
function p.generate_all_players(frame)
    local players = get_all_players()
    
    if not players then
        return "Помилка: Не вдалося отримати список гравців"
    end
    
    local limit = tonumber(frame.args.limit) or 5
    local output = {}
    table.insert(output, "== Згенеровані коди для гравців ==\n")
    
    for i, player_name in ipairs(players) do
        if i > limit then
            table.insert(output, string.format("\n''... і ще %d гравців. Збільш limit для показу більше.''", #players - limit))
            break
        end
        
        table.insert(output, string.format("=== %d. %s ===", i, player_name))
        local player_code = p.generate_single_player({args = {player = player_name}})
        table.insert(output, player_code)
        table.insert(output, "\n----\n")
    end
    
    return table.concat(output, "\n")
end

return p