Module:vote total
Appearance
- The following documentation is located at Module:vote total/documentation. [edit]
- Useful links: subpage list • links • transclusions • testcases • sandbox
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 '# {{support}} ~~~~' on next blank line", which appears in the first support section.
local offset = string.find (fullPage, "Enter '# {{support}} ~~~~' 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:
-- # {{support}} per [[User:Example1]] --[[User:Example2|Example2]] ([[User talk:Example3#Fragment|talk]]) 01:00, 13 September 2015 (UTC)
-- It has three "User" or "User talk" links.
-- The username "Example3" from the last link, [[User talk:Example3#Fragment|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([=[# {{support}} per [[User:Example1]] --[[User:Example2|Example2]] ([[User talk:Example3#Fragment|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: # {{support}} --[[User:Example|Example]] ([[User talk: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, "{{votes/layout", 1, 1)
startList = startList + 14
local endList = 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