Mô đun:Build bracket

local p = {}
local entries = {}
local pathEntries = {}
local pathcolor
local shift = {}
local hascross = {}
local teams_per_match = {}
local rlegs = {}
local maxlegs = {}
local autolegs
local byes = {}
local hide = {}
local matchgroup = {}
local autocol
local seeds
local forceseeds
local nowrap
local boldwinner
local aggregate
local paramstyle
local masterindex
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 pargss or fargss
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()
	for j=minc,c do
		matchgroupj={}
		for i=1,r do
			if entriesji~= nil and entriesji'ctype'=='team' then
				matchgroupji=math.ceil(entriesji'index'/teams_per_matchj)
				entriesji'group' = math.ceil(entriesji'index'/teams_per_matchj)
			end
		end
	end
end
local function teamLegs(j,i)
	local legs = rlegsj
	if notempty(entriesji'legs') then
		legs = tonumber(entriesji'legs')
	end
	if autolegs then
		local l=1
		repeat l=l+1
		until isempty(entriesji'score'l)
		legs = l-1
	end
	return legs
end
local function boldWinner()
	local function boldScore(j,i,l)
		if entriesji~= nil and entriesji'ctype'=='team' then
			local myscore = entriesji'score'l:gsub('%W',)
			if myscore == "" or myscore:find("%D") then return 'normal'
				else myscore=tonumber(myscore) end
			local compscore = {}
			for k,v in pairs(matchgroupj) do
				if matchgroupji==v and k~=i then
					local theirscore = entriesjk'score'l or 
					theirscore = theirscore:gsub('%W',)
					if theirscore== "" or theirscore:find("%D") then return 'normal'
						else table.insert(compscore,tonumber(theirscore)) end
				end
			end
			for k,v in pairs(compscore) do
				if myscorelegs/2 then 
				return 'bold' 
			end
			if autolegs then
				for l=1,legs do
					if notempty(entriesji'score'l) and string.find(entriesji'score'l,"nbsp") then 
						return 'normal' 
					end
				end
			else
				for l=1,legs do
					if isempty(entriesji'score'l) or string.find(entriesji'score'l,"nbsp") then 
						return 'normal' 
					end
				end
			end
		else 
			wins = 'aggwins'
		end
		
		local compteam = {}
		for k,v in pairs(matchgroupj) do
			if matchgroupji==v and k~=i then
				table.insert(compteam,tonumber(entriesjkwins))
			end
		end
		for k,v in pairs(compteam) do
			if entriesjiwins1 then
					entriesji'scoreweightagg' = boldScore(j,i,'agg')
				end
			end
		end
		for i=1,r do
			if entriesji~= nil and entriesji'ctype'=='team' then
				local agg
				local legs = teamLegs(j,i)
				if aggregate and legs>1 then agg=true end
				entriesji'weight' = boldTeam(j,i,agg)
			end
		end
	end
end
local function isBlankEntry(col,row,ctype)
	if isempty(entriescolrow) then return true end
	if isempty(entriescolrow'team') and isempty(entriescolrow'text') then return true end
	return false
end
local function showSeeds(j,i)
	local showseed=false
	if forceseeds or notempty(entriesji'seed') then
		showseed=true
	else
		for k=1,teams_per_matchj-1 do
			if notempty(entriesji+2*k) and entriesji'group'==entriesji+2*k'group' and notempty(entriesji+2*k'seed') then
				showseed=true
			end
			if notempty(entriesji-2*k) and entriesji'group'==entriesji-2*k'group' and notempty(entriesji-2*k'seed') then
				showseed=true
			end
		end
	end
	return showseed
end
local function blankCell(tbl,j,i,rowspan,colspan,text,align)
	local cell = tbl:tag('td')
		cell:attr('colspan',colspan)
	end
		cell:attr('rowspan',rowspan)
	end
	if notempty(align) then
		cell:css('text-align',align)
	end
	if notempty(text) then
		if nowrap then
			cell:css('white-space', 'nowrap')
		end
		cell:wikitext(text)
	end
	return cell
end
local function headerCell(tbl,j,i,colspan)
	local cell = tbl:tag('td')
					:attr('rowspan',2)
					:css('text-align','center')
					:css('border','1px solid #aaa')
					:css('background-color',entriesji'shade')
					:wikitext(entriesji'header')
		cell:attr('colspan',colspan)
	end
	if nowrap then
		cell:css('white-space', 'nowrap')
	end
	if entriesji'position'=='top' and entriesji-2~=nil and entriesji-2'ctype'~='blank' and entriesji-2'ctype'~='text' and entriesji-2'ctype'~='group' and (not byesjentriesji'headerindex' or not isBlankEntry(j,i-2)) then
		cell:css('border-top','2px solid #aaa')
	end
	return cell
