לדלג לתוכן

יחידה:Team bracket

מתוך ויקיפדיה, האנציקלופדיה החופשית

יחידה זו מייצרת ייצוג חזותי גנרי של טורניר הנערך בשיטת גביע.

{{#invoke: Team bracket | main
| rounds      =
| RD1-group1  =

| RD1         =
| RD1-seed1   =
| RD1-team1   =
| RD1-score1  =
 ...
}}
פרמטר תיאור
rounds מספר הסיבובים. לדוגמא, 2 עבור טורניר חצי גמר, 3 עבור רבע גמר, וכן הלאה.
maxround סיבוב מקסימלי לתצוגה. אם מספר זה קטן מהפרמטר rounds, אזי הסיבובים האחרונים (השמאליים ביותר) יושמטו. אם מספר זה גדול מהפרמטר rounds תוחזר שגיאה.
seed-width רוחב תאי הדירוג בפיקסלים. ניתן להכניס כל פרמטר בפורמט CSS.
team-width רוחב תאי הקבוצות בפיקסלים. ניתן להכניס כל פרמטר בפורמט CSS.
score-width רוחב תאי הניקוד בפיקסלים. ניתן להכניס כל פרמטר בפורמט CSS.
compact הגדר yes עבור עץ קומפקטי (גובה העץ מצטמצם והאפשרות של בתים מבוטלת).
seeds הגדר no על מנת להסתיר את תאי הדירוג. הגדר yes על מנת להציג אותם.
sets או legs מספר המפגשים בכל סיבוב. אם ברצונך להשתמש במספר שונה עבור כל סיבוב, הפרד בין המספרים עם "/" (מימין לשמאל).
nowrap הגדר yes על מנת למנוע מהשורות לגלוש.
byes הכנס 2, 1 וכן הלאה על מנת לציין את מספר הסיבובים שלא שוחקו (כלומר הקבוצה העפילה אוטומטית ללא משחק).
boldwinner הגדר high על מנת להדגיש באופן אוטומטי את הקבוצה בעלת הניקוד הגבוה ביותר, הגדר low על מנת להדגיש באופן אוטומטי את הקבוצה בעלת הניקוד הנמוך ביותר.
hideomittedscores הכנס 1 על מנת להסתיר את כל תאי הניקוד הריקים. הכנס 2 אם ברצונך להציג את תאי הניקוד הראשונים ולהסתיר את כל השאר במקרה שהפרמטר legs גדול מ־1).
sepwidth הכנס 1 או 2 על מנת לעקוף את רוחב ברירת המחדל.
headings הגדר no על מנת להסתיר את כותרות העמודות.
autoseeds הגדר yes או y על מנת להוסיף דירוג אוטומטי בסיבוב הראשון (הדירוג האוטומטי הוא הדירוג המקובל בטורנירים רבים: המדורג ראשון מול המדורג אחרון, המדורג שני מול השני מהסוף, וכן הלאה).
RDn שם הסיבוב ה־n־י. ברירת המחדל היא "גמר", "חצי הגמר", "רבע הגמר", שמינית הגמר", ומכאן ואילך: "סיבוב ה־x", כאשר x הוא מספר הקבוצות בשלב (x=2^n).
RDnb המשחק על המקום השלישי אינו מופיע באופן אוטומטי ויש להוסיפו באמצעות פרמטר זה, כאשר n הוא מספר הסיבובים (למשל: 3 עבור תבנית רבע גמר), ובפרמטר עצמו יש להכניס את הכותרת המבוקשת (למשל: "מקום שלישי", "מדליית ארד").
RDn-groupm שם הבית ה־m־י בסיבוב ה־n־י. עבור כל סיבוב, כל ארבע קבוצות (שני משחקים) מסווגת כ"בית".
RDn-seedm הדירוג של הקבוצה ה־m־ית בסיבוב ה־n־י. אם הפרמטר מושמט התא מוסתר.
RDn-teamm שם הקבוצה ה־m־ית בסיבוב ה־n־י.
RDn-scorem הניקוד של הקבוצה ה־m־ית בסיבוב ה־n־י.
RDn-scorem-s הניקוד ה־s־י של הקבוצה ה־m־ית בסיבוב ה־n־י. בשימוש אם הפרמטר legs גדול מ־1.
RDn-scorem-agg הניקוד בתיבת הניקוד האחרונה של הקבוצה ה־m־ית בסיבוב ה־n־י. ניתן כמובן להשתמש גם במספור התיבה בצורה RDn-scorem-s.
RD1-omit השמט קבוצות מהסיבוב הראשון, הפרד בין המספרים עם "/". למשל, אם ברצונך להשמיט כליל את המשחק הראשון ואת הקבוצה השנייה מהמשחק השנייה שים בפרמטר זה את הערך 1 / 2 / 4.
RD-shade צבע הרקע של כותרות הסיבובים.
RDn-shadem-s צבע הרקע של תיבת הניקוד ה־s־ית של הקבוצה ה־m־ית בסיבוב ה־n־י.
RDn-RDn+1-path הכנס 0 על מנת למחוק את הקווים בין הסיבוב ה־n־י לבין הסיבוב שלאחריו.
float הגדר right או center או left על מנת להצמיד את העץ לימין, למרכז או לשמאל בהתאמה.
clear אם ברצונך למנוע מהיחידה "לנקות" את צד שמאל/ימין של העמוד לפני היישור שמאלה/ימינה, הגדר פרמטר זה no. עובד רק עם |float=left או |float=right.
aggregate הכנס sets או legs אם ברצונך לסכום את מספר הניצחונות ולהציג אותם בתיבת ניקוד נוספת (לדוגמה: 3 סיבובים שבכולם ניצחה קבוצה 1 בתוצאה 2–1 יסוכמו כ־3–0). הכנס score אם ברצונך לסכום את כל תיבות הניקוד ולהציג אותם בתיבת ניקוד נוספת (לדוגמה: 3 סיבובים שבכולם ניצחה קבוצה 1 בתוצאה 2–1 יסוכמו כ־6–3). הכנס yes או y על מנת לאפשר תיבת ניקוד נוספת (מעבר למה שהוגדר בפרמטר legs) עם הסיומת -agg, אך ללא חישוב אוטומטי. פרמטר זה עובד רק כשמספר הסיבובים גדול מ־1. ניתן "לדרוס" באופן ידני כל ערך מחושב עם פרמטר ניקוד נוסף עם הסיומת -agg.

