Для документации этого модуля может быть создана страница Модуль:Рейтинги/doc

local p = {}
local rankingsData = require('Модуль:Рейтинги/Данные')

-- ==========================================
-- НАСТРОЙКИ (Менять здесь!)
-- ==========================================
local CURRENT_YEAR = 2045 -- <== Изменить эту цифру, когда выйдет новый рейтинг
-- ==========================================

-- СЛОВАРЬ: Полное название -> Код
local nameToCode = {
    ["Абхазия"] = "АБХ", ["Американские Виргины"] = "АВИ", ["Австралийские Аборигены"] = "АВС",
    ["Азавад"] = "АЗА", ["Азорские Острова"] = "АЗО", ["Акри"] = "АКР", ["Аландские Острова"] = "АЛА",
    ["Аляска"] = "АЛЯ", ["Амбазония"] = "АМБ", ["Ангилья"] = "АНГ", ["Англси"] = "АНЛ",
    ["Антарктида"] = "АНР", ["Антигуа и Барбуда"] = "АНТ", ["Аомынь"] = "АОМ", ["Аруба"] = "АРУ",
    ["Американское Самоа"] = "АСА", ["Ассирия"] = "АСС", ["Атолл Джонстон"] = "АТО", ["Афганистан"] = "АФГ",
    ["Ачех"] = "АЧЕ", ["Багамы"] = "БАГ", ["Бакасси"] = "БАК", ["Бангладеш"] = "БАН",
    ["Барбадос"] = "БАР", ["Британские Виргины"] = "БВИ", ["Буганда"] = "БГН", ["Белиз"] = "БЕЛ",
    ["Бенин"] = "БЕН", ["Бермуды"] = "БЕР", ["Биафра"] = "БИА", ["Белуджистан"] = "БЛД",
    ["Бонайре"] = "БОН", ["Ботсвана"] = "БОТ", ["Барава"] = "БРВ", ["Бретань"] = "БРЕ",
    ["Бруней"] = "БРУ", ["Бугенвиль"] = "БУГ", ["Буркина-Фасо"] = "БУР", ["Бутан"] = "БУТ",
    ["Вазиристан"] = "ВАЗ", ["Валлония"] = "ВАЛ", ["Ватикан"] = "ВАТ", ["Венда"] = "ВЕН",
    ["Внешние Гебриды"] = "ВНЕ", ["Внутренняя Монголия"] = "ВНУ", ["Восточный Тимор"] = "ВОС",
    ["Гавайи"] = "ГАВ", ["Гагаузия"] = "ГАГ", ["Гайана"] = "ГАЙ", ["Галапагос"] = "ГАЛ",
    ["Гамбия"] = "ГАМ", ["Гваделупа"] = "ГВА", ["Гвинея-Бисау"] = "ГВБ", ["Гвиана"] = "ГВИ",
    ["Гернси"] = "ГЕР", ["Гибралтар"] = "ГИБ", ["Гонгконг"] = "ГОН", ["Государство Ва"] = "ГОС",
    ["Готланд"] = "ГОТ", ["Гоцо"] = "ГОЦ", ["Графство Ницца"] = "ГРА", ["Гренада"] = "ГРЕ",
    ["Гренландия"] = "ГРЛ", ["Гуам"] = "ГУА", ["Дарфур"] = "ДАР", ["Дельвидек"] = "ДЕЛ",
    ["Джерси"] = "ДЖЕ", ["Джибути"] = "ДЖИ", ["ДНР"] = "ДНР", ["Доминика"] = "ДОМ",
    ["Доминиканская Республика"] = "ДРЕ", ["Западная Армения"] = "ЗАА", ["Закарпатье"] = "ЗАК",
    ["Замбезия"] = "ЗАМ", ["Занзибар"] = "ЗАН", ["Западное Папуа"] = "ЗАП", ["Западная Сахара"] = "ЗАС",
    ["Западный Тоголенд"] = "ЗАТ", ["Земля Франца-Иосифа"] = "ЗФИ", ["Индия"] = "ИНД", ["Ичкерия"] = "ИЧК",
    ["Йемен"] = "ЙЕМ", ["Кабилия"] = "КАБ", ["Кайманы"] = "КАЙ", ["Камбоджа"] = "КАМ",
    ["Канары"] = "КАН", ["Каприви"] = "КАП", ["Каскадия"] = "КАС", ["Катанга"] = "КАТ",
    ["Кашмир"] = "КАШ", ["Кабинда"] = "КБН", ["Кения"] = "КЕН", ["Кергелен"] = "КЕР",
    ["Киргизия"] = "КИР", ["Китайский Тайпей"] = "КИТ", ["Кокос"] = "КОК", ["Коморы"] = "КОМ",
    ["Конк"] = "КОН", ["Кокосовые Острова"] = "КОО", ["Корейцы Японии"] = "КОР", ["Королевство обеих Сицилий"] = "КОС",
    ["Кирибати"] = "КРБ", ["Кермадек"] = "КРМ", ["Корнуолл"] = "КРН", ["Крым"] = "КРЫ",
    ["Курдистан"] = "КУР", ["Кюрасао"] = "КЮР", ["Ладония"] = "ЛАД", ["Лакота"] = "ЛАК",
    ["Лаос"] = "ЛАО", ["Лапландия"] = "ЛАП", ["Латгалия"] = "ЛАТ", ["Лесото"] = "ЛЕС",
    ["Ливан"] = "ЛИВ", ["ЛНР"] = "ЛНР", ["Логон"] = "ЛОГ", ["Маврикий"] = "МАВ",
    ["Мадагаскар"] = "МАД", ["Майотта"] = "МАЙ", ["Мальдивы"] = "МАЛ", ["Мальтийский Орден"] = "МАО",
    ["Мапуче"] = "МАП", ["Маршаллы"] = "МАР", ["Масаи"] = "МАС", ["Матабелеленд"] = "МАТ",
    ["Мавритания"] = "МВР", ["Мадейра"] = "МДР", ["Мелилья"] = "МЕЛ", ["Менорка"] = "МЕН",
    ["Мидуэй"] = "МИД", ["Микронезия"] = "МИК", ["Малайзия"] = "МЛЗ", ["Монако"] = "МНК",
    ["Монтсеррат"] = "МНТ", ["Мозамбик"] = "МОЗ", ["Молоссия"] = "МОЛ", ["Монголия"] = "МОН",
    ["Мореснет"] = "МОР", ["Марианы"] = "МРН", ["Мартиника"] = "МРТ", ["Мьянма"] = "МЬЯ",
    ["Нагорный Карабах"] = "НАГ", ["Науру"] = "НАУ", ["Нагаленд"] = "НГЛ", ["Непал"] = "НЕП",
    ["Новая Земля"] = "НЗЕ", ["Нигер"] = "НИГ", ["Никарагуа"] = "НИК", ["Ниуэ"] = "НИУ",
    ["Новая Каледония"] = "НОВ", ["Норфолк"] = "НОР", ["Ньюфаундленд"] = "НЬЮ", ["Острова Антиподов"] = "ОАН",
    ["Остров Вознесения"] = "ОВО", ["Огненная Земля"] = "ОГН", ["Остров Европа"] = "ОЕВ",
    ["Окситания"] = "ОКС", ["Острова Кука"] = "ОКУ", ["Олдерни"] = "ОЛД", ["Остров Мэн"] = "ОМЭ",
    ["Остров Пасхи"] = "ОПА", ["Остров Петра Первого"] = "ОПП", ["Остров Принца Эдуарда"] = "ОПЭ",
    ["Оркнейские Острова"] = "ОРК", ["Остров Рождества"] = "ОРО", ["Острова Силли"] = "ОСИ",
    ["Остров св. Елены"] = "ОСТ", ["Остров Уайт"] = "ОУА", ["Падания"] = "ПАД", ["Пакистан"] = "ПАК",
    ["Палау"] = "ПАЛ", ["Папуа-Новая Гвинея"] = "ПАП", ["Пенджаб"] = "ПЕН", ["Питкэрн"] = "ПИТ",
    ["Палестина"] = "ПЛС", ["Полинезийские Спорады"] = "ПОЛ", ["Приднестровье"] = "ПРИ", ["Прованс"] = "ПРО",
    ["Пуэрто-Рико"] = "ПУЭ", ["Раф-энд-Рэди"] = "РАФ", ["Рехобот"] = "РЕХ", ["Реция"] = "РЕЦ",
    ["Реюньон"] = "РЕЮ", ["Родос"] = "РОД", ["Сааремаа"] = "САА", ["Саба"] = "САБ",
    ["Самоа"] = "САМ", ["Сан-Марино"] = "САН", ["Сарк"] = "САР", ["Сен-Бартельми"] = "СБА",
    ["Свазиленд"] = "СВА", ["Сент-Винсент и Гренадины"] = "СВГ", ["Себорга"] = "СЕБ", ["Северный Кипр"] = "СЕВ",
    ["Сейшелы"] = "СЕЙ", ["Секейский Край"] = "СЕК", ["Сент-Люсия"] = "СЕН", ["Сеута"] = "СЕУ",
    ["Силенд"] = "СИЛ", ["Сингапур"] = "СИН", ["Сицилия"] = "СИЦ", ["Сент-Китс и Невис"] = "СКН",
    ["Сент-Мартен"] = "СМА", ["Сомалиленд"] = "СМЛ", ["Сан-Андрес"] = "СНА", ["Синд"] = "СНД",
    ["Соже"] = "СОЖ", ["Соломоны"] = "СОЛ", ["Сомали"] = "СОМ", ["Сен-Пьер и Микелон"] = "СПМ",
    ["Сардиния"] = "СРД", ["Сан-Томе и Принсипи"] = "СТП", ["Сулу"] = "СУЛ", ["Суринам"] = "СУР",
    ["Сент-Эстатиус"] = "СЭС", ["Таджикистан"] = "ТАД", ["Таити"] = "ТАИ", ["Тамил-Илам"] = "ТАМ",
    ["Танзания"] = "ТАН", ["Тасмания"] = "ТАС", ["Теркс и Кайкос"] = "ТЕР", ["Тибет"] = "ТИБ",
    ["Токелау"] = "ТОК", ["Тонга"] = "ТОН", ["Тристан-да-Кунья"] = "ТРИ", ["Триест"] = "ТРС",
    ["Туамоту"] = "ТУА", ["Тувалу"] = "ТУВ", ["Туркмения"] = "ТУР", ["Ужупис"] = "УЖУ",
    ["Уоллис и Футуна"] = "УОЛ", ["Уэйк"] = "УЭЙ", ["Федеральные владения Венесуэлы"] = "ФВВ", ["Фельвидек"] = "ФЕЛ",
    ["Фиджи"] = "ФИД", ["Филиппины"] = "ФИЛ", ["Фолклендские Острова"] = "ФОЛ", ["Фрёйа"] = "ФРЁ",
    ["Французская Полинезия"] = "ФРА", ["Франкония"] = "ФРН", ["Хатт-Ривер"] = "ХАТ", ["Хёрд"] = "ХЁР",
    ["Хитра"] = "ХИТ", ["Хмонг"] = "ХМО", ["Христиания"] = "ХРИ", ["Хузестан"] = "ХУЗ",
    ["ЦАР"] = "ЦАР", ["Цыгане"] = "ЦЫГ", ["Чагос"] = "ЧАГ", ["Чад"] = "ЧАД",
    ["Чамерия"] = "ЧАМ", ["Чатем"] = "ЧАТ", ["Шан"] = "ШАН", ["Шетландские Острова"] = "ШЕТ",
    ["Шпицберген"] = "ШПИ", ["Шри-Ланка"] = "ШРИ", ["Экваториальная Гвинея"] = "ЭКВ", ["Эритрея"] = "ЭРИ",
    ["Эфиопия"] = "ЭФИ", ["Южная Георгия"] = "ЮГЕ", ["Южный Судан"] = "ЮЖН", ["Южный Йемен"] = "ЮЙМ",
    ["Южное Касаи"] = "ЮКА", ["Южный Камерун"] = "ЮКМ", ["Южное Конго"] = "ЮКО", ["Южная Осетия"] = "ЮОС",
    ["Южный Тироль"] = "ЮТИ", ["Ян-Майен"] = "ЯНМ"
}