end
local function teamCell(tbl,k,j,i,l,colspan)
	local bg = '#F2F2F2'
	local cell = tbl:tag('td')
					:attr('rowspan',2)
					:css('border','1px solid #aaa')
		cell:attr('colspan',colspan)
	end
	if k=='seed' or k=='score' then
		cell:css('text-align','center')
	end
	if k=='seed' or k=='score' or nowrap then
		cell:css('white-space', 'nowrap')
	end
	if k=='seed' then
		cell:css('border-right','2px solid #aaa')
	else
		bg='#F9F9F9'
	end
	if k=='team' then 
		cell:css('padding-left','0.3em') 
	end
	if l=='agg' then
		cell:css('border-left','2px solid #aaa')
	end	
	if (l==nil and entriesji'weight'=='bold') or entriesji'scoreweight'l=='bold' then
		cell:css('font-weight','bold')
	end
	if entriesji'position'=='top' and entriesji-2~=nil and entriesji-2'ctype'~='blank' and entriesji-2'ctype'~='text' and entriesji-2'ctype'~='group' and (not byesjentriesji'headerindex' or not isBlankEntry(j,i-2)) then
		cell:css('border-top','2px solid #aaa')
	end
	cell:css('background-color',bg)
	if l==nil then
		cell:wikitext(entriesjik)
	else
		cell:wikitext(tostring(entriesjikl))
	end
	return cell
end
local function insertEntry(tbl,j,i)
	local entry_colspan=maxlegsj+2
	if not seeds then entry_colspan=entry_colspan-1	end
	if (aggregate and maxlegsj>1) or maxlegsj==0 then
		entry_colspan=entry_colspan+1
	end
	
	if entriesji~=nil and entriesji'ctype'=='blank' then
		return
	end
	
	if entriesji==nil then
		if entriesji-1~=nil or i==1 then
			local rowspan = 0
			local row = i
			repeat
				row=row+1
			until entriesjrow~=nil or row>r
			return blankCell(tbl,j,i,rowspan,entry_colspan)
		else
			return
		end
	end
	if entriesji'ctype'=='header' then
		if byesjentriesji'headerindex' then
			local emptyround = true
			local row = i+1
			repeat
				if not isBlankEntry(j,row) then
					emptyround = false
				end
				row = row+1
			until (entriesjrow~=nil and entriesjrow'ctype'=='header') or row>r
			if emptyround == true then
				return blankCell(tbl,j,i,2,entry_colspan)
			end
		end
		
		if hidejentriesji'headerindex' then
			return blankCell(tbl,j,i,2,entry_colspan)
		end
		
		if isempty(entriesji'header') then
			if entriesji'headerindex'==1 then
				if     j==c   then entriesji'header' = 'Chung kết'
				elseif j==c-1 then entriesji'header' = 'Bán kết'
				elseif j==c-2 then entriesji'header' = 'Tứ kết'
				else			   entriesji'header' = 'Vòng '..j
				end
			else
				entriesji'header' = 'Lower round '..j
			end
		end
		
		return headerCell(tbl,j,i,entry_colspan)
	end
	
	if entriesji'ctype'=='team' then
		if byesjentriesji'headerindex' and isBlankEntry(j,i) then
			return blankCell(tbl,j,i,2,entry_colspan)
		end
		if hidejentriesji'headerindex' then
			return blankCell(tbl,j,i,2,entry_colspan)
		end
		
		local legs = teamLegs(j,i)
		local team_colspan
		
		team_colspan = maxlegsj-legs+1
		if aggregate and legs==1 and maxlegsj>1 then
			team_colspan=team_colspan+1
		end
		if maxlegsj==0 then 
			team_colspan=team_colspan+1
		end
		
		if seeds then
			if showSeeds(j,i)==true then
				teamCell(tbl,'seed',j,i)
			else
				team_colspan=team_colspan+1
			end
		end
		teamCell(tbl,'team',j,i,nil,team_colspan)
		for l=1,legs do
			teamCell(tbl,'score',j,i,l)
		end
		if aggregate and legs>1 then
			teamCell(tbl,'score',j,i,'agg')
		end
	end
	
	if entriesji'ctype'=='text' then
		blankCell(tbl,j,i,2,entry_colspan,entriesji'text')
	end
	
	if entriesji'ctype'=='group' then
		local colspan=0
		for m=j,entriesji'colspan'+j-1 do
			if not seeds then colspan=colspan-1 end
			if (aggregate and maxlegsm>1) or maxlegsm==0 then
			end
		end
		blankCell(tbl,j,i,2,colspan,entriesji'group','center')
	end
	
	if entriesji'ctype'=='line' then
		tbl:tag('td')
			:attr('rowspan',2)
			:attr('colspan',entry_colspan)
			:css('border-bottom','3px solid black')
			:wikitext(entriesji'text')
	end
