* Get a data of given precision, assuring the sum of percentages * in valueList is 1. * The largest remainer method is used. * https://en.wikipedia.org/wiki/Largest_remainder_method * * @param {Array. } valueList a list of all data * @param {number} idx index of the data to be processed
(valueList, idx, precision)
| 19020 | * @return {number} percent ranging from 0 to 100 |
| 19021 | */ |
| 19022 | function getPercentWithPrecision(valueList, idx, precision) { |
| 19023 | if (!valueList[idx]) { |
| 19024 | return 0; |
| 19025 | } |
| 19026 | |
| 19027 | var sum = reduce(valueList, function (acc, val) { |
| 19028 | return acc + (isNaN(val) ? 0 : val); |
| 19029 | }, 0); |
| 19030 | if (sum === 0) { |
| 19031 | return 0; |
| 19032 | } |
| 19033 | |
| 19034 | var digits = Math.pow(10, precision); |
| 19035 | var votesPerQuota = map(valueList, function (val) { |
| 19036 | return (isNaN(val) ? 0 : val) / sum * digits * 100; |
| 19037 | }); |
| 19038 | var targetSeats = digits * 100; |
| 19039 | |
| 19040 | var seats = map(votesPerQuota, function (votes) { |
| 19041 | // Assign automatic seats. |
| 19042 | return Math.floor(votes); |
| 19043 | }); |
| 19044 | var currentSum = reduce(seats, function (acc, val) { |
| 19045 | return acc + val; |
| 19046 | }, 0); |
| 19047 | |
| 19048 | var remainder = map(votesPerQuota, function (votes, idx) { |
| 19049 | return votes - seats[idx]; |
| 19050 | }); |
| 19051 | |
| 19052 | // Has remainding votes. |
| 19053 | while (currentSum < targetSeats) { |
| 19054 | // Find next largest remainder. |
| 19055 | var max = Number.NEGATIVE_INFINITY; |
| 19056 | var maxId = null; |
| 19057 | for (var i = 0, len = remainder.length; i < len; ++i) { |
| 19058 | if (remainder[i] > max) { |
| 19059 | max = remainder[i]; |
| 19060 | maxId = i; |
| 19061 | } |
| 19062 | } |
| 19063 | |
| 19064 | // Add a vote to max remainder. |
| 19065 | ++seats[maxId]; |
| 19066 | remainder[maxId] = 0; |
| 19067 | ++currentSum; |
| 19068 | } |
| 19069 | |
| 19070 | return seats[idx] / digits; |
| 19071 | } |
| 19072 | |
| 19073 | // Number.MAX_SAFE_INTEGER, ie do not support. |
| 19074 |
no test coverage detected