Skip to content
Permalink
devel
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
128 lines (91 sloc) 3.55 KB
package org.jseats.model.methods;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Properties;
import org.jseats.model.InmutableTally;
import org.jseats.model.Result;
import org.jseats.model.Result.ResultType;
import org.jseats.model.SeatAllocationException;
import org.jseats.model.SeatAllocationMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EqualProportionsMethod implements SeatAllocationMethod {
Logger log = LoggerFactory.getLogger(EqualProportionsMethod.class);
NumberFormat df = DecimalFormat.getInstance();
protected double coefficient(int seatNumber) {
return 1 / Math.sqrt(seatNumber * (seatNumber + 1));
}
public EqualProportionsMethod() {
df.setMinimumFractionDigits(2);
df.setMaximumFractionDigits(2);
df.setRoundingMode(RoundingMode.DOWN);
}
@Override
public Result process(InmutableTally tally, Properties properties)
throws SeatAllocationException {
// Get properties
int numberOfCandidates = tally.getNumberOfCandidates();
int numberOfSeats = Integer.parseInt(properties.getProperty(
"numberOfSeats", Integer.toString(numberOfCandidates)));
int numberOfInitialSeats = Integer.parseInt(properties.getProperty(
"numberOfInitialSeats", Integer.toString(0)));
// Allocating initial seats
log.debug("Allocating " + numberOfInitialSeats
+ " initial seats per candidate.");
int[] candidateSeats = new int[numberOfCandidates];
Result result = new Result(ResultType.MULTIPLE);
for (int candidate = 0; candidate < numberOfCandidates; candidate++) {
for (int seat = 0; seat < numberOfInitialSeats; seat++) {
result.addSeat(tally.getCandidateAt(candidate));
candidateSeats[candidate]++;
numberOfSeats--;
}
}
log.debug("Number of seats remaining: " + numberOfSeats);
// Order by priority
double[] candidatePriority = new double[numberOfCandidates];
while (numberOfSeats > 0) {
log.debug("Seat #" + numberOfSeats + ": Computing candidate");
// Get priority for each candidate
for (int candidate = 0; candidate < numberOfCandidates; candidate++) {
double coefficient = coefficient(candidateSeats[candidate]);
int votes = tally.getCandidateAt(candidate).getVotes();
candidatePriority[candidate] = votes * coefficient;
if (log.isTraceEnabled())
log.trace("Coefficient: " + df.format(coefficient)
+ " Priority: "
+ df.format(candidatePriority[candidate]) + " "
+ tally.getCandidateAt(candidate));
}
// Find candidate with higher priority:
int maxCandidate = -1;
double maxPriority = -1;
for (int candidate = 0; candidate < numberOfCandidates; candidate++) {
if (candidatePriority[candidate] == maxPriority) {
Result tieResult = new Result(ResultType.TIE);
tieResult.addSeat(tally.getCandidateAt(maxCandidate));
tieResult.addSeat(tally.getCandidateAt(candidate));
return tieResult;
}
if (candidatePriority[candidate] > maxPriority) {
maxCandidate = candidate;
maxPriority = candidatePriority[candidate];
}
}
// and assign the seat
log.debug("Seat #" + numberOfSeats + ": Winner candidate is "
+ tally.getCandidateAt(maxCandidate));
result.addSeat(tally.getCandidateAt(maxCandidate));
candidateSeats[maxCandidate]++;
numberOfSeats--;
}
// Summary
if (log.isTraceEnabled())
for (int candidate = 0; candidate < numberOfCandidates; candidate++) {
log.trace("Candidate " + tally.getCandidateAt(candidate)
+ " has " + candidateSeats[candidate] + " seats.");
}
return result;
}
}