Modulo:Sandbox/M.casanova/SecondoLivelloItaliano

require('Module:No globals')
local p = {}
local getArgs = require('Module:Arguments').getArgs
local colore = require('Module:Partiti').colore
local lcella = 60
local tcella = '<th width="'..lcella..'px">Voti</th><th width="'..lcella..'px">%</th>'
local ff = 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 edate = '<br/><span style="font-size:85%%">%s</span>'

-- html per affiancamento di tabelle tramite parametro "allinea"
local flex = {}
flex['primo'] = {'<div style="display:flex;flex-direction:row;flex-wrap:wrap"><div style="flex-grow:0;flex-shrink:0;flex-basis:auto;padding: 0 2em 0 0">','</div>','0'}
flex['medio'] = {'<div style="flex-grow:0;flex-shrink:0;flex-basis:auto;padding: 0 2em 0 0">','</div>','0'}
flex['ultimo'] = {'<div style="flex-grow:0;flex-shrink:0;flex-basis:auto;padding: 0 2em 0 0">','</div></div>','0'}
flex['centro'] = { [3] = 'auto' }

local function agg(a,...)
    local args = {...}
    for _, s in ipairs(args) do
        table.insert(a, s)
    end
end

-- estrae voce del partito da eventuale wikilink
local function estrai(partito)
	local a = partito
	local x1 = a:find('%[%[')
	if (x1 == nil) then
		return a
	else
		local x2 = a:sub(x1+2):find('%|')
		local x3 = a:sub(x1+2):find('%]%]')
		if (x3) then
			if (x2) then
				a = a:sub(x1+2,x2+x1)
			else
				a = a:sub(x1+2,x3+x1)
			end
		end
		return a
	end
end

-- crea le due tabelle con valore intero e valore percentuale;
-- è inserita spaziatura nel valore numerico
-- a = numero intero; b = denominatore su cui calcolare la percentuale
local function vrg(a,b)
	local s1, k
	local s2 = ''..a
	while true do
		s2, k = s2:gsub("^(-?%d+)(%d%d%d)", '%1&nbsp;%2')
		if (k==0) then break end
	end
	s1 = string.format('<td>%s</td><td><small>%4.2f</small></td>', s2, 100*tonumber(a)/b)
	s1 = s1:gsub('%.',',')
	return s1
end

-- recupera colore del partito da Modulo:Partiti
-- a = partito; b = colore opzionale
local function colora(a,b)
	return colore({estrai(a),(b or '#EEE')})
end

-- controlla possibili errori nei dati numerici inseriti per primo e secondo turno
-- el,el2 = elettori; vt,vt2 = votanti; tt,tt2 = totale
local function verifica(e,el,vt,tt,b,el2,vt2,tt2)
	if (vt == 0) then e = e..' - non indicati votanti della votazione' end
	if (el == 0) then e = e..' - non indicati elettori della votazione' end
	if (vt < tt) then e = e..' - il totale è superiore al numero di votanti' end
	if (b>0) then
		if (vt2 == 0) then e = e..' - non indicati votanti del ballottaggio' end
		if (el2 == 0) then e = e..' - non indicati elettori del ballottaggio' end
		if (vt2 < tt2) then e = e..' - il totale è superiore al numero di votanti nel ballottaggio' end
	end
	return e
end

-- crea le righe finali della tabella
-- el,el2 = elettori; vt,vt2 = votanti; tt,tt2 = totale
-- b = ballottaggio
-- cc = colonne su cui espandere la prima cella
-- cc2 = totale colonne per linea di separazione (viene aggiunto 2 in caso di ballottaggio)
-- e = opzione per mostrare righe relative a voti validi/non validi
local function fine(el,vt,tt,b,el2,vt2,tt2,cc,cc2,e)
	local ss = {}
	local ss2 = '<tr><td align=left colspan='..cc..'>'

	if (b>0) then
		agg(ss,string.format('<tr><td colspan=%d></td></tr>',cc2+2))
		agg(ss,ss2,'Iscritti</td>',vrg(el,el),vrg(el2,el2),'</tr>')
		agg(ss,ss2,'&#x21b3; Votanti <small>(% su iscritti)</small></td>',vrg(vt,el),vrg(vt2,el2),'</tr>')
		if (e == 1) then
			agg(ss,ss2,'&emsp;&#x21b3; Voti validi <small>(% su votanti)</small></td>',vrg(tt,vt),vrg(tt2,vt2),'</tr>')
			agg(ss,ss2,'&emsp;&#x21b3; Voti non validi <small>(% su votanti)</small></td>',vrg(vt-tt,vt),vrg(vt2-tt2,vt2),'</tr>')
		agg(ss,ss2,'&#x21b3; Astenuti <small>(% su iscritti)</small></td>',vrg(el-vt,el),vrg(el2-vt2,el2),'</tr>')
		end
	else
		agg(ss,string.format('<tr><td colspan=%d></td></tr>',cc2))
		agg(ss,ss2,'Iscritti</td>',vrg(el,el),'</tr>')
		agg(ss,ss2,'&#x21b3; Votanti <small>(% su iscritti)</small></td>',vrg(vt,el),'</tr>')
		if (e == 1) then
			agg(ss,ss2,'&emsp;&#x21b3; Voti validi <small>(% su votanti)</small></td>',vrg(tt,vt),'</tr>')
			agg(ss,ss2,'&emsp;&#x21b3; Voti non validi <small>(% su votanti)</small></td>',vrg(vt-tt,vt),'</tr>')
		end
		agg(ss,ss2,'&#x21b3; Astenuti <small>(% su iscritti)</small></td>',vrg(el-vt,el),'</tr>')
	end
	return table.concat(ss)
