Modul:Stanovništvo

Izvor: Wikipedija
Dokumentacija modula[stvori]
local Array = require('Module:Array')
local Arguments = require('Module:Arguments')
local NumberFormatting = require('Module:NumberFormatting')

local Stanovnistvo, Internal, Input, Output = {},{},{},{}

function Stanovnistvo.main(support,frame)
	Internal.parse(support,frame)
	Internal.output()
	return Output
end

------------------------------------------------------------------------------
-- Parser functions
------------------------------------------------------------------------------

function Internal.parse(support,frame)	
	Input.args = Array(Arguments.getArgs(frame))
	Input.support = support
	Internal.meta = Internal.parseMeta()
	Internal.categories = Internal.parseCategories()
end

function Internal.parseMeta()
	local meta = Input.support.meta
	local parsed = Array()
	parsed.title = Input.args[meta.title] or 'Sastav stanovništva'
	parsed.name = Input.args[meta.name] or ''
	parsed.type = Input.args[meta.type] or ''
	parsed.years = meta.years or Array()
	parsed.sources = Array()
	for k,v in Array.pairs(parsed.years) do
		if Input.args[v[3] .. '_' .. meta.source] ~= nil then
			parsed.sources[k] = Input.args[v[3] .. '_' .. meta.source]
		end
	end
	return parsed
end

function Internal.parseCategories()
	local categories = Input.support
	categories["meta"] = nil
	local parsed = Array()
	for categoryName,categoryRows in Array.pairs(categories) do
		local count = Array()
		for rowName,rowDefinition in Array.pairs(categoryRows) do
			for columnYearIndex,columnName in Array.pairs(rowDefinition[3]) do
				if Input.args[Internal.meta.years[columnYearIndex][3]..'_'..columnName] then
					if parsed[categoryName] == nil then 
						parsed[categoryName] = Array()
					end
					if parsed[categoryName][rowName] == nil then 
						parsed[categoryName][rowName] = Array()
					end
					parsed[categoryName][rowName][columnYearIndex] = Array()
					parsed[categoryName][rowName][columnYearIndex]["num"] = 
						tonumber(Input.args[Internal.meta.years[columnYearIndex][3]..'_'..columnName])
					if count[columnYearIndex] == nil then
						count[columnYearIndex] = parsed[categoryName][rowName][columnYearIndex]["num"]
					else
						count[columnYearIndex] = count[columnYearIndex] + 
							parsed[categoryName][rowName][columnYearIndex]["num"]
					end
					if Array.position(parsed["total"],1)[columnYearIndex]["num"] > 0 then
						parsed[categoryName][rowName][columnYearIndex]["pro"] = 
							parsed[categoryName][rowName][columnYearIndex]["num"] /
							Array.position(parsed["total"],1)[columnYearIndex]["num"]
					else
						parsed[categoryName][rowName][columnYearIndex]["pro"] = 0
					end
					if Input.support[categoryName][rowName][4] then
						if string.len(Input.support[categoryName][rowName][4][columnYearIndex]) ~= 0 then
							parsed[categoryName][rowName][columnYearIndex]["note"] = 
								Input.support[categoryName][rowName][4][columnYearIndex]
						end
					end
				end
			end
		end
		for yearIndex,yearDefinition in Array.pairs(Internal.meta.years) do
			if count[yearIndex] then
				if count[yearIndex] ~= Array.position(parsed["total"],1)[yearIndex]["num"] then
					if parsed[categoryName] ~= nil then
						local diff = Array.position(parsed["total"],1)[yearIndex]["num"] -
							count[yearIndex]
						if parsed[categoryName]["difference"] == nil then
							parsed[categoryName]["difference"] = Array()
						end
						parsed[categoryName]["difference"][yearIndex] = Array()
						parsed[categoryName]["difference"][yearIndex]["num"] = diff
						if Array.position(parsed["total"],1)[yearIndex]["num"] > 0 then
							parsed[categoryName]["difference"][yearIndex]["pro"] = 
								parsed[categoryName]["difference"][yearIndex]["num"] /
								Array.position(parsed["total"],1)[yearIndex]["num"]
						else
							parsed[categoryName]["difference"][yearIndex]["pro"] = 0
						end
					end
				end
			end
		end
	end
	return parsed
end

------------------------------------------------------------------------------
-- Output functions
------------------------------------------------------------------------------

function Internal.output()
	Output.root = mw.html.create('table')
		:css('text-align', 'center')
		:addClass('wikitable')
	Internal.outputHeader()
	Internal.outputCategories()
	Internal.outputNotes()
	Output = tostring(Output.root) .. tostring(Output.notes)
end

function Internal.outputHeader()
	--Title
	local tablehead = Output.root:tag('tr')
	local tableheadfirst = tablehead:tag('th')
		:css('background-color', '#D8D8D8')
		:attr('colspan',8)
	if Internal.meta.type ~= '' and Internal.meta.name ~= '' then
		tableheadfirst:wikitext(Internal.meta.title .. ' – ' .. Internal.meta.type .. ' ' .. Internal.meta.name)
	elseif Internal.meta.name ~= '' then
		tableheadfirst:wikitext(Internal.meta.title .. ' – ' .. Internal.meta.name)
	else
		tableheadfirst:wikitext(Internal.meta.title)
	end
	--Years
	local years = Output.root:tag('tr')
	local empty = years:tag('td')
		:css('background-color', '#F2F2F2')
		:css('border-bottom', '1px solid #000')
	for yearIndex,yearDefinition in Array.pairs(Internal.meta.years) do
		if Array.position(Internal.categories["total"],1)[yearIndex] then
			local yearth = years:tag('td')
				:css('background-color', '#F2F2F2')
				:css('color', '#333')
				:wikitext('[[' .. yearDefinition[2] .. '|' 
				 .. yearDefinition[1] .. ']]')
				:css('border-bottom', '1px solid #000')
			if Internal.meta.sources[yearIndex] ~= nil then
				local source = yearth:tag('span')
					:wikitext('' .. Internal.meta.sources[yearIndex])
			end
		end
	end
