Dokumentacija modula[uredi] [historija] [osvježi keš]
Ova dokumentacija je prikazana u Modul:Stanovništvo/dok.

Ovaj modul omogućava pravljenje Modula za prikaz Stanovništva. Ovo je meta-modul, što znači da je napravljen da se koristi u drugim modulima i da se nebi trebao koristiti preko #invoke direktno.

Osnovno korištenje

Prvo je potrebno učitati modul.

local pop = require('Modul:Stanovništvo')

Poslije se napuni tabela 'support' sa svim informacijama koje se hoće da koristi u novom Modulu, odnosno šablonu.

support = {
	meta = {
		title = 'naslov_tabele',
		name = 'ime_naseljenog_mjesta',
		type = 'vrsta_naseljenog_mjesta',
		years = {
			g2013 = {'2013.','g2013','Popis stanovništva u Bosni i Hercegovini 2013.'},
			g1991 = {'1991.','g1991','Popis stanovništva u SR Bosni i Hercegovini 1991.'},
			g1981 = {'1981.','g1981','Popis stanovništva u SR Bosni i Hercegovini 1981.'},
			g1971 = {'1971.','g1971','Popis stanovništva u SR Bosni i Hercegovini 1971.'}
		}
	},
	total = {
		total = {'Ukupno','ukupno','ukupno','ukupno','ukupno'},
		difference = {'Ostali','ostali','ostali','ostali','ostali'}
	},
	gender = {
		muskih = {'Muških','muskih','muskih','muskih','muskih','Muškarac'},
		zenski = {'Ženski','zenski','zenski','zenski','zenski','Žena'},
		difference = {'Ostali','ostali','ostali','ostali','ostali'}
	},
	ethnics = {
		bosnjaci = {'Bošnjaci','muslimani','muslimani','muslimani','bosnjaci','Bošnjaci',
			{
				'Modalitet [[Muslimani]] se danas označava kao modalitet [[Bošnjaci]].',
				'Modalitet [[Muslimani]] se danas označava kao modalitet [[Bošnjaci]].',
				'Modalitet [[Muslimani]] se danas označava kao modalitet [[Bošnjaci]].',
				''
			}
		},
		srbi = {'Srbi','srbi','srbi','srbi','srbi','Srbi'},
		hrvati = {'Hrvati','hrvati','hrvati','hrvati','hrvati','Hrvati'},
		jugosloveni = {'Jugoslaveni','jugosloveni','jugosloveni','jugosloveni','jugosloveni','Jugoslaveni'},
		crnogorci = {'Crnogorci','crnogorci','crnogorci','crnogorci','crnogorci','Crnogorci'},
		makedonci = {'Makedonci','makedonci','makedonci','makedonci','makedonci','Makedonci'},
		slovenci = {'Slovenci','slovenci','slovenci','slovenci','slovenci','Slovenci'},
		albanci = {'Albanci','albanci','albanci','albanci','albanci','Albanci'},
		cesi = {'Česi','cesi','cesi','cesi','cesi','Česi'},
		italijani = {'Italijani','italijani','italijani','italijani','italijani','Italijani'},
		jevreji = {'Jevreji','zidovi','zidovi','jevreji','jevreji','Jevreji',
			{
				'Modalitet [[Židovi]] se danas označava kao modalitet [[Jevreji]].',
				'Modalitet [[Židovi]] se danas označava kao modalitet [[Jevreji]].',
				'Modalitet [[Židovi]] se danas označava kao modalitet [[Jevreji]].',
				''
			}
		},
		madari = {'Mađari','madari','madari','madari','madari','Mađari'},
		nijemci = {'Nijemci','nijemci','nijemci','nijemci','nijemci','Nijemci'},
		poljaci = {'Poljaci','poljaci','poljaci','poljaci','poljaci','Poljaci'},
		romi = {'Romi','romi','romi','romi','romi','Romi'},
		rumuni = {'Rumuni','rumuni','rumuni','rumuni','rumuni','Rumuni'},
		rusi = {'Rusi','rusi','rusi','rusi','rusi','Rusi'},
		rusini = {'Rusini','rusini','rusini','rusini','rusini','Rusini'},
		slovaci = {'Slovaci','slovaci','slovaci','slovaci','slovaci','Slovaci'},
		turci = {'Turci','turci','turci','turci','turci','Turci'},
		ukrajinci = {'Ukrajinci','ukrajinci','ukrajinci','ukrajinci','ukrajinci','Ukrajinci'},
		nisu_izjasnili = {'Nisu se izjasnili','nisu_izjasnili','nisu_izjasnili','nisu_izjasnili','nisu_izjasnili'},
		regionalno = {'Regionalno','regionalno','regionalno','regionalno','regionalno'},
		nepoznato = {'Nepoznato','nepoznato','nepoznato','nepoznato','nepoznato'},
		difference = {'Ostali','ostali','ostali','ostali','ostali'}
	}
}