end
local function isRoundHidden(j,i,headerindex)
	if notempty(entriesji'pheader') then
		hidejentriesji'headerindex' = false
	end
	local row = i+1
	repeat
		if not isBlankEntry(j,row) then
			hidejentriesji'headerindex' = false
		end
		row = row+1
	until (entriesjrow~=nil and entriesjrow'ctype'=='header') or row>r
end
local function paramNames(cname,j,i,l)
	local rname = {
			{'RD'..j, bargs('RD'..j..'-altname') or 'RD'..j},
			{'RD'..j..toChar(entriesji'headerindex'),bargs('RD'..j..toChar(entriesji'headerindex')..'-altname') or 'RD'..j..toChar(entriesji'headerindex')}
			}
	local name = {cname, bargs(cname..'-altname') or cname}
	local index = {entriesji'index', entriesji'altindex'}
	local result = {}
	if cname=='header' then
		if entriesji'headerindex'==1 then 
			for k=1,2 do
				table.insert(result,bargs(rname13-k) or )
				table.insert(result,bargs(rname23-k) or )
			end
		else 
			for k=1,2 do
				table.insert(result,bargs(rname23-k) or )
			end
		end
	elseif cname=='pheader' then
		if entriesji'headerindex'==1 then 
			for k=1,2 do
				table.insert(result,pargsrname13-k or )
				table.insert(result,pargsrname23-k or )
			end
		else 
			for k=1,2 do
				table.insert(result,pargsrname23-k or )
			end
		end
	elseif cname=='score' then
		for m=1,2 do for k=1,2 do
			if l==1 then
				table.insert(result,bargs(rname3-m3-k..'-'..name1..index3-m) or bargs(rname3-m3-k..'-'..name1..'0'..index3-m) or )
			end
			table.insert(result,bargs(rname3-m3-k..'-'..name1..index3-m..'-'..l) or bargs(rname3-m3-k..'-'..name1..'0'..index3-m..'-'..l) or )
		end	end
	elseif cname=='shade' then
		for k=1,2 do
			if entriesji'headerindex'==1 then
				table.insert(result,bargs(rname13-k..'-'..name1) or )
			else
				table.insert(result,bargs(rname23-k..'-'..name1) 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(rname3-m3-k..'-'..name3-n..index3-m) or bargs(rname3-m3-k..'-'..name3-n..'0'..index3-m) or )
		end end	end
	else
		for m=1,2 do for k=1,2 do
			table.insert(result,bargs(rname3-m3-k..'-'..name1..index3-m) or bargs(rname3-m3-k..'-'..name1..'0'..index3-m) or )
		end	end
	end
	for k=1,#result do
		if notempty(resultk) then
			return resultk
		end
	end
	return 
end
local function indexedParams(j)
	for i=1,r do
		if entriesji~=nil then
			if entriesji'ctype'=='team' then
				local legs = rlegsj
				if forceseeds then
					entriesji'seed' = bargs(masterindex) or 
					masterindex = masterindex+1
				end
				entriesji'team' = bargs(tostring(masterindex)) or 
				masterindex = masterindex+1
				entriesji'legs' = paramNames('legs',j,i)
				entriesji'score' = {}
				entriesji'weight' = 'normal'
				entriesji'scoreweight' = {}
				if notempty(entriesji'legs') then
					legs = tonumber(entriesji'legs')
				end
				for l=1,legs do
					entriesji'score'l = bargs(tostring(masterindex)) or 
					masterindex = masterindex+1
					entriesji'scoreweight'l = 'normal'
				end
				if aggregate and legs>1 then
					entriesji'scoreagg' = bargs(masterindex) or 
					masterindex = masterindex+1
					entriesji'scoreweightagg' = 'normal'
				end
			end
			if entriesji'ctype'=='header' then
				entriesji'header' = paramNames('header',j,i)
				entriesji'pheader' = paramNames('pheader',j,i)
				entriesji'shade' = paramNames('shade',j,i)
			end
			if entriesji'ctype'=='text' then
				entriesji'text' = bargs(tostring(masterindex)) or 
				masterindex = masterindex+1
			end
			if entriesji'ctype'=='group' then
				entriesji'group' = bargs(tostring(masterindex)) or 
				masterindex = masterindex+1
			end
			if entriesji'ctype' == 'line' and entriesji'hastext'==true then
				entriesji'text' = bargs(masterindex) or 
				masterindex = masterindex+1
			end
		end
	end
