5441
редагування
Admin (обговорення | внесок) Немає опису редагування Мітки: Ручний відкіт Скасовано |
Admin (обговорення | внесок) Немає опису редагування Мітка: Ручний відкіт |
||
| Рядок 2: | Рядок 2: | ||
-- ================================================ | -- ================================================ | ||
-- | -- КЕШУВАННЯ (найважливіша оптимізація) | ||
-- ================================================ | -- ================================================ | ||
local page_cache = {} | local page_cache = {} | ||
local table_cache = {} | local table_cache = {} | ||
local function get_page_content(page_name) | local function get_page_content(page_name) | ||
| Рядок 30: | Рядок 15: | ||
local title = mw.title.new(page_name) | local title = mw.title.new(page_name) | ||
if not title or not title.exists then | if not title or not title.exists then | ||
page_cache[page_name] = nil | |||
return nil | return nil | ||
end | end | ||
| Рядок 44: | Рядок 30: | ||
local content = get_page_content(page_name) | local content = get_page_content(page_name) | ||
if not content then return nil end | if not content then | ||
table_cache[page_name] = nil | |||
return nil | |||
end | |||
local table_start = mw.ustring.find(content, "{|") | local table_start = mw.ustring.find(content, "{|") | ||
local table_end = mw.ustring.find(content, "|}", table_start) | local table_end = mw.ustring.find(content, "|}", table_start) | ||
if not table_start or not table_end then return nil end | if not table_start or not table_end then | ||
table_cache[page_name] = nil | |||
return nil | |||
end | |||
local table_content = mw.ustring.sub(content, table_start, table_end + 1) | local table_content = mw.ustring.sub(content, table_start, table_end + 1) | ||
table_cache[page_name] = table_content | table_cache[page_name] = table_content | ||
return table_content | return table_content | ||
end | |||
-- ================================================ | |||
-- УТИЛІТИ (спільні для всіх функцій) | |||
-- ================================================ | |||
local function error_output(context, error_details) | |||
local safe_details = error_details or "N/A" | |||
return string.format("<span style='color:red; font-weight:bold;'>[Error: %s. Details: %s]</span>", | |||
context or "Unknown", safe_details) | |||
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 strip_html_tags(text) | |||
if not text then return text end | |||
text = mw.ustring.gsub(text, "<span[^>]*>", "") | |||
text = mw.ustring.gsub(text, "</span>", "") | |||
return mw.text.trim(text) | |||
end | end | ||
| Рядок 71: | Рядок 87: | ||
local cells = {} | local cells = {} | ||
row = mw.ustring.gsub(row, "^%s*|%s*", "") | row = mw.ustring.gsub(row, "^%s*|%s*", "") | ||
for cell in mw.ustring.gmatch(row, "([^|]+)") do | |||
for cell in mw.ustring.gmatch(row, " | |||
local trimmed = mw.text.trim(cell) | local trimmed = mw.text.trim(cell) | ||
if trimmed ~= "" then | if trimmed ~= "" then | ||
| Рядок 78: | Рядок 93: | ||
end | end | ||
end | end | ||
return cells | return cells | ||
end | end | ||
local function | local function find_player_in_table(table_content, player_name, column_index) | ||
if not table_content then return nil end | if not table_content then return nil end | ||
| Рядок 92: | Рядок 106: | ||
for _, row in ipairs(rows) do | for _, row in ipairs(rows) do | ||
if mw.ustring.find(row, player_pattern) then | if mw.ustring.find(row, player_pattern) then | ||
local cells = parse_row_cells(row) | |||
if column_index and column_index <= #cells then | |||
return cells[column_index] | |||
end | |||
return cells | |||
end | end | ||
end | end | ||
return nil | return nil | ||
end | end | ||
-- ================================================ | -- ================================================ | ||
-- | -- FETCHDATA (season_result) | ||
-- ================================================ | -- ================================================ | ||
function p.season_result(frame) | function p.season_result(frame) | ||
local | local season = frame.args.season | ||
local | local player = frame.args.player | ||
local season_titles = { | |||
"Перший сезон", "Другий сезон", "Третій сезон", | |||
"Четвертий сезон", "П'ятий сезон", "Шостий сезон", | |||
"Сьомий сезон", "Восьмий сезон", "Дев'ятий сезон" | |||
local | |||
} | } | ||
local season_title = season_titles[tonumber(season)] | |||
if not season_title then return "??" end | |||
if not | |||
local | local content = get_page_content(season_title) | ||
if not content then return "??" end | |||
if not | local rating_section = mw.ustring.match(content, "==%s*Рейтинг%s*==.-{|%s*class%s*=%s*\"wikitable sortable\"(.-)|}") | ||
if not rating_section then return "--" end | |||
local | local pattern = "|%s*(%d+)%s*|%s*%[%[" .. mw.ustring.gsub(player, "([%(%)%.%-%+%[%]])", "%%%1") .. "%]%]" | ||
local | local direct_pattern = "|%s*(%d+)%s*|%s*" .. mw.ustring.gsub(player, "([%(%)%.%-%+%[%]])", "%%%1") .. "%s*" | ||
local rank = mw.ustring.match(rating_section, pattern) or mw.ustring.match(rating_section, direct_pattern) | |||
return rank or "--" | |||
return | |||
end | end | ||
-- ================================================ | -- ================================================ | ||
-- | -- FETCHDATA2 (базова статистика) | ||
-- ================================================ | -- ================================================ | ||
function p.games_count(frame) | function p.games_count(frame) | ||
local player_name = frame.args.player | local player_name = frame.args.player | ||
if not player_name or player_name == "" then return "0" end | |||
if not player_name or player_name == "" then | |||
return | local result = find_player_in_table(get_table_from_page("Статистика"), player_name, 2) | ||
return result or "0" | |||
end | end | ||
function p.wins_count(frame) | function p.wins_count(frame) | ||
local player_name = frame.args.player | local player_name = frame.args.player | ||
if not player_name or player_name == "" then return "0" end | |||
if not player_name or player_name == "" then | |||
local | local result = find_player_in_table(get_table_from_page("Статистика"), player_name, 3) | ||
return result or "0" | |||
return | |||
end | end | ||
function p.losses_count(frame) | function p.losses_count(frame) | ||
local player_name = frame.args.player or | local player_name = frame.args.player | ||
if not player_name or player_name == "" then return "0" end | |||
local result = find_player_in_table(get_table_from_page("Статистика"), player_name, 4) | |||
return result or "0" | |||
return | |||
end | end | ||
function p.win_rate_colored(frame) | function p.win_rate_colored(frame) | ||
local player_name = frame.args.player or | local player_name = frame.args.player | ||
if not player_name or player_name == "" then return "0%" end | |||
if not | local win_rate = find_player_in_table(get_table_from_page("Статистика"), player_name, 5) | ||
if not win_rate then return "0%" end | |||
end | |||
local rate_num = tonumber(mw.ustring.match(win_rate, "([%d%.]+)")) | |||
if not rate_num then return win_rate end | |||
local | local color = "#4caf50" | ||
if | if rate_num < 40 then | ||
color = "indianred" | |||
elseif rate_num < 50 then | |||
color = "orange" | |||
end | end | ||
if not mw.ustring.find(win_rate, "%%") then | |||
win_rate = win_rate .. "%" | |||
end | end | ||
return string.format('<span style="color:%s;">%s</span>', color, win_rate) | |||
end | end | ||
function p.recruiter(frame) | function p.recruiter(frame) | ||
local player_name = frame.args.player | local player_name = frame.args.player | ||
if not player_name or player_name == "" then return "Не вказано" end | |||
if not player_name or player_name == "" then | |||
local table_content = get_table_from_page("Гравці") | local table_content = get_table_from_page("Гравці") | ||
if not table_content then | if not table_content then return "Не вказано" end | ||
local | local cells = find_player_in_table(table_content, player_name) | ||
if not cells or #cells < 2 then return "Не вказано" end | |||
if | local raw = mw.text.trim(cells[2]) | ||
return "Не вказано" | if raw == "Відсутній" or raw == "-" or raw == "" then | ||
return "Не вказано" | |||
end | end | ||
return raw | |||
end | end | ||
function p.date_added(frame) | function p.date_added(frame) | ||
local player_name = frame.args.player | local player_name = frame.args.player | ||
if not player_name or player_name == "" then return "Лише Бог знає" end | |||
if not player_name or player_name == "" then | |||
local | local raw = find_player_in_table(get_table_from_page("Гравці"), player_name, 3) | ||
if not | if not raw or raw == "" or raw == "-" or raw == "Відсутній" then | ||
return "Лише Бог знає" | return "Лише Бог знає" | ||
end | end | ||
local | local day, month, year = mw.ustring.match(raw, "(%d+)%.(%d+)%.(%d+)") | ||
if | 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) | |||
return string.format("%s (%d днів)", raw, days_diff) | |||
end | end | ||
return "Лише Бог знає" | |||
return | |||
end | end | ||
function p.foundation(frame) | function p.foundation(frame) | ||
local player_name = frame.args.player or | local player_name = frame.args.player | ||
if not player_name or player_name == "" then return "0₴" end | |||
local raw = find_player_in_table(get_table_from_page("Фундація"), player_name, 2) | |||
if not raw or raw == "" or raw == "-" then return "0₴" end | |||
raw = mw.ustring.gsub(raw, "[^%d%s]", "") | |||
raw = mw.text.trim(raw) | |||
return (raw or "0") .. " ₴" | |||
end | end | ||
function p.prize_pool(frame) | function p.prize_pool(frame) | ||
local player_name = frame.args.player or | local player_name = frame.args.player | ||
if not player_name or player_name == "" then return "0₴" end | |||
local raw = find_player_in_table(get_table_from_page("Призовий_фонд"), player_name, 2) | |||
if not raw or raw == "" or raw == "-" then return "0₴" end | |||
raw = mw.ustring.gsub(raw, "[^%d%s]", "") | |||
raw = mw.text.trim(raw) | |||
return (raw or "0") .. " ₴" | |||
end | end | ||
function p.finalist(frame) | function p.finalist(frame) | ||
local player_name = frame.args.player or | local player_name = frame.args.player | ||
if not player_name or player_name == "" then return "0/9" end | |||
local raw = find_player_in_table(get_table_from_page("Фіналіст"), player_name, 2) | |||
if not raw or raw == "" or raw == "-" then return "0/9" end | |||
local | local number_only = mw.ustring.gsub(raw, "[^%d]", "") | ||
local count = tonumber(number_only) | |||
if | if count then | ||
return " | return string.format("%d/9", count) | ||
end | end | ||
return "0/9" | |||
end | end | ||
function p.foty_rating(frame) | function p.foty_rating(frame) | ||
local player_name = frame.args.player | local player_name = frame.args.player | ||
if not player_name or player_name == "" then return "—" end | |||
if not player_name or player_name == "" then | |||
local content = get_page_content("Період") | local content = get_page_content("Період") | ||
if not content then | if not content then return "—" end | ||
local foty_section = mw.ustring.match(content, "==+%s*Фінал Року%s*==+(.-)\n==") | local foty_section = mw.ustring.match(content, "==+%s*Фінал Року%s*==+(.-)\n==") | ||
| Рядок 442: | Рядок 299: | ||
end | end | ||
if not foty_section then | if not foty_section then return "—" end | ||
local table_start = mw.ustring.find(foty_section, "{|") | local table_start = mw.ustring.find(foty_section, "{|") | ||
local table_end = mw.ustring.find(foty_section, "|}", table_start) | local table_end = mw.ustring.find(foty_section, "|}", table_start) | ||
if not table_start or not table_end then | if not table_start or not table_end then return "—" end | ||
local table_content = mw.ustring.sub(foty_section, table_start, table_end + 1) | local table_content = mw.ustring.sub(foty_section, table_start, table_end + 1) | ||
local | local cells = find_player_in_table(table_content, player_name) | ||
if not | if not cells or #cells < 3 then return "—" end | ||
local place = | local place = strip_html_tags(cells[1]) or "—" | ||
local rating = | local rating = strip_html_tags(cells[3]) or "—" | ||
rating = mw.ustring.gsub(rating, "[^%d%-]", "") | rating = mw.ustring.gsub(rating, "[^%d%-]", "") | ||
rating = mw.text.trim(rating) | rating = mw.text.trim(rating) | ||
| Рядок 476: | Рядок 325: | ||
-- ================================================ | -- ================================================ | ||
-- | -- FETCHDATA3 (титули та нагороди) | ||
-- ================================================ | -- ================================================ | ||
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 | if value == "" then return nil | ||
elseif value == "1" then return "[[Файл:Gold.png|20px|link=]]" | |||
elseif value == "2" then return "[[Файл:Silver.png|20px|link=]]" | |||
elseif value == "3" then return "[[Файл:Bronze.png|20px|link=]]" | |||
elseif value == "4" then return "[[Файл:Finalist.png|20px|link=]]" | |||
elseif value == "S" or mw.ustring.match(value, "^S%d") then return "[[Файл:Star.png|20px|link=]]" | |||
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_link(header_name) | |||
local season_num = mw.ustring.match(header_name, "([А-Яа-яЁёІіЏїЄєҐґ']+) сезон %(фінал%)") | |||
if not season_num then | |||
season_num = mw.ustring.match(header_name, "([А-Яа-яЁёІіЇїЄєҐґ']+) сезон %(рейтинг%)") | |||
end | end | ||
local | 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 сезон. %s]]", clean_name, roman, type_text) | |||
end | |||
end | end | ||
return string.format("[[%s]]", header_name) | |||
local | end | ||
local function get_player_row(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 | 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 | end | ||
local table_content = | if #headers == 0 then return nil end | ||
local | |||
local cells = find_player_in_table(table_content, player_name) | |||
if not cells then return nil end | |||
return {headers = headers, cells = cells} | |||
end | |||
function p.titles(frame) | |||
local name = frame.args.player | |||
if not name or name == "" then return "''Відсутні''" end | |||
local titles_data = get_player_row("Титули", name) | |||
if not titles_data then return "''Відсутні''" end | |||
end | |||
local | local prize_data = get_player_row("Призові", name) | ||
if not prize_data then return error_output("Prize Data Missing", name) end | |||
local | local results = {} | ||
for | for i = 2, #titles_data.cells do | ||
local cell_value = titles_data.cells[i] | |||
local | 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 | if medal then | ||
local | 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 .. " ₴" | |||
if | |||
end | end | ||
end | end | ||
local date = tournament_dates[header] or "01.01.2023" | |||
local tournament_link = get_tournament_link(header) | |||
table.insert(results, { | |||
date = date, | |||
medal = medal, | |||
tournament = tournament_link, | |||
prize = prize_amount | |||
}) | |||
end | |||
end | |||
end | |||
if #results == 0 then return "''Відсутні''" end | |||
local table_html = { | |||
'{| class="wikitable sortable" style="font-size: 14.5px;"', | |||
'|-', | |||
'! style="" | Дата', | |||
'! style="text-align: left;" | Місце і турнір', | |||
'! style="text-align: left;" | Приз' | |||
} | |||
for _, result in ipairs(results) do | |||
table.insert(table_html, '|-') | |||
table.insert(table_html, string.format( | |||
'| style="width:80px; text-align:center;" | %s || style="text-align:left; padding-left:10px;" | %s %s || style="text-align:right;" | %s', | |||
result.date, result.medal, result.tournament, result.prize | |||
)) | |||
end | |||
table.insert(table_html, '|}') | |||
return table.concat(table_html, '\n') | |||
end | |||
-- ================================================ | |||
-- FETCHDATA4 (цікаві факти) | |||
-- ================================================ | |||
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 | |||
function p.facts(frame) | |||
local player_name = frame.args.player or frame.args[1] or mw.title.getCurrentTitle().text | |||
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 | ||
end | end | ||
if #player_facts > 0 then | |||
local block = string.format("==== %s ====\n", page_title) | |||
for _, fact in ipairs(player_facts) do | |||
block = block .. fact .. "\n" | |||
end | |||
table.insert(result_parts, string.format('<div style="margin-bottom: 20px;">\n%s</div>', block)) | |||
end | |||
end | |||
end | |||
if #result_parts == 0 then return "" end | |||
return table.concat(result_parts, "\n") | |||
end | |||
-- ================================================ | |||
-- FETCHDATA5 (записи ігор) | |||
-- ================================================ | |||
local function get_tournament_link_games(short_name, full_name) | |||
if short_name == "Фанова гра" then | |||
return "Фанова гра" | |||
elseif short_name == "Score Battle" then | |||
return "[[Score Open Battle I|Score Battle]]" | |||
elseif short_name and short_name ~= "" and full_name and full_name ~= "" then | |||
return "[[" .. full_name .. "|" .. short_name .. "]]" | |||
else | |||
return short_name or full_name or "Невідомо" | |||
end | |||
end | |||
local function get_player_role(player_name, cells) | |||
for i = 5, 10 do | |||
if cells[i] and clean_wikilinks(cells[i]) == player_name then | |||
return "Мирний" | |||
end | end | ||
end | end | ||
if | if cells[11] and clean_wikilinks(cells[11]) == player_name then | ||
return " | return "Шериф" | ||
end | end | ||
for i = 12, 13 do | |||
if cells[i] and clean_wikilinks(cells[i]) == player_name then | |||
return "Мафія" | |||
end | |||
end | |||
if cells[14] and clean_wikilinks(cells[14]) == player_name then | |||
return "Дон" | |||
end | |||
return "Невідомо" | |||
end | |||
local function get_player_result(role, game_result) | |||
if not game_result or game_result == "" then return "Невідомо" end | |||
game_result = mw.text.trim(game_result) | |||
if game_result == "Місто" or game_result == "Мирні" then | |||
return (role == "Мирний" or role == "Шериф") and "Перемога" or "Поразка" | |||
end | |||
if game_result == "Мафія" then | |||
return (role == "Мафія" or role == "Дон") and "Перемога" or "Поразка" | |||
end | |||
return "Невідомо" | |||
end | |||
local function get_player_games_list(player_name) | |||
local table_content = get_table_from_page("Ігри") | |||
if not table_content then return nil end | |||
local rows = parse_table_rows(table_content) | |||
local games = {} | |||
for _, row in ipairs(rows) do | |||
local cells = parse_row_cells(row) | |||
local | local player_in_game = false | ||
for i = 5, 14 do | |||
if cells[i] and clean_wikilinks(cells[i]) == player_name then | |||
player_in_game = true | |||
break | |||
end | |||
end | end | ||
if player_in_game and #cells >= 15 then | |||
local role = get_player_role(player_name, cells) | |||
local result = get_player_result(role, cells[15]) | |||
table.insert(games, { | |||
tournament = cells[3] or "", | |||
short = cells[4] or "", | |||
role = role, | |||
result = result, | |||
link = cells[16] or "" | |||
}) | |||
end | end | ||
end | end | ||
return games | |||
return | |||
end | end | ||
function p. | function p.player_games(frame) | ||
local player_name = frame.args.player | local player_name = frame.args.player | ||
if not player_name or player_name == "" then | if not player_name or player_name == "" then | ||
return " | return error_output("No Player Name", "") | ||
end | end | ||
local | local games = get_player_games_list(player_name) | ||
if not | if not games then | ||
return " | return error_output("Cannot Load Games", "Ігри") | ||
end | end | ||
if #games == 0 then | |||
return "''Ігор не знайдено''" | |||
return " | |||
end | end | ||
local | local htmlTable = mw.html.create('table') | ||
:addClass('wikitable sortable') | |||
:css('width', '100%') | |||
:css('font-size', '14.5px') | |||
local | local headerRow = htmlTable:tag('tr') | ||
headerRow:tag('th'):wikitext('Турнір') | |||
headerRow:tag('th'):wikitext('Роль') | |||
headerRow:tag('th'):wikitext('Результат') | |||
headerRow:tag('th'):wikitext('Запис') | |||
for _, game in ipairs(games) do | |||
for _, | local row = htmlTable:tag('tr') | ||
if | |||
row:tag('td'):css('text-align', 'center'):css('padding', '8px') | |||
:wikitext(get_tournament_link_games(game.short, game.tournament)) | |||
row:tag('td'):css('text-align', 'center'):css('padding', '8px'):wikitext(game.role) | |||
local resultCell = row:tag('td'):css('text-align', 'center'):css('padding', '8px') | |||
if game.result == "Перемога" then | |||
resultCell:tag('span'):css('color', '#4caf50'):css('font-weight', 'normal'):wikitext('Перемога') | |||
elseif game.result == "Поразка" then | |||
resultCell:tag('span'):css('color', 'indianred'):css('font-weight', 'normal'):wikitext('Поразка') | |||
else | |||
resultCell:wikitext(game.result) | |||
end | |||
local linkCell = row:tag('td'):css('text-align', 'center'):css('padding', '8px') | |||
if game.link and game.link ~= "" then | |||
linkCell:wikitext('<span class="game-record-btn">[' .. game.link .. ' ▶︎]</span>') | |||
end | end | ||
end | end | ||
return tostring( | return tostring(htmlTable) | ||
end | |||
function p.games_count_records(frame) | |||
local player_name = frame.args.player | |||
if not player_name or player_name == "" then return "0" end | |||
local games = get_player_games_list(player_name) | |||
return games and tostring(#games) or "0" | |||
end | end | ||
-- ================================================ | -- ================================================ | ||
-- | -- FETCHDATA6 (досягнення в сезонах) | ||
-- ================================================ | -- ================================================ | ||
function | local function get_season_data(season_number, player_name) | ||
local | local season_names = { | ||
[1] = "Перший сезон", [2] = "Другий сезон", [3] = "Третій сезон", | |||
[4] = "Четвертий сезон", [5] = "П'ятий сезон", [6] = "Шостий сезон", | |||
[7] = "Сьомий сезон", [8] = "Восьмий сезон", [9] = "Дев'ятий сезон" | |||
} | |||
local season_name = season_names[season_number] | |||
if not season_name then return nil end | |||
local content = get_page_content(season_name) | |||
if not content then return nil end | |||
local rating_section = mw.ustring.match(content, "==+%s*Рейтинг%s*==+(.-)\n==") | |||
if not rating_section then | |||
rating_section = mw.ustring.match(content, "==+%s*Рейтинг%s*==+(.*)") | |||
end | end | ||
if not rating_section then return nil end | |||
local | local table_start = mw.ustring.find(rating_section, "{|") | ||
local | local table_end = mw.ustring.find(rating_section, "|}", table_start) | ||
if not table_start or not table_end then return nil end | |||
local table_content = mw.ustring.sub(rating_section, table_start, table_end + 1) | |||
local current_row = {} | |||
local all_rows = {} | |||
} | |||
for | for line in mw.ustring.gmatch(table_content .. "\n", "([^\n]*)\n") do | ||
line = mw.text.trim(line) | |||
if | if line == "|-" then | ||
if #current_row > 0 then | |||
if | table.insert(all_rows, current_row) | ||
end | end | ||
current_row = {} | |||
elseif mw.ustring.match(line, "^|[^-}]") then | |||
local cell_content = mw.ustring.gsub(line, "^|%s*", "") | |||
table.insert(current_row, cell_content) | |||
end | |||
end | |||
if #current_row > 0 then | |||
table.insert(all_rows, current_row) | |||
end | |||
for _, row in ipairs(all_rows) do | |||
if #row >= 5 then | |||
local player_cell = clean_wikilinks(row[2]) | |||
if | if player_cell == player_name then | ||
return { | |||
place = mw.text.trim(row[1]), | |||
points = mw.text.trim(row[3]), | |||
games = mw.text.trim(row[4]), | |||
winrate = mw.text.trim(row[5]) | |||
} | |||
end | end | ||
end | end | ||
end | end | ||
if | return nil | ||
return "'' | end | ||
function p.season_achievements(frame) | |||
local player_name = frame.args.player | |||
if not player_name or player_name == "" then | |||
return "<span style='color:red;'>Ім'я гравця не вказано</span>" | |||
end | end | ||
local | local htmlTable = mw.html.create('table') | ||
:addClass('wikitable sortable') | |||
:css('width', '100%') | |||
:css('font-size', '14.5px') | |||
local headerRow = htmlTable:tag('tr') | |||
headerRow:tag('th'):wikitext('Сезон') | |||
headerRow:tag('th'):wikitext('Місце') | |||
headerRow:tag('th'):wikitext('Бали') | |||
headerRow:tag('th'):wikitext('% перемог') | |||
headerRow:tag('th'):wikitext('Ігор') | |||
local season_links = { | |||
[1] = "[[Перший сезон#Рейтинг|01 сезон]]", | |||
[2] = "[[Другий сезон#Рейтинг|02 сезон]]", | |||
[3] = "[[Третій сезон#Рейтинг|03 сезон]]", | |||
[4] = "[[Четвертий сезон#Рейтинг|04 сезон]]", | |||
[5] = "[[П'ятий сезон#Рейтинг|05 сезон]]", | |||
[6] = "[[Шостий сезон#Рейтинг|06 сезон]]", | |||
[7] = "[[Сьомий сезон#Рейтинг|07 сезон]]", | |||
[8] = "[[Восьмий сезон#Рейтинг|08 сезон]]", | |||
[9] = "[[Дев'ятий сезон#Рейтинг|09 сезон]]" | |||
} | |||
for | for season = 1, 9 do | ||
local data = get_season_data(season, player_name) | |||
local row = htmlTable:tag('tr') | |||
row:tag('td'):css('text-align', 'center'):css('padding', '8px'):wikitext(season_links[season]) | |||
if data then | |||
row:tag('td'):css('text-align', 'center'):css('padding', '8px'):wikitext(data.place) | |||
row:tag('td'):css('text-align', 'center'):css('padding', '8px'):wikitext(data.points) | |||
row:tag('td'):css('text-align', 'center'):css('padding', '8px'):wikitext(data.winrate) | |||
row:tag('td'):css('text-align', 'center'):css('padding', '8px'):wikitext(data.games) | |||
else | |||
for i = 1, 4 do | |||
row:tag('td'):css('text-align', 'center'):css('padding', '8px'):css('color', '#666'):wikitext('-') | |||
end | |||
end | |||
end | end | ||
return tostring(htmlTable) | |||
return | |||
end | end | ||
return p | return p | ||