-- ФУНКЦИЯ 1: Отрисовка таблицы
function p.table_rows(frame)
    local teamCode = frame.args[1] or frame:getParent().args[1]

    local grid = {
        {2009, 2024, 2036}, {2010, 2025, 2037}, {2013, 2026, 2038},
        {2014, 2027, 2039}, {2015, 2028, 2040}, {2017, 2029, 2041},
        {2018, 2030, 2042}, {2019, 2031, 2043}, {2020, 2032, 2044},
        {2021, 2033, 2045}, {2022, 2034, nil},  {2023, 2035, nil}
    }

    local result = {} 

    for _, row in ipairs(grid) do
        table.insert(result, "|-") 
        for i = 1, 3 do
            local year = row[i]
            if year then
                local rank = nil
                if rankingsData[year] then rank = rankingsData[year][teamCode] end

                local rankStr = rank or "—"
                local bgColor = ""

                if rank == 1 then bgColor = "gold"
                elseif rank == 2 then bgColor = "silver"
                elseif rank == 3 then bgColor = "rgb(204,153,102)"
                elseif rank == 4 then bgColor = "darkkhaki"
                elseif rank and rank >= 5 and rank <= 10 then bgColor = "palegoldenrod"
                end

                local styleAttr = 'style="white-space:nowrap;text-align:center;'
                if bgColor ~= "" then styleAttr = styleAttr .. 'background-color:' .. bgColor .. ';"'
                else styleAttr = styleAttr .. '"' end

                table.insert(result, '| style="white-space:nowrap;text-align:center;background-color:#ebf3fe;" | [[Рейтинг ЧТМ (' .. year .. ')|' .. year .. ']]')
                table.insert(result, '| ' .. styleAttr .. ' | ' .. rankStr)
            else
                table.insert(result, '|') table.insert(result, '|')
            end
        end
    end
    return table.concat(result, "\n")
