Added calculation of overall seat allocation
This commit is contained in:
@@ -2,6 +2,7 @@ package de.twomartens.wahlrecht.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -35,6 +36,10 @@ public class Nomination {
|
||||
Arrays.stream(candidates).forEach(this::addCandidate);
|
||||
}
|
||||
|
||||
public void addCandidates(Collection<Candidate> candidates) {
|
||||
candidates.forEach(this::addCandidate);
|
||||
}
|
||||
|
||||
public Candidate getCandidate(int position) {
|
||||
return positionToCandidate.get(position);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package de.twomartens.wahlrecht.model;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.Map;
|
||||
import lombok.Builder;
|
||||
|
||||
@Builder
|
||||
public record SeatResult(Map<Nomination, Long> seatsPerNomination,
|
||||
Deque<Double> usedElectionNumbers) {
|
||||
|
||||
}
|
||||
@@ -8,18 +8,21 @@ import lombok.Getter;
|
||||
public class VotingResult {
|
||||
|
||||
private final int votesOnNomination;
|
||||
private final int votesThroughHealing;
|
||||
private final Map<Integer, Integer> votesPerPosition;
|
||||
private Integer totalVotes = null;
|
||||
|
||||
@Builder
|
||||
public VotingResult(int votesOnNomination, Map<Integer, Integer> votesPerPosition) {
|
||||
public VotingResult(int votesOnNomination, int votesThroughHealing,
|
||||
Map<Integer, Integer> votesPerPosition) {
|
||||
this.votesOnNomination = votesOnNomination;
|
||||
this.votesThroughHealing = votesThroughHealing;
|
||||
this.votesPerPosition = votesPerPosition;
|
||||
}
|
||||
|
||||
public int getTotalVotes() {
|
||||
if (totalVotes == null) {
|
||||
totalVotes = votesOnNomination + votesPerPosition.values().stream()
|
||||
totalVotes = votesOnNomination + votesThroughHealing + votesPerPosition.values().stream()
|
||||
.reduce(0, Integer::sum);
|
||||
}
|
||||
return totalVotes;
|
||||
|
||||
+39
-1
@@ -3,7 +3,9 @@ package de.twomartens.wahlrecht.service;
|
||||
import de.twomartens.wahlrecht.model.Candidate;
|
||||
import de.twomartens.wahlrecht.model.Constituency;
|
||||
import de.twomartens.wahlrecht.model.ElectedResult;
|
||||
import de.twomartens.wahlrecht.model.Election;
|
||||
import de.twomartens.wahlrecht.model.Nomination;
|
||||
import de.twomartens.wahlrecht.model.SeatResult;
|
||||
import de.twomartens.wahlrecht.model.VotingResult;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
@@ -19,7 +21,7 @@ import org.springframework.lang.NonNull;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class ConstituencyCalculationService {
|
||||
public class CalculationService {
|
||||
private final Deque<Double> electionNumberHistory = new ArrayDeque<>();
|
||||
|
||||
public ElectedResult calculateConstituency(@NonNull Constituency constituency,
|
||||
@@ -41,6 +43,42 @@ public class ConstituencyCalculationService {
|
||||
.build();
|
||||
}
|
||||
|
||||
public SeatResult calculateOverallSeatDistribution(@NonNull Election election,
|
||||
@NonNull Collection<Nomination> nominations) {
|
||||
electionNumberHistory.clear();
|
||||
int totalVotes = nominations.stream()
|
||||
.map(Nomination::getVotingResult)
|
||||
.map(VotingResult::getTotalVotes)
|
||||
.reduce(0, Integer::sum);
|
||||
|
||||
List<Nomination> validNominations = new ArrayList<>();
|
||||
int totalIgnoredVotes = 0;
|
||||
for (Nomination nomination : nominations) {
|
||||
if (passesVotingThreshold(election, totalVotes, nomination)) {
|
||||
validNominations.add(nomination);
|
||||
} else {
|
||||
totalIgnoredVotes += nomination.getVotingResult().getTotalVotes();
|
||||
}
|
||||
}
|
||||
totalVotes -= totalIgnoredVotes;
|
||||
|
||||
int numberOfSeats = election.totalNumberOfSeats();
|
||||
double initialElectionNumber = totalVotes / (double) numberOfSeats;
|
||||
|
||||
Map<Nomination, Long> assignedSeatsPerNomination = calculateAssignedSeatsPerNomination(
|
||||
validNominations, numberOfSeats, initialElectionNumber);
|
||||
|
||||
return SeatResult.builder()
|
||||
.seatsPerNomination(assignedSeatsPerNomination)
|
||||
.usedElectionNumbers(electionNumberHistory)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static boolean passesVotingThreshold(Election election, int totalVotes, Nomination nomination) {
|
||||
return totalVotes * election.votingThreshold().getMultiplier()
|
||||
<= nomination.getVotingResult().getTotalVotes();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Map<Nomination, Collection<Candidate>> findElectedCandidates(
|
||||
@NonNull Map<Nomination, Long> assignedSeatsPerNomination) {
|
||||
Reference in New Issue
Block a user