Bước tới nội dung

Mô đun:Build bracket

Bách khoa toàn thư mở Wikipedia
local p = {}local entries = {}local pathEntries = {}local pathcolorlocal shift = {}local hascross = {}local teams_per_match = {}local rlegs = {}local maxlegs = {}local autolegslocal byes = {}local hide = {}local matchgroup = {}local autocollocal seedslocal forceseedslocal nowraplocal boldwinnerlocal aggregatelocal paramstylelocal masterindexlocal function isempty(s)	return s==nil or s==''endlocal function notempty(s)	return s~=nil and s~=''endlocal function bargs(s)	return pargs[s] or fargs[s]endlocal function toChar(num)	return string.char(string.byte("a")+num-1)endlocal 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;endlocal 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 resultendlocal 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	endendlocal 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 legsendlocal 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	endendlocal 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 falseendlocal 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 showseedendlocal function blankCell(tbl,j,i,rowspan,colspan,text,align)	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(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 cellendlocal 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',entries[j][i]['shade'])					:wikitext(entries[j][i]['header'])	if colspan~=1 then		cell:attr('colspan',colspan)	end	if nowrap then		cell:css('white-space', 'nowrap')	end	if entries[j][i]['position']=='top' and entries[j][i-2]~=nil and entries[j][i-2]['ctype']~='blank' and entries[j][i-2]['ctype']~='text' and entries[j][i-2]['ctype']~='group' and (not byes[j][entries[j][i]['headerindex']] or not isBlankEntry(j,i-2)) then		cell:css('border-top','2px solid #aaa')	end	return cellendlocal function teamCell(tbl,k,j,i,l,colspan)	local bg = '#F2F2F2'	local cell = tbl:tag('td')					:attr('rowspan',2)					:css('border','1px solid #aaa')	if colspan~=1 and colspan~=nil then		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 entries[j][i]['weight']=='bold') or entries[j][i]['score']['weight'][l]=='bold' then		cell:css('font-weight','bold')	end	if entries[j][i]['position']=='top' and entries[j][i-2]~=nil and entries[j][i-2]['ctype']~='blank' and entries[j][i-2]['ctype']~='text' and entries[j][i-2]['ctype']~='group' and (not byes[j][entries[j][i]['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(entries[j][i][k])	else		cell:wikitext(tostring(entries[j][i][k][l]))	end	return cellendlocal 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 blankCell(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 blankCell(tbl,j,i,2,entry_colspan)			end		end				if hide[j][entries[j][i]['headerindex']] then			return blankCell(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'] = 'Chung kết'				elseif j==c-1 then entries[j][i]['header'] = 'Bán kết'				elseif j==c-2 then entries[j][i]['header'] = 'Tứ kết'				else			   entries[j][i]['header'] = 'Vòng '..j				end			else				entries[j][i]['header'] = 'Lower round '..j			end		end				return headerCell(tbl,j,i,entry_colspan)	end		if entries[j][i]['ctype']=='team' then		if byes[j][entries[j][i]['headerindex']] and isBlankEntry(j,i) then			return blankCell(tbl,j,i,2,entry_colspan)		end		if hide[j][entries[j][i]['headerindex']] then			return blankCell(tbl,j,i,2,entry_colspan)		end				local legs = teamLegs(j,i)		local team_colspan				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		blankCell(tbl,j,i,2,entry_colspan,entries[j][i]['text'])	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)		blankCell(tbl,j,i,2,colspan,entries[j][i]['group'],'center')	end		if entries[j][i]['ctype']=='line' then		tbl:tag('td')			:attr('rowspan',2)			:attr('colspan',entry_colspan)			:css('border-bottom','3px solid black')			:wikitext(entries[j][i]['text'])	endendlocal 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>rendlocal 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 ''endlocal 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	endendlocal 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	endendlocal 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	endendlocal 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	endendlocal 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)	endendlocal function pathCell(tbl,j,i,k,a,b,c,bg,rowspan)	if not hascross[j] and k==2 then return end	if pathcolor==nil then pathcolor='black' end	local cell=tbl:tag('td')	if rowspan~=1 then		cell:attr('rowspan',rowspan)	end	if notempty(bg[k]) then		cell:css('background',bg[k])	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 black')			:css('border-width',a[k][1]..'px '..a[k][2]..'px '..a[k][3]..'px '..a[k][4]..'px')	end	if c[k][2]~=0 then		cell:css('border-right',c[k][2]..'px solid '..pathcolor)	end	if b[k][2]~=0 then		cell:css('box-shadow', '0px '..b[k][2]..'px 0px '..pathcolor)	end	if c[k][4]~=0 then		cell:css('border-left',c[k][4]..'px solid '..pathcolor)	end	return cellendlocal 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 hascross[j] then colspan = 3 end		if pathEntries['black'][j][i]=='blank' then return end		if isempty(pathEntries['black'][j][i]) and isempty(pathEntries['color'][j][i]) then		if (pathEntries['black'][j][i-1]~='blank' and notempty(pathEntries['black'][j][i-1])  and (pathEntries['black'][j][i-1]['cross'][1] == 1 or pathEntries['black'][j][i-1]['cross'][2] == 1)) or (notempty(pathEntries['color'][j][i-1]) and (pathEntries['color'][j][i-1]['cross'][1] == 1 or pathEntries['color'][j][i-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(pathEntries[key][j]) and notempty(pathEntries[key][j][i-1]) and pathEntries[key][j][i-1]~='blank' then			if pathEntries[key][j][i-1]['cross'][1]==1 or pathEntries[key][j][i-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		a[k]={0,0,0,0}		b[k]={0,0}		c[k]={0,0,0,0}		bg[k] = ''		cross[k] = {}		for n=1,2 do			cross[k][n] = ''		end	end		for key,_ in pairs(pathEntries) do		local color		if key=='black' then color='black' else color=pathcolor end		if notempty(pathEntries[key][j]) and notempty(pathEntries[key][j][i]) then			if key=='black' then				a[1][3] = 3*pathEntries['black'][j][i]['out'][1]				a[2][3] = 3*pathEntries['black'][j][i]['mid'][1]				a[3][3] = 3*pathEntries['black'][j][i]['in'][1]				a[1][2] = 2*pathEntries['black'][j][i]['out'][2]				a[3][4] = 2*pathEntries['black'][j][i]['in'][2]			else				if pathEntries['color'][j][i]['out'][3]=='below' then					b[1][2] = 4*pathEntries['color'][j][i]['out'][1] 				end				if pathEntries['color'][j][i]['mid'][3]=='below' then					b[2][2] = 4*pathEntries['color'][j][i]['mid'][1]				end				if pathEntries['color'][j][i]['in'][3]=='below' then					b[3][2] = 4*pathEntries['color'][j][i]['in'][1]				end				c[1][2] = 2*pathEntries['color'][j][i]['out'][2]				c[3][4] = 2*pathEntries['color'][j][i]['in'][2]			end			if pathEntries[key][j][i]['cross'][1]==1 or pathEntries[key][j][i]['cross'][2]==1 then				rowspan = 2				if pathEntries[key][j][i]['cross'][1]==1 then					cross[1][1] = createCross('65.5deg',color,100)					cross[2][1] = createCross('to top right',color,50)					cross[3][1] = createCross('245.5deg',color,100)				end				if pathEntries[key][j][i]['cross'][2]==1 then					cross[1][2] = createCross('114.4deg',color,100)					cross[2][2] = createCross('to bottom right',color,50)					cross[3][2] = createCross('294.4deg',color,100)				end			end		end	end	if notempty(pathEntries['color'][j]) and notempty(pathEntries['color'][j][i-1]) then		if pathEntries['color'][j][i]['out'][3]=='above' then			b[1][2] = -4		end		if pathEntries['color'][j][i]['mid'][3]=='above' then			b[2][2] = -4		end		if pathEntries['color'][j][i]['in'][3]=='above' then			b[3][2] = -4		end	end	if notempty(cross[2][1]) and notempty(cross[2][2]) then		for k=1,3 do cross[k][1] = cross[k][1]..',' end	end	for k=1,3 do		bg[k] = cross[k][1]..cross[k][2]	end		for k=1,3 do		pathCell(tbl,j,i,k,a,b,c,bg,rowspan)	endendlocal 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'][j][i] = {['out']={0,0,nil},['mid']={0,0,nil},['in']={0,0,nil},['cross']={0,0,nil}}			pathEntries['color'][j][i] = {['out']={0,0,nil},['mid']={0,0,nil},['in']={0,0,nil},['cross']={0,0,nil}}		end		paths[j] = {}		hascross[j] = 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				result[k] = split(result[k],{","})			end			if notempty(result[2]) then				for m=1,#result[2] do					result[3] = {}					result[2][m] = split(result[2][m],{":"})					result[3][m] = result[2][m][2]					result[2][m] = result[2][m][1]				end				for n=1,#result[1] do					for m=1,#result[2] do						table.insert(paths[j],{tonumber(result[1][n]),tonumber(result[2][m]),['color']=result[3][m]})					end				end			end		end		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 color			local hidepath = false			if shift[j]~=0 then				paths[j][k][1] = paths[j][k][1]+shift[j]			end			if shift[j+1]~=0 then				paths[j][k][2] = paths[j][k][2]+shift[j+1]			end			local start = 2*paths[j][k][1]+(teams_per_match[j]-2)			local mid = {}			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			local stop = 2*paths[j][k][2]+(teams_per_match[j+1]-2)			if paths[j][k]['color']~=nil then 				pathcolor = paths[j][k]['color']				color = 'color'			else				color = 'black'			end			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					hidepath=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					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(entries[j][start-1]) and entries[j][start-1]['headerindex']==1 then					hidepath=true				end			end						local cross = 0			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					hascross[j]=true					cross = mid[n]				end			end			if not hidepath then				if start==stop then					if start>r then break end					start = math.min(start,r)					pathEntries[color][j][start]['out'][1] = 1					pathEntries[color][j][start]['in'][1] = 1					if cross==0 then						pathEntries[color][j][start]['mid'][1] = 1					end				elseif start<stop then					if stop>r then break end					pathEntries[color][j][start]['out'][1] = 1					pathEntries[color][j][stop]['in'][1] = 1					pathEntries[color][j][stop]['in'][2] = 1					if color~='black' then						pathEntries[color][j][start]['out'][3] = 'below'						pathEntries[color][j][stop+1]['in'][3] = 'above'					end					if cross==0 then						pathEntries[color][j][start]['mid'][1] = 1						pathEntries[color][j][start]['mid'][3] = 'below'						for i=start+1,stop-1 do pathEntries[color][j][i]['in'][2] = 1 end					else						pathEntries[color][j][cross]['cross'][1] = 1						for i=start+1,cross-1 do pathEntries[color][j][i]['out'][2] = 1 end						for i=cross+2,stop-1 do pathEntries[color][j][i]['in'][2] = 1 end					end				elseif start>stop then					if start>r then break end					pathEntries[color][j][stop]['in'][1] = 1					if cross==0 then						for i=stop+1,start-1 do pathEntries[color][j][i]['in'][2] = 1 end						pathEntries[color][j][start]['out'][1] = 1						pathEntries[color][j][start]['mid'][1] = 1						pathEntries[color][j][start]['in'][2] = 1						if color~='black' then							pathEntries[color][j][start+1]['out'][3] = 'above'							pathEntries[color][j][start+1]['mid'][3] = 'above'							pathEntries[color][j][stop]['in'][3] = 'below'						end					else						pathEntries[color][j][cross]['cross'][2] = 1						for i=stop+1,cross-1 do pathEntries[color][j][i]['in'][2] = 1 end						for i=cross+2,start-1 do pathEntries[color][j][i]['out'][2] = 1 end						pathEntries[color][j][start]['out'][1] = 1						pathEntries[color][j][start]['out'][2] = 1						if color~='black' then							pathEntries[color][j][start+1]['out'][3] = 'above'							pathEntries[color][j][stop]['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(pathEntries[key][j][i]) do					if v[1]~=0 or v[2]~=0 or v[3]~=nil then						empty = false					end				end				if empty then pathEntries[key][j][i] = 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 (entries[j+1][i-1]==nil or (byes[j+1][entries[j+1][i-1]['headerindex']]) and isBlankEntry(j+1,i-1)) and notempty(pathEntries['black'][j][i]) and notempty(pathEntries['black'][j+1][i]) then					if pathEntries['black'][j][i]['in'][1]==1 and pathEntries['black'][j+1][i]['out'][1]==1 then						entries[j+1][i-1]={['ctype']='line'}						entries[j+1][i]={['ctype']='blank'}					end				end			end		end	endendlocal 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 do				if (notempty(pathEntries['black'][j][i]) and pathEntries['black'][j][i]['in'][1] == 1) or (notempty(pathEntries['color'][j][i]) and pathEntries['color'][j][i]['in'][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 isempty(pathEntries['black'][j-k][i]) and isempty(pathEntries['color'][j-k][i]) then								pathEntries['black'][j-k][i] = 'blank'								pathEntries['black'][j-k][i+1] = 'blank'							end							k=k+1						until k>j-1 or not check(j-k,i) or notempty(pathEntries['black'][j-k][i]) or notempty(pathEntries['color'][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	endendlocal 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'}				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	endendfunction 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','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			if hascross[j] 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)endreturn p