Module:vote table

local export = {}

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

-- This function returns the start date of a vote, in the format of "Dec 9". -- It uses the full page contents as the only parameter. local function startDateFullPage(fullPage)

local result = ""

local startDateFull = string.match(fullPage, "Vote start.-%(UTC%)") local startDateParts = mw.text.split(startDateFull, "Vote start.-: ") local dateString = startDateParts[2] local languageObject = mw.language.new("en") local success, startDate = pcall(languageObject.formatDate, languageObject, "M j", dateString) if success then result = startDate else mw.log('Unparseable "date" in startDateFullPage function of Module:vote_table: ' .. (dateString or startDateFull)) result = startDateFull end

return result

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. local 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

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

local votesText = pageExcerptFullPage(fullPage)

local votes = {}

-- The line is a match, as long as it starts with a "#" but not with "##", "#*" or "#:". So, the line is a vote, not a comment to a vote. -- matchLine (boolean) is true if the line is a match. -- Example of accepted line: # --Example (talk) 03:16, 26 November 2015 (UTC) for line in mw.text.gsplit(votesText, "\n") do		local matchLine = false if string.sub(line, 1, 1) == "#" then matchLine = true local tmp = string.sub(line, 1, 2); if tmp == "##" or tmp == "#*" or tmp == "#:" then matchLine = false end end

if matchLine then

local linkedUser=""

-- Checks all links (in the format: link) in the current line. for link in string.gmatch(line, "%[%[.-%]%]") do

-- The link is a match when it points to a user page or talk page. -- matchUserLink (boolean) is true if the link is a match. local matchUserLink = false if string.sub(link, 1, 7):lower == "[[user:" then					matchUserLink = true				end				if string.sub(link, 1, 12):lower == "[[user talk:" then					matchUserLink = true				end

-- Consider the line: # per User:Example2 --Example (talk) 01:00, 13 September 2015 (UTC) -- It has two links (a user page and a talk page). Only the last link is ultimately used as the parameter "linkedUser". -- Sometimes, a person has only the link to the user page or the talk page, this makes sure their votes are counted too. if matchUserLink then linkedUser = link end end

if linkedUser ~= "" then -- linkedUser = Example (with brackets, link format, sometimes section links) -- unlinkedUser = Example (just the user name, unlike linkedUser) local cutNamespace = mw.text.split(linkedUser, ":", true) local cutAfterPipe = mw.text.split(cutNamespace[2], "|", true) local cutAfterHash = mw.text.split(cutAfterPipe[1], "#", true) local unlinkedUser = cutAfterHash[1] if votes[unlinkedUser] == nil then votes[unlinkedUser] = 1 else votes[unlinkedUser] = votes[unlinkedUser] + 1; end

end end end

return votes

end

function export.createTable(frame) -- 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) list = mw.text.trim(list)

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

-- firstVote -> the first vote to be shown; use 1 to show the first vote (frame.args[1] = 1st template argument) -- lastVote -> the upper limit, how many votes (vote columns) can be shown on the table at most. (frame.args[2] = 2nd template argument) local firstVote = tonumber(frame.args[1]) local lastVote = tonumber(frame.args[2])

-- voteOrder -> key = # of vote in the order, value = vote name -- activeVotes -> key = vote name, value = true by default, unless the vote didn't start or already ended -- voteContents -> key = vote name, value = the contents of each vote page -- voteStatusText -> key = vote name, value = the status text, if it exists, or "" (empty string) -- voteStartDate -> key = vote name, value = the end date, in the format "Dec 9" -- voteEndDate -> key = vote name, value = the end date, in the format "Dec 9" local voteOrder = {} local activeVotes = {} local voteContents = {} local voteStatusText = {} local voteStartDate = {} local voteEndDate = {}

local i = firstVote while i <= lastVote and parts[i * 3] do		local vote = parts[i * 3] table.insert(voteOrder, parts[i * 3]) activeVotes[vote] = true voteContents[vote] = getFullPage("Wiktionary:Votes/" .. vote) voteStatusText[vote] = parts[i * 3 + 1] or "" voteStartDate[vote] = startDateFullPage(voteContents[vote]) voteEndDate[vote] = parts[i * 3 - 1] i = i + 1 end

-- Parse all votes local voteTable = {} for _, vote in pairs(voteOrder) do		voteTable[vote] = countVotesFullPage(voteContents[vote]) end

-- people = the name of each separate people that voted in at least one vote page -- numberOfPeople = number of people that voted in at least one vote page local people = {} local numberOfPeople = 0;

for _, vote in pairs(voteOrder) do		-- count = (key = user name; value = number of votes in the given vote page) -- only the key (user name) is used below. local count = voteTable[vote]

-- We are building the list "people", with all people that voted in at least one vote page. -- alreadyListed = checks if the person is already listed in "people", to avoid repetition. -- When adding a new person in "people", the "numberOfPeople" is increased by 1. for countKey, countValue in pairs(count) do			local alreadyListed = false for peopleKey, peopleValue in pairs(people) do				if countKey == peopleValue then alreadyListed = true end end

if alreadyListed == false then table.insert(people, countKey) numberOfPeople = numberOfPeople + 1 end end end

-- Sorting "people" alphabetically. table.sort(people)

-- Starting the table. (variable "result") local result = " "

return result end

return export