Modulo:Demografia/sandbox

Da Wikipedia, l'enciclopedia libera.
Vai alla navigazione Vai alla ricerca
require("strict")
local getArgs = require('Module:Arguments').getArgs
local p = {}

local minimo, massimo

-- =====================================================================
-- Legge gli argomenti per caricare un array di valori numerici.
-- Prima tenta di leggere il parametro <list_name> che deve contenere una
-- lista di valori separati da ",". 
-- Se fallisce tenta di leggere i singoli valori 
-- <base_name1>, <base_name2> .. <base_name20>
-- Eventuali valori non numerici sono ignorati
-- =====================================================================
local function read_array(args, base_name, list_name)
	local array = {}
	if args[list_name] then
		array = mw.text.split(string.gsub(args[list_name], "%s", ""), ",")
	end
	-- mi assicuro di tenere solo i primi venti valori
	if #array > 20 then
		for i = 21, #array do
			array[i] = nil
		end
	end 
	-- se l'array ha lunghezza nulla tento di leggere i valori con il vecchio metodo
	if #array == 0 then
		for i= 1,20 do
			array[i] = args[base_name .. tonumber(i)]
		end
	end
	-- converto in numeri
	for i =1,20 do
		array[i] = array[i] and tonumber(array[i])
	end
	return array
end
-- =====================================================================
-- Fonde le due liste years e population in un'unica lista
-- =====================================================================
local function merge_years_population(years, populations)
	local values = { }
	local t
	for i =1,#populations do
		if (minimo == nil or years[i] < minimo) then minimo = years[i] end
		if (massimo == nil or years[i] > massimo) then massimo = years[i] end
		t = string.format("%g",math.floor(populations[i]+0.5))
		t = t:gsub('%.',',')
		values[i] = { year = years[i], population = populations[i], num = i, txt = t }
	end
	return values
end

-- =====================================================================
-- Crea tabella laterale
-- =====================================================================
local function formato(a)
	local k
	local s = ''..a
	while true do
		s, k = s:gsub("^(-?%d+)(%d%d%d)", '%1&nbsp;%2')
		if (k==0) then break end
	end
	return s
end

