Module:Election results/sandbox

This is an old revision of this page, as edited by Frietjes (talk | contribs) at 16:04, 19 August 2020 (refactoring). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
require('Module:No globals')
local p = {}

function p.main(frame)
	local args = require('Module:Arguments').getArgs(frame)
	local index, headings = {}, {}
	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 electorate = {tonumber(args.electorate) or 0, tonumber(args.electorate2) or tonumber(args.electorate) or 0}
	local row, secondrow
	local tracking = ''
	
	-- helper functions
	local lang = mw.getContentLanguage()
	local function fmt(n)
		return n and lang:formatNum(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 unlink(s)
		if s then
			s = s:match(".-%[%[(.-)|.-%]%].*")
			s = s:match(".-%[%[(.-)%]%].*")
		end
		return s
	end

	-- preprocess the input
	for i = 1, 20 do
		for k, key in ipairs({'cand', 'vp', 'party', 'sc', 'seats'}) do
			if args[key .. i] then
				headings[key] = true
			end
		end
		-- temporary tracking
		for k, key in ipairs({'party', 'cand', 'vp'}) do
			if args[key .. i] then
				if unlink(args[key .. i]) == args[key .. i] then
					tracking = tracking .. '[[Category:Pages using election results with unlinked ' .. key .. '|' .. i .. ']]'
				end
			end
		end
		if args['cand' .. i] or args['party' .. i] then
			table.insert(index, i)
			if args['votes' .. i] then
				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['votes' .. i .. '_2'] then
				rounds = 2
				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
		end
	end

	-- build the table
	local root = mw.html.create('table')
	root
		:addClass('wikitable sortable')
		:tag('caption')
			:wikitext(args.caption)

	local rowspan = (rounds > 1) and 2 or nil
	row = root:tag('tr')
	if headings['cand'] then
		row
			:tag('th')
				:wikitext(headings['vp'] and 'President' or 'Candidate')
				:attr('scope', 'col')
				:attr('colspan', 2)
				:attr('rowspan', rowspan)
		cols = cols + 2
		if headings['vp'] then
			row
				:tag('th')
						:wikitext('Vice president')
						:attr('scope', 'col')
						:attr('rowspan', rowspan)
			cols = cols + 1
		end
		if headings['party'] then
			row
				:tag('th')
				:attr('scope', 'col')
				:attr('rowspan', rowspan)
			cols = cols + 1
		end
	elseif headings['party'] then
		row
			:tag('th')
				:wikitext('Party')
				:attr('scope', 'col')
				:attr('colspan', 2)
				:attr('rowspan', rowspan)
		cols = cols + 2
	end
	if rounds > 1 then
		row
			:tag('th')
				:wikitext('First round')
				:attr('scope', 'col')
				:attr('colspan', 2)
			:tag('th')
				:wikitext('Second round')
				:attr('scope', 'col')
				:attr('colspan', 2)
		secondrow = root:tag('tr')
	else
		secondrow = row
	end
	for k=1,rounds do
		secondrow
			:tag('th')
				:wikitext('Votes')
				:attr('scope', 'col')
			:tag('th')
				:wikitext('%')
				:attr('scope', 'col')
		cols = cols + 2
	end
	if headings['seats'] then
		row
			:tag('th')
				:wikitext('Seats')
				:attr('scope', 'col')
				:attr('rowspan', rowspan)
		cols = cols + 1
	end
	if headings['sc'] then
		row
			:tag('th')
				:wikitext(headings['seats'] and '+/–' or 'Seats±')
				:attr('scope', 'col')
				:attr('rowspan', rowspan)
		cols = cols + 1
	end
	
	local rsuff = (rounds > 1) and {'', '_2'} or {''}
	for i, v in ipairs(index) do
		row = root:tag('tr')

		-- 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
		-- create the empty color cell
		row
			:tag('td')
				:css('background-color', color)

		-- add the rest of the row
		if headings['cand'] then
			row
				:tag('td')
					:wikitext(args['cand' .. v])
			if headings['vp'] then
				row
					:tag('td')
						:wikitext(args['vp' .. v])
			end
		end
		if headings['party'] then
			row
				:tag('td')
					:wikitext(args['party' .. v])
		end
		for kk, suf in ipairs(rsuff) do
			if(args['votes' .. v .. suf]) then
				row:tag('td')
					:css('text-align', 'right')
					:wikitext(fmt(args['votes' .. v .. suf]))
				row:tag('td')
					:css('text-align', 'right')
					:wikitext(pct(args['votes' .. v .. suf], valid[kk]))
			else
				row:tag('td'):attr('colspan', 2)
			end
		end
		if headings['seats'] then
			row
				:tag('td')
					:css('text-align', 'right')
					:wikitext(fmt(args['seats' .. v]))
		end
		if headings['sc'] then
			row
				:tag('td')
					:css('text-align', 'right')
					:wikitext(args['sc' .. v])
		end
	end
	row = root
		:tag('tr')
			:addClass('sortbottom')
			:css('background', '#eaecf0')
			:css('text-align', 'right')
	row
		:tag('td')
			:wikitext('Valid votes')
			:attr('colspan', cols - 2*rounds)
	        :css('text-align', 'left')
	for k=1,rounds do
		row
			:tag('td')
				:wikitext(fmt(valid[k]))
			:tag('td')
				:wikitext(pct(valid[k], valid[k] + invalid[k]))
	end
	row = root:tag('tr')
			:addClass('sortbottom')
			:css('background', '#eaecf0')
			:css('text-align', 'right')
	row
		:tag('td')
			:wikitext('Invalid votes')
			:attr('colspan', cols - 2*rounds)
 	        :css('text-align', 'left')
   	for k=1,rounds do
		row
			:tag('td')
				:wikitext(fmt(invalid[k]))
			:tag('td')
				:wikitext(pct(invalid[k], valid[k] + invalid[k]))
	end
	row = root:tag('tr')
			:addClass('sortbottom')
			:css('font-weight', 'bold')
			:css('background', '#eaecf0')
			:css('text-align', 'right')
	row
		:tag('td')
			:wikitext('Total votes')
			:attr('colspan', cols - 2*rounds)
	        :css('text-align', 'left')
   	for k=1,rounds do
		row
			:tag('td')
				:wikitext(fmt(valid[k] + invalid[k]))
			:tag('td')
				:wikitext(pct(1,1))
	end
	
	row = root:tag('tr')
			:addClass('sortbottom')
			:css('background', '#eaecf0')
			:css('text-align', 'right')
	row:tag('td')
		:wikitext('Registered voters/turnout')
		:attr('colspan', cols - 2*rounds)
 		:css('text-align', 'left')
   	for k=1,rounds do
		row:tag('td')
			:wikitext(fmt(electorate[k]))
		row:tag('td')
			:wikitext(pct(valid[k] + invalid[k], electorate[k]))
	end
	row = root:tag('tr')
			:addClass('sortbottom')
			:css('background', '#eaecf0')
			:css('text-align', 'right')
	row:tag('td')
		:wikitext('Source: ', args.source)
		:attr('colspan', cols)
 		:css('text-align', 'left')
 		
	return tostring(root) .. tracking
end

return p