FIX: use an algorithm that doesn't re-order percentages when rounding them up to 100% in single choice polls

This commit is contained in:
Régis Hanol 2015-11-25 00:14:24 +01:00
parent 434deb1bd3
commit 68a44a1d59
2 changed files with 11 additions and 11 deletions

View File

@ -5,17 +5,16 @@ export default Em.Component.extend({
tagName: "ul",
classNames: ["results"],
@computed("poll.voters", "poll.options.[]", "poll.type")
options() {
@computed("poll.voters", "poll.type", "poll.options.[]")
options(voters, type) {
const options = this.get("poll.options");
const voters = this.get("poll.voters");
let percentages = voters === 0 ?
Array(options.length).fill(0) :
_.map(options, o => 100 * o.get("votes") / voters);
// properly round percentages
if (this.get("poll.type") === "multiple") {
if (type === "multiple") {
// when the poll is multiple choices, just "round down"
percentages = percentages.map(p => Math.floor(p));
} else {
@ -34,7 +33,7 @@ export default Em.Component.extend({
});
});
return this.get("poll.options");
return options;
}
});

View File

@ -1,8 +1,9 @@
// stolen from http://stackoverflow.com/a/13485888/11983
// stolen from http://stackoverflow.com/a/13484088/11983
export default (percentages) => {
const off = 100 - _.reduce(percentages, (acc, x) => acc + Math.round(x), 0);
return _.chain(percentages)
.sortBy(x => Math.round(x) - x)
.map((x, i) => Math.round(x) + (off > i) - (i >= (percentages.length + off)))
.value();
const sumOfDecimals = Math.ceil(percentages.map(a => a % 1).reduce((a, b) => a + b));
// compensate error by adding 1 to the first n items
for (let i = 0; i < sumOfDecimals; i++) {
percentages[i] = ++percentages[i];
}
return percentages.map(a => Math.floor(a));
};