<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://mywikibiz.com/index.php?action=history&amp;feed=atom&amp;title=Module%3ASignpost_poll</id>
	<title>Module:Signpost poll - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://mywikibiz.com/index.php?action=history&amp;feed=atom&amp;title=Module%3ASignpost_poll"/>
	<link rel="alternate" type="text/html" href="https://mywikibiz.com/index.php?title=Module:Signpost_poll&amp;action=history"/>
	<updated>2026-04-17T02:23:23Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.3</generator>
	<entry>
		<id>https://mywikibiz.com/index.php?title=Module:Signpost_poll&amp;diff=479462&amp;oldid=prev</id>
		<title>Zoran: Pywikibot 6.4.0</title>
		<link rel="alternate" type="text/html" href="https://mywikibiz.com/index.php?title=Module:Signpost_poll&amp;diff=479462&amp;oldid=prev"/>
		<updated>2021-07-16T06:03:01Z</updated>

		<summary type="html">&lt;p&gt;Pywikibot 6.4.0&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;-- This module implements polls used in articles of the Signpost.&lt;br /&gt;
&lt;br /&gt;
local CONFIG_MODULE = 'Module:Signpost poll/config'&lt;br /&gt;
&lt;br /&gt;
local yesno = require('Module:Yesno')&lt;br /&gt;
local lang = mw.language.getContentLanguage()&lt;br /&gt;
&lt;br /&gt;
-------------------------------------------------------------------------------&lt;br /&gt;
-- Message method&lt;br /&gt;
-- This method is available in every class, so it is defined separately.&lt;br /&gt;
-------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function message(self, key, params, isPreprocessed)&lt;br /&gt;
	local msg = self.cfg.msg[key]&lt;br /&gt;
	if params and #params &amp;gt; 0 then&lt;br /&gt;
		msg = mw.message.newRawMessage(msg, params):plain()&lt;br /&gt;
	end&lt;br /&gt;
	if isPreprocessed then&lt;br /&gt;
		msg = self.frame:preprocess(msg)&lt;br /&gt;
	end&lt;br /&gt;
	return msg&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-------------------------------------------------------------------------------&lt;br /&gt;
