Modulo:Discendenza

Questo è un modulo scritto in Lua. Le istruzioni che seguono sono contenute nella sottopagina Modulo:Discendenza/man (modifica · cronologia)
Sandbox: Modulo:Discendenza/sandbox (modifica · cronologia) · Sottopagine: lista · Test: Modulo:Discendenza/test (modifica · cronologia · Esegui)
Questo modulo serve a {{Discendenza}} per la creazione automatica di grafici genealogici.
require('Module:No globals')
local getArgs = require('Module:Arguments').getArgs
local p = {}
local pers = {}
local tabella = {}
local txt = {}
local function agg(t)
table.insert(txt,t)
end
local function dividi(dati)
local n = 1
local resto = 0
local nx,px
local err = '-'
while (dati[n]) do n = n+1 end
n = n-1
for m=4,n,4 do
nx = tonumber(dati[m-3])
px = tonumber(dati[m-2])
if (nx) then
if (px) then
if (pers[nx]) then
err = string.format('inserito id = <b>%d</b> per più elementi',nx)
else
pers[nx] = { padre = px, testo = dati[m-1], nota = dati[m], id = -1, x = -1, y = -1, sp = 0, figli = {} }
end
else
err = string.format('inserito id genitore = <b>%s</b> non numerico (id = <b>%d</b>)',dati[m-2],nx)
end
else
err = string.format('inserito id = <b>%s</b> non numerico',dati[m-3])
end
resto = n-m
end
if (err == '-' and resto > 0) then
err = string.format('numero di dati %d non valido (elementi in più: %d)',n,resto)
end
return err
end
local function organizza(pid, y)
local nn = 1
pers[pid].y = y
if (not tabella[y]) then tabella[y] = {} end
table.insert(tabella[y], pid)
for i, v in pairs(pers[pid].figli) do
pers[v].id = i
nn = nn + organizza(v, y+1)
end
return nn
end
local function limSx(pid, delta, dt)
if (dt[pers[pid].y]) then
dt[pers[pid].y] = math.min(dt[pers[pid].y], pers[pid].x+delta)
else
dt[pers[pid].y] = pers[pid].x + delta
end
for _, v in pairs(pers[pid].figli) do
dt = limSx(v, delta+pers[pid].sp, dt)
end
return dt
end
local function limDx(pid, delta, dt)
if (dt[pers[pid].y]) then
dt[pers[pid].y] = math.max(dt[pers[pid].y], pers[pid].x+delta)
else
dt[pers[pid].y] = pers[pid].x + delta
end
for _, v in pairs(pers[pid].figli) do
dt = limDx(v, delta+pers[pid].sp, dt)
end
return dt
end
local function riallinea(pid2, n1, n2)
local distanza = n2 - n1
local vrf = 0
local pos, inizio, passo
if (distanza > 1) then
inizio = pers[pers[pid2].figli[n1]].x
passo = (pers[pers[pid2].figli[n2]].x - inizio)/distanza
for cc=1,(distanza-1) do
pos = inizio + math.floor(cc*passo)
if (pos - pers[pers[pid2].figli[n1+cc]].x > 0) then
pers[pers[pid2].figli[n1+cc]].x = pos
pers[pers[pid2].figli[n1+cc]].sp = pos
end
end
vrf = 1
end
return vrf
end
local function verifica(pid)
local tSx
local tDx
local sposta = 0
local fine = pers[pid].id
local frt2, n
for frt=1,(fine-1) do
frt2 = pers[pers[pid].padre].figli[frt]
tDx = limDx(frt2, 0, {})
tSx = limSx(pid, 0, {})
n = pers[pid].y
while ((tSx[n]) and (tDx[n])) do
if (tSx[n] - tDx[n] + sposta < 2) then
sposta = 2 + tDx[n] - tSx[n]
end
n = n + 1
end
if (sposta > 0) then
pers[pid].x = pers[pid].x + sposta
pers[pid].sp = pers[pid].sp + sposta
if (riallinea(pers[pid].padre, frt, fine) == 1) then verifica(pid) end
sposta = 0
end
end
end
local function calcolaX1(pid)
for _, v in pairs(pers[pid].figli) do
calcolaX1(v)
end
local tt = #pers[pid].figli
if (tt == 0) then
if (pers[pid].padre == -1) then
pers[pid].x = 0
elseif (pers[pid].id == 1) then
pers[pid].x = 0
else
pers[pid].x = pers[pers[pers[pid].padre].figli[pers[pid].id - 1]].x + 2
end
elseif (tt == 1) then
if (pers[pid].padre == -1) then
pers[pid].x = pers[pers[pid].figli[1]].x
elseif (pers[pid].id == 1) then
pers[pid].x = pers[pers[pid].figli[1]].x
else
pers[pid].x = pers[pers[pers[pid].padre].figli[pers[pid].id - 1]].x + 2
pers[pid].sp = pers[pid].x - pers[pers[pid].figli[1]].x
verifica(pid)
end
else
local media = math.floor((pers[pers[pid].figli[1]].x + pers[pers[pid].figli[tt]].x)/2)
if (pers[pid].padre == -1) then
pers[pid].x = media
elseif (pers[pid].id == 1) then
pers[pid].x = media
else
pers[pid].x = pers[pers[pers[pid].padre].figli[pers[pid].id - 1]].x + 2
pers[pid].sp = pers[pid].x - media
verifica(pid)
end
end
end
local function calcolaX2(pid)
local sposta = 0
local tt = limSx(pid, 0, {})
for _, v in pairs(tt) do
if (v+sposta<0) then
sposta = -v
end
end
if (sposta > 0) then
pers[pid].x = pers[pid].x + sposta
pers[pid].sp = pers[pid].sp + sposta
end
end
local function calcolaX3(pid, sposta)
pers[pid].x = pers[pid].x + sposta
for _, v in pairs(pers[pid].figli) do
calcolaX3(v, sposta + pers[pid].sp)
end
end
local function massimoXY(pid, t)
if (pers[pid].x > t[1]) then t[1] = pers[pid].x end
if (pers[pid].y > t[2]) then t[2] = pers[pid].y end
for _, v in pairs(pers[pid].figli) do
t = massimoXY(v,t)
end
return t
end
local function mostraX(pid,allinea,largo,dida)
local xy = massimoXY(pid, {0, 0})
local p1, p2, p3
local n1
local s1, s2, s3
local xx, xp
if (allinea == 'destra') then
agg('<div class="floatright" style="width:'..largo..'px;padding:3px;background:#fff;border:1px solid #c8ccd1"><table cellpadding="1" cellspacing="0" border=0 style="text-align:center;font-size:95%;line-height:110%;margin:0px auto">')
else
agg('<table cellpadding="1" cellspacing="0" border=0 style="text-align:center;font-size:95%;line-height:110%;margin:10px auto">')
end
local lg = math.floor(100/(xy[1]+2))
if (lg == 0) then lg = 1 end
for n=1,xy[2] do
p1 = 0; p2 = 0; p3 = 0
n1 = 0
if (n==1) then s1 = '<tr>' else s1 = '<tr style="line-height:8px">' end
s2 = '<tr>'
if (n<xy[2]) then s3 = '<tr style="line-height:8px">' else s3 = '' end
for _, v in pairs(tabella[n]) do
xx = pers[v].x
xp = pers[v].padre
if (n>1) then
s1 = s1..'<td style="border-right:1px solid #000'
if (n1 == xp) then s1 = s1 ..';border-top:1px solid #000' end
n1 = xp
if (xx-p1>0) then s1 = s1..'" colspan="'..(xx+1-p1) end
p1 = xx + 1
s1 = s1 .. '"> </td>'
else
for m=1,(xy[1]+2) do s1 = s1..'<td width='..lg..'%></td>' end
end
if (xx-p2>0) then
s2 = s2..'<td'
if (xx-p2>1) then s2 = s2..' colspan="'..(xx-p2)..'"' end
s2 = s2..'> </td>'
end
s2 = s2..'<td colspan=2>'..pers[v].testo..'<br/>'
if (pers[v].nota == '-') then else s2 = s2..'<span style="font-size:90%"><i>'..pers[v].nota..'</i></span>' end
s2 = s2..'</td>'
p2 = xx + 2
if (n<xy[2]) then
if (#pers[v].figli > 0) then
s3 = s3..'<td style="border-right: 1px solid #000'
if (xx-p3>0) then s3 = s3..'" colspan="'..(xx+1-p3) end
p3 = xx + 1
s3 = s3 .. '"> </td>'
end
end
end
s1 = s1..'</tr>'
s2 = s2..'</tr>'
if (n<xy[2]) then s3 = s3..'</tr>' end
agg(s1);agg(s2);agg(s3)
end
agg('</table>')
if (allinea == 'destra') then
if not (dida=='') then agg('<p>'..dida..'</p>') end
agg('</div>')
end
return table.concat(txt)
end
local function calcolaY(pid, t)
if (pers[pid].y > t) then t = pers[pid].y end
for _, v in pairs(pers[pid].figli) do
t = calcolaY(v,t)
pers[pid].sp = pers[pid].sp + 1 + pers[v].sp
end
return t
end
local function mostraY2(pid, a)
if (pers[pid].id > 1) then agg('<tr>') end
if (pers[pid].padre > -1) then
agg('<td style="width:6px"></td><td style="border-left:1px solid #666;border-bottom:1px solid #666;width:10px;line-height:3px;height:12px"> </td>')
agg(string.format('<td colspan=%d rowspan=2 style="padding: 0px 3px 2px 1px">%s',2*a-1,pers[pid].testo))
if not (pers[pid].nota == '') then agg(string.format(' - %s',pers[pid].nota)) end
agg('</td></tr>')
agg('<tr><td></td><td style="line-height:8px;line-height:3px;height:12px')
if (pers[pid].id < #pers[pers[pid].padre].figli) then
agg(';border-left:1px solid #666')
end
agg('"> </td></tr>')
if (pers[pid].sp > 0) then
agg(string.format('<tr><td rowspan=%d></td><td rowspan=%d',2*pers[pid].sp,2*pers[pid].sp))
if (pers[pid].id < #pers[pers[pid].padre].figli) then
agg(' style="border-left:1px solid #666"')
end
agg('> </td>')
end
else
agg(string.format('<td colspan=%d style="padding: 0px 0px 2px 2px">%s',2*a-1,pers[pid].testo))
if not (pers[pid].nota == '') then agg(string.format(' - %s',pers[pid].nota)) end
agg('</td></tr><tr>')
end
if (pers[pid].sp > 0) then
-- agg(string.format('<td rowspan=%d style="width:6px"> </td>',2*pers[pid].sp))
for _, v in pairs(pers[pid].figli) do
mostraY2(v,a-1)
end
end
end
local function mostraY(pid)
agg('<table cellpadding="0" cellspacing="0" border=0 style="text-align:left;margin:10px 0 10px 16px"><tr>')
mostraY2(pid,calcolaY(pid,0))
agg('</tr></table>')
return table.concat(txt)
end
function p.main(frame)
local capo = -1
local n1, n2
local err = '-'
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 lato = args['allinea'] or 'centro'
local larg = args['larghezza'] or '300'
local tipo = args['tipo'] or 'o'
local dida = args['didascalia'] or ''
err = dividi(args)
if (err == '-') then
n1 = 0
for i, v in pairs(pers) do
n1 = n1+1
if (v.padre == -1) then
if (capo == -1) then
capo = i
else
err = string.format('inseriti più elementi come capostipite (id = <b>%d, %d</b>)',capo,i)
end
else
if (v.padre == i) then
err = string.format('inserito elemento come figlio di se stesso (id = <b>%d</b>)', i)
elseif (pers[v.padre]) then
table.insert(pers[v.padre].figli,i)
else
err = string.format('inserito id genitore = <b>%d</b> non valido (id = <b>%d</b>)',v.padre,i)
end
end
end
if (err == '-') then
if (capo == -1) then
err = 'capostipite non definito'
else
n2 = organizza(capo, 1)
if (n1 == n2) then
if (tipo == 'v') then
return mostraY(capo)
elseif (tipo == 'o') then
calcolaX1(capo)
calcolaX2(capo)
calcolaX3(capo, 0)
return mostraX(capo, lato, larg, dida)
end
else
err = 'inseriti elementi non collegati al capostipite'
end
end
end
end
return string.format('<p style="color:#b80000"><b>Template:Discendenza - Errore:</b> %s</p>[[Categoria:Errori di compilazione del template Discendenza]]',err)
end
return p