Repository navigation
Expand file tree
/
Copy pathindex.js
More file actions
100 lines (83 loc) · 2.01 KB
/
Copy pathindex.js
File metadata and controls
100 lines (83 loc) · 2.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/* Largest remainder - written by Nic Mulvaney */
const totalObj = (obj, key) => {
return Object.values(obj).reduce(
(t, i) => t + parseFloat(key ? i[key] : i),
0
)
}
const largestRemainder = (input, totalSeats, type) => {
if (!Object.keys(input).length) {
console.error('Empty input for proportional-distribution')
return []
}
// Make sure seats is a number
totalSeats = parseFloat(totalSeats)
let tally = []
// Get the total votes
let total = totalObj(input)
// choose a quota
let quota
if (type === 'droop') {
quota = Math.floor(total / (totalSeats + 1)) + 1
}
let tooLow = quota <= totalSeats
if (type === 'hare' || tooLow) {
quota = total / totalSeats
}
if (type === 'hagenbach-bischoff') {
quota = total / (1 + totalSeats)
}
if (type === 'imperiali') {
quota = total / (2 + totalSeats)
}
if (tooLow) {
type = 'hare (was droop)'
}
// For each party create an analysis object
for (var i in input) {
let votes = parseFloat(input[i])
let percentage = votes / total
let distribution = percentage * totalSeats
let seats, remainder
if (type) {
let seatsFloat = votes / quota
seats = Math.floor(seatsFloat)
remainder = seatsFloat - seats
} else {
seats = Math.floor(distribution)
remainder = distribution - seats
}
tally.push({
type,
party: i,
votes,
percentage,
distribution,
remainder,
seats,
error: distribution - seats
})
}
// sum the total seats
total = totalObj(tally, 'seats')
// check for a difference from the total
let remainder = totalSeats - total
// sort by the largest remainder
tally.sort((a, b) => {
return b.remainder - a.remainder
})
// increment up to the full total
for (var i = 0; i < remainder; i++) {
tally[i].seats++
tally[i].error = tally[i].seats - tally[i].distribution
}
for (var i in tally) {
tally[i].percentageSeats = tally[i].seats / totalSeats
}
// Sort by allocated seats
tally.sort((a, b) => {
return b.percentage - a.percentage
})
return tally
}
module.exports = largestRemainder