-- Option class&lt;br /&gt;
-------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local Option = {}&lt;br /&gt;
Option.__index = Option&lt;br /&gt;
Option.message = message&lt;br /&gt;
&lt;br /&gt;
function Option.new(t)&lt;br /&gt;
	local self = setmetatable({}, Option)&lt;br /&gt;
	self.cfg = t.cfg&lt;br /&gt;
	self.frame = t.frame&lt;br /&gt;
	self.nOption = t.nOption&lt;br /&gt;
	self.votePage = t.votePage&lt;br /&gt;
	self.preload = t.preload&lt;br /&gt;
	self.text = t.text&lt;br /&gt;
	self.voteText = t.voteText&lt;br /&gt;
	self.color = t.color&lt;br /&gt;
	return self&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Option:getCount()&lt;br /&gt;
	if self.count then&lt;br /&gt;
		return self.count&lt;br /&gt;
	else&lt;br /&gt;
		self.count = mw.getCurrentFrame():expandTemplate{title=&amp;quot;String count&amp;quot;,args={&lt;br /&gt;
			page = self.votePage,&lt;br /&gt;
			search = self:getVoteText(n)&lt;br /&gt;
		}}&lt;br /&gt;
		return self.count&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Option:setVoteTotal(n)&lt;br /&gt;
	self.total = n&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Option:getVoteTotal()&lt;br /&gt;
	return self.total or error('total number of votes has not been set')&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Option:getPercentage()&lt;br /&gt;
	if self.percentage then&lt;br /&gt;
		return self.percentage&lt;br /&gt;
	else&lt;br /&gt;
		self.percentage = self:getCount() / self:getVoteTotal() * 100&lt;br /&gt;
		return self.percentage&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Option:getColor()&lt;br /&gt;
	-- Get the default color for option n&lt;br /&gt;
	if self.color then&lt;br /&gt;
		return self.color&lt;br /&gt;
	end&lt;br /&gt;
	local colors = self.cfg.colors&lt;br /&gt;
	local color = colors[self.nOption]&lt;br /&gt;
	if color then&lt;br /&gt;
		self.color = color&lt;br /&gt;
	else&lt;br /&gt;
		-- Loop to find the length of colors. We can't use the # operator as&lt;br /&gt;
		-- a metatable is set by mw.loadData. This is bad for polls with&lt;br /&gt;
		-- more options than there are colors in the config, as we would loop&lt;br /&gt;
		-- for every single option object. This will likely never be a problem&lt;br /&gt;
		-- in practice, however.&lt;br /&gt;
		local nColors = 0&lt;br /&gt;
		for i in ipairs(colors) do&lt;br /&gt;
			nColors = i&lt;br /&gt;
		end&lt;br /&gt;
		-- colors[nColors] is necessary as Lua arrays are indexed starting at&lt;br /&gt;
		-- 1, and n % self.nColors might sometimes equal 0.&lt;br /&gt;
		self.color = colors[self.nOption % nColors] or colors[nColors]&lt;br /&gt;
	end&lt;br /&gt;
	return self.color&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Option:getVoteText()&lt;br /&gt;
	self.voteText = self.voteText or self:message(&lt;br /&gt;
		'vote-default',&lt;br /&gt;
		{self.nOption},&lt;br /&gt;
		true&lt;br /&gt;
	)&lt;br /&gt;
	return self.voteText&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Option:makeVoteURL()&lt;br /&gt;
	local url = mw.uri.fullUrl(&lt;br /&gt;
		self.votePage,&lt;br /&gt;
		{&lt;br /&gt;
			action = 'edit',&lt;br /&gt;
			section = 'new',&lt;br /&gt;
			nosummary = 'true',&lt;br /&gt;
			preload = self.preload,&lt;br /&gt;
			['preloadparams[]'] = self:getVoteText()&lt;br /&gt;
		}&lt;br /&gt;
	)&lt;br /&gt;
	return tostring(url)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Option:renderButton()&lt;br /&gt;
	local button = mw.html.create('span')&lt;br /&gt;
		:addClass('mw-ui-button mw-ui-progressive')&lt;br /&gt;
		:attr('role', 'button')&lt;br /&gt;
		:attr('aria-disabled', 'false')&lt;br /&gt;
		:wikitext(self.text)&lt;br /&gt;
	local wrapper = mw.html.create('span')&lt;br /&gt;
		:addClass('plainlinks')&lt;br /&gt;
		:css('margin', '0 4px')&lt;br /&gt;
		:wikitext(string.format(&lt;br /&gt;
			'[%s %s]',&lt;br /&gt;
			self:makeVoteURL(),&lt;br /&gt;
			tostring(button)&lt;br /&gt;
		))&lt;br /&gt;
	return wrapper&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Option:renderLegendRow()&lt;br /&gt;
	local legend = mw.html.create('div')&lt;br /&gt;
	legend&lt;br /&gt;
		:css('margin', '4px')&lt;br /&gt;
		:tag('span')&lt;br /&gt;
			:css('display', 'inline-block')&lt;br /&gt;
			:css('width', '1.5em')&lt;br /&gt;
			:css('height', '1.5em')&lt;br /&gt;
			:css('margin', '1px 0')&lt;br /&gt;
			:css('border', '1px solid black')&lt;br /&gt;
			:css('background-color', self:getColor())&lt;br /&gt;
			:css('text-align', 'center')&lt;br /&gt;
			:wikitext('&amp;amp;nbsp;')&lt;br /&gt;
			:done()&lt;br /&gt;
		:wikitext('&amp;amp;nbsp;')&lt;br /&gt;
		:wikitext(self:message('legend-option-text', {&lt;br /&gt;
			self.text,&lt;br /&gt;
			self:getCount(),&lt;br /&gt;
			string.format('%.0f', self:getPercentage())&lt;br /&gt;
		}, true))&lt;br /&gt;
	return legend&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-------------------------------------------------------------------------------&lt;br /&gt;
-- Poll class&lt;br /&gt;
-------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local Poll = {}&lt;br /&gt;
Poll.__index = Poll&lt;br /&gt;
Poll.message = message&lt;br /&gt;
&lt;br /&gt;
function Poll.new(args, cfg, frame)&lt;br /&gt;
	local self = setmetatable({}, Poll)&lt;br /&gt;
	self.cfg = cfg or mw.loadData(CONFIG_MODULE)&lt;br /&gt;
	self.frame = frame or mw.getCurrentFrame()&lt;br /&gt;
&lt;br /&gt;
	-- Set required fields&lt;br /&gt;
	self.question = assert(args.question, self:message('no-question-error'))&lt;br /&gt;
	self.votePage = assert(args.votepage, self:message('no-votepage-error'))&lt;br /&gt;
