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 or fargs 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]~= nil and entries[j]['ctype']=='team' then matchgroup[j]=math.ceil(entries[j]['index']/teams_per_match[j]) entries[j]['group'] = math.ceil(entries[j]['index']/teams_per_match[j]) end end end end local function boldWinner local function boldScore(j,i,l) if entries[j]~= nil and entries[j]['ctype'] 'team' then local myscore entries[j]['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] 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]['wins'] = entries[j]['wins']+1 else entries[j]['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][wins] local compteam = {} for k,v in pairs(matchgroup[j]) do if matchgroup[j] 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]~ nil and entries[j]['ctype'] 'team' then entries[j]['wins'] = 0 entries[j]['aggwins'] = 0 end end for i=1,r do if entries[j]~= nil and entries[j]['ctype'] 'team' then local legs rlegs[j] if notempty(entries[j]['legs']) then legs tonumber(entries[j]['legs']) end for l 1,legs do entries[j]['score']['weight'][l] boldScore(j,i,l) end if aggregate and legs>1 then entries[j]['score']['weight']['agg'] boldScore(j,i,'agg') end end end for i 1,r do if entries[j]~ nil and entries[j]['ctype'] 'team' then local agg local legs = rlegs[j] if notempty(entries[j]['legs']) then legs = tonumber(entries[j]['legs']) end if aggregate and legs>1 then agg=true end entries[j]['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]['headerindex']),bargs('RD'..j..toChar(entries[j]['headerindex'])..'-altname') or 'RD'..j..toChar(entries[j]['headerindex'])} } local name = {cname, bargs(cname..'-altname') or cname} local index = {entries[j]['index'], entries[j]['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]['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]['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] nil then tbl:tag('td'):attr('colspan',entry_colspan) else local border_top if entries[j]['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]['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]['shade']) :wikitext(entries[j]['header']) end if entries[j]['ctype'] 'team' then local legs rlegs[j] if notempty(entries[j]['legs']) then legs tonumber(entries[j]['legs']) end if autolegs then local l 1 repeat l l+1 until isempty(entries[j]['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]['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]['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]['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]['weight']) :css('white-space', 'nowrap') :wikitext(entries[j]['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]['weight']) :wikitext(entries[j]['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]['score']['weight'][l]) :css('white-space', 'nowrap') :wikitext(tostring(entries[j]['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]['score']['weight']['agg']) :css('white-space', 'nowrap') :wikitext(tostring(entries[j]['score']['agg'])) end end end if entries[j]['ctype'] 'text' then tbl:tag('td') :attr('rowspan',2) :attr('colspan',entry_colspan) :wikitext(entries[j]['text']) end if entries[j]['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]['text']) end if entries[j]['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]['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]~=nil then if entries[j]['ctype'] 'team' then local legs rlegs[j] entries[j]['seed'] paramNames('seed',j,i) entries[j]['team'] paramNames('team',j,i) entries[j]['legs'] paramNames('legs',j,i) entries[j]['score'] {} entries[j]['weight'] 'normal' entries[j]['score']['weight'] {} if notempty(entries[j]['legs']) then legs tonumber(entries[j]['legs']) end if autolegs then local l 1 repeat entries[j]['score'][l] paramNames('score',j,i,l) entries[j]['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]['score'][l] paramNames('score',j,i,l) entries[j]['score']['weight'][l] 'normal' end end if aggregate and legs>1 then entries[j]['score']['agg'] paramNames('score',j,i,'agg') entries[j]['score']['weight']['agg'] 'normal' end end if entries[j]['ctype'] 'header' then entries[j]['header'] = paramNames('header',j,i) entries[j]['shade'] = paramNames('shade',j,i) end if entries[j]['ctype'] 'text' then entries[j]['text'] paramNames('text',j,i) end if entries[j]['ctype'] 'line' and entries[j]['hastext']==true then entries[j]['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]~=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] nil and i 1 then headerindex=headerindex+1 end if entries[j]~=nil then if entries[j]['ctype'] 'header' then entries[j]['altindex'] headerindex teamindex 1 textindex 1 headerindex headerindex+1 elseif entries[j]['ctype'] 'team' then entries[j]['altindex'] = teamindex teamindex=teamindex+1 elseif entries[j]['ctype'] 'text' then entries[j]['altindex'] textindex textindex textindex+1 elseif entries[j]['ctype'] 'line' and entries[j]['hastext']==true then entries[j]['altindex'] = textindex textindex=textindex+1 end entries[j]['headerindex'] = headerindex end end end end local function insertPath(tbl,j,i) if isempty(pathEntries[j]) or (isempty(pathEntries[j]) 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]) then if pathEntries[j]:find("out") then a[1][3]=3 end if pathEntries[j]:find("up") then a[1][2]=2 a[2][4]=2 end if pathEntries[j]:find("down") then a[1][2]=2 a[2][4]=2 end if pathEntries[j]: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] = (pathEntries[j] 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] = (pathEntries[j] 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]={['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] {['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]={['ctype']=ctype} else entries[j]={['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]) then if notempty(entries[j]['legs']) then maxlegs[j] = math.max(rlegs[j],entries[j]['legs']) end if autolegs then local l=1 repeat l=l+1 until isempty(entries[j]['score']) or isempty(entries[j]['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] 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]~ 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