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