&lt;br /&gt;
	-- Set optional fields&lt;br /&gt;
	self.headerText = args.header or self:message('header-text')&lt;br /&gt;
	self.icon = args.icon or self:message('icon-default')&lt;br /&gt;
	self.overlay = args.overlay or self:message('overlay-default')&lt;br /&gt;
	self.minimum = tonumber(args.minimum) or self:message('minimum-default')&lt;br /&gt;
	self.expiry = args.expiry&lt;br /&gt;
	self.lineBreak = args['break']&lt;br /&gt;
&lt;br /&gt;
	-- Set options&lt;br /&gt;
	self.options = {}&lt;br /&gt;
	do&lt;br /&gt;
		local preload = self:message('preload-page')&lt;br /&gt;
		local i = 1&lt;br /&gt;
		while true do&lt;br /&gt;
			local key = 'option' .. tostring(i)&lt;br /&gt;
			local text = args[key]&lt;br /&gt;
			if not text then&lt;br /&gt;
				break&lt;br /&gt;
			end&lt;br /&gt;
			table.insert(self.options, Option.new{&lt;br /&gt;
				nOption = i,&lt;br /&gt;
				text = text,&lt;br /&gt;
				voteText = args[key .. 'vote'],&lt;br /&gt;
				color = args[key .. 'color'],&lt;br /&gt;
				cfg = self.cfg,&lt;br /&gt;
				frame = self.frame,&lt;br /&gt;
				votePage = self.votePage,&lt;br /&gt;
				preload = preload&lt;br /&gt;
			})&lt;br /&gt;
			i = i + 1&lt;br /&gt;
		end&lt;br /&gt;
		if #self.options &amp;lt; 2 then&lt;br /&gt;
			error(self:message('not-enough-options-error'))&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Check for duplicate vote text&lt;br /&gt;
	do&lt;br /&gt;
		local votes = {}&lt;br /&gt;
		for option in self:iterateOptions() do&lt;br /&gt;
			if votes[option:getVoteText()] then&lt;br /&gt;
				error(self:message(&lt;br /&gt;
					'duplicate-vote-text-error',&lt;br /&gt;
					{votes[option:getVoteText()], option.nOption},&lt;br /&gt;
					true&lt;br /&gt;
				))&lt;br /&gt;
			else&lt;br /&gt;
				votes[option:getVoteText()] = option.nOption&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Prompt users to create the vote page if it doesn't exist.&lt;br /&gt;
	do&lt;br /&gt;
		local success, votePageContent = pcall(function ()&lt;br /&gt;
			return mw.title.new(self.votePage):getContent()&lt;br /&gt;
		end)&lt;br /&gt;
		if not success or not votePageContent then&lt;br /&gt;
			local createVotePageUrl = mw.uri.fullUrl(&lt;br /&gt;
				self.votePage,&lt;br /&gt;
				{&lt;br /&gt;
					action = 'edit',&lt;br /&gt;
					preload = self:message('vote-page-preload-default'),&lt;br /&gt;
					['preloadparams[]'] = mw.title.getCurrentTitle().prefixedText,&lt;br /&gt;
					summary = self:message('vote-page-create-summary'),&lt;br /&gt;
					editintro = self:message('vote-page-create-editintro')&lt;br /&gt;
				}&lt;br /&gt;
			)&lt;br /&gt;
			error(self:message(&lt;br /&gt;
				'votepage-nonexistent-error',&lt;br /&gt;
				{tostring(createVotePageUrl)}&lt;br /&gt;
			), 0)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Find total number of votes&lt;br /&gt;
	do&lt;br /&gt;
		local total = 0&lt;br /&gt;
		for option in self:iterateOptions() do&lt;br /&gt;
			total = total + option:getCount()&lt;br /&gt;
		end&lt;br /&gt;
		for option in self:iterateOptions() do&lt;br /&gt;
			option:setVoteTotal(total)&lt;br /&gt;
		end&lt;br /&gt;
		self.voteTotal = total&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return self&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Static methods&lt;br /&gt;
&lt;br /&gt;
function Poll.getUnixDate(date)&lt;br /&gt;
	date = lang:formatDate('U', date)&lt;br /&gt;
	return tonumber(date)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Normal methods&lt;br /&gt;