--
-- This module implements many bracket templates
--

local p = {}
local args = {}
local rows = {}
local mask = {}
local rounds
local maxround
local legs = {}
local compact
local byes
local hideSeeds
local showSeeds
local hideHeadings
local showThird
local offsetThird
local compactFinal
local sepwidth
local aggsep
local aggregate
local boldwinner
local hideomittedscores
local RD1seedmap = {}
local tcats = ''

local function isnotblank(s)
	return s and s ~= ''
end

local function isblank(s)
	return (not s) or (s == '')
end

local function sumScores(s1, s2)
	s1 = mw.ustring.gsub(s1 or '', '^[\'%s]*([%d%.]*).-$', '%1')
	s2 = mw.ustring.gsub(s2 or '', '^[\'%s]*([%d%.]*).-$', '%1')
	if s1 ~= '' and s2 ~= '' then
		return tonumber(s1) + tonumber(s2)
	end
	return s1
end

local function scoreCompare(s1,s2,highwin)
	local ps1 = mw.ustring.gsub(s1 or '', '^[\'%s]*([%d%.]*)[\'%s]*%([\'%s]*([%d%.]*)[\'%s]*%).-$', '%2')
	local ps2 = mw.ustring.gsub(s2 or '', '^[\'%s]*([%d%.]*)[\'%s]*%([\'%s]*([%d%.]*)[\'%s]*%).-$', '%2')
	s1 = mw.ustring.gsub(s1 or '', '^[\'%s]*([%d%.]*).-$', '%1')
	s2 = mw.ustring.gsub(s2 or '', '^[\'%s]*([%d%.]*).-$', '%1')
	
	if s1 ~= '' and s2 ~= '' then
		s1 = tonumber(s1)
		s2 = tonumber(s2)
		if s1 and s2 then
			if (s1 == s2) then
				ps1 = tonumber(ps1)
				ps2 = tonumber(ps2)
				if ps1 and ps2 then
					s1 = ps1
					s2 = ps2
				end
			end
			if highwin then
				return ((s1 > s2) and 1) or ((s1 < s2) and 2) or 0
			else
				return ((s2 > s1) and 1) or ((s2 < s1) and 2) or 0
			end
		end
	end
	return 0
end

