UNPKG

factom-vote

Version:

JS implementation of the Factom voting specification

64 lines (54 loc) 2.2 kB
function computeBinaryVotingWinner(optionsStats, winnerCriteria) { const { winners, maxWeightedOptions } = computeWinners(optionsStats, winnerCriteria); switch (winners.length) { case 0: // The other option wins by default return Object.keys(optionsStats).find(o => !maxWeightedOptions.includes(o)); case 1: return winners[0]; case 2: // Perfect tie 50/50 with no minSupport criteria: no winner return; default: throw new Error('Invalid state'); } } function computeApprovalVotingWinner(optionsStats, winnerCriteria) { const { winners } = computeWinners(optionsStats, winnerCriteria); return winners.length === 1 ? winners[0] : undefined; } function computeWinners(optionsStats, winnerCriteria) { let maxWeight = 0, maxWeightedOptions = []; for (const opt in optionsStats) { const weight = optionsStats[opt].weight; if (weight > maxWeight) { maxWeightedOptions = [opt]; maxWeight = weight; } else if (weight === maxWeight) { maxWeightedOptions.push(opt); } } const minSupportCriteria = (winnerCriteria || {}).minSupport; const winners = maxWeightedOptions.filter(function (opt) { const { minSupport, weightedMinSupport } = getMinSupport(minSupportCriteria, opt); return optionsStats[opt].support >= minSupport && optionsStats[opt].weightedSupport >= weightedMinSupport; }); return { maxWeightedOptions, winners }; } function getMinSupport(minSupportCriteria, opt) { let minSupport = 0, weightedMinSupport = 0; if (minSupportCriteria) { if (minSupportCriteria[opt]) { minSupport = minSupportCriteria[opt].unweighted || 0; weightedMinSupport = minSupportCriteria[opt].weighted || 0; } else if (minSupportCriteria['*']) { minSupport = minSupportCriteria['*'].unweighted || 0; weightedMinSupport = minSupportCriteria['*'].weighted || 0; } } return { minSupport, weightedMinSupport }; } module.exports = { computeBinaryVotingWinner, computeApprovalVotingWinner };