Module:vote total

local export = {}

-- This function returns the full vote page. function getFullPage (pageName) local pageObject = mw.title.new (pageName) return pageObject:getContent end

-- This function returns the portion of a vote page with the actual votes, without the vote description and the decision. -- It uses the full page contents as theonly parameter. function pageExcerptFullPage (fullPage) -- This is the offset of the match first match of "Enter '# ~' on next blank line", which appears in the first support section. local offset = string.find (fullPage, "Enter '# ~' on next blank line", 1, 1) or 0

-- cutDescription cuts the description at the start of the vote, based on the offset parameter. -- cutDecision cuts the decision at the end of the vote, based on the "==== Decision ====" header. -- result is the part of the page that has the actual list of votes. local cutDescription = string.sub (fullPage, offset, 100000000) local cutDecision = mw.text.split (cutDescription, "==== Decision ====", true) local result = cutDecision[1]

return result end

function normalizeNamespace(namespace) return namespace:lower:gsub("_", " ") end

-- Processes all links that may have a namespace, stores each username in a link -- to a "User" or "User talk" page, and returns the last username encountered, -- or else nil. -- Removes fragments (the part after #) and link text (the part after | if the -- link is piped). -- Consider the text: -- # per User:Example1 --Example2 (talk) 01:00, 13 September 2015 (UTC) -- It has three "User" or "User talk" links. -- The username "Example3" from the last link, talk, -- is returned. -- Sometimes, a person has only the link to the user page or the talk page, -- this makes sure their votes are counted too. function getLastUsername(text) local username for potentialNamespace, potentialUser in text:gmatch("%[%[([%a_ ]+):([^|%[%]#|]+).-%]%]") do		potentialNamespace = normalizeNamespace(potentialNamespace) if potentialNamespace == "user" or potentialNamespace == "user talk" then username = potentialUser end end return username end

assert(	getLastUsername([=[# per User:Example1 --Example2 (talk) 01:00, 13 September 2015 (UTC)]=]),	"Example3")

-- This function returns a variable with a list of all people who voted in the page. function countVotesFullPage (fullPage) local votesText = pageExcerptFullPage (fullPage)

-- Sets not-yet-created fields to 0 when they are indexed. local votes = setmetatable({}, {		__index = function(self, key)			self[key] = 0			return 0		end	})

-- Iterates over all lines that start with a "#" but not with "##", "#*" or -- "#:", which excludes discussion and crossed-out votes. -- Example of accepted line: # --Example (talk) 03:16, 26 November 2015 (UTC) local i	local commentStart while true do		local nextCommentStart -- Get positions of all # at the beginning of a line, not followed by # or * or :. nextCommentStart, i = votesText:find("%f[^\n%z]#[^#*:]", i)		-- Work with the comment that begins with the previous # -- and ends before the current #. -- Remove the current # from the end of the comment. local commentEnd = nextCommentStart and nextCommentStart - 1 -- If # was found in the previous execution of the loop, -- get text between last # and current #. if commentStart then local voteComment = votesText:sub(commentStart, commentEnd) local username -- Look over every line starting with #, possibly followed by # or * or :. -- The first line will have # alone, but the signature -- may be in any of the following lines. for line in voteComment:gmatch("%f[^\n%z]#[^\n]*") do -- Find the first line that ends with a possible date. -- If it has a username, assume that is the person who is -- casting a vote in this vote comment. if line:find "%d%d:%d%d, %d%d? %u%l+ 20%d%d %(UTC%)%s*$" then username = getLastUsername(line) if username then votes[username] = votes[username] + 1 else mw.log("Didn't find username on the following line that ended with a date:\n" .. line) end break end end if not username then mw.log("Didn't find username in\n" .. voteComment) end end if not commentEnd then break end commentStart = commentEnd end

return votes end

function voteParts -- Concerning the page "Wiktionary:Votes/Active": -- pageObject is the page object, -- fullPage is the full contents of the page. local pageObject = mw.title.new ("Wiktionary:Votes/Active") local fullPage = pageObject:getContent

-- startList is the start of the list of votes. -- endList is the end of the list of votes. -- For startList, we locate "{{votes/layout" in the code and add 14. The addition of 14 is because otherwise the "{{votes/layout" would be present in the final result. -- For endList, we locate "}}" in the code and subtract 1. The subtraction of 1 is because otherwise "}" would be present in the final result. local startList = string.find (fullPage, "", 1, 1) endList = endList - 1

-- list is just the list of votes, as a single string. local list = string.sub (fullPage, startList, endList)

-- parts = the list of votes, as an array separated by the "|" in the original text. local parts = mw.text.split (list, "|", true)

return parts end

function export.countSOA local parts = voteParts

-- voteOrder -> key = # of vote in the order, value = vote name -- voteContents -> key = vote name, value = the contents of each vote page local voteOrder = {} local voteContents = {}

-- k%3 == 0 → vote title, without "Wiktionary:Votes/" -- k+1 == the status of the vote, if k%3 -- k-1 == the end date of the vote, if k%3 for k, v in pairs(parts) do		if k%3 == 0 then table.insert(voteOrder, v) voteContents[v] = getFullPage("Wiktionary:Votes/" .. v)		end end

-- SOA = total number of supports, opposes, abstains local SOA = 0;

for k, v in pairs(voteOrder) do		-- count = (key = user name; value = number of votes in the given vote page) local count = countVotesFullPage(voteContents[v])

for countKey, countValue in pairs (count) do			SOA = SOA + countValue end end

return SOA end

function export.countPages local parts = voteParts local voteCount = 0

for k, v in pairs(parts) do		if k%3 == 0 then voteCount = voteCount + 1 end end

return voteCount end

return export