Module:Election results

require('Module:No globals') local p = {}

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} local valid = {0, 0} local invalid = {tonumber(args.invalid) or 0, tonumber(args.invalid2) 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)} local electorate = {tonumber(args.electorate), tonumber(args.electorate2)} local turnout = {tonumber(args.turnout), tonumber(args.turnout2)} local seats = 0 local seats_2 = 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, '&[MmNn][Dd][Aa][Ss][Hh];', '-') s = mw.ustring.gsub(s, '&[Mm][Ii][Nn][Uu][Ss];', '-') 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

-- 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_seats = args['seats' .. i .. '_2']	local has_sw = args['sw' .. i .. '_2']	local seats_only = has_seats and not has_votes local has_rspan = args['vspan' .. i] local has_sspan = args['sspan' .. 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'}) do if args[key .. i] then headings[key] = 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_votes[1] then winner[1] = i						winner_votes[1] = votesi end valid[1] = valid[1] + votesi 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_sw = true rounds = 2 end if args['valid2'] or args['invalid2'] or args['totalvotes2'] or args['electorate2'] or args['turnout2'] then rounds = 2 end if args['vspan' .. i] then has_rspan = true end if args['sspan' .. i] then has_sspan = true end if args['ipct' .. i .. '_2'] then rounds = 2 end if args['votes' .. i .. '_2'] then has_votes = true rounds = 2 if tonumber(args['votes' .. i .. '_2']) then showtotal.votes_2 = 1 end local votesi = tonumber(args['votes' .. i .. '_2']) or 0 args['votes' .. i .. '_2'] = votesi if votesi > winner_votes[2] then winner[2] = i						winner_votes[2] = votesi end valid[2] = valid[2] + 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'] then has_seats = true rounds = 2 if tonumber(args['seats' .. i ..'_2']) then showtotal.seats_2 = 1 end seats_2 = seats_2 + (tonumber(args['seats' .. i .. '_2']) or 0) end if args['st1t' .. i] then if tonumber(args['st1t' .. i]) then showtotal.st1t = 1 end st1t = st1t + (tonumber(args['st1t' .. i]) or 0) end if args['st2t' .. i] then if tonumber(args['st2t' .. i]) then showtotal.st2t = 1 end st2t = st2t + (tonumber(args['st2t' .. i]) or 0) end if args['st3t' .. i] then if tonumber(args['st3t' .. i]) then showtotal.st3t = 1 end st3t = st3t + (tonumber(args['st3t' .. i]) or 0) end if args['st4t' .. i] then if tonumber(args['st4t' .. i]) then showtotal.st4t = 1 end st4t = st4t + (tonumber(args['st4t' .. i]) or 0) end if args['st5t' .. i] then if tonumber(args['st5t' .. i]) then showtotal.st5t = 1 end st5t = st5t + (tonumber(args['st5t' .. i]) or 0) end if args['totseats' .. i] then if tonumber(args['totseats' .. i]) then showtotal.totseats = 1 end totseats = totseats + (tonumber(args['totseats' .. i]) or 0) end if has_seats and not has_votes then seats_only = true end end end end