&lt;br /&gt;
function Poll:iterateOptions()&lt;br /&gt;
	local i = 0&lt;br /&gt;
	local n = #self.options&lt;br /&gt;
	return function ()&lt;br /&gt;
		i = i + 1&lt;br /&gt;
		if i &amp;lt;= n then&lt;br /&gt;
			return self.options[i]&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Poll:renderHeader()&lt;br /&gt;
	local headerDiv = mw.html.create('div')&lt;br /&gt;
	headerDiv&lt;br /&gt;
		:css('border-top', '1px solid #CCC')&lt;br /&gt;
		:css('font-family', 'Georgia, Palatino, Palatino Linotype, Times, Times New Roman, serif')&lt;br /&gt;
		:css('color', '#333')&lt;br /&gt;
		:css('padding', '5px 0')&lt;br /&gt;
		:css('line-height', '120%')&lt;br /&gt;
		:wikitext(string.format(&lt;br /&gt;
			'[[File:%s|right|30px|link=]]',&lt;br /&gt;
			self.icon&lt;br /&gt;
		))&lt;br /&gt;
		:tag('span')&lt;br /&gt;
			:css('text-transform', 'uppercase')&lt;br /&gt;
			:css('color', '#999')&lt;br /&gt;
			:css('font-size', '105%')&lt;br /&gt;
			:css('font-weight', 'bold')&lt;br /&gt;
			:wikitext(self.headerText)&lt;br /&gt;
	return headerDiv&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Poll:renderQuestion()&lt;br /&gt;
	local question = mw.html.create('div')&lt;br /&gt;
		:css('margin-top', '10px')&lt;br /&gt;
		:css('margin-bottom', '10px')&lt;br /&gt;
		:css('line-height', '100%')&lt;br /&gt;
		:css('font-size', '95%')&lt;br /&gt;
		:wikitext(self.question)&lt;br /&gt;
	return question&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Poll:renderVisualization()&lt;br /&gt;
	local overlayWidth = '253px'&lt;br /&gt;
	local vzn = mw.html.create('div')&lt;br /&gt;
		:css('height', '250px')&lt;br /&gt;
		:css('border-spacing', '0')&lt;br /&gt;
		:css('width', overlayWidth)&lt;br /&gt;
		:css('margin-left', 'auto')&lt;br /&gt;
		:css('margin-right', 'auto')&lt;br /&gt;
&lt;br /&gt;
	-- Overlay&lt;br /&gt;
	vzn&lt;br /&gt;
		:tag('div')&lt;br /&gt;
			:css('position', 'absolute')&lt;br /&gt;
			:css('z-index', '2')&lt;br /&gt;
			:css('padding', '0')&lt;br /&gt;
			:css('margin', '0')&lt;br /&gt;
			:wikitext(string.format(&lt;br /&gt;
				'[[File:%s|%s|link=]] &amp;amp;nbsp;',&lt;br /&gt;
				self.overlay,&lt;br /&gt;
				overlayWidth&lt;br /&gt;
			))&lt;br /&gt;
