La documentación pa esti módulu pue crease en Módulu:Copa/usu

--
-- This module will implement {{TeamBracket}}
--

local p = {}
local args
local rounds
local showSeeds
local roundNames = {}
local roundNamesExists
local dates={} -- Fecha de cada round
local roundDatesExists
local teamsRound1 -- Diferente
local teams  = {} -- Diferente. Número de equipos de un round
local matches = {} -- Diferente. Número de partidos de un round
local allMatches= {} -- Diferente. Número de partidos de un round y de los anteriores

local rows={}
local numberOfRows
local rowsPerTeam

local scoresConBlancos = false
local scoresConComas = false

-- Constantes
local CRoundNames = {'Final', 'Semifinales', 'Cuartos de final', 'Octavos de final', 'Dieciseisavos de final', ['3rd']='Tercer llugar'}
local CteamCellWidth={'176px', 
		'16em' -- de la plantilla:Copa de 4 equipos-1 ronda
		--, '16em' 
		, '11em' -- de la plantilla:Copa de 8 equipos-1 ronda con número
	} -- 150px en el original siempre. 226 en total

local function getArgs(frame)
	-- Lo rehago. No funcionaba
	local parent = frame:getParent();
	local args = {}
	
	for k,v in pairs(parent.args) do
		args[k] = v
	end

	for k,v in pairs(frame.args) do
		args[k] = v
	end
	
	-- Es diferente a la versión original del módulo pues en la Wikipedia española el nombre de los campos puede ser diferente
	local args2 = {}
	local k2
	
	for k,v in pairs(args) do
		k2= tostring(k):gsub('seed0','seed')
		k2= k2:gsub('team0','team')
		k2= k2:gsub('score0','score')
		k2= k2:gsub('a$','-1') -- {{{RD3-score01a}}}
		k2= k2:gsub('b$','-2') -- {{{RD3-score01b}}}
		
		args2[k2] = v
	end
	
	return args2;
end

function getRounds() -- Diferente
	if args['RD5'] or args['RD5-team1'] then
		return 5
	elseif args['RD4'] or args['RD4-team1'] then
		return 4
	elseif args['RD3'] or args['RD3-team1'] then
		return 3
	elseif args['RD2'] or args['RD2-team1'] then 
		return 2
	elseif args['RD1'] or args['RD1-team1'] then
		return 1
	end
end

function getGroup(round, group)
	local groupArg = args['RD' .. round .. '-group' .. group]
	
	if groupArg then
		return groupArg
	end
	
	if args['group8'] then -- hay 8 grupos
		if rounds == round + 4 then
			return args['group'..group]
		end
	elseif args['group4'] then -- hay 4 grupos
		if rounds == round + 3 then
			return args['group'..group]
		end
		
	elseif args['group2'] then -- solo hay 2 grupos
		if rounds == round + 2 then
			return args['group'..group]
		end	
	end
end

function getScore(round, team, match)
	local resultado
	if round == '3rd' then
		resultado = args[round .. '-score' .. team .. '-' .. match] or 
		(match==1 and args[round .. '-score' .. team]) or ''
	else
		resultado = args['RD' .. round .. '-score' .. team .. '-' .. match] or 
		(match==1 and args['RD' .. round .. '-score' .. team]) or ''
	end
	
	if resultado:match(',') then
		scoresConComas= true
	end

	if resultado:match(' ') and not resultado:match(' %(') and not resultado:match(' {{') and not resultado:match(' <') then
		scoresConBlancos = true
	end

	return resultado
end

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

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

function addBlank(row, width)
	local cell = row:tag('td')
	if width then
		cell:css('width', width)
	end
	return cell
end

-- Draws an horizontal line

function addPath(row, top, showPath)
	local cell = addBlank(row)
		:attr('rowspan', '2')
		
	if showPath then
		cell
			:css('border-width', '0')
			:css('border-style', 'solid')
			:css('border-color', 'black')				
			:css(top and 'border-bottom-width' or 'border-top-width', '2px')
	end
	return cell	
end