end

-- calcola colore di sfondo per linea eletti sulla base del colore del partito
local function sfondo(a)
	local t = a:sub(6)
	local c = {}
	if (t:len() == 6) then
		c[1] = tonumber(t:sub(1,2),16) or 255
		c[2] = tonumber(t:sub(3,4),16) or 255
		c[3] = tonumber(t:sub(5,6),16) or 255
	elseif (t:len() == 3) then
		c[1] = 17*(tonumber(t:sub(1,1),16) or 15)
		c[2] = 17*(tonumber(t:sub(2,2),16) or 15)
		c[3] = 17*(tonumber(t:sub(3,3),16) or 15)
	else
		return '&#35;FFFFEE'
	end
	c[1] = 224 + math.floor(c[1]/8)
	c[2] = 224 + math.floor(c[2]/8)
	c[3] = 224 + math.floor(c[3]/8)
	return string.format('&#35;%x%x%x',c[1],c[2],c[3])
end

-- restituisce il colore del partito
function p.colorato(frame)
	local args = getArgs(frame, { valueFunc = ff })
	return colore({estrai(args[1]),'#EEE'})
end

function p.partito(frame)
	local args = getArgs(frame, { valueFunc = ff })
	return estrai(args[1])
end

-- crea tabella per elezione uninominale
function p.unico(frame)
	local args = getArgs(frame, { valueFunc = ff })
	local elettori = tonumber(args['elettori'] or 0)
	local elettori2 = tonumber(args['elettori2'] or elettori)
	local votanti = tonumber(args['votanti'] or 0)
	local votanti2 = tonumber(args['votanti2'] or 0)
	local edata = ''
	if (args['data']) then edata = string.format(edate,args['data']) end
	local edata2 = ''
	if (args['data2']) then edata2 = string.format(edate,args['data2']) end
	local ball = tonumber(args['ball1'] or 0)
	local titolo = args['titolo'] or ''
	local allinea = args['allinea'] or ''
	local solovotanti = args['solovotanti'] and 0 or 1
	local err = '-'
	local ss = {}
	local num = 1
	local tot,tot2 = 0,0
	local dati = {}

	while (args['cand'..num]) do
		if (args['voti'..num]) then
			dati[num] = {
				n = args['cand'..num], v = tonumber(args['voti'..num]), b = tonumber(args['ball'..num] or -1),
				p = args['part'..num] or '—', c = colora(args['part'..num] or '',args['col'..num])
			}
			tot = tot+dati[num].v
			if (dati[num].b > -1) then tot2 = tot2 + dati[num].b end
		else
			err = ' - non indicato il numero di voti per il candidato '..num
		end
		num = num+1
	end
	num = num-1

	err = verifica(err,elettori,votanti,tot,ball,elettori2,votanti2,tot2)
	if (err == '-') then
		if (flex[allinea]) then agg(ss,flex[allinea][1]) end
		agg(ss,'<table class="wikitable" style="text-align:right;margin:10px ',flex[allinea] and flex[allinea][3] or '0','"><caption>',titolo,'</caption><tr><th rowspan=2 colspan=2>Partito</th><th rowspan=2>Candidato</th><th colspan=2>')
		if (ball>0) then agg(ss,'Primo turno',edata,'</th><th colspan=2>Ballottaggio',edata2) else agg(ss,'Risultati',edata) end
		agg(ss,'</th></tr><tr>',tcella,((ball>0) and tcella or ''),'</tr>')

		for i=1,num do
			if (i==1) then
				agg(ss,string.format('<tr style="font-weight:bold;background:%s">',sfondo(dati[i].c)))
			else
				agg(ss,'<tr>')
			end
			agg(ss,string.format('<td style="width:0;background:%s"></td><td align=left>%s</td><td align=left>%s</td>', dati[i].c, dati[i].p, dati[i].n))
			agg(ss,vrg(dati[i].v,tot))
			if (dati[i].b>-1) then agg(ss,vrg(dati[i].b,tot2)) end
			agg(ss,'</tr>')
		end
		agg(ss,fine(elettori,votanti,tot,ball,elettori2,votanti2,tot2,3,5,solovotanti))
		if (args['nota']) then
			agg(ss,string.format('<tr><td colspan=%d></td></tr>', (ball>0 and 7 or 5)))
			agg(ss,string.format('<tr><td style="width:0;background:%s"></td>', dati[1].c))
			agg(ss,string.format('<td align=left colspan=%d style="font-size:90%%">%s</td></tr>',(ball>0 and 6 or 4),args['nota']))
		elseif (args['part0'] and not (dati[1].p == '—')) then
			agg(ss,string.format('<tr><td colspan=%d></td></tr>', (ball>0 and 7 or 5)))
			agg(ss,string.format('<tr><td style="width:0;background:%s"></td><td align=left colspan=%d style="font-size:90%%"><b>Esito:</b> ', dati[1].c,(ball>0 and 6 or 4)))
			if (estrai(dati[1].p) == estrai(args['part0'])) then
				agg(ss,string.format('collegio confermato a %s</b>', dati[1].p))
			elseif (args['part0'] == 'n') then
				agg(ss,string.format('collegio a %s (nuovo collegio)',dati[1].p))
			else
				agg(ss,string.format('collegio passa da %s a %s',args['part0'],dati[1].p))
			end
			agg(ss,'</td></tr>')
		end
		agg(ss,'</table>')
		if (flex[allinea]) then agg(ss,flex[allinea][2]) end
		return table.concat(ss)
	else
		return '<p style="color:red"><b>Errore nel template:</b> '..err..'</p>'
	end