end

-- ФУНКЦИЯ 2: Высшее место (с поддержкой полных названий и группировкой годов)
function p.best_rank(frame)
    local input = frame.args[1] or frame:getParent().args[1]
    
    -- Проверяем, попросил ли пользователь вывести годы. 
    -- Поддерживаем параметры: 2-й неименованный параметр, или именованные "годы=" и "years="
    local showYears = frame.args[2] or frame.args["годы"] or frame:getParent().args["годы"]
    
    if not input or input == "" then
        return "—"
    end

    local teamCode = nameToCode[input] or input
    local bestRank = nil
    local bestYears = {} -- Сюда будем складывать победные годы

    -- Пробегаемся по базе данных
    for year, teams in pairs(rankingsData) do
        local currentRank = teams[teamCode]
        if currentRank then
            if not bestRank or currentRank < bestRank then
                -- Нашли место ЛУЧШЕ! Запоминаем его, а старые годы выбрасываем
                bestRank = currentRank
                bestYears = { year } 
            elseif currentRank == bestRank then
                -- Нашли такое же лучшее место. Добавляем год в копилку
                table.insert(bestYears, year)
            end
        end
    end

    -- Если команды вообще нет в рейтинге
    if not bestRank then
        return "—"
    end

    -- Если пользователь НЕ просил годы (просто нужна цифра)
    if not showYears or showYears == "" then
        return tostring(bestRank)
    end

    -- === ГРУППИРОВКА ГОДОВ ===
    -- 1. Сортируем годы по возрастанию
    table.sort(bestYears)

    local groups = {}
    local start_year = bestYears[1]
    local prev_year = bestYears[1]

    -- 2. Перебираем отсортированные годы и ищем последовательности
    for i = 2, #bestYears do
        local current_year = bestYears[i]
        
        if current_year == prev_year + 1 then
            -- Год идет строго за предыдущим (например, 2020 после 2019). Продолжаем цепочку.
            prev_year = current_year
        else
            -- Цепочка прервалась. Записываем накопленное.
            if start_year == prev_year then
                table.insert(groups, tostring(start_year)) -- Одиночный год
            else
                table.insert(groups, start_year .. "—" .. prev_year) -- Диапазон
            end
            -- Начинаем новую цепочку
            start_year = current_year
            prev_year = current_year
        end
    end
    
    -- Не забываем записать последнюю цепочку (хвост цикла)
    if start_year == prev_year then
        table.insert(groups, tostring(start_year))
    else
        table.insert(groups, start_year .. "—" .. prev_year)
    end

    -- 3. Склеиваем всё через запятую и пробел
    local yearsStr = table.concat(groups, ", ")

    -- Выдаем результат вида: 1 (2015, 2017, 2019—2021)
    return bestRank .. " (" .. yearsStr .. ")"
end

-- ==========================================
-- ФУНКЦИЯ 3: Получить место в конкретном году
-- ==========================================
function p.get_rank(frame)
    local input = frame.args[1] or frame:getParent().args[1]
    
    -- Получаем запрошенный год. Если год не указали, используем CURRENT_YEAR
    local requestedYear = frame.args[2] or frame.args["год"] or frame:getParent().args["год"] or frame.args["year"] or frame:getParent().args["year"]
    
    -- Превращаем год в число, если ничего не передали - берем текущий
    local year = tonumber(requestedYear) or CURRENT_YEAR
    
    if not input or input == "" then
        return "—"
    end

    -- Переводим "Доминика" -> "ДОМ" (если нужно)
    local teamCode = nameToCode[input] or input

    -- Проверяем, есть ли вообще такой год в базе
    if not rankingsData[year] then
        return "—"
    end

    -- Ищем место команды в этом году
    local rank = rankingsData[year][teamCode]

    -- Возвращаем место, либо прочерк, если команды в этом году не было
    return rank and tostring(rank) or "—"
end

-- ФУНКЦИЯ 4: Вывести текущий год (для подписей)
function p.current_year()
    return tostring(CURRENT_YEAR)
end

return p