function addCompactPath(index, round, top, left)
	local prop = top and 'border-bottom-width' or 'border-top-width'
	if left and round == 1 then
		addBlank(rows[index])
		return nil
	else
		local cell = addBlank(rows[index])
			:css('border-width', '0')
			:css('border-style', 'solid')
			:css('border-color', 'black')
		if left or round < rounds and not left then
			cell:css(prop, '2px')
		end
		return cell
	end
end

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

function getTeamArg(round, type, team)
	return args[getTeamArgName(round, type, team)]
end

function getTeamArgName(round, type, team)
	if round == '3rd' then
		return '3rd-' .. type .. team
	else
		return string.format('RD%d-%s%01d', round, type, team)
	end
end

function renderTeam(row, round, team, top, compact, showTeam)
	local seedCell
	local seedArg = getTeamArg(round, 'seed', team)
	-- seed value for the paired team
	local pairSeedArg = getTeamArg(round, 'seed',
		team % 2 == 0 and team - 1 or team + 1)
	
	-- show seed if seed is defined for either or both
	local showSeed = showTeam and (seedArg and string.len(seedArg) > 0
		or pairSeedArg and string.len(pairSeedArg) > 0)
		
	local teamArg = getTeamArg(round, 'team', team)	

	if showSeed and showSeeds then
		seedCell = row:tag('td')
			:css('text-align', 'center')
			:css('font-size', '95%')
			:css('background-color', '#e6e6e6')
			:css('border-color', '#fff')
			:css('border-style', 'solid')
			:css('border-top-width', '0.5px')
			:css('border-left-width', '0.5px')
			:css('border-right-width', '0')
			:css('border-bottom-width', '0.5px')
			:wikitext(seedArg)
			:newline()
	end

	if not teamArg or string.len(teamArg) == 0 then
		teamArg = '&nbsp;'
	end
	local teamCell = row:tag('td')
	if showTeam then
		teamCell
			:css('background-color', '#f9f9f9')
			:css('border-color', '#bbb')
			:css('border-style', 'solid')
			:css('border-top-width', '1px')
			:css('border-left-width', '1px')
			:css('border-right-width', '0')
			:css('border-bottom-width', '0')
			:css('padding', '0 2px')
			:wikitext('&nbsp;' .. teamArg .. '&nbsp;') -- Diferente
			:newline()
	end
	if not showSeed and showSeeds then
		teamCell:attr('colspan', '2')
	end

	local scoreCell
	
	for match= 1, matches[round] do
		scoreCell = row:tag('td')
		if showTeam then
			scoreCell
				:css('text-align', 'center')
				:css('border-color', '#bbb')
				:css('border-style', 'solid')
				:css('border-top-width', '1px')
				:css('border-left-width', '0')
				:css('border-right-width', '1px')
				:css('border-bottom-width', '0')
				:css('background-color', '#f9f9f9')
				:wikitext(getScore(round,team,match))
				:newline()
			end
		
		if not compact then
			scoreCell:attr('rowspan', '2')
		end
		
		if showTeam and not compact and not top then
			scoreCell:css('border-bottom-width', '1px')
		end
	end

	if not compact then
		if seedCell then
			seedCell:attr('rowspan', '2')
			
			if not top then
				seedCell:css('border-bottom-width', '1px')
			end
		end
		teamCell:attr('rowspan', '2')
		
		if showTeam then
			teamCell:css('border-right-width', '1px')
			
			if not top then
				teamCell:css('border-bottom-width', '1px')
			end
		end
	else
		if not top then
			if seedCell then
				seedCell:css('border-bottom-width', '1px')
			end
			if showTeam then
				teamCell:css('border-bottom-width', '1px')
			end
		end
	end
end