Poslije toga se napravi funkcija 'bhPop.main' u kojoj se funkciji 'pop.main' preda podatke iz tabele 'frame' i završi modul sa 'return pop'.

function bhPop.main(frame)
	pop.main(frame)
end
 
return pop

tabela support

meta

(table) meta: glavne informacije o modulu. (cardinality:1)

  • (string) title: Ime parametara koji se koristi za prikaz naslova tabele. (1)
  • (string) name: Ime parametara koji se koristi za prikaz imena naseljenog mjesta. (1)
  • (string) type: Ime parametara koji se koristi za prikaz vrste naseljenog mjesta. (1)
  • (table) years: Tabela sa godinama popisa stanovništva. (1)
    • (table) year-[x]: Tabela sa dodatnim informacijama popisa stanovništva. (1*)
    1. (string) naslov pukotine. (1)
    2. (string) ime parametara koji se koristi za prikaz godina. (1)
    3. (string) ime članka. (1)
support = {
	meta = {
		title = 'naslov_tabele',
		name = 'ime_naseljenog_mjesta',
		type = 'vrsta_naseljenog_mjesta',
		years = {
			g2013 = {'2013.','g2013','Popis stanovništva u Bosni i Hercegovini 2013.'},
			g1991 = {'1991.','g1991','Popis stanovništva u SR Bosni i Hercegovini 1991.'},
			g1981 = {'1981.','g1981','Popis stanovništva u SR Bosni i Hercegovini 1981.'},
			g1971 = {'1971.','g1971','Popis stanovništva u SR Bosni i Hercegovini 1971.'}
		}
	},
	[...]
}

types

Jedan 'type' može sve moguće biti, kao na primjer 'ukupno', 'nacionalnost', 'spol', itd. Ime tabele nije bitan, koristi se samo interno.

(table) [type]: kontejner sa pod tabela koji reprezentiraju jedan redak u tablici. (cardinality:1*)

  • (table) [subtype-[x]]: Tabela sa informacijama od tog redaka u tablici. (1*)
  1. (string) naslov redaka u tablici. (1)
  2. (string) ime parametara koji se koristi za prikaz 'subtype'-a u toj godini, prvi je za najstariji popis, zadnji za najnoviji. ([broj godina])
  3. (string) ime članka. (*1)
  4. (table) tabela za dodavanje dodatnih informacijama o jednom 'subtype'-u u jednoj specifičnoj godini kroz [0-9]. (*1)
    • (string) teksta kojega se treba dodati, prvi je za najstariji popis, zadnji za najnoviji. ([broj godina])
  • (table) difference: Isti princip kao kod tabele subtype-[x], parametar služi kao redak u tablici za diferencije između ostalih parametrima. (1)
support = {
	[...]
	ethnics= {
		bosnjaci = {'Bošnjaci','muslimani','muslimani','muslimani','bosnjaci','Bošnjaci',
			{
				'Modalitet [[Muslimani]] se danas označava kao modalitet [[Bošnjaci]].',
				'Modalitet [[Muslimani]] se danas označava kao modalitet [[Bošnjaci]].',
				'Modalitet [[Muslimani]] se danas označava kao modalitet [[Bošnjaci]].',
				''
			}
		},
		srbi = {'Srbi','srbi','srbi','srbi','srbi','Srbi'},
		hrvati = {'Hrvati','hrvati','hrvati','hrvati','hrvati','Hrvati'},
		jugosloveni = {'Jugoslaveni','jugosloveni','jugosloveni','jugosloveni','jugosloveni','Jugoslaveni'},
		crnogorci = {'Crnogorci','crnogorci','crnogorci','crnogorci','crnogorci','Crnogorci'},
		makedonci = {'Makedonci','makedonci','makedonci','makedonci','makedonci','Makedonci'},
		slovenci = {'Slovenci','slovenci','slovenci','slovenci','slovenci','Slovenci'},
		albanci = {'Albanci','albanci','albanci','albanci','albanci','Albanci'},
		[...]
		difference = {'Ostali','ostali','ostali','ostali','ostali'}
	}
	[...]
}

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