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 p = {}
local pers = {}
local tabella = {}
local tdg = ''
local function mostra2(pid, idt)
local ss = idt .. pers[pid].id .. ' => x = ' .. pers[pid].x .. ', sp = ' .. pers[pid].sp .. ', y = ' .. pers[pid].y .. '<br/>'
for i, v in pairs(pers[pid].figli) do
ss = ss .. idt .. mostra2(v,idt .. '> ')
end
return ss
end
local function dividi(dati)
local n = 0
local m = 1
local err = 0
local v1 = {}
for x in string.gmatch(dati,'([^@]+)') do
n = n+1
v1[n] = x
end
if (4*math.floor(n/4) == n) then
while (4*m<=n) do
if ((tonumber(v1[4*m-3])) and (tonumber(v1[4*m-2]))) then
pers[tonumber(v1[4*m-3])] = { id = tonumber(v1[4*m-3]), padre = tonumber(v1[4*m-2]), testo = v1[4*m-1], nota = v1[4*m], id2 = -1, x = -1, y = -1, sp = 0, figli = {} }
else
err = m
end
m = m+1
end
else
err = -1
end
return err
end
local function organizza(pid, plev)
pers[pid].y = plev
if (not tabella[plev]) then
tabella[plev] = {}
end
table.insert(tabella[plev], pid)
for i, v in pairs(pers[pid].figli) do
pers[v].id2 = i
organizza(v, plev+1)
end
end
local function limSx(pid, delta, dt)
local tt = dt
if (tt[pers[pid].y]) then
tt[pers[pid].y] = math.min(tt[pers[pid].y], pers[pid].x+delta)
else
tt[pers[pid].y] = pers[pid].x + delta
end
for i, v in pairs(pers[pid].figli) do
tt = limSx(v, delta+pers[pid].sp, tt)
end
return tt
end
local function limDx(pid, delta, dt)
local tt = dt
if (tt[pers[pid].y]) then
tt[pers[pid].y] = math.max(tt[pers[pid].y], pers[pid].x+delta)
else
tt[pers[pid].y] = pers[pid].x + delta
end
for i, v in pairs(pers[pid].figli) do
tt = limDx(v, delta+pers[pid].sp, tt)
end
return tt
end
local function riallinea(pid2, n1, n2)
local distanza = n2 - n1
local vrf = 0
if (distanza > 1) then
local dst = (pers[pers[pid2].figli[n2]].x - pers[pers[pid2].figli[n1]].x)/distanza
local cc = 1
while (n1+cc < n2) do
local sposta = pers[pers[pid2].figli[n1]].x + math.floor(cc*dst)
if (sposta - pers[pers[pid2].figli[n1+cc]].x > 0) then
pers[pers[pid2].figli[n1+cc]].x = sposta
pers[pers[pid2].figli[n1+cc]].sp = sposta
end
cc = cc + 1
end
vrf = 1
end
return vrf
end
local function verifica(pid)
local tSx
local tDx
local sposta = 0
local fine = pers[pid].id2
local frt = 1
local frt2, n
while (frt < fine) do
frt2 = pers[pers[pers[pid].padre].figli[frt]].id
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]
tdg = tdg .. '<br/>Sposta: id = ' .. pid .. ' (' .. pers[pid].x .. ',' .. pers[pid].sp .. '), Sx = ' .. tSx[n]
tdg = tdg .. '// id2 = ' .. frt2 .. ' (' .. pers[frt2].x .. ',' .. pers[frt2].sp .. '), Dx = ' .. tDx[n]
tdg = tdg .. '// n = ' .. n .. ', d = ' .. sposta
tdg = tdg .. '<br/>' .. mostra2(pid, '* ') .. '<br/>'
for i, v in pairs(tSx) do
tdg = tdg .. i .. ' = ' .. v .. ' - '
end
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
frt = frt + 1
end
end
local function calcolaX1(pid)
local tt = 0
for i, v in pairs(pers[pid].figli) do
calcolaX1(v)
tt = i
end
if (tt == 0) then -- non ha figli
if (pers[pid].padre == -1) then -- è capostipite
pers[pid].x = 0
elseif (pers[pers[pid].padre].figli[1] == pid) then -- è primo figlio
pers[pid].x = 0
else -- è figlio successivo
pers[pid].x = pers[pers[pers[pid].padre].figli[pers[pid].id2 - 1]].x + 2
end
elseif (tt == 1) then -- ha un figlio
if (pers[pid].padre == -1) then -- è capostipite
pers[pid].x = pers[pers[pid].figli[1]].x
elseif (pers[pers[pid].padre].figli[1] == pid) then -- è primo figlio
pers[pid].x = pers[pers[pid].figli[1]].x
else -- è figlio successivo
pers[pid].x = pers[pers[pers[pid].padre].figli[pers[pid].id2 - 1]].x + 2
pers[pid].sp = pers[pid].x - pers[pers[pid].figli[1]].x
end
else -- ha più figli
local media = math.floor((pers[pers[pid].figli[1]].x + pers[pers[pid].figli[tt]].x)/2)
if (pers[pid].padre == -1) then -- è capostipite
pers[pid].x = media
elseif (pers[pers[pid].padre].figli[1] == pid) then -- è primo figlio
pers[pid].x = media
else -- è figlio successivo
pers[pid].x = pers[pers[pers[pid].padre].figli[pers[pid].id2 - 1]].x + 2
pers[pid].sp = pers[pid].x - media
end
end
if (tt>0 and pers[pid].padre>-1) then
if not (pers[pers[pid].padre].figli[1] == pid) then
verifica(pid)
end
end
end
local function calcolaX2(pid)
local tt = {}
local sposta = 0
tt = limSx(pid, 0, tt)
for i, 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
local sposta2 = sposta + pers[pid].sp
for i, v in pairs(pers[pid].figli) do
calcolaX3(v, sposta2)
end
end
local function massimoXY(pid, x, y)
local t = {}
t[1] = math.max(x,pers[pid].x)
t[2] = math.max(y,pers[pid].y)
for i, v in pairs(pers[pid].figli) do
t = massimoXY(v,t[1],t[2])
end
return t
end
local function mostra(pid,allinea,largo)
local xy = massimoXY(pid, 0, 0)
local p1, p2, p3, n1, n2, n3, s1, s2, s3, px, nx
local ss = ''
if (allinea == 'destra') then
ss = '<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;line-height:110%;margin:0px auto">'
else
ss = '<center><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:6px">' end
s2 = '<tr>'
if (n<xy[2]) then s3 = '<tr style="line-height:6px">' else s3 = '' end
for i, v in pairs(tabella[n]) do
px = pers[v].x
nx = pers[v].padre
if (n>1) then
s1 = s1 .. '<td style="border-right:1px solid #000'
if (n1 == nx) then s1 = s1 ..';border-top:1px solid #000' end
n1 = nx
if (px - p1 > 0) then s1 = s1 .. '" colspan="' .. (px+1-p1) end
p1 = px + 1
s1 = s1 .. '"> </td>'
else
for m=1,(xy[1]+2) do s1 = s1 .. '<td width='..lg..'%></td>' end
end
if (px-p2>0) then
s2 = s2 .. '<td'
if (px - p2>1) then s2 = s2 .. ' colspan="'.. (px-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 = px + 2
if (n<xy[2]) then
if (#pers[v].figli > 0) then
s3 = s3 .. '<td style="border-right: 1px solid #000'
if (px - p3 > 0) then s3 = s3 .. '" colspan="' .. (px+1-p3) end
p3 = px + 1
s3 = s3 .. '"> </td>'
end
end
end
if (n>1) then s1 = s1 .. '</tr>' end
s2 = s2 .. '</tr>'
if (n<xy[2]) then s3 = s3 .. '</tr>' end
ss = ss .. s1 .. s2 .. s3
n = n + 1
end
ss = ss .. '</table>'
if (allinea == 'destra') then ss = ss .. '</div>' else ss = ss .. '</center>' end
return ss
end
function p.main(frame)
local capo = -1
local err = 0
err = dividi(frame.args[1])
if (err == 0) then
for i, v in pairs(pers) do
if (v.padre == -1) then
if (capo == -1) then
capo = v.id
else
err = -1
end
else
if (v.padre == v.id) then
err = i
elseif (pers[v.padre]) then
table.insert(pers[v.padre].figli,i)
else
err = i
end
end
end
if (err == 0) then
if (capo == -1) then
return '<p style="color:red"><b>Template:Discendenza - Errore:</b> Non è stato indicato un capostipite</p>[[Categoria:Errori di compilazione del template Discendenza]]'
else
organizza(capo, 1)
calcolaX1(capo)
calcolaX2(capo)
calcolaX3(capo, 0)
if (frame.args[4] == '0') then
return mostra(capo, frame.args[2], frame.args[3])
else
return '<pre>'..mostra2(capo, '')..tdg .. '</pre>'
end
end
elseif (err == -1) then
return '<p style="color:red"><b>Template:Discendenza - Errore:</b> sono indicati più elementi come capostipite</p>[[Categoria:Errori di compilazione del template Discendenza]]'
else
return '<p style="color:red"><b>Template:Discendenza - Errore:</b> riferimento al genitore non valido per l\'identificativo ' .. err .. '</p>[[Categoria:Errori di compilazione del template Discendenza]]'
end
elseif (err == -1) then
return '<p style="color:red"><b>Template:Discendenza - Errore:</b> numero di parametri non valido</p>[[Categoria:Errori di compilazione del template Discendenza]]'
else
return '<p style="color:red"><b>Template:Discendenza - Errore:</b> identificativo o riferimento a genitore non valido per l\'elemento ' .. err .. ' in ordine di inserimento</p>[[Categoria:Errori di compilazione del template Discendenza]]'
end
end
return p