Jump to content

Module:Team bracket

Permanently protected module
From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by SocietyBox (talk | contribs) at 16:24, 21 December 2013 (start). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
(diff) ← Previous revision | Latest revision (diff) | Newer revision → (diff)

--
-- This module will implement {{TeamBracket}}
--
 
local p = {}
local HtmlBuilder = require('Module:HtmlBuilder')
local args
local rounds

local function getArgs(frame)
	local args = frame.args;
 
	-- if there are any arguments, then assume that we've got proper ones
	for k,v in pairs(args) do 
		return args
	end
 
	-- otherwise, return args from the parent
	local parent = frame:getParent();
	return parent.args;
end

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

function addTableRow(tbl)
	return tbl.tag('tr')
end

function addBlank(row, width)
	local cell = row.tag('td')
		.css('border-width', '0')
		.css('border-style', 'solid')
		.css('border-color', 'black')
	if width then
		cell.css('width', width)
	end
	return cell
end

function addPath(rows, index, round, top, left)
	local prop = top and 'border-bottom-width' or 'border-top-width'
	if left and round == 1 then
		addBlank(rows[index]).css('height', '7px')
		addBlank(rows[index + 1]).css('height', '7px')
		return nil
	else
		local cell = addBlank(rows[index]).attr('rowspan', '2')
		if left or round < rounds and not left then
			cell.css(prop, '2px')
		end
		return cell
	end
end

function renderGroups(rows, count, r)
	local groups = math.pow(2, r - 2)
	local step = count / groups
	local group = 1
	for i = step / 2, count, step do
		addBlank(rows[i]).css('height', '7px')
		addBlank(rows[i+1]).css('height', '7px')
		addBlank(rows[i])
			.attr('rowspan', '2')
			.attr('colspan', 5 * (rounds - r + 1) - 1)
			.css('text-align', 'center')
			.css('border-right-width', '2px')
			.wikitext(args['RD' .. r .. '-group' .. group])
		group = group + 1
	end
end

function renderRound(rows, count, r)	
	local teams = math.pow(2, rounds - r + 1)
	local step = count / teams
	local top = true
	local open = false
	local team = 1
	for i = 1, count, step do
		local offset, height, blank
		if team == 1 or team == teams then
			offset = top and i or i + 2
			height = step - 2
		else
			offset = top and i + 1 or i + 2
			height = step - 3
		end
		if height > 0 then
			blank = addBlank(rows[offset])
				.attr('colspan', '5')
				.attr('rowspan', height)
		end
		local j = top and i + step - 2 or i
		addPath(rows, j, r, top, true)
		renderTeam(rows[j], r, team)
		local right = addPath(rows, j, r, top, false)
		if not top then open = not open end
		if open and r < rounds then
			if blank then blank.css('border-right-width', '2px') end
			right.css('border-right-width', '2px')
		end
		team = team + 1
		top = not top
	end
end	

function getTeamArg(round, type, team)
	return args['RD' .. round .. '-' .. type .. '0' .. team] or
		args['RD' .. round .. '-' .. type .. team]
end

function getRoundName(round)
	local name = args['RD' .. round]
	if name then
		return name
	end
	local roundFromLast = rounds - round + 1
	if roundFromLast == 1 then
		return "Finals"
	elseif roundFromLast == 2 then
		return "Semifinals"
	elseif roundFromLast == 3 then
		return "Quarterfinals"
	else
		return "Round of " .. math.pow(2, roundFromLast)
	end
end
 
function renderTeam(row, round, team)
	row.tag('td')
		.attr('rowspan', '2')
		.css('text-align', 'center')
		.css('background-color', '#f2f2f2')
		.css('border', '1px solid #aaa')
		.wikitext(getTeamArg(round, 'seed', team))
	row.tag('td')
		.attr('rowspan', '2')
		.css('background-color', '#f9f9f9')
		.css('border', '1px solid #aaa')
		.wikitext(getTeamArg(round, 'team', team))
	row.tag('td')
		.attr('rowspan', '2')
		.css('text-align', 'center')
		.css('border', '1px solid #aaa')
		.css('background-color', '#f9f9f9')
		.wikitext(getTeamArg(round, 'score', team))
end

function renderTree(tbl)
	local count = math.pow(2, rounds) * 3
	local rows = {}
	for i = 1, count do
		rows[i] = addTableRow(tbl)
	end
	for r = 2, rounds do
		renderGroups(rows, count, r)
	end
	for r = 1, rounds do
		renderRound(rows, count, r)
	end
end

function renderHeading(tbl)
	local titleRow = addTableRow(tbl)
	local widthRow = addTableRow(tbl)
	for r = 1, rounds do
		addBlank(titleRow)
		addBlank(widthRow, r > 1 and '5px' or nil)
		titleRow.tag('td')
			.attr('colspan', '3')
			.css('text-align', 'center')
			.css('border', '1px solid #aaa')
			.css('background-color', '#f2f2f2')
			.wikitext(getRoundName(r))
		addBlank(widthRow, args['seed-width'] or '25px').wikitext('&nbsp;')
		addBlank(widthRow, args['team-width'] or '150px').wikitext('&nbsp;')
		addBlank(widthRow, args['score-width'] or '25px').wikitext('&nbsp;')
		addBlank(titleRow)
		addBlank(widthRow, r < rounds and '5px' or nil)
	end
end

function p.teamBracket(frame)
	args = getArgs(frame)
	rounds = tonumber(args.rounds) or 2
	local seeds = getSeeds()
	for i = 1, table.getn(seeds) do
		if not args['RD1-seed' .. i] then
			args['RD1-seed' .. i] = seeds[i]
		end
	end

	local tbl = HtmlBuilder.create('table')
		.css('border-style', 'none')
		.css('font-size', '90%')
		.css('margin', '1em 2em 1em 1em')
		.css('border-collapse', 'separate')
		.css('border-spacing', '0')
 
	renderHeading(tbl)
	renderTree(tbl)
	return tostring(tbl)
end
 
return p