local function parseArgs(frame)
	local fargs = frame.args
	local pargs = frame:getParent().args;

	local r = tonumber(fargs.rounds or '') or tonumber(pargs.rounds or '') or 2
	local teams = math.pow(2, r)
	local rdstr = 'RD' .. tostring(r)
	local rdbstr = 'RD' .. tostring(r) .. 'b'
	local rdp1str = 'RD' .. tostring(r+1)

	for i=1,2 do
		local targs = (i == 1) and pargs or fargs
		for k,v in pairs(targs) do
			if type(k) == 'string' then
				if k:find('^[R3][Dr][d1-9]b?%-[a-z][a-z]*00*') then
					k = mw.ustring.gsub(k, '^([R3][Dr][d1-9]b?%-[a-z][a-z]*)00*', '%1')
					if (teams < 10) then 
						tcats = tcats .. '[[Category:Pages using a team bracket with deprecated syntax|P]]'
					end
				end
				if k:find('^' .. rdp1str) then
					k = mw.ustring.gsub(k, '^' .. rdp1str, '3rd')
					tcats = tcats .. '[[Category:Pages using a team bracket with deprecated syntax|3]]'
				elseif k:find('^' .. rdbstr) then
					k = mw.ustring.gsub(k, '^' .. rdbstr, '3rd')
				elseif k:find('^' .. rdstr .. '%-[a-z][a-z]*3') then
					k = mw.ustring.gsub(k, '^' .. rdstr .. '(%-[a-z][a-z]*)3', '3rd%11')
				elseif k:find('^' .. rdstr .. '%-[a-z][a-z]*4') then
					k = mw.ustring.gsub(k, '^' .. rdstr .. '(%-[a-z][a-z]*)4', '3rd%12')
				elseif  k:find('^Consol') then
					k = mw.ustring.gsub(k, '^Consol', '3rd')
					tcats = tcats .. '[[Category:Pages using a team bracket with deprecated syntax|3]]'
				elseif k:find('^group[0-9]') then
					tcats = tcats .. '[[Category:Pages using a team bracket with deprecated syntax|G]]'
				end
			end
			args[k] = v
		end
	end

	if (args['byes'] and (args['byes'] == 'yes' or args['byes'] == 'y')) then
		tcats = tcats .. '[[Category:Pages using a team bracket with deprecated syntax|B]]'
	end
end

local function parseSeedmap(s)
	s = mw.text.split((s or '0') .. '/', '[%s]*/[%s]*')
	local teams = math.pow(2, rounds)
	for r=1,teams do
		RD1seedmap[r] = 1
	end
	for r=1,#s do
		if tonumber(s[r] or 'x') then
			RD1seedmap[tonumber(s[r])] = 0
		end
	end
	local c = 1
	for r=1,teams do
		if RD1seedmap[r] > 0 then
			RD1seedmap[r] = c
			c = c + 1
		end
	end
end

local function parseLegs(s)
	s = mw.text.split((s or '1') .. '/', '[%s]*/[%s]*')
	if aggregate == 'n' or aggregate == 'no' or aggregate == '0' then
		aggregate = ''
	end
	local n = showThird and (rounds + 1) or (rounds)
	local lastlegs = nil
	for r=1,n do
		if s[r] ~= nil and s[r] ~= '' and tonumber(s[r]) then
			legs[r] = tonumber(s[r])
		elseif lastlegs then
			legs[r] = lastlegs
		else
			legs[r] = 1
		end
		lastlegs = legs[r]
		if legs[r] > 1 and aggregate ~= '' then
			legs[r] = legs[r] + 1
		end
	end
end

local function getSeeds()
	local seeds = {1, 2}
	local count = 2
	local before = false
	for r = 2, rounds do
		local max = math.pow(2, r)
		for i = 1, count do
			local pos = i * 2
			if before then pos = pos - 1 end
			table.insert(seeds, pos, max - seeds[i * 2 - 1] + 1)
			before = not before
		end
		count = count * 2
	end
	return seeds
end

local function addTableRow(tbl)
	return tbl:tag('tr')
end

local function addBlank(i, css, rowspan, colspan)
	local row = rows[i]
	rowspan = rowspan or 1
	local jmax = i + rowspan - 1
	for j = i, jmax do
		if rows[j] == nil then
			rowspan = rowspan - 1
		elseif row == nil then
			row = rows[j]
		end
	end
	local cell = row and row:tag('td') or mw.html.create('td')
	if rowspan and rowspan > 1 then
		cell:attr('rowspan', rowspan)
	end
	if colspan and colspan > 1 then
		cell:attr('colspan', colspan)
	end
	if css then
		cell:css(css)
	end
	return cell
end

local function addBorders(cell, topcell, seedorteam, extrasep)
	if sepwidth > 1 then topcell = true end
	if seedorteam then
		cell:css('border', '1px solid #aaa')
			:css('border-top-width', topcell and '1px' or '0')
	else
		cell:css('border-color', '#aaa')
			:css('border-style', 'solid')
			:css('border-top-width', topcell and '1px' or '0')
			:css('border-right-width', (extrasep and '1px') or ((sepwidth > 1) and '1px') or '0')
			:css('border-left-width', '1px')
			:css('border-bottom-width', '1px')
	end
end