function renderRound(round)
	local teamsRound = teams[round]
	local step = numberOfRows / teamsRound
	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 showTeam
	
	for i = 1, numberOfRows, step do
		local offset, height, blank
		
		if getTeamArg(round, 'team', team) or (team%2 == 0 and getTeamArg(round, 'team', team - 1)) or  
		(team%2 == 1 and getTeamArg(round, 'team', team + 1)) then
			showTeam = true
		else
			showTeam = false
		end
		
		if not topTeam then 
			topPair = not topPair
		end
		
		-- leave room for groups for teams other than first and last
		if round ~= rounds then
			if team == 1 or team == teamsRound 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 height > 0 then
				local k=offset
				while k < offset + height do
					blank = addBlank(rows[k])
						:attr('colspan', (showSeeds and 4 or 3) + matches[round])
						
					if showTeam then
						blank
							:css('border-color', 'black')
							:css('border-style', 'solid')
							:css('border-width', '0')
						if not topPair and round < rounds then
							blank:css('border-right-width', '2px')
						end
					end

					k=k + 1
				end

			end
		end
	
		-- Mostrar las 6 filas de los 2 equipos
		if showTeam and topTeam then
			rows[i + step - 3].show = true			
			rows[i + step - 2].show = true
			rows[i + step - 1].show = true
			rows[i + step].show = true
			rows[i + step + 1].show = true
			rows[i + step + 2].show = true			
		end
		
		-- add bracket
		local j = topTeam and i + step - 2 or i
		-- add left path
		if round == 1 then
			addBlank(rows[j]):css('height', '7px')
			addBlank(rows[j + 1]):css('height', '7px')			
		else
			local showLeftTeams
			local aux = 4 * (math.ceil(team/2) - 1)
		
			if getTeamArg(round - 1 , 'team', 1 + aux) or 
				   getTeamArg(round - 1 , 'team', 2 + aux) or 
				   getTeamArg(round - 1 , 'team', 3 + aux) or 
				   getTeamArg(round - 1 , 'team', 4 + aux) then
					showLeftTeams = true
			end
		
			addPath(rows[j], topTeam, showTeam and showLeftTeams)
		end
		
		renderTeam(rows[j], round, team, topTeam, false,showTeam)
		
		local rightPath = addPath(rows[j], topTeam, showTeam and round < rounds)
		
		if not topPair and round < rounds and showTeam then
			rightPath:css('border-right-width', '2px')
		end
		team = team + 1
		topTeam = not topTeam
	end
end


function renderCompactRound(round)
	local teamsRound = teams[round]
	local step = numberOfRows / teamsRound
	local topTeam = true -- is top row in match-up
	local topPair = true -- is top match-up in pair of match-ups
	local team = 1

	for i = 1, numberOfRows, step do
		local offset, height, blank
		-- empty space above or below
		local offset = topTeam and i or i + 1
		local height = step - 1

		if height > 0 then
			blank = addBlank(rows[offset])
				:attr('colspan', (showSeeds and 4 or 3) + matches[round])
				:css('border-color', 'black')
				:css('border-style', 'solid')
				:css('border-width', '0')
				:attr('rowspan', height)
		end
		-- add bracket
		local j = topTeam and i + step - 1 or i
		-- add left path
		addCompactPath(j, round, topTeam, true)
		renderTeam(rows[j], round, team, topTeam, true)
		local rightPath = addCompactPath(j, round, topTeam, false)
		if not topTeam then topPair = not topPair end
		if not topPair and round < rounds then
			if blank then blank:css('border-right-width', '2px') end
			rightPath:css('border-right-width', '2px')
		end
		team = team + 1
		topTeam = not topTeam
	end
end

function renderGroups(round)
	local roundFromLast = rounds - round + 1
	local groups = math.pow(2, roundFromLast - 2)
	local step = numberOfRows / groups
	local group = 1
	local cell

	for i = step / 2, numberOfRows, step do
		addBlank(rows[i]):css('height', '7px')
		addBlank(rows[i + 1]):css('height', '7px')
		addBlank(rows[i])
			:attr('rowspan', '2')
			:attr('colspan', ((showSeeds and 4 or 3)) * round + allMatches[round] - 2)
			:css('text-align', 'center')
			:wikitext(getGroup(round, group))
			:newline()			
		cell=addBlank(rows[i])
		if getTeamArg(round, 'team', 1 + (group - 1) * 4) or getTeamArg(round, 'team', 2 + (group - 1) * 4) then
			cell
				:css('border-color', 'black')
				:css('border-style', 'solid')
				:css('border-width', '0 2px 0 0')
		end
		
		cell=addBlank(rows[i + 1])
		if getTeamArg(round, 'team', 3 + (group - 1) * 4) or getTeamArg(round, 'team', 4 + (group - 1) * 4) then
			cell
				:css('border-color', 'black')
				:css('border-style', 'solid')
				:css('border-width', '0 2px 0 0')
		end
		
		group = group + 1
	end
