Modulo:Diagramma parlamentare

Versione del 8 feb 2018 alle 19:57 di M.casanova (discussione | contributi) (fix errore variabile)
Info Istruzioni per l'uso
Questo è un modulo scritto in Lua. Le istruzioni che seguono sono contenute nella sottopagina Modulo:Diagramma parlamentare/man (modifica · cronologia)
Sandbox: Modulo:Diagramma parlamentare/sandbox (modifica · cronologia) · Sottopagine: lista · Test: Modulo:Diagramma parlamentare/test (modifica · cronologia · esegui)

Questo modulo serve a creare un diagramma parlamentare. È utilizzato da {{Diagramma parlamentare}} e da {{Risultati}}.

Fino alla versione 140050527 veniva usato il tag Graph (Vega versione 2).


require('Module:No globals')
local p = {}
local getArgs = require('Module:Arguments').getArgs
local colore = require('Module:Partiti').colore
local dimx = 175
local dimr = 50
local dimc = 40
local limite = 2000

-- crea unico array per stringa
local function agg(a,...)
    local args = {...}
    for _, s in ipairs(args) do
        table.insert(a, s)
    end
end

-- recupera colore del partito da Modulo:Partiti
-- a = partito; b = colore opzionale
local function colora(a,b)
	local c = colore({a,(b or '#CCC')})
	if string.sub(c,1,5) == '#' then c = "#" .. string.sub(c, 6, 11) end
	return c
end

-- crea punti
local function valori(n)
	local totali= {4, 17, 36, 65, 100, 144, 196, 255, 322, 398, 480, 571, 670, 776, 891, 1013, 1143, 1281, 1427, 1580, 1743, 1911, 2089}

   	local punti = 0
	local righe = 1
	local jj,rr,aa

	-- cerca numero di righe che permettano di mostrare tutti i punti
   	while (n > totali[righe]) do
      righe = righe + 1
	end
	local dd = dimr/righe -- distanza tra gli archi
	dimc = 0.7*dimr/righe -- dimensione dei cerchi
	local lista = {} -- lista dei punti
	-- calcola angolo e raggio di ogni punto
	for rg=0,righe-2 do
		rr = dimx - dd*(2*rg+1) -- raggio
    	jj = math.floor((n/totali[righe])*math.pi/(2*math.asin(dd/rr)))+1 --numero punti
    	if (jj==1) then
      		punti = punti + 1
        	lista[punti] = {0.5, rr}
    	else
        	for ps=0,jj-1 do
        		aa = ps/(jj-1)
        		punti = punti + 1
        		lista[punti] = {aa,rr}
        	end
        end
	end
	-- punti rimasti da porre su arco più interno
    jj=n-punti
    rr= dimx - dd*(2*righe-1) -- raggio
    if (jj==1) then
		punti = punti + 1
		lista[punti] = {1/2, rr}
    else
    	for ps=0,jj-1 do
			aa=ps/(jj-1)
			punti = punti + 1
			lista[punti] = {aa,rr}
		end
	end
	-- ordina punti per angolo crescente partendo dal centro
	table.sort(lista, function(a,b) return ((a[1]<b[1]) or (a[1]==b[1] and a[2]<b[2])) end)
	return lista
end

-- crea arco parlamentare
function p.parlamento(frame)
	local args = getArgs(frame, { valueFunc =
		function (key, value)
			if type(key) == "number" then
				if value == nil then return nil else value = mw.text.trim(value) end
			else
				if value == '' then return nil end
			end
			return value
		end })
	local err = {}
	agg(err, '<p style="color:#800"><b>Errore nel template:</b>')
	local ss = {}
	local ss2 = {}
	local dati = {}
	local num = 1
	local totalepunti = 0
	local dida = args['didascalia'] or ''
	local mostra = 'n'
	if (args['mostra'] and args['mostra']=='s') then mostra = 's' end

	while (args['n'..num]) do
		if (tonumber(args['n'..num])) then
			dati[num] = { n = args['n'..num] and tonumber(args['n'..num]), c = colora(args['p'..num] or '',args['c'..num]), b = args['b'..num] or '-' }
			totalepunti = totalepunti + dati[num].n
			num = num+1
		else
			agg(err,' Valore per n'..num..' non valido.')
		end
	end
	num = num - 1
	if (totalepunti>limite) then
		agg(err,' Numero di punti superiore al limite.')
	elseif (totalepunti<1) then
		agg(err,' Non sono stati indicati punti.')
	end
	if (#err == 1) then
		local punti = valori(totalepunti)
		local larghezza = 2*dimx
		local altezza = dimx+dimc
		local scala = 1.0
		if (args['larghezza'] and tonumber(args['larghezza'])) then
			larghezza = tonumber(args['larghezza'])
			scala = larghezza/(2*dimx)
			altezza = (dimx+dimc)*scala
		elseif (args['altezza'] and tonumber(args['altezza'])) then
			altezza = tonumber(args['altezza'])
			scala = altezza/(dimx+dimc)
			larghezza = 2*dimx*scala
		end
		local graph = {
			version = 2, width = larghezza, height = altezza, padding = "no",
			data = { },
			scales = {
				{ name = "x", type = "linear", range = "width", zero = true, domainMin = 0, domainMax = 2*dimx },
				{ name = "y", type = "linear", range = "height", zero = true, domainMin = 0, domainMax = dimx + dimc }
			},
			marks = { }
		}
		local ee = 0
		local valori
		for i=1,num do
			valori = {}
			for j=1,dati[i].n do
				ee = ee + 1
				valori[j] = {
					px = dimx-punti[ee][2]*math.cos(math.pi*punti[ee][1]),
					py = dimc+punti[ee][2]*math.sin(math.pi*punti[ee][1]),
				}
			end
			graph['data'][i] = { name = "tab"..i, values = valori }
			graph['marks'][i] = { type = "symbol", from = {data = "tab"..i },
				properties = {
					enter = {
						x = {scale = "x",field = "px"},
						y = {scale = "y",field = "py"},
						fill = {value = dati[i].c},
						size = {value = (2*dimc*scala)^2}
					}
				}
			}
			if (dati[i].b ~= "-") then
				graph['marks'][i]['properties']['enter']['stroke'] = {value = dati[i].b}
				graph['marks'][i]['properties']['enter']['strokeWidth'] = {value = 1}
			end
			agg(ss2,string.format('<span style="display:inline-block;border:solid grey 1px;background:%s;width:1em;height:1em">&nbsp;</span>&nbsp;%s', dati[i].c, dati[i].n))
		end
		graph['marks'][num+1] = {
			type = "text",
			properties = {
				enter = {
					x = {scale = "x",value=dimx},
					y = {scale = "y",value=dimc+8},
					align = {value = "center"},
					fill = {value = "#000"},
					font = {value = "Helvetica"},
					fontSize = { value = 36*scala },
					fontWeight = { value = "bold" },
					text = {value = totalepunti }
				}
			}
		}
		agg(ss, mw.getCurrentFrame():extensionTag('graph', mw.text.jsonEncode(graph)))
		if (dida ~= '') then
			agg(ss,string.format('<p style="font-size:90%%; margin-left:10px">%s</p>',dida))
		end
		if (mostra == 's') then
			agg(ss,'<p style="font-size:90%; margin-left:10px">')
			agg(ss,table.concat(ss2," · "))
			agg(ss,'</p>')
		end
		if args['debug'] then
			return mw.text.jsonEncode(graph)
		else
			return table.concat(ss)
		end
	else
		agg(err,'</p>')
		return table.concat(err)
	end
end

return p