local function addHeading(row, r, text, pad)
	pad = (pad == nil or pad < 0) and 0 or pad
	row:tag('td')
		:attr('colspan', tonumber(hideSeeds and '1' or '2') + legs[r] + pad)
		:css('text-align', 'center')
		:css('border', '1px solid #aaa')
		:css('background-color', args['RD-shade'] or '#f2f2f2')
		:wikitext(text)
		:newline()
end

local function getWidth(param, default)
	local arg = args[param .. '-width']
	if isblank(arg) then
		arg = default
	end
	if tonumber(arg) ~= nil then
		arg = arg .. 'px'
	end
	return arg
end

local function getTeamArgName(round, type, team)
	if round > rounds then
		return mw.ustring.format('3rd-%s%d', type, team)
	else
		if (round == 1) then
			team = RD1seedmap[team]
			if team == 0 then
				return 'NIL'
			end
		end
		return mw.ustring.format('RD%d-%s%d', round, type, team)
	end
end

local function getShadeArg(round, team, s)
	local argname = getTeamArgName(round, 'shade', team) .. (s and ('-' .. s) or '')
	local value = args[argname]
	if isblank(value) then
		return '#f9f9f9'
	end
	return value
end

local function getScoreArg(round, team, s)
	local argname = getTeamArgName(round, 'score', team) .. (s and ('-' .. s) or '')
	local value = args[argname]
	return value
end

local function getTeamArg(round, type, team)
	local argname = getTeamArgName(round, type, team)
	local value = args[argname]
	if isblank(value) then
		return ''
	end
	if mw.ustring.find(value, '[%s]*<[%s/]*[Bb][Rr][%s/]*>[%s ]*&[Nn][Bb][Ss][Pp];[%s]*') then
		tcats = tcats .. '[[Category:Pages using a team bracket with nbsp]]'
	end
	return mw.ustring.gsub(value, '[%s]*<[%s/]*[Bb][Rr][%s/]*>[%s ]*&[Nn][Bb][Ss][Pp];[%s]*', '<br/>')
end

local function isHidden(r, team)
	return isblank( getTeamArg(r, 'team', team) )
end

local function getRoundName(round)
	local name = args['RD' .. round]
	if isnotblank(name) then
		return name
	end
	local roundFromLast = rounds - round + 1
	if roundFromLast == 1 then
		return "גמר"
	elseif roundFromLast == 2 then
		return "חצי הגמר"
	elseif roundFromLast == 3 then
		return "רבע הגמר"
	elseif roundFromLast == 4 then
		return "שמינית הגמר"
	else
		return "סיבוב ה־" .. math.pow(2, roundFromLast)
	end
end

local function addPath(index, round, top, left, w)
	local prop = top and 'border-bottom-width' or 'border-top-width'
	if left and round == 1 then
		if compact then
			addBlank(index)
		else
			addBlank(index, {['height'] = '7px'})
			addBlank(index+1, {['height'] = '7px'})
		end
		return nil
	else
		local cell = addBlank(index, 
			{['border-width'] = '0',
			['border-style'] = 'solid',
			['border-color'] = 'black'}, (not compact) and 2 or 1)
		if left or round < maxround and not left then
			cell:css(prop, w or '2px')
		end
		return cell
	end
end