end

-- crea tabella per elezione plurinominale
function p.poli(frame)
	local args = getArgs(frame, { valueFunc = ff })
	local elettori = tonumber(args['elettori'] or 0)
	local elettori2 = tonumber(args['elettori2'] or elettori)
	local votanti = tonumber(args['votanti'] or 0)
	local votanti2 = tonumber(args['votanti2'] or 0)
	local edata = ''
	if (args['data']) then edata = string.format(edate,args['data']) end
	local edata2 = ''
	if (args['data2']) then edata2 = string.format(edate,args['data2']) end
	local eletti = tonumber(args['eletti'] or 0)
	local ball = tonumber(args['ball1'] or 0)
	local titolo = args['titolo'] or ''
	local allinea = args['allinea'] or ''
	local err = '-'
	local ss = {}
	local num = 1
	local dati = {}

	while (args['cand'..num]) do
		if (args['voti'..num]) then
			dati[num] = {
				n = args['cand'..num], v = tonumber(args['voti'..num]), b = tonumber(args['ball'..num] or -1),
				p = args['part'..num] or '—', c = colora(args['part'..num] or '',args['col'..num])
			}
		else
			err = ' - non indicato il numero di voti per il candidato '..num
		end
		num = num+1
	end
	num = num-1

	err = verifica(err,elettori,votanti,votanti,ball,elettori2,votanti2,votanti2)
	if (eletti == 0) then err = err..' - non indicati eletti della votazione' end
	if (err == '-') then
		if (flex[allinea]) then agg(ss,flex[allinea][1]) end
		agg(ss,'<table class="wikitable" style="text-align:right;margin:10px ',flex[allinea] and flex[allinea][3] or '0','"><caption>',titolo,'</caption><tr><th rowspan=2 colspan=2>Partito</th><th rowspan=2>Candidato</th><th colspan=2>')
		if (ball>0) then agg(ss,'Primo turno',edata,'</th><th colspan=2>Ballottaggio',edata2) else agg(ss,'Risultati',edata) end
		agg(ss,'</th></tr><tr>',tcella,((ball>0) and tcella or ''),'</tr>')

		for i=1,num do
			if (i<=eletti) then
				agg(ss,string.format('<tr style="font-weight:bold;background:%s">',sfondo(dati[i].c)))
			else
				agg(ss,'<tr>')
			end
			agg(ss,string.format('<td style="width:0;background:%s"></td><td align=left>%s</td><td align=left>%s</td>', dati[i].c, dati[i].p, dati[i].n))
			agg(ss,vrg(dati[i].v,votanti))
			if (dati[i].b>-1) then agg(ss,vrg(dati[i].b,votanti2)) end
			agg(ss,'</tr>')
		end
		agg(ss,fine(elettori,votanti,1,ball,elettori2,votanti2,1,3,5,0))
		if (args['nota']) then
			agg(ss,string.format('<td align=left colspan=%d></td></tr>',(ball>0 and 7 or 5)))
			agg(ss,string.format('<td align=left colspan=%d style="font-size:90%%">%s</td></tr>',(ball>0 and 7 or 5),args['nota']))
		end
		agg(ss,'</table>')
		if (flex[allinea]) then agg(ss,flex[allinea][2]) end
		return table.concat(ss)
	else
		return '<p style="color:red"><b>Errore nel template:</b> '..err..'</p>'
	end