local ovalid = {valid[1], valid[2]} seats = ((args['total_seats'] or '') == 'TOTAL' and seats) or args['total_seats'] or seats totseats = ((args['total_totseats'] or '') == 'TOTAL' and totseats) or args['total_totseats'] or totseats st1t = ((args['total_st1t'] or '') == 'TOTAL' and st1t) or args['total_st1t'] or st1t st2t = ((args['total_st2t'] or '') == 'TOTAL' and st2t) or args['total_st2t'] or st2t st3t = ((args['total_st3t'] or '') == 'TOTAL' and st3t) or args['total_st3t'] or st3t st4t = ((args['total_st4t'] or '') == 'TOTAL' and st4t) or args['total_st4t'] or st4t st5t = ((args['total_st5t'] or '') == 'TOTAL' and st5t) or args['total_st5t'] or st5t if seats or totseats or st1t or st2t or st3t or st4t or st5t or args['total_sc'] or args['total_st1t'] or args['total_st2t'] or args['total_st3t'] or args['total_st4t'] or args['total_st5t'] or args['valid'] or ((rounds > 1) and args['valid2']) then max_rows = max_rows + 1 local i = max_rows table.insert(index, i) args['votes' .. i] = showtotal.votes and valid[1] or nil args['votes' .. i .. '_2'] = showtotal.votes_2 and valid[2] 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['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' ovalid[1] = tonumber(args['valid']) or valid[1] ovalid[2] = tonumber(args['valid2']) or valid[2] end

-- build the table local root = mw.html.create(args['embed'] and '' or 'table') if 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('tr') :tag('td') :wikitext(args['image']) :css('text-align', 'center') 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'] then row :tag('th') :wikitext('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 headings['cand'] then if headings['cand'] and headings['party'] then row :tag('th') :wikitext('Candidate') :attr('scope', 'col') :attr('colspan', 2) :attr('rowspan', rowspan) :done cols = cols + 2 end if headings['cand'] and not headings['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 headings['party'] then row :tag('th') :wikitext('Party') :attr('scope', 'col') :attr('rowspan', rowspan) :done cols = cols + 1 end elseif headings['party'] and headings['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_seats and headings['sw'] 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_seats 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_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 rowspan = (rounds > 1) and 1 or (rounds < 2 and headings['st1t']) and 2 or nil if has_seats and headings['sw'] then for k=1, rounds do			secondrow :tag('th') :wikitext(args.votestitle or 'Votes') :attr('scope', 'col') :attr('rowspan', rowspan) :done :tag('th') :wikitext('%') :attr('scope', 'col') :attr('rowspan', rowspan) :done :tag('th') :wikitext('+/–') :attr('scope', 'col') :attr('rowspan', rowspan) :done :tag('th') :wikitext(args.seatstitle or 'Seats') :attr('scope', 'col') :attr('rowspan', rowspan) :done cols = cols + 4 end end if has_seats and not headings['sw'] then for k=1, rounds do			secondrow :tag('th') :wikitext(args.votestitle or 'Votes') :attr('scope', 'col') :attr('rowspan', rowspan) :done :tag('th') :wikitext('%') :attr('scope', 'col') :attr('rowspan', rowspan) :done :tag('th') :wikitext(args.seatstitle or 'Seats') :attr('scope', 'col') :attr('rowspan', rowspan) :done cols = cols + 3 end end if has_votes and not has_seats then for k=1, rounds do			secondrow :tag('th') :wikitext(args.votestitle or 'Votes') :attr('scope', 'col') :attr('rowspan', rowspan) :done :tag('th') :wikitext('%') :attr('scope', 'col') :attr('rowspan', rowspan) :done cols = cols + 2 end end if headings['sw'] and not has_seats then row :tag('th') :wikitext('+/–') :attr('scope', 'col') :attr('rowspan', rowspan) :done cols = cols + 1 end rowspan = (rounds > 1) and 2 or headings['sc'] and headings['st1t'] and 2 or nil if headings['seats'] and not has_seats 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 < 2 then secondrow = root:tag('tr') end secondrow :tag('th') :wikitext(args.seattype1) :attr('scope', 'col') :done cols = cols + 1 if headings['st2t'] then secondrow :tag('th') :wikitext(args.seattype2) :attr('scope', 'col') :done cols = cols + 1 end if headings['st3t'] then secondrow :tag('th') :wikitext(args.seattype3) :attr('scope', 'col') :done cols = cols + 1 end if headings['st4t'] then secondrow :tag('th') :wikitext(args.seattype4) :attr('scope', 'col') :done cols = cols + 1 end if headings['st5t'] then secondrow :tag('th') :wikitext(args.seattype5) :attr('scope', 'col') :done cols = cols + 1 end end if headings['totseats'] then row :tag('th') :wikitext(headings['totseats'] and 'Total seats' or 'Totseats&pm;') :attr('scope', 'col') :attr('rowspan', rowspan) :done cols = cols + 1 end if headings['sc'] then row :tag('th') :wikitext('+/–') :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_seats and 1 or 0) - (has_sw and 1 or 0) + (has_votes and 0 or 2) - (seats_only and 2 or 0) local rsuff = (rounds > 1) and {, '_2'} or {} for i, v in ipairs(index) do		row = root:tag('tr') :addClass(args['class' .. v]) :css('font-weight', args['font-weight' .. v])

-- determine the color local color = args['colour' .. v] or args['color' .. v] or nil if color == nil then local party = unlink(args['party' .. v]) or '' if party ~= '' and mw.title.new('Template:' .. party .. '/meta/color').exists then color = frame:expandTemplate{title = party .. '/meta/color'} end end local acolor = args['acolour' .. v] or args['acolor' .. v] or nil if acolor == nil then local alliance = unlink(args['alliance' .. v]) or '' if alliance ~= '' and mw.title.new('Template:' .. alliance .. '/meta/color').exists then acolor = frame:expandTemplate{title = alliance .. '/meta/color'} end end if args['header' .. v] then row :tag('th') :wikitext(args['header' .. v]) :attr('colspan', cols) else if args['row' .. v] or headings['cand'] and not headings['party'] then row :css('background-color', args['acolor' .. v]) :tag('td') :wikitext(args['row' .. v] or args['cand' .. v]) :attr('colspan', cs) elseif args['alliance' .. v] and args['party' .. v] then row :tag('td') :attr('rowspan', args['aspan' .. v]) :css('background-color', acolor) row :tag('td') :attr('rowspan', args['aspan' .. v]) :wikitext(args['alliance' .. v]) row :tag('td') :css('background-color', color) row :tag('td') :wikitext(args['party' .. v]) elseif args['alliance' .. v] then row :tag('td') :css('background-color', acolor) row :tag('td') :attr('colspan', '3') :wikitext(args['alliance' .. v]) elseif args['atotal' .. v] or args['atotalnv' .. v] then row :css('font-style', 'italic') :tag('td') :attr('colspan', '2') :wikitext('Total') else -- create the empty color cell row :css('background-color', args['acolor' .. v]) :tag('td') :css('background-color', color) -- add the rest of the row if args['dsv'] then row :tag('td') :wikitext(args['party' .. v]) row :tag('td') :wikitext(args['cand' .. v]) end if headings['cand'] and not args['dsv'] then row :tag('td') :wikitext(args['cand' .. v]) if headings['vp'] then row :tag('td') :wikitext(args['vp' .. v]) end end if headings['party'] and not args['dsv'] then row :tag('td') :wikitext(args['party' .. v]) end end if 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], valid[1])) 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], valid[1])) else row:tag('td') :attr('rowspan', args['vspan' .. v]) :wikitext end elseif has_votes and not headings['sw'] and not has_seats and not has_rspan or args['invalid'] and not headings['sw'] and not has_seats and not has_rspan or args['totalvotes'] and not headings['sw'] and not has_seats and not has_rspan or args['electorate'] and not headings['sw'] and not has_seats and not has_rspan or args['turnout'] and not headings['sw'] and not has_seats and not has_rspan or has_seats and args['seats' .. v] and not args['votes' .. v] and not args['ivotes' .. v] and not has_rspan or has_votes and not args['votes' .. v] and not args['ivotes' .. v] and not args['ipct' .. v] and not args['apct' .. v] and not args['atotal' .. v] and args['row' .. v] and args['seats' .. v] and headings ['alliance'] and not headings['sw'] or args['atotalnv' .. v] and args['aseats' .. v] and not has_rspan then row:tag('td') :attr('colspan', 2) elseif has_seats and not args['seats' .. v] and not headings['sw'] and not has_rspan or has_votes and headings['sw'] and not has_seats and not has_rspan then row:tag('td') :attr('colspan', 3) elseif has_seats and headings['sw'] and not has_rspan then row:tag('td') :attr('colspan', 4) end if headings['sw'] and args['votes' .. v] or headings['sw'] and args['ivotes' .. v] or headings['sw'] and args['atotal' .. v] then row :tag('td') :css('text-align', 'right') :wikitext(args['sw' .. v]) end if headings['seats'] and not args['dsv'] and not has_seats and rounds < 2 or has_seats and args['seats' .. v] or has_seats and args['votes' .. v] or has_seats and args['iseats' .. v] or has_seats and args['aseats' .. v] then if args['iseats' .. v] or args['aseats' .. v] then row :tag('td') :css('font-style', 'italic') :css('text-align', 'right') :wikitext(args['iseats' .. v] or args['aseats' .. v]) elseif args['seats' .. v] or headings['seats'] and not has_sspan then row :tag('td') :attr('rowspan', args['sspan' .. v]) :css('text-align', 'right') :wikitext(fmt(args['seats' .. v]) or '–') end end if args['votes' .. v .. '_2'] then row:tag('td') :attr('rowspan', args['v2span' .. v]) :css('text-align', 'right') :wikitext(fmt(args['votes' .. v .. '_2']))				row:tag('td') :attr('rowspan', args['v2span' .. v]) :css('text-align', 'right') :wikitext(pct(args['votes' .. v .. '_2'], valid[2])) elseif args['ivotes' .. v .. '_2'] or args ['ipct' .. v.. '_2'] or args['avotes' .. v .. '_2'] then row:tag('td') :attr('rowspan', args['v2span' .. v]) :css('text-align', 'right') :css('font-style', 'italic') :wikitext(fmt(args['ivotes' .. v .. '_2']) or fmt(args['avotes' .. v .. '_2']))				row:tag('td') :attr('rowspan', args['v2span' .. v]) :css('text-align', 'right') :css('font-style', 'italic') :wikitext(args['ipct' .. v .. '_2'] or args['apct' .. v .. '_2'] or pct(args['avotes' .. v .. '_2'], valid[2])) elseif args['invalid2'] and args['seats' .. v .. '_2'] and not has_rspan or args['totalvotes2'] and args['seats' .. v .. '_2'] and not has_rspan or args['electorate2'] and args['seats' .. v .. '_2'] and not has_rspan or args['turnout2'] and args['seats' .. v .. '_2'] and not has_rspan or has_votes and rounds > 1 and args['seats' .. v .. '_2'] and not has_rspan or has_votes and rounds > 1 and not has_seats and not has_rspan or has_seats and not args['votes' .. v .. '_2'] and args['seats' .. v .. '_2'] and not has_rspan or args['atotalnv' .. v] and args['aseats' .. v .. '_2'] and not has_rspan then row:tag('td') :attr('colspan', 2) elseif has_seats and not args['seats' .. v .. '_2'] and not headings['sw'] and not has_rspan then row:tag('td') :attr('colspan', 3) elseif has_seats and headings['sw'] and not has_rspan then row:tag('td') :attr('colspan', 4) end if headings['seats'] and args['dsv'] and not has_sspan or headings['seats'] and rounds > 1 and not has_seats and not has_sspan or args['seats' .. v] and has_sspan and rounds > 1 then row :tag('td') :attr('rowspan', args['sspan' .. v]) :css('text-align', 'right') :wikitext(fmt(args['seats' .. v]) or '–') end if has_sw 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_seats 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_seats 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 headings['st1t'] then row :tag('td') :css('text-align', 'right') :wikitext(args['st1t' .. v] or '–') end if headings['st2t'] then row :tag('td') :css('text-align', 'right') :wikitext(args['st2t' .. v] or '–') end if headings['st3t'] then row :tag('td') :css('text-align', 'right') :wikitext(args['st3t' .. v] or '–') end if headings['st4t'] then row :tag('td') :css('text-align', 'right') :wikitext(args['st4t' .. v] or '–') end if headings['st5t'] then row :tag('td') :css('text-align', 'right') :wikitext(args['st5t' .. v] or '–') end if headings['totseats'] and not args['itotseats' .. v] and not args['atotseats' .. v] then row :tag('td') :css('text-align', 'right') :wikitext(fmt(args['totseats' .. v]) or '–') elseif headings['totseats'] then row :tag('td') :css('text-align', 'right') :css('font-style', 'italic') :wikitext(args['itotseats' .. v] or args['atotseats' .. v]) end if 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['invalid'] or args['invalid2'] or args['totalvotes'] or args['totalvotes2'] or args['electorate'] or args['electorate2'] or args['turnout'] or args['turnout2'] or args['source'] then row = root :tag('tr') :addClass('sortbottom') row :tag('td') :css('background', '#eaecf0') :attr('colspan', cols) end -- valid votes if args['invalid'] or args['invalid2'] 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('background', 'inherit') if args['invalid'] then row :tag('td') :wikitext(fmt(ovalid[1])) :tag('td') :wikitext(pct(ovalid[1], ovalid[1] + invalid[1])) elseif not args['invalid'] then row :tag('td') :wikitext :tag('td') :wikitext end if has_seats and not headings['sw'] then row :tag('td') :wikitext end if has_seats and headings['sw'] and args['validsw'] then row :tag('td') :wikitext(args['validsw']) :tag('td') :wikitext end if has_seats 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(ovalid[2])) :tag('td') :wikitext(pct(ovalid[2], ovalid[2] + invalid[2])) elseif rounds > 1 and not args['invalid2'] then row :tag('td') :wikitext :tag('td') :wikitext end if has_seats and not headings['sw'] then row :tag('td') :wikitext end if has_seats and headings['sw'] and args['validsw2'] then row :tag('td') :wikitext(args['validsw2']) :tag('td') :wikitext end if has_seats and headings['sw'] and not args['validsw2'] then row :tag('td') :attr('colspan', 2) :wikitext end if args['invalidsw'] and not has_sw 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) 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) 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) 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['blank'] then row :tag('th') :wikitext('Invalid votes') :attr('scope', 'row') :attr('colspan', cs) :css('text-align', 'left') :css('font-weight', 'normal') :css('background', 'inherit') else row :tag('th') :wikitext('Invalid/blank votes') :attr('scope', 'row') :attr('colspan', cs) :css('text-align', 'left') :css('font-weight', 'normal') :css('background', 'inherit') end if args['invalid'] then row :tag('td') :wikitext(fmt(invalid[1])) :tag('td') :wikitext(pct(invalid[1], ovalid[1] + invalid[1])) elseif not args['invalid'] then row :tag('td') :wikitext :tag('td') :wikitext end if has_seats and not headings['sw'] then row :tag('td') :wikitext end if has_seats and headings['sw'] and args['invalidsw'] then row :tag('td') :wikitext(args['invalidsw']) :tag('td') :wikitext end if has_seats 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(invalid[2])) :tag('td') :wikitext(pct(invalid[2], ovalid[2] + invalid[2])) elseif rounds > 1 and not args['invalid2'] then row :tag('td') :wikitext :tag('td') :wikitext end if has_seats and not headings['sw'] then row :tag('td') :wikitext end if has_seats and headings['sw'] and args['invalidsw2'] then row :tag('td') :wikitext(args['invalidsw2']) :tag('td') :wikitext end if has_seats and headings['sw'] and not args['invalidsw2'] then row :tag('td') :attr('colspan', 2) :wikitext end if args['invalidsw'] and not has_sw 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) 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) 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('Total votes') :attr('scope', 'row') :attr('colspan', cs) :css('text-align', 'left') :css('background', 'inherit') if not args['totalvotes'] and args['invalid'] then row :tag('td') :wikitext(fmt(ovalid[1] + invalid[1])) :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_seats and not headings['sw'] then row :tag('td') :wikitext end if has_seats and headings['sw'] and args['invalidsw'] then row :tag('td') :wikitext('–') :tag('td') :wikitext end if has_seats 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(ovalid[2] + invalid[2])) :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_seats and not headings['sw'] then row :tag('td') :wikitext end if has_seats and headings['sw'] and args['invalidsw2'] then row :tag('td') :wikitext('–') :tag('td') :wikitext end if has_seats and headings['sw'] and not args['invalidsw2'] then row :tag('td') :attr('colspan', 2) :wikitext end if args['invalidsw'] and not has_sw 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) 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) 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('background', 'inherit') row :tag('td') :wikitext(fmt(electorate[1])) if args['invalid'] and args['electorate'] then row :tag('td') :wikitext(pct(ovalid[1] + invalid[1], electorate[1])) elseif args['totalvotes'] and args['electorate'] then row :tag('td') :wikitext(pct(totalvotes[1], electorate[1])) elseif args['electorate'] then row :tag('td') :wikitext(args.turnout or '–') else row :tag('td') :wikitext(args.turnout) end if has_seats and not headings['sw'] then row :tag('td') :wikitext end if has_seats and headings['sw'] and args['turnoutsw'] then row :tag('td') :wikitext(args['turnoutsw']) :tag('td') :wikitext end if has_seats 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(electorate[2])) if args['invalid2'] and args['electorate2'] then row :tag('td') :wikitext(pct(ovalid[2] + invalid[2], electorate[2])) elseif args['totalvotes2'] and args['electorate2'] then row :tag('td') :wikitext(pct(totalvotes[2], electorate[2])) elseif args['electorate2'] then row :tag('td') :wikitext(args.turnout2 or '–') else row :tag('td') :wikitext(args.turnout2) end if has_seats and not headings['sw'] then row :tag('td') :wikitext end if has_seats and headings['sw'] and args['turnoutsw2'] then row :tag('td') :wikitext(args['turnoutsw2']) :tag('td') :wikitext end if has_seats and headings['sw'] and not args['turnoutsw2'] then row :tag('td') :attr('colspan', 2) :wikitext end end if args['turnoutsw'] and not has_sw 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) 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) 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('background', '#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('background', 'inherit') for k=1, rounds do	row :tag('td') :wikitext(fmt(majority[k])) :tag('td') :wikitext(fmt(majoritypct[k])) 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 = args['resultcolour'] or nil if color == nil then local result = unlink(args['result']) or '' if result ~= '' and mw.title.new('Template:' .. result .. '/meta/color').exists then color = frame:expandTemplate{title = result .. '/meta/color'} end end 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('background', 'inherit') for k=1, rounds do	row :tag('td') :wikitext(fmt(majority2[k])) :tag('td') :wikitext(fmt(majoritypct2[k])) 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 = args['resultcolour'] or nil if color == nil then local result = unlink(args['result2']) or '' if result ~= '' and mw.title.new('Template:' .. result .. '/meta/color').exists then color = frame:expandTemplate{title = result .. '/meta/color'} end end 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