local function renderTeam(row, round, team, top, otherbye, pad)
	pad = (pad == nil or pad < 0) and 0 or pad
	tcs = pad + 1
	local seedCell
	local seedArg = getTeamArg(round, 'seed', team)
	-- seed value for the paired team
	local otherteam = team % 2 == 0 and team-1 or team+1
	local pairSeedArg = otherbye and '' 
		or getTeamArg(round, 'seed', otherteam)
	-- show seed if seed is defined for either or both
	local showSeed = showSeeds
		or isnotblank(seedArg)
		or isnotblank(pairSeedArg)
	if showSeed and (not hideSeeds) then
		seedCell = row:tag('td')
			:css('text-align', 'center')
			:css('background-color', '#f2f2f2')
			:attr('rowspan', (not compact) and '2' or nil)
			:wikitext(seedArg)
			:newline()
		addBorders(seedCell, top or otherbye, true, false)
	end

	local teamArg = getTeamArg(round, 'team', team)
	if isblank(teamArg) then
		teamArg = '&nbsp;'
	end
	
	if not showSeed and (not hideSeeds) then
		tcs = tcs + 1
	end

	local teamCell = row:tag('td')
		:css('background-color', '#f9f9f9')
		:css('padding', '0 2px')
		:attr('rowspan', (not compact) and '2' or nil)
		:attr('colspan', (tcs > 1) and tcs or nil)
		:wikitext(teamArg)
		:newline()
	addBorders(teamCell, top or otherbye, true, false)

	local scoreCells = {}
	local wins, otherwins = 0, 0
	local sumscore, othersumscore = 0, 0
	local teamcolspan = tcs
	local hassum = false
	for s = 1, legs[round] do
		local fw = nil
		local agg = legs[round] > 1 and s == legs[round] and true or false
		local score1 = (agg and getScoreArg(round, team, 'agg') or nil) or 
			getScoreArg(round, team, s) or ((legs[round] == 1) and getScoreArg(round, team)) or nil
		local score2 = (agg and getScoreArg(round, otherteam, 'agg') or nil) or 
			getScoreArg(round, otherteam, s) or ((legs[round] == 1) and getScoreArg(round, otherteam)) or nil
		local showscore = true
		if agg and aggregate ~= '' and score1 == nil and hassum then
			score1 = (aggregate == 'score')	and sumscore 
				or ((aggregate == 'legs' or aggregate == 'sets') and wins)
				or nil
		end
		if agg and aggregate ~= '' and score2 == nil and hassum then
			score2 = (aggregate == 'score')	and othersumscore
				or ((aggregate == 'legs' or aggregate == 'sets') and otherwins)
				or nil
		end
		if (score1 == nil or score1 == '') and (score2 == nil or score2 == '') then
			if hideomittedscores > 0 and s >= hideomittedscores then
				teamcolspan = teamcolspan + 1
				showscore = false
			end
		else
			hassum = true
		end
		if showscore then
			local winner = scoreCompare(score1, score2, boldwinner ~= 'low')
			sumscore = sumScores(sumscore, score1)
			othersumscore = sumScores(othersumscore, score2)
			if winner == 1 then
				if boldwinner ~= '' or (agg and (aggregate == 'score' or aggregate == 'legs' or aggregate == 'sets')) then 
					if agg and (aggregate == 'legs' or aggregate == 'sets') and (wins <= (legs[round] - 1)/2) then
					else
						fw = 'bold'
					end
				end
				if not (agg and (aggregate == 'score' or aggregate == 'legs' or aggregate == 'sets')) then wins = wins + 1 end
			elseif winner == 2 then
				if not (agg and (aggregate == 'score' or aggregate == 'legs' or aggregate == 'sets')) then otherwins = otherwins + 1 end
			end
			scoreCells[s] = row:tag('td')
				:css('text-align', 'center')
				:css('background-color', getShadeArg(round, team, s))
				:css('font-weight', fw)
				:attr('rowspan', (not compact) and '2' or nil)
				:wikitext(score1)
				:newline()
			addBorders(scoreCells[s], top or otherbye, false, s > 1 and s == legs[round] and aggsep or nil)
		end
	end
	if teamcolspan > 1 then
		teamCell:attr('colspan', teamcolspan)
	end
	if boldwinner ~= '' and wins > otherwins then
		if (aggregate == 'legs' or aggregate == 'sets') and (wins <= (legs[round] - 1)/2) then
		else
			if seedCell then
				seedCell:css('font-weight', 'bold')
			end
			if teamCell then
				teamCell:css('font-weight', 'bold')
			end
		end
	end
end

