5441
редагування
Admin (обговорення | внесок) Немає опису редагування |
Admin (обговорення | внесок) Немає опису редагування Мітка: Скасовано |
||
| Рядок 2: | Рядок 2: | ||
-- ================================================ | -- ================================================ | ||
-- КЕШУВАННЯ | -- ГЛОБАЛЬНЕ КЕШУВАННЯ | ||
-- ================================================ | -- ================================================ | ||
local page_cache = {} | local page_cache = {} | ||
local table_cache = {} | local table_cache = {} | ||
-- ================================================ | |||
-- УТИЛІТИ | |||
-- ================================================ | |||
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 error_output(message) | |||
return '<span style="color:red; font-weight:bold;">Помилка: ' .. message .. '</span>' | |||
end | |||
local function get_page_content(page_name) | local function get_page_content(page_name) | ||
| Рядок 15: | Рядок 30: | ||
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 | ||
return nil | return nil | ||
end | end | ||
| Рядок 30: | Рядок 44: | ||
local content = get_page_content(page_name) | local content = get_page_content(page_name) | ||
if not content then | if not content then 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 | if not table_start or not table_end then 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 | end | ||
| Рядок 87: | Рядок 71: | ||
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, "|([^|]+)") do | |||
local trimmed = mw.text.trim(cell) | local trimmed = mw.text.trim(cell) | ||
if trimmed ~= "" then | if trimmed ~= "" then | ||
| Рядок 93: | Рядок 78: | ||
end | end | ||
end | end | ||
return cells | return cells | ||
end | end | ||
local function | local function find_player_data(table_content, player_name) | ||
if not table_content then return nil end | if not table_content then return nil end | ||
| Рядок 106: | Рядок 92: | ||
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 | ||
return parse_row_cells(row) | |||
end | end | ||
end | end | ||
return nil | return nil | ||
end | |||
-- Конвертація часу (якщо потрібно) | |||
local function format_time(time_str) | |||
if not time_str or time_str == "" then return "" end | |||
time_str = mw.text.trim(time_str) | |||
-- Якщо вже в правильному форматі | |||
if mw.ustring.find(time_str, "хв") then | |||
return time_str | |||
end | |||
-- Парсимо формат HH:MM:SS або MM:SS | |||
local hours, minutes, seconds = mw.ustring.match(time_str, "(%d+):(%d+):(%d+)") | |||
if not hours then | |||
minutes, seconds = mw.ustring.match(time_str, "(%d+):(%d+)") | |||
hours = "0" | |||
end | |||
if minutes and seconds then | |||
hours = tonumber(hours) or 0 | |||
minutes = tonumber(minutes) or 0 | |||
seconds = tonumber(seconds) or 0 | |||
if hours > 0 then | |||
return string.format("%d год %02d хв %02d с", hours, minutes, seconds) | |||
else | |||
return string.format("%d хв %02d с", minutes, seconds) | |||
end | |||
end | |||
return time_str | |||
end | end | ||
-- ================================================ | -- ================================================ | ||
-- FETCHDATA | -- ФУНКЦІЇ З FETCHDATA | ||
-- ================================================ | -- ================================================ | ||
function p.season_result(frame) | function p.season_result(frame) | ||
local | local player_name = frame.args.player or frame.args[1] | ||
local | local season_number = frame.args.season or frame.args[2] | ||
local | if not player_name or player_name == "" then | ||
"Перший сезон", "Другий сезон", "Третій сезон", | return error_output("Не вказано ім'я гравця") | ||
"Четвертий сезон", "П'ятий сезон", "Шостий сезон", | end | ||
"Сьомий сезон", "Восьмий сезон", "Дев'ятий сезон" | |||
if not season_number or season_number == "" then | |||
return error_output("Не вказано номер сезону") | |||
end | |||
local season_page = nil | |||
local season_names = { | |||
["1"] = "Перший сезон", | |||
["2"] = "Другий сезон", | |||
["3"] = "Третій сезон", | |||
["4"] = "Четвертий сезон", | |||
["5"] = "П'ятий сезон", | |||
["6"] = "Шостий сезон", | |||
["7"] = "Сьомий сезон", | |||
["8"] = "Восьмий сезон", | |||
["9"] = "Дев'ятий сезон" | |||
} | } | ||
local | season_page = season_names[season_number] | ||
if not | |||
if not season_page then | |||
return error_output("Невірний номер сезону") | |||
end | |||
local content = get_page_content(season_page) | |||
if not content then | |||
return error_output("Не вдалося завантажити сторінку сезону") | |||
end | |||
local final_section = mw.ustring.match(content, "==+%s*Фінал%s*==+(.-)\n==") | |||
if not final_section then | |||
final_section = mw.ustring.match(content, "==+%s*Фінал%s*==+(.*)") | |||
end | |||
if not final_section then | |||
return error_output("Не знайдено секцію Фінал") | |||
end | |||
local | local table_start = mw.ustring.find(final_section, "{|") | ||
local table_end = mw.ustring.find(final_section, "|}", table_start) | |||
if not table_start or not table_end then | |||
return error_output("Не знайдено таблицю у секції Фінал") | |||
end | |||
local | local table_content = mw.ustring.sub(final_section, table_start, table_end + 1) | ||
local | local player_data = find_player_data(table_content, player_name) | ||
if not player_data or #player_data < 2 then | |||
return "—" | |||
end | |||
return | local place = player_data[1] | ||
return place or "—" | |||
end | end | ||
-- ================================================ | -- ================================================ | ||
-- FETCHDATA2 | -- ФУНКЦІЇ З FETCHDATA2 | ||
-- ================================================ | -- ================================================ | ||
function p.games_count(frame) | function p.games_count(frame) | ||
local player_name = frame.args.player | local player_name = frame.args.player or frame.args[1] | ||
if not player_name or player_name == "" then return "0" end | |||
if not player_name or player_name == "" then | |||
return error_output("Не вказано ім'я гравця") | |||
end | |||
local table_content = get_table_from_page("Статистика") | |||
if not table_content then | |||
return error_output("Не вдалося завантажити таблицю") | |||
end | |||
local data = find_player_data(table_content, player_name) | |||
if not data or #data < 3 then | |||
return "0" | |||
end | |||
return data[3] or "0" | |||
return | |||
end | end | ||
function p.wins_count(frame) | function p.wins_count(frame) | ||
local player_name = frame.args.player | local player_name = frame.args.player or frame.args[1] | ||
if not player_name or player_name == "" then return " | |||
if not player_name or player_name == "" then | |||
return error_output("Не вказано ім'я гравця") | |||
end | |||
local table_content = get_table_from_page("Статистика") | |||
if not table_content then | |||
return error_output("Не вдалося завантажити таблицю") | |||
end | |||
local | local data = find_player_data(table_content, player_name) | ||
return | |||
if not data or #data < 4 then | |||
return "0" | |||
end | |||
return data[4] or "0" | |||
end | end | ||
function p.losses_count(frame) | function p.losses_count(frame) | ||
local player_name = frame.args.player | local player_name = frame.args.player or frame.args[1] | ||
local | if not player_name or player_name == "" then | ||
return | return error_output("Не вказано ім'я гравця") | ||
end | |||
local table_content = get_table_from_page("Статистика") | |||
if not table_content then | |||
return error_output("Не вдалося завантажити таблицю") | |||
end | |||
local data = find_player_data(table_content, player_name) | |||
if not data or #data < 5 then | |||
return "0" | |||
end | |||
return data[5] or "0" | |||
end | end | ||
function p.win_rate_colored(frame) | function p.win_rate_colored(frame) | ||
local player_name = frame.args.player | local player_name = frame.args.player or frame.args[1] | ||
if not player_name or player_name == "" then | |||
return error_output("Не вказано ім'я гравця") | |||
end | |||
local | local table_content = get_table_from_page("Статистика") | ||
if not | if not table_content then | ||
return error_output("Не вдалося завантажити таблицю") | |||
end | |||
local | local data = find_player_data(table_content, player_name) | ||
if | |||
if not data or #data < 6 then | |||
return '<span style="color:indianred;">0%</span>' | |||
end | end | ||
local winrate = data[6] | |||
winrate = mw.ustring.gsub(winrate, "%%", "") | |||
winrate = mw.text.trim(winrate) | |||
local rate = tonumber(winrate) or 0 | |||
local color = rate < 40 and "indianred" or "#4caf50" | |||
return | return '<span style="color:' .. color .. ';">' .. winrate .. '%</span>' | ||
end | end | ||
function p.recruiter(frame) | function p.recruiter(frame) | ||
local player_name = frame.args.player | local player_name = frame.args.player or frame.args[1] | ||
if not player_name or player_name == "" then return "Не вказано" end | |||
if not player_name or player_name == "" then | |||
return error_output("Не вказано ім'я гравця") | |||
end | |||
local table_content = get_table_from_page("Гравці") | local table_content = get_table_from_page("Гравці") | ||
if not table_content then return "Не | if not table_content then | ||
return error_output("Не вдалося завантажити таблицю") | |||
end | |||
local | local data = find_player_data(table_content, player_name) | ||
if not data or #data < 4 then | |||
if | return "Не вказано" | ||
return "Не вказано" | |||
end | end | ||
return | local recruiter = mw.text.trim(data[4]) | ||
if recruiter == "Відсутній" or recruiter == "-" or recruiter == "" then | |||
return "Не вказано" | |||
end | |||
return recruiter | |||
end | end | ||
function p.date_added(frame) | function p.date_added(frame) | ||
local player_name = frame.args.player | local player_name = frame.args.player or frame.args[1] | ||
if not player_name or player_name == "" then return " | |||
if not player_name or player_name == "" then | |||
return error_output("Не вказано ім'я гравця") | |||
end | |||
local table_content = get_table_from_page("Гравці") | |||
if not table_content then | |||
return error_output("Не вдалося завантажити таблицю") | |||
end | |||
local | local data = find_player_data(table_content, player_name) | ||
if not | if not data or #data < 3 then | ||
return "Лише Бог знає" | return "Лише Бог знає" | ||
end | end | ||
local | local raw_date = data[3] | ||
if | if not raw_date or raw_date == "" or raw_date == "-" then | ||
return "Лише Бог знає" | |||
local | end | ||
local day, month, year = mw.ustring.match(raw_date, "(%d+)%.(%d+)%.(%d+)") | |||
if not day or not month or not year then | |||
return raw_date | |||
end | end | ||
return " | 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) | |||
return string.format("%s (%d днів)", raw_date, days_diff) | |||
end | end | ||
function p.foundation(frame) | function p.foundation(frame) | ||
local player_name = frame.args.player | local player_name = frame.args.player or frame.args[1] | ||
if not player_name or player_name == "" then | |||
return error_output("Не вказано ім'я гравця") | |||
end | |||
local table_content = get_table_from_page("Фундація") | |||
if not table_content then | |||
return error_output("Не вдалося завантажити таблицю") | |||
end | |||
local data = find_player_data(table_content, player_name) | |||
return | if not data or #data < 3 then | ||
return "0" | |||
end | |||
local amount = mw.ustring.gsub(data[3], "[^%d]", "") | |||
return amount | |||
end | end | ||
function p.prize_pool(frame) | function p.prize_pool(frame) | ||
local player_name = frame.args.player | local player_name = frame.args.player or frame.args[1] | ||
if not player_name or player_name == "" then | |||
return error_output("Не вказано ім'я гравця") | |||
end | |||
local table_content = get_table_from_page("Призовий_фонд") | |||
if not table_content then | |||
return error_output("Не вдалося завантажити таблицю") | |||
end | |||
local data = find_player_data(table_content, player_name) | |||
return | if not data or #data < 2 then | ||
return "0" | |||
end | |||
local amount = mw.ustring.gsub(data[2], "[^%d]", "") | |||
return amount | |||
end | end | ||
function p.finalist(frame) | function p.finalist(frame) | ||
local player_name = frame.args.player | local player_name = frame.args.player or frame.args[1] | ||
if not player_name or player_name == "" then | |||
return error_output("Не вказано ім'я гравця") | |||
end | |||
local table_content = get_table_from_page("Фіналіст") | |||
if not table_content then | |||
return error_output("Не вдалося завантажити таблицю") | |||
end | |||
local | local data = find_player_data(table_content, player_name) | ||
if | if not data or #data < 3 then | ||
return | return "0" | ||
end | end | ||
local count = mw.ustring.gsub(data[3], "[^%d]", "") | |||
return count | |||
end | end | ||
function p.foty_rating(frame) | function p.foty_rating(frame) | ||
local player_name = frame.args.player | local player_name = frame.args.player or frame.args[1] | ||
if not player_name or player_name == "" then return " | |||
if not player_name or player_name == "" then | |||
return error_output("Не вказано ім'я гравця") | |||
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==") | ||
| Рядок 299: | Рядок 442: | ||
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 | local data = find_player_data(table_content, player_name) | ||
if not | if not data or #data < 3 then | ||
return "—" | |||
end | |||
local place = | local place = mw.text.trim(data[1]) | ||
local rating = | local rating = mw.text.trim(data[3]) | ||
rating = mw.ustring.gsub(rating, "<span[^>]*>", "") | |||
rating = mw.ustring.gsub(rating, "</span>", "") | |||
rating = mw.ustring.gsub(rating, "[^%d%-]", "") | rating = mw.ustring.gsub(rating, "[^%d%-]", "") | ||
rating = mw.text.trim(rating) | rating = mw.text.trim(rating) | ||
| Рядок 325: | Рядок 476: | ||
-- ================================================ | -- ================================================ | ||
-- | -- ФУНКЦІЇ З FETCHDATA5 (player_games) | ||
-- ================================================ | -- ================================================ | ||
function p.player_games(frame) | |||
local player_name = frame.args.player or frame.args[1] | |||
if | if not player_name or player_name == "" then | ||
return error_output("Не вказано ім'я гравця") | |||
end | end | ||
local page_content = get_page_content("Записи_ігор") | |||
if not page_content then | |||
return error_output("Не вдалося завантажити сторінку Записи_ігор") | |||
end | end | ||
local table_start = mw.ustring.find(page_content, "{|") | |||
local table_end = mw.ustring.find(page_content, "|}", table_start) | |||
local | |||
if | if not table_start or not table_end then | ||
return error_output("Не знайдено таблицю") | |||
end | end | ||
local table_content = mw.ustring.sub(page_content, table_start, table_end + 1) | |||
local rows = parse_table_rows(table_content) | |||
if #rows < 1 then | |||
return error_output("Таблиця порожня") | |||
end | |||
local escaped_name = mw.ustring.gsub(player_name, "([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1") | |||
local player_pattern = "%[%[" .. escaped_name .. "%]%]" | |||
local | |||
local | local player_games = {} | ||
for _, row in ipairs(rows) do | |||
if mw.ustring.find(row, player_pattern) then | |||
local cells = parse_row_cells(row) | |||
local | |||
if | if #cells >= 17 then | ||
local | local game_type = cells[2] | ||
local tournament = cells[4] | |||
local time = cells[5] | |||
local result = cells[16] | |||
local link = cells[17] | |||
if | local position = nil | ||
local role = nil | |||
for j = 6, 15 do | |||
local cell_player = clean_wikilinks(cells[j]) | |||
if cell_player == player_name then | |||
position = j - 5 | |||
if j >= 6 and j <= 11 then | |||
role = "Мирний" | |||
elseif j == 12 then | |||
role = "Шериф" | |||
elseif j >= 13 and j <= 14 then | |||
role = "Мафія" | |||
elseif j == 15 then | |||
role = "Дон" | |||
end | |||
break | |||
end | end | ||
end | end | ||
if position and role then | |||
table.insert(player_games, { | |||
type = game_type, | |||
tournament = tournament, | |||
time = time, | |||
position = position, | |||
role = role, | |||
result = result, | |||
link = link | |||
}) | |||
end | |||
end | end | ||
end | end | ||
end | end | ||
if # | if #player_games == 0 then | ||
return "''Записів ігор не знайдено''" | |||
end | end | ||
table.insert( | local output = {} | ||
table.insert(output, '{| class="wikitable sortable" style="font-size: 14px;"') | |||
table.insert(output, '|-') | |||
table.insert(output, '! №') | |||
table.insert(output, '! Тип') | |||
table.insert(output, '! Турнір') | |||
table.insert(output, '! Час') | |||
table.insert(output, '! Позиція') | |||
table.insert(output, '! Роль') | |||
table.insert(output, '! Результат') | |||
table.insert(output, '! Відео') | |||
for i, game in ipairs(player_games) do | |||
table.insert(output, '|-') | |||
table.insert(output, '| style="text-align:center;" | ' .. i) | |||
table.insert(output, '| ' .. game.type) | |||
table.insert(output, '| ' .. game.tournament) | |||
table.insert(output, '| style="text-align:center;" | ' .. game.time) | |||
table.insert(output, '| style="text-align:center;" | ' .. game.position) | |||
local role_color = "" | |||
if game.role == "Мирний" then | |||
role_color = "#90EE90" | |||
elseif game.role == "Шериф" then | |||
role_color = "#4169E1" | |||
elseif game.role == "Мафія" then | |||
role_color = "#DC143C" | |||
elseif game.role == "Дон" then | |||
role_color = "#8B0000" | |||
end | |||
table.insert(output, '| style="background-color:' .. role_color .. '; text-align:center;" | ' .. game.role) | |||
end | |||
local result_style = "" | |||
if game.result == "Місто" or game.result == "Мирні" then | |||
result_style = 'style="color:#4caf50; font-weight:bold;"' | |||
elseif game.result == "Мафія" then | |||
result_style = 'style="color:#f44336; font-weight:bold;"' | |||
end | end | ||
table.insert(output, '| ' .. result_style .. ' | ' .. game.result) | |||
table.insert(output, '| [' .. game.link .. ' YouTube]') | |||
end | end | ||
table.insert(output, '|}') | |||
return table.concat( | return table.concat(output, '\n') | ||
end | end | ||
function p.games_count_records(frame) | |||
local player_name = frame.args.player or frame.args[1] | |||
if | if not player_name or player_name == "" then | ||
return " | return "0" | ||
end | end | ||
local page_content = get_page_content("Записи_ігор") | |||
if not page_content then | |||
return "0" | |||
end | end | ||
local table_start = mw.ustring.find(page_content, "{|") | |||
local table_end = mw.ustring.find(page_content, "|}", table_start) | |||
if not table_start or not table_end then | |||
return "0" | |||
if not | |||
return | |||
end | end | ||
local table_content = mw.ustring.sub(page_content, table_start, table_end + 1) | |||
local rows = parse_table_rows(table_content) | |||
local escaped_name = mw.ustring.gsub(player_name, "([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1") | |||
local player_pattern = "%[%[" .. escaped_name .. "%]%]" | |||
local | |||
local | |||
local count = 0 | |||
for _, row in ipairs(rows) do | for _, row in ipairs(rows) do | ||
if mw.ustring.find(row, player_pattern) then | |||
count = count + 1 | |||
end | end | ||
end | end | ||
return | return tostring(count) | ||
end | end | ||
-- ================================================ | -- ================================================ | ||
-- FETCHDATA6 ( | -- ФУНКЦІЇ З FETCHDATA6 (season_achievements) | ||
-- ================================================ | -- ================================================ | ||
function p.season_achievements(frame) | |||
local | local player_name = frame.args.player or frame.args[1] | ||
if not player_name or player_name == "" then | |||
if not | return error_output("Не вказано ім'я гравця") | ||
end | end | ||
local | local season_data = {} | ||
local | local season_names = { | ||
"Перший сезон", | |||
"Другий сезон", | |||
"Третій сезон", | |||
"Четвертий сезон", | |||
"П'ятий сезон", | |||
"Шостий сезон", | |||
"Сьомий сезон", | |||
"Восьмий сезон", | |||
"Дев'ятий сезон" | |||
} | |||
for i, season_name in ipairs(season_names) do | |||
local content = get_page_content(season_name) | |||
if | if content then | ||
if | local final_section = mw.ustring.match(content, "==+%s*Фінал%s*==+(.-)\n==") | ||
if not final_section then | |||
final_section = mw.ustring.match(content, "==+%s*Фінал%s*==+(.*)") | |||
end | end | ||
if | if final_section then | ||
local table_start = mw.ustring.find(final_section, "{|") | |||
local table_end = mw.ustring.find(final_section, "|}", table_start) | |||
if table_start and table_end then | |||
local table_content = mw.ustring.sub(final_section, table_start, table_end + 1) | |||
local player_data = find_player_data(table_content, player_name) | |||
if player_data and #player_data >= 1 then | |||
table.insert(season_data, { | |||
season = i, | |||
place = player_data[1] or "—" | |||
}) | |||
end | |||
end | |||
end | end | ||
end | end | ||
end | end | ||
if #season_data == 0 then | |||
return "''Гравець не брав участі в жодному сезоні''" | |||
if | |||
return " | |||
end | end | ||
local | local output = {} | ||
table.insert(output, '{| class="wikitable" style="text-align:center; font-size: 14px;"') | |||
table.insert(output, '|-') | |||
for _, data in ipairs(season_data) do | |||
table.insert(output, '! [[' .. season_names[data.season] .. '|' .. data.season .. ']]') | |||
end | |||
table.insert(output, '|-') | |||
for | for _, data in ipairs(season_data) do | ||
table.insert(output, '| ' .. data.place) | |||
end | end | ||
return | table.insert(output, '|}') | ||
return table.concat(output, '\n') | |||
end | end | ||
return p | return p | ||