end
local function assignParams()
	masterindex = 1
	local maxcol = 1
	local byerows = 1
	local hiderows = 1
	for j=minc,c do
		rlegsj = tonumber(bargs('RD'..j..'-legs')) or tonumber(bargs('legs')) or 1
		if notempty(bargs('RD'..j..'-legs')) or bargs('legs') then autolegs = false end
		if paramstyle == 'numbered' then
			indexedParams(j)
		else
			for i=1,r do
				if entriesji~=nil then
					if entriesji'ctype'=='team' then
						local legs = rlegsj
						entriesji'seed' = paramNames('seed',j,i)
						entriesji'team' = paramNames('team',j,i)
						entriesji'legs' = paramNames('legs',j,i)
						entriesji'score' = {}
						entriesji'weight' = 'normal'
						entriesji'scoreweight' = {}
						if notempty(entriesji'legs') then
							legs = tonumber(entriesji'legs')
						end
						if autolegs then
							local l=1
							repeat
								entriesji'score'l = paramNames('score',j,i,l)
								entriesji'scoreweight'l = 'normal'
								l=l+1
							until isempty(paramNames('score',j,i,l))
							legs = l-1
						else
							for l=1,legs do
								entriesji'score'l = paramNames('score',j,i,l)
								entriesji'scoreweight'l = 'normal'
							end
						end
						if aggregate and legs>1 then
							entriesji'scoreagg' = paramNames('score',j,i,'agg')
							entriesji'scoreweightagg' = 'normal'
						end
					end
					if entriesji'ctype'=='header' then
						entriesji'header' = paramNames('header',j,i)
						entriesji'pheader' = paramNames('pheader',j,i)
						entriesji'shade' = paramNames('shade',j,i)
					end
					if entriesji'ctype'=='text' then
						entriesji'text' = paramNames('text',j,i)
					end
					if entriesji'ctype'=='group' then
						entriesji'group' = paramNames('group',j,i)
					end
					if entriesji'ctype' == 'line' and entriesji'hastext'==true then
						entriesji'text' = paramNames('text',j,i)
					end
				end
				if autocol and not isBlankEntry(j,i) then
					maxcol = math.max(maxcol,j)
				end
			end
		end
		for i=1,r do
			if entriesji~=nil and entriesji'ctype'=='header' then 
				isRoundHidden(j,i) 
			end
			if entriesji~=nil and not hidejentriesji'headerindex' then
				if not byesjentriesji'headerindex' or (byesjentriesji'headerindex' and not isBlankEntry(j,i)) then
					byerows = math.max(byerows,i)
				end
			end
		end
	end
	for j=minc,c do
		for k=1,headerindexj do
			if byesjk or hidejk then
				r=byerows+1
			end
		end
	end
	if autocol then
		c = maxcol
	end
end
local function getHide(j,headerindex)
	hidej = {}
	for k=1,headerindexj do
		if bargs('RD'..j..toChar(k)..'-hide')=='yes' or bargs('RD'..j..toChar(k)..'-hide')=='y' then
			hidejk=true
		end
	end
end
local function getByes(j,headerindex)
	byesj = {}
	for k=1,headerindexj do
		if bargs('byes')=='yes' or bargs('byes')=='y' then
			byesjk=true else byesjk=false
		end
		if bargs('RD'..j..'-byes')=='yes' or bargs('RD'..j..'-byes')=='y' then
			byesjk=true
		elseif bargs('RD'..j..'-byes')=='no' or bargs('RD'..j..'-byes')=='n' then
			byesjk=false
		end
		if bargs('RD'..j..toChar(k)..'-byes')=='yes' or bargs('RD'..j..toChar(k)..'-byes')=='y' then
			byesjk=true
		elseif bargs('RD'..j..'-byes')=='no' or bargs('RD'..j..'-byes')=='n' then
			byesjk=false
		end
	end