local function renderRound(count, r)
	local teams = math.pow(2, rounds - r + 1)
	local step = count / teams
	local topTeam = true -- is top row in match-up
	local topPair = true -- is top match-up in pair of match-ups
	local team = 1
	local group = 1

	for i = 1, count, step do
		local offset, height, blank

		local hideteam = false
		local otherhideteam = false
		local hideleftpath = false
		local hiderightpath = false
		if r <= byes then
			hideteam = isHidden(r, team)
			otherhideteam = isHidden(r, team % 2 == 0 and team-1 or team+1)
		end
		if (r == 1) and (RD1seedmap[team] <= 0) then
				hideteam = true
		end
		if (r > 1) and (r <= (byes + 1)) then
			hideleftpath = isHidden(r-1, 2*team-1) and isHidden(r-1, 2*team)
		end
		if (r == 2) and (RD1seedmap[2*team-1] <= 0 and RD1seedmap[2*team] <= 0) then
			hideleftpath = true
		end
		if compactFinal and (r == rounds) then
			hideleftpath = true
		end
		if (tonumber(args['RD' .. (r-1) .. '-RD' .. (r) .. '-path']) or 2) == 0 then
			hideleftpath = true
		end
		if (tonumber(args['RD' .. (r) .. '-RD' .. (r + 1) .. '-path']) or 2) == 0 then
			hiderightpath = true
		end

		-- empty space above or below
		if compact then
			offset = topTeam and i or i + 1
			height = step - 1
		-- leave room for groups for teams other than first and last
		elseif team == 1 or team == teams then
			offset = topTeam and i or i + 2
			height = step - 2
		else
			offset = topTeam and i + 1 or i + 2
			height = step - 3
		end
		if showThird and (r == rounds) and (not topTeam) then
			height = offset - offsetThird
		end
		if compactFinal and (r == (maxround - 1)) then
			if team == 2 then
				height = height - 3
			end
			if team == 3 then
				height = height - 1
				offset = offset + 1
				addBlank(offset-3, nil, 1, tonumber(hideSeeds and '2' or '3') + legs[r])
				addBlank(offset-4)
				addHeading(rows[offset-4], r + 1, getRoundName(r+1), legs[r] - legs[r+1])
				local b = addBlank(offset-4, {
					['border-color'] = 'black',
					['border-style']= 'solid',
					['border-width']= '0'}, 2)
				b:css('border-left-width', '2px')
			end
		end
		if height > 0 then
			local pad = 0
			local betweenTeams = (topTeam == false and topPair == true) or (topTeam == true and topPair == false)
			if compactFinal and (r == maxround - 1) then
				betweenTeams = false
			end
			if compactFinal and (r == maxround - 1) and legs[r+1] > legs[r] then
				pad = legs[r+1] - legs[r]
			end
			if compact and betweenTeams then
				addBlank(offset, nil, height, 1)
				if topPair then
					blank = addBlank(offset, nil, 2*height, tonumber(hideSeeds and '1' or '2') + legs[r] + pad)
					if args['RD' .. r .. '-group' .. group] then
						blank:wikitext(args['RD' .. r .. '-group' .. group])
						blank:css('text-align', 'center')
					end
					group = group + 1
				end
				blank = addBlank(offset, 
				{['border-width'] = '0',
				['border-style'] = 'solid',
				['border-color'] = 'black'},
				height, 1)
			else
				blank = addBlank(offset, 
				{['border-width'] = '0',
				['border-style'] = 'solid',
				['border-color'] = 'black'},
				height, tonumber(hideSeeds and '3' or '4') + legs[r] + pad)
			end
		end
		-- add bracket
		local j = topTeam and i + step - (compact and 1 or 2) or i
		-- add left path
		addPath(j, r, topTeam, true, hideleftpath and '0' or '2px')
		if hideteam then
			addBlank(j, nil, (not compact) and 2 or nil, tonumber(hideSeeds and '1' or '2') + legs[r])
		elseif rows[j] then
			if compactFinal and (r == maxround) then
				renderTeam(rows[j], r, team, topTeam, otherhideteam, legs[r-1] - legs[r])
			elseif compactFinal and (r == maxround - 1) then
				renderTeam(rows[j], r, team, topTeam, otherhideteam, legs[r+1] - legs[r])
			else
				renderTeam(rows[j], r, team, topTeam, otherhideteam)
			end
		end
		local rightPath = addPath(j, r, topTeam, false, (hiderightpath or hideteam) and '0' or '2px')
		if not topTeam then topPair = not topPair end
		if not topPair and r < maxround and (not (hiderightpath or hideteam)) then
			if blank then blank:css('border-left-width', '2px') end
			rightPath:css('border-left-width', '2px')
		end
		if compactFinal and (r == maxround) then
			local prop = (team == 1) and 'border-bottom-width' or 'border-top-width'
			rightPath:css('border-left-width', '2px')
				:css(prop, '2px')
		end
		team = team + 1
		topTeam = not topTeam
	end
end

local function renderGroups(count, round)
	local roundFromLast = rounds - round + 1
	local groups = math.pow(2, roundFromLast - 2)
	local step = count / groups
	local group = 1
	local offset = 0
	local team = 0
	local wdef = (tonumber(args['RD' .. (round) .. '-RD' .. (round + 1) .. '-path']) or 2) .. 'px'
	local w = wdef

	for r = 1,round do
		offset = offset + (hideSeeds and 3 or 4) + legs[r]
	end
	for i = step / 2, count, step do
		local name = 'RD' .. round .. '-group' .. group
		addBlank(i, {['height'] = '7px'})
		addBlank(i+1, {['height'] = '7px'})
		addBlank(i, {['text-align'] = 'center'}, 2, offset-2)
			:wikitext(args[name])
			:newline()
		if (round <= byes) then
			team = i/(step/2)
			w = isHidden(round, 2*team-1) and isHidden(round, 2*team) and '0' or wdef
		end
		if (round < maxround) then
			addBlank(i, {
				['border-color'] = 'black',
				['border-style'] = 'solid', 
				['border-width'] = '0 0 0 ' .. w})
		else
			addBlank(i)
		end
		if (round <= byes) then
			team = team + 1
			w = isHidden(round, 2*team-1) and isHidden(round, 2*team) and '0' or wdef
		end
		if (round < maxround) then
			addBlank(i+1, {
				['border-color'] = 'black',
				['border-style'] = 'solid', 
				['border-width'] = '0 0 0 ' .. w})
		else
			addBlank(i+1)
		end
		group = group + 1
	end
