Mô đun:Thời biểu dân số

Tài liệu mô đun[tạo]
---Các hàm phân tích dữ liệu cho [[Bản mẫu:Thời biểu dân số]]
local p = {}
local m = require("Module:Math") -- [[Module:Math]]

---Horizontal width of each bar, including spacing, when there is no risk of the
-- graph overflowing the allotted horizontal space.
local defaultBarIncrement = 35 -- px

---Returns the [[Lịch Gregory đón trước|proleptic Gregorian]] (ISO 8601)
-- representation of the year in the given argument.
function p.toyear(arg)
    local year = tonumber(arg)
    if year then return year end
    
    year = string.match(arg, "(%d+) *S?CN")
    if year then
        year = math.floor(tonumber(year))
        assert(year > 0, "Không có năm " .. year .. " CN.")
        return year
    end
    
    year = string.match(arg, "(%d+) *TCN") or string.match(arg, "(%d+) *TTL")
    if year then
        year = math.floor(tonumber(year))
        assert(year > 0, "Không có năm " .. year .. " TCN.")
        return -1 * year + 1
    end
end

---Returns the total span of years represented in the given data.
function p.count(frame)
    local args = frame:getParent().args
    local earliestYear = math.huge
    local latestYear = 0
    for year, value in pairs(args) do
        year = p.toyear(year)
        value = tonumber(value)
        if year and value then
            if year < earliestYear then earliestYear = year end
            if year > latestYear then latestYear = year end
        end
    end
    return latestYear - earliestYear + 1
end

function p.max(frame)
    local args = frame:getParent().args
    local maxYear = 0
    local maxValue = 0
    for year, value in pairs(args) do
        year = p.toyear(year)
        value = tonumber(value)
        if year and value and value > maxValue then
            maxValue = value
            maxYear = year
        end
    end
    return maxValue
end

function p.maxorder(frame)
    return m._order(p.max(frame))
end

function p.fit(frame)
    local max = p.max(frame)
    if max == 0 then return 0 end
    return (math.ceil(max / 10^(m._order(max) - 1))) * 10^(m._order(max) - 1)
end

---Returns the global minimum of the derivative of the set of numbers in the
-- given array.
function minInterval(numbers)
    local dxmin = math.huge
    for i = 2, #numbers do
        local x = numbers[i]
        local xlast = numbers[i - 1]
        if x - xlast < dxmin then dxmin = x - xlast end
    end
    return dxmin
end

function p.barIncrement(frame)
    local args = frame:getParent().args
    local years = {}
    local valuesByYear = {}
    for year, value in pairs(args) do
        year = p.toyear(year)
        value = tonumber(value)
        if year and value then
            table.insert(years, year)
            valuesByYear[year] = value
        end
    end
    table.sort(years)
    local width = defaultBarIncrement / minInterval(years)
    local count = p.count(frame)
    if math.ceil(width) * count <= 1600 - 60 then return width end
    return math.floor((1600 - 60) / count)
end

function p.bars(frame)
    local args = frame:getParent().args
    local years = {}
    local valuesByYear = {}
    for year, value in pairs(args) do
        year = p.toyear(year)
        value = tonumber(value)
        if year and value then
            table.insert(years, year)
            valuesByYear[year] = value
        end
    end
    table.sort(years)
    for year = years[1], years[#years] do
        if not valuesByYear[year] then
            table.insert(years, year)
        end
    end
    table.sort(years)
    local bars = {}
    for i, year in ipairs(years) do
        local bar = "  bar:" .. year
        if valuesByYear[year] then
            bar = bar .. " text:" .. year
        end
        table.insert(bars, bar)
    end
    return table.concat(bars, "\n")
end

function p.plots(frame)
    local args = frame:getParent().args
    local plots = {}
    for year, value in pairs(args) do
        year = p.toyear(year)
        value = tonumber(value)
        if year and value then
            local plot = string.format("  bar:%i from:0 till:%i", year, value)
            table.insert(plots, plot)
        end
    end
    return table.concat(plots, "\n")
end

function p.labels(frame)
    local args = frame:getParent().args
    local lang = mw.getContentLanguage()
    local labels = {}
    for year, value in pairs(args) do
        year = p.toyear(year)
        value = tonumber(value)
        if year and value then
            local label = string.format("  bar:%i at:%i text:%s",
                year, value, lang:formatNum(value))
            table.insert(labels, label)
        end
    end
    return table.concat(labels, "\n")
end

return p