6395
редагувань
Admin (обговорення | внесок) Немає опису редагування |
Admin (обговорення | внесок) Немає опису редагування |
||
| Рядок 2: | Рядок 2: | ||
-- ================================================ | -- ================================================ | ||
-- КЕШУВАННЯ | -- КЕШУВАННЯ | ||
-- ================================================ | -- ================================================ | ||
| Рядок 12: | Рядок 12: | ||
return page_cache[page_name] | return page_cache[page_name] | ||
end | end | ||
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 | ||
| Рядок 18: | Рядок 18: | ||
return nil | return nil | ||
end | end | ||
local content = title:getContent() | local content = title:getContent() | ||
page_cache[page_name] = content | page_cache[page_name] = content | ||
| Рядок 28: | Рядок 28: | ||
return table_cache[page_name] | return table_cache[page_name] | ||
end | end | ||
local content = get_page_content(page_name) | local content = get_page_content(page_name) | ||
if not content then | if not content then | ||
table_cache[page_name] = nil | table_cache[page_name] = nil | ||
return nil | return nil | ||
end | 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 | if not table_start or not table_end then | ||
table_cache[page_name] = nil | table_cache[page_name] = nil | ||
return nil | return nil | ||
end | 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 | ||
| Рядок 49: | Рядок 49: | ||
-- ================================================ | -- ================================================ | ||
-- УТИЛІТИ | -- УТИЛІТИ | ||
-- ================================================ | -- ================================================ | ||
local function error_output(context, error_details) | local function error_output(context, error_details) | ||
local safe_details = error_details or "N/A" | local safe_details = error_details or "N/A" | ||
return string.format("<span style='color:red; font-weight:bold;'>[Error: %s. Details: %s]</span>", | return string.format("<span style='color:red; font-weight:bold;'>[Error: %s. Details: %s]</span>", | ||
context or "Unknown", safe_details) | context or "Unknown", safe_details) | ||
end | end | ||
-- ШВИДКА ВЕРСІЯ: патерни тільки з ASCII-символів, тому string.gsub безпечний | |||
local function clean_wikilinks(text) | local function clean_wikilinks(text) | ||
if not text then return nil end | if not text then return nil end | ||
text = | text = string.gsub(text, "%[%[([^%]|]+)|([^%]]+)%]%]", "%2") | ||
text = | text = string.gsub(text, "%[%[([^%]]+)%]%]", "%1") | ||
return mw.text.trim(text) | return mw.text.trim(text) | ||
end | end | ||
| Рядок 86: | Рядок 87: | ||
local function parse_row_cells(row) | local function parse_row_cells(row) | ||
local cells = {} | local cells = {} | ||
for line in mw.ustring.gmatch(row, "[^\n]+") do | for line in mw.ustring.gmatch(row, "[^\n]+") do | ||
line = mw.text.trim(line) | line = mw.text.trim(line) | ||
if line ~= "|-" and line ~= "" then | if line ~= "|-" and line ~= "" then | ||
line = mw.ustring.gsub(line, "^|%s*", "") | line = mw.ustring.gsub(line, "^|%s*", "") | ||
if line ~= "" then | if line ~= "" then | ||
table.insert(cells, line) | table.insert(cells, line) | ||
| Рядок 98: | Рядок 99: | ||
end | end | ||
end | end | ||
return cells | return cells | ||
end | end | ||
| Рядок 104: | Рядок 105: | ||
local function find_player_in_table(table_content, player_name, column_index) | 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 | ||
local escaped = mw.ustring.gsub(player_name, "([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1") | local escaped = mw.ustring.gsub(player_name, "([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1") | ||
local player_pattern = "%[%[" .. escaped .. "%]%]" | local player_pattern = "%[%[" .. escaped .. "%]%]" | ||
local rows = parse_table_rows(table_content) | local rows = parse_table_rows(table_content) | ||
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 | ||
| Рядок 119: | Рядок 120: | ||
end | end | ||
end | end | ||
return nil | return nil | ||
end | end | ||
-- ================================================ | -- ================================================ | ||
-- | -- SEASON RESULT | ||
-- ================================================ | -- ================================================ | ||
| Рядок 130: | Рядок 131: | ||
local season = frame.args.season | local season = frame.args.season | ||
local player = frame.args.player | local player = frame.args.player | ||
local season_titles = { | local season_titles = { | ||
"Перший сезон", "Другий сезон", "Третій сезон", | "Перший сезон", "Другий сезон", "Третій сезон", | ||
"Четвертий сезон", "П'ятий сезон", "Шостий сезон", | "Четвертий сезон", "П'ятий сезон", "Шостий сезон", | ||
"Сьомий сезон", "Восьмий сезон", "Дев'ятий сезон" | "Сьомий сезон", "Восьмий сезон", "Дев'ятий сезон" | ||
} | } | ||
local season_title = season_titles[tonumber(season)] | local season_title = season_titles[tonumber(season)] | ||
if not season_title then return "??" end | if not season_title then return "??" end | ||
local content = get_page_content(season_title) | local content = get_page_content(season_title) | ||
if not content then return "??" end | if not content then return "??" end | ||
local rating_section = mw.ustring.match(content, "==%s*Рейтинг%s*==.-{|%s*class%s*=%s*\"wikitable sortable\"(.-)|}") | local rating_section = mw.ustring.match(content, "==%s*Рейтинг%s*==.-{|%s*class%s*=%s*\"wikitable sortable\"(.-)|}") | ||
if not rating_section then return "--" end | if not rating_section then return "--" end | ||
local pattern = "|%s*(%d+)%s*|%s*%[%[" .. mw.ustring.gsub(player, "([%(%)%.%-%+%[%]])", "%%%1") .. "%]%]" | local pattern = "|%s*(%d+)%s*|%s*%[%[" .. mw.ustring.gsub(player, "([%(%)%.%-%+%[%]])", "%%%1") .. "%]%]" | ||
local direct_pattern = "|%s*(%d+)%s*|%s*" .. mw.ustring.gsub(player, "([%(%)%.%-%+%[%]])", "%%%1") .. "%s*" | 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) | local rank = mw.ustring.match(rating_section, pattern) or mw.ustring.match(rating_section, direct_pattern) | ||
return rank or "--" | return rank or "--" | ||
end | end | ||
-- ================================================ | -- ================================================ | ||
-- | -- БАЗОВА СТАТИСТИКА | ||
-- ================================================ | -- ================================================ | ||
| Рядок 161: | Рядок 162: | ||
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 "0" end | ||
local result = find_player_in_table(get_table_from_page("Статистика"), player_name, 2) | local result = find_player_in_table(get_table_from_page("Статистика"), player_name, 2) | ||
return result or "0" | return result or "0" | ||
| Рядок 169: | Рядок 170: | ||
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 "0" end | ||
local result = find_player_in_table(get_table_from_page("Статистика"), player_name, 3) | local result = find_player_in_table(get_table_from_page("Статистика"), player_name, 3) | ||
return result or "0" | return result or "0" | ||
| Рядок 177: | Рядок 178: | ||
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 "0" end | ||
local result = find_player_in_table(get_table_from_page("Статистика"), player_name, 4) | local result = find_player_in_table(get_table_from_page("Статистика"), player_name, 4) | ||
return result or "0" | return result or "0" | ||
| Рядок 185: | Рядок 186: | ||
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 "0%" end | ||
local win_rate = find_player_in_table(get_table_from_page("Статистика"), player_name, 5) | local win_rate = find_player_in_table(get_table_from_page("Статистика"), player_name, 5) | ||
if not win_rate then return "0%" end | if not win_rate then return "0%" end | ||
local rate_num = tonumber(mw.ustring.match(win_rate, "([%d%.]+)")) | local rate_num = tonumber(mw.ustring.match(win_rate, "([%d%.]+)")) | ||
if not rate_num then return win_rate end | if not rate_num then return win_rate end | ||
local color = "#4caf50" | local color = "#4caf50" | ||
if rate_num < 40 then | if rate_num < 40 then | ||
| Рядок 198: | Рядок 199: | ||
color = "orange" | color = "orange" | ||
end | end | ||
if not mw.ustring.find(win_rate, "%%") then | if not mw.ustring.find(win_rate, "%%") then | ||
win_rate = win_rate .. "%" | win_rate = win_rate .. "%" | ||
end | end | ||
return string.format('<span style="color:%s;">%s</span>', color, win_rate) | return string.format('<span style="color:%s;">%s</span>', color, win_rate) | ||
end | end | ||
| Рядок 209: | Рядок 210: | ||
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 return "Не вказано" end | ||
local table_content = get_table_from_page("Гравці") | local table_content = get_table_from_page("Гравці") | ||
if not table_content then return "Не вказано" end | if not table_content then return "Не вказано" end | ||
local cells = find_player_in_table(table_content, player_name) | local cells = find_player_in_table(table_content, player_name) | ||
if not cells or #cells < 2 then return "Не вказано" end | if not cells or #cells < 2 then return "Не вказано" end | ||
local raw = mw.text.trim(cells[2]) | local raw = mw.text.trim(cells[2]) | ||
if raw == "Відсутній" or raw == "-" or raw == "" then | if raw == "Відсутній" or raw == "-" or raw == "" then | ||
return "Не вказано" | return "Не вказано" | ||
end | end | ||
return raw | return raw | ||
end | end | ||
| Рядок 227: | Рядок 228: | ||
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 return "Лише Бог знає" end | ||
local raw = find_player_in_table(get_table_from_page("Гравці"), player_name, 3) | local raw = find_player_in_table(get_table_from_page("Гравці"), player_name, 3) | ||
if not raw or raw == "" or raw == "-" or raw == "Відсутній" then | if not raw or raw == "" or raw == "-" or raw == "Відсутній" then | ||
return "Лише Бог знає" | return "Лише Бог знає" | ||
end | end | ||
local day, month, year = mw.ustring.match(raw, "(%d+)%.(%d+)%.(%d+)") | local day, month, year = mw.ustring.match(raw, "(%d+)%.(%d+)%.(%d+)") | ||
if day and month and year then | if day and month and year then | ||
local end_date = os.time({year=2024, month=12, day=1}) | 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 start_date = os.time({year=tonumber(year), month=tonumber(month), day=tonumber(day)}) | ||
local days_diff = math.floor((end_date - start_date) / 86400) | local days_diff = math.floor((end_date - start_date) / 86400) | ||
return string.format("%s (%d днів)", raw, days_diff) | return string.format("%s (%d днів)", raw, days_diff) | ||
end | end | ||
return "Лише Бог знає" | return "Лише Бог знає" | ||
end | end | ||
| Рядок 250: | Рядок 251: | ||
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 "0₴" end | ||
local raw = find_player_in_table(get_table_from_page("Фундація"), player_name, 2) | local raw = find_player_in_table(get_table_from_page("Фундація"), player_name, 2) | ||
if not raw or raw == "" or raw == "-" then return "0₴" end | if not raw or raw == "" or raw == "-" then return "0₴" end | ||
raw = mw.ustring.gsub(raw, "[^%d%s]", "") | raw = mw.ustring.gsub(raw, "[^%d%s]", "") | ||
raw = mw.text.trim(raw) | raw = mw.text.trim(raw) | ||
return (raw or "0") .. " ₴" | return (raw or "0") .. " ₴" | ||
end | end | ||
| Рядок 264: | Рядок 265: | ||
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 "0₴" end | ||
local raw = find_player_in_table(get_table_from_page("Призовий_фонд"), player_name, 2) | local raw = find_player_in_table(get_table_from_page("Призовий_фонд"), player_name, 2) | ||
if not raw or raw == "" or raw == "-" then return "0₴" end | if not raw or raw == "" or raw == "-" then return "0₴" end | ||
raw = mw.ustring.gsub(raw, "[^%d%s]", "") | raw = mw.ustring.gsub(raw, "[^%d%s]", "") | ||
raw = mw.text.trim(raw) | raw = mw.text.trim(raw) | ||
return (raw or "0") .. " ₴" | return (raw or "0") .. " ₴" | ||
end | end | ||
| Рядок 278: | Рядок 279: | ||
local player_name = frame.args.player | local player_name = frame.args.player | ||
if not player_name or player_name == "" then return "0/9" end | 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) | 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 | if not raw or raw == "" or raw == "-" then return "0/9" end | ||
local number_only = mw.ustring.gsub(raw, "[^%d]", "") | local number_only = mw.ustring.gsub(raw, "[^%d]", "") | ||
local count = tonumber(number_only) | local count = tonumber(number_only) | ||
if count then | if count then | ||
return string.format("%d/9", count) | return string.format("%d/9", count) | ||
end | end | ||
return "0/9" | return "0/9" | ||
end | end | ||
| Рядок 296: | Рядок 297: | ||
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 return "—" end | ||
local content = get_page_content("Період") | local content = get_page_content("Період") | ||
if not content then return "—" end | 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==") | ||
if not foty_section then | if not foty_section then | ||
foty_section = mw.ustring.match(content, "==+%s*Фінал Року%s*==+(.*)") | foty_section = mw.ustring.match(content, "==+%s*Фінал Року%s*==+(.*)") | ||
end | end | ||
if not foty_section then return "—" end | 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 return "—" end | 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 cells = find_player_in_table(table_content, player_name) | local cells = find_player_in_table(table_content, player_name) | ||
if not cells or #cells < 3 then return "—" end | if not cells or #cells < 3 then return "—" end | ||
local place = strip_html_tags(cells[1]) or "—" | local place = strip_html_tags(cells[1]) or "—" | ||
local rating = strip_html_tags(cells[3]) or "—" | 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) | ||
if rating and rating ~= "" then | if rating and rating ~= "" then | ||
return rating .. " (" .. place .. " місце)" | return rating .. " (" .. place .. " місце)" | ||
end | end | ||
return "—" | return "—" | ||
end | end | ||
-- ================================================ | -- ================================================ | ||
-- | -- ТИТУЛИ ТА НАГОРОДИ | ||
-- ================================================ | -- ================================================ | ||
| Рядок 379: | Рядок 380: | ||
if not value or value == "" or value == " " then return nil end | if not value or value == "" or value == " " then return nil end | ||
value = mw.text.trim(value) | value = mw.text.trim(value) | ||
if value == "" then return nil | if value == "" then return nil | ||
elseif value == "1" then return "[[Файл:Gold.png|20px|link=]]" | elseif value == "1" then return "[[Файл:Gold.png|20px|link=]]" | ||
| Рядок 400: | Рядок 401: | ||
season_num = mw.ustring.match(header_name, "([А-Яа-яЁёІіЇїЄєҐґ']+) сезон %(рейтинг%)") | season_num = mw.ustring.match(header_name, "([А-Яа-яЁёІіЇїЄєҐґ']+) сезон %(рейтинг%)") | ||
end | end | ||
if season_num then | if season_num then | ||
local season_map = { | local season_map = { | ||
| Рядок 407: | Рядок 408: | ||
["Сьомий"] = 7, ["Восьмий"] = 8, ["Дев'ятий"] = 9 | ["Сьомий"] = 7, ["Восьмий"] = 8, ["Дев'ятий"] = 9 | ||
} | } | ||
local season_number = season_map[season_num] | local season_number = season_map[season_num] | ||
if season_number then | if season_number then | ||
| Рядок 415: | Рядок 416: | ||
clean_name = mw.ustring.gsub(clean_name, "%s*%(рейтинг%)%s*", "") | clean_name = mw.ustring.gsub(clean_name, "%s*%(рейтинг%)%s*", "") | ||
clean_name = mw.text.trim(clean_name) | clean_name = mw.text.trim(clean_name) | ||
return string.format("[[%s|%s сезон. %s]]", clean_name, roman, type_text) | return string.format("[[%s|%s сезон. %s]]", clean_name, roman, type_text) | ||
end | end | ||
end | end | ||
return string.format("[[%s]]", header_name) | return string.format("[[%s]]", header_name) | ||
end | end | ||
| Рядок 426: | Рядок 427: | ||
local table_content = get_table_from_page(page_title) | local table_content = get_table_from_page(page_title) | ||
if not table_content then return nil end | if not table_content then return nil end | ||
local first_row = mw.ustring.match(table_content, "{|[^\n]*\n!(.-)[\n]") | local first_row = mw.ustring.match(table_content, "{|[^\n]*\n!(.-)[\n]") | ||
local headers = {} | local headers = {} | ||
if first_row then | if first_row then | ||
for header in mw.ustring.gmatch(first_row, "([^|]+)") do | for header in mw.ustring.gmatch(first_row, "([^|]+)") do | ||
| Рядок 438: | Рядок 439: | ||
end | end | ||
end | end | ||
if #headers == 0 then return nil end | if #headers == 0 then return nil end | ||
local cells = find_player_in_table(table_content, player_name) | local cells = find_player_in_table(table_content, player_name) | ||
if not cells then return nil end | if not cells then return nil end | ||
return {headers = headers, cells = cells} | return {headers = headers, cells = cells} | ||
end | end | ||
function p.player_image(frame) | function p.player_image(frame) | ||
| Рядок 455: | Рядок 452: | ||
local player_file = "Player_" .. nickname .. ".png" | local player_file = "Player_" .. nickname .. ".png" | ||
local placeholder = "MCC_Placeholder.png" | local placeholder = "MCC_Placeholder.png" | ||
local title = mw.title.new("File:" .. player_file) | local title = mw.title.new("File:" .. player_file) | ||
local file_to_use | local file_to_use | ||
if title and title.exists then | if title and title.exists then | ||
| Рядок 464: | Рядок 461: | ||
file_to_use = placeholder | file_to_use = placeholder | ||
end | end | ||
return string.format("[[File:%s|none|alt=Фотографія гравця|center|360px]]", file_to_use) | return string.format("[[File:%s|none|alt=Фотографія гравця|center|360px]]", file_to_use) | ||
end | end | ||
| Рядок 471: | Рядок 468: | ||
local name = frame.args.player | local name = frame.args.player | ||
if not name or name == "" then return "''Відсутні''" end | if not name or name == "" then return "''Відсутні''" end | ||
local titles_data = get_player_row("Титули", name) | local titles_data = get_player_row("Титули", name) | ||
if not titles_data then return "''Відсутні''" end | if not titles_data then return "''Відсутні''" end | ||
local prize_data = get_player_row("Призові", name) | local prize_data = get_player_row("Призові", name) | ||
if not prize_data then return error_output("Prize Data Missing", name) end | if not prize_data then return error_output("Prize Data Missing", name) end | ||
local results = {} | local results = {} | ||
for i = 2, #titles_data.cells do | for i = 2, #titles_data.cells do | ||
local cell_value = titles_data.cells[i] | local cell_value = titles_data.cells[i] | ||
local header = titles_data.headers[i] | local header = titles_data.headers[i] | ||
local prize_value = prize_data.cells[i] | local prize_value = prize_data.cells[i] | ||
if cell_value and cell_value ~= "" and cell_value ~= "-" and header then | if cell_value and cell_value ~= "" and cell_value ~= "-" and header then | ||
local medal = get_medal_icon(cell_value) | local medal = get_medal_icon(cell_value) | ||
if medal then | if medal then | ||
local prize_amount = "0 ₴" | local prize_amount = "0 ₴" | ||
if prize_value and prize_value ~= "" and prize_value ~= "-" then | if prize_value and prize_value ~= "" and prize_value ~= "-" then | ||
prize_value = mw.ustring.gsub(prize_value, "₴", "") | prize_value = mw.ustring.gsub(prize_value, "₴", "") | ||
| Рядок 498: | Рядок 495: | ||
end | end | ||
end | end | ||
local date = tournament_dates[header] or "01.01.2023" | local date = tournament_dates[header] or "01.01.2023" | ||
local tournament_link = get_tournament_link(header) | local tournament_link = get_tournament_link(header) | ||
table.insert(results, { | table.insert(results, { | ||
date = date, | date = date, | ||
| Рядок 511: | Рядок 508: | ||
end | end | ||
end | end | ||
if #results == 0 then return "''Відсутні''" end | if #results == 0 then return "''Відсутні''" end | ||
local table_html = { | local table_html = { | ||
'{| class="wikitable sortable" style="font-size: 14.5px;"', | '{| class="wikitable sortable" style="font-size: 14.5px;"', | ||
| Рядок 521: | Рядок 518: | ||
'! style="text-align: left;" | Приз' | '! style="text-align: left;" | Приз' | ||
} | } | ||
for _, result in ipairs(results) do | for _, result in ipairs(results) do | ||
table.insert(table_html, '|-') | table.insert(table_html, '|-') | ||
| Рядок 529: | Рядок 526: | ||
)) | )) | ||
end | end | ||
table.insert(table_html, '|}') | table.insert(table_html, '|}') | ||
return table.concat(table_html, '\n') | return table.concat(table_html, '\n') | ||
| Рядок 535: | Рядок 532: | ||
-- ================================================ | -- ================================================ | ||
-- | -- ЦІКАВІ ФАКТИ | ||
-- ================================================ | -- ================================================ | ||
| Рядок 554: | Рядок 551: | ||
local content = get_page_content(page_title) | local content = get_page_content(page_title) | ||
if not content then return nil end | if not content then return nil end | ||
local section_start = mw.ustring.find(content, "==%s*[Цц]ікаві%s*[Фф]акти%s*==") | local section_start = mw.ustring.find(content, "==%s*[Цц]ікаві%s*[Фф]акти%s*==") | ||
if not section_start then return nil end | if not section_start then return nil end | ||
local section_end = mw.ustring.find(content, "\n==[^=]", section_start + 1) | local section_end = mw.ustring.find(content, "\n==[^=]", section_start + 1) | ||
local section_content | local section_content | ||
if section_end then | if section_end then | ||
| Рядок 566: | Рядок 563: | ||
section_content = mw.ustring.sub(content, section_start) | section_content = mw.ustring.sub(content, section_start) | ||
end | end | ||
return section_content | return section_content | ||
end | end | ||
| Рядок 574: | Рядок 571: | ||
local pattern1 = "%[%[" .. escaped_name .. "%]%]" | local pattern1 = "%[%[" .. escaped_name .. "%]%]" | ||
local pattern2 = "%[%[" .. escaped_name .. "|[^%]]+%]%]" | local pattern2 = "%[%[" .. escaped_name .. "|[^%]]+%]%]" | ||
return mw.ustring.find(fact, pattern1) or mw.ustring.find(fact, pattern2) | return mw.ustring.find(fact, pattern1) or mw.ustring.find(fact, pattern2) | ||
end | end | ||
| Рядок 588: | Рядок 585: | ||
function p.facts(frame) | function p.facts(frame) | ||
local player_name = frame.args.player or frame.args[1] or mw.title.getCurrentTitle().text | local player_name = frame.args.player or frame.args[1] or mw.title.getCurrentTitle().text | ||
local result_parts = {} | local result_parts = {} | ||
for _, page_title in ipairs(pages_to_search) do | for _, page_title in ipairs(pages_to_search) do | ||
local section = get_facts_section(page_title) | local section = get_facts_section(page_title) | ||
if section then | if section then | ||
local facts = extract_facts(section) | local facts = extract_facts(section) | ||
local player_facts = {} | local player_facts = {} | ||
for _, fact in ipairs(facts) do | for _, fact in ipairs(facts) do | ||
if fact_contains_player(fact, player_name) then | if fact_contains_player(fact, player_name) then | ||
| Рядок 603: | Рядок 600: | ||
end | end | ||
end | end | ||
if #player_facts > 0 then | if #player_facts > 0 then | ||
local block = string.format("==== %s ====\n", page_title) | local block = string.format("==== %s ====\n", page_title) | ||
| Рядок 613: | Рядок 610: | ||
end | end | ||
end | end | ||
if #result_parts == 0 then return "" end | if #result_parts == 0 then return "" end | ||
return table.concat(result_parts, "\n") | return table.concat(result_parts, "\n") | ||
end | end | ||
-- ================================================ | -- ================================================ | ||
-- | -- ЗАПИСИ ІГОР | ||
-- ================================================ | -- ================================================ | ||
| Рядок 627: | Рядок 624: | ||
return "Невідомо" | return "Невідомо" | ||
end | end | ||
if short_name == "Фанова гра" then | if short_name == "Фанова гра" then | ||
return "Фанова гра" | return "Фанова гра" | ||
end | end | ||
if full_name then | if full_name then | ||
full_name = clean_wikilinks(full_name) | full_name = clean_wikilinks(full_name) | ||
end | end | ||
if full_name and full_name ~= "" and full_name ~= short_name then | if full_name and full_name ~= "" and full_name ~= short_name then | ||
return "[[" .. full_name .. "|" .. short_name .. "]]" | return "[[" .. full_name .. "|" .. short_name .. "]]" | ||
| Рядок 643: | Рядок 640: | ||
end | end | ||
local function | local function parse_games_row_cells(row) | ||
local cells = {} | |||
row = string.gsub(row, "^%s*|%s*", "") | |||
for cell in string.gmatch(row .. "||", "(.-)%s*||%s*") do | |||
table.insert(cells, mw.text.trim(cell)) | |||
end | |||
return cells | |||
end | |||
-- Кеш: таблиця розбирається ОДИН раз на сторінку | |||
local games_rows_cache = nil | |||
local player_games_cache = {} | |||
local function get_games_rows() | |||
if games_rows_cache then return games_rows_cache end | |||
local table_content = get_table_from_page("Ігри") | |||
if not table_content then return nil end | |||
local rows = {} | local rows = {} | ||
for row in string.gmatch(table_content, "|-\n([^\n]+)") do | |||
for row in | if not string.match(row, "^%s*!") then | ||
if not | local cells = parse_games_row_cells(row) | ||
table.insert(rows, | if #cells >= 17 then | ||
local names = {} | |||
for i = 6, 15 do | |||
names[i] = clean_wikilinks(cells[i]) | |||
end | |||
table.insert(rows, { cells = cells, names = names }) | |||
end | |||
end | end | ||
end | end | ||
games_rows_cache = rows | |||
return rows | return rows | ||
end | end | ||
| Рядок 671: | Рядок 680: | ||
local res = cells[16] | local res = cells[16] | ||
if not res or mw.text.trim(res) == "" then return true end | if not res or mw.text.trim(res) == "" then return true end | ||
return | return string.find(res, "?", 1, true) ~= nil | ||
end | end | ||
local function get_player_role(player_name, | local function get_player_role(player_name, entry) | ||
if has_unknown_roles(cells) then return "—" end | if has_unknown_roles(entry.cells) then return "—" end | ||
local names = entry.names | |||
for i = 6, 11 do | for i = 6, 11 do | ||
if | if names[i] == player_name then return "Мир" end | ||
end | end | ||
if names[12] == player_name then return "Шер" end | |||
if | |||
for i = 13, 14 do | for i = 13, 14 do | ||
if | if names[i] == player_name then return "Маф" end | ||
end | end | ||
if names[15] == player_name then return "Дон" end | |||
if | |||
return "—" | return "—" | ||
end | end | ||
| Рядок 708: | Рядок 704: | ||
game_result = mw.text.trim(game_result) | game_result = mw.text.trim(game_result) | ||
if string.find(game_result, "?", 1, true) then return "—" end | |||
if | |||
if game_result == "Місто" or game_result == "Мирні" then | if game_result == "Місто" or game_result == "Мирні" then | ||
| Рядок 723: | Рядок 718: | ||
local function get_player_games_list(player_name) | local function get_player_games_list(player_name) | ||
local | if player_games_cache[player_name] then | ||
if not | return player_games_cache[player_name] | ||
end | |||
local rows = get_games_rows() | |||
if not rows then return nil end | |||
local games = {} | local games = {} | ||
for _, | for _, entry in ipairs(rows) do | ||
local | local found = false | ||
for i = 6, 15 do | |||
if entry.names[i] == player_name then | |||
found = true | |||
break | |||
end | end | ||
end | |||
if found then | |||
local cells = entry.cells | |||
local role = get_player_role(player_name, entry) | |||
local result = get_player_result(role, cells[16]) | |||
local time_raw = cells[5] or "" | |||
local time_formatted = time_raw | |||
local minutes, seconds = string.match(time_raw, "(%d+)%s*хв%s*(%d+)%s*с") | |||
if minutes and seconds then | |||
time_formatted = minutes .. ":" .. string.format("%02d", tonumber(seconds)) | |||
end | end | ||
table.insert(games, { | |||
short = cells[3] or "", | |||
tournament = cells[4] or "", | |||
time = time_formatted, | |||
role = role, | |||
result = result, | |||
link = cells[17] or "" | |||
}) | |||
end | end | ||
end | end | ||
player_games_cache[player_name] = games | |||
return games | return games | ||
end | end | ||
| Рядок 773: | Рядок 768: | ||
return error_output("No Player Name", "") | return error_output("No Player Name", "") | ||
end | end | ||
local games = get_player_games_list(player_name) | local games = get_player_games_list(player_name) | ||
if not games then | if not games then | ||
return error_output("Cannot Load Games", "Ігри") | return error_output("Cannot Load Games", "Ігри") | ||
end | end | ||
if #games == 0 then | if #games == 0 then | ||
return "''Ігор не знайдено''" | return "''Ігор не знайдено''" | ||
end | end | ||
local htmlTable = mw.html.create('table') | local htmlTable = mw.html.create('table') | ||
:addClass('wikitable sortable') | :addClass('wikitable sortable') | ||
:css('width', '100%') | :css('width', '100%') | ||
:css('font-size', '14.5px') | :css('font-size', '14.5px') | ||
local headerRow = htmlTable:tag('tr') | local headerRow = htmlTable:tag('tr') | ||
headerRow:tag('th'):wikitext('Подія') | headerRow:tag('th'):wikitext('Подія') | ||
| Рядок 795: | Рядок 790: | ||
headerRow:tag('th'):wikitext('Запис') | headerRow:tag('th'):wikitext('Запис') | ||
for _, game in ipairs(games) do | for _, game in ipairs(games) do | ||
local row = htmlTable:tag('tr') | local row = htmlTable:tag('tr') | ||
local unknown = (game.result == "—") | |||
-- Турнір | -- Турнір | ||
row:tag('td') | row:tag('td') | ||
| Рядок 806: | Рядок 799: | ||
:css('padding', '8px') | :css('padding', '8px') | ||
:wikitext(get_tournament_link_games(game.short, game.tournament)) | :wikitext(get_tournament_link_games(game.short, game.tournament)) | ||
-- Роль | -- Роль | ||
row:tag('td') | |||
:css('text-align', 'center') | :css('text-align', 'center') | ||
:css('padding', '8px') | :css('padding', '8px') | ||
:tag('span') | |||
:css('color', unknown and '#777' or '#fff') | |||
:wikitext(game.role) | |||
-- Час | -- Час | ||
| Рядок 837: | Рядок 828: | ||
:wikitext('П') | :wikitext('П') | ||
else | else | ||
resultCell:tag('span'):css('color', '#777'):wikitext('—') | resultCell:tag('span') | ||
:css('color', '#777') | |||
:wikitext('—') | |||
end | end | ||
-- | -- Запис | ||
local linkCell = row:tag('td') | local linkCell = row:tag('td') | ||
:css('text-align', 'center') | :css('text-align', 'center') | ||
:css('padding', '8px') | :css('padding', '8px') | ||
if game.link and game.link ~= "" then | if game.link and game.link ~= "" then | ||
linkCell:wikitext('<span class="game-record-btn">[' .. game.link .. ' ▶︎]</span>') | linkCell:wikitext('<span class="game-record-btn">[' .. game.link .. ' ▶︎]</span>') | ||
end | end | ||
end | end | ||
return tostring(htmlTable) | return tostring(htmlTable) | ||
end | end | ||
| Рядок 856: | Рядок 849: | ||
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 "0" end | ||
local games = get_player_games_list(player_name) | local games = get_player_games_list(player_name) | ||
return games and tostring(#games) or "0" | return games and tostring(#games) or "0" | ||
| Рядок 862: | Рядок 855: | ||
-- ================================================ | -- ================================================ | ||
-- | -- ДОСЯГНЕННЯ В СЕЗОНАХ | ||
-- ================================================ | -- ================================================ | ||
| Рядок 871: | Рядок 864: | ||
[7] = "Сьомий сезон", [8] = "Восьмий сезон", [9] = "Дев'ятий сезон" | [7] = "Сьомий сезон", [8] = "Восьмий сезон", [9] = "Дев'ятий сезон" | ||
} | } | ||
local season_name = season_names[season_number] | local season_name = season_names[season_number] | ||
if not season_name then return nil end | if not season_name then return nil end | ||
local content = get_page_content(season_name) | local content = get_page_content(season_name) | ||
if not content then return nil end | if not content then return nil end | ||
local rating_section = mw.ustring.match(content, "==+%s*Рейтинг%s*==+(.-)\n==") | local rating_section = mw.ustring.match(content, "==+%s*Рейтинг%s*==+(.-)\n==") | ||
if not rating_section then | if not rating_section then | ||
| Рядок 883: | Рядок 876: | ||
end | end | ||
if not rating_section then return nil end | if not rating_section then return nil end | ||
local table_start = mw.ustring.find(rating_section, "{|") | local table_start = mw.ustring.find(rating_section, "{|") | ||
local table_end = mw.ustring.find(rating_section, "|}", table_start) | local table_end = mw.ustring.find(rating_section, "|}", table_start) | ||
if not table_start or not table_end then return nil end | 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 table_content = mw.ustring.sub(rating_section, table_start, table_end + 1) | ||
local current_row = {} | local current_row = {} | ||
local all_rows = {} | local all_rows = {} | ||
for line in mw.ustring.gmatch(table_content .. "\n", "([^\n]*)\n") do | for line in mw.ustring.gmatch(table_content .. "\n", "([^\n]*)\n") do | ||
line = mw.text.trim(line) | line = mw.text.trim(line) | ||
if line == "|-" then | if line == "|-" then | ||
if #current_row > 0 then | if #current_row > 0 then | ||
| Рядок 906: | Рядок 899: | ||
end | end | ||
end | end | ||
if #current_row > 0 then | if #current_row > 0 then | ||
table.insert(all_rows, current_row) | table.insert(all_rows, current_row) | ||
end | end | ||
for _, row in ipairs(all_rows) do | for _, row in ipairs(all_rows) do | ||
if #row >= 5 then | if #row >= 5 then | ||
local player_cell = clean_wikilinks(row[2]) | local player_cell = clean_wikilinks(row[2]) | ||
if player_cell == player_name then | if player_cell == player_name then | ||
return { | return { | ||
| Рядок 925: | Рядок 918: | ||
end | end | ||
end | end | ||
return nil | return nil | ||
end | end | ||
| Рядок 934: | Рядок 927: | ||
return "<span style='color:red;'>Ім'я гравця не вказано</span>" | return "<span style='color:red;'>Ім'я гравця не вказано</span>" | ||
end | end | ||
local htmlTable = mw.html.create('table') | local htmlTable = mw.html.create('table') | ||
:addClass('wikitable sortable') | :addClass('wikitable sortable') | ||
:css('width', '100%') | :css('width', '100%') | ||
:css('font-size', '14.5px') | :css('font-size', '14.5px') | ||
local headerRow = htmlTable:tag('tr') | local headerRow = htmlTable:tag('tr') | ||
headerRow:tag('th'):wikitext('Сезон') | headerRow:tag('th'):wikitext('Сезон') | ||
| Рядок 946: | Рядок 939: | ||
headerRow:tag('th'):wikitext('% перемог') | headerRow:tag('th'):wikitext('% перемог') | ||
headerRow:tag('th'):wikitext('Ігор') | headerRow:tag('th'):wikitext('Ігор') | ||
local season_links = { | local season_links = { | ||
[1] = "[[Перший сезон#Рейтинг|01 сезон]]", | [1] = "[[Перший сезон#Рейтинг|01 сезон]]", | ||
| Рядок 958: | Рядок 951: | ||
[9] = "[[Дев'ятий сезон#Рейтинг|09 сезон]]" | [9] = "[[Дев'ятий сезон#Рейтинг|09 сезон]]" | ||
} | } | ||
for season = 1, 9 do | for season = 1, 9 do | ||
local data = get_season_data(season, player_name) | local data = get_season_data(season, player_name) | ||
local row = htmlTable:tag('tr') | local row = htmlTable:tag('tr') | ||
row:tag('td'):css('text-align', 'center'):css('padding', '8px'):wikitext(season_links[season]) | row:tag('td'):css('text-align', 'center'):css('padding', '8px'):wikitext(season_links[season]) | ||
if data then | 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.place) | ||
| Рядок 976: | Рядок 969: | ||
end | end | ||
end | end | ||
return tostring(htmlTable) | return tostring(htmlTable) | ||
end | end | ||
return p | return p | ||