end

local function getThirdOffset()
	local offset = (compact and 1 or 3) * (math.pow(2, rounds) - math.pow(2, rounds-3)) - (compact and 2 or 4)
	if rounds < 4 then
		offset = compact and 8 or 17
		if rounds < 3 then
			offset = compact and 6 or 10
			if rounds < 2 then
				offset = compact and 4 or 7
			end
		end
	end
	return offset
end

local function renderThird(count)
	local k = offsetThird
	local row = rows[k]
	local blank
	if rounds < 2 then
		blank = addBlank(k-1, {['height'] = '7px'})
	end
	blank = addBlank(k, rounds < 2 and {['height'] = '7px'} or nil)
	addHeading(row, rounds + 1, args['3rd'] or 'מקום שלישי')
	if rounds < 2 then
		for i = 1,(compact and 1 or 2) do
			blank = addBlank(k+i, {['height'] = '7px'})
		end
	end
	k = k + (compact and 2 or 3)
	for i = 1,2 do
		row = rows[k]
		blank = addBlank(k, rounds < 2 and {['height'] = '7px'} or nil)
		if row then
			renderTeam(row, rounds + 1, i, i == 1, false)
		end
		if rounds < 2 and not compact then
			blank = addBlank(k+1, {['height'] = '7px'})
		end
		k = k + (compact and 1 or 2)
	end
end

local function maskRows(tbl, count, offsetcount)
	local rmin = 1
	local rmax = count
	for i = rmin, rmax do
		mask[i] = false
	end
	if showThird then
		for i = offsetThird,(offsetThird+ (compact and 3 or 5)) do
			rmax = (i > rmax) and i or rmax
			mask[i] = true
		end
	end
	for r = 1, maxround do
		local teams = math.pow(2, rounds - r + 1)
		local step = count / teams
		local topTeam = true -- is top row in match-up
		local team = 1

		for i = 1, count, step do
			local offset, height, blank
			local hideteam = false
			if r <= byes then
				hideteam = isHidden(r, team)
			end
			if (r == 1) and (RD1seedmap[team] <= 0) then
				hideteam = true
			end
			if not hideteam then
				local j = topTeam and i + step - (compact and 1 or 2) or i
				mask[j] = true
			end
			team = team + 1
			topTeam = not topTeam
		end
	end
	
	for r = 1, maxround do
		local roundFromLast = rounds - r + 1
		local groups = math.pow(2, roundFromLast - 2)
		local step = count / groups
		local group = 1
		for i = step / 2, count, step do
			if args['RD' .. r .. '-group' .. group] then
				mask[i] = true
				mask[i+1] = true
			end
			group = group + 1
		end
	end
	local mmin, mmax = rmax, rmin
	for i = rmin, rmax do
		if mask[i] == true then
			mmin = (i < mmin) and i or mmin
			mmax = (i > mmax) and i or mmax
		end
	end
	for i = mmin, mmax do
		rows[i] = addTableRow(tbl)
	end
end

local function renderTree(tbl)
	-- create 3 or 1 rows for every team
	local count = math.pow(2, rounds) * (compact and 1 or 3)
	local offsetcount = 2 * (compact and 1 or 3) + (compact and 2 or 3)
	offsetThird = getThirdOffset()
	maskRows(tbl, count, offsetcount)
	if showThird then
		for i = (count+1), (offsetcount + offsetThird) do
			if (rounds > 1) then
				local blank = addBlank(i, nil, 1, tonumber(hideSeeds and '3' or '4') + legs[1])
				if compact and (rounds > 2) then
					blank = addBlank(i, nil, 1, tonumber(hideSeeds and '3' or '4') + legs[2])
				end
			end
		end
	end
	if not compact then
		-- fill rows with groups
		for r = 1, rounds - 1 do
			renderGroups(count, r)
		end
	end
	-- fill rows with bracket
	for r = 1, maxround do
		renderRound(count, r)
	end
	if showThird then
		renderThird(count, compact)
	end
end