end
local function getAltIndices()
	local teamindex=1
	local textindex=1
	local groupindex=1
	for j=minc,c do
		headerindexj=0
		for i=1,r do
			if entriesji==nil and i==1 then
				headerindexj=headerindexj+1
			end
			if entriesji~=nil then
				if entriesji'ctype' == 'header' then
					entriesji'altindex' = headerindexj
					teamindex=1
					textindex=1
					headerindexj=headerindexj+1
				elseif entriesji'ctype' == 'team' then
					entriesji'altindex' = teamindex
					teamindex=teamindex+1
				elseif entriesji'ctype' == 'text' then
					entriesji'altindex' = textindex
					textindex=textindex+1
				elseif entriesji'ctype' == 'group' then
					entriesji'altindex' = groupindex
					groupindex=groupindex+1
				elseif entriesji'ctype' == 'line' and entriesji'hastext'==true then
					entriesji'altindex' = textindex
					textindex=textindex+1
				end
				entriesji'headerindex' = headerindexj
			end
		end
		getByes(j,headerindex)
		getHide(j,headerindex)
	end
end
local function pathCell(tbl,j,i,k,a,b,c,bg,rowspan)
	if not hascrossj and k==2 then return end
	if pathcolor==nil then pathcolor='black' end
	local cell=tbl:tag('td')
		cell:attr('rowspan',rowspan)
	end
	if notempty(bgk) then
		cell:css('background',bgk)
	end
	if ak1~=0 or ak2~=0 or ak3~=0 or ak4~=0 then
		cell:css('border','solid black')
			:css('border-width',ak1..'px '..ak2..'px '..ak3..'px '..ak4..'px')
	end
	if ck2~=0 then
		cell:css('border-right',ck2..'px solid '..pathcolor)
	end
	if bk2~=0 then
		cell:css('box-shadow', '0px '..bk2..'px 0px '..pathcolor)
	end
	if ck4~=0 then
		cell:css('border-left',ck4..'px solid '..pathcolor)
	end
	return cell
end
local function insertPath(tbl,j,i)
	local function createCross(angle,color,percent)
		local result = 'linear-gradient('..angle..', transparent calc('..percent..'% - 1px),'..color..' calc('..percent..'% - 1px),'..color..' calc('..percent..'% + 1px), transparent calc('..percent..'% + 1px))'
		return result
	end
	local colspan = 2
	if hascrossj then colspan = 3 end
	
	if pathEntries'black'ji=='blank' then return end
	
	if isempty(pathEntries'black'ji) and isempty(pathEntries'color'ji) then
		if (pathEntries'black'ji-1~='blank' and notempty(pathEntries'black'ji-1)  and (pathEntries'black'ji-1'cross'1 == 1 or pathEntries'black'ji-1'cross'2 == 1)) or (notempty(pathEntries'color'ji-1) and (pathEntries'color'ji-1'cross'1 == 1 or pathEntries'color'ji-1'cross'2 == 1)) then
			return
		else
			local cell = tbl:tag('td')
			for k=1,colspan-1 do
				cell:tag('td')
			end
			return cell
		end
	end
	
	for key,_ in pairs(pathEntries) do
		if notempty(pathEntrieskeyj) and notempty(pathEntrieskeyji-1) and pathEntrieskeyji-1~='blank' then
			if pathEntrieskeyji-1'cross'1==1 or pathEntrieskeyji-1'cross'2==1 then return end
		end
	end
	
	local a = {}
	local b = {}
	local c = {}
	local bg = {}
	local cross = {}
	local rowspan = 1
	
	for k=1,3 do
		ak={0,0,0,0}
		bk={0,0}
		ck={0,0,0,0}
		bgk = 
		crossk = {}
		for n=1,2 do
			crosskn = 
		end
	end
	
	for key,_ in pairs(pathEntries) do
		local color
		if key=='black' then color='black' else color=pathcolor end
		if notempty(pathEntrieskeyj) and notempty(pathEntrieskeyji) then
			if key=='black' then
				a13 = 3*pathEntries'black'ji'out'1
				a23 = 3*pathEntries'black'ji'mid'1
				a33 = 3*pathEntries'black'ji'in'1
				a12 = 2*pathEntries'black'ji'out'2
				a34 = 2*pathEntries'black'ji'in'2
			else
				if pathEntries'color'ji'out'3=='below' then
					b12 = 4*pathEntries'color'ji'out'1 
				end
				if pathEntries'color'ji'mid'3=='below' then
					b22 = 4*pathEntries'color'ji'mid'1
				end
				if pathEntries'color'ji'in'3=='below' then
					b32 = 4*pathEntries'color'ji'in'1
				end
				c12 = 2*pathEntries'color'ji'out'2
				c34 = 2*pathEntries'color'ji'in'2
			end
			if pathEntrieskeyji'cross'1==1 or pathEntrieskeyji'cross'2==1 then
				if pathEntrieskeyji'cross'1==1 then
					cross11 = createCross('65.5deg',color,100)
					cross21 = createCross('to top right',color,50)
					cross31 = createCross('245.5deg',color,100)
				end
				if pathEntrieskeyji'cross'2==1 then
					cross12 = createCross('114.4deg',color,100)
					cross22 = createCross('to bottom right',color,50)
					cross32 = createCross('294.4deg',color,100)
				end
			end
		end
	end
	if notempty(pathEntries'color'j) and notempty(pathEntries'color'ji-1) then
		if pathEntries'color'ji'out'3=='above' then
			b12 = -4
		end
		if pathEntries'color'ji'mid'3=='above' then
			b22 = -4
		end
		if pathEntries'color'ji'in'3=='above' then
			b32 = -4
		end
	end
	if notempty(cross21) and notempty(cross22) then
		for k=1,3 do crossk1 = crossk1..',' end
	end
	for k=1,3 do
		bgk = crossk1..crossk2
	end
	
	for k=1,3 do
		pathCell(tbl,j,i,k,a,b,c,bg,rowspan)
	end
