Modulo:Discendenza: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
m dettagli in segnale errore
m modulo no globals obsoleto
 
(39 versioni intermedie di 2 utenti non mostrate)
Riga 1:
require('Module:No globalsstrict')
 
local getArgs = require('Module:Arguments').getArgs
local errorCategory = '[[Categoria:Errori di compilazione del template Discendenza]]'
local mwHtml = getmetatable( mw.html.create() ).__index
 
function mwHtml:attrIf( cond, name, value )
if cond then
return self:attr( name, value )
else
return self
end
end
 
function mwHtml:cssIf( cond, name, value )
if cond then
return self:css( name, value )
else
return self
end
end
 
function mwHtml:wikitextIf( cond, value1, value2 )
if cond then
return self:wikitext( value1 )
elseif not (value2 == nil) then
return self:wikitext( value2 )
else
return self
end
end
 
local p = {}
local pers = {}
local tabella = {}
 
local function errhandler(msg)
local cat = mw.title.getCurrentTitle().namespace == 0 and errorCategory or ''
return string.format('<span class="error">%s</span>%s', msg, cat)
end
 
local function dividi(dati)
local n = 01
local mresto = 10
local err = '-'nx,px
while (dati[n]) do n = n+1 end
local v1 = {}
n = n-1
for x in string.gmatch(dati,'([^@]+)') do
for m=4,n,4 do
n = n+1
nx = tonumber(dati[m-3])
v1[n] = x
px = tonumber(dati[m-2])
end
if (4*math.floor(n/4) == nnx) then
while if (4*m<=npx) dothen
if ((tonumber(v1[4*m-3])) and (tonumber(v1pers[4*m-2nx]))) then
error(string.format('Inserito id = %d per più elementi',nx))
if (pers[tonumber(v1[4*m-3])]) then
err = 'id ' .. v1[4*m-3] .. ' utilizzato per elementi diversi'
else
pers[tonumber(v1[4*m-3])nx] = { id = tonumber(v1[4*m-3]), padre = tonumber(v1[4*m-2])px, testo = v1dati[4*m-1], nota = v1dati[4*m], id2id = -1, x = -1, y = -1, sp = 0, figli = {} }
end
else
errerror(string.format('Inserito id genitore = 'identificativo%s non numerico ('id .. v1[4*m-3]= %d)' o ' .. v1,dati[4*m-2] .. ',nx)) per l\'elemento ' .. m
end
else
m = m+1
error(string.format('Inserito id = %s non numerico',dati[m-3]))
end
resto = n-m
else
end
err = 'numero di dati (' .. n .. ') non valido'
if (resto > 0) then
error(string.format('Numero di dati %d non valido (elementi in più: %d)',n,resto))
end
return err
end
 
local function organizza(pid, plevy)
local nn = 1
pers[pid].y = plev -- assegna y ad ogni persona
pers[pid].y = y
if (not tabella[plev]) then
if (not tabella[plevy]) then tabella[y] = {} end
table.insert(tabella[y], pid)
end
table.insert(tabella[plev], pid) -- inserisce la persona in tabella
for i, v in pairs(pers[pid].figli) do
pers[v].id2id = i -- assegna numero del figlio
nn = nn + organizza(v, plevy+1) -- ricorsione per assegnare y ai figli
end
return nn
end
 
local function limSx(pid, delta, dt) -- calcola la posizione più a sinistra tra gli elementi del ramo per ogni y
if (dt[pers[pid].y]) then
local tt = dt
if dt[pers[pid].y] = math.min(ttdt[pers[pid].y]), thenpers[pid].x+delta)
tt[pers[pid].y] = math.min(tt[pers[pid].y], pers[pid].x+delta)
else
ttdt[pers[pid].y] = pers[pid].x + delta
end
for i_, v in pairs(pers[pid].figli) do
ttdt = limSx(v, delta+pers[pid].sp, ttdt)
end
return ttdt
end
 
