diff --git a/patterns-modules/clean-architecture/src/main/java/com/baeldung/pattern/richdomainmodel/Player.java b/patterns-modules/clean-architecture/src/main/java/com/baeldung/pattern/richdomainmodel/Player.java new file mode 100644 index 0000000000..f683b1158d --- /dev/null +++ b/patterns-modules/clean-architecture/src/main/java/com/baeldung/pattern/richdomainmodel/Player.java @@ -0,0 +1,35 @@ +package com.baeldung.pattern.richdomainmodel; + +public class Player { + private int points ; + final String name; + + public Player(String name) { + this(name, 0); + } + + private Player(String name, int points) { + this.name = name; + this.points = 0; + } + + public void gainPoint() { + points++; + } + + public boolean hasScoreBiggerThan(Score score) { + return this.points > score.points(); + } + + public int pointsDifference(Player other) { + return points - other.points; + } + + public String name() { + return name; + } + + public String score() { + return Score.from(points).label(); + } +} \ No newline at end of file diff --git a/patterns-modules/clean-architecture/src/main/java/com/baeldung/pattern/richdomainmodel/Score.java b/patterns-modules/clean-architecture/src/main/java/com/baeldung/pattern/richdomainmodel/Score.java new file mode 100644 index 0000000000..da5823763c --- /dev/null +++ b/patterns-modules/clean-architecture/src/main/java/com/baeldung/pattern/richdomainmodel/Score.java @@ -0,0 +1,29 @@ +package com.baeldung.pattern.richdomainmodel; + +import java.util.Arrays; + +public enum Score { + LOVE(0, "Love"), FIFTEEN(1, "Fifteen"), THIRTY(2, "Thirty"), FORTY(3, "Forty"); + + private final int points; + private final String label; + + Score(int points, String label) { + this.points = points; + this.label = label; + } + + public static Score from(int value) { + return Arrays.stream(values()) + .filter(v -> v.points == value) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("no such element: " + value)); + } + + public int points() { + return points; + } + public String label() { + return label; + } +} \ No newline at end of file diff --git a/patterns-modules/clean-architecture/src/main/java/com/baeldung/pattern/richdomainmodel/TennisGame.java b/patterns-modules/clean-architecture/src/main/java/com/baeldung/pattern/richdomainmodel/TennisGame.java new file mode 100644 index 0000000000..30811a2eb9 --- /dev/null +++ b/patterns-modules/clean-architecture/src/main/java/com/baeldung/pattern/richdomainmodel/TennisGame.java @@ -0,0 +1,71 @@ +package com.baeldung.pattern.richdomainmodel; + +public class TennisGame { + private final Player server; + private final Player receiver; + + public TennisGame(String server, String receiver) { + this.server = new Player(server); + this.receiver = new Player(receiver); + } + + public void wonPoint(String playerName) { + if(server.name().equals(playerName)) { + server.gainPoint(); + } else { + receiver.gainPoint(); + } + } + + public String getScore() { + if (gameContinues()) { + return getGameScore(); + } + return "Win for " + leadingPlayer().name(); + } + + private String getGameScore() { + if (isScoreEqual()) { + return getEqualScore(); + } + if (isAdvantage()) { + return "Advantage " + leadingPlayer().name(); + } + return getSimpleScore(); + } + + private boolean isScoreEqual() { + return server.pointsDifference(receiver) == 0; + } + + private boolean isAdvantage() { + return leadingPlayer().hasScoreBiggerThan(Score.FORTY) + && Math.abs(server.pointsDifference(receiver)) == 1; + } + + private boolean isGameFinished() { + return leadingPlayer().hasScoreBiggerThan(Score.FORTY) + && Math.abs(server.pointsDifference(receiver)) >= 2; + } + + private Player leadingPlayer() { + if (server.pointsDifference(receiver) > 0) { + return server; + } + return receiver; + } + + private boolean gameContinues() { + return !isGameFinished(); + } + private String getSimpleScore() { + return String.format("%s-%s", server.score(), receiver.score()); + } + + private String getEqualScore() { + if (server.hasScoreBiggerThan(Score.THIRTY)) { + return "Deuce"; + } + return String.format("%s-All", server.score()); + } +} diff --git a/patterns-modules/clean-architecture/src/test/java/com/baeldung/pattern/richdomainmodel/RichDomainModelUnitTest.java b/patterns-modules/clean-architecture/src/test/java/com/baeldung/pattern/richdomainmodel/RichDomainModelUnitTest.java new file mode 100644 index 0000000000..b620c7e0e2 --- /dev/null +++ b/patterns-modules/clean-architecture/src/test/java/com/baeldung/pattern/richdomainmodel/RichDomainModelUnitTest.java @@ -0,0 +1,33 @@ +package com.baeldung.pattern.richdomainmodel; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +public class RichDomainModelUnitTest { + + @Test + public void givenATennisGame_whenReceiverWinsThreePoints_thenScoreIsFortyLove() { + TennisGame game = new TennisGame("server", "receiver"); + + game.wonPoint("server"); + game.wonPoint("server"); + game.wonPoint("server"); + + assertThat(game.getScore()) + .isEqualTo("Forty-Love"); + } + + @Test + public void givenATennisGame_whenEachPlayerWonTwoPoints_thenScoreIsThirtyAll() { + TennisGame game = new TennisGame("server", "receiver"); + + game.wonPoint("server"); + game.wonPoint("server"); + game.wonPoint("receiver"); + game.wonPoint("receiver"); + + assertThat(game.getScore()) + .isEqualTo("Thirty-All"); + } +} \ No newline at end of file