Module:Thời biểu dân số

There are no reviewed versions of this page, so it may not have been checked for adherence to standards.

Documentation for this module may be created at Module:Thời biểu dân số/doc

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)
        if year 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 > 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)
        if year then
            table.insert(years, year)
            valuesByYear[year] = tonumber(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)
        if year then
            table.insert(years, year)
            valuesByYear[year] = tonumber(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)
        if year 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