&lt;br /&gt;
	-- Option colors&lt;br /&gt;
	for option in self:iterateOptions() do&lt;br /&gt;
		vzn:tag('div')&lt;br /&gt;
			:css('background', option:getColor())&lt;br /&gt;
			:css('padding', '0')&lt;br /&gt;
			:css('margin', '0')&lt;br /&gt;
			:css('width', '250px')&lt;br /&gt;
			:css('height', string.format(&lt;br /&gt;
				'%.3f%%', -- Round to 3 decimal places and add a percent sign&lt;br /&gt;
				option:getPercentage()&lt;br /&gt;
			))&lt;br /&gt;
			:wikitext('&amp;amp;nbsp;')&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return vzn&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Poll:renderLegend()&lt;br /&gt;
	local legend = mw.html.create('div')&lt;br /&gt;
		:css('margin-top', '3px')&lt;br /&gt;
		:css('display', 'flex')&lt;br /&gt;
		:css('justify-content', 'center')&lt;br /&gt;
	local centered = legend:tag('div')&lt;br /&gt;
	for option in self:iterateOptions() do&lt;br /&gt;
		centered:node(option:renderLegendRow())&lt;br /&gt;
	end&lt;br /&gt;
	return legend&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Poll:hasLineBreaks()&lt;br /&gt;
	-- Try to auto-detect whether we should have line breaks&lt;br /&gt;
	if self.lineBreak then&lt;br /&gt;
		return yesno(self.lineBreak) or true&lt;br /&gt;
	end&lt;br /&gt;
	local nOptions = #self.options&lt;br /&gt;
	if nOptions &amp;gt; 3 then&lt;br /&gt;
		return true&lt;br /&gt;
	end&lt;br /&gt;
	local wordCount = 0&lt;br /&gt;
	for option in self:iterateOptions() do&lt;br /&gt;
		wordCount = wordCount + mw.ustring.len(option.text)&lt;br /&gt;
	end&lt;br /&gt;
	if nOptions == 3 then&lt;br /&gt;
		return wordCount &amp;gt;= 12&lt;br /&gt;
	else&lt;br /&gt;
		return wordCount &amp;gt;= 15&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Poll:renderButtons()&lt;br /&gt;
	local hasBreaks = self:hasLineBreaks()&lt;br /&gt;
	local buttons = mw.html.create('div')&lt;br /&gt;
		:css('margin-top', '5px')&lt;br /&gt;
		:css('display', 'flex')&lt;br /&gt;
		:css('justify-content', 'center')&lt;br /&gt;
	local centered = buttons:tag('div')&lt;br /&gt;
	if not hasBreaks then&lt;br /&gt;
		centered:css('text-align', 'center')&lt;br /&gt;
	end&lt;br /&gt;
	for option in self:iterateOptions() do&lt;br /&gt;
		local button&lt;br /&gt;
		if hasBreaks then&lt;br /&gt;
			button = centered:tag('div')&lt;br /&gt;
				:css('margin', '4px 0')&lt;br /&gt;
		else&lt;br /&gt;
			button = centered&lt;br /&gt;
		end&lt;br /&gt;
		button:node(option:renderButton())&lt;br /&gt;
	end&lt;br /&gt;
	return buttons&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Poll:renderWarning(s)&lt;br /&gt;
	local warning = mw.html.create('div')&lt;br /&gt;
	warning&lt;br /&gt;
		:css('line-height', '90%')&lt;br /&gt;
		:css('width', '100%')&lt;br /&gt;
		:css('margin-top', '5px')&lt;br /&gt;
		:css('text-align', 'center')&lt;br /&gt;
		:css('color', 'red')&lt;br /&gt;
		:css('font-size', '85%')&lt;br /&gt;
		:wikitext(s)&lt;br /&gt;
	return warning&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Poll:hasMinimumVoteCount()&lt;br /&gt;
	return self.voteTotal &amp;gt;= self.minimum&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Poll:isOpen()&lt;br /&gt;
	if self.expiry then&lt;br /&gt;
		return self.getUnixDate() &amp;lt; self.getUnixDate(self.expiry)&lt;br /&gt;
	else&lt;br /&gt;
		return true&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Poll:__tostring()&lt;br /&gt;
	local root = mw.html.create('div')&lt;br /&gt;
		:css('width', '270px')&lt;br /&gt;
		:css('float', 'right')&lt;br /&gt;
		:css('clear', 'right')&lt;br /&gt;
		:css('background', 'none')&lt;br /&gt;
		:css('margin-bottom', '10px')&lt;br /&gt;
		:css('margin-left', '10px')&lt;br /&gt;
		:addClass('signpost-sidebar')&lt;br /&gt;
&lt;br /&gt;
	root:node(self:renderHeader())&lt;br /&gt;
	root:node(self:renderQuestion())&lt;br /&gt;
&lt;br /&gt;
	-- Visualization and legend&lt;br /&gt;
	if self:hasMinimumVoteCount() then&lt;br /&gt;
		root:node(self:renderVisualization())&lt;br /&gt;
		root:node(self:renderLegend())&lt;br /&gt;
	else&lt;br /&gt;
		root:node(self:renderWarning(self:message(&lt;br /&gt;
			'not-enough-votes-warning',&lt;br /&gt;
			{self.minimum - self.voteTotal},&lt;br /&gt;
			true&lt;br /&gt;
		)))&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Buttons&lt;br /&gt;
	if self:isOpen() then&lt;br /&gt;
		root:node(self:renderButtons())&lt;br /&gt;
	else&lt;br /&gt;
		root:node(self:renderWarning(self:message('poll-closed-warning')))&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-------------------------------------------------------------------------------&lt;br /&gt;
-- Exports&lt;br /&gt;
-------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
function p._main(args, cfg, frame)&lt;br /&gt;
	return tostring(Poll.new(args, cfg, frame))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main(frame, cfg)&lt;br /&gt;
	cfg = cfg or mw.loadData(CONFIG_MODULE)&lt;br /&gt;
	local args = require('Module:Arguments').getArgs(frame, {&lt;br /&gt;
		wrappers = cfg.wrappers&lt;br /&gt;
	})&lt;br /&gt;
	return p._main(args, cfg, frame)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Zoran</name></author>
	</entry>
</feed>