Модуль:FetchData
Документацію для цього модуля можна створити у Модуль:FetchData/документація
local p = {}
-- ================================================
-- ГЛОБАЛЬНЕ КЕШУВАННЯ
-- ================================================
local page_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)
if page_cache[page_name] then
return page_cache[page_name]
end
local title = mw.title.new(page_name)
if not title or not title.exists then
return nil
end
local content = title:getContent()
page_cache[page_name] = content
return content
end
local function get_table_from_page(page_name)
if table_cache[page_name] then
return table_cache[page_name]
end
local content = get_page_content(page_name)
if not content then return nil end
local table_start = mw.ustring.find(content, "{|")
local table_end = mw.ustring.find(content, "|}", table_start)
if not table_start or not table_end then return nil end
local table_content = mw.ustring.sub(content, table_start, table_end + 1)
table_cache[page_name] = table_content
return table_content
end
local function parse_table_rows(table_content)
local rows = {}
for row in mw.ustring.gmatch(table_content, "|-\n(.-)\n|-") do
table.insert(rows, row)
end
local last_row = mw.ustring.match(table_content, "|-\n(.-)%s*|}")
if last_row then
table.insert(rows, last_row)
end
return rows
end
local function parse_row_cells(row)
local cells = {}
row = mw.ustring.gsub(row, "^%s*|%s*", "")
for cell in mw.ustring.gmatch(row, "|([^|]+)") do
local trimmed = mw.text.trim(cell)
if trimmed ~= "" then
table.insert(cells, trimmed)
end
end
return cells
end
local function find_player_data(table_content, player_name)
if not table_content then return nil end
local escaped = mw.ustring.gsub(player_name, "([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1")
local player_pattern = "%[%[" .. escaped .. "%]%]"
local rows = parse_table_rows(table_content)
for _, row in ipairs(rows) do
if mw.ustring.find(row, player_pattern) then
return parse_row_cells(row)
end
end
return nil
end
-- Конвертація часу (якщо потрібно)
local function 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
-- ================================================
-- ФУНКЦІЇ З FETCHDATA
-- ================================================
function p.season_result(frame)
local player_name = frame.args.player or frame.args[1]
local season_number = frame.args.season or frame.args[2]
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"] = "Дев'ятий сезон"
}
season_page = season_names[season_number]
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 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 table_content = mw.ustring.sub(final_section, table_start, table_end + 1)
local player_data = find_player_data(table_content, player_name)
if not player_data or #player_data < 2 then
return "—"
end
local place = player_data[1]
return place or "—"
end
-- ================================================
-- ФУНКЦІЇ З FETCHDATA2
-- ================================================
function p.games_count(frame)
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)
if not data or #data < 3 then
return "0"
end
return data[3] or "0"
end
function p.wins_count(frame)
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)
if not data or #data < 4 then
return "0"
end
return data[4] or "0"
end
function p.losses_count(frame)
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)
if not data or #data < 5 then
return "0"
end
return data[5] or "0"
end
function p.win_rate_colored(frame)
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)
if not data or #data < 6 then
return '<span style="color:indianred;">0%</span>'
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 '<span style="color:' .. color .. ';">' .. winrate .. '%</span>'
end
function p.recruiter(frame)
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)
if not data or #data < 4 then
return "Не вказано"
end
local recruiter = mw.text.trim(data[4])
if recruiter == "Відсутній" or recruiter == "-" or recruiter == "" then
return "Не вказано"
end
return recruiter
end
function p.date_added(frame)
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)
if not data or #data < 3 then
return "Лише Бог знає"
end
local raw_date = data[3]
if not raw_date or raw_date == "" or raw_date == "-" then
return "Лише Бог знає"
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
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
function p.foundation(frame)
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)
if not data or #data < 3 then
return "0"
end
local amount = mw.ustring.gsub(data[3], "[^%d]", "")
return amount
end
function p.prize_pool(frame)
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)
if not data or #data < 2 then
return "0"
end
local amount = mw.ustring.gsub(data[2], "[^%d]", "")
return amount
end
function p.finalist(frame)
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)
if not data or #data < 3 then
return "0"
end
local count = mw.ustring.gsub(data[3], "[^%d]", "")
return count
end
function p.foty_rating(frame)
local player_name = frame.args.player or frame.args[1]
if not player_name or player_name == "" then
return error_output("Не вказано ім'я гравця")
end
local content = get_page_content("Період")
if not content then
return "—"
end
local foty_section = mw.ustring.match(content, "==+%s*Фінал Року%s*==+(.-)\n==")
if not foty_section then
foty_section = mw.ustring.match(content, "==+%s*Фінал Року%s*==+(.*)")
end
if not foty_section then
return "—"
end
local table_start = mw.ustring.find(foty_section, "{|")
local table_end = mw.ustring.find(foty_section, "|}", table_start)
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 data = find_player_data(table_content, player_name)
if not data or #data < 3 then
return "—"
end
local place = mw.text.trim(data[1])
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.text.trim(rating)
if rating and rating ~= "" then
return rating .. " (" .. place .. " місце)"
end
return "—"
end
-- ================================================
-- ФУНКЦІЇ З FETCHDATA5 (player_games)
-- ================================================
function p.player_games(frame)
local player_name = frame.args.player or frame.args[1]
if not player_name or player_name == "" then
return error_output("Не вказано ім'я гравця")
end
local page_content = get_page_content("Записи_ігор")
if not page_content then
return error_output("Не вдалося завантажити сторінку Записи_ігор")
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 error_output("Не знайдено таблицю")
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 player_games = {}
for _, row in ipairs(rows) do
if mw.ustring.find(row, player_pattern) then
local cells = parse_row_cells(row)
if #cells >= 17 then
local game_type = cells[2]
local tournament = cells[4]
local time = cells[5]
local result = cells[16]
local link = cells[17]
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
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
if #player_games == 0 then
return "''Записів ігор не знайдено''"
end
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)
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
table.insert(output, '| ' .. result_style .. ' | ' .. game.result)
table.insert(output, '| [' .. game.link .. ' YouTube]')
end
table.insert(output, '|}')
return table.concat(output, '\n')
end
function p.games_count_records(frame)
local player_name = frame.args.player or frame.args[1]
if not player_name or player_name == "" then
return "0"
end
local page_content = get_page_content("Записи_ігор")
if not page_content then
return "0"
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"
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 count = 0
for _, row in ipairs(rows) do
if mw.ustring.find(row, player_pattern) then
count = count + 1
end
end
return tostring(count)
end
-- ================================================
-- ФУНКЦІЇ З FETCHDATA6 (season_achievements)
-- ================================================
function p.season_achievements(frame)
local player_name = frame.args.player or frame.args[1]
if not player_name or player_name == "" then
return error_output("Не вказано ім'я гравця")
end
local season_data = {}
local season_names = {
"Перший сезон",
"Другий сезон",
"Третій сезон",
"Четвертий сезон",
"П'ятий сезон",
"Шостий сезон",
"Сьомий сезон",
"Восьмий сезон",
"Дев'ятий сезон"
}
for i, season_name in ipairs(season_names) do
local content = get_page_content(season_name)
if content then
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 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
if #season_data == 0 then
return "''Гравець не брав участі в жодному сезоні''"
end
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 _, data in ipairs(season_data) do
table.insert(output, '| ' .. data.place)
end
table.insert(output, '|}')
return table.concat(output, '\n')
end
return p