end

function renderTree(tbl, compact)
	-- create 3 or 1 rows for every team
	rowsPerTeam  = compact and 1 or 3
	numberOfRows = teamsRound1 * rowsPerTeam

	for i = 1, numberOfRows do
		rows[i] = addTableRow(tbl)
	end
	if not compact then
		-- fill rows with groups
		for r = 1, rounds - 1 do
			renderGroups(r)
		end
	end
	-- fill rows with bracket
	for r = 1, rounds do
		if compact then
			renderCompactRound(r)
		else
			renderRound(r)
		end
	end
	
	-- Third. De momento solo si no es compacto
	if args['3rd-team1'] or args['3rd-team2'] then
		if rounds == 2 then
			addBlank(rows[numberOfRows])
				:attr('colspan', (showSeeds and 4 or 3) + matches[1])
				--:css('height', '20px')
				:wikitext('&nbsp;')
				
			numberOfRows = numberOfRows + 1
			rows[numberOfRows] = addTableRow(tbl)
			addBlank(rows[numberOfRows])
				:attr('colspan', (showSeeds and 4 or 3) + matches[1])			
			numberOfRows = numberOfRows + 1
			rows[numberOfRows] = addTableRow(tbl)
			addBlank(rows[numberOfRows])
				:attr('colspan', (showSeeds and 4 or 3) + matches[1])
			numberOfRows = numberOfRows + 1
			rows[numberOfRows] = addTableRow(tbl)
			addBlank(rows[numberOfRows])
				:attr('colspan', (showSeeds and 4 or 3) + matches[1])			
			numberOfRows = numberOfRows + 1
			rows[numberOfRows] = addTableRow(tbl)			
			addBlank(rows[numberOfRows])
				:attr('colspan', (showSeeds and 4 or 3) + matches[1])			
			numberOfRows = numberOfRows + 1
			rows[numberOfRows] = addTableRow(tbl)			
			addBlank(rows[numberOfRows])
				:attr('colspan', (showSeeds and 4 or 3) + matches[1])
		end
		addBlank(rows[numberOfRows - 7])
		local cell = addBlank(rows[numberOfRows - 7])
			:attr('rowspan', 2)
			:attr('colspan', (showSeeds and 2 or 1) + matches['3rd'])
			:css('text-align', 'center')
			:css('border', '1px solid #aaa')
			:css('background-color', '#f2f2f2')
			:wikitext(args['3rd'] or CRoundNames['3rd'])
			:newline()			
		
		addBlank(rows[numberOfRows - 4])
		renderTeam(rows[numberOfRows - 4], '3rd', 1 , true, false, true)
		addBlank(rows[numberOfRows - 2])
		renderTeam(rows[numberOfRows - 2], '3rd', 2 , false, false, true)
		
		--rows[numberOfRows - 5].show = true
		rows[numberOfRows - 4].show = true
		rows[numberOfRows - 3].show = true
		rows[numberOfRows - 2].show = true
		rows[numberOfRows - 1].show = true
		rows[numberOfRows    ].show = true
	end
	
	-- Hide empty rows
	local j, row
	
	for j, row in pairs(rows) do
		if not row.show then
			row:css('display','none')
		end
	end
end

function renderHeading(tbl, compact)
	if not roundNamesExists then
		return
	end
	
	local titleRow = addTableRow(tbl)
	local dateRow  = roundDatesExists and 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', (showSeeds and 2 or 1) + matches[r])
			:css('text-align', 'center')
			:css('border', '1px solid #aaa')
			:css('background-color', '#f2f2f2')
			:wikitext(roundNames[r])
			:newline()
		local seedCell
		if showSeeds then
			seedCell = addBlank(widthRow, getWidth('seed', '25px'))
			
			if not compact then
				seedCell:wikitext('&nbsp;')
			end
		end
