Mô đun:Historical populations

--
-- Bản mẫu này thực hiện 
--
local p = {}
local lang = mw.getContentLanguage()
local Date -- lazy initialization
local function ifexist(page)
if not page then return false end
if mw.title.new(page).exists then return true end
return false
end
local function isempty( s )
	return not s or s:match( '^%s*(.-)%s*$' ) == 
end
local function splitnumandref( s )
	s = s:match( '^%s*(.-)%s*$' )
	local t1 = mw.text.unstrip(s)
local t2 = s:match( '^(%d%d,*)' )
	if( t1 == t2 ) then
		local t3 = s:match( '^%d%d,*(.-)$' )
		return t1, t3
	else
		return s, 
	end
end
local function formatnumR(num)
	return tonumber(lang:parseFormattedNumber(num))
end
local function formatnum(num)
	return lang:parseFormattedNumber(num) and lang:formatNum(lang:parseFormattedNumber(num)) or num
end
-- this function creates an array with the {year, population, percent change}
local function getpoprow(year, popstr, pyear, ppopstr, linktype, percentages, current_year)
	local pop, popref = splitnumandref( popstr or )
	local ppop, ppopref = splitnumandref( ppopstr or )
	local percent = 
	local yearnum = formatnumR(mw.ustring.gsub(year or , '^%s*(%d%d%.%d+).*$', '%1') or )
	local pyearnum = formatnumR(mw.ustring.gsub(pyear or , '^%s*(%d%d%.%d+).*$', '%1') or )
	local popnum = formatnumR(pop)
	local ppopnum = formatnumR(ppop)
	if( linktype == 'US' or linktype == 'USA' ) then
		if( (yearnum or 0) >= 1790 and yearnum  0)) then
			if(percentages == 'pagr') then
				pstr = mw.ustring.format('%.2f', 100*math.abs(math.pow(popnum/ppopnum,1/(yearnum-pyearnum)) - 1))
			elseif(percentages == 'monthly') then
				if Date == nil then Date = require('Mô đun:Date')._Date end
				local date1 = Date(year)
				local date2 = Date(pyear)
				local diff = date1 - date2
				local months = (diff.age_days/(365.25/12))
				pstr = mw.ustring.format('%.2f', 100*math.abs(math.pow(popnum/ppopnum,1/months) - 1))
			else
				pstr = mw.ustring.format('%.1f', 100*math.abs(popnum/ppopnum - 1))
			end
			if( popnum Số dân'
	end
	-- percentages cell
	if( percentages ~= 'off' and percentname == ) then
		if( percentages == 'pagr' ) then
			percentname = '±% năm'
		elseif( percentages == 'monthly' ) then
			percentname = '±% tháng'
		else
			percentname = '±%'
		end
	end
	return {yearname, popname, percentname}
end
-- this function builds the json for the population graph
local function graphjson(data, gwidth, gheight)
	local yearcount = #data
	local graphargs = {
		'width' = gwidth,
		'height' = gheight,
		'type' = 'line',
		'yAxisTitle' = 'Dân số',
		'yAxisMin' = 0,
		'xAxisTitle' = 'Năm',
		'xAxisAngle' = '-45',
		'yGrid' = 'y',
		'yAxisFormat' = ',d',
		'x' = ,
		'y' = 
	}
	local firstpoint = true
	for offset = 1,yearcount do
		local x,y = dataoffset1, dataoffset2
		-- delink if necessary
		if x:match('^%s*%%^%%*%|(^%%*)%%') then
			x = x:match('^%s*%%^%%*%|(^%%*)%%')
		end
		y = formatnumR(y)
		if x and y then
			graphargs'x' = graphargs'x' .. (firstpoint and  or ', ') .. x
			graphargs'y' = graphargs'y' .. (firstpoint and  or ', ') .. y
			firstpoint = false
		end
	end
	local Graph = require('Mô đun:Graph')
	
	return Graph.chart({args = graphargs})
end
local function rendergraph(frame, data, gwidth, gheight, gthumb)
	local graph = frame:extensionTag{
			name = 'templatestyles', 
			args = { src = 'Graph:Chart/styles.css'} 
		} .. frame:extensionTag{name = 'graph', content = graphjson(data, gwidth, gheight)}
	if(gthumb ~= ) then
		local graphdiv = mw.html.create('div')
			:addClass('thumb')
			:addClass(gthumb == 'right' and 'tright' or 'tleft')
			:css('clear', 'none')
		graphdiv
			:tag('div')
			:addClass('thumbinner')
			:wikitext(graph)
		return tostring(graphdiv)
	end
	
	return  .. graph .. 
end
-- this function renders the population table in a vertical format
local function rendervertical(data, head, title, footnote, alignfn, class, style, width, shading, percol, cols, graphpos, graph)
	-- define a couple helper functions
	local function addrowcell(trow, tag, text, align, shading, style)
		cell = trow:tag(tag)
		cell
			:css('text-align', align)
			:css('padding', '1px')
			:wikitext(text)
			:css('border-bottom', shading ~= 'off' and '1px solid #bbbbbb' or nil)
			:cssText(style)
	end
	local function addheadcell(trow, text, align, width, pad)
		cell = trow:tag('th')
		cell
			:css('border-bottom', '1px solid black')
			:css('padding', pad and ('1px ' .. pad) or '1px')
			:css('text-align', align)
			:css('width', width)
			:wikitext(text)
	end
	local colspan = 3
	local yearcount = #data
	local argcount = 2*yearcount
	
	if( isempty(width) ) then
		width = '15em'
	end
	
	-- override the value of cols if percol has been specified
	if( percol > 0 ) then
		cols = math.floor( (yearcount - 1) / percol ) + 1
	end
	
	-- compute the number of rows per col
	local rowspercol = math.floor( (yearcount - 1) / cols ) + 1
	-- specify the colspan for the title and footer lines
	if( cols > 1 ) then
	else
		if (head3 == ) then 
		else
		end
	end
	-- compute outer table width
	local twidth = width
	if( (cols > 1) and width:match('^%s*%d+%w+%s*$') ) then
		local widthnum = mw.ustring.gsub( width, '^%s*(%d+)(%w+)%s*$', '%1' )
		local widthunit = mw.ustring.gsub( width, '^%s*(%d+)(%w+)%s*$', '%2' )
		twidth = tostring(widthnum*cols) .. widthunit
	end
	
	-- create the outer table
	local root = mw.html.create('table')
	root
		:addClass(class)
		:css('width', twidth)
		:css('border-top-width', '0')
		:cssText(style'table')
	-- add title
	local caption = root:tag('caption')
	caption
		:css('border-top', '1px #aaa solid')
		:css('border-left', '1px #aaa solid')
		:css('border-right', '1px #aaa solid')
		:css('background-color', 'lavender')
		:css('padding', '0.25em')
		:css('font-weight', 'bold')
		:wikitext(title)
		
	-- add the graph line (if top graph)
	if((graphpos == 'top' or graphpos == 't') and graph ~= ) then
		row = root:tag('tr')
		cell = row:tag('td')
		cell
			:attr('colspan', colspan)
			:css('border-bottom', '1px solid black')
			:wikitext(graph)
		graph = 
	end
	
	-- loop over columns and rows within columns
	local offset = 1
	local t = root
	for c = 1,cols do
		-- add inner tables if we are rendering more than one column
		if( cols > 1) then
			if (c == 1) then
				row = root:tag('tr')
				row:attr('valign', 'top')
				cell = row:tag('td')
				cell:css('padding', '0 0.5em')
			else
				cell = row:tag('td')
				cell
					:css('padding', '0 0.5em')
					:css('border-left', 'solid 1px #aaa')
			end
			t = cell:tag('table')
			t
				:css('border-spacing', '0')
				:css('width', width)
		end
		-- start column headers
		local hrow = t:tag('tr')
		hrow:css('font-size', '95%')
		-- year header
		addheadcell(hrow, head1, nil, head3 ~=  and '3em' or 'auto', nil, nil)
		-- population header
		addheadcell(hrow, head2, 'right', nil, '2px')
		-- percentages header
		if( head3 ~=  ) then
			addheadcell(hrow, head3, 'right', nil, nil)
		end
		-- end column headers
		-- start population rows
		for r = 1,rowspercol do
			-- generate the row if we have not exceeded the rowcount
			-- shade every fifth row, unless shading = off
			local s = 'off'
			if( math.fmod((c - 1)*rowspercol + r, 5) == 0 and r ~= rowspercol) then
				s = shading
			end
			if(offset  0 ) then
		rows = math.floor( (yearcount - 1) / perrow ) + 1
	end
	
	-- compute the number of cols per row
	local colsperrow = math.floor( (yearcount - 1) / rows ) + 1
	-- create the outer table
	local root = mw.html.create('table')
	root
		:addClass(class)
		:css('font-size', '90%')
		:cssText(style'table')
	-- create title row
	row = root:tag('tr')
	cell = row:tag('th')
	cell
		:css('padding', '0.25em')
		:attr('colspan', colsperrow + 1)
		:wikitext(title)
	-- add the graph line (if top graph)
	if((graphpos == 'top' or graphpos == 't') and graph ~= ) then
		row = root:tag('tr')
		cell = row:tag('td')
		cell
			:attr('colspan', colsperrow + 1)
			:css('border-bottom', '1px solid black')
			:wikitext(graph)
		graph = 
	end
	-- loop over rows and columns within rows
	local offset = 1
	for r = 1,rows do
		local rowoffset = offset
		-- render the years
		row = root:tag('tr')
		cell = row:tag('th')
		cell:wikitext(head1)
			:css('border-top', r > 1 and '2px solid #000' or nil)
		for c = 1,colsperrow do
			cell = row:tag('td')
			if(offset  1 and '2px solid #000' or nil)
					:cssText(style'year')
			else
				cell:css('border-width', r > 1 and '2px 0 0 0' or 0)
					:css('border-top', r > 1 and '2px solid #000' or nil)
			end
			offset = offset + 1
		end
		-- render the pop
		offset = rowoffset
		row = root:tag('tr')
		cell = row:tag('th')
		cell:wikitext(head2)
		for c = 1,colsperrow do
			cell = row:tag('td')
			if(offset '
		end
	end
	footnote = footnote .. source
	
	-- setup the data header cols/rows
	local head = getheadrow(percentages, popname, yearname, percentname)
	
	-- count the total number of population rows
	local argcount = 0
	local rowcount = 0
	for k, v in pairs( args ) do
		if ( (type( k ) == 'number') and (not isempty(argsk)) ) then
			if( k >= 1 and math.floor(k) == k and k > argcount) then
				argcount = k
			end
			if( math.fmod(k - 1, 2) == 0 ) then
				rowcount = rowcount + 1
			end
		end
	end
	-- here is where we build all the data for the table
	-- loop over columns and rows within columns
	local pyear = 
	local ppop = 
	local offset = 1
	local current_year = tonumber(os.date("%Y", os.time()))
	for r = 1,rowcount do
		-- skip blank rows
		while(isempty(argsoffset) and offset <= argcount) do
			offset = offset + 2
		end
		-- generate the row if we have not exceeded the rowcount
		if(offset <= argcount) then
			table.insert(data, getpoprow(argsoffset, argsoffset + 1 or , pyear, ppop, 
				linktype, percentages, current_year) )
			pyear = argsoffset
			ppop = argsoffset+1 or 
			offset = offset + 2
		end
	end
	local graph = 
	graphpos = graphpos:lower()
	-- now that we have the data for the table, render it in the requested format
	if (direction == 'horizontal') then
		if graphpos ~=  then
			local gwidth = tonumber(graphwidth) or 200
			local gheight= tonumber(graphheight) or 170
			local gthumb = 
				(graphpos == 'r' or graphpos == 'right' and 'right') or
				(graphpos == 'l' or graphpos == 'left' and 'left') or 
			graph = rendergraph(frame, data, gwidth, gheight, gthumb)
		end
		return renderhorizontal(data, head, title, footnote, alignfn, class, style, width, shading, perrow, rows, graphpos, graph)
	else
		if graphpos ~=  then
			local gwidth = tonumber(graphwidth) or (170 * cols)
			local gheight= tonumber(graphheight) or 170
			local gthumb = 
				(graphpos == 'r' or graphpos == 'right' and 'right') or
				(graphpos == 'l' or graphpos == 'left' and 'left') or 
			graph = rendergraph(frame, data, gwidth, gheight, gthumb)
		end
		return rendervertical(data, head, title, footnote, alignfn, class, style, width, shading, percol, cols, graphpos, graph)
	end
end
return p