Moduli:Категория по годам

On otettu Рувики-späi

Tämän moduulin ohjeistuksen voi tehdä sivulle Moduli:Категория по годам/ohje

local p = {}

local function getDecade(y)
    return y - (y % 10)
end

local function toRoman(num)
    local romanNumerals = {
        {1000, "M"}, {900, "CM"}, {500, "D"}, {400, "CD"},
        {100, "C"},  {90,  "XC"}, {50,  "L"}, {40,  "XL"},
        {10,   "X"}, {9,   "IX"}, {5,   "V"}, {4,   "IV"},
        {1,    "I"},
    }
    local res = {}
    for _, rn in ipairs(romanNumerals) do
        while num >= rn[1] do
            table.insert(res, rn[2])
            num = num - rn[1]
        end
    end
    return table.concat(res)
end

local function getCentury(y)
    local c = math.floor((y - 1) / 100) + 1
    return toRoman(c)
end

function p.applyPatterns(patternTable, fullText, year, bcFlag)
    if type(patternTable) ~= 'table' then
        return ''
    end
    for patternKey, categoriesString in pairs(patternTable) do
        local candidateName = patternKey
            :gsub("{y}", tostring(year))
            :gsub("{bc}", bcFlag and " до н. э." or "")
        if candidateName == fullText then
            local decade = getDecade(year)
            local century = getCentury(year)
            local result = categoriesString
                :gsub("{y}", tostring(year))
                :gsub("{d}", tostring(decade))
                :gsub("{c}", century)
            if bcFlag then
                result = result:gsub("{bc}", " до н. э.")
            else
                result = result:gsub("{bc}", "")
            end
            return result
        end
    end
    return ''
end

function p.getExtraCategories(fullText, year, bcFlag)
    if not fullText or fullText == '' then
        return ''
    end
    local firstLetter = mw.ustring.sub(fullText, 1, 1)
    firstLetter = mw.ustring.upper(firstLetter)
    if firstLetter:match("[%aА-Яа-я]") then
        local subModuleName = 'Модуль:Категория по годам/список/' .. firstLetter
        local ok, subModule = pcall(require, subModuleName)
        if ok and type(subModule) == 'table' then
            local cats = p.applyPatterns(subModule, fullText, year, bcFlag)
            if cats and cats ~= '' then
                return cats
            end
        end
    end
    local ok2, generalModule = pcall(require, 'Модуль:Категория по годам/список')
    if not ok2 or type(generalModule) ~= 'table' then
        return ''
    end
    return p.applyPatterns(generalModule, fullText, year, bcFlag)
end

local function makeYearLink(baseName, realY, suffix)
    if realY == 0 then
        return nil
    elseif realY < 0 then
        local posY = -realY
        return '[[:Категория:' .. baseName .. ' ' .. posY .. ' ' .. suffix .. '|−' .. posY .. ']]'
    else
        return '[[:Категория:' .. baseName .. ' ' .. realY .. ' ' .. suffix .. '|' .. realY .. ']]'
    end
end

local function rangeList(baseName, startNum, endNum, suffix)
    local step = (startNum <= endNum) and 1 or -1
    local results = {}
    local i = startNum
    while true do
        if step > 0 and i > endNum then break end
        if step < 0 and i < endNum then break end
        if i ~= 0 then
            local link = makeYearLink(baseName, i, suffix)
            if link then
                table.insert(results, link)
            end
        end
        i = i + step
    end
    return results
end

function p._makeNavRow(baseName, year, suffix, bcFlag)
    local realYear = bcFlag and -year or year
    local older = rangeList(baseName, realYear - 5, realYear - 1, suffix)
    local newer = rangeList(baseName, realYear + 1, realYear + 5, suffix)
    local centerLink = makeYearLink(baseName, realYear, suffix)
    local t = {}
    table.insert(t, '{| class="standard" align="center"')
    for _, val in ipairs(older) do
        table.insert(t, '| ' .. val)
    end
    if centerLink then
        if bcFlag then
            table.insert(t, '! −' .. year)
        else
            table.insert(t, '! ' .. year)
        end
    end
    for _, val in ipairs(newer) do
        table.insert(t, '| ' .. val)
    end
    table.insert(t, '|}')
    return table.concat(t, '\n')
end

function p.main(frame)
    local title = mw.title.getCurrentTitle()
    if title.namespace ~= 14 then
        return "Модуль «Категория по годам» вызывается не в пространстве «Категория»."
    end
    local text = title.text
    local baseName, year, suffix
    local bcFlag = false
    baseName, year, suffix = text:match('^(.-)%s+(%d+)%s+(года)$')
    if not (baseName and year) then
        baseName, year, suffix = text:match('^(.-)%s+(%d+)%s+(году)$')
    end
    if not (baseName and year) then
        baseName, year, suffix = text:match('^(.-)%s+(%d+)%s+(года до н%. э%.)$')
        if baseName and year then
            bcFlag = true
        end
    end
    if not (baseName and year) then
        baseName, year, suffix = text:match('^(.-)%s+(%d+)%s+(году до н%. э%.)$')
        if baseName and year then
            bcFlag = true
        end
    end
    if not (baseName and year) then
        local y, after = text:match('^(%d+)%s+год%s+до н%. э%.%s*(.*)$')
        if y then
            bcFlag = true
            year = y
            if after ~= '' then
                suffix = 'год до н. э. ' .. after
            else
                suffix = 'год до н. э.'
            end
            baseName = ''
        else
            y, after = text:match('^(%d+)%s+год%s*(.*)$')
            if y then
                year = y
                if after ~= '' then
                    suffix = 'год ' .. after
                else
                    suffix = 'год'
                end
                baseName = ''
            end
        end
    end
    if not (baseName and year) then
        return ''
    end
    year = tonumber(year)
    if not year then
        return ''
    end
    local navRow = p._makeNavRow(baseName, year, suffix, bcFlag)
    local extraCats = p.getExtraCategories(text, year, bcFlag)
    return navRow .. '\n' .. extraCats
end

return p