end
local function getPaths()
	local paths = {}
	pathEntries'black' = {}
	pathEntries'color' = {}
	for j=minc,c-1 do
		pathEntries'black'j = {}
		pathEntries'color'j = {}
		for i=1,r do
			pathEntries'black'ji = {'out'={0,0,nil},'mid'={0,0,nil},'in'={0,0,nil},'cross'={0,0,nil}}
			pathEntries'color'ji = {'out'={0,0,nil},'mid'={0,0,nil},'in'={0,0,nil},'cross'={0,0,nil}}
		end
		pathsj = {}
		hascrossj = false
		local crossloc = split((fargs'col'..j..'-col'..(j+1)..'-cross' or ):gsub("%s+", ""),{","},true)
		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
				resultk = split(resultk,{","})
			end
			if notempty(result2) then
				for m=1,#result2 do
					result3 = {}
					result2m = split(result2m,{":"})
					result3m = result2m2
					result2m = result2m1
				end
				for n=1,#result1 do
					for m=1,#result2 do
						table.insert(pathsj,{tonumber(result1n),tonumber(result2m),'color'=result3m})
					end
				end
			end
		end
		if shiftj~=0 and notempty(crossloc1) then
			for n=1,#crossloc do
				crosslocn = crosslocn+shiftj
			end
		end
		for k,v in ipairs(pathsj) do
			local color
			local hidepath = false
			if shiftj~=0 then
				pathsjk1 = pathsjk1+shiftj
			end
			if shiftj+1~=0 then
				pathsjk2 = pathsjk2+shiftj+1
			end
			local start = 2*pathsjk1+(teams_per_matchj-2)
			local mid = {}
			if notempty(crossloc1) then
				for n=1,#crossloc do
					midn = 2*crosslocn+(teams_per_matchj-2)
				end
			else
				mid1=0
			end
			local stop = 2*pathsjk2+(teams_per_matchj+1-2)
			if pathsjk'color'~=nil then 
				pathcolor = pathsjk'color'
				color = 'color'
			else
				color = 'black'
			end
			if notempty(entriesjstart-1) and (byesjentriesjstart-1'headerindex' and isBlankEntry(j,start-1) and isBlankEntry(j,start+1) or hidejentriesjstart-1'headerindex') then
				if bargs('show-bye-paths')~='y' and bargs('show-bye-paths')~='yes' then
					hidepath=true
				end
			end
			if notempty(entriesj+1stop-1) and (byesj+1entriesj+1stop-1'headerindex' and isBlankEntry(j+1,stop-1) and isBlankEntry(j+1,stop+1) or hidej+1entriesj+1stop-1'headerindex')then
				if bargs('show-bye-paths')~='y' and bargs('show-bye-paths')~='yes' then
					hidepath=true
				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 notempty(entriesjstart-1) and entriesjstart-1'headerindex'==1 then
					hidepath=true
				end
			end
			
			local cross = 0
			for n=1,#mid do
				if (startstart) or (start>stop and midn>stop and midnr then break end
					start = math.min(start,r)
					pathEntriescolorjstart'out'1 = 1
					pathEntriescolorjstart'in'1 = 1
					if cross==0 then
						pathEntriescolorjstart'mid'1 = 1
					end
				elseif startr then break end
					pathEntriescolorjstart'out'1 = 1
					pathEntriescolorjstop'in'1 = 1
					pathEntriescolorjstop'in'2 = 1
					if color~='black' then
						pathEntriescolorjstart'out'3 = 'below'
						pathEntriescolorjstop+1'in'3 = 'above'
					end
					if cross==0 then
						pathEntriescolorjstart'mid'1 = 1
						pathEntriescolorjstart'mid'3 = 'below'
						for i=start+1,stop-1 do pathEntriescolorji'in'2 = 1 end
					else
						pathEntriescolorjcross'cross'1 = 1
						for i=start+1,cross-1 do pathEntriescolorji'out'2 = 1 end
						for i=cross+2,stop-1 do pathEntriescolorji'in'2 = 1 end
					end
				elseif start>stop then
					if start>r then break end
					pathEntriescolorjstop'in'1 = 1
					if cross==0 then
						for i=stop+1,start-1 do pathEntriescolorji'in'2 = 1 end
						pathEntriescolorjstart'out'1 = 1
						pathEntriescolorjstart'mid'1 = 1
						pathEntriescolorjstart'in'2 = 1
						if color~='black' then
							pathEntriescolorjstart+1'out'3 = 'above'
							pathEntriescolorjstart+1'mid'3 = 'above'
							pathEntriescolorjstop'in'3 = 'below'
						end
					else
						pathEntriescolorjcross'cross'2 = 1
						for i=stop+1,cross-1 do pathEntriescolorji'in'2 = 1 end
						for i=cross+2,start-1 do pathEntriescolorji'out'2 = 1 end
						pathEntriescolorjstart'out'1 = 1
						pathEntriescolorjstart'out'2 = 1
						if color~='black' then
							pathEntriescolorjstart+1'out'3 = 'above'
							pathEntriescolorjstop'in'3 = 'below'
						end
					end
				end
			end
		end
	end
	for j=minc,c-1 do
		for i=1,r do
			local empty = true
			for key,_ in pairs(pathEntries) do
				for k,v in pairs(pathEntrieskeyji) do
					if v1~=0 or v2~=0 or v3~=nil then
						empty = false
					end
				end
				if empty then pathEntrieskeyji = nil end
			end
		end
	end
	for j=minc,c-1 do
		if notempty(pathEntries'black'j) and notempty(pathEntries'black'j+1) then
			for i=1,r do
				if (entriesj+1i-1==nil or (byesj+1entriesj+1i-1'headerindex') and isBlankEntry(j+1,i-1)) and notempty(pathEntries'black'ji) and notempty(pathEntries'black'j+1i) then
					if pathEntries'black'ji'in'1==1 and pathEntries'black'j+1i'out'1==1 then
						entriesj+1i-1={'ctype'='line'}
						entriesj+1i={'ctype'='blank'}
					end
				end
			end
		end
	end
end
local function getGroups()
	local function check(j,i)
		local result=false
		if entriesji == nil then
			if entriesji+1 == nil then 
				result=true 
			elseif entriesji+1'ctype'=='text' and isBlankEntry(j,i+1) then
				result=true
			end
		elseif entriesji'ctype'=='text' and isBlankEntry(j,i) then
			result=true
		end
		return result
	end
	for j=minc,c-1 do
		if teams_per_matchj==2 then
			local n=0
			for i=1,r do
				if (notempty(pathEntries'black'ji) and pathEntries'black'ji'in'1 == 1) or (notempty(pathEntries'color'ji) and pathEntries'color'ji'in'1 == 1) then
					n=n+1
					if check(j,i) then
						local k=minc-1
						repeat
							if entriesj-ki+1~=nil and entriesj-ki+1'ctype'=='text' and isBlankEntry(j-k,i+1) then
								entriesj-ki+2=nil
							end
							entriesj-ki={'ctype'='blank'}
							entriesj-ki+1={'ctype'='blank'}
							if k>0 and isempty(pathEntries'black'j-ki) and isempty(pathEntries'color'j-ki) then
								pathEntries'black'j-ki = 'blank'
								pathEntries'black'j-ki+1 = 'blank'
							end
							k=k+1
						until k>j-1 or not check(j-k,i) or notempty(pathEntries'black'j-ki) or notempty(pathEntries'color'j-ki)
						k=k-1
						entriesj-ki={'ctype'='group','index'=n,'colspan'=k+1}
						entriesj-ki+1={'ctype'='blank'}
						entriesj-ki'group' = bargs('RD'..j..'-group'..n)
					end
				end
			end
		end
	end
end
local function getCells()
	local maxrow = 1
	local colentry = {}
	local bool = true
	for j=minc,c do
		if notempty(fargs'col'..j..'-headers') then bool=false end
		teams_per_matchj = tonumber(fargs'RD'..j..'-teams-per-match') or tonumber(fargs'col'..j..'-teams-per-match') or tonumber(fargs'teams-per-match') or 2
		maxtpm = math.max(maxtpm,teams_per_matchj)
	end
	for j=minc,c do
		entriesj = {}
		shiftj = tonumber(bargs('RD'..j..'-shift')) or tonumber(bargs('shift')) or 0
		colentryj = {
			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(colentryj1,1)
		end
	end
	for j=minc,c do
		local textindex=0
		for k,v in ipairs(colentryj) do
			table.sort(colentryjk)
			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'
			elseif k==5 then ctype='group'
			end
			for n=1,#colentryjk do
				if shiftj~=0 and colentryjkn>1 then
					colentryjkn = colentryjkn+shiftj
				end
				local i=2*colentryjkn-1
				maxrow = math.max(i+2*teams_per_matchj-1,maxrow)
				if ctype=='team' then
					if entriesji-1==nil and entriesji-2==nil then
						entriesji-2={'ctype'='text','index'=n}
						entriesji-1={'ctype'='blank'}
						textindex=n
					end
					entriesji={'ctype'=ctype,'index'=teams_per_matchj*n-(teams_per_matchj-1),'position'='top'}
					entriesji+1={'ctype'='blank'}
					for m=2,teams_per_matchj do
						entriesji+2*(m-1)={'ctype'=ctype,'index'=teams_per_matchj*n-(teams_per_matchj-m)}
						entriesji+2*(m-1)+1={'ctype'='blank'}
					end
				elseif ctype=='text' then
					entriesji={'ctype'=ctype,'index'=textindex+n}
					entriesji+1={'ctype'='blank'}
				elseif ctype=='line' then
					entriesji={'ctype'=ctype}
					entriesji+1={'ctype'='blank'}
				elseif ctype=='group' then
					entriesji={'ctype'=ctype,'index'=n}
					entriesji+1={'ctype'='blank'}
				else
					entriesji={'ctype'=ctype,'index'=n,'position'='top'}
					entriesji+1={'ctype'='blank'}
				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
	headerindex = {}
	if notempty(maxc) then c=maxc end
	if fargs.autocol=='yes' or fargs.autocol=='y' then autocol=true end
	local colspacing = tonumber(fargs'col-spacing') or 5
	
	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 bargs('aggregate')=='y' or bargs('aggregate')=='yes' then aggregate=true end
	if bargs('autolegs')=='y' or bargs('autolegs')=='yes' then autolegs=true end
	if bargs('nowrap')=='y' or bargs('nowrap')=='yes' then nowrap=true end
	if bargs('paramstyle')=='numbered' then 
		paramstyle = 'numbered'
	else
		paramstyle = 'indexed'
	end
	
	getCells()
	getAltIndices()
	assignParams()
	matchGroups()
	if (boldwinner=='yes' or boldwinner=='y' or boldwinner=='high') then boldWinner() end
	getPaths()
	if minc==1 then
	getGroups()
	end
	
	for j=minc,c do
		maxlegsj = rlegsj
		for i=1,r do
			if notempty(entriesji) then
				if notempty(entriesji'legs') then
					maxlegsj = math.max(rlegsj,entriesji'legs')
				end
				if autolegs then
					local l=1
					repeat l=l+1
					until isempty(entriesji'score') or isempty(entriesji'score'l)
					maxlegsj = math.max(maxlegsj,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 maxlegsj==0 then
			tbl:tag('td'):css('width',getWidth('score','25px'))
			else
			for l=1,maxlegsj do
				tbl:tag('td'):css('width',getWidth('score','25px'))
			end
		end
		if aggregate and maxlegsj>1 then
			tbl:tag('td'):css('width',getWidth('score','25px'))
		end
		if j~=c then
			if hascrossj then
				tbl:tag('td'):css('width',colspacing..'px')
				tbl:tag('td'):css('width','10px')
				tbl:tag('td'):css('width',colspacing..'px')
			else
				tbl:tag('td'):css('width',colspacing..'px')
				tbl:tag('td'):css('width',colspacing..'px')
			end
		end
	end
	
	for i=1,r do
		local row = tbl:tag('tr')
		row:tag('td'):css('height','11px')
		for j=minc,c do
			insertEntry(row,j,i)
			if j~=c then
				insertPath(row,j,i)
			end
		end
	end
			
	return tostring(tbl)
end
return p