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 %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