Документацію для цього модуля можна створити у Модуль: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
-- Дата (рахуємо до 26.10.2024)
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=10, day=26})
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 >= 4 then
local raw = mw.text.trim(player_info[4])
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 >= 6 then
local games = stats[3] or "0"
local wins = stats[4] or "0"
local losses = stats[5] or "0"
local winrate = stats[6] or "0"
winrate = mw.ustring.gsub(winrate, "%%", "")
winrate = mw.text.trim(winrate)
table.insert(output, "| games = " .. games)
table.insert(output, "| wins = " .. wins)
table.insert(output, "| losses = " .. losses)
table.insert(output, "| winrate = " .. winrate)
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 >= 3 then
local found = mw.ustring.gsub(foundation[3] 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 >= 3 then
local fin = mw.ustring.gsub(finalist[3] 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)
-- ВИПРАВЛЕННЯ: Використовуємо mw.html для створення блоку з кодом
local final_code = table.concat(output, "\n")
local html = mw.html.create('div')
:css('background', '#f5f5f5')
:css('border', '1px solid #ddd')
:css('padding', '15px')
:css('margin', '10px 0')
:css('border-radius', '4px')
html:tag('div')
:css('margin-bottom', '10px')
:css('font-weight', 'bold')
:css('color', '#333')
:wikitext('📋 Код для сторінки ' .. player_name .. ':')
html:tag('pre')
:css('background', 'white')
:css('border', '1px solid #ccc')
:css('padding', '10px')
:css('overflow', 'auto')
:css('max-height', '400px')
:css('font-family', 'monospace')
:css('font-size', '12px')
:css('white-space', 'pre-wrap')
:css('word-wrap', 'break-word')
:wikitext(final_code)
html:tag('button')
:attr('onclick', 'navigator.clipboard.writeText(this.previousElementSibling.textContent); this.textContent="✓ Скопійовано!"; setTimeout(()=>this.textContent="📋 Копіювати код", 2000);')
:css('background', '#4CAF50')
:css('color', 'white')
:css('padding', '8px 16px')
:css('border', 'none')
:css('border-radius', '4px')
:css('cursor', 'pointer')
:css('font-size', '14px')
:wikitext('📋 Копіювати код')
return tostring(html)
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