local p = {} local entries = {} local pathCell = {} local crossCell = {} local skipPath = {} 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 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() 	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 teamLegs(j,i) 	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 	return legs 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]:gsub('%W',) 			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 					local theirscore = entries[j][k]['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 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 boldTeam(j,i,agg) 		local wins 		local legs = teamLegs(j,i) 		if agg~=true then 			wins = 'wins' 			if entries[j][i][wins]>legs/2 then  				return 'bold'  			end 			if autolegs then 				for l=1,legs do 					if notempty(entries[j][i]['score'][l]) and string.find(entries[j][i]['score'][l],"nbsp") then  						return 'normal'  					end 				end 			else 				for l=1,legs do 					if isempty(entries[j][i]['score'][l]) or string.find(entries[j][i]['score'][l],"nbsp") then  						return 'normal'  					end 				end 			end 		else  			wins = 'aggwins' 		end 		 		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 entries[j][i][wins]<=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 = teamLegs(j,i) 				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 = teamLegs(j,i) 				if aggregate and legs>1 then agg=true end 				entries[j][i]['weight'] = boldTeam(j,i,agg) 			end 		end 	end end  local function isBlankEntry(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 showSeeds(j,i) 	local showseed=false 	if forceseeds or 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]) and entries[j][i]['group']==entries[j][i+2*k]['group'] and notempty(entries[j][i+2*k]['seed']) then 				showseed=true 			end 			if notempty(entries[j][i-2*k]) and entries[j][i]['group']==entries[j][i-2*k]['group'] and notempty(entries[j][i-2*k]['seed']) then 				showseed=true 			end 		end 	end 	return showseed end  local function cellBorder(b) 	return b[1]..'px '..b[2]..'px '..b[3]..'px '..b[4]..'px' end  local function Cell(tbl,j,i,rowspan,colspan,text,align,border,border_width,bg,padding,weight,nwrap) 	local cell = tbl:tag('td') 	if colspan~=1 then 		cell:attr('colspan',colspan) 	end 	if rowspan~=1 then 		cell:attr('rowspan',rowspan) 	end 	if notempty(border) then 		cell:css('border',border) 	end 	if notempty(border_width) then 		cell:css('border-width',cellBorder(border_width)) 	end 	if notempty(bg) then 		cell:css('background-color',bg) 	end 	if notempty(align) then 		cell:css('text-align',align) 	end 	if notempty(padding) then 		cell:css('padding-left',padding) 	end 	if weight=='bold' then 		cell:css('font-weight',weight) 	end 	if notempty(text) then 		if nowrap or nwrap then 			cell:css('white-space','nowrap') 		end 		cell:wikitext(text) 	end 	return cell end  local function teamCell(tbl,k,j,i,l,colspan) 	local bg = '#F2F2F2' 	local align 	local padding 	local weight 	local text 	local nwrap 	local b={0,0,1,1} 	if k=='seed' or k=='score' then 		align='center' 	end 	if k=='seed' or k=='score' or nowrap then 		nwrap=true 	end 	if k~='seed' then 		bg='#F9F9F9' 	end 	if k=='team' then  		padding='0.3em' 		if teamLegs(j,i)==0 then 			b[2]=1 		end 	end 	if entries[j][i]['position']=='top' then 		b[1]=1 	end 	if l==teamLegs(j,i) or l=='agg' or k=='seed' then 		b[2]=1 	end 	if (l==nil and entries[j][i]['weight']=='bold') or entries[j][i]['score']['weight'][l]=='bold' then 		weight='bold' 	end 	if l==nil then 		text=entries[j][i][k] 	else 		text=tostring(entries[j][i][k][l]) 	end 	return Cell(tbl,j,i,2,colspan,text,align,'solid #aaa',b,bg,padding,weight,nwrap) 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 and entries[j][i]['ctype']=='blank' then 		return 	end 	 	if entries[j][i]==nil then 		if entries[j][i-1]~=nil or i==1 then 			local rowspan = 0 			local row = i 			repeat 				rowspan=rowspan+1 				row=row+1 			until entries[j][row]~=nil or row>r 			return Cell(tbl,j,i,rowspan,entry_colspan) 		else 			return 		end 	end  	if entries[j][i]['ctype']=='header' then 		if byes[j][entries[j][i]['headerindex']] then 			local emptyround = true 			local row = i+1 			repeat 				if not isBlankEntry(j,row) then 					emptyround = false 				end 				row = row+1 			until (entries[j][row]~=nil and entries[j][row]['ctype']=='header') or row>r 			if emptyround == true then 				return Cell(tbl,j,i,2,entry_colspan) 			end 		end 		 		if hide[j][entries[j][i]['headerindex']] then 			return Cell(tbl,j,i,2,entry_colspan) 		end 		 		if isempty(entries[j][i]['header']) then 			if entries[j][i]['headerindex']==1 then 				if     j==c   then entries[j][i]['header'] = 'ফাইনাল' 				elseif j==c-1 then entries[j][i]['header'] = 'সেমিফাইনাল' 				elseif j==c-2 then entries[j][i]['header'] = 'কোয়ার্টার ফাইনাল' 				else			   entries[j][i]['header'] = 'রাউন্ড '..j 				end 			else 				entries[j][i]['header'] = 'নিম্ন রাউন্ড '..j 			end 		end 		 		return Cell(tbl,j,i,2,entry_colspan,entries[j][i]['header'],'center','1px solid #aaa',nil,entries[j][i]['shade']) 	end 	 	if entries[j][i]['ctype']=='team' then 		if (byes[j][entries[j][i]['headerindex']] and isBlankEntry(j,i)) or hide[j][entries[j][i]['headerindex']] then 			return Cell(tbl,j,i,2,entry_colspan) 		end 		 		local legs = teamLegs(j,i) 		local team_colspan = maxlegs[j]-legs+1 		if aggregate and legs==1 and maxlegs[j]>1 then 			team_colspan=team_colspan+1 		end 		if maxlegs[j]==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 entries[j][i]['ctype']=='text' then 		Cell(tbl,j,i,2,entry_colspan,entries[j][i]['text'],nil,nil,nil,nil,'0.3em') 	end 	 	if entries[j][i]['ctype']=='group' then 		local colspan=0 		for m=j,entries[j][i]['colspan']+j-1 do 			colspan=colspan+maxlegs[m]+2 			if not seeds then colspan=colspan-1 end 			if (aggregate and maxlegs[m]>1) or maxlegs[m]==0 then 				colspan=colspan+1 			end 		end 		colspan = colspan+2*(entries[j][i]['colspan']-1) 		return Cell(tbl,j,i,2,colspan,entries[j][i]['group'],'center') 	end 	 	if entries[j][i]['ctype']=='line' then 		local b={0,0,0,0} 		b[3]=2*pathCell[j-1][i+1][3][3] 		return Cell(tbl,j,i,2,entry_colspan,entries[j][i]['text'],nil,'solid black',b) 	end 	 	if entries[j][i]['ctype']=='line2' then 		local b={0,0,0,0} 		b[1]=2*pathCell[j-1][i][3][1] 		return Cell(tbl,j,i,2,entry_colspan,entries[j][i]['text'],nil,'solid black',b) 	end end  local function isRoundHidden(j,i,headerindex) 	if notempty(entries[j][i]['pheader']) then 		hide[j][entries[j][i]['headerindex']] = false 	end 	local row = i+1 	repeat 		if not isBlankEntry(j,row) then 			hide[j][entries[j][i]['headerindex']] = false 		end 		row = row+1 	until (entries[j][row]~=nil and entries[j][row]['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(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 		if entries[j][i]['headerindex']==1 then  			for k=1,2 do 				table.insert(result,bargs(rname[1][3-k]) or ) 				table.insert(result,bargs(rname[2][3-k]) or ) 			end 		else  			for k=1,2 do 				table.insert(result,bargs(rname[2][3-k]) or ) 			end 		end 	elseif cname=='pheader' then 		if entries[j][i]['headerindex']==1 then  			for k=1,2 do 				table.insert(result,pargs[rname[1][3-k]] or ) 				table.insert(result,pargs[rname[2][3-k]] or ) 			end 		else  			for k=1,2 do 				table.insert(result,pargs[rname[2][3-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(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 indexedParams(j) 	for i=1,r do 		if entries[j][i]~=nil then 			if entries[j][i]['ctype']=='team' then 				local legs = rlegs[j] 				if forceseeds then 					entries[j][i]['seed'] = bargs(masterindex) or 					masterindex = masterindex+1 				end 				entries[j][i]['team'] = bargs(tostring(masterindex)) or  				masterindex = masterindex+1 				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 				for l=1,legs do 					entries[j][i]['score'][l] = bargs(tostring(masterindex)) or 					masterindex = masterindex+1 					entries[j][i]['score']['weight'][l] = 'normal' 				end 				if aggregate and legs>1 then 					entries[j][i]['score']['agg'] = bargs(masterindex) or  					masterindex = masterindex+1 					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]['pheader'] = paramNames('pheader',j,i) 				entries[j][i]['shade'] = paramNames('shade',j,i) 			end 			if entries[j][i]['ctype']=='text' then 				entries[j][i]['text'] = bargs(tostring(masterindex)) or 				masterindex = masterindex+1 			end 			if entries[j][i]['ctype']=='group' then 				entries[j][i]['group'] = bargs(tostring(masterindex)) or  				masterindex = masterindex+1 			end 			if entries[j][i]['ctype'] == 'line' and entries[j][i]['hastext']==true then 				entries[j][i]['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 		rlegs[j] = 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 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]['pheader'] = paramNames('pheader',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']=='group' then 						entries[j][i]['group'] = paramNames('group',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 isBlankEntry(j,i) then 					maxcol = math.max(maxcol,j) 				end 			end 		end 		for i=1,r do 			if entries[j][i]~=nil and entries[j][i]['ctype']=='header' then  				isRoundHidden(j,i)  			end 			if entries[j][i]~=nil and not hide[j][entries[j][i]['headerindex']] then 				if not byes[j][entries[j][i]['headerindex']] or (byes[j][entries[j][i]['headerindex']] and not isBlankEntry(j,i)) then 					byerows = math.max(byerows,i) 				end 			end 		end 	end 	for j=minc,c do 		for k=1,headerindex[j] do 			if byes[j][k] or hide[j][k] then 				r=byerows+1 			end 		end 	end 	if autocol then 		c = maxcol 	end end  local function getHide(j,headerindex) 	hide[j] = {} 	for k=1,headerindex[j] do 		if bargs('RD'..j..toChar(k)..'-hide')=='yes' or bargs('RD'..j..toChar(k)..'-hide')=='y' then 			hide[j][k]=true 		end 	end end  local function getByes(j,headerindex) 	byes[j] = {} 	for k=1,headerindex[j] do 		if bargs('byes')=='yes' or bargs('byes')=='y' then 			byes[j][k]=true else byes[j][k]=false 		end 		if bargs('RD'..j..'-byes')=='yes' or bargs('RD'..j..'-byes')=='y' then 			byes[j][k]=true 		elseif bargs('RD'..j..'-byes')=='no' or bargs('RD'..j..'-byes')=='n' then 			byes[j][k]=false 		end 		if bargs('RD'..j..toChar(k)..'-byes')=='yes' or bargs('RD'..j..toChar(k)..'-byes')=='y' then 			byes[j][k]=true 		elseif bargs('RD'..j..'-byes')=='no' or bargs('RD'..j..'-byes')=='n' then 			byes[j][k]=false 		end 	end end  local function getAltIndices() 	local teamindex=1 	local textindex=1 	local groupindex=1 	for j=minc,c do 		headerindex[j]=0 		for i=1,r do 			if entries[j][i]==nil and i==1 then 				headerindex[j]=headerindex[j]+1 			end 			if entries[j][i]~=nil then 				if entries[j][i]['ctype'] == 'header' then 					entries[j][i]['altindex'] = headerindex[j] 					teamindex=1 					textindex=1 					headerindex[j]=headerindex[j]+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'] == 'group' then 					entries[j][i]['altindex'] = groupindex 					groupindex=groupindex+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[j] 			end 		end 		getByes(j,headerindex) 		getHide(j,headerindex) 	end end  local function noPaths(j,i) 	local result = true 	local cols = 2 	if hascross[j]==true then 		cols = 3 	end 	for k=1,cols do 		for n=1,4 do 			if pathCell[j][i][k][n]~=0 then 				result = false 				return result 			end 		end 	end 	if hascross[j]==true and (crossCell[j][i]['left'][1]==1 or crossCell[j][i]['right'][1]==1) then 		result = false 		return result 	end 	return result end  local function generatePathCell(tbl,j,i,k,color,bg,rowspan) 	if not hascross[j] and k==2 then  		return  	end 	local cell=tbl:tag('td') 	local a=pathCell[j][i] 	if rowspan~=1 then 		cell:attr('rowspan',rowspan) 	end 	if notempty(bg) and k==2 then 		cell:css('background',bg) 			:css('transform','translate(-1px)') 	end 	if a[k][1]~=0 or a[k][2]~=0 or a[k][3]~=0 or a[k][4]~=0 then 		cell:css('border','solid '..color) 			:css('border-width',2*a[k][1]..'px '..2*a[k][2]..'px '..2*a[k][3]..'px '..2*a[k][4]..'px') 	end 	return cell end  local function insertPath(tbl,j,i) 	if skipPath[j][i] then 		return 	end 	 	local colspan = 2 	local rowspan = 1 	local angle = 58.2 	local pathcolor = pathCell[j][i]['color'] or 'black' 	local bg =  	local cross = {,} 	 	if i<r then 		local function repeatedPath(a) 			if a>r-1 or skipPath[j][a] then 				return false 			end 			for k=1,3 do 				for n=1,4 do 					if pathCell[j][i][k][n]~=pathCell[j][a][k][n] then 						return false 					end 				end 			end 			return true 		end 		if repeatedPath(i) then 			local row=i 			repeat 				if row~=i and repeatedPath(row) then 					skipPath[j][row]=true 				end 				rowspan=rowspan+1 				row=row+1 			until row>r or not repeatedPath(row) 			rowspan=rowspan-1 		end 	end 	 	if i>1 and (crossCell[j][i-1]['left'][1]==1 or crossCell[j][i-1]['right'][1]==1) then 		return 	end 	if hascross[j] then 		colspan = 3 		if crossCell[j][i]['left'][1]==1 or crossCell[j][i]['right'][1]==1 then 			rowspan = 2 			if crossCell[j][i]['left'][1]==1 then 				cross[1] = 'linear-gradient(to top right, transparent calc(50% - 1px),'..crossCell[j][i]['left'][2]..' calc(50% - 1px),'..crossCell[j][i]['left'][2]..' calc(50% + 1px), transparent calc(50% + 1px))' 			end 			if crossCell[j][i]['right'][1]==1 then 				cross[2] = 'linear-gradient(to bottom right, transparent calc(50% - 1px),'..crossCell[j][i]['right'][2]..' calc(50% - 1px),'..crossCell[j][i]['right'][2]..' calc(50% + 1px), transparent calc(50% + 1px))' 			end 		end 		if notempty(cross[1]) and notempty(cross[2]) then 			cross[1] = cross[1]..',' 		end 		bg = cross[1]..cross[2] 	end 	for k=1,3 do 		generatePathCell(tbl,j,i,k,pathcolor,bg,rowspan) 	end end  local function parsePaths(j) 	local result={} 	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 array = split(val:gsub("%s+",""):gsub("%)",""):gsub("%(",""),{"-"}) 			for k,_ in pairs(array) do 				array[k] = split(array[k],{","}) 			end 			if notempty(array[2]) then 				for m=1,#array[2] do 					array[3] = {} 					array[2][m] = split(array[2][m],{":"}) 					array[3][m] = array[2][m][2] 					array[2][m] = array[2][m][1] 				end 				for n=1,#array[1] do 					for m=1,#array[2] do 						table.insert(result,{tonumber(array[1][n]),tonumber(array[2][m]),['color']=array[3][m]}) 					end 				end 			end 		end 	return result end  local function isPathHidden(j,i,start,stop) 	local result=false 	if notempty(entries[j][start-1]) and (byes[j][entries[j][start-1]['headerindex']] and isBlankEntry(j,start-1) and isBlankEntry(j,start+1) or hide[j][entries[j][start-1]['headerindex']]) then 		if bargs('show-bye-paths')~='y' and bargs('show-bye-paths')~='yes' then 			result=true 		end 	end 	if notempty(entries[j+1][stop-1]) and (byes[j+1][entries[j+1][stop-1]['headerindex']] and isBlankEntry(j+1,stop-1) and isBlankEntry(j+1,stop+1) or hide[j+1][entries[j+1][stop-1]['headerindex']])then 		if bargs('show-bye-paths')~='y' and bargs('show-bye-paths')~='yes' then 			result=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(entries[j][start-1]) and entries[j][start-1]['headerindex']==1 then 			result=true 		end 	end 	return result end  local function getPaths() 	local paths = {} 	for j=minc,c-1 do 		hascross[j] = false 		if notempty(fargs['col'..j..'-col'..(j+1)..'-cross']) then 			hascross[j] = true 		end 	end 	for j=minc,c-1 do 		local straightpaths = {} 		local outpaths = {} 		local inpaths = {} 		paths[j]=parsePaths(j) 		pathCell[j] = {} 		crossCell[j] = {} 		skipPath[j] = {} 		for i=1,r do 			pathCell[j][i] = {} 			crossCell[j][i] = {['left']={0,'black'},['right']={0,'black'}} 			for k=1,3 do 				pathCell[j][i][k] = {0,0,0,0} 			end 			skipPath[j][i] = false 			end 		local crossloc = split((fargs['col'..j..'-col'..(j+1)..'-cross'] or ):gsub("%s+", ""),{","},true) 		if shift[j]~=0 and notempty(crossloc[1]) then 			for n=1,#crossloc do 				crossloc[n] = crossloc[n]+shift[j] 			end 		end 		for k,v in ipairs(paths[j]) do 			local start = 2*(paths[j][k][1]+shift[j])+(teams_per_match[j]-2) 			local stop = 2*(paths[j][k][2]+shift[j+1])+(teams_per_match[j+1]-2) 			local mid = {} 			local cross = 0 			 			if notempty(crossloc[1]) then 				for n=1,#crossloc do 					mid[n] = 2*crossloc[n]+(teams_per_match[j]-2) 				end 			else 				mid[1]=0 			end 			for n=1,#mid do 				if (start<stop and mid[n]<stop and mid[n]>start) or (start>stop and mid[n]>stop and mid[n]<start) then 					cross = mid[n] 				end 			end 			paths[j][k]['color'] = paths[j][k]['color'] or 'black' 			table.insert(outpaths,{start,paths[j][k]['color']}) 			table.insert(inpaths,{stop,paths[j][k]['color']}) 			if not isPathHidden(j,i,start,stop) then 				if start==stop then 					table.insert(straightpaths,{start,paths[j][k]['color']}) 				elseif start<stop then 					if stop>r then break end 					for i=start+1,stop do 						pathCell[j][i]['color'] = paths[j][k]['color'] 					end 					pathCell[j][start+1][1][1] = 1 					if cross==0 then 						if hascross[j] then 							pathCell[j][start+1][2][1] = 1 							for i=start+1,stop do 								pathCell[j][i][2][2] = 1 							end 						else 							for i=start+1,stop do 								pathCell[j][i][1][2] = 1 							end 						end 					else 						crossCell[j][cross]['left'] = {1,paths[j][k]['color']} 						for i=start+1,cross-1 do pathCell[j][i][1][2] = 1 end 						for i=cross+2,stop do pathCell[j][i][2][2] = 1 end	 					end 					pathCell[j][stop][3][3] = 1 				elseif start>stop then 					if start>r then break end 					for i=stop+1,start do 						pathCell[j][i]['color'] = paths[j][k]['color'] 					end 					pathCell[j][stop+1][3][1] = 1 					if cross==0 then 						if hascross[j] then 							for i=stop+1,start do 								pathCell[j][i][2][2] = 1 							end 							pathCell[j][start][2][3] = 1 						else 							for i=stop+1,start do 								pathCell[j][i][1][2] = 1 							end 						end 					else 						crossCell[j][cross]['right'] = {1,paths[j][k]['color']} 						for i=stop+1,cross-1 do pathCell[j][i][2][2] = 1 end 						for i=cross+2,start do pathCell[j][i][1][2] = 1 end	 					end 					pathCell[j][start][1][3] = 1 				end 			end 		end 		-- Thicken start==stop paths 		for n=1,#straightpaths do 			local i = straightpaths[n][1] 			local color = straightpaths[n][2] 			if i>r then break end 			if pathCell[j][i][1][3]==0 then 				pathCell[j][i]['color'] = color 				pathCell[j][i][1][3] = 1 				pathCell[j][i][2][3] = 1 				pathCell[j][i][3][3] = 1 				if pathCell[j][i+1][1][1]==0 then 					pathCell[j][i+1]['color'] = color 					pathCell[j][i+1][1][1] = 0.5 					pathCell[j][i+1][2][1] = 0.5 					pathCell[j][i+1][3][1] = 0.5 				end 			elseif pathCell[j][i+1][1][1]==0 then 				pathCell[j][i+1]['color'] = color 				pathCell[j][i+1][1][1] = 1 				if hascross[j] then 					pathCell[j][i+1][2][1] = 1 				end 				pathCell[j][i+1][3][1] = 1 			end 		end 		-- Thicken/Thin out paths 		for n=1,#outpaths do 			local i = outpaths[n][1] 			local color = outpaths[n][2] 			if i<r and pathCell[j][i][1][3]==1 and pathCell[j][i+1][1][1]==0 then 				pathCell[j][i+1]['color'] = color 				pathCell[j][i+1][1][1] = 0.5*pathCell[j][i][1][3] 				pathCell[j][i+1][2][1] = 0.5*pathCell[j][i][2][3] 			elseif i<r and pathCell[j][i][1][3]==0 and pathCell[j][i+1][1][1]==1 then 				pathCell[j][i]['color'] = color 				pathCell[j][i][1][3] = pathCell[j][i+1][1][1] 				pathCell[j][i][2][3] = pathCell[j][i+1][2][1] 				pathCell[j][i+1][1][1] = 0.5*pathCell[j][i][1][3] 				pathCell[j][i+1][2][1] = 0.5*pathCell[j][i][2][3] 			end 		end 		-- Thin double-in paths 		for n=1,#inpaths do 			local i = inpaths[n][1] 			local color = inpaths[n][2] 			if i<r and pathCell[j][i][3][3]==1 and pathCell[j][i+1][3][1]==1 and pathCell[j][i]['color']==pathCell[j][i+1]['color'] then 				pathCell[j][i+1][3][1] = 0.5*pathCell[j][i][3][3] 			end 		end 	end 	for j=minc,c-1 do 		for i=1,r-1 do 			local straightpath=false 			if (entries[j+1][i-1]==nil or (byes[j+1][entries[j+1][i-1]['headerindex']]) and isBlankEntry(j+1,i-1)) then 				if (pathCell[j][i][3][3]~=0 and pathCell[j+1][i][1][3]~=0) or (pathCell[j][i+1][3][1]~=0 and pathCell[j+1][i+1][1][1]~=0) then 					if pathCell[j+1][i][1][3]==pathCell[j+1][i][3][3] and pathCell[j+1][i+1][1][1]==pathCell[j+1][i+1][3][1] then 						straightpath=true 					end 					pathCell[j+1][i][1][3]=pathCell[j][i][3][3] 					pathCell[j+1][i+1][1][1]=pathCell[j][i+1][3][1] 					pathCell[j+1][i][2][3]=pathCell[j][i][3][3] 					pathCell[j+1][i+1][2][1]=pathCell[j][i+1][3][1] 					entries[j+1][i-1]={['ctype']='line'} 					entries[j+1][i]={['ctype']='blank'} 					if notempty(entries[j+1][i+1]) then 						entries[j+1][i+1]['ctype'] = 'line2' 					else 						entries[j+1][i+1]={['ctype']='line2'} 					end 					entries[j+1][i+2]={['ctype']='blank'} 					if straightpath then 						pathCell[j+1][i][3][3]=pathCell[j+1][i][1][3] 						pathCell[j+1][i+1][3][1]=pathCell[j+1][i+1][1][1] 					end 				end 			end 		end 	end end  local function getGroups() 	local function check(j,i) 		local result=false 		if entries[j][i] == nil then 			if entries[j][i+1] == nil then  				result=true  			elseif entries[j][i+1]['ctype']=='text' and isBlankEntry(j,i+1) then 				result=true 			end 		elseif entries[j][i]['ctype']=='text' and isBlankEntry(j,i) then 			result=true 		end 		return result 	end 	for j=minc,c-1 do 		if teams_per_match[j]==2 then 			local n=0 			for i=1,r-1 do 				if pathCell[j][i][3][3]==1 or pathCell[j][i+1][3][1]==1 then 					n=n+1 					if check(j,i) then 						local k=minc-1 						repeat 							if entries[j-k][i+1]~=nil and entries[j-k][i+1]['ctype']=='text' and isBlankEntry(j-k,i+1) then 								entries[j-k][i+2]=nil 							end 							entries[j-k][i]={['ctype']='blank'} 							entries[j-k][i+1]={['ctype']='blank'} 							if k>0 and noPaths(j-k,i) then 								skipPath[j-k][i] = true 								skipPath[j-k][i+1] = true 							end 							k=k+1 						until k>j-1 or not check(j-k,i) or not noPaths(j-k,i) 						k=k-1 						entries[j-k][i]={['ctype']='group',['index']=n,['colspan']=k+1} 						entries[j-k][i+1]={['ctype']='blank'} 						entries[j-k][i]['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_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 		maxtpm = math.max(maxtpm,teams_per_match[j]) 	end 	for j=minc,c do 		entries[j] = {} 		shift[j] = tonumber(bargs('RD'..j..'-shift')) or tonumber(bargs('shift')) or 0 		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  	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' 			elseif k==5 then ctype='group' 			end 			for n=1,#colentry[j][k] do 				if shift[j]~=0 and colentry[j][k][n]>1 then 					colentry[j][k][n] = colentry[j][k][n]+shift[j] 				end 				local i=2*colentry[j][k][n]-1 				maxrow = math.max(i+2*teams_per_match[j]-1,maxrow) 				if ctype=='team' then 					if entries[j][i-1]==nil and entries[j][i-2]==nil then 						entries[j][i-2]={['ctype']='text',['index']=n} 						entries[j][i-1]={['ctype']='blank'} 						textindex=n 					end 					entries[j][i]={['ctype']=ctype,['index']=teams_per_match[j]*n-(teams_per_match[j]-1),['position']='top'} 					entries[j][i+1]={['ctype']='blank'} 					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)} 						entries[j][i+2*(m-1)+1]={['ctype']='blank'} 					end 				elseif ctype=='text' then 					entries[j][i]={['ctype']=ctype,['index']=textindex+n} 					entries[j][i+1]={['ctype']='blank'} 				elseif ctype=='line' then 					entries[j][i]={['ctype']=ctype} 					entries[j][i+1]={['ctype']='blank'} 					entries[j][i+2]={['ctype']='line2'} 					entries[j][i+3]={['ctype']='blank'} 				elseif ctype=='group' then 					entries[j][i]={['ctype']=ctype,['index']=n} 					entries[j][i+1]={['ctype']='blank'} 				else 					entries[j][i]={['ctype']=ctype,['index']=n,['position']='top'} 					entries[j][i+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 		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','separate') 			: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 			if hascross[j] then 				tbl:tag('td'):css('width',colspacing+1 ..'px') 				tbl:tag('td'):css('width','10px') 				tbl:tag('td'):css('width',colspacing-1 ..'px') 			else 				tbl:tag('td'):css('width',colspacing+1 ..'px') 				tbl:tag('td'):css('width',colspacing-1 ..'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