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.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -35,6 +36,10 @@ public class Nomination {
|
|||||||
Arrays.stream(candidates).forEach(this::addCandidate);
|
Arrays.stream(candidates).forEach(this::addCandidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addCandidates(Collection<Candidate> candidates) {
|
||||||
|
candidates.forEach(this::addCandidate);
|
||||||
|
}
|
||||||
|
|
||||||
public Candidate getCandidate(int position) {
|
public Candidate getCandidate(int position) {
|
||||||
return positionToCandidate.get(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 {
|
public class VotingResult {
|
||||||
|
|
||||||
private final int votesOnNomination;
|
private final int votesOnNomination;
|
||||||
|
private final int votesThroughHealing;
|
||||||
private final Map<Integer, Integer> votesPerPosition;
|
private final Map<Integer, Integer> votesPerPosition;
|
||||||
private Integer totalVotes = null;
|
private Integer totalVotes = null;
|
||||||
|
|
||||||
@Builder
|
@Builder
|
||||||
public VotingResult(int votesOnNomination, Map<Integer, Integer> votesPerPosition) {
|
public VotingResult(int votesOnNomination, int votesThroughHealing,
|
||||||
|
Map<Integer, Integer> votesPerPosition) {
|
||||||
this.votesOnNomination = votesOnNomination;
|
this.votesOnNomination = votesOnNomination;
|
||||||
|
this.votesThroughHealing = votesThroughHealing;
|
||||||
this.votesPerPosition = votesPerPosition;
|
this.votesPerPosition = votesPerPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTotalVotes() {
|
public int getTotalVotes() {
|
||||||
if (totalVotes == null) {
|
if (totalVotes == null) {
|
||||||
totalVotes = votesOnNomination + votesPerPosition.values().stream()
|
totalVotes = votesOnNomination + votesThroughHealing + votesPerPosition.values().stream()
|
||||||
.reduce(0, Integer::sum);
|
.reduce(0, Integer::sum);
|
||||||
}
|
}
|
||||||
return totalVotes;
|
return totalVotes;
|
||||||
|
|||||||
+39
-1
@@ -3,7 +3,9 @@ package de.twomartens.wahlrecht.service;
|
|||||||
import de.twomartens.wahlrecht.model.Candidate;
|
import de.twomartens.wahlrecht.model.Candidate;
|
||||||
import de.twomartens.wahlrecht.model.Constituency;
|
import de.twomartens.wahlrecht.model.Constituency;
|
||||||
import de.twomartens.wahlrecht.model.ElectedResult;
|
import de.twomartens.wahlrecht.model.ElectedResult;
|
||||||
|
import de.twomartens.wahlrecht.model.Election;
|
||||||
import de.twomartens.wahlrecht.model.Nomination;
|
import de.twomartens.wahlrecht.model.Nomination;
|
||||||
|
import de.twomartens.wahlrecht.model.SeatResult;
|
||||||
import de.twomartens.wahlrecht.model.VotingResult;
|
import de.twomartens.wahlrecht.model.VotingResult;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -19,7 +21,7 @@ import org.springframework.lang.NonNull;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class ConstituencyCalculationService {
|
public class CalculationService {
|
||||||
private final Deque<Double> electionNumberHistory = new ArrayDeque<>();
|
private final Deque<Double> electionNumberHistory = new ArrayDeque<>();
|
||||||
|
|
||||||
public ElectedResult calculateConstituency(@NonNull Constituency constituency,
|
public ElectedResult calculateConstituency(@NonNull Constituency constituency,
|
||||||
@@ -41,6 +43,42 @@ public class ConstituencyCalculationService {
|
|||||||
.build();
|
.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
|
@NonNull
|
||||||
private Map<Nomination, Collection<Candidate>> findElectedCandidates(
|
private Map<Nomination, Collection<Candidate>> findElectedCandidates(
|
||||||
@NonNull Map<Nomination, Long> assignedSeatsPerNomination) {
|
@NonNull Map<Nomination, Long> assignedSeatsPerNomination) {
|
||||||
+348
@@ -0,0 +1,348 @@
|
|||||||
|
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 de.twomartens.wahlrecht.model.VotingThreshold;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.Month;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.assertj.core.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
|
||||||
|
class CalculationServiceTest {
|
||||||
|
private static final Constituency EIMSBUETTEL_NORD = new Constituency("Eimsbüttel-Nord", 3);
|
||||||
|
private static final Constituency EIMSBUETTEL_SUED = new Constituency("Eimsbüttel-Süd", 5);
|
||||||
|
private static final Constituency HARO = new Constituency("Rotherbaum/Harvestehude", 4);
|
||||||
|
private static final Constituency LOKSTEDT = new Constituency("Lokstedt", 3);
|
||||||
|
private static final Constituency NIENDORF = new Constituency("Niendorf", 5);
|
||||||
|
private static final Constituency SCHNELSEN = new Constituency("Schnelsen", 3);
|
||||||
|
private static final Constituency EIDELSTEDT = new Constituency("Eidelstedt", 4);
|
||||||
|
private static final Constituency STELLINGEN = new Constituency("Stellingen", 3);
|
||||||
|
private static final Nomination SPD_NIENDORF = buildNomination("SPD-Niendorf", false);
|
||||||
|
private static final Nomination CDU_NIENDORF = buildNomination("CDU-Niendorf", false);
|
||||||
|
private static final Nomination FDP_NIENDORF = buildNomination("FDP-Niendorf", false);
|
||||||
|
private static final Nomination LINKE_NIENDORF = buildNomination("LINKE-Niendorf", false);
|
||||||
|
private static final Nomination GRUENE_NIENDORF = buildNomination("GRUENE-Niendorf", false);
|
||||||
|
private static final Nomination AFD_NIENDORF = buildNomination("AFD-Niendorf", false);
|
||||||
|
|
||||||
|
private static final Nomination SPD_BEZIRK = buildNomination("SPD-Bezirk", true);
|
||||||
|
private static final Nomination CDU_BEZIRK = buildNomination("CDU-Bezirk", true);
|
||||||
|
private static final Nomination FDP_BEZIRK = buildNomination("FDP-Bezirk", true);
|
||||||
|
private static final Nomination LINKE_BEZIRK = buildNomination("LINKE-Bezirk", true);
|
||||||
|
private static final Nomination GRUENE_BEZIRK = buildNomination("GRUENE-Bezirk", true);
|
||||||
|
private static final Nomination AFD_BEZIRK = buildNomination("AFD-Bezirk", true);
|
||||||
|
private static final Nomination PIRATEN_BEZIRK = buildNomination("Piraten-Bezirk", true);
|
||||||
|
|
||||||
|
private CalculationService service;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setService() {
|
||||||
|
service = new CalculationService();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldCalculateConstituencyCorrectly() {
|
||||||
|
Collection<Nomination> nominations = List.of(
|
||||||
|
SPD_NIENDORF,
|
||||||
|
CDU_NIENDORF,
|
||||||
|
LINKE_NIENDORF,
|
||||||
|
FDP_NIENDORF,
|
||||||
|
GRUENE_NIENDORF,
|
||||||
|
AFD_NIENDORF
|
||||||
|
);
|
||||||
|
setUpCandidatesConstituency();
|
||||||
|
setUpResultsConstituency();
|
||||||
|
|
||||||
|
ElectedResult elected = service.calculateConstituency(NIENDORF, nominations);
|
||||||
|
|
||||||
|
Assertions.assertThat(elected.electedCandidates())
|
||||||
|
.containsKey(SPD_NIENDORF)
|
||||||
|
.containsKey(CDU_NIENDORF)
|
||||||
|
.containsKey(GRUENE_NIENDORF)
|
||||||
|
.doesNotContainKey(LINKE_NIENDORF)
|
||||||
|
.doesNotContainKey(AFD_NIENDORF)
|
||||||
|
.doesNotContainKey(FDP_NIENDORF);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldCalculateOverallSeatsCorrectly() {
|
||||||
|
Collection<Constituency> constituencies = List.of(
|
||||||
|
EIMSBUETTEL_NORD, EIMSBUETTEL_SUED, HARO,
|
||||||
|
LOKSTEDT, NIENDORF, SCHNELSEN, EIDELSTEDT, STELLINGEN);
|
||||||
|
Election election = new Election("Bezirkswahl 2019",
|
||||||
|
LocalDate.of(2019, Month.MAY, 26), VotingThreshold.THREE,
|
||||||
|
51, constituencies);
|
||||||
|
Collection<Nomination> nominations = List.of(
|
||||||
|
SPD_BEZIRK,
|
||||||
|
CDU_BEZIRK,
|
||||||
|
LINKE_BEZIRK,
|
||||||
|
FDP_BEZIRK,
|
||||||
|
GRUENE_BEZIRK,
|
||||||
|
AFD_BEZIRK
|
||||||
|
);
|
||||||
|
setUpCandidatesOverall();
|
||||||
|
setUpResultsOverall();
|
||||||
|
|
||||||
|
SeatResult result = service.calculateOverallSeatDistribution(election, nominations);
|
||||||
|
|
||||||
|
Assertions.assertThat(result.seatsPerNomination())
|
||||||
|
.containsEntry(SPD_BEZIRK, 12L)
|
||||||
|
.containsEntry(CDU_BEZIRK, 9L)
|
||||||
|
.containsEntry(LINKE_BEZIRK, 5L)
|
||||||
|
.containsEntry(FDP_BEZIRK, 3L)
|
||||||
|
.containsEntry(GRUENE_BEZIRK, 19L)
|
||||||
|
.containsEntry(AFD_BEZIRK, 3L);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpCandidatesConstituency() {
|
||||||
|
SPD_NIENDORF.addCandidates(new Candidate("Schwarzarius, Ines", ""));
|
||||||
|
SPD_NIENDORF.addCandidates(new Candidate("Urbanski, Torge", ""));
|
||||||
|
SPD_NIENDORF.addCandidates(new Candidate("Fischbach-Pyttel, Carola", ""));
|
||||||
|
SPD_NIENDORF.addCandidates(new Candidate("Bäcker, Guido", ""));
|
||||||
|
SPD_NIENDORF.addCandidates(new Candidate("Porr, Ulrike", ""));
|
||||||
|
SPD_NIENDORF.addCandidates(new Candidate("Petersen, Johannes", ""));
|
||||||
|
SPD_NIENDORF.addCandidates(new Candidate("Kröger, Manuela-Andrea", ""));
|
||||||
|
SPD_NIENDORF.addCandidates(new Candidate("Steppat, Wolfgang", ""));
|
||||||
|
SPD_NIENDORF.addCandidates(new Candidate("Canbay, Berfin", ""));
|
||||||
|
SPD_NIENDORF.addCandidates(new Candidate("Schumacher, Wolfgang", ""));
|
||||||
|
|
||||||
|
CDU_NIENDORF.addCandidates(new Candidate("Kuhn, Rüdiger", ""));
|
||||||
|
CDU_NIENDORF.addCandidates(new Candidate("Ahrens, Mareike", ""));
|
||||||
|
CDU_NIENDORF.addCandidates(new Candidate("Wysocki, Michael", ""));
|
||||||
|
CDU_NIENDORF.addCandidates(new Candidate("Dönselmann, Malte", ""));
|
||||||
|
CDU_NIENDORF.addCandidates(new Candidate("Seehaber, Daniel", ""));
|
||||||
|
|
||||||
|
LINKE_NIENDORF.addCandidates(new Candidate("Dr. Khenkhar, Malik", ""));
|
||||||
|
LINKE_NIENDORF.addCandidates(new Candidate("Radom, Claudia", ""));
|
||||||
|
LINKE_NIENDORF.addCandidates(new Candidate("Kara, Başak", ""));
|
||||||
|
|
||||||
|
FDP_NIENDORF.addCandidates(new Candidate("Häffs, Marvin", ""));
|
||||||
|
FDP_NIENDORF.addCandidates(new Candidate("Bahmer, Larissa", ""));
|
||||||
|
FDP_NIENDORF.addCandidates(new Candidate("Patzer, Heinrich-Otto", ""));
|
||||||
|
|
||||||
|
GRUENE_NIENDORF.addCandidates(new Candidate("Demirhan, Sina", ""));
|
||||||
|
GRUENE_NIENDORF.addCandidates(new Candidate("Schmidt, Lutz", "Redakteur"));
|
||||||
|
|
||||||
|
AFD_NIENDORF.addCandidates(new Candidate("Hanssen, Wolfgang", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpResultsConstituency() {
|
||||||
|
SPD_NIENDORF.setVotingResult(VotingResult.builder()
|
||||||
|
.votesOnNomination(0)
|
||||||
|
.votesPerPosition(Map.of(
|
||||||
|
1, 11882,
|
||||||
|
2, 7617,
|
||||||
|
3, 1946,
|
||||||
|
4, 1743,
|
||||||
|
5, 1363,
|
||||||
|
6, 762,
|
||||||
|
7, 895,
|
||||||
|
8, 1598,
|
||||||
|
9, 1786,
|
||||||
|
10, 781
|
||||||
|
))
|
||||||
|
.build());
|
||||||
|
|
||||||
|
CDU_NIENDORF.setVotingResult(VotingResult.builder()
|
||||||
|
.votesOnNomination(0)
|
||||||
|
.votesPerPosition(Map.of(
|
||||||
|
1, 10733,
|
||||||
|
2, 4550,
|
||||||
|
3, 2310,
|
||||||
|
4, 2333,
|
||||||
|
5, 2565
|
||||||
|
))
|
||||||
|
.build());
|
||||||
|
|
||||||
|
LINKE_NIENDORF.setVotingResult(VotingResult.builder()
|
||||||
|
.votesOnNomination(0)
|
||||||
|
.votesPerPosition(Map.of(
|
||||||
|
1, 3782,
|
||||||
|
2, 1584,
|
||||||
|
3, 1185
|
||||||
|
))
|
||||||
|
.build());
|
||||||
|
|
||||||
|
FDP_NIENDORF.setVotingResult(VotingResult.builder()
|
||||||
|
.votesOnNomination(0)
|
||||||
|
.votesPerPosition(Map.of(
|
||||||
|
1, 2498,
|
||||||
|
2, 3200,
|
||||||
|
3, 992
|
||||||
|
))
|
||||||
|
.build());
|
||||||
|
|
||||||
|
GRUENE_NIENDORF.setVotingResult(VotingResult.builder()
|
||||||
|
.votesOnNomination(0)
|
||||||
|
.votesPerPosition(Map.of(
|
||||||
|
1, 14838,
|
||||||
|
2, 12501
|
||||||
|
))
|
||||||
|
.build());
|
||||||
|
|
||||||
|
AFD_NIENDORF.setVotingResult(VotingResult.builder()
|
||||||
|
.votesOnNomination(0)
|
||||||
|
.votesPerPosition(Map.of(
|
||||||
|
1, 6616
|
||||||
|
))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpCandidatesOverall() {
|
||||||
|
SPD_BEZIRK.addCandidates(buildCandidates(
|
||||||
|
"Gottlieb, Gabor", "Meding, Sarah", "Harringa, Nils", "Nendza-Ammar, Charlotte",
|
||||||
|
"Rust, Rüdiger", "Köster-Marjanovic, Hannelore", "Riegel, Ann-Kathrin", "Rüter, Monika",
|
||||||
|
"Heise, Elk", "Fischbach-Pyttel, Carola", "Schirmer, Stephan-Philipp", "Telljohann, Katharina",
|
||||||
|
"Röder, Wilfried", "Dr. Matiss, Claudia", "Koßel, Uwe", "Wagner, Saskia", "Bäcker, Guido",
|
||||||
|
"Tiben-Thörner, Karin", "Ptach, Stephan", "Steinbiß, Emily", "Berisha, Dafina",
|
||||||
|
"Meyer, Simon", "Porr, Ulrike", "Lange, Frederik", "Oliva, Nora", "Drossinakis, Panagiotis",
|
||||||
|
"Jacobs, Ruth", "Bernstein, Til", "Kröger, Manuela-Andrea", "Dr. Enzmann, Dirk",
|
||||||
|
"Schilling, Alexandra", "Abboud, Hussein", "Petersen, Britt", "Petersen, Johannes",
|
||||||
|
"Petersen, Doris", "Frese, Gabor", "Suh-von Bremen, Sun Won", "Steppat, Wolfgang",
|
||||||
|
"Hildebrand, Denise"
|
||||||
|
));
|
||||||
|
|
||||||
|
CDU_BEZIRK.addCandidates(buildCandidates(
|
||||||
|
"Höflich, Jutta", "Könecke, Christian", "Birnbaum, Andreas", "Möller-Fiedler, Sybille",
|
||||||
|
"Kochmann, Franziska", "von Deutsch, Christiane", "Hoffmann, Bernd", "Holst, Christian",
|
||||||
|
"Lau, Roman", "Hille, Robert", "Ahrens, Mareike", "Dr. Langhein, A.W.Heinrich",
|
||||||
|
"Wichmann, Norbert", "Lau, Johanna", "Czernotzky, Birgit", "von Sawilski, Marlies",
|
||||||
|
"Dönselmann, Malte",
|
||||||
|
"Jarzembowski, Daniel", "Howe, Sönke", "Recknagel, Dennis", "Dieball, Laura",
|
||||||
|
"Josefowsky, Ernst Günther", "Wysocki, Michael", "Thomsen, Thomas", "Greshake, Sascha",
|
||||||
|
"Thiesen, Marianne",
|
||||||
|
"Schüller, Michael", "Jacobs, Jürgen", "Weiler, Johannes", "Howe, Raphaela"
|
||||||
|
));
|
||||||
|
|
||||||
|
LINKE_BEZIRK.addCandidates(buildCandidates(
|
||||||
|
"Pagels, Manuela", "Wiegmann, Roland", "Peters, Ralf", "Hoyer, Jonas",
|
||||||
|
"Kleinert, Mikey", "Schulte, Kolja", "Huwald, Kristin", "Dr. Ritter, Sabine",
|
||||||
|
"Pirling, David", "Reipschläger, Bernhard", "Arndt, Thomas", "Artus, Holger",
|
||||||
|
"WLaab, Helene"
|
||||||
|
));
|
||||||
|
|
||||||
|
GRUENE_BEZIRK.addCandidates(buildCandidates(
|
||||||
|
"Kern, Lisa", "Hadji Mir Agha, Ali", "Dr. Putz, Miriam", "Kuhlmann, Dietmar",
|
||||||
|
"Dr. Hunter, Lynne", "Schmidt-Tobler, Falk", "Demirhan, Sina", "Klein, Robert",
|
||||||
|
"Erk, Aramak", "Martens, Jim", "Warnecke, Anne Kathrin", "Dr. Fischer, Jost Leonhardt",
|
||||||
|
"Kost, Cornelia", "Brandt, Christopher", "Schübel, Nina Joana", "Schmidt, Lutz",
|
||||||
|
"Wolf, Rita",
|
||||||
|
"Alam, Leon", "Schwarzwald, Cristina", "Thies, Nico", "Hasselmann, Annette",
|
||||||
|
"Koriath, Jan", "Küll, Gabriela", "Köhler, Kevin", "Hericks, Susanne",
|
||||||
|
"Bohny, Carl Maria",
|
||||||
|
"Fester, Emilia", "Hofmann, Klaus-Dieter", "Neumann, Bernd", "Braasch, Julian",
|
||||||
|
"Dorsch, Sebastian", "Hasselmann, Harald"
|
||||||
|
));
|
||||||
|
|
||||||
|
FDP_BEZIRK.addCandidates(buildCandidates(
|
||||||
|
"Krüger, Klaus", "Schwanke, Benjamin", "Cleven, Martina", "Zielinski, Mathias",
|
||||||
|
"Thiele, Camilla Joyce", "Krüger, Hannelore", "Welling, Jörg", "Häffs, Marvin",
|
||||||
|
"Korb, Hendrik", "Bahmer, Larissa", "Langbehn, Marian", "Szrubarski, Sebastian",
|
||||||
|
"Patzer, Heinrich-Otto", "Sosin, Tatjana", "Damm, Renate", "Müller-Sönksen, Burkhardt"
|
||||||
|
));
|
||||||
|
|
||||||
|
AFD_BEZIRK.addCandidates(buildCandidates(
|
||||||
|
"Schömer, Dirk", "Zimmermann, Elke", "Pillatzke, Jörg", "Pohl, Christian",
|
||||||
|
"Hanssen, Wolfgang", "Lemke, Martin", "Cremer-Thursby, Marc", "Schultz, Thomas",
|
||||||
|
"Ziob, Peter"
|
||||||
|
));
|
||||||
|
|
||||||
|
PIRATEN_BEZIRK.addCandidates(buildCandidates(
|
||||||
|
"Dr. Siebert-Schütz, Martin", "Mewes, Christoph", "Brümmer, Amadeus"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpResultsOverall() {
|
||||||
|
SPD_BEZIRK.setVotingResult(VotingResult.builder()
|
||||||
|
.votesOnNomination(84703)
|
||||||
|
.votesThroughHealing(985)
|
||||||
|
.votesPerPosition(buildVotesPerPosition(
|
||||||
|
8782, 3318, 3825, 3519, 2036, 3923, 5427, 2131, 566, 895, 1425, 1924, 819,
|
||||||
|
2590, 2190, 3568, 742, 401, 554, 1133, 1268, 580, 254, 1217, 693, 1359, 481,
|
||||||
|
650, 230, 1544, 1080, 1879, 400, 353, 525, 469, 196, 759, 872
|
||||||
|
))
|
||||||
|
.build());
|
||||||
|
|
||||||
|
CDU_BEZIRK.setVotingResult(VotingResult.builder()
|
||||||
|
.votesOnNomination(66245)
|
||||||
|
.votesThroughHealing(660)
|
||||||
|
.votesPerPosition(buildVotesPerPosition(
|
||||||
|
5966, 1982, 1604, 2414, 1322, 2237, 1868, 1872, 1889, 881, 1253, 2921, 598,
|
||||||
|
2721, 618, 941, 620, 837, 378, 594, 484, 584, 472, 408, 748, 650, 282,
|
||||||
|
315, 1397, 502
|
||||||
|
))
|
||||||
|
.build());
|
||||||
|
|
||||||
|
LINKE_BEZIRK.setVotingResult(VotingResult.builder()
|
||||||
|
.votesOnNomination(47452)
|
||||||
|
.votesThroughHealing(330)
|
||||||
|
.votesPerPosition(buildVotesPerPosition(
|
||||||
|
4890, 875, 1532, 1293, 2321, 696, 1843, 2212, 1488, 483, 764, 572, 892
|
||||||
|
))
|
||||||
|
.build());
|
||||||
|
|
||||||
|
GRUENE_BEZIRK.setVotingResult(VotingResult.builder()
|
||||||
|
.votesOnNomination(150842)
|
||||||
|
.votesThroughHealing(900)
|
||||||
|
.votesPerPosition(buildVotesPerPosition(
|
||||||
|
10586, 5629, 12597, 2935, 3378, 735, 5662, 4021, 2065, 2469, 1561, 3557, 2290,
|
||||||
|
1411, 2445, 1761, 1252, 1628, 652, 3524, 677, 843, 2375, 500, 1674, 3264, 1569,
|
||||||
|
531, 531, 652, 5358, 2129
|
||||||
|
))
|
||||||
|
.build());
|
||||||
|
|
||||||
|
FDP_BEZIRK.setVotingResult(VotingResult.builder()
|
||||||
|
.votesOnNomination(24435)
|
||||||
|
.votesThroughHealing(240)
|
||||||
|
.votesPerPosition(buildVotesPerPosition(
|
||||||
|
3528, 1964, 1633, 897, 1193, 355, 401, 1012, 496, 1242, 643, 300, 311,
|
||||||
|
998, 505, 2181
|
||||||
|
))
|
||||||
|
.build());
|
||||||
|
|
||||||
|
AFD_BEZIRK.setVotingResult(VotingResult.builder()
|
||||||
|
.votesOnNomination(21625)
|
||||||
|
.votesThroughHealing(220)
|
||||||
|
.votesPerPosition(buildVotesPerPosition(
|
||||||
|
1226, 1950, 3007, 874, 1032, 780, 535, 221, 283
|
||||||
|
))
|
||||||
|
.build());
|
||||||
|
|
||||||
|
PIRATEN_BEZIRK.setVotingResult(VotingResult.builder()
|
||||||
|
.votesOnNomination(6715)
|
||||||
|
.votesThroughHealing(25)
|
||||||
|
.votesPerPosition(buildVotesPerPosition(
|
||||||
|
871, 1907, 987
|
||||||
|
))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Nomination buildNomination(String name, boolean supportVotesOnNomination) {
|
||||||
|
return new Nomination(name, supportVotesOnNomination);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Collection<Candidate> buildCandidates(String... names) {
|
||||||
|
return Arrays.stream(names).map(name -> new Candidate(name, "")).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private static Map<Integer, Integer> buildVotesPerPosition(@NonNull int... votes) {
|
||||||
|
Map<Integer, Integer> votesPerPosition = new HashMap<>();
|
||||||
|
for (int i = 0; i < votes.length; i++) {
|
||||||
|
int vote = votes[i];
|
||||||
|
votesPerPosition.put(i + 1, vote);
|
||||||
|
}
|
||||||
|
return votesPerPosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
-152
@@ -1,152 +0,0 @@
|
|||||||
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.Nomination;
|
|
||||||
import de.twomartens.wahlrecht.model.VotingResult;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import org.assertj.core.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
class ConstituencyCalculationServiceTest {
|
|
||||||
private static final Nomination SPD_NIENDORF = buildNomination("SPD-Niendorf");
|
|
||||||
private static final Nomination CDU_NIENDORF = buildNomination("CDU-Niendorf");
|
|
||||||
private static final Nomination FDP_NIENDORF = buildNomination("FDP-Niendorf");
|
|
||||||
private static final Nomination LINKE_NIENDORF = buildNomination("LINKE-Niendorf");
|
|
||||||
private static final Nomination GRUENE_NIENDORF = buildNomination("GRUENE-Niendorf");
|
|
||||||
private static final Nomination AFD_NIENDORF = buildNomination("AFD-Niendorf");
|
|
||||||
|
|
||||||
private ConstituencyCalculationService service;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setService() {
|
|
||||||
service = new ConstituencyCalculationService();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void shouldCalculateConstituencyCorrectly() {
|
|
||||||
Constituency constituency = new Constituency("Niendorf", 5);
|
|
||||||
Collection<Nomination> nominations = List.of(
|
|
||||||
SPD_NIENDORF,
|
|
||||||
CDU_NIENDORF,
|
|
||||||
LINKE_NIENDORF,
|
|
||||||
FDP_NIENDORF,
|
|
||||||
GRUENE_NIENDORF,
|
|
||||||
AFD_NIENDORF
|
|
||||||
);
|
|
||||||
setUpCandidates();
|
|
||||||
setUpResults();
|
|
||||||
|
|
||||||
ElectedResult elected = service.calculateConstituency(constituency, nominations);
|
|
||||||
|
|
||||||
Assertions.assertThat(elected.electedCandidates())
|
|
||||||
.containsKey(SPD_NIENDORF)
|
|
||||||
.containsKey(CDU_NIENDORF)
|
|
||||||
.containsKey(GRUENE_NIENDORF)
|
|
||||||
.doesNotContainKey(LINKE_NIENDORF)
|
|
||||||
.doesNotContainKey(AFD_NIENDORF)
|
|
||||||
.doesNotContainKey(FDP_NIENDORF);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setUpCandidates() {
|
|
||||||
SPD_NIENDORF.addCandidates(new Candidate("Schwarzarius, Ines", ""));
|
|
||||||
SPD_NIENDORF.addCandidates(new Candidate("Urbanski, Torge", ""));
|
|
||||||
SPD_NIENDORF.addCandidates(new Candidate("Fischbach-Pyttel, Carola", ""));
|
|
||||||
SPD_NIENDORF.addCandidates(new Candidate("Bäcker, Guido", ""));
|
|
||||||
SPD_NIENDORF.addCandidates(new Candidate("Porr, Ulrike", ""));
|
|
||||||
SPD_NIENDORF.addCandidates(new Candidate("Petersen, Johannes", ""));
|
|
||||||
SPD_NIENDORF.addCandidates(new Candidate("Kröger, Manuela-Andrea", ""));
|
|
||||||
SPD_NIENDORF.addCandidates(new Candidate("Steppat, Wolfgang", ""));
|
|
||||||
SPD_NIENDORF.addCandidates(new Candidate("Canbay, Berfin", ""));
|
|
||||||
SPD_NIENDORF.addCandidates(new Candidate("Schumacher, Wolfgang", ""));
|
|
||||||
|
|
||||||
CDU_NIENDORF.addCandidates(new Candidate("Kuhn, Rüdiger", ""));
|
|
||||||
CDU_NIENDORF.addCandidates(new Candidate("Ahrens, Mareike", ""));
|
|
||||||
CDU_NIENDORF.addCandidates(new Candidate("Wysocki, Michael", ""));
|
|
||||||
CDU_NIENDORF.addCandidates(new Candidate("Dönselmann, Malte", ""));
|
|
||||||
CDU_NIENDORF.addCandidates(new Candidate("Seehaber, Daniel", ""));
|
|
||||||
|
|
||||||
LINKE_NIENDORF.addCandidates(new Candidate("Dr. Khenkhar, Malik", ""));
|
|
||||||
LINKE_NIENDORF.addCandidates(new Candidate("Radom, Claudia", ""));
|
|
||||||
LINKE_NIENDORF.addCandidates(new Candidate("Kara, Başak", ""));
|
|
||||||
|
|
||||||
FDP_NIENDORF.addCandidates(new Candidate("Häffs, Marvin", ""));
|
|
||||||
FDP_NIENDORF.addCandidates(new Candidate("Bahmer, Larissa", ""));
|
|
||||||
FDP_NIENDORF.addCandidates(new Candidate("Patzer, Heinrich-Otto", ""));
|
|
||||||
|
|
||||||
GRUENE_NIENDORF.addCandidates(new Candidate("Demirhan, Sina", ""));
|
|
||||||
GRUENE_NIENDORF.addCandidates(new Candidate("Schmidt, Lutz", "Redakteur"));
|
|
||||||
|
|
||||||
AFD_NIENDORF.addCandidates(new Candidate("Hanssen, Wolfgang", ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setUpResults() {
|
|
||||||
SPD_NIENDORF.setVotingResult(VotingResult.builder()
|
|
||||||
.votesOnNomination(0)
|
|
||||||
.votesPerPosition(Map.of(
|
|
||||||
1, 11882,
|
|
||||||
2, 7617,
|
|
||||||
3, 1946,
|
|
||||||
4, 1743,
|
|
||||||
5, 1363,
|
|
||||||
6, 762,
|
|
||||||
7, 895,
|
|
||||||
8, 1598,
|
|
||||||
9, 1786,
|
|
||||||
10, 781
|
|
||||||
))
|
|
||||||
.build());
|
|
||||||
|
|
||||||
CDU_NIENDORF.setVotingResult(VotingResult.builder()
|
|
||||||
.votesOnNomination(0)
|
|
||||||
.votesPerPosition(Map.of(
|
|
||||||
1, 10733,
|
|
||||||
2, 4550,
|
|
||||||
3, 2310,
|
|
||||||
4, 2333,
|
|
||||||
5, 2565
|
|
||||||
))
|
|
||||||
.build());
|
|
||||||
|
|
||||||
LINKE_NIENDORF.setVotingResult(VotingResult.builder()
|
|
||||||
.votesOnNomination(0)
|
|
||||||
.votesPerPosition(Map.of(
|
|
||||||
1, 3782,
|
|
||||||
2, 1584,
|
|
||||||
3, 1185
|
|
||||||
))
|
|
||||||
.build());
|
|
||||||
|
|
||||||
FDP_NIENDORF.setVotingResult(VotingResult.builder()
|
|
||||||
.votesOnNomination(0)
|
|
||||||
.votesPerPosition(Map.of(
|
|
||||||
1, 2498,
|
|
||||||
2, 3200,
|
|
||||||
3, 992
|
|
||||||
))
|
|
||||||
.build());
|
|
||||||
|
|
||||||
GRUENE_NIENDORF.setVotingResult(VotingResult.builder()
|
|
||||||
.votesOnNomination(0)
|
|
||||||
.votesPerPosition(Map.of(
|
|
||||||
1, 14838,
|
|
||||||
2, 12501
|
|
||||||
))
|
|
||||||
.build());
|
|
||||||
|
|
||||||
AFD_NIENDORF.setVotingResult(VotingResult.builder()
|
|
||||||
.votesOnNomination(0)
|
|
||||||
.votesPerPosition(Map.of(
|
|
||||||
1, 6616
|
|
||||||
))
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Nomination buildNomination(String name) {
|
|
||||||
return new Nomination(name, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user