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

---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 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 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