end

function Internal.outputCategories()
	Internal.notes = Array()
	for categoryName,categoryRows in Array.pairs(Internal.categories) do
		categoryRowsOld = categoryRows
		categoryRows = Internal.sortCategoryRowsByYears(categoryRows)
		local wikiTableTd, wikiTableTr, wikiTableRowTitleTd
		local lastline = false
		for rowName,rowColumns in Array.pairs(categoryRows) do
			if Array.position(categoryRows,Array.length(categoryRows)) == rowColumns and
			   Array.position(Internal.categories,Array.length(Internal.categories)) ~= categoryRowsOld then
				lastline = true
			end
			wikiTableTr = Output.root:tag('tr')
			local text = ''
			if Input.support[categoryName][rowName][2] then
				text = '[[' .. Input.support[categoryName][rowName][2]
						 .. '|' 
						 .. Input.support[categoryName][rowName][1] .. ']]'
			else
				text = Input.support[categoryName][rowName][1]
			end
			wikiTableRowTitleTd = wikiTableTr:tag('td')
				:wikitext(text)
				:css('text-align','left')
				:css('background-color','#F2F2F2')
			if lastline then
				wikiTableRowTitleTd:css('border-bottom', '1px solid #000')
			end
			for yearIndex,yearDefinition in Array.pairs(Internal.meta.years) do
				if rowColumns[yearIndex] then
					wikiTableTd = wikiTableTr:tag('td')
					local text,sup = '',''
					if rowColumns[yearIndex]["note"] then
						if not Array.inArray(Internal.notes,rowColumns[yearIndex]["note"]) then
							sup = Array.insert(Internal.notes,rowColumns[yearIndex]["note"])
						else
							sup = Array.length(Internal.notes)
						end
						sup = '<sup>'..sup..'</sup>'
					end
					text = text .. Internal.outputMakeNum(rowColumns[yearIndex]["num"])
							..Internal.outputMakePro(rowColumns[yearIndex]["pro"]) .. sup
					wikiTableTd
						:wikitext(text)
						:css('text-align','right')
						:css('background-color', 
							Internal.outputMakeBg(rowColumns[yearIndex]["highest"]))
					if lastline then wikiTableTd:css('border-bottom', '1px solid #000') end
				elseif Array.position(Internal.categories["total"],1)[yearIndex] then
					wikiTableTd = wikiTableTr:tag('td')
						:wikitext("–")
						:css('text-align','center')
					if lastline then wikiTableTd:css('border-bottom', '1px solid #000') end
				end
			end
		end
	end
end

function Internal.outputNotes()
	Output.notes = mw.html.create('ol')
		:css('list-style-type','none')
		:css('margin','0')
	for sup,text in Array.pairs(Internal.notes) do
		local li = Output.notes:tag('li')
			:wikitext('<small><sup>' .. sup .. '</sup> ' .. text .. '</small>')
	end
end

function Internal.sortCategoryRowsByYears(category)
	local sorted = Array()
	for yearIndex,yearDefinition in Array.pairs(Internal.meta.years) do
		indexByYear, indexByYearHighest = Array(), Array()
		for rowName,rowColumns in Array.pairs(category) do
			if rowColumns[yearIndex] and sorted[rowName] == nil then
				indexByYear[rowName] = rowColumns[yearIndex]["num"]
			end
			if rowColumns[yearIndex] then
				indexByYearHighest[rowName] = rowColumns[yearIndex]["num"]
			end
		end
		repeat
			local highestIndexByYear = Array(-1,'')
			for rowName,number in Array.pairs(indexByYear) do
				if number > highestIndexByYear[1] then
					highestIndexByYear[1] = number
					highestIndexByYear[2] = rowName
				end
			end
			sorted[highestIndexByYear[2]] = category[highestIndexByYear[2]]
			indexByYear[highestIndexByYear[2]] = nil
		until Array.length(indexByYear) == 0
		local highest = true
		repeat
			local highestIndexByYear = Array(-1,'')
			for rowName,number in Array.pairs(indexByYearHighest) do
				if number > highestIndexByYear[1] then
					highestIndexByYear[1] = number
					highestIndexByYear[2] = rowName
				end
			end
			if sorted[highestIndexByYear[2]] then
				sorted[highestIndexByYear[2]][yearIndex]["highest"] = highest
				highest = false
			end
			indexByYearHighest[highestIndexByYear[2]] = nil
		until Array.length(indexByYearHighest) == 0
	end
	return sorted
end

function Internal.outputMakeBg(bg)
	if bg == true then
		return '#E2E2E2'
	else
		return 'initial'
	end
end

function Internal.outputMakePro(pro)
	local length = 1
	if pro < 0.1 then
		length = 3
	elseif pro < 1 then
		length = 2
	end
	if pro == 0 then
		pro = ' (' .. '0,000' .. '%)' or ' ( - )'
	elseif pro ~= false then
		pro = ' (' .. NumberFormatting.format(pro * 100,length) .. '%)' or ' ( - )'
	else
		pro = ''
	end
	return pro
end

function Internal.outputMakeNum(num)
	return NumberFormatting.format(num,0)
end

return Stanovnistvo