local function mostraTabella(a,b,f)
	local ss = {}
	table.insert(ss,'</td><td style="vertical-align:top"><table class="wikitable" style="font-size:smaller;text-align:right"><tr><th>Anno</th><th>Abitanti</th>')
	if #b > 12 then
		table.insert(ss,'<th>Anno</th><th>Abitanti</th></tr>')
		local c = math.floor(0.5+#b/2)
		for i =1,c do
			table.insert(ss,string.format('<tr><th>%s</th><td>%s</td>',a[i],formato(math.floor(b[i]*f+0.5))))
			if b[i+c] then table.insert(ss,string.format('<th>%s</th><td>%s</td>',a[i+c],formato(math.floor(b[i+c]*f+0.5)))) end
			table.insert(ss,'</tr>')
		end
	else
		table.insert(ss,'</tr>')
		for i =1,#b do
			table.insert(ss,string.format('<tr><th>%s</th><td>%s</td></tr>',a[i],formato(math.floor(b[i]*f+0.5))))
		end
	end
	table.insert(ss,'</table></td></tr></table>')
	return table.concat(ss)
end

-- =====================================================================
-- Generazione del grafico demografico
-- =====================================================================
function p._demografia(args)
	-- Definizione base del grafico
	local graph = {
		version = 2,
		width = 450,
		height = 250,
		padding = "auto",
		data = {
			{
				name = "table",
				transform = {
					{ type = "formula", field = "population", expr = "round(datum.population)" },
					{ type = "sort", by = "year" }
				},
				values = { }
			},
			{
				name = "table2",
				transform = {
					{ type = "formula", field = "population", expr = "round(datum.population)" },
					{ type = "sort", by = "year" }
				},
				values = {  }
			}
		},
		scales = {
			{
				name = "x",
				type = "linear",
				range = "width",
				zero = false,
				domain = {fields = {{data = "table",field = "year"}, {data = "table2",field = "year"}}}
			},
			{
				name = "y",
				type = "linear",
				range = "height",
				nice = true,
				domain = {fields = {{data = "table",field = "population"}, {data = "table2",field = "population"}}}
			}
		},
		axes = {
			{
				type = "x",
				scale = "x",
				format = "d",
				title = "Anno",
				grid = true,
				properties = {
					labels = { font = { value = "Helvetica" } },
					title = { font = { value = "Helvetica" } }
				}
			},
			{
				type = "y",
				scale = "y",
				title = "Abitanti",
				grid = true,
				layer = "back",
				properties = {
					labels = { font = { value = "Helvetica" } },
					title = { font = { value = "Helvetica" } }
				}
			}
		},
		marks = {
			{
				type = "line",
				from = {data = "table" },
				properties = {
					enter = {
						interpolate = {value = "linear"},
						x = {scale = "x",field = "year"},
						y = {scale = "y",field = "population"},
						stroke = {value = "#1f77b4"},
						strokeWidth = {value = 4},
						opacity = {value = 0.5}
					}
				}
			},
			{
				type = "symbol",
				from = {data = "table2"},
				properties = {
					enter = {
						x = {scale = "x",field = "year"},
						y = {scale = "y",field = "population"},
						stroke = {value = "#1f77b4"},
						fill = {value = "#fff"},
						size = {value = 18}
					}
				}
			},
			{
				type = "symbol",
				from = {data = "table"},
				properties = {
					enter = {
						x = {scale = "x",field = "year"},
						y = {scale = "y",field = "population"},
						stroke = {value = "1f77b4"},
						fill = {value = "#fff"},
						size = {value = 30}
					}
				}
			},
			{
				type = "text",
				from = {data = "table"},
				properties = {
					enter = {
						x = {scale = "x",field = "year"},
						y = {scale = "y",field = "population", offset = -8},
						align = {value = "center"},
						fill = {value = "#000"},
						text = {field = "txt" },
						font = {value = "Helvetica"},
					}
				}
			},
			{
				type = "text",
				from = {
					data = "table",
					transform = {
						{
						 type = "aggregate",
						 summarize = {year = {"min","max"}}
						}
					}
				},
				properties = {
					enter = {
						x = {signal = "width",mult = 0.5},
						y = {value = -10},
						text = {
						 template = ""
						},
						fill = {value = "black"},
						fontSize = {value = 14},
						font = {value = "Helvetica"},
						align = {value = "center"},
						fontWeight = {value = "bold"}
					}
				}
			}
		}
	}
	local titolo = args.titolo or args[1] or "Abitanti censiti"
	if args.fonte then
		titolo = titolo .. '<ref>' .. args.fonte .. '</ref>'
	end
	titolo = titolo .. '\n\n'
	local populations = read_array(args, "p", "popolazione")
	local years = read_array(args, "a", "anni")
	local populations2 = read_array(args, "pb", "popolazione2")
	local years2 = read_array(args, "b", "anni2")
	graph['data'][1]['values'] =  merge_years_population(years, populations)
	graph['data'][2]['values'] =  merge_years_population(years2, populations2)
	graph['width'] = args.dimx and tonumber(args.dimx) and tonumber(args.dimx)
	graph['height'] = args.dimy and tonumber(args.dimy) and tonumber(args.dimy)
	local tabella1 = ''
	local tabella2 = ''
	local fattore = args.fattore and tonumber(args.fattore) and tonumber(args.fattore) or 1
	if fattore == 1000 then
		graph['axes'][2]['title'] = 'Abitanti (migliaia)'
	elseif fattore == 1000000 then
		graph['axes'][2]['title'] = 'Abitanti (milioni)'
	end
	if args.etichette then
		if args.etichette == "dispari" then
			-- mostra solo etichette dispari
			graph['marks'][4]['from']['transform'] = {{ type = "filter", test = "datum.num % 2 == 1"}}
		elseif args.etichette == "pari" then
			-- mostra solo etichette pari
			graph['marks'][4]['from']['transform'] = {{ type = "filter", test = "datum.num % 2 == 0"}}
		elseif args.etichette == "tabella" then
			-- nasconde etichette e crea tabella a fianco
			graph['marks'][4]['from']['transform'] = {{ type = "filter", test = "datum.num < 1"}}
			tabella1 = '<table><tr><td style="vertical-align:top">'
			tabella2 = mostraTabella(years, populations, fattore)
		end
	end 
	--if true then return mw.text.jsonEncode(graph) end
	local template_text = "Censimenti dal {{datum.min_year}} al {{datum.max_year}}"
	if #years2 > 0 then 
		graph['marks'][5]['properties']['enter']['text']['template'] = template_text .. " e dati annuali"
	else
		graph['marks'][5]['properties']['enter']['text']['template'] = template_text 
	end
	
	if (massimo - minimo > 1) then
		graph['scales'][1]['domainMin'] = minimo - (massimo-minimo)*0.04
		graph['scales'][1]['domainMax'] = massimo + (massimo-minimo)*0.04
	end
	
	local ris = {}
	table.insert(ris,titolo)
	table.insert(ris,tabella1)
	table.insert(ris,mw.getCurrentFrame():extensionTag('graph', mw.text.jsonEncode(graph)))
	table.insert(ris,tabella2)
	return table.concat(ris)
end

-- ======================================================================================================
-- Funzione di intefaccia con template:Demografia
-- ======================================================================================================
function p.demografia(frame)
	local args = getArgs(frame)
	return p._demografia(args)
end

return p