end

-- crea tabella per elezione di lista
function p.lista(frame)
	local args = getArgs(frame, { valueFunc = ff })
	local elettori = tonumber(args['elettori'] or 0)
	local elettori2 = tonumber(args['elettori2'] or elettori)
	local votanti = tonumber(args['votanti'] or 0)
	local votanti2 = tonumber(args['votanti2'] or 0)
	local edata = ''
	if (args['data']) then edata = string.format(edate,args['data']) end
	local edata2 = ''
	if (args['data2']) then edata2 = string.format(edate,args['data2']) end
	local ball = tonumber(args['ball1'] or 0)
	local titolo = args['titolo'] or ''
	local allinea = args['allinea'] or ''
	local solovotanti = args['solovotanti'] and 0 or 1
	local err = '-'
	local ss = {}
	local num = 1
	local tot,tot2 = 0,0
	local dati = {}

	while (args['part'..num]) do
		if (args['voti'..num]) then
			dati[num] = {
				p = args['part'..num], v = tonumber(args['voti'..num]), b = tonumber(args['ball'..num] or -1),
				c = colora(args['part'..num] or '',args['col'..num]), s = args['seggi'..num] or '', sv = args['seggiv'..num] or '<small>n.d.</small>'
			}
			tot = tot+dati[num].v
			if (dati[num].b > -1) then tot2 = tot2 + dati[num].b end
		else
			err = ' - non indicato il numero di voti per il partito '..num
		end
		num = num+1
	end
	num = num-1

	err = verifica(err,elettori,votanti,tot,ball,elettori2,votanti2,tot2)
	if (err == '-') then
		if (flex[allinea]) then agg(ss,flex[allinea][1]) end
		agg(ss,'<table cellpadding=0 cellspacing=0 style="margin:10px ',flex[allinea] and flex[allinea][3] or '0','"><caption><b>',titolo,'</b><tr style="vertical-align:top"><td>')
		agg(ss,'<table class="wikitable" style="text-align:right"><tr><th rowspan=2 colspan=2>Partito</th><th colspan=2>')
		if (ball>0) then agg(ss,'Primo turno',edata,'</th><th colspan=2>Ballottaggio',edata2) else agg(ss,'Risultati',edata) end
		agg(ss,'</th><th colspan=2>Seggi')
		agg(ss,'</th></tr><tr>',tcella,((ball>0) and tcella or ''),'<th>Num</th><th>±</th></tr>')

		for i=1,num do
			agg(ss,string.format('<tr><td style="width:0;background:%s"></td><td align=left>%s</td>', dati[i].c, dati[i].p))
			agg(ss,vrg(dati[i].v,tot))
			if (ball>0) then
				if (dati[i].b>-1) then agg(ss,vrg(dati[i].b,tot2)) else agg(ss,'<td></td><td></td>') end
			end
			agg(ss,string.format('<td>%s</td><td>%s</td></tr>',dati[i].s,dati[i].sv))
		end
		agg(ss,fine(elettori,votanti,tot,ball,elettori2,votanti2,tot2,2,6,solovotanti))
		if (args['nota']) then
			agg(ss,string.format('<td align=left colspan=%d></td></tr>',(ball>0 and 8 or 6)))
			agg(ss,string.format('<td align=left colspan=%d style="font-size:90%%">%s</td></tr>',(ball>0 and 8 or 6),args['nota']))
		end
		agg(ss,'</table></td>')
		if (args['el1']) then
			agg(ss,'<td width="12px"></td><td><table class="wikitable"><tr><th colspan=2>Eletti</th></tr>')
			num = 1
			while (args['el'..num]) do
				agg(ss,string.format('<tr><td style="background:%s"> </td><td>%s</td></tr>',dati[tonumber(args['part el'..num])].c, args['el'..num]))
				num = num+1
			end
			agg(ss,'</table></td>')
		end
		agg(ss,'</tr></table>')
		if (flex[allinea]) then agg(ss,flex[allinea][2]) end
		return table.concat(ss)
	else
		return '<p style="color:red"><b>Errore nel template:</b> '..err..'</p>'
	end
end

return p