local function renderHeadings(tbl)
	local titleRow = addTableRow((not hideHeadings) and tbl or mw.html.create('table'))
	local widthRow = addTableRow(tbl)
	for r = 1, (compactFinal and (maxround-1) or maxround) do
		titleRow:tag('td')
		widthRow:tag('td'):css('width', r > 1 and '5px' or '1px')
		if compactFinal and r == (maxround-1) then
			addHeading(titleRow, r, getRoundName(r), legs[r+1] - legs[r])
		else
			addHeading(titleRow, r, getRoundName(r) )
		end
		local seedCell
		if (not hideSeeds) then
			seedCell = widthRow:tag('td'):css('width', getWidth('seed', '25px'))
		end
		local teamCell = widthRow:tag('td'):css('width', getWidth('team', '150px'))
		local scoreCells = {}
		local legsr = legs[r]
		if compactFinal and r == (maxround-1) then
			legsr = legs[r+1] > legs[r] and legs[r+1] or legs[r]
		end
		for s = 1, legsr do
			scoreCells[s] = widthRow:tag('td'):css('width', getWidth('score', '25px'))
		end
		titleRow:tag('td')
		widthRow:tag('td'):css('width', r < rounds and '5px' or '1px')

		if compact then
			teamCell:css('height', '7px')
		else
			if seedCell then
				seedCell:wikitext('&nbsp;')
			end
			teamCell:wikitext('&nbsp;')
			for s = 1, legs[r] do
				scoreCells[s]:wikitext('&nbsp;')
			end
		end
	end
end

function p.main(frame)
	parseArgs(frame)
	rounds = tonumber(args.rounds) or 2
	maxround = tonumber(args.maxround) or rounds
	local teams = math.pow(2, rounds)
	compact = (args['compact'] and (args['compact'] == 'yes' or args['compact'] == 'y'))
	compactFinal = ((rounds > 4) and compact and args['compact-final'] and (args['compact-final'] == 'yes' or args['compact-final'] == 'y'))
	sepwidth = tonumber(args['sepwidth'] or ((args.sets or args.legs) and 1) or (compact and 1) or 2) or 1
	aggregate = (args['aggregate'] or ''):lower()
	aggsep = args['aggsep'] or args['aggregate'] or nil
	boldwinner = args['boldwinner'] or args['bold_winner'] or ''
	local autoSeeds = (args['autoseeds'] and (args['autoseeds'] == 'yes' or args['autoseeds'] == 'y'))
	hideSeeds = (args['seeds'] and (args['seeds'] == 'no' or args['seeds'] == 'n'))
	showSeeds = (args['seeds'] and (args['seeds'] == 'yes' or args['seeds'] == 'y'))
	byes = (args['byes'] and (args['byes'] == 'yes' or args['byes'] == 'y') and 1) or (tonumber(args['byes'] or '0') or 0)
	hideomittedscores = (args['hideomittedscores'] and (args['hideomittedscores'] == 'yes' or args['hideomittedscores'] == 'y') and 1) or (tonumber(args['hideomittedscores'] or '0') or 0)
	hideHeadings = (args['headings'] and (args['headings'] == 'no' or args['headings'] == 'n'))
	showThird = isnotblank(args['3rd']) or isnotblank(args['3rd-team1']) or isnotblank(args['3rd-team2'])
	local align = (args['float'] or args['align'] or ''):lower()
	local clear = args['clear'] or 'none'
	parseSeedmap(args['RD1-omit'])
	parseLegs(args.sets or args.legs)
	
	if autoSeeds then
		-- set default seeds for round 1
		local seeds = getSeeds()
		for i = 1, table.getn(seeds) do
			local argname = getTeamArgName(1, 'seed', i)
			if not args[argname] then
				args[argname] = seeds[i]
			end
		end
	end

	-- create the table
	local tbl = mw.html.create('table')
		:css('border-style', 'none')
		:css('font-size', '90%')
		:css('border-collapse', 'separate')
		:css('border-spacing', '0')
		:attr('cellpadding', '0')

	if (args['nowrap'] and (args['nowrap'] == 'yes' or args['nowrap'] == 'y')) then
		tbl:css('white-space', 'nowrap')
	end
	
	if align == 'left' then
		tbl:css('float', 'left')
		if clear ~= 'none' and clear ~= 'no' and clear ~= 'n' then
			tbl:css('clear', 'left')
		end
		tbl:css('margin', '1em 2em 1em 0')
	elseif align == 'right' then
		tbl:css('float', 'right')
		if clear ~= 'none' and clear ~= 'no' and clear ~= 'n' then
			tbl:css('clear', 'right')
		end
		tbl:css('margin', '1em 0 1em 2em')
	elseif align == 'center' or align == 'centre' then
		tbl:css('margin', '1em auto')
	else
		tbl:css('margin', '1em 1em 1em 2em')
	end

	renderHeadings(tbl)
	renderTree(tbl)
	if (args['wide'] and (args['wide'] == 'y' or args['wide'] == 'yes')) then
		return '<div class="noresize" style="overflow:auto">' .. tostring(tbl) .. '</div>' .. tcats
	end
	return tostring(tbl) .. tcats
end

function p.teamBracket(frame)
	return p.main(frame)
end

return p