local function limDx(pid, delta, dt) -- calcola la posizione più a destra tra gli elementi del ramo per ogni y
if (dt[pers[pid].y]) then
local tt = dt
if dt[pers[pid].y] = math.max(ttdt[pers[pid].y]), thenpers[pid].x+delta)
tt[pers[pid].y] = math.max(tt[pers[pid].y], pers[pid].x+delta)
else
ttdt[pers[pid].y] = pers[pid].x + delta
end
for i_, v in pairs(pers[pid].figli) do
ttdt = limDx(v, delta+pers[pid].sp, ttdt)
end
return ttdt
end
 
local function riallinea(pid2, n1, n2) -- sposta gli elementi tra i fratelli n1 e n2 per cercare di equispaziarli
local distanza = n2 - n1
local vrf = 0
local pos, inizio, passo
if (distanza > 1) then
local dstinizio = (pers[pers[pid2].figli[n2n1]].x
passo -= (pers[pers[pid2].figli[n1n2]].x - inizio)/distanza
localfor cc = 1,(distanza-1) do
pos = inizio + math.floor(cc*passo)
while (n1+cc < n2) do
localif sposta(pos =- pers[pers[pid2].figli[n1+cc]].x +> math.floor(cc*dst0) then
if (sposta - pers[pers[pid2].figli[n1+cc]].x > 0)= thenpos
pers[pers[pid2].figli[n1+cc]].xsp = spostapos
pers[pers[pid2].figli[n1+cc]].sp = sposta
end
cc = cc + 1
end
vrf = 1
Line 89 ⟶ 124:
end
 
local function verifica(pid) -- verifica che i rami non si sovrappongano e calcola eventuali spostamenti
local tSx
local tDx
local sposta = 0
 
local fine = pers[pid].id2id
local frt = 1
local frt2, n
for frt=1,(fine-1) do
while (frt < fine) do -- controlla tutti i rami fratelli da 1 fino al ramo corrente
frt2 = pers[pers[pers[pid].padre].figli[frt]].id
tDx = limDx(frt2, 0, {}) -- elementi più a destra del ramo fratello per ogni y
tSx = limSx(pid, 0, {}) -- elementi più a sinistra del ramo corrente per ogni y
n = pers[pid].y
while ((tSx[n]) and (tDx[n])) do
if (tSx[n] - tDx[n] + sposta < 2) then -- verifica che ci sia almeno una distanza 2 tra i rami (2 = larghezza casella)
sposta = 2 + tDx[n] - tSx[n]
end
n = n + 1
end
if (sposta > 0) then -- se deve spostare verifica se riallineare elementi intermedi
pers[pid].x = pers[pid].x + sposta
pers[pid].sp = pers[pid].sp + sposta
Line 115 ⟶ 149:
sposta = 0
end
frt = frt + 1
end
end
 
local function calcolaX1(pid) -- prima verifica di posizionamento
for _, v in pairs(pers[pid].figli) do
local tt = 0
for i, v in pairs(pers[pid].figli) do
calcolaX1(v)
tt = i
end
local tt = #pers[pid].figli
if (tt == 0) then -- non ha figli
if (pers[pid].padre == -1) thenor --pers[pid].id è== capostipite1) then
pers[pid].x = 0
else
elseif (pers[pid].id2 == 1) then -- è primo figlio
pers[pid].x = 0pers[pers[pers[pid].padre].figli[pers[pid].id - 1]].x + 2
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) thenor --pers[pid].id è== capostipite1) then
pers[pid].x = pers[pers[pid].figli[1]].x
elseif (pers[pid].id2 == 1) then -- è primo figlio
pers[pid].x = pers[pers[pid].figli[1]].x
else
else -- è figlio successivo
pers[pid].x = pers[pers[pers[pid].padre].figli[pers[pid].id2id - 1]].x + 2
pers[pid].sp = pers[pid].x - pers[pers[pid].figli[1]].x
verifica(pid)
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) thenor --pers[pid].id è== capostipite1) then
pers[pid].x = media
else
elseif (pers[pid].id2 == 1) then -- è primo figlio
pers[pid].x = mediapers[pers[pers[pid].padre].figli[pers[pid].id - 1]].x + 2
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
verifica(pid)
Line 159 ⟶ 184:
 
