require('strict')local p = ;local political_party = require('Module:Political party')
local LANG = 'en'local FALLBACK_LANGS =
--Properties shorthands local P_COUNTRY = 'P17'local P_MEMBER_OF_PARTY = 'P102'local P_FOLLOWS = 'P155'local P_FOLLOWED_BY = 'P156'local P_HAS_PARTS = 'P527'local P_PART_OF = 'P361'local P_COLOR = 'P465'local P_APPLIES_TO_PART = 'P518'local P_POINT_IN_TIME = 'P585'local P_CANDIDATE = 'P726'local P_SUCCESSFUL_CANDIDATE = 'P991'local P_VOTES_RECEIVED = 'P1111'local P_REPLACED_BY = 'P1366'local P_SEATS = 'P1410'local P_TOTAL_VALID_VOTES = 'P1697'local P_SHORT_NAME = 'P1813'local P_ELIGIBLE_VOTERS = 'P1867'local P_BALLOTS_CAST = 'P1868'local P_NAME = 'P2561'local P_OBJECT_HAS_ROLE = 'P3831'local P_CANDIDATE_NUMBER = '4243'local P_SPOILT_VOTES = 'P5044'local P_BLANK_VOTES = 'P5045'
--Get a best ranking statement value from "item" with the property "property". The value is returned through the function "typefunc". -- Function copied from elsewherelocal function getStatementValue(item, property, typefunc) local statements = mw.wikibase.getBestStatements(item, property) if statements[1] and statements[1].mainsnak.snaktype
local function getStatementQualifier(item, property, qualifier, typefunc) local statements = mw.wikibase.getBestStatements(item, property) if statements[1] and statements[1].qualifiers and statements[1].qualifiers[qualifier] and statements[1].qualifiers[qualifier][1] then return typefunc(statements[1].qualifiers[qualifier][1].datavalue.value) endend
--The "typefunc"s - A series of functions that extract the wanted information from a statement value depending on the value type. local function getAmount(value) return tonumber(value.amount) endlocal function getString(value) return value endlocal function getItem(value) return value.id endlocal function getTimestamp(value) return value.time end
-- Finds the text value of a given property in the given languagelocal function getValueFromLanguage(qid, property, lang) local statement = mw.wikibase.getBestStatements(qid, property) for i, v in ipairs(statement) do if v.mainsnak.datavalue.value.language
'mul' then return v.mainsnak.datavalue.value.text end endend
local function getPartyColor(qid, articleTitle) local color = getStatementValue(qid, P_COLOR, getString) if color then return '#'..color end if articleTitle
local function sortParties(listParties) local function comparePartyByVotes(partyA, partyB) if partyB.qid
'Q86630688' then return false elseif (partyA.votes1 or 0) > (partyB.votes1 or 0) then -- compare votes return true elseif (partyA.votes1 or 0) < (partyB.votes1 or 0) then return false elseif (partyA.seats or 0) > (partyB.seats or 0) then -- compare seats return true elseif (partyA.seats or 0) < (partyB.seats or 0) then return false elseif (partyA.number or 0) < (partyB.number or 0) then -- compare electoral numbers (comparisons reversed, smaller numbers first) return true elseif (partyA.number or 0) > (partyB.number or 0) then return false elseif (partyA.candidateName or partyA.partyArticle or partyA.partyName or ) < (partyB.candidateName or partyB.partyArticle or partyB.partyName or ) then -- compare candidate names (comparisons reversed, first letters first) return true elseif (partyA.candidateName or partyA.partyArticle or partyA.partyName or ) > (partyB.candidateName or partyB.partyArticle or partyB.partyName or ) then return false else return ((partyA.seats or 0) > (partyB.seats or 0)) end end table.sort(listParties, comparePartyByVotes)end
local function formatWikilink_simple(link, displaytext) return ''..displaytext..''end
local function getAndFormatInterlanguageLinks(qid) local fallbackLinks = for _, language in ipairs(FALLBACK_LANGS) do local sitelink = mw.wikibase.getSitelink(qid, language..'wiki') if sitelink then fallbackLinks[#fallbackLinks+1] = formatWikilink_simple(':'..language..':'..sitelink, language) end end if #fallbackLinks
local function formatWikilink(link, displaytext, qid) if link then if displaytext then return ''..displaytext..'' else return ''..link..'' end else if displaytext then return displaytext..getAndFormatInterlanguageLinks(qid) else return ''..getAndFormatInterlanguageLinks(qid) end endend
local function fetchCandidacyData_party(partyQid) local data = data.candidacyType = 'party' -- Get party qid data.partyQid = partyQid -- Get party article local partyArticle, label partyArticle = mw.wikibase.getSitelink(partyQid) if not partyArticle then label = mw.wikibase.getLabel(partyQid) end data.partyArticle = partyArticle -- Get party name data.partyName = getValueFromLanguage(partyQid, P_NAME, LANG) or label return dataend
local function fetchCandidacyData_partyShort(partyQid) local data = -- Get party data.partyQid = partyQid if not data.partyQid then return data end data.partyArticle = mw.wikibase.getSitelink(data.partyQid) data.partyName = getValueFromLanguage(data.partyQid, P_SHORT_NAME, LANG) return dataend
local function fetchCandidacyData_candidate(candidateQid) local data = data.candidacyType = 'candidate' data.candidateQid = candidateQid -- Get article name local candidateArticle, label data.candidateArticle = mw.wikibase.getSitelink(candidateQid) data.candidateName = mw.wikibase.getLabel(candidateQid) return dataend
-- For a given candidacy: gets their name, article link, party shortlink, and colorlocal function fetchCandidacyData(qid, candidacyType) if candidacyType
'candidate' then return fetchCandidacyData_candidate(qid) else error('candidacyType not specified') endend
-- Returns the candidacy qid from a candidacy statementlocal function getCandidacyQidFromStatement(candidacyStatement, candidacyType, doGroupByParty) if doGroupByParty then if candidacyStatement.qualifiers[P_MEMBER_OF_PARTY] then return candidacyStatement.qualifiers[P_MEMBER_OF_PARTY][1].datavalue.value.id end end return candidacyStatement.mainsnak.datavalue.value.idend
-- function internal to findCandidacyIndexlocal function findCandidacyIndex_finder(listParties, partyQid) local finalPartyIndex = nil for curPartyindex, curParty in ipairs(listParties) do if curParty.qid
-- Returns the index of a candidacy in a list given its qid. If it is not present and doCreate is true, creates an index for itlocal function findCandidacyIndex(listCandidacies, candidacyQid, candidacyType, doCreate) local candidacyIndex = findCandidacyIndex_finder(listCandidacies, candidacyQid) if not doCreate then return candidacyIndex end if not candidacyIndex then if candidacyType
'candidate' then table.insert(listCandidacies,) else error('candidacyType not specified') end candidacyIndex = #listCandidacies end return candidacyIndexend
-- Returns a table with data from the candidacy's statementlocal function addCandidacyDataFromStatement(candidacyData, statement, candidacyType, round, doPrevious, isWinning) local roundKey if round then roundKey = tostring(round) else roundKey = '1' end if doPrevious then if not candidacyData.prevVotes then candidacyData.prevVotes = 0 end if statement.qualifiers[P_VOTES_RECEIVED] then candidacyData.prevVotes = candidacyData.prevVotes + getAmount(statement.qualifiers[P_VOTES_RECEIVED][1].datavalue.value) end if not candidacyData.prevSeats then candidacyData.prevSeats = 0 end if statement.qualifiers[P_SEATS] then candidacyData.prevSeats = candidacyData.prevSeats + getAmount(statement.qualifiers[P_SEATS][1].datavalue.value) end return candidacyData end if isWinning then candidacyData.winning = round end if not statement.qualifiers then return candidacyData end if statement.qualifiers[P_VOTES_RECEIVED] then if not candidacyData['votes'..roundKey] then candidacyData['votes'..roundKey] = 0 end candidacyData['votes'..roundKey] = candidacyData['votes'..roundKey] + getAmount(statement.qualifiers[P_VOTES_RECEIVED][1].datavalue.value) end if statement.qualifiers[P_SEATS] then if not candidacyData.seats then candidacyData.seats = 0 end candidacyData.seats = candidacyData.seats + getAmount(statement.qualifiers[P_SEATS][1].datavalue.value) end if statement.qualifiers[P_MEMBER_OF_PARTY] then candidacyData.partyQid = getItem(statement.qualifiers[P_MEMBER_OF_PARTY][1].datavalue.value) end if statement.qualifiers[P_OBJECT_HAS_ROLE] and getItem(statement.qualifiers[P_OBJECT_HAS_ROLE][1].datavalue.value)
local function findPartyPredecessorOverride(listParties, partyQid, partyIndex) for tempIndex, tempParty in ipairs(listParties) do if tempParty.predecessors then for _, tempPredecessor in ipairs(tempParty.predecessors) do if tempPredecessor
-- function internal to insertCandidacyInListlocal function insertCandidacyInList_previous(listCandidacies, candidacyStatement, candidacyType, candidacyQid) local candidacyIndex = findCandidacyIndex(listCandidacies, candidacyQid, candidacyType, false) candidacyIndex = findPartyPredecessorOverride(listCandidacies, candidacyQid, candidacyIndex) if not candidacyIndex then candidacyIndex = findCandidacyIndex(listCandidacies, getStatementValue(candidacyQid, P_REPLACED_BY, getItem), candidacyType, false) end if candidacyIndex then listCandidacies[candidacyIndex] = addCandidacyDataFromStatement(listCandidacies[candidacyIndex], candidacyStatement, candidacyType, 1, true) end return listCandidaciesend
-- Inserts a candidacy in the list of candidacieslocal function insertCandidacyInList(listCandidacies, candidacyStatement, candidacyType, round, doPrevious, doGroupByParty, isWinning) local candidacyQid = getCandidacyQidFromStatement(candidacyStatement, candidacyType, doGroupByParty) if doPrevious then return insertCandidacyInList_previous(listCandidacies, candidacyStatement, candidacyType, candidacyQid) end local candidacyIndex = findCandidacyIndex(listCandidacies, candidacyQid, candidacyType, true) listCandidacies[candidacyIndex] = addCandidacyDataFromStatement(listCandidacies[candidacyIndex], candidacyStatement, candidacyType, round, false, isWinning) return listCandidaciesend
local function addPartyPredecessorsByComponents(listParties) for partyIndex, partyData in ipairs(listParties) do local allParts = mw.wikibase.getAllStatements(partyData.qid, P_HAS_PARTS) for _, predecessorStatement in ipairs(allParts) do if not partyData.predecessors then partyData.predecessors = end table.insert(partyData.predecessors, getItem(predecessorStatement.mainsnak.datavalue.value)) end listParties[partyIndex] = partyData end return listPartiesend
-- Retrieves the list of parties and sorts it by votes/seatslocal function getCandidaciesDataFromElection(roundsQidsList, candidacyType, previousQid, doGroupByParty) local listCandidacies = -- For each round for round, roundQid in ipairs(roundsQidsList) do -- For each candidate local allStatementsInElection = mw.wikibase.getAllStatements(roundQid, P_CANDIDATE) for _, candidacyStatement in ipairs(allStatementsInElection) do insertCandidacyInList(listCandidacies, candidacyStatement, candidacyType, round, false, doGroupByParty) end local allWinningStatementsInElection = mw.wikibase.getAllStatements(roundQid, P_SUCCESSFUL_CANDIDATE) for _, winningStatement in ipairs(allWinningStatementsInElection) do insertCandidacyInList(listCandidacies, winningStatement, candidacyType, round, false, false, true) end end -- For each party in the previous election if previousQid then listCandidacies = addPartyPredecessorsByComponents(listCandidacies) local allStatementsPrevElection = mw.wikibase.getAllStatements(previousQid, P_CANDIDATE) for _, partyStatement in ipairs(allStatementsPrevElection) do insertCandidacyInList(listCandidacies, partyStatement, 'party', 1, true, doGroupByParty) end end return listCandidaciesend
local function getAllCandidaciesData(roundsQidsList, candidacyType, previousQid, partyNameOverrides, doGroupByParty) local candidaciesData = getCandidaciesDataFromElection(roundsQidsList, candidacyType, previousQid, doGroupByParty) for candidacyIndex, candidacyData in ipairs(candidaciesData) do local fetchedCandidacyData = fetchCandidacyData(candidacyData.qid, candidacyType) if candidacyType
local function getElectionSitelink(qid) local articleTitle = mw.wikibase.getSitelink(qid) local supersetElectionQid = getStatementValue(qid, P_PART_OF, getItem) while (not articleTitle) or supersetElectionQid do qid = supersetElectionQid supersetElectionQid = getStatementValue(qid, P_PART_OF, getItem) articleTitle = mw.wikibase.getSitelink(qid) end return articleTitleend
local function filterArgs(args, filter) local matched = for k, v in pairs(args) do if string.match(k, filter) then matched[k] = v end end return matchedend
local function getYear(timestamp) return tonumber(string.match(timestamp, '%+(%d%d%d%d)%-%d%d%-%d%dT%d%d:%d%d:%d%d'))end
local function getReferences(electionQid) local allReferences = local function getReferenceIndex(allReferences, reference) local url = reference.snaks.P854[1].datavalue.value for i, curRef in ipairs(allReferences) do if curRef.url
for _, property in ipairs do for _, statement in ipairs(mw.wikibase.getBestStatements(electionQid, property)) do if statement.references then for _, reference in ipairs(statement.references) do addReference(allReferences, reference) end end end end return allReferencesend
local function round(n) local quotient, remainder = math.modf(n) if remainder >= 0.5 then return quotient+1 else return quotient endend
local function getElectionStatistics(qid, fallbackQid) local statistics if fallbackQid then -- fallbackQid is used to handle the fact data can be in the main item or in a separate "first round" item statistics = getElectionStatistics(fallbackQid) else statistics = end if not qid then return end statistics.eligibleVoters = getStatementValue(qid, P_ELIGIBLE_VOTERS, getAmount) or statistics.eligibleVoters statistics.totalBallots = getStatementValue(qid, P_BALLOTS_CAST, getAmount) or statistics.totalBallots statistics.invalidBallots = getStatementQualifier(qid, P_BALLOTS_CAST, P_SPOILT_VOTES, getAmount) or statistics.invalidBallots statistics.blankBallots = getStatementQualifier(qid, P_BALLOTS_CAST, P_BLANK_VOTES, getAmount) or statistics.blankBallots statistics.invalidVotes = getStatementValue(qid, P_SPOILT_VOTES, getAmount) or statistics.invalidVotes statistics.blankVotes = getStatementValue(qid, P_BLANK_VOTES, getAmount) or statistics.blankVotes statistics.validVotes = getStatementValue(qid, P_TOTAL_VALID_VOTES, getAmount) or statistics.validVotes statistics.validBallots = (statistics.totalBallots or 0) - (statistics.invalidBallots or 0) - (statistics.blankBallots or 0) statistics.totalVotes = (statistics.validVotes or 0) + (statistics.invalidVotes or 0) + (statistics.blankVotes or 0) statistics.magnitude = round(statistics.totalVotes / statistics.validBallots) return statisticsend
local function getRounds(electionQid) local rounds = for _,partStatement in ipairs(mw.wikibase.getAllStatements(electionQid, P_HAS_PARTS)) do local roundQid = partStatement.mainsnak.datavalue.value.id local roundNumber = partStatement.qualifiers.P1545[1].datavalue.value rounds[tonumber(roundNumber)] = roundQid end if rounds
local function getSeatsTotals(partiesData) local totalSeats = 0 local totalSeatsChange = 0 for _, partyData in ipairs(partiesData) do totalSeats = totalSeats + (partyData.seats or 0) totalSeatsChange = totalSeatsChange + (partyData.seats or 0) - (partyData.prevSeats or 0) end return totalSeats, totalSeatsChangeend
-- Formatting functions (some copied from Module:Election_results)local lang = mw.getContentLanguagelocal function fmt(n) return n and tonumber(n) and lang:formatNum(tonumber(n)) or nilend
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 formatMultiplier(n, d) local n, d = tonumber(n), tonumber(d) if (not n) or (not d) or d
local function diff(n, prevN) if not n then return ' - ' elseif not prevN then return "New" end n, prevN = tonumber(n), tonumber(prevN) if n > prevN then return '+'..tostring(n-prevN) elseif prevN > n then return '−'..tostring(prevN-n) else return '±0' endend
local function diffPct(n, d, prevN, prevD) if not n or not d or not prevD then return ' - ' elseif not prevN then return "New" end n = tonumber(n) / tonumber(d) prevN = tonumber(prevN) / tonumber(prevD) if n > prevN then return '+'..string.format('%.2f', (n - prevN) * 100) elseif prevN > n then return '−'..string.format('%.2f', (prevN - n) * 100) else return '±0.00' endend
local function diffKey(n, prevN) if (not prevN) then return n end return n - prevNend
local function diffKeyPct(n, d, prevN, prevD) if not n or not d or not prevD then return nil end n = tonumber(n) / tonumber(d) if not prevN then return n end prevN = tonumber(prevN) / tonumber(prevD) return n - prevNend
--Table-generating functions
local function beginTable(classes, electionQid) local root = mw.html.create('span') root:attr('id', electionQid..'_resultsTable') local tab = root:tag('table') tab:addClass(classes) local tableCaption = tab:tag('caption') local caption = 'Results of the ' .. mw.wikibase.getLabel(electionQid) local previousElectionQid = getStatementValue(electionQid, P_FOLLOWS, getItem) local nextElectionQid = getStatementValue(electionQid, P_FOLLOWED_BY, getItem) if previousElectionQid then caption = '← ' .. caption end if nextElectionQid then caption = caption .. ' →' end tableCaption:wikitext(caption) tableCaption:done tab:done return root, tabend
local function addHeaderCell(row, wikitext, colspan, rowspan, dataSortType) local cell = row:tag('th') cell:wikitext(wikitext) cell:attr('scope', 'col') if colspan then cell:attr('colspan', tostring(colspan)) end if rowspan then cell:attr('rowspan', tostring(rowspan)) end if dataSortType then cell:attr('data-sort-type', dataSortType) end cell:doneend
local function addCell(row, wikitext, align, colspan, isBold, sortValue) local cell = row:tag('td') if align then cell:css('text-align', align) end if colspan then cell:attr('colspan', tostring(colspan)) end if isBold then cell:css('font-weight', 'bold') end if sortValue then cell:attr('data-sort-value', sortValue) end cell:wikitext(wikitext) cell:doneend
local function addEmptyCell(row, colspan) local cell = row:tag('td') if colspan then cell:attr('colspan', tostring(colspan)) end cell:css('border', 'none') cell:doneend
local function addColorCell(row, color) local cell = row:tag('td') cell:css('width', '0px') cell:css('background-color', color) cell:doneend
local function fillDiagramCell(diagramCell, wikitext, colspan) diagramCell:wikitext(wikitext) diagramCell:css('text-align', 'center') diagramCell:css('background', '#F8F9FA') diagramCell:attr('colspan', colspan) diagramCell:doneend
local function addStatRow(root, rowTitle, titleColspan, statisticsTables, statistic, fractionNumerator, fractionDenominator, doMakeBold, doUseMultiplier) local isStatisticPresent for _, roundStatistics in ipairs(statisticsTables) do -- Check if the statistic is even present if roundStatistics[statistic] then isStatisticPresent = true break end end local row if isStatisticPresent then row = root:tag('tr') row:addClass('sortbottom') if doMakeBold then row:css('font-weight', 'bold') end addCell(row, rowTitle, 'left', titleColspan) for _,roundStatistics in ipairs(statisticsTables) do if roundStatistics[statistic] then addCell(row, fmt(roundStatistics[statistic]), 'right') if doUseMultiplier then addCell(row, formatMultiplier(roundStatistics[fractionNumerator], roundStatistics[fractionDenominator] or 1), 'right') else addCell(row, pct(roundStatistics[fractionNumerator], roundStatistics[fractionDenominator]), 'right') end end end end return rowend
local function addReference(refsCell, ref) local r = refsCell:wikitext(mw.getCurrentFrame:extensionTag ) return rend
local function formatReferencesRow(root, references, electionQid, cols, hasIncumbent) -- References and wikidata link row local row = root:tag('tr') row:addClass('sortbottom') row:css('font-size', '90%') local refsCell = row:tag('td') refsCell:wikitext('See on Wikidata – See template') -- @ todo update link when publishing refsCell:attr('colspan', cols) if #references > 0 then refsCell:wikitext(' – Sources') for _, ref in ipairs(references) do addReference(refsCell, ref) end end --}}, but not sure it will stay refsCell:wikitext(' – * incumbent') endend
local function checkElectionProperty(candidaciesData, property) for _,candidacy in ipairs(candidaciesData) do if candidacy[property] and candidacy[property] ~= 0 then return true end end return falseend
local function getElectionProperties(candidaciesData) local properties = if checkElectionProperty(candidaciesData, 'partyQid') then properties.party = true end if checkElectionProperty(candidaciesData, 'seats') then properties.seats = true end if checkElectionProperty(candidaciesData, 'votes1') then properties.round1 = true end if checkElectionProperty(candidaciesData, 'votes2') then properties.round2 = true end if checkElectionProperty(candidaciesData, 'prevVotes') or checkElectionProperty(candidaciesData, 'prevSeats') then properties.previousElection = true end return propertiesend
local function getSumOfVotes(candidaciesData, round) local total = 0 local hasVotes = false for _,candidacy in ipairs(candidaciesData) do if candidacy['votes'..round] then hasVotes = true end total = total + (candidacy['votes'..round] or 0) end if hasVotes then return total endend
--Main functions
function p._ch_proportional(args) local electionQid = args.qid or args.election or args[1] local previousElectionQid = getStatementValue(electionQid, P_FOLLOWS, getItem) local doGroupByParty = args.groupByParty or false local cols = 0 local year = getYear(getStatementValue(electionQid, P_POINT_IN_TIME, getTimestamp)) local totalVotes = getStatementValue(electionQid, P_TOTAL_VALID_VOTES, getAmount) local statistics = getElectionStatistics(electionQid) statistics.validVotes = statistics.validVotes or totalVotes mw.logObject('statistics') local prevTotalVotes if previousElectionQid then prevTotalVotes = getStatementValue(previousElectionQid, P_TOTAL_VALID_VOTES, getAmount) end local references = getReferences(electionQid) local rootSpan, root = beginTable('wikitable sortable', electionQid) -- Fetch parties data local partyNameOverrides = filterArgs(args, 'name_override_Q%d+') local partiesData = getAllCandidaciesData('party', previousElectionQid, partyNameOverrides, doGroupByParty) local totalSeats, totalSeatsChange = getSeatsTotals(partiesData) mw.logObject(partiesData) if #partiesData
-- Table header local headerRow = root:tag('tr') addHeaderCell(headerRow, (args.partytitle or 'Party'), 2) if properties.round1 then addHeaderCell(headerRow, 'Votes') addHeaderCell(headerRow, '%') end if properties.previousElection and properties.round1 then addHeaderCell(headerRow, '+/−', nil, nil, 'number') end if properties.seats then addHeaderCell(headerRow, 'Seats') end if properties.previousElection and properties.seats then addHeaderCell(headerRow, '+/−', nil, nil, 'number') end cols = cols + 5 if properties.previousElection then cols = cols + 2 end if diagramCell then fillDiagramCell(diagramCell, (args['image'] or require('Module:Sandbox/Julio974fr/parliament_diagram').makeParliamentDiagram(partiesData, year)), cols ) end -- Get parties list and make the rows for _, party in ipairs(partiesData) do local row = root:tag('tr') if party.qid
function p._ch_majoritarian(args) local electionQid = args.qid or args.election or args[1] local cols = 0 local year = getYear(getStatementValue(electionQid, P_POINT_IN_TIME, getTimestamp)) local hasIncumbent = false local references = getReferences(electionQid) local roundsQid = getRounds(electionQid) local firstRoundQid = roundsQid[1] or electionQid local secondRoundQid = roundsQid[2] local statistics = getElectionStatistics(electionQid, firstRoundQid) local statistics2 = getElectionStatistics(secondRoundQid) mw.logObject('statistics') local rootSpan, root = beginTable('wikitable sortable', electionQid) -- Fetch parties data local partyNameOverrides = filterArgs(args, 'name_override_Q%d+') local candidatesData = getAllCandidaciesData('candidate', nil, partyNameOverrides, nil) mw.logObject(candidatesData) statistics.validVotes = statistics.validVotes or getSumOfVotes(candidatesData, 1) statistics2.validVotes = statistics2.validVotes or getSumOfVotes(candidatesData, 2) if #candidatesData
-- Table header local headerRow = root:tag('tr') if secondRoundQid then -- not using properties.round2 cause it may be useful to show second-round qualifications later on (@todo Add candidate qualifications without votes) local secondHeaderRow = root:tag('tr') addHeaderCell(headerRow, 'Candidate', 2, 2) if properties.party then addHeaderCell(headerRow, (args.partytitle or 'Party'), 1, 2) end addHeaderCell(headerRow, 'First round', 2) addHeaderCell(headerRow, 'Second round', 2) addHeaderCell(secondHeaderRow, 'Votes') addHeaderCell(secondHeaderRow, '%') addHeaderCell(secondHeaderRow, 'Votes') addHeaderCell(secondHeaderRow, '%') cols = cols+7 else -- If no results yet addHeaderCell(headerRow, 'Candidate', 2) if properties.party then addHeaderCell(headerRow, (args.partytitle or 'Party')) end cols = cols+3 if properties.round1 then addHeaderCell(headerRow, 'Votes') addHeaderCell(headerRow, '%') cols = cols+2 end end -- Get parties list and make the rows for _, candidate in ipairs(candidatesData) do local row = root:tag('tr') if candidate.isIncumbent then candidate.candidateWikilink = candidate.candidateWikilink .. ' inc.' hasIncumbent = true end if candidate.qid
1)) addCell(row, pct(candidate.votes1, (statistics.validVotes/statistics.magnitude)), 'right', 1, (candidate.winning
2)) addCell(row, pct(candidate.votes2, (statistics2.validVotes/statistics2.magnitude)), 'right', 1, (candidate.winning
--Wrappers
function p.ch_proportional(frame) -- Initialise and populate variables local getArgs = require("Module:Arguments").getArgs local args = getArgs(frame) return p._ch_proportional(args)end
function p.ch_majoritarian(frame) -- Initialize and populate variables local getArgs = require("Module:Arguments").getArgs local args = getArgs(frame) return p._ch_majoritarian(args)end
return p