Modül:Build bracket
Modül belgelemesi[oluştur]
local p = {}
local entries = {}
local pathEntries = {}
local teams_per_match = {}
local rlegs = {}
local maxlegs = {}
local autolegs
local rowadj = {}
local byes = {}
local autocol
local seeds
local forceseeds
local boldwinner
local aggregate
local compact
local matchgroup
local function isempty(s)
return s==nil or s==''
end
local function notempty(s)
return s~=nil and s~=''
end
local function bargs(s)
return pargs[s] or fargs[s]
end
local function toChar(num)
return string.char(string.byte("a")+num-1)
end
local function split(str,delim,tonum)
result = {};
local a = "[^"..table.concat(delim).."]+"
for w in str:gmatch(a) do
if tonum==true then
table.insert(result, tonumber(w));
else
table.insert(result, w);
end
end
return result;
end
local function getWidth(ctype, default)
local result = bargs(ctype..'-width')
if isempty(result) then return default end
if tonumber(result)~=nil then return result..'px' end
return result
end
local function matchGroups()
matchgroup = {}
for j=minc,c do
matchgroup[j]={}
for i=1,r do
if entries[j][i]~= nil and entries[j][i]['ctype']=='team' then
matchgroup[j][i]=math.ceil(entries[j][i]['index']/teams_per_match[j])
entries[j][i]['group'] = math.ceil(entries[j][i]['index']/teams_per_match[j])
end
end
end
end
local function boldWinner()
local function boldScore(j,i,l)
if entries[j][i]~= nil and entries[j][i]['ctype']=='team' then
local myscore = entries[j][i]['score'][l]
if myscore == "" or myscore:find("%D") then return 'normal'
else myscore=tonumber(myscore) end
local compscore = {}
for k,v in pairs(matchgroup[j]) do
if matchgroup[j][i]==v and k~=i then
if entries[j][k]['score'][l] == "" or entries[j][k]['score'][l]:find("%D") then return 'normal'
else table.insert(compscore,tonumber(entries[j][k]['score'][l])) end
end
end
for k,v in pairs(compscore) do
if myscore<=v then return 'normal' end
end
if l~='agg' then
entries[j][i]['wins'] = entries[j][i]['wins']+1
else
entries[j][i]['aggwins'] = 1
end
return 'bold'
end
end
local function boldEntry(j,i,agg)
local wins
if agg~=true then
wins = 'wins'
else
wins = 'aggwins'
end
local myteam = entries[j][i][wins]
local compteam = {}
for k,v in pairs(matchgroup[j]) do
if matchgroup[j][i]==v and k~=i then
table.insert(compteam,tonumber(entries[j][k][wins]))
end
end
for k,v in pairs(compteam) do
if myteam<=v then return 'normal' end
end
return 'bold'
end
for j=minc,c do
for i=1,r do
if entries[j][i]~= nil and entries[j][i]['ctype']=='team' then
entries[j][i]['wins'] = 0
entries[j][i]['aggwins'] = 0
end
end
for i=1,r do
if entries[j][i]~= nil and entries[j][i]['ctype']=='team' then
local legs = rlegs[j]
if notempty(entries[j][i]['legs']) then
legs = tonumber(entries[j][i]['legs'])
end
for l=1,legs do
entries[j][i]['score']['weight'][l] = boldScore(j,i,l)
end
if aggregate and legs>1 then
entries[j][i]['score']['weight']['agg'] = boldScore(j,i,'agg')
end
end
end
for i=1,r do
if entries[j][i]~= nil and entries[j][i]['ctype']=='team' then
local agg
local legs = rlegs[j]
if notempty(entries[j][i]['legs']) then
legs = tonumber(entries[j][i]['legs'])
end
if aggregate and legs>1 then agg=true end
entries[j][i]['weight'] = boldEntry(j,i,agg)
end
end
end
end
local function paramNames(cname,j,i,l)
local rname = {
{'RD'..j, bargs('RD'..j..'-altname') or 'RD'..j},
{'RD'..j..toChar(entries[j][i]['headerindex']),bargs('RD'..j..toChar(entries[j][i]['headerindex'])..'-altname') or 'RD'..j..toChar(entries[j][i]['headerindex'])}
}
local name = {cname, bargs(cname..'-altname') or cname}
local index = {entries[j][i]['index'], entries[j][i]['altindex']}
local result = {}
if cname=='header' then
local default
if j==c then default = 'Final'
elseif j==c-1 then default = 'Yarı final'
elseif j==c-2 then default = 'Çeyrek final'
else default = 'Tur '..j
end
if entries[j][i]['headerindex']==1 then
for k=1,2 do
table.insert(result,bargs(rname[1][3-k]) or '')
end
table.insert(result,default)
else
for k=1,2 do
table.insert(result,bargs(rname[2][3-k]) or '')
end
table.insert(result,'Lower round '..j)
end
elseif cname=='score' then
for m=1,2 do for k=1,2 do
if l==1 then
table.insert(result,bargs(rname[3-m][3-k]..'-'..name[1]..index[3-m]) or bargs(rname[3-m][3-k]..'-'..name[1]..'0'..index[3-m]) or '')
end
table.insert(result,bargs(rname[3-m][3-k]..'-'..name[1]..index[3-m]..'-'..l) or bargs(rname[3-m][3-k]..'-'..name[1]..'0'..index[3-m]..'-'..l) or '')
end end
elseif cname=='shade' then
for k=1,2 do
if entries[j][i]['headerindex']==1 then
table.insert(result,bargs(rname[1][3-k]..'-'..name[1]) or '')
else
table.insert(result,bargs(rname[2][3-k]..'-'..name[1]) or '')
end
end
table.insert(result,bargs('RD-shade'))
table.insert(result,'#F2F2F2')
elseif cname=='text' then
for n=1,2 do for m=1,2 do for k=1,2 do
table.insert(result,bargs(rname[3-m][3-k]..'-'..name[3-n]..index[3-m]) or bargs(rname[3-m][3-k]..'-'..name[3-n]..'0'..index[3-m]) or '')
end end end
else
for m=1,2 do for k=1,2 do
table.insert(result,bargs(rname[3-m][3-k]..'-'..name[1]..index[3-m]) or bargs(rname[3-m][3-k]..'-'..name[1]..'0'..index[3-m]) or '')
end end
end
for k=1,#result do
if notempty(result[k]) then
return result[k]
end
end
return ''
end
local function blankEntry(col,row,ctype)
if isempty(entries[col][row]) then return true end
if isempty(entries[col][row]['team']) and isempty(entries[col][row]['text']) then return true end
return false
end
local function insertEntry(tbl,j,i)
local entry_colspan=maxlegs[j]+2
if not seeds then
entry_colspan=entry_colspan-1
end
if (aggregate and maxlegs[j]>1) or maxlegs[j]==0 then
entry_colspan=entry_colspan+1
end
if entries[j][i]==nil then
tbl:tag('td'):attr('colspan',entry_colspan)
else
local border_top
if entries[j][i]['position']=='top' and entries[j][i-2]~=nil and entries[j][i-2]['ctype']~='line' and entries[j][i-2]['ctype']~='text' then
if not byes[j] or not blankEntry(j,i-2) then
border_top = '2px solid #aaa'
end
end
if entries[j][i]['ctype']=='header' then
tbl:tag('td')
:attr('rowspan',2)
:attr('colspan',entry_colspan)
:css('text-align','center')
:css('border','1px solid #aaa')
:css('border-top',border_top)
:css('background-color',entries[j][i]['shade'])
:wikitext(entries[j][i]['header'])
end
if entries[j][i]['ctype']=='team' then
local legs = rlegs[j]
if notempty(entries[j][i]['legs']) then
legs = tonumber(entries[j][i]['legs'])
end
if autolegs then
local l=1
repeat l=l+1
until isempty(entries[j][i]['score'][l])
legs = l-1
end
local colspan = 1+maxlegs[j]-legs
if byes[j] and blankEntry(j,i) then
tbl:tag('td')
:attr('rowspan',2)
:attr('colspan',entry_colspan)
else
if maxlegs[j]==0 then
colspan=colspan+1
end
if seeds then
local showseed=false
if forceseeds then
showseed=true
else
if notempty(entries[j][i]['seed']) then
showseed=true
else
for k=1,teams_per_match[j]-1 do
if notempty(entries[j][i+2*k]) then
if entries[j][i]['group']==entries[j][i+2*k]['group'] and notempty(entries[j][i+2*k]['seed']) then
showseed=true
end
end
if notempty(entries[j][i-2*k]) then
if entries[j][i]['group']==entries[j][i-2*k]['group'] and notempty(entries[j][i-2*k]['seed']) then
showseed=true
end
end
end
end
end
if showseed==true then
tbl:tag('td')
:attr('rowspan',2)
:css('text-align','center')
:css('border','1px solid #aaa')
:css('border-right','2px solid #aaa')
:css('border-top',border_top)
:css('background-color','#F2F2F2')
:css('font-weight',entries[j][i]['weight'])
:css('white-space', 'nowrap')
:wikitext(entries[j][i]['seed'])
else
colspan=colspan+1
end
end
tbl:tag('td')
:attr('rowspan',2)
:attr('colspan',colspan)
:css('border','1px solid #aaa')
:css('border-top',border_top)
:css('padding-left','0.3em')
:css('background-color','#F9F9F9')
:css('font-weight',entries[j][i]['weight'])
:wikitext(entries[j][i]['team'])
for l=1,legs do
tbl:tag('td')
:attr('rowspan',2)
:css('text-align','center')
:css('border','1px solid #aaa')
:css('border-top',border_top)
:css('background-color','#F9F9F9')
:css('font-weight',entries[j][i]['score']['weight'][l])
:css('white-space', 'nowrap')
:wikitext(tostring(entries[j][i]['score'][l]))
end
if aggregate and legs>1 then
tbl:tag('td')
:attr('rowspan',2)
:css('text-align','center')
:css('border','1px solid #aaa')
:css('border-left','2px solid #aaa')
:css('border-top',border_top)
:css('background-color','#F9F9F9')
:css('font-weight',entries[j][i]['score']['weight']['agg'])
:css('white-space', 'nowrap')
:wikitext(tostring(entries[j][i]['score']['agg']))
end
end
end
if entries[j][i]['ctype']=='text' then
tbl:tag('td')
:attr('rowspan',2)
:attr('colspan',entry_colspan)
:wikitext(entries[j][i]['text'])
end
if entries[j][i]['ctype']=='line' and (entries[j][i-2]==nil or (entries[j][i-2]~=nil and entries[j][i-2]['ctype']~='line')) then
tbl:tag('td')
:attr('rowspan',2)
:attr('colspan',entry_colspan)
:css('border-width','0 0 3px 0')
:css('border-style','solid')
:css('border-color','black')
:wikitext(entries[j][i]['text'])
end
if entries[j][i]['ctype']=='line' and entries[j][i-2]~=nil and entries[j][i-2]['ctype']=='line' then
tbl:tag('td')
:attr('rowspan',2)
:attr('colspan',entry_colspan)
:css('border-width','3px 0 0 0')
:css('border-style','solid')
:css('border-color','black')
:wikitext(entries[j][i]['text'])
end
end
end
local function assignParams()
local maxcol = 1
local byerows = 1
local hiderows = false
for j=minc,c do
rlegs[j] = tonumber(bargs('RD'..j..'-legs')) or tonumber(bargs('legs')) or 1
for i=1,r do
if entries[j][i]~=nil then
if entries[j][i]['ctype']=='team' then
local legs = rlegs[j]
entries[j][i]['seed'] = paramNames('seed',j,i)
entries[j][i]['team'] = paramNames('team',j,i)
entries[j][i]['legs'] = paramNames('legs',j,i)
entries[j][i]['score'] = {}
entries[j][i]['weight'] = 'normal'
entries[j][i]['score']['weight'] = {}
if notempty(entries[j][i]['legs']) then
legs = tonumber(entries[j][i]['legs'])
end
if autolegs then
local l=1
repeat
entries[j][i]['score'][l] = paramNames('score',j,i,l)
entries[j][i]['score']['weight'][l] = 'normal'
l=l+1
until isempty(paramNames('score',j,i,l))
legs = l-1
else
for l=1,legs do
entries[j][i]['score'][l] = paramNames('score',j,i,l)
entries[j][i]['score']['weight'][l] = 'normal'
end
end
if aggregate and legs>1 then
entries[j][i]['score']['agg'] = paramNames('score',j,i,'agg')
entries[j][i]['score']['weight']['agg'] = 'normal'
end
end
if entries[j][i]['ctype']=='header' then
entries[j][i]['header'] = paramNames('header',j,i)
entries[j][i]['shade'] = paramNames('shade',j,i)
end
if entries[j][i]['ctype']=='text' then
entries[j][i]['text'] = paramNames('text',j,i)
end
if entries[j][i]['ctype'] == 'line' and entries[j][i]['hastext']==true then
entries[j][i]['text'] = paramNames('text',j,i)
end
end
if autocol and not blankEntry(j,i) then
maxcol = math.max(maxcol,j)
end
if not byes[j] and entries[j][i]~=nil then
byerows = math.max(byerows,i)
end
if byes[j] and not blankEntry(j,i) then
byerows = math.max(byerows,i)
end
end
end
for j=minc,c do
if byes[j] then
r=byerows+1
end
end
if autocol then
c = maxcol
end
end
local function getAltIndices()
local teamindex=1
local textindex=1
local headerindex
for j=minc,c do
headerindex=0
for i=1,r do
if entries[j][i]==nil and i==1 then
headerindex=headerindex+1
end
if entries[j][i]~=nil then
if entries[j][i]['ctype'] == 'header' then
entries[j][i]['altindex'] = headerindex
teamindex=1
textindex=1
headerindex=headerindex+1
elseif entries[j][i]['ctype'] == 'team' then
entries[j][i]['altindex'] = teamindex
teamindex=teamindex+1
elseif entries[j][i]['ctype'] == 'text' then
entries[j][i]['altindex'] = textindex
textindex=textindex+1
elseif entries[j][i]['ctype'] == 'line' and entries[j][i]['hastext']==true then
entries[j][i]['altindex'] = textindex
textindex=textindex+1
end
entries[j][i]['headerindex'] = headerindex
end
end
end
end
local function insertPath(tbl,j,i)
if isempty(pathEntries[j]) or (isempty(pathEntries[j][i]) and isempty(pathEntries[j][i-1])) then
return tbl:tag('td')
:attr('colspan','2')
end
local a = {}
for k=1,2 do
a[k]={0,0,0,0}
end
if notempty(pathEntries[j]) and notempty(pathEntries[j][i]) then
if pathEntries[j][i]:find("out") then a[1][3]=3 end
if pathEntries[j][i]:find("up") then a[1][2]=2 a[2][4]=2 end
if pathEntries[j][i]:find("down") then a[1][2]=2 a[2][4]=2 end
if pathEntries[j][i]:find("in") then a[2][3]=3 end
end
if notempty(pathEntries[j]) and notempty(pathEntries[j][i-1]) then
if pathEntries[j][i-1]:find("out") then a[1][1]=3 end
if pathEntries[j][i-1]:find("in") then a[2][1]=3 end
end
tbl:tag('td')
:css('border-width',a[1][1]..'px '..a[1][2]..'px '..a[1][3]..'px '..a[1][4]..'px')
:css('border-style','solid')
:css('border-color','black')
tbl:tag('td')
:css('border-width',a[2][1]..'px '..a[2][2]..'px '..a[2][3]..'px '..a[2][4]..'px')
:css('border-style','solid')
:css('border-color','black')
end
local function getPaths()
local paths = {}
for j=minc,c-1 do
pathEntries[j] = {}
paths[j] = {}
local str = fargs['col'..j..'-col'..(j+1)..'-paths'] or ''
for val in str:gsub("%s+","")
:gsub(",",", ")
:gsub("%S+","\0%0\0")
:gsub("%b()", function(s) return s:gsub("%z","") end)
:gmatch("%z(.-)%z") do
local result = split(val:gsub("%s+",""):gsub("%)",""):gsub("%(",""),{"-"})
for k,_ in pairs(result) do
result[k] = split(result[k],{","},true)
end
for n=1,#result[1] do
for m=1,#result[2] do
table.insert(paths[j],{result[1][n],result[2][m]})
end
end
end
for k,v in ipairs(paths[j]) do
local hidepath = false
local start = 2*paths[j][k][1]+(teams_per_match[j]-2)
local stop = 2*paths[j][k][2]+(teams_per_match[j+1]-2)
if compact then
start = math.ceil((3*paths[j][k][1]-1)/2)+rowadj[paths[j][k][1]]+(teams_per_match[j]-1)
stop = math.ceil((3*paths[j][k][2]-1)/2)+rowadj[paths[j][k][2]]+(teams_per_match[j+1]-1)
end
if byes[j] then
if blankEntry(j,start-1) and blankEntry(j,start+1) then
hidepath=true
elseif blankEntry(j,start-1) and not blankEntry(j,start+1) then
start=start+1
elseif not blankEntry(j,start-1) and blankEntry(j,start+1) then
start=start-1
end
end
if byes[j+1] then
if blankEntry(j+1,stop-1) and blankEntry(j+1,stop+1) then
hidepath=true
elseif blankEntry(j+1,stop-1) and not blankEntry(j+1,stop+1) then
stop=stop+1
elseif not blankEntry(j+1,stop-1) and blankEntry(j+1,stop+1) then
stop=stop-1
end
end
if bargs('RD'..j..'-RD'..(j+1)..'-path')=='n' or bargs('RD'..j..'-RD'..(j+1)..'-path')=='no' or bargs('RD'..j..'-RD'..(j+1)..'-path')==0 then
if entries[j][start-1]['headerindex']==1 then
hidepath=true
end
end
if not hidepath then
if start==stop then
pathEntries[j][start] = (pathEntries[j][start] or '')..' out in'
elseif start<stop then
pathEntries[j][start] = (pathEntries[j][start] or '')..' out'
for i=start+1,stop-1 do
pathEntries[j][i] = (pathEntries[j][i] or '')..' up down'
end
pathEntries[j][stop] = (pathEntries[j][stop] or '')..' up down in'
elseif start>stop then
pathEntries[j][start] = (pathEntries[j][start] or '')..' up down out'
for i=stop+1,start-1 do
pathEntries[j][i] = (pathEntries[j][i] or '')..' up down'
end
pathEntries[j][stop] = (pathEntries[j][stop] or '')..' in'
end
end
end
end
end
local function getCells()
local maxrow = 1
local colentry = {}
local bool = true
for n=1,100 do
rowadj[n]=0
end
for j=minc,c do
if notempty(fargs['col'..j..'-headers']) then bool=false end
teams_per_match[j] = tonumber(fargs['RD'..j..'-teams-per-match']) or tonumber(fargs['col'..j..'-teams-per-match']) or tonumber(fargs['teams-per-match']) or 2
if bargs('byes')=='yes' or bargs('byes')=='y' then
byes[j]=true else byes[j]=false
end
if bargs('RD'..j..'-byes')=='yes' or bargs('RD'..j..'-byes')=='y' then
byes[j]=true
elseif bargs('RD'..j..'-byes')=='no' or bargs('RD'..j..'-byes')=='n' then
byes[j]=false
end
maxtpm = math.max(maxtpm,teams_per_match[j])
end
for j=minc,c do
entries[j] = {}
colentry[j] = {
split((fargs['col'..j..'-headers'] or ''):gsub("%s+", ""),{","},true),
split((fargs['col'..j..'-matches'] or ''):gsub("%s+", ""),{","},true),
split((fargs['col'..j..'-lines'] or ''):gsub("%s+", ""),{","},true),
split((fargs['col'..j..'-text'] or ''):gsub("%s+", ""),{","},true)
}
if bool==true and fargs['noheaders']~='y' and fargs['noheaders']~='yes' then
table.insert(colentry[j][1],1)
end
end
if compact then
for j=minc,c do
local d = 0
for n=1,#colentry[j][1] do
if colentry[j][1][n]~=1 then
d=d+1
for m=(colentry[j][1][n]),#rowadj do
rowadj[m]=math.max(rowadj[math.floor(m)],d)
end
end
d=d+1
for m=(colentry[j][1][n]+1),#rowadj do
rowadj[m]=math.max(rowadj[math.floor(m)],d)
end
end
end
end
for j=minc,c do
local textindex=0
for k,v in ipairs(colentry[j]) do
table.sort(colentry[j][k])
local ctype
if k==1 then ctype='header'
elseif k==2 then ctype='team'
elseif k==3 then ctype='line'
elseif k==4 then ctype='text'
end
for n=1,#colentry[j][k] do
local i=2*colentry[j][k][n]-1
if compact then
i=math.ceil((3*colentry[j][k][n]-1)/2)+rowadj[colentry[j][k][n]]
end
maxrow = math.max(i+2*teams_per_match[j]-1,maxrow)
if ctype=='team' then
if entries[j][i-2]==nil and entries[j][i-3]==nil then
entries[j][i-2]={['ctype']='text',['index']=n}
textindex=n
end
entries[j][i]={['ctype']=ctype,['index']=teams_per_match[j]*n-(teams_per_match[j]-1),['position']='top'}
for m=2,teams_per_match[j] do
entries[j][i+2*(m-1)]={['ctype']=ctype,['index']=teams_per_match[j]*n-(teams_per_match[j]-m)}
end
elseif ctype=='text' then
entries[j][i]={['ctype']=ctype,['index']=textindex+n}
elseif ctype=='line' then
if entries[j][i+2]~=nil and entries[j][i+2]['ctype']=='text' then
entries[j][i+2]['hastext'] = true
entries[j][i+2]['ctype'] = ctype
else
entries[j][i+2]={['ctype']=ctype}
end
entries[j][i]={['ctype']=ctype}
else
entries[j][i]={['ctype']=ctype,['index']=n,['position']='top'}
end
end
end
end
if isempty(r) then
r = maxrow
end
end
function p.main(frame)
fargs = frame.args
pargs = frame:getParent().args;
r = tonumber(fargs.rows) or ''
c = tonumber(fargs.rounds) or 1
maxc = tonumber(pargs.maxrounds) or tonumber(pargs.maxround) or ''
minc = tonumber(pargs.minround) or 1
if notempty(maxc) then c=maxc end
if fargs.autocol=='yes' or fargs.autocol=='y' then autocol=true end
maxtpm = 1
seeds = true
forceseeds = false
boldwinner = bargs('boldwinner') or ''
if bargs('seeds')=='y' or bargs('seeds')=='yes' then forceseeds=true end
if bargs('seeds')=='n' or bargs('seeds')=='no' then seeds=false end
if fargs.compact=='y' or fargs.compact=='yes' then compact=true end
if bargs('aggregate')=='y' or bargs('aggregate')=='yes' then aggregate=true end
if bargs('autolegs')=='y' or bargs('autolegs')=='yes' then autolegs=true end
getCells()
getAltIndices()
assignParams()
matchGroups()
if (boldwinner=='yes' or boldwinner=='y') then boldWinner() end
getPaths()
for j=minc,c do
maxlegs[j] = rlegs[j]
for i=1,r do
if notempty(entries[j][i]) then
if notempty(entries[j][i]['legs']) then
maxlegs[j] = math.max(rlegs[j],entries[j][i]['legs'])
end
if autolegs then
local l=1
repeat l=l+1
until isempty(entries[j][i]['score']) or isempty(entries[j][i]['score'][l])
maxlegs[j] = math.max(maxlegs[j],l-1)
end
end
end
end
local tbl = mw.html.create('table')
:attr('cellpadding','0')
:attr('cellspacing','0')
:css('font-size','90%')
:css('border-collapse','collapse')
:css('margin','1em 2em 1em 1em')
tbl:tag('tr'):css('visibility','collapse')
tbl:tag('td'):css('width','1px')
for j=minc,c do
if seeds then
tbl:tag('td'):css('width',getWidth('seed','25px'))
end
tbl:tag('td'):css('width',getWidth('team','150px'))
if maxlegs[j]==0 then
tbl:tag('td'):css('width',getWidth('score','25px'))
else
for l=1,maxlegs[j] do
tbl:tag('td'):css('width',getWidth('score','25px'))
end
end
if aggregate and maxlegs[j]>1 then
tbl:tag('td'):css('width',getWidth('score','25px'))
end
if j~=c then
tbl:tag('td'):css('width','5px')
tbl:tag('td'):css('width','5px')
end
end
for i=1,r do
tbl:tag('tr')
tbl:tag('td'):css('height','11px')
for j=minc,c do
if entries[j][i]==nil and entries[j][i-1]==nil then
insertEntry(tbl,j,i)
end
if entries[j][i-1]~=nil and j~=c then
insertPath(tbl,j,i)
end
if entries[j][i]~=nil then
insertEntry(tbl,j,i)
end
if entries[j][i-1]==nil and j~=c then
insertPath(tbl,j,i)
end
end
end
return tostring(tbl)
end
return p