모듈:Election results

require('strict')
local p = {}
local political_party = require('Module:Political party')
function p.main(frame)
	local args = require('Module:Arguments').getArgs(frame)
	local index, headings, showtotal = {}, {}, {}
	local cols, rounds = 0, 1
	local winner, winner_votes = {0, 0, 0}, {0, 0, 0}
	local valid = {0, 0, 0}
	local invalid = {tonumber(args.invalid) or 0, tonumber(args.invalid2) or 0, tonumber(args.invalid3) or 0}
	local blank = {tonumber(args.blank) or 0, tonumber(args.blank2) or 0, tonumber(args.blank3) or 0}
	local majority = {tonumber(args.majority)}
	local majority2 = {tonumber(args.majority2)}
	local majoritypct = {tonumber(args.majoritypct)}
	local majoritypct2 = {tonumber(args.majoritypct2)}
	local totalvotes = {tonumber(args.totalvotes), tonumber(args.totalvotes2), tonumber(args.totalvotes3)}
	local electorate = {tonumber(args.electorate), tonumber(args.electorate2), tonumber(args.electorate3)}
	local turnout = {tonumber(args.turnout), tonumber(args.turnout2), tonumber(args.turnout3)}
	local seats = 0
	local seats_2 = 0
	local seats_3 = 0
	local st1t = 0
	local st2t = 0
	local st3t = 0
	local st4t = 0
	local st5t = 0
	local totseats = 0
	local row, secondrow
	local tracking = 
	local max_rows = 0
	-- helper functions
	local lang = mw.getContentLanguage()
	local function fmt(n)
		return n and tonumber(n) and lang:formatNum(tonumber(n)) or nil
	end
	local function pct(n, d)
		n, d = tonumber(n), tonumber(d)
		if n and d and d > 0 then
			return string.format('%.2f', n / d * 100)
		end
		return '–'
	end
	local function tonumdash(s)
		if s then
			s = mw.ustring.gsub(s, '&MmNnDdAaSsHh;', '-')
			s = mw.ustring.gsub(s, '&MmIiNnUuSs;', '-')
			s = mw.ustring.gsub(s, '—–−', '-')
			return tonumber(s) or 0
		end
	end
	local function unlink(s)
		if s then
			s = s:match("^^%-%%(^%-)|^%-%%.*$") or s
			s = s:match("^^%-%%(^%-)%%.*$") or s
		end
		return s
	end
	local function get_color(color, party)
		if color == nil then
			local party = unlink(party) or 
			if party ~=  then
				color = political_party._fetch({party, 'color'})
			end
		end
		if color ~= nil then
			color = mw.ustring.gsub(color, '&(#)35;', '%1')
		end
		return color
	end
	-- preprocess the input
	local stop_flag = false
	local i = 0
	local has_votes = args'invalid' or args'totalvotes' or args'electorate' or args'turnout'
	local has_votes2 = args'invalid2' or args'totalvotes2' or args'electorate2' or args'turnout2'
	local has_votes3 = args'votes' .. i .. '_3' or args'ivotes' .. i .. '_3'
	local has_seats2 = args'seats' .. i .. '_2' or args'iseats' .. i .. '_2'
	local has_seats3 = args'seats' .. i .. '_3'
	local has_sw2 = args'sw' .. i .. '_2'
	local seats_only = has_seats2 and not has_votes
	local has_cand = args'cand' .. i
	local has_alliance = args'alliance' .. i
	local has_party = args'party' .. i
	local has_rspan = args'vspan' .. i or args'v2span' .. i
	local has_sspan = args'sspan' .. i or args'tsspan' .. i
	while stop_flag == false do
		stop_flag = true
		for kk = 1, 20 do
			i = i + 1
			for k, key in ipairs({'alliance', 'atotal', 'cand', 'vp', 'party', 'ivotes', 'ipct', 'iseats', 'sc', 'st1t', 'st2t', 'st3t', 'st4t', 'st5t', 'sw', 'seats', 'totalvotes', 'totseats', 'acolor', 'rcolor'}) do
				if argskey .. i then
					headingskey = true
					stop_flag = false
					max_rows = i > max_rows and i or max_rows
				end
			end
			if args'row' .. i then
				stop_flag = false
				max_rows = i > max_rows and i or max_rows
			end
			if args'row' .. i or args'cand' .. i or args'party' .. i or args'alliance' .. i or args'atotal' .. i or args'atotalnv' .. i or args'header' .. i then
				table.insert(index, i)
				if args'votes' .. i then
					has_votes = true
					if tonumber(args'votes' .. i) then showtotal.votes = 1 end
					local votesi = tonumber(args'votes' .. i) or 0
					args'votes' .. i = votesi
					if votesi > winner_votes1 then
						winner1 = i
						winner_votes1 = votesi
					end
					valid1 = valid1 + votesi
				end
				if args'votes' .. i .. '_2' or args'ivotes' .. i .. '_2' or args'avotes' .. i .. '_2' or args'ipct' .. i .. '_2' or args'apct' .. i .. '_2' then
					has_votes2 = true
				end
				if args'votes' .. i .. '_3' or args'ivotes' .. i .. '_3' or args'ipct' .. i .. '_3' then
					has_votes3 = true
				end
				if args'alliance' .. i then
					has_alliance = true
				end
				if args'party' .. i then
					has_party = true
				end
				if args'cand' .. i then
					has_cand = true
				end
				if args'ivotes' .. i then
					has_votes = true
				end
				if args'ipct' .. i then
					has_votes = true
				end
				if args'sw' .. i .. '_2' then
					has_sw2 = true
					rounds = (rounds  winner_votes2 then
						winner2 = i
						winner_votes2 = votesi
					end
					valid2 = valid2 + votesi
				end
				if args'votes' .. i .. '_3' then
					has_votes = true
					rounds = (rounds  winner_votes3 then
						winner3 = i
						winner_votes3 = votesi
					end
					valid3 = valid3 + votesi
				end
				if args'seats' .. i then
					if tonumber(args'seats' .. i) then showtotal.seats = 1 end
					seats = seats + (tonumber(args'seats' .. i) or 0)
				end
				if args'seats' .. i .. '_2' or args'iseats' .. i .. '_2' then
					has_seats2 = true
					rounds = (rounds  1) and args'valid2') or ((rounds > 1) and args'valid3') then
		max_rows = max_rows + 1
		local i = max_rows
		table.insert(index, i)
		args'votes' .. i = showtotal.votes and valid1 or nil
		args'votes' .. i .. '_2' = showtotal.votes_2 and valid2 or nil
		args'votes' .. i .. '_3' = showtotal.votes_3 and valid3 or nil
		args'colour' .. i = 'inherit'
		args'color' .. i = 'inherit'
		args'row' .. i = 'Total'
		args'sw' .. i = '–'
		args'sw' .. i .. '_2' = '–'
		args'seats' .. i = showtotal.seats and seats or nil
		args'seats' .. i .. '_2' = showtotal.seats_2 and seats_2 or nil
		args'seats' .. i .. '_3' = showtotal.seats_3 and seats_3 or nil
		args'st1t' .. i = showtotal.st1t and st1t or args.total_st1t
		args'st2t' .. i = showtotal.st2t and st2t or args.total_st2t
		args'st3t' .. i = showtotal.st3t and st3t or args.total_st3t
		args'st4t' .. i = showtotal.st4t and st4t or args.total_st4t
		args'st5t' .. i = showtotal.st5t and st5t or args.total_st5t
		args'sc' .. i = args'total_sc'
		args'totseats' .. i = showtotal.totseats and totseats or nil
		args'font-weight' .. i = 'bold'
		args'class' .. i = 'sortbottom'
		ovalid1 = tonumber(args'valid') or valid1
		ovalid2 = tonumber(args'valid2') or valid2
		ovalid3 = tonumber(args'valid3') or valid3
	end
	-- build the table
	local root = mw.html.create(args'embed' and  or 'table')
	if args'embed' == nil and args'floatright' then
		root
			:addClass('wikitable sortable floatright')
			:tag('caption')
				:wikitext(args.caption)
				:done()
	elseif args'embed' == nil then
		root
			:addClass('wikitable sortable')
			:tag('caption')
				:wikitext(args.caption)
				:done()
	end
	local topcell = nil
	if args'image' then
		topcell = root
			:tag('th')
				:css('text-align', 'center')
				:css('color', 'var( --color-base, #202122 )')
				:css('background', 'var( --background-color-neutral, #F8F9FA )')
				:wikitext(args'image')
	end
	if args'reporting' then
		if (topcell == nil) then
			topcell = root
				:tag('td')
					:css('text-align', 'center')
					:css('color', 'var( --color-base, #202122 )')
					:css('background', 'var( --background-color-neutral, #F8F9FA )')
		end
		topcell:tag('div')
				:addClass('center')
				:wikitext(frame:expandTemplate{
					title = 'percentage bar',
					args = {args.reporting, 
						args.reporting .. '% reporting',
						'width' = '200px',
						'hex' = '1BCE0E'
						}})
	end
	local rowspan = (rounds > 1) and 2 or headings'st1t' and 2 or nil
	row = args'embed' and mw.html.create() or root:tag('tr')
	if args'dsv' and has_alliance and has_party then
		row
			:tag('th')
				:wikitext(args.partytitle or 'Party or alliance')
				:attr('scope', 'col')
				:attr('colspan', 4)
				:attr('rowspan', rowspan)
				:done()
		cols = cols + 4
		row
			:tag('th')
			:wikitext(args.candtitle or 'Candidate')
			:attr('scope', 'col')
			:attr('rowspan', rowspan)
			:done()
		cols = cols + 1
	elseif args'dsv' then
		row
			:tag('th')
				:wikitext(args.partytitle or 'Party')
				:attr('scope', 'col')
				:attr('colspan', 2)
				:attr('rowspan', rowspan)
				:done()
		cols = cols + 2
		row
			:tag('th')
			:wikitext(args.candtitle or 'Candidate')
			:attr('scope', 'col')
			:attr('rowspan', rowspan)
			:done()
		cols = cols + 1
	elseif has_cand then
	if has_cand and has_party and has_alliance then
			row
				:tag('th')
				:wikitext('Candidate')
				:attr('rowspan', rowspan)
				:attr('colspan', 2)
			row
				:tag('th')
				:wikitext(args.partytitle or 'Party or alliance')
				:attr('scope', 'col')
				:attr('rowspan', rowspan)
				:attr('colspan', 3)
				:done()
			cols = cols + 5
	elseif has_cand and has_party then
		row
			:tag('th')
				:wikitext('Candidate')
				:attr('scope', 'col')
				:attr('colspan', 2)
				:attr('rowspan', rowspan)
				:done()
		cols = cols + 2
	end
	if has_cand and not has_party then
		row
			:tag('th')
				:wikitext('Candidate')
				:attr('scope', 'col')
				:attr('rowspan', rowspan)
				:done()
		cols = cols + 1
	end
		if headings'vp' then
			row
				:tag('th')
						:wikitext('Running mate')
						:attr('scope', 'col')
						:attr('rowspan', rowspan)
						:done()
			cols = cols + 1
		end
		if has_party and not has_alliance then
			row
				:tag('th')
				:wikitext(args.partytitle or 'Party')
				:attr('scope', 'col')
				:attr('rowspan', rowspan)
				:done()
			cols = cols + 1
		end
	elseif has_party and has_alliance then
			row
				:tag('th')
				:wikitext(args.partytitle or 'Party or alliance')
				:attr('scope', 'col')
				:attr('rowspan', rowspan)
				:attr('colspan', 4)
				:done()
			cols = cols + 4
	else 
			row
			:tag('th')
				:wikitext(args.partytitle or 'Party')
				:attr('scope', 'col')
				:attr('colspan', 2)
				:attr('rowspan', rowspan)
				:done()
		cols = cols + 2
	end
	if rounds > 1 then
		if has_seats2 and headings'sw' and not has_seats3 then
			row
				:tag('th')
					:wikitext(args.firstround or 'First round')
					:attr('scope', 'col')
					:attr('colspan', 4)
					:done()
				:tag('th')
					:wikitext(args.secondround or 'Second round')
					:attr('scope', 'col')
					:attr('colspan', 4)
					:done()
		elseif has_seats2 and not has_seats3 then
			row
				:tag('th')
					:wikitext(args.firstround or 'First round')
					:attr('scope', 'col')
					:attr('colspan', 3)
					:done()
				:tag('th')
					:wikitext(args.secondround or 'Second round')
					:attr('scope', 'col')
					:attr('colspan', 3)
					:done()
		elseif has_seats3 then
			row
				:tag('th')
					:wikitext(args.firstround or 'First round')
					:attr('scope', 'col')
					:attr('colspan', 3)
					:done()
				:tag('th')
					:wikitext(args.secondround or 'Second round')
					:attr('scope', 'col')
					:attr('colspan', 3)
					:done()
				:tag('th')
					:wikitext(args.thirdround or 'Third round')
					:attr('scope', 'col')
					:attr('colspan', 3)
					:done()
		elseif has_votes3 then
			row
				:tag('th')
					:wikitext(args.firstround or 'First round')
					:attr('scope', 'col')
					:attr('colspan', 2)
					:done()
				:tag('th')
					:wikitext(args.secondround or 'Second round')
					:attr('scope', 'col')
					:attr('colspan', 2)
					:done()
				:tag('th')
					:wikitext(args.thirdround or 'Third round')
					:attr('scope', 'col')
					:attr('colspan', 2)
					:done()
		elseif has_votes then
			row
				:tag('th')
					:wikitext(args.firstround or 'First round')
					:attr('scope', 'col')
					:attr('colspan', 2)
					:done()
				:tag('th')
					:wikitext(args.secondround or 'Second round')
					:attr('scope', 'col')
					:attr('colspan', 2)
					:done()
		end
		secondrow = args'embed' and mw.html.create() or root:tag('tr')
	else
		secondrow = row
	end
	if headings'seats' and not has_seats2 then
		row
			:tag('th')
				:wikitext(args.seatstitle or 'Seats')
				:attr('scope', 'col')
				:attr('rowspan', rowspan)
				:done()
		cols = cols + 1
	end
	if headings'st1t' then
		row
			:tag('th')
				:wikitext('Seats')
				:attr('colspan', 5)
				:attr('scope', 'col')
				:done()
	if rounds seats' or 'Totseats&pm;')
				:attr('scope', 'col')
				:attr('rowspan', rowspan)
				:done()
		cols = cols + 1
	end
	if headings'sc' then
		row
			:tag('th')
				:wikitext(args.sctitle or '+/–')
				:attr('scope', 'col')
				:attr('rowspan', rowspan)
				:done()
		cols = cols + 1
	end
	if topcell then
		topcell:attr('colspan', cols)
	end
	local cs = cols - 2*rounds
			- (headings'sw' and 1 or 0)
			- (headings'totseats' and 1 or 0)
			- (headings'seats' and 1 or 0)
			- (headings'sc' and 1 or 0)
			- (headings'st1t' and 1 or 0)
			- (headings'st2t' and 1 or 0)
			- (headings'st3t' and 1 or 0)
			- (headings'st4t' and 1 or 0)
			- (headings'st5t' and 1 or 0)
			- (has_seats2 and 1 or 0)
			- (has_seats3 and 1 or 0)
			- (has_sw2 and 1 or 0)
			+ (has_votes and 0 or 2)
			- (seats_only and 2 or 0)
	local rsuff = (rounds > 1) and {, '_2'} or (rounds > 2) and {, '_3'} or {}
	for i, v in ipairs(index) do
		local has_votesrow = args'votes' .. v or args'ivotes' .. v or args'avotes' .. v or args'ipct' .. v or args'apct' .. v or args'atotal' .. v
		local has_seatsrow = args'seats' .. v or args'iseats' .. v or args'aseats' .. v
		local has_votesrow2 = args'votes' .. v .. '_2' or args'ivotes' .. v .. '_2' or args'avotes' .. v .. '_2' or args'ipct' .. v .. '_2' or args'apct' .. v .. '_2' or args'atotal' .. v .. '_2'
		local has_seatsrow2 = args'seats' .. v .. '_2' or args'iseats' .. v .. '_2' or args'aseats' .. v .. '_2'
		local has_votesrow3 = args'votes' .. v .. '_3' or args'ivotes' .. v .. '_3' or args'avotes' .. v .. '_3' or args'ipct' .. v .. '_3' or args'apct' .. v .. '_3' or args'atotal' .. v .. '_3'
		local has_seatsrow3 = args'seats' .. v .. '_3' or args'iseats' .. v .. '_3' or args'aseats' .. v .. '_3'
					row = root:tag('tr')
			:addClass(args'class' .. v)
			:css('font-weight', args'font-weight' .. v)
		-- determine the colors
		local color = get_color(args'colour' .. v or args'color' .. v or nil, args'party' .. v)
		local acolor = get_color(args'acolour' .. v or args'acolor' .. v or nil, args'alliance' .. v)
		local rcolor = get_color(args'rcolour' .. v or args'rcolor' .. v or nil)
		-- headers
		if args'header' .. v then
			row
			:tag('th')
				:wikitext(args'header' .. v)
				:attr('colspan', cols)
		else
		if args'alliance' .. v then
			row
				:tag('td')
					:attr('rowspan', args'aspan' .. v)
					:css('width', '0px')
					:css('background-color', acolor)
		elseif args'party' .. v and not has_alliance or args'cand' .. v and has_party and not has_alliance then
			row
				:tag('td')
					:css('width', '0px')
					:css('background-color', color)
		end
		if args'cand' .. v and not args.dsv then
			row
					:css('background-color', rcolor)
				:tag('td')
					:attr('rowspan', args'candspan' .. v or args'aspan' .. v)
					:wikitext(args'cand' .. v)
		end
		if args'vp' .. v then
			row
				:tag('td')
					:wikitext(args'vp' .. v)
		end
		if args'alliance' .. v and not has_party and args.dsv then
			row
				:tag('td')
					:attr('rowspan', args'aspan' .. v)
					:wikitext(args'alliance' .. v)
		end
		if args'alliance' .. v and not args'party' .. v and not args.dsv then
			row
				:tag('td')
					:attr('rowspan', args'aspan' .. v)
					:attr('colspan', 3)
					:wikitext(args'alliance' .. v)
		end
		if args'alliance' .. v and not args'party' .. v and has_party and args.dsv then
			row
				:tag('td')
					:attr('rowspan', args'aspan' .. v)
					:attr('colspan', 3)
					:wikitext(args'alliance' .. v)
		end
		if args'alliance' .. v and args'party' .. v then
			row
				:tag('td')
					:attr('rowspan', args'aspan' .. v)
					:wikitext(args'alliance' .. v)
		end
		if args'party' .. v and not has_alliance or args'cand' .. v and has_party and not has_alliance then
			row
				:tag('td')
					:wikitext(args'party' .. v)
		end
		if args'row' .. v then
			row
					:css('background-color', rcolor)
				:tag('td')
					:attr('colspan', cs)
					:wikitext(args'row' .. v)
		end
		if has_alliance and args'party' .. v then
			row
				:tag('td')
					:css('background-color', color)
				:tag('td')
					:wikitext(args'party' .. v)
		end
		if args'cand' .. v and args.dsv then
			row
				:tag('td')
					:attr('rowspan', args'candspan' .. v)
					:wikitext(args'cand' .. v)
		end
		if args'atotal' .. v and has_party and not args.dsv or args'atotalnv' .. v and has_party and not args.dsv then
			row
					:css('font-style', 'italic')
				:tag('td')
					:attr('colspan', 2)
					:wikitext('Total')
		end
		if args'atotal' .. v and not has_party or args'atotalnv' .. v and not has_party then
			row
					:css('font-style', 'italic')
				:tag('td')
					:wikitext('Total')
		end
		if args'atotal' .. v and has_cand and has_party and args.dsv or args'atotalnv' .. v and has_party and args.dsv then
			row
					:css('font-style', 'italic')
				:tag('td')
					:attr('colspan', 3)
					:wikitext('Total')
		end
		if args'votes' .. v and args'divisor' then
				row:tag('td')
					:attr('rowspan', args'vspan' .. v)
					:css('text-align', 'right')
					:wikitext(fmt(args'votes' .. v))
				row:tag('td')
					:attr('rowspan', args'vspan' .. v)
					:css('text-align', 'right')
					:wikitext(pct(args'votes' .. v, (args'row' .. v == 'Total') and args'votes' .. v or args'divisor'))
		elseif args'votes' .. v then
				row:tag('td')
					:attr('rowspan', args'vspan' .. v)
					:css('text-align', 'right')
					:wikitext(fmt(args'votes' .. v))
				row:tag('td')
					:attr('rowspan', args'vspan' .. v)
					:css('text-align', 'right')
					:wikitext(pct(args'votes' .. v, valid1))
		elseif args'avotes' .. v then
				row:tag('td')
					:attr('rowspan', args'vspan' .. v)
					:css('text-align', 'right')
					:css('font-style', 'italic')
					:wikitext(fmt(args'avotes' .. v))
				row:tag('td')
					:attr('rowspan', args'vspan' .. v)
					:css('text-align', 'right')
					:css('font-style', 'italic')
					:wikitext(pct(args'avotes' .. v, valid1))
		elseif args'ivotes' .. v or args 'ipct' .. v or args'atotal' .. v then
				row:tag('td')
					:attr('rowspan', args'vspan' .. v)
					:css('text-align', 'right')
					:css('font-style', 'italic')
					:wikitext(fmt(args'ivotes' .. v) or fmt(args'atotal' .. v))
			if args'ipct' .. v or args'apct' .. v or args'atotal' .. v then
				row:tag('td')
					:attr('rowspan', args'vspan' .. v)
					:css('text-align', 'right')
					:css('font-style', 'italic')
					:wikitext(args'ipct' .. v or args'apct' .. v or pct(args'atotal' .. v, valid1))
			else
				row:tag('td')
					:attr('rowspan', args'vspan' .. v)
					:wikitext()
			end
		elseif has_votes and headings'seats' and headings'sw' and not has_votesrow and not has_seatsrow and not args'sw' .. v and not has_rspan then
				row:tag('td')
					:attr('colspan', 4)
		elseif has_votes and headings'seats' and not has_votesrow and not has_seatsrow and not has_rspan or has_votes and headings'sw' and not has_votesrow and not args'sw' .. v and not has_rspan or has_seats2 and not has_votesrow and not has_seatsrow and not has_rspan then
				row:tag('td')
					:attr('colspan', 3)
		elseif has_votes and not has_votesrow and not has_rspan or has_votes and args'row' .. v and has_seatsrow and not has_votesrow or has_seats2 and not has_votesrow and not has_rspan then
				row:tag('td')
					:attr('colspan', 2)
		elseif args'r1blockc' .. v then
				row:tag('td')
					:attr('rowspan', args'r1blockr' .. v)
					:attr('colspan', args'r1blockc' .. v)
					:wikitext()
		end
		if headings'sw' and has_votesrow then
			row
				:tag('td')
					:css('text-align', 'right')
					:wikitext(args'sw' .. v)
		end
		if headings'seats' and not args'dsv' and not has_seats2 and rounds  1 and not has_seats2 and not has_sspan or args'seats' .. v and has_sspan and rounds > 1 and not has_seats2 then
			row
				:tag('td')
					:attr('rowspan', args'sspan' .. v)
					:css('text-align', 'right')
					:wikitext(fmt(args'seats' .. v) or fmt(args'aseats' .. v) or '–')
		end
		if has_sw2 and args'votes' .. v .. '_2' then
			row
				:tag('td')
					:css('text-align', 'right')
					:wikitext(args'sw' .. v .. '_2')
		end
		if args'seats' .. v .. '_2' or has_seats2 and args'votes' .. v .. '_2' then
			row
				:tag('td')
					:css('text-align', 'right')
					:wikitext(fmt(args'seats' .. v .. '_2') or '–')
		end
		if args'iseats' .. v .. '_2' or has_seats2 and args'ivotes' .. v .. '_2' and not args'seats' .. v .. '_2' or args'aseats' .. v .. '_2' then
			row
				:tag('td')
					:css('text-align', 'right')
					:wikitext(fmt(args'iseats' .. v .. '_2') or fmt(args'aseats' .. v .. '_2'))
		end
		if has_seats3 or has_votes3 then
		if args'votes' .. v .. '_3' then
				row:tag('td')
					:attr('rowspan', args'v3span' .. v)
					:css('text-align', 'right')
					:wikitext(fmt(args'votes' .. v .. '_3'))
				row:tag('td')
					:attr('rowspan', args'v3span' .. v)
					:css('text-align', 'right')
					:wikitext(pct(args'votes' .. v .. '_3', valid3))
		elseif args'ivotes' .. v .. '_3' or args 'ipct' .. v.. '_3' or args'avotes' .. v .. '_3' then
				row:tag('td')
					:attr('rowspan', args'v3span' .. v)
					:css('text-align', 'right')
					:css('font-style', 'italic')
					:wikitext(fmt(args'ivotes' .. v .. '_3') or fmt(args'avotes' .. v .. '_3'))
				row:tag('td')
					:attr('rowspan', args'v3span' .. v)
					:css('text-align', 'right')
					:css('font-style', 'italic')
					:wikitext(args'ipct' .. v .. '_3' or args'apct' .. v .. '_3' or pct(args'avotes' .. v .. '_3', valid3))
		elseif has_seats3 and not has_votesrow3 and not has_seatsrow3 and not has_rspan then
				row:tag('td')
					:attr('colspan', 3)
		elseif has_seats3 and not has_votesrow3 and not has_rspan or has_seats3 and args'row' .. v and has_seatsrow3 and not has_votesrow3 or has_votes3 and not has_votesrow3 and not has_rspan then
				row:tag('td')
					:attr('colspan', 2)
		elseif args'r3blockc' .. v then
				row:tag('td')
					:attr('rowspan', args'r3blockr' .. v)
					:attr('colspan', args'r3blockc' .. v)
					:wikitext()
		end
		if has_sw2 and args'votes' .. v .. '_3' then
			row
				:tag('td')
					:css('text-align', 'right')
					:wikitext(args'sw' .. v .. '_3')
		end
		if args'seats' .. v .. '_3' or has_seats3 and args'votes' .. v .. '_3' then
			row
				:tag('td')
					:css('text-align', 'right')
					:wikitext(fmt(args'seats' .. v .. '_3') or '–')
		end
		if args'iseats' .. v .. '_3' or has_seats3 and args'ivotes' .. v .. '_3' and not args'seats' .. v .. '_3' or args'aseats' .. v .. '_3' then
			row
				:tag('td')
					:css('text-align', 'right')
					:wikitext(fmt(args'iseats' .. v .. '_3') or fmt(args'aseats' .. v .. '_3'))
		end
		end
		if args'st1t' .. v and has_sspan or headings'st1t' and not has_sspan then
			row
				:tag('td')
					:attr('rowspan', args'sspan' .. v)
					:css('text-align', 'right')
					:wikitext(args'st1t' .. v or '–')
		end
		if args'st2t' .. v and has_sspan or headings'st2t' and not has_sspan then
			row
				:tag('td')
					:attr('rowspan', args'sspan' .. v)
					:css('text-align', 'right')
					:wikitext(args'st2t' .. v or '–')
		end
		if args'st3t' .. v and has_sspan or headings'st3t' and not has_sspan then
			row
				:tag('td')
					:attr('rowspan', args'sspan' .. v)
					:css('text-align', 'right')
					:wikitext(args'st3t' .. v or '–')
		end
		if args'st4t' .. v and has_sspan or headings'st4t' and not has_sspan then
			row
				:tag('td')
					:attr('rowspan', args'sspan' .. v)
					:css('text-align', 'right')
					:wikitext(args'st4t' .. v or '–')
		end
		if args'st5t' .. v and has_sspan or headings'st5t' and not has_sspan then
			row
				:tag('td')
					:attr('rowspan', args'sspan' .. v)
					:css('text-align', 'right')
					:wikitext(args'st5t' .. v or '–')
		end
		if args'totseats' .. v and has_sspan or args'atotseats' .. v and has_sspan then
			row
				:tag('td')
					:attr('rowspan', args'tsspan' .. v)
					:css('text-align', 'right')
					:wikitext(args'totseats' .. v or args'atotseats' .. v or '–')
		end
		if headings'totseats' and not args'itotseats' .. v and not args'atotseats' .. v and not has_sspan then
			row
				:tag('td')
					:css('text-align', 'right')
					:wikitext(fmt(args'totseats' .. v) or '–')
		elseif headings'totseats' and not has_sspan then
			row
				:tag('td')
					:css('text-align', 'right')
					:css('font-style', 'italic')
					:wikitext(args'itotseats' .. v or args'atotseats' .. v)
		end
		if headings'sc' and args.sctitle then
			row
				:tag('td')
					:wikitext(args'sc' .. v)
		elseif headings'sc' then
			row
				:tag('td')
					:css('text-align', 'right')
					:wikitext(args'sc' .. v or '–')
		end
	end
	end
	-- separating line
	if args'valid' or args'valid2' or args'valid3' or args'invalid' or args'invalid2' or args'invalid3' or args'totalvotes' or args'totalvotes2' or args'totalvotes3' or args'electorate' or args'electorate2' or args'electorate3' or args'turnout' or args'turnout2' or args'turnout3' or args'source' then
	row = root
		:tag('tr')
			:addClass('sortbottom')
	row
		:tag('td')
			:css('color', 'var( --color-base, #202122 )')
			:css('background', 'var( --background-color-neutral, #eaecf0 )')
			:attr('colspan', cols)
	end
	-- valid votes
	if args'invalid' or args'invalid2'  or args'invalid3' then
	row = root
		:tag('tr')
			:addClass('sortbottom')
			:css('text-align', 'right')
	row
		:tag('th')
			:wikitext('Valid votes')
			:attr('scope', 'row')
			:attr('colspan', cs)
			:css('text-align', 'left')
			:css('font-weight', 'normal')
			:css('color', 'inherit')
			:css('background', 'inherit')
	if args'invalid' then
	row
		:tag('td')
			:wikitext(fmt(ovalid1))
		:tag('td')
				:wikitext(pct(ovalid1, ovalid1 + invalid1 + blank1))
	elseif not args'invalid' then
	row
		:tag('td')
			:wikitext()
		:tag('td')
				:wikitext()
	end
	if has_seats2 and not headings'sw' then
	row
		:tag('td')
			:wikitext()
	end
	if has_seats2 and headings'sw' and args'validsw' then
	row
		:tag('td')
			:wikitext(args'validsw')
		:tag('td')
			:wikitext()
	end
	if has_seats2 and headings'sw' and not args'validsw' then
	row
		:tag('td')
			:attr('colspan', 2)
			:wikitext()
	end
	if rounds > 1 and args'invalid2' then
	row
		:tag('td')
			:wikitext(fmt(ovalid2))
		:tag('td')
				:wikitext(pct(ovalid2, ovalid2 + invalid2 + blank2))
	elseif rounds > 1 and not args'invalid2' then
	row
		:tag('td')
			:wikitext()
		:tag('td')
			:wikitext()
	end
	if has_seats2 and not headings'sw' then
	row
		:tag('td')
			:wikitext()
	end
	if has_seats2 and headings'sw' and args'validsw2' then
	row
		:tag('td')
			:wikitext(args'validsw2')
		:tag('td')
			:wikitext()
	end
	if has_seats2 and headings'sw' and not args'validsw2' then
	row
		:tag('td')
			:attr('colspan', 2)
			:wikitext()
	end
	if args'invalid3' then
	row
		:tag('td')
			:wikitext(fmt(ovalid3))
		:tag('td')
				:wikitext(pct(ovalid3, ovalid3 + invalid3 + blank3))
	elseif has_seats3 and not args'invalid3' then
	row
		:tag('td')
			:wikitext()
		:tag('td')
			:wikitext()
	end
	if args'invalidsw' and not has_sw2 then
		row:tag('td')
			:wikitext(args'validsw')
		local cspan = (headings'seats' and 1 or 0) + (headings'sc' and 1 or 0) + (headings'st1t' and 1 or 0) + (headings'st2t' and 1 or 0) + (headings'st3t' and 1 or 0) + (headings'st4t' and 1 or 0) + (headings'st5t' and 1 or 0) + (has_seats3 and 1 or 0)
	if headings'seats' or headings'sc' then
		local cspan = (headings'seats' and 1 or 0) + (headings'sc' and 1 or 0) + (headings'st1t' and 1 or 0) + (headings'st2t' and 1 or 0) + (headings'st3t' and 1 or 0) + (headings'st4t' and 1 or 0) + (headings'st5t' and 1 or 0) + (has_seats3 and 1 or 0)
		row
			:tag('td')
				:attr('colspan', cspan > 1 and cspan or nil)
	end
	elseif headings'sw' or headings'seats' or headings'sc' or headings'st1t' or headings'st2t' or headings'st3t' or headings'st4t' or headings'st5t' then
		local cspan = (headings'sw' and 1 or 0) + (headings'seats' and 1 or 0) + (headings'sc' and 1 or 0) + (headings'st1t' and 1 or 0) + (headings'st2t' and 1 or 0) + (headings'st3t' and 1 or 0) + (headings'st4t' and 1 or 0) + (headings'st5t' and 1 or 0) + (has_seats3 and 1 or 0)
		row
			:tag('td')
				:attr('colspan', cspan > 1 and cspan or nil)
	end
	-- invalid votes
	row = root:tag('tr')
			:addClass('sortbottom')
			:css('text-align', 'right')
		if args'invalidonly' or args'blank' then
	row
		:tag('th')
			:wikitext('Invalid votes')
			:attr('scope', 'row')
			:attr('colspan', cs)
			:css('text-align', 'left')
			:css('font-weight', 'normal')
			:css('color', 'inherit')
			:css('background', 'inherit')
	else
	row
		:tag('th')
			:wikitext('Invalid/blank votes')
			:wikitext(args.invalidnote)
			:attr('scope', 'row')
			:attr('colspan', cs)
			:css('text-align', 'left')
			:css('font-weight', 'normal')
			:css('color', 'inherit')
			:css('background', 'inherit')
	end
	if args'invalid' then
	row
		:tag('td')
			:wikitext(fmt(invalid1))
		:tag('td')
				:wikitext(pct(invalid1, ovalid1 + invalid1 + blank1))
	elseif not args'invalid' then
	row
		:tag('td')
			:wikitext()
		:tag('td')
				:wikitext()
	end
	if has_seats2 and not headings'sw' then
	row
		:tag('td')
			:wikitext()
	end
	if has_seats2 and headings'sw' and args'invalidsw' then
	row
		:tag('td')
			:wikitext(args'invalidsw')
		:tag('td')
			:wikitext()
	end
	if has_seats2 and headings'sw' and not args'invalidsw' then
	row
		:tag('td')
			:attr('colspan', 2)
			:wikitext()
	end
	if rounds > 1 and args'invalid2' then
	row
		:tag('td')
			:wikitext(fmt(invalid2))
		:tag('td')
				:wikitext(pct(invalid2, ovalid2 + invalid2 + blank2))
	elseif rounds > 1 and not args'invalid2' then
	row
		:tag('td')
			:wikitext()
		:tag('td')
				:wikitext()
	end
	if has_seats2 and not headings'sw' then
	row
		:tag('td')
			:wikitext()
	end
	if has_seats2 and headings'sw' and args'invalidsw2' then
	row
		:tag('td')
			:wikitext(args'invalidsw2')
		:tag('td')
			:wikitext()
	end
	if has_seats2 and headings'sw' and not args'invalidsw2' then
	row
		:tag('td')
			:attr('colspan', 2)
			:wikitext()
	end
	if has_seats3 and args'invalid3' or has_votes3 and args'invalid3' then
	row
		:tag('td')
			:wikitext(fmt(invalid3))
		:tag('td')
				:wikitext(pct(invalid3, ovalid3 + invalid3 + blank3))
	elseif has_seats3 and not args'invalid3' then
	row
		:tag('td')
			:wikitext()
		:tag('td')
			:wikitext()
	end
	if args'invalidsw' and not has_sw2 then
		row:tag('td')
			:wikitext(args'invalidsw')
	if headings'seats' or headings'sc' or headings'st1t' or headings'st2t' or headings'st3t' or headings'st4t' or headings'st5t' then
		local cspan = (headings'seats' and 1 or 0) + (headings'sc' and 1 or 0) + (has_seats3 and 1 or 0)
		row
			:tag('td')
				:attr('colspan', cspan > 1 and cspan or nil)
	end
	elseif headings'sw' or headings'seats' or headings'sc' or headings'st1t' or headings'st2t' or headings'st3t' or headings'st4t' or headings'st5t' then
		local cspan = (headings'sw' and 1 or 0) + (headings'seats' and 1 or 0) + (headings'sc' and 1 or 0) + (headings'st1t' and 1 or 0) + (headings'st2t' and 1 or 0) + (headings'st3t' and 1 or 0) + (headings'st4t' and 1 or 0) + (headings'st5t' and 1 or 0) + (has_seats3 and 1 or 0)
		row
			:tag('td')
				:attr('colspan', cspan > 1 and cspan or nil)
	end
	end
	-- blank votes
	if args'blank' or args'blank2' or args'blank3' then
	row = root:tag('tr')
			:addClass('sortbottom')
			:css('text-align', 'right')
	row
		:tag('th')
			:wikitext('Blank votes')
			:attr('scope', 'row')
			:attr('colspan', cs)
			:css('text-align', 'left')
			:css('font-weight', 'normal')
			:css('color', 'inherit')
			:css('background', 'inherit')
	if args'blank' then
	row
		:tag('td')
			:wikitext(fmt(blank1))
		:tag('td')
			:wikitext(pct(blank1, ovalid1 + invalid1 + blank1))
	else
	row
		:tag('td')
			:wikitext()
		:tag('td')
			:wikitext()
	end
	if has_seats2 and not headings'sw' then
	row
		:tag('td')
			:wikitext()
	end
	if has_seats2 and headings'sw' and args'blanksw' then
	row
		:tag('td')
			:wikitext(args'blanksw')
		:tag('td')
			:wikitext()
	end
	if has_seats2 and headings'sw' and not args'blanksw' then
	row
		:tag('td')
			:attr('colspan', 2)
			:wikitext()
	end
	if rounds > 1 and args'blank2' then
	row
		:tag('td')
			:wikitext(fmt(blank2))
		:tag('td')
				:wikitext(pct(blank2, ovalid2 + invalid2 + blank2))
	elseif rounds > 1 and not args'blank2' then
	row
		:tag('td')
			:wikitext()
		:tag('td')
				:wikitext()
	end
	if has_seats2 and not headings'sw' then
	row
		:tag('td')
			:wikitext()
	end
	if has_seats2 and headings'sw' and args'blanksw2' then
	row
		:tag('td')
			:wikitext(args'blanksw2')
		:tag('td')
			:wikitext()
	end
	if has_seats2 and headings'sw' and not args'blanksw2' then
	row
		:tag('td')
			:attr('colspan', 2)
			:wikitext()
	end
	if has_seats3 and args'blank3' or has_votes3 and args'blank3' then
	row
		:tag('td')
			:wikitext(fmt(blank3))
		:tag('td')
				:wikitext(pct(blank3, ovalid3 + invalid3 + blank3))
	elseif has_seats3 and args'blank3' or has_votes3 and args'blank3' then
	row
		:tag('td')
			:wikitext()
		:tag('td')
			:wikitext()
	end
	if args'blanksw' and not has_sw2 then
		row:tag('td')
			:wikitext(args'blanksw')
	if headings'seats' or headings'sc' or headings'st1t' or headings'st2t' or headings'st3t' or headings'st4t' or headings'st5t' then
		local cspan = (headings'seats' and 1 or 0) + (headings'sc' and 1 or 0) + (has_seats3 and 1 or 0)
		row
			:tag('td')
				:attr('colspan', cspan > 1 and cspan or nil)
	end
	elseif headings'sw' or headings'seats' or headings'sc' or headings'st1t' or headings'st2t' or headings'st3t' or headings'st4t' or headings'st5t' then
		local cspan = (headings'sw' and 1 or 0) + (headings'seats' and 1 or 0) + (headings'sc' and 1 or 0) + (headings'st1t' and 1 or 0) + (headings'st2t' and 1 or 0) + (headings'st3t' and 1 or 0) + (headings'st4t' and 1 or 0) + (headings'st5t' and 1 or 0) + (has_seats3 and 1 or 0)
		row
			:tag('td')
				:attr('colspan', cspan > 1 and cspan or nil)
	end
	end
	-- total
	if args'invalid' or args'totalvotes' or args'invalid2' or args'totalvotes2' then
	row = root:tag('tr')
			:addClass('sortbottom')
			:css('font-weight', 'bold')
			:css('text-align', 'right')
	row
		:tag('th')
			:wikitext(args.tvtitle or 'Total votes')
			:attr('scope', 'row')
			:attr('colspan', cs)
			:css('text-align', 'left')
			:css('background', 'inherit')
			:css('color', 'inherit')
	if not args'totalvotes' and args'invalid' then
	row
		:tag('td')
			:wikitext(fmt(ovalid1 + invalid1 + blank1))
		:tag('td')
			:wikitext(pct(1, 1))
	elseif args'totalvotes' then
	row
		:tag('td')
			:wikitext(fmt(args.totalvotes))
		:tag('td')
			:wikitext('–')
	elseif not args'invalid' and not args'totalvotes' then
	row
		:tag('td')
			:wikitext()
		:tag('td')
			:wikitext()
	end
	if has_seats2 and not headings'sw' then
	row
		:tag('td')
			:wikitext()
	end
	if has_seats2 and headings'sw' and args'invalidsw' then
	row
		:tag('td')
			:wikitext('–')
		:tag('td')
			:wikitext()
	end
	if has_seats2 and headings'sw' and not args'invalidsw' then
	row
		:tag('td')
			:attr('colspan', 2)
			:wikitext()
	end
	if rounds > 1 and args'invalid2' and not args'totalvotes2' then
	row
		:tag('td')
			:wikitext(fmt(ovalid2 + invalid2 + blank2))
		:tag('td')
			:wikitext(pct(1, 1))
	elseif rounds > 1 and args'totalvotes2' then
	row
		:tag('td')
			:wikitext(fmt(args.totalvotes2))
		:tag('td')
			:wikitext('–')
	elseif rounds > 1 and not args'invalid2' or rounds > 1 and not args'totalvotes2' then
	row
		:tag('td')
			:wikitext()
		:tag('td')
				:wikitext()
	end
	if has_seats2 and not headings'sw' then
	row
		:tag('td')
			:wikitext()
	end
	if has_seats2 and headings'sw' and args'invalidsw2' then
	row
		:tag('td')
			:wikitext('–')
		:tag('td')
			:wikitext()
	end
	if has_seats2 and headings'sw' and not args'invalidsw2' then
	row
		:tag('td')
			:attr('colspan', 2)
			:wikitext()
	end
	if has_seats3 and not args'totalvotes3' and args'invalid3' or has_votes3 and not args'totalvotes3' and args'invalid3' then
	row
		:tag('td')
			:wikitext(fmt(ovalid3 + invalid3 + blank3))
		:tag('td')
			:wikitext(pct(1, 1))
	elseif has_seats3 and args'totalvotes3' or has_votes3 and args'totalvotes3' then
	row
		:tag('td')
			:wikitext(fmt(args.totalvotes3))
		:tag('td')
			:wikitext('–')
	elseif has_seats3 and not args'invalid3' or has_votes3 and not args'invalid3' then
	row
		:tag('td')
			:wikitext()
		:tag('td')
				:wikitext()
	end
	if args'invalidsw' and not has_sw2 then
		row:tag('td')
			:wikitext('–')
	if headings'seats' or headings'sc' or headings'st1t' or headings'st2t' or headings'st3t' or headings'st4t' or headings'st5t' then
		local cspan = (headings'seats' and 1 or 0) + (headings'sc' and 1 or 0) + (headings'st1t' and 1 or 0) + (headings'st2t' and 1 or 0) + (headings'st3t' and 1 or 0) + (headings'st4t' and 1 or 0) + (headings'st5t' and 1 or 0) + (has_seats3 and 1 or 0)
		row
			:tag('td')
				:attr('colspan', cspan > 1 and cspan or nil)
	end
	elseif headings'sw' or headings'seats' or headings'sc' or headings'st1t' or headings'st2t' or headings'st3t' or headings'st4t' or headings'st5t' then
		local cspan = (headings'sw' and 1 or 0) + (headings'seats' and 1 or 0) + (headings'sc' and 1 or 0) + (headings'st1t' and 1 or 0) + (headings'st2t' and 1 or 0) + (headings'st3t' and 1 or 0) + (headings'st4t' and 1 or 0) + (headings'st5t' and 1 or 0) + (has_seats3 and 1 or 0)
		row
			:tag('td')
				:attr('colspan', cspan > 1 and cspan or nil)
	end
	end
	-- registered
	if args'electorate' or args'electorate2' or args'turnout' or args'turnout2' then
	row = root:tag('tr')
			:addClass('sortbottom')
			:css('text-align', 'right')
	row
		:tag('th')
			:wikitext('Registered voters/turnout')
			:attr('scope', 'row')
			:attr('colspan', cs)
			:css('text-align', 'left')
			:css('font-weight', 'normal')
			:css('color', 'inherit')
			:css('background', 'inherit')
	row
			:tag('td')
				:wikitext(fmt(electorate1))
	if args'invalid' and args'electorate' and not args'totalvotes' then
		row
			:tag('td')
				:wikitext(args.turnout or pct(ovalid1 + invalid1 + blank1, electorate1))
	elseif args'totalvotes' and args'electorate' then
		row
			:tag('td')
				:wikitext(args.turnout or pct(totalvotes1, electorate1))
	elseif args'electorate' then
		row
			:tag('td')
				:wikitext(args.turnout or '–')
	else
		row
			:tag('td')
				:wikitext(args.turnout)
	end
	if has_seats2 and not headings'sw' then
		row
			:tag('td')
				:wikitext()
	end
	if has_seats2 and headings'sw' and args'turnoutsw' then
	row
		:tag('td')
			:wikitext(args'turnoutsw')
		:tag('td')
			:wikitext()
	end
	if has_seats2 and headings'sw' and not args'turnoutsw' then
	row
		:tag('td')
			:attr('colspan', 2)
			:wikitext()
	end
	if rounds > 1 then
		row
			:tag('td')
				:wikitext(fmt(electorate2))
	if args'invalid2' and args'electorate2' then
		row
			:tag('td')
				:wikitext(args.turnout2 or pct(ovalid2 + invalid2 + blank2, electorate2))
	elseif args'totalvotes2' and args'electorate2' then
		row
			:tag('td')
				:wikitext(args.turnout2 or pct(totalvotes2, electorate2))
	elseif args'electorate2' then
		row
			:tag('td')
				:wikitext(args.turnout2 or '–')
	else
		row
			:tag('td')
				:wikitext(args.turnout2)
	end
	if has_seats2 and not headings'sw' then
		row
			:tag('td')
				:wikitext()
	end
	if has_seats2 and headings'sw' and args'turnoutsw2' then
	row
		:tag('td')
			:wikitext(args'turnoutsw2')
		:tag('td')
			:wikitext()
	end
	if has_seats2 and headings'sw' and not args'turnoutsw2' then
	row
		:tag('td')
			:attr('colspan', 2)
			:wikitext()
	end
	end
	if has_seats3 or has_votes3 then
		row
			:tag('td')
				:wikitext(fmt(electorate3))
	if args'invalid3' and args'electorate3' then
		row
			:tag('td')
				:wikitext(args.turnout3 or pct(ovalid3 + invalid3 + blank3, electorate3))
	elseif args'totalvotes3' and args'electorate3' then
		row
			:tag('td')
				:wikitext(args.turnout3 or pct(totalvotes3, electorate3))
	elseif args'electorate3' then
		row
			:tag('td')
				:wikitext(args.turnout3 or '–')
	else
		row
			:tag('td')
				:wikitext(args.turnout3)
	end
	end
	if args'turnoutsw' and not has_sw2 then
		row:tag('td')
			:wikitext(args'turnoutsw')
	if headings'seats' or headings'sc' or headings'st1t' or headings'st2t' or headings'st3t' or headings'st4t' or headings'st5t' then
		local cspan = (headings'seats' and 1 or 0) + (headings'sc' and 1 or 0) + (headings'st1t' and 1 or 0) + (headings'st2t' and 1 or 0) + (headings'st3t' and 1 or 0) + (headings'st4t' and 1 or 0) + (headings'st5t' and 1 or 0) + (has_seats3 and 1 or 0)
		row
			:tag('td')
				:attr('colspan', cspan > 1 and cspan or nil)
	end
	elseif headings'sw' or headings'seats' or headings'sc' or headings'st1t' or headings'st2t' or headings'st3t' or headings'st4t' or headings'st5t' then
		local cspan = (headings'sw' and 1 or 0) + (headings'seats' and 1 or 0) + (headings'sc' and 1 or 0) + (headings'st1t' and 1 or 0) + (headings'st2t' and 1 or 0) + (headings'st3t' and 1 or 0) + (headings'st4t' and 1 or 0) + (headings'st5t' and 1 or 0) + (has_seats3 and 1 or 0)
		row
			:tag('td')
				:attr('colspan', cspan > 1 and cspan or nil)
	end
	end
	if args'majority' then
	if args'invalid' or args'electorate' then
	row = root
		:tag('tr')
			:addClass('sortbottom')
	row
		:tag('td')
			:css('color', 'var( --color-base, #202122 )')
			:css('background', 'var( --background-color-neutral, #eaecf0 )')
			:attr('colspan', cols)
	end
	row = root
		:tag('tr')
			:addClass('sortbottom')
			:css('text-align', 'right')
	row
		:tag('th')
			:wikitext('Majority')
			:attr('scope', 'row')
			:attr('colspan', cs)
			:css('text-align', 'left')
			:css('font-weight', 'normal')
			:css('color', 'inherit')
			:css('background', 'inherit')
	for k=1, rounds do
	row
		:tag('td')
			:wikitext(fmt(majorityk))
		:tag('td')
			:wikitext(fmt(majoritypctk))
	end
	if args'majoritysw' then
	row
		:tag('td')
			:wikitext(args'majoritysw')
	end
	end
	if args'result' then
		row = root:tag('tr')
			:addClass('sortbottom')
		-- determine the color
		local color = get_color(args'resultcolour' or nil, args'result')
		if args'resultsw' then
			row
				:tag('td')
					:css('background-color', color)
			row
				:tag('td')
					:attr('colspan', 2)
					:wikitext(args'result')
			row
				:tag('td')
					:attr('colspan', 2)
					:css('text-align', 'right')
					:wikitext('Swing')
			row
				:tag('td')
					:css('text-align', 'right')
					:wikitext(args'resultsw')
		else
			row
				:tag('td')
					:css('background-color', color)
			row
				:tag('td')
					:attr('colspan', cols - 1)
					:wikitext(args'result')
		end
	end
	if args'majority2' then
	row = root
		:tag('tr')
			:addClass('sortbottom')
			:css('text-align', 'right')
	row
		:tag('th')
			:wikitext('Majority')
			:attr('scope', 'row')
			:attr('colspan', cs)
			:css('text-align', 'left')
			:css('font-weight', 'normal')
			:css('color', 'inherit')
			:css('background', 'inherit')
	for k=1, rounds do
	row
		:tag('td')
			:wikitext(fmt(majority2k))
		:tag('td')
			:wikitext(fmt(majoritypct2k))
	end
	if args'majoritysw2' then
	row
		:tag('td')
			:wikitext(args'majoritysw2')
	end
	end
	if args'result2' then
		row = root:tag('tr')
			:addClass('sortbottom')
		-- determine the color
		local color = get_color(args'resultcolour' or nil, args'result2')
		if args'resultsw2' then
			row
				:tag('td')
					:css('background-color', color)
			row
				:tag('td')
					:attr('colspan', 2)
					:wikitext(args'result2')
			row
				:tag('td')
					:attr('colspan', 2)
					:css('text-align', 'right')
					:wikitext('Swing')
			row
				:tag('td')
					:css('text-align', 'right')
					:wikitext(args'resultsw2')
		else
			row
				:tag('td')
					:css('background-color', color)
			row
				:tag('td')
					:attr('colspan', cols - 1)
					:wikitext(args'result2')
		end
	end
	if args'source' then
	row = root:tag('tr')
			:addClass('sortbottom')
			:css('text-align', 'right')
	row:tag('td')
		:wikitext('Source: ', args.source)
		:attr('colspan', cols)
		:css('text-align', 'left')
	end
	if args'embedded' then
		root:wikitext(args'embedded')
	end
	return tostring(root) .. tracking
end
return p