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