local function calcolaX2(pid)
local tt = {}
local sposta = 0
local tt = limSx(pid, 0, {})
 
ttfor = limSx(pid_, 0,v in pairs(tt) do
for i, v in pairs(tt) do
if (v+sposta<0) then
sposta = -v
Line 176 ⟶ 199:
local function calcolaX3(pid, sposta)
pers[pid].x = pers[pid].x + sposta
localfor sposta2_, =v sposta +in pairs(pers[pid].spfigli) do
for i calcolaX3(v, vsposta in+ pairs(pers[pid].figlisp) do
calcolaX3(v, sposta2)
end
end
 
local function massimoXY(pid, x, yt) -- calcola numero colonne e righe totali
if (pers[pid].x > t[1]) then t[1] = pers[pid].x end
local t = {}
if (pers[pid].y > t[12]) then t[2] = math.max(x,pers[pid].x)y end
t[2]for =_, math.maxv in pairs(y,pers[pid].yfigli) do
t = massimoXY(v,t)
for i, v in pairs(pers[pid].figli) do
t = massimoXY(v,t[1],t[2])
end
return t
end
 
local function mostramostraX(pid,allinea,largo,dida) -- crea HTML tabella finale
local xyposx = massimoXY(pid, 0, 0){}
local n1
local p1, p2, p3 -- posizione all'interno della riga per 1. parte superiore; 2. parte con testo; 3. parte inferiore
local stx
local n1 -- padre dell'ultimo elemento analizzato (per connessione tra fratelli)
local riga = {}
local s1, s2, s3 -- HTML per 1. parte superiore; 2. parte con testo; 3. parte inferiore
local xx, xp
local px, nx -- posizione e padre dell'elemento corrente
local stileDiv = { ['width'] = largo..'px', ['padding'] = '3px', ['background'] = '#FFF', ['border'] = '1px solid #C8CCD1' }
local ss = ''
local stileTabella = { ['border-collapse'] = 'separate', ['text-align'] = 'center', ['font-size'] = '95%', ['line-height'] = '105%', ['margin'] = '8px auto !important', }
local xy = massimoXY(pid, {0, 0})
local lg = math.floor(100/(xy[1]+2))
if (lg == 0) then lg = 1 end
 
local bDiv = mw.html.create('div'):attr({['style']='overflow:auto'})
if (allinea == 'destra') then
bDiv:css(stileDiv):addClass('floatright')
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">'
stileTabella['margin'] = '0px auto !important'
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 bTabella = mw.html.create('table')
local lg = math.floor(100/(xy[1]+2)) -- larghezza percentuale di ogni colonna
:css(stileTabella)
if (lg == 0) then lg = 1 end
:attr({['cellpadding']='1',['cellspacing']='0',['border']='0'})
for n=1,xy[2] do -- analisi delle righe
for n=1,xy[2] do
p1 = 0; p2 = 0; p3 = 0
local riga1 = mw.html.create('tr')
local riga2 = mw.html.create('tr')
local riga3 = mw.html.create('tr')
posx[1] = 0; posx[2] = 0; posx[3] = 0
n1 = 0
if (n==>1) then s1 = riga1:css('<tr>' else s1 = '<tr style="line-height:6px">','8px') end
if (n<xy[2]) then riga3:css('line-height','8px') end
s2 = '<tr>'
for _, v in pairs(tabella[n]) do
if (n<xy[2]) then s3 = '<tr style="line-height:6px">' else s3 = '' end
xx = pers[v].x
for i, v in pairs(tabella[n]) do
pxxp = pers[v].xpadre
nx = pers[v].padre
if (n==1) then
 
for m=1,(xy[1]+2) do
if (n>1) then -- 1. parte superiore
riga1:node(mw.html.create('td'):css('width',lg..'%'))
s1 = s1 .. '<td style="border-right:1px solid #000'
end
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 .. '">&nbsp;</td>'
else
riga1:node(mw.html.create('td')
for m=1,(xy[1]+2) do s1 = s1 .. '<td width='..lg..'%></td>' end
:css('border-right','1px solid #000')
:cssIf(n1 == xp,'border-top','1px solid #000')
:attrIf(xx-posx[1]>0,'colspan',xx+1-posx[1])
:wikitext('&nbsp;')
)
n1 = xp
posx[1] = xx + 1
end
 
if (pxxx-p2posx[2]>0) then -- 2. parte con testo
s2 = s2 riga2:node(mw.html. create('<td')
if :attrIf(px xx- p2posx[2]>1) then s2 = s2 .. ,' colspan="'.. (px,xx-p2posx[2]) ..'"' end
s2 = s2 .. :wikitext('>&nbsp;</td>')
)
end
riga2:node(mw.html.create('td')
s2 = s2 .. '<td colspan=2>' .. pers[v].testo .. '<br/>'
:attr('colspan','2')
if (pers[v].nota == '-') then else s2 = s2 .. '<span style="font-size:90%"><i>' .. pers[v].nota .. '</i></span>' end
:wikitextIf(pers[v].nota=='-', pers[v].testo, string.format('%s<br/><span style="font-size:90%%"><i>%s</i></span>',pers[v].testo,pers[v].nota))
s2 = s2 .. '</td>'
p2 = px + 2)
posx[2] = xx + 2
 
if (n<xy[2]) then -- 3. parte inferiore (non creata per l'ultima riga)
if (#pers[v].figli > 0) then
riga3:node(mw.html.create('td')
s3 = s3 .. '<td style="border-right: 1px solid #000'
:css('border-right','1px solid #000')
if (px - p3 > 0) then s3 = s3 .. '" colspan="' .. (px+1-p3) end
:attrIf(xx-posx[3]>0,'colspan',xx+1-posx[3])
p3 = px + 1
s3 = s3 .. :wikitext('">&nbsp;</td>')
)
posx[3] = xx + 1
end
end
end
 
bTabella:node(riga1):node(riga2):node(riga3)
if (n>1) then s1 = s1 .. '</tr>' end -- chiusura delle righe
end
s2 = s2 .. '</tr>'
if (n<xy[2]) then s3 = s3 .. '</tr>' end
 
bDiv:node(bTabella)
ss = ss .. s1 .. s2 .. s3
if (allinea == 'destra' and not (dida=='')) then
n = n + 1
bDiv:node(mw.html.create('p')
:css({['font-size'] = '87%', ['font-style'] = 'normal', ['border-top'] = '1px solid #c8ccd1', ['margin'] = '8px 2px 3px'})
:wikitext(dida)
)
end
return tostring(bDiv)
end
 
local function calcolaY(pid, t)
ss = ss .. '</table>' -- chiusura tabella
if (allineapers[pid].y ==> 'destra't) then sst = ss pers[pid].. '</div>' else ss = ss .. '</center>'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 mostraY(pid)
local bTabella = mw.html.create('table')
:attr({['cellpadding']='0',['cellspacing']='0',['border']='0'})
:css({['border-collapse']='separate',['text-align']='left',['margin']='10px 0 10px 16px'})
 
local function mostraY2(pid, a)
if (pers[pid].padre > -1) then
local riga1 = mw.html.create('tr')
local riga2 = mw.html.create('tr')
local spd = pers[pers[pid].padre].sp
if (pers[pid].id == 1 and pers[pers[pid].padre].padre > -1) then
riga1:node(mw.html.create('td')
:attr('rowspan',2*spd))
riga1:node(mw.html.create('td')
:attr('rowspan',2*spd)
:cssIf(pers[pers[pid].padre].id < #pers[pers[pers[pid].padre].padre].figli,'border-left','1px solid #666')
)
end
riga1
:node(mw.html.create('td')
:css('width','6px'))
:node(mw.html.create('td')
:css({['border-left']='1px solid #666',['border-bottom']='1px solid #666',['width']='10px',['line-height']='3px',['height']='12px'}))
:node(mw.html.create('td')
:attr({['colspan']=2*a-1, ['rowspan']=2})
:css('padding', '0px 3px 2px 1px')
:wikitextIf(pers[pid].nota=='', pers[pid].testo, pers[pid].testo..' - '..pers[pid].nota))
riga2
:node(mw.html.create('td'))
:node(mw.html.create('td')
:css({['line-height']='8px',['line-height']='3px',['height']='12px'})
:cssIf(pers[pid].id < #pers[pers[pid].padre].figli,'border-left','1px solid #666'))
bTabella:node(riga1):node(riga2)
else
bTabella:node(
mw.html.create('tr')
:node(mw.html.create('td')
:attr('colspan',2*a-1)
:css('padding','0px 0px 2px 2px')
:wikitextIf(pers[pid].nota=='',pers[pid].testo,pers[pid].testo..' - '..pers[pid].nota)
)
)
end
if (pers[pid].sp > 0) then
for _, v in pairs(pers[pid].figli) do
mostraY2(v,a-1)
end
end
end
 
mostraY2(pid,calcolaY(pid,0))
return ss
return tostring(bTabella)
end
 
function p.main_discendenza(frameargs)
local capo = -1
local errn1, = '-'n2
local lato = args['allinea'] or 'centro'
err = dividi(frame.args[1])
local larg = args['larghezza'] or '300'
if (err == '-') then
local tipo = args['tipo'] or 'o'
for i, v in pairs(pers) do
local dida = args['didascalia'] or ''
if (v.padre == -1) then
dividi(args)
if (capo == -1) then
n1 = 0
capo = v.id
for i, v in pairs(pers) do
else
n1 = n1+1
err = 'più elementi (id: ' .. capo .. ', ' .. v.id .. ') indicati come capostipite'
if (v.padre == -1) then
end
if (capo == -1) then
capo = i
else
error(string.format('Inseriti più elementi come capostipite (id = %d, %d)',capo,i))
if (v.padre == v.id) then
end
err = 'elemento con id ' .. i .. ' indicato come figlio di se stesso'
else
elseif (pers[v.padre]) then
table.insertif (pers[v.padre].figli, == i) then
error(string.format('Inserito elemento come figlio di se stesso (id = %d)', i))
else
elseif (pers[v.padre]) then
err = 'valore per genitore (' .. v.padre .. ') non valido per l\'elemento con id ' .. i
table.insert(pers[v.padre].figli,i)
end
else
error(string.format('Inserito id genitore = %d non valido (id = %d)',v.padre,i))
end
end
end
 
if (errcapo == '-'1) then
error('Capostipite non definito')
if (capo == -1) then
else
err = 'capostipite non definito'
n2 = organizza(capo, 1)
else
if (n1 == n2) then
organizza(capo, 1)
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
error('Inseriti elementi non collegati al capostipite')
end
end
end
if (err == '-') then
 
return mostra(capo, frame.args[2], frame.args[3])
function p.discendenza(frame)
else
local args = getArgs(frame, {
return '<p style="color:#b80000"><b>Template:Discendenza - Errore:</b> ' .. err .. '</p>[[Categoria:Errori di compilazione del template Discendenza]]'
valueFunc = function (key, value)
end
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
})
return p._discendenza(args)
end