From 3e178885b5957ac2b19bfeedaf853c274ac3cc5d Mon Sep 17 00:00:00 2001 From: Jim Martens Date: Sun, 9 Jul 2023 15:05:34 +0200 Subject: [PATCH] Reorganized model structure --- .../wahlrecht/model/Constituency.java | 9 --- .../de/twomartens/wahlrecht/model/Party.java | 21 ------ .../wahlrecht/model/db/Candidate.java | 41 +++++++++++ .../wahlrecht/model/db/Constituency.java | 43 ++++++++++++ .../wahlrecht/model/db/Election.java | 47 +++++++++++++ .../wahlrecht/model/db/Nomination.java | 49 +++++++++++++ .../wahlrecht/model/db/PartyInElection.java | 46 +++++++++++++ .../model/{ => dto/v1}/Candidate.java | 2 +- .../wahlrecht/model/dto/v1/Constituency.java | 9 +++ .../wahlrecht/model/{ => dto/v1}/Elected.java | 2 +- .../model/{ => dto/v1}/ElectedCandidate.java | 3 +- .../wahlrecht/model/dto/v1/ElectedResult.java | 14 ++++ .../model/{ => dto/v1}/Election.java | 2 +- .../wahlrecht/model/dto/v1/Nomination.java | 9 +++ .../model/dto/v1/PartyInElection.java | 12 ++++ .../wahlrecht/model/dto/v1/SeatResult.java | 13 ++++ .../wahlrecht/model/dto/v1/VotingResult.java | 10 +++ .../model/{ => dto/v1}/VotingThreshold.java | 2 +- .../wahlrecht/model/internal/Candidate.java | 5 ++ .../model/internal/Constituency.java | 9 +++ .../wahlrecht/model/internal/Elected.java | 8 +++ .../model/internal/ElectedCandidate.java | 13 ++++ .../model/{ => internal}/ElectedResult.java | 6 +- .../wahlrecht/model/internal/Election.java | 10 +++ .../model/{ => internal}/Nomination.java | 11 +-- .../model/{ => internal}/SeatResult.java | 6 +- .../model/{ => internal}/VotingResult.java | 2 +- .../model/internal/VotingThreshold.java | 15 ++++ .../wahlrecht/service/CalculationService.java | 32 ++++----- .../service/CalculationServiceTest.java | 68 ++++++++++--------- 30 files changed, 424 insertions(+), 95 deletions(-) delete mode 100644 module-server/src/main/java/de/twomartens/wahlrecht/model/Constituency.java delete mode 100644 module-server/src/main/java/de/twomartens/wahlrecht/model/Party.java create mode 100644 module-server/src/main/java/de/twomartens/wahlrecht/model/db/Candidate.java create mode 100644 module-server/src/main/java/de/twomartens/wahlrecht/model/db/Constituency.java create mode 100644 module-server/src/main/java/de/twomartens/wahlrecht/model/db/Election.java create mode 100644 module-server/src/main/java/de/twomartens/wahlrecht/model/db/Nomination.java create mode 100644 module-server/src/main/java/de/twomartens/wahlrecht/model/db/PartyInElection.java rename module-server/src/main/java/de/twomartens/wahlrecht/model/{ => dto/v1}/Candidate.java (57%) create mode 100644 module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/Constituency.java rename module-server/src/main/java/de/twomartens/wahlrecht/model/{ => dto/v1}/Elected.java (69%) rename module-server/src/main/java/de/twomartens/wahlrecht/model/{ => dto/v1}/ElectedCandidate.java (81%) create mode 100644 module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/ElectedResult.java rename module-server/src/main/java/de/twomartens/wahlrecht/model/{ => dto/v1}/Election.java (84%) create mode 100644 module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/Nomination.java create mode 100644 module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/PartyInElection.java create mode 100644 module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/SeatResult.java create mode 100644 module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/VotingResult.java rename module-server/src/main/java/de/twomartens/wahlrecht/model/{ => dto/v1}/VotingThreshold.java (85%) create mode 100644 module-server/src/main/java/de/twomartens/wahlrecht/model/internal/Candidate.java create mode 100644 module-server/src/main/java/de/twomartens/wahlrecht/model/internal/Constituency.java create mode 100644 module-server/src/main/java/de/twomartens/wahlrecht/model/internal/Elected.java create mode 100644 module-server/src/main/java/de/twomartens/wahlrecht/model/internal/ElectedCandidate.java rename module-server/src/main/java/de/twomartens/wahlrecht/model/{ => internal}/ElectedResult.java (76%) create mode 100644 module-server/src/main/java/de/twomartens/wahlrecht/model/internal/Election.java rename module-server/src/main/java/de/twomartens/wahlrecht/model/{ => internal}/Nomination.java (92%) rename module-server/src/main/java/de/twomartens/wahlrecht/model/{ => internal}/SeatResult.java (73%) rename module-server/src/main/java/de/twomartens/wahlrecht/model/{ => internal}/VotingResult.java (95%) create mode 100644 module-server/src/main/java/de/twomartens/wahlrecht/model/internal/VotingThreshold.java diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/Constituency.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/Constituency.java deleted file mode 100644 index 9dd8ded..0000000 --- a/module-server/src/main/java/de/twomartens/wahlrecht/model/Constituency.java +++ /dev/null @@ -1,9 +0,0 @@ -package de.twomartens.wahlrecht.model; - -public record Constituency(String name, int numberOfSeats) { - - @Override - public String toString() { - return name; - } -} diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/Party.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/Party.java deleted file mode 100644 index a3c252f..0000000 --- a/module-server/src/main/java/de/twomartens/wahlrecht/model/Party.java +++ /dev/null @@ -1,21 +0,0 @@ -package de.twomartens.wahlrecht.model; - -import java.util.Map; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.Setter; - -@RequiredArgsConstructor -@Setter -@Getter -public class Party { - private final String name; - private Nomination overallNomination; - private Map constituencyNominations; - private boolean passesVotingThreshold; - - @Override - public String toString() { - return name; - } -} diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/db/Candidate.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/db/Candidate.java new file mode 100644 index 0000000..343e45e --- /dev/null +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/db/Candidate.java @@ -0,0 +1,41 @@ +package de.twomartens.wahlrecht.model.db; + +import java.util.Date; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.FieldDefaults; +import org.bson.types.ObjectId; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document +@Getter +@Setter +@Builder +@EqualsAndHashCode +@ToString +@FieldDefaults(level = AccessLevel.PRIVATE) +@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class Candidate { + + @Id + ObjectId id; + @CreatedDate + Date created; + @LastModifiedDate + Date lastModified; + + @Indexed + String name; + String profession; +} diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/db/Constituency.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/db/Constituency.java new file mode 100644 index 0000000..ddc7685 --- /dev/null +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/db/Constituency.java @@ -0,0 +1,43 @@ +package de.twomartens.wahlrecht.model.db; + +import java.time.Instant; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.FieldDefaults; +import org.bson.types.ObjectId; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.mongodb.core.index.CompoundIndex; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document +@Getter +@Setter +@Builder +@EqualsAndHashCode +@ToString +@FieldDefaults(level = AccessLevel.PRIVATE) +@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@CompoundIndex(def = "{'number': 1, 'electionName': 1}") +public class Constituency { + + @Id + ObjectId id; + @CreatedDate + Instant created; + @LastModifiedDate + Instant lastModified; + + int number; + String electionName; + String name; + int numberOfSeats; +} diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/db/Election.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/db/Election.java new file mode 100644 index 0000000..ffabe9c --- /dev/null +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/db/Election.java @@ -0,0 +1,47 @@ +package de.twomartens.wahlrecht.model.db; + +import de.twomartens.wahlrecht.model.dto.v1.VotingThreshold; +import java.time.LocalDate; +import java.util.Collection; +import java.util.Date; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.FieldDefaults; +import org.bson.types.ObjectId; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document +@Getter +@Setter +@Builder +@EqualsAndHashCode +@ToString +@FieldDefaults(level = AccessLevel.PRIVATE) +@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class Election { + + @Id + ObjectId id; + @CreatedDate + Date created; + @LastModifiedDate + Date lastModified; + + @Indexed(unique = true) + String name; + LocalDate day; + VotingThreshold votingThreshold; + int totalNumberOfSeats; + Collection constituencies; +} diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/db/Nomination.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/db/Nomination.java new file mode 100644 index 0000000..8f17df0 --- /dev/null +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/db/Nomination.java @@ -0,0 +1,49 @@ +package de.twomartens.wahlrecht.model.db; + +import java.util.Collection; +import java.util.Date; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.FieldDefaults; +import org.bson.types.ObjectId; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.mongodb.core.index.CompoundIndex; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document +@Getter +@Setter +@Builder +@EqualsAndHashCode +@ToString +@FieldDefaults(level = AccessLevel.PRIVATE) +@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@CompoundIndex(def = "{'name': 1, 'partyAbbreviation': 1, 'electionName': 1}") +public class Nomination { + + @Id + ObjectId id; + @CreatedDate + Date created; + @LastModifiedDate + Date lastModified; + + String name; + String partyAbbreviation; + String electionName; + Collection candidates; + boolean supportVotesOnNomination; + + public boolean supportsVotesOnNomination() { + return supportVotesOnNomination; + } +} diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/db/PartyInElection.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/db/PartyInElection.java new file mode 100644 index 0000000..e0f3b2c --- /dev/null +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/db/PartyInElection.java @@ -0,0 +1,46 @@ +package de.twomartens.wahlrecht.model.db; + +import java.util.Date; +import java.util.Map; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.FieldDefaults; +import org.bson.types.ObjectId; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.mongodb.core.index.CompoundIndex; +import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document +@Getter +@Setter +@Builder +@EqualsAndHashCode +@ToString +@FieldDefaults(level = AccessLevel.PRIVATE) +@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@CompoundIndex(def = "{'abbreviation': 1, 'electionName': 1}") +public class PartyInElection { + + @Id + ObjectId id; + @CreatedDate + Date created; + @LastModifiedDate + Date lastModified; + + String abbreviation; + String electionName; + String name; + Nomination overallNomination; + Map constituencyNominations; +} diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/Candidate.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/Candidate.java similarity index 57% rename from module-server/src/main/java/de/twomartens/wahlrecht/model/Candidate.java rename to module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/Candidate.java index 75cf245..a0690e8 100644 --- a/module-server/src/main/java/de/twomartens/wahlrecht/model/Candidate.java +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/Candidate.java @@ -1,4 +1,4 @@ -package de.twomartens.wahlrecht.model; +package de.twomartens.wahlrecht.model.dto.v1; public record Candidate(String name, String profession) { diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/Constituency.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/Constituency.java new file mode 100644 index 0000000..1e30e91 --- /dev/null +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/Constituency.java @@ -0,0 +1,9 @@ +package de.twomartens.wahlrecht.model.dto.v1; + +public record Constituency(String electionName, int number, String name, int numberOfSeats) { + + @Override + public String toString() { + return name; + } +} diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/Elected.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/Elected.java similarity index 69% rename from module-server/src/main/java/de/twomartens/wahlrecht/model/Elected.java rename to module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/Elected.java index 7207896..ece82f8 100644 --- a/module-server/src/main/java/de/twomartens/wahlrecht/model/Elected.java +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/Elected.java @@ -1,4 +1,4 @@ -package de.twomartens.wahlrecht.model; +package de.twomartens.wahlrecht.model.dto.v1; public enum Elected { NOT_ELECTED, diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/ElectedCandidate.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/ElectedCandidate.java similarity index 81% rename from module-server/src/main/java/de/twomartens/wahlrecht/model/ElectedCandidate.java rename to module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/ElectedCandidate.java index c27d5bd..1f71cf3 100644 --- a/module-server/src/main/java/de/twomartens/wahlrecht/model/ElectedCandidate.java +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/ElectedCandidate.java @@ -1,6 +1,7 @@ -package de.twomartens.wahlrecht.model; +package de.twomartens.wahlrecht.model.dto.v1; public record ElectedCandidate(Candidate candidate, Elected elected) { + public String name() { return candidate.name(); } diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/ElectedResult.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/ElectedResult.java new file mode 100644 index 0000000..de506db --- /dev/null +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/ElectedResult.java @@ -0,0 +1,14 @@ +package de.twomartens.wahlrecht.model.dto.v1; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import lombok.Builder; + +@Builder +public record ElectedResult(Map> electedCandidates, + LinkedList usedElectionNumbers) { + +} diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/Election.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/Election.java similarity index 84% rename from module-server/src/main/java/de/twomartens/wahlrecht/model/Election.java rename to module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/Election.java index 87d84dd..aa23fb7 100644 --- a/module-server/src/main/java/de/twomartens/wahlrecht/model/Election.java +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/Election.java @@ -1,4 +1,4 @@ -package de.twomartens.wahlrecht.model; +package de.twomartens.wahlrecht.model.dto.v1; import java.time.LocalDate; import java.util.Collection; diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/Nomination.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/Nomination.java new file mode 100644 index 0000000..1489b03 --- /dev/null +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/Nomination.java @@ -0,0 +1,9 @@ +package de.twomartens.wahlrecht.model.dto.v1; + +import java.util.List; + +public record Nomination(String name, String partyAbbreviation, String electionName, + boolean supportVotesOnNomination, + List candidates) { + +} diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/PartyInElection.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/PartyInElection.java new file mode 100644 index 0000000..0d535a7 --- /dev/null +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/PartyInElection.java @@ -0,0 +1,12 @@ +package de.twomartens.wahlrecht.model.dto.v1; + +import java.util.Map; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +public record PartyInElection(String electionName, String abbreviation, String name, + Nomination overallNomination, + Map constituencyNominations) { + +} diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/SeatResult.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/SeatResult.java new file mode 100644 index 0000000..af4942c --- /dev/null +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/SeatResult.java @@ -0,0 +1,13 @@ +package de.twomartens.wahlrecht.model.dto.v1; + +import java.util.LinkedList; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import lombok.Builder; + +@Builder +public record SeatResult(Map seatsPerResult, + LinkedList usedElectionNumbers) { + +} diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/VotingResult.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/VotingResult.java new file mode 100644 index 0000000..b30d459 --- /dev/null +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/VotingResult.java @@ -0,0 +1,10 @@ +package de.twomartens.wahlrecht.model.dto.v1; + +import java.util.Map; +import lombok.Builder; +import lombok.Getter; + +public record VotingResult(int votesOnNomination, int votesThroughHealing, Integer totalVotes, + Map votesPerPosition, String nominationName) { + +} diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/VotingThreshold.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/VotingThreshold.java similarity index 85% rename from module-server/src/main/java/de/twomartens/wahlrecht/model/VotingThreshold.java rename to module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/VotingThreshold.java index f5412f2..a611927 100644 --- a/module-server/src/main/java/de/twomartens/wahlrecht/model/VotingThreshold.java +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/dto/v1/VotingThreshold.java @@ -1,4 +1,4 @@ -package de.twomartens.wahlrecht.model; +package de.twomartens.wahlrecht.model.dto.v1; import lombok.AccessLevel; import lombok.Getter; diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/Candidate.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/Candidate.java new file mode 100644 index 0000000..587b64b --- /dev/null +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/Candidate.java @@ -0,0 +1,5 @@ +package de.twomartens.wahlrecht.model.internal; + +public record Candidate(String name, String profession) { + +} diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/Constituency.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/Constituency.java new file mode 100644 index 0000000..81440d3 --- /dev/null +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/Constituency.java @@ -0,0 +1,9 @@ +package de.twomartens.wahlrecht.model.internal; + +public record Constituency(String electionName, int number, String name, int numberOfSeats) { + + @Override + public String toString() { + return name; + } +} diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/Elected.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/Elected.java new file mode 100644 index 0000000..672e1c3 --- /dev/null +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/Elected.java @@ -0,0 +1,8 @@ +package de.twomartens.wahlrecht.model.internal; + +public enum Elected { + NOT_ELECTED, + CONSTITUENCY, + OVERALL_NOMINATION_ORDER, + OVERALL_VOTE_ORDER +} diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/ElectedCandidate.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/ElectedCandidate.java new file mode 100644 index 0000000..217cc41 --- /dev/null +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/ElectedCandidate.java @@ -0,0 +1,13 @@ +package de.twomartens.wahlrecht.model.internal; + + +public record ElectedCandidate(Candidate candidate, Elected elected) { + + public String name() { + return candidate.name(); + } + + public String profession() { + return candidate.profession(); + } +} diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/ElectedResult.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/ElectedResult.java similarity index 76% rename from module-server/src/main/java/de/twomartens/wahlrecht/model/ElectedResult.java rename to module-server/src/main/java/de/twomartens/wahlrecht/model/internal/ElectedResult.java index 9630838..1ba7ccc 100644 --- a/module-server/src/main/java/de/twomartens/wahlrecht/model/ElectedResult.java +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/ElectedResult.java @@ -1,7 +1,7 @@ -package de.twomartens.wahlrecht.model; +package de.twomartens.wahlrecht.model.internal; import java.util.Collection; -import java.util.Deque; +import java.util.LinkedList; import java.util.Map; import java.util.Map.Entry; import java.util.stream.Collectors; @@ -9,7 +9,7 @@ import lombok.Builder; @Builder public record ElectedResult(Map> electedCandidates, - Deque usedElectionNumbers) { + LinkedList usedElectionNumbers) { public Map> electedCandidatesByNomination() { return electedCandidates.entrySet().stream() diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/Election.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/Election.java new file mode 100644 index 0000000..87f5d30 --- /dev/null +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/Election.java @@ -0,0 +1,10 @@ +package de.twomartens.wahlrecht.model.internal; + +import java.time.LocalDate; +import java.util.Collection; + +public record Election(String name, LocalDate day, VotingThreshold votingThreshold, + int totalNumberOfSeats, + Collection constituencies) { + +} diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/Nomination.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/Nomination.java similarity index 92% rename from module-server/src/main/java/de/twomartens/wahlrecht/model/Nomination.java rename to module-server/src/main/java/de/twomartens/wahlrecht/model/internal/Nomination.java index bf8b289..b454d4a 100644 --- a/module-server/src/main/java/de/twomartens/wahlrecht/model/Nomination.java +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/Nomination.java @@ -1,4 +1,4 @@ -package de.twomartens.wahlrecht.model; +package de.twomartens.wahlrecht.model.internal; import java.util.ArrayList; import java.util.Arrays; @@ -13,12 +13,15 @@ import lombok.ToString.Include; @RequiredArgsConstructor @ToString(onlyExplicitlyIncluded = true) public class Nomination { - private final List candidates = new ArrayList<>(); - private final Map candidateToPosition = new HashMap<>(); - private final Map positionToCandidate = new HashMap<>(); + + private final String electionName; + private final String partyAbbreviation; @Include private final String name; private final boolean supportVotesOnNomination; + private final List candidates = new ArrayList<>(); + private final Map candidateToPosition = new HashMap<>(); + private final Map positionToCandidate = new HashMap<>(); private void addCandidate(Candidate candidate) { candidates.add(candidate); diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/SeatResult.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/SeatResult.java similarity index 73% rename from module-server/src/main/java/de/twomartens/wahlrecht/model/SeatResult.java rename to module-server/src/main/java/de/twomartens/wahlrecht/model/internal/SeatResult.java index c6647c9..ca95cbe 100644 --- a/module-server/src/main/java/de/twomartens/wahlrecht/model/SeatResult.java +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/SeatResult.java @@ -1,6 +1,6 @@ -package de.twomartens.wahlrecht.model; +package de.twomartens.wahlrecht.model.internal; -import java.util.Deque; +import java.util.LinkedList; import java.util.Map; import java.util.Map.Entry; import java.util.stream.Collectors; @@ -8,7 +8,7 @@ import lombok.Builder; @Builder public record SeatResult(Map seatsPerResult, - Deque usedElectionNumbers) { + LinkedList usedElectionNumbers) { public Map seatsPerNomination() { return seatsPerResult.entrySet().stream() diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/VotingResult.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/VotingResult.java similarity index 95% rename from module-server/src/main/java/de/twomartens/wahlrecht/model/VotingResult.java rename to module-server/src/main/java/de/twomartens/wahlrecht/model/internal/VotingResult.java index 5ed5536..28ea5f7 100644 --- a/module-server/src/main/java/de/twomartens/wahlrecht/model/VotingResult.java +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/VotingResult.java @@ -1,4 +1,4 @@ -package de.twomartens.wahlrecht.model; +package de.twomartens.wahlrecht.model.internal; import java.util.Map; import lombok.Builder; diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/VotingThreshold.java b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/VotingThreshold.java new file mode 100644 index 0000000..95148d6 --- /dev/null +++ b/module-server/src/main/java/de/twomartens/wahlrecht/model/internal/VotingThreshold.java @@ -0,0 +1,15 @@ +package de.twomartens.wahlrecht.model.internal; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +public enum VotingThreshold { + NONE(0.00), + THREE(0.03), + FIVE(0.05); + + private final double multiplier; +} diff --git a/module-server/src/main/java/de/twomartens/wahlrecht/service/CalculationService.java b/module-server/src/main/java/de/twomartens/wahlrecht/service/CalculationService.java index 81ae60d..0b42393 100644 --- a/module-server/src/main/java/de/twomartens/wahlrecht/service/CalculationService.java +++ b/module-server/src/main/java/de/twomartens/wahlrecht/service/CalculationService.java @@ -1,21 +1,20 @@ package de.twomartens.wahlrecht.service; -import de.twomartens.wahlrecht.model.Candidate; -import de.twomartens.wahlrecht.model.Constituency; -import de.twomartens.wahlrecht.model.Elected; -import de.twomartens.wahlrecht.model.ElectedCandidate; -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 de.twomartens.wahlrecht.model.internal.Candidate; +import de.twomartens.wahlrecht.model.internal.Constituency; +import de.twomartens.wahlrecht.model.internal.Elected; +import de.twomartens.wahlrecht.model.internal.ElectedCandidate; +import de.twomartens.wahlrecht.model.internal.ElectedResult; +import de.twomartens.wahlrecht.model.internal.Election; +import de.twomartens.wahlrecht.model.internal.Nomination; +import de.twomartens.wahlrecht.model.internal.SeatResult; +import de.twomartens.wahlrecht.model.internal.VotingResult; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; -import java.util.Deque; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -26,7 +25,8 @@ import org.springframework.stereotype.Service; @Service public class CalculationService { - private final Deque electionNumberHistory = new ArrayDeque<>(); + + private final LinkedList electionNumberHistory = new LinkedList<>(); public ElectedResult calculateConstituency(@NonNull Constituency constituency, @NonNull Collection votingResults) { @@ -76,7 +76,8 @@ public class CalculationService { .build(); } - public ElectedResult calculateElectedOverallCandidates(Map seatsPerNomination, + public ElectedResult calculateElectedOverallCandidates( + Map seatsPerNomination, Map> electedCandidates) { electionNumberHistory.clear(); @@ -161,7 +162,8 @@ public class CalculationService { return elected; } - private static int calculateSeatsByNominationOrder(@NonNull VotingResult votingResult, int numberOfSeats) { + private static int calculateSeatsByNominationOrder(@NonNull VotingResult votingResult, + int numberOfSeats) { int votesOnNomination = votingResult.getVotesOnNomination(); int totalVotes = votingResult.getTotalVotesWithoutHealing(); return (int) Math.round((numberOfSeats * votesOnNomination) / (double) totalVotes); @@ -199,7 +201,6 @@ public class CalculationService { } } while (assignedSeats != numberOfSeats); - return assignedSeatsPerVotingResult; } @@ -232,7 +233,6 @@ public class CalculationService { } - private double calculateAssignedSeatNumber(double electionNumber, int totalVotesOfNomination) { return totalVotesOfNomination / electionNumber; } diff --git a/module-server/src/test/java/de/twomartens/wahlrecht/service/CalculationServiceTest.java b/module-server/src/test/java/de/twomartens/wahlrecht/service/CalculationServiceTest.java index cd16a89..894d708 100644 --- a/module-server/src/test/java/de/twomartens/wahlrecht/service/CalculationServiceTest.java +++ b/module-server/src/test/java/de/twomartens/wahlrecht/service/CalculationServiceTest.java @@ -1,15 +1,15 @@ package de.twomartens.wahlrecht.service; -import de.twomartens.wahlrecht.model.Candidate; -import de.twomartens.wahlrecht.model.Constituency; -import de.twomartens.wahlrecht.model.Elected; -import de.twomartens.wahlrecht.model.ElectedCandidate; -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 de.twomartens.wahlrecht.model.internal.Candidate; +import de.twomartens.wahlrecht.model.internal.Constituency; +import de.twomartens.wahlrecht.model.internal.Elected; +import de.twomartens.wahlrecht.model.internal.ElectedCandidate; +import de.twomartens.wahlrecht.model.internal.ElectedResult; +import de.twomartens.wahlrecht.model.internal.Election; +import de.twomartens.wahlrecht.model.internal.Nomination; +import de.twomartens.wahlrecht.model.internal.SeatResult; +import de.twomartens.wahlrecht.model.internal.VotingResult; +import de.twomartens.wahlrecht.model.internal.VotingThreshold; import java.time.LocalDate; import java.time.Month; import java.util.Arrays; @@ -27,6 +27,7 @@ import org.springframework.lang.NonNull; class CalculationServiceTest { + private static final String BEZIRKSWAHL = "Bezirkswahl 2019"; public static final String GOTTLIEB_GABOR = "Gottlieb, Gabor"; public static final String RIEGEL_ANN_KATHRIN = "Riegel, Ann-Kathrin"; public static final String HOEFLICH_JUTTA = "Höflich, Jutta"; @@ -48,58 +49,58 @@ class CalculationServiceTest { public static final String ERK_ARAMAK = "Erk, Aramak"; public static final String DR_FISCHER_JOST_LEONHARDT = "Dr. Fischer, Jost Leonhardt"; public static final String KUELL_GABRIELA = "Küll, Gabriela"; - 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 Constituency EIMSBUETTEL_NORD = new Constituency(BEZIRKSWAHL, 1, "Eimsbüttel-Nord", 3); + private static final Constituency EIMSBUETTEL_SUED = new Constituency(BEZIRKSWAHL, 2, "Eimsbüttel-Süd", 5); + private static final Constituency HARO = new Constituency(BEZIRKSWAHL, 3, "Rotherbaum/Harvestehude", 4); + private static final Constituency LOKSTEDT = new Constituency(BEZIRKSWAHL, 4, "Lokstedt", 3); + private static final Constituency NIENDORF = new Constituency(BEZIRKSWAHL, 5, "Niendorf", 5); + private static final Constituency SCHNELSEN = new Constituency(BEZIRKSWAHL, 6, "Schnelsen", 3); + private static final Constituency EIDELSTEDT = new Constituency(BEZIRKSWAHL, 7, "Eidelstedt", 4); + private static final Constituency STELLINGEN = new Constituency(BEZIRKSWAHL, 8, "Stellingen", 3); + private static final Nomination SPD_NIENDORF = buildNomination("SPD", "SPD-Niendorf", false); private static final VotingResult SPD_NIENDORF_RESULT = buildVotingResult(SPD_NIENDORF, 0, 0, 11882, 7617, 1946, 1743, 1363, 762, 895, 1598, 1786, 781); - private static final Nomination CDU_NIENDORF = buildNomination("CDU-Niendorf", false); + private static final Nomination CDU_NIENDORF = buildNomination("CDU", "CDU-Niendorf", false); public static final VotingResult CDU_NIENDORF_RESULT = buildVotingResult(CDU_NIENDORF, 0, 0, 10733, 4550, 2310, 2333, 2565); - private static final Nomination FDP_NIENDORF = buildNomination("FDP-Niendorf", false); + private static final Nomination FDP_NIENDORF = buildNomination("FDP", "FDP-Niendorf", false); public static final VotingResult FDP_NIENDORF_RESULT = buildVotingResult(FDP_NIENDORF, 0, 0, 2498, 3200, 992); - private static final Nomination LINKE_NIENDORF = buildNomination("LINKE-Niendorf", false); + private static final Nomination LINKE_NIENDORF = buildNomination("LINKE", "LINKE-Niendorf", false); public static final VotingResult LINKE_NIENDORF_RESULT = buildVotingResult(LINKE_NIENDORF, 0, 0, 3782, 1584, 1185); - private static final Nomination GRUENE_NIENDORF = buildNomination("GRUENE-Niendorf", false); + private static final Nomination GRUENE_NIENDORF = buildNomination("GRUENE", "GRUENE-Niendorf", false); public static final VotingResult GRUENE_NIENDORF_RESULT = buildVotingResult(GRUENE_NIENDORF, 0, 0, 14838, 12501); - private static final Nomination AFD_NIENDORF = buildNomination("AFD-Niendorf", false); + private static final Nomination AFD_NIENDORF = buildNomination("AFD", "AFD-Niendorf", false); public static final VotingResult AFD_NIENDORF_RESULT = buildVotingResult(AFD_NIENDORF, 0, 0, 6616); - private static final Nomination SPD_BEZIRK = buildNomination("SPD-Bezirk", true); + private static final Nomination SPD_BEZIRK = buildNomination("SPD", "SPD-Bezirk", true); public static final VotingResult SPD_BEZIRK_RESULT = buildVotingResult(SPD_BEZIRK, 84703, 985, 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); - private static final Nomination CDU_BEZIRK = buildNomination("CDU-Bezirk", true); + private static final Nomination CDU_BEZIRK = buildNomination("CDU", "CDU-Bezirk", true); public static final VotingResult CDU_BEZIRK_RESULT = buildVotingResult(CDU_BEZIRK, 66245, 660, 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); - private static final Nomination FDP_BEZIRK = buildNomination("FDP-Bezirk", true); + private static final Nomination FDP_BEZIRK = buildNomination("FDP", "FDP-Bezirk", true); public static final VotingResult FDP_BEZIRK_RESULT = buildVotingResult(FDP_BEZIRK, 24435, 240, 3528, 1964, 1633, 897, 1193, 355, 401, 1012, 496, 1242, 643, 300, 311, 998, 505, 2181); - private static final Nomination LINKE_BEZIRK = buildNomination("LINKE-Bezirk", true); + private static final Nomination LINKE_BEZIRK = buildNomination("LINKE", "LINKE-Bezirk", true); public static final VotingResult LINKE_BEZIRK_RESULT = buildVotingResult(LINKE_BEZIRK, 47452, 330, 4890, 875, 1532, 1293, 2321, 696, 1843, 2212, 1488, 483, 764, 572, 892); - private static final Nomination GRUENE_BEZIRK = buildNomination("GRUENE-Bezirk", true); + private static final Nomination GRUENE_BEZIRK = buildNomination("GRUENE", "GRUENE-Bezirk", true); public static final VotingResult GRUENE_BEZIRK_RESULT = buildVotingResult(GRUENE_BEZIRK, 150842, 900, 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); - private static final Nomination AFD_BEZIRK = buildNomination("AFD-Bezirk", true); + private static final Nomination AFD_BEZIRK = buildNomination("AFD", "AFD-Bezirk", true); public static final VotingResult AFD_BEZIRK_RESULT = buildVotingResult(AFD_BEZIRK, 21625, 220, 1226, 1950, 3007, 874, 1032, 780, 535, 221, 283); - private static final Nomination PIRATEN_BEZIRK = buildNomination("Piraten-Bezirk", true); + private static final Nomination PIRATEN_BEZIRK = buildNomination("PIRATEN", "Piraten-Bezirk", true); public static final VotingResult PIRATEN_BEZIRK_RESULT = buildVotingResult(PIRATEN_BEZIRK, 6715, 25, 871, 1907, 987); @@ -220,8 +221,9 @@ class CalculationServiceTest { )); } - private static Nomination buildNomination(String name, boolean supportVotesOnNomination) { - return new Nomination(name, supportVotesOnNomination); + private static Nomination buildNomination(String partyAbbreviation, + String name, boolean supportVotesOnNomination) { + return new Nomination(BEZIRKSWAHL, partyAbbreviation, name, supportVotesOnNomination); } private static Collection buildCandidates(String... names) {