--		local teamCell = addBlank(widthRow, getWidth('team', '150px'))
       	local teamCell = addBlank(widthRow, getWidth('team', CteamCellWidth[rounds] or '150px'))
        
       	if compact then
			teamCell:css('height', '7px')
		else
			teamCell:wikitext('&nbsp;')
		end
        
       	local scoreCell
        
       	for match= 1, matches[r] do
       		scoreCell = addBlank(widthRow, getWidth('score', (matches[1]>=3 and '12px') or '25px'))
        	
       		if not compact then
       			scoreCell:wikitext('&nbsp;')
       		end
    	end
    
		addBlank(titleRow)
		addBlank(widthRow, r < rounds and '5px' or nil)
		
		if roundDatesExists then
			addBlank(dateRow)

			dateRow:tag('td')
				:attr('colspan', (showSeeds and 2 or 1) + matches[r])
				:css('text-align', 'center')
				:css('border', '1px solid #aaa')
				:css('background-color', '#f9f9f9')
				:wikitext(dates[r] or '&nbsp;')
				:newline()
			addBlank(dateRow)				
		end
	end
end

function p.teamBracket(frame)
	local round
	
	args = getArgs(frame)
	--rounds = tonumber(args.rounds) or 2                  -- Diferente
	rounds      = tonumber(args.rounds) or getRounds(args) or 2 -- Diferente
	
	rows = {}
	
	-- Get the names and the dates of each round
	local argRound
	
	for round = 1, rounds do
		argRound = args['RD' .. round]
		
		roundNames[round] = (argRound and argRound:match('([^<]*)<br />.*')) or argRound
			or CRoundNames[rounds - round + 1] or ("Round of " .. teams[round])
			
		if roundNames[round] ~= '' then
			roundNamesExists = true
		end
		
		dates[round] = args['RD' .. round .. '-date'] or (argRound and argRound:match('[^<]*<br />(.*)')) or ''
		
		if dates[round] ~= '' then
			roundDatesExists = true
		end
	end
	
	
	--Set the number of teams of each round
	teamsRound1 = 2
	
	for round=rounds,2,-1 do
		teams[round] = teamsRound1
		teamsRound1 = teamsRound1 * 2
	end
	
	teams[1] = teamsRound1
	
	showSeeds = true
	if args['seeds'] and args['seeds'] == 'no' then
		showSeeds = false
	end
	
	--Set the matches of each round
	for round=1,rounds do
		matches[round] = 1
	end
	
	for k,v in pairs(args) do
		round,match = k:match('^RD(.*)%-score.*%-(.*)$')
		
		if round and match then 
			round=tonumber(round)
			match = tonumber(match)
			if match and matches[round] and match > matches[round] then
				matches[round] = match
			end
		end
	end
	
	allMatches[1] = matches[1]

	for round=2,rounds do
		allMatches[round] = allMatches[round - 1] + matches[round]
	end	
	
	--Set the matches of 3rd
	matches['3rd'] = 1
	
	for k,v in pairs(args) do
		match = k:match('^3rd%-score.*%-(.*)$')
		
		if match then 
			match = tonumber(match)
			if match > matches['3rd'] then
				matches['3rd'] = match
			end
		end
	end	
	
	
	--if true then return require('Módulo:Tablas').tostring(matches) end

	-- set default seeds for round 1
	local seeds = getSeeds()
	local argname
	for i = 1, table.getn(seeds) do
		argname = getTeamArgName(1, 'seed', i)
		if not args[argname] then
			args[argname] = seeds[i]
		end
	end

	local tbl = mw.html.create('table')
		:css('border-style', 'none')
		:css('font-size', '90%')
		:css('margin', '1em 2em 1em 1em')
		:css('border-collapse', 'separate')
		:css('border-spacing', '0')

	local compact = false
	if args['compact'] and args['compact'] == 'yes' then
		compact = true
	end

	if compact then
		tbl:css('font-size', '90%'):attr('cellpadding', '0')
	end

	renderHeading(tbl, compact)
	renderTree(tbl, compact)
	
	local output
	output = tostring(tbl)
	if scoresConComas then
		output = output .. '[[Categoría:Wikipedia:Artículos que usen la plantía copa con comes]]'
	end
	if scoresConBlancos then
		output = output .. '[[Categoría:Wikipedia:Artículos que usen la plantía copa con espacios en blanco]]'
	end
	
	return output
end

-- Diferencias con el módulo original
p.copa = p.teamBracket


return p