From 73f6899d332c22e8c0f96dff332180feda41c91b Mon Sep 17 00:00:00 2001 From: Jerome Berclaz Date: Sun, 23 Aug 2020 11:07:04 -0700 Subject: [PATCH] Simplified announcement processing Added more async functions Added unit tests --- .../java/com/leflat/jass/common/Team.java | 2 +- .../leflat/jass/server/GameController.java | 116 ++++++++++++------ .../java/com/leflat/jass/test/MockUi.java | 5 + .../com/leflat/jass/server/AsyncTests.java | 37 +++++- .../com/leflat/jass/server/CommonTests.java | 4 +- 5 files changed, 125 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/leflat/jass/common/Team.java b/src/main/java/com/leflat/jass/common/Team.java index 62a597b..cbffe1e 100644 --- a/src/main/java/com/leflat/jass/common/Team.java +++ b/src/main/java/com/leflat/jass/common/Team.java @@ -51,7 +51,7 @@ public void addPlayer(BasePlayer p) { p.setTeam(this); } - public void addAnnoucementScore(List anouncements) { + public void addAnnouncementScore(List anouncements) { for (var a : anouncements) { currentScore += Card.atout == Card.COLOR_SPADE ? 2 * a.getValue() : a.getValue(); } diff --git a/src/main/java/com/leflat/jass/server/GameController.java b/src/main/java/com/leflat/jass/server/GameController.java index 670c402..c69cf33 100644 --- a/src/main/java/com/leflat/jass/server/GameController.java +++ b/src/main/java/com/leflat/jass/server/GameController.java @@ -196,55 +196,50 @@ Plie playPlie(int startingPlayer) throws PlayerLeftExpection, BrokenRuleExceptio } boolean processAnnouncements() throws PlayerLeftExpection { - boolean validAnnoucements = false; - Map> annoucements = new HashMap<>(); + boolean validAnnouncements = false; BasePlayer playerWithStoeck = null; Announcement highestAnnouncement = null; Team announcingTeam = null; // joueur qui a la plus grosse annonce - for (var p : players) { - var a = p.getAnnouncements(); + for (var player : players) { + var a = player.getAnnouncements(); if (a.isEmpty()) { continue; } - annoucements.put(p.getId(), a); for (var announcement : a) { - LOGGER.info(p + " announces : " + announcement); + LOGGER.info(player + " announces : " + announcement); if (announcement.getType() == Announcement.STOECK) { - playerWithStoeck = p; + playerWithStoeck = player; continue; } if (highestAnnouncement == null || announcement.compareTo(highestAnnouncement) > 0) { highestAnnouncement = announcement; - announcingTeam = p.getTeam(); + announcingTeam = player.getTeam(); } } } if (announcingTeam != null) { // there are announces - for (var p : players) { - if (!annoucements.containsKey(p.getId())) { + for (var player : players) { + var a = player.getAnnouncements(); + if (a.isEmpty()) { continue; } - if ((p.getTeam() == announcingTeam)) { - announcingTeam.addAnnoucementScore(annoucements.get(p.getId())); - for (var p2 : players) { - p2.setAnnouncements(p, annoucements.get(p.getId())); - } - validAnnoucements = true; + if ((player.getTeam() == announcingTeam)) { + announcingTeam.addAnnouncementScore(a); + setAnnoucementsAsync(player, a); + validAnnouncements = true; } - p.clearAnnouncements(); + player.clearAnnouncements(); } - } else if (playerWithStoeck != null) { // no announce but stock - for (var p : players) { - p.setAnnouncements(playerWithStoeck, Collections.singletonList(new Announcement(Announcement.STOECK, null))); - } - int stoeckScore = Card.atout == Card.COLOR_SPADE ? Announcement.VALUES[Announcement.STOECK] * 2 : Announcement.VALUES[Announcement.STOECK]; + } else if (playerWithStoeck != null) { // no announce but stoeck + setAnnoucementsAsync(playerWithStoeck, Collections.singletonList(new Announcement(Announcement.STOECK, null))); // add stock points + int stoeckScore = Card.atout == Card.COLOR_SPADE ? Announcement.VALUES[Announcement.STOECK] * 2 : Announcement.VALUES[Announcement.STOECK]; playerWithStoeck.getTeam().addScore(stoeckScore); playerWithStoeck.clearAnnouncements(); - validAnnoucements = true; + validAnnouncements = true; } - return validAnnoucements; + return validAnnouncements; } int chooseAtout(int playerNumber) throws PlayerLeftExpection { @@ -287,16 +282,12 @@ void chooseTeam() throws PlayerLeftExpection { reorderPlayers(); var order = players.stream().map(BasePlayer::getId).collect(Collectors.toList()); - for (var p : players) { - p.setPlayersOrder(order); - } + setPlayersOrderAsync(order); } void chooseTeamsRandomly() throws PlayerLeftExpection { // préparation du tirage des équipes - for (var player : players) { - player.prepareTeamDrawing(true); - } + prepareTeamDrawingAsync(true); boolean drawingSuccessful; do { @@ -315,9 +306,7 @@ void chooseTeamsRandomly() throws PlayerLeftExpection { // détermine les équipes drawingSuccessful = calculateTeam(cardsDrawn); if (!drawingSuccessful) { - for (var p : players) { - p.prepareTeamDrawing(false); - } + prepareTeamDrawingAsync(false); waitSec(2); } } while (!drawingSuccessful); @@ -505,7 +494,7 @@ void setDrawnCardAsync(BasePlayer player, int position, Card card) throws Player } } - void collectPlieAsync(BasePlayer player) throws PlayerLeftExpection { + void collectPlieAsync(BasePlayer player) throws PlayerLeftExpection { var answers = players.stream() .map(p -> CompletableFuture.supplyAsync(() -> { try { @@ -524,7 +513,7 @@ void collectPlieAsync(BasePlayer player) throws PlayerLeftExpection { } } - void setAtoutAsync(int color, BasePlayer player) throws PlayerLeftExpection { + void setAtoutAsync(int color, BasePlayer player) throws PlayerLeftExpection { var answers = players.stream() .map(p -> CompletableFuture.supplyAsync(() -> { try { @@ -542,4 +531,61 @@ void setAtoutAsync(int color, BasePlayer player) throws PlayerLeftExpection { throw (PlayerLeftExpection) ex.getCause(); } } + + void setAnnoucementsAsync(BasePlayer player, List announcements) throws PlayerLeftExpection { + var answers = players.stream() + .map(p -> CompletableFuture.supplyAsync(() -> { + try { + p.setAnnouncements(player, announcements); + } catch (PlayerLeftExpection playerLeftExpection) { + throw new CompletionException(playerLeftExpection); + } + return 0; + })) + .collect(Collectors.toList()); + + try { + answers.stream().map(CompletableFuture::join).collect(Collectors.toList()); + } catch (CompletionException ex) { + throw (PlayerLeftExpection) ex.getCause(); + } + } + + void setPlayersOrderAsync(List order) throws PlayerLeftExpection { + var answers = players.stream() + .map(p -> CompletableFuture.supplyAsync(() -> { + try { + p.setPlayersOrder(order); + } catch (PlayerLeftExpection playerLeftExpection) { + throw new CompletionException(playerLeftExpection); + } + return 0; + })) + .collect(Collectors.toList()); + + try { + answers.stream().map(CompletableFuture::join).collect(Collectors.toList()); + } catch (CompletionException ex) { + throw (PlayerLeftExpection) ex.getCause(); + } + } + + void prepareTeamDrawingAsync(boolean firstAttempt) throws PlayerLeftExpection { + var answers = players.stream() + .map(p -> CompletableFuture.supplyAsync(() -> { + try { + p.prepareTeamDrawing(firstAttempt); + } catch (PlayerLeftExpection playerLeftExpection) { + throw new CompletionException(playerLeftExpection); + } + return 0; + })) + .collect(Collectors.toList()); + + try { + answers.stream().map(CompletableFuture::join).collect(Collectors.toList()); + } catch (CompletionException ex) { + throw (PlayerLeftExpection) ex.getCause(); + } + } } diff --git a/src/main/java/com/leflat/jass/test/MockUi.java b/src/main/java/com/leflat/jass/test/MockUi.java index fa85ea8..c203452 100644 --- a/src/main/java/com/leflat/jass/test/MockUi.java +++ b/src/main/java/com/leflat/jass/test/MockUi.java @@ -12,6 +12,7 @@ public class MockUi implements IJassUi { private List hand; private IRemotePlayer player; private float delaySeconds = 0; + private boolean hasAskedForNewGame = false; public MockUi(IRemotePlayer player, float delaySeconds) { this.player = player; @@ -149,6 +150,10 @@ public void displayGameResult(Team winningTeam, boolean won) { @Override public boolean getNewGame() { + if (!hasAskedForNewGame) { + hasAskedForNewGame = true; + return true; + } return false; } diff --git a/src/test/java/com/leflat/jass/server/AsyncTests.java b/src/test/java/com/leflat/jass/server/AsyncTests.java index 3d44fdf..80aad3e 100644 --- a/src/test/java/com/leflat/jass/server/AsyncTests.java +++ b/src/test/java/com/leflat/jass/server/AsyncTests.java @@ -10,7 +10,7 @@ public class AsyncTests { @Test - void async_tests() throws PlayerLeftExpection { + void async_error_test() throws PlayerLeftExpection { Card.atout = Card.COLOR_SPADE; RemotePlayer player1 = mock(RemotePlayer.class); RemotePlayer player2 = mock(RemotePlayer.class); @@ -37,4 +37,39 @@ void async_tests() throws PlayerLeftExpection { game.setHandScoreAsync(new int[]{10, 20}, null); }); } + + @Test + void async_test() throws PlayerLeftExpection { + Card.atout = Card.COLOR_SPADE; + RemotePlayer player1 = mock(RemotePlayer.class); + RemotePlayer player2 = mock(RemotePlayer.class); + RemotePlayer player3 = mock(RemotePlayer.class); + RemotePlayer player4 = mock(RemotePlayer.class); + when(player1.getId()).thenReturn(0); + when(player2.getId()).thenReturn(1); + when(player3.getId()).thenReturn(2); + when(player4.getId()).thenReturn(3); + var t1 = new Team(0); + var t2 = new Team(1); + t1.addScore(100); + t2.addScore(200); + when(player1.getTeam()).thenReturn(t1); + when(player2.getTeam()).thenReturn(t1); + when(player3.getTeam()).thenReturn(t2); + when(player4.getTeam()).thenReturn(t2); + + var game = new GameController(0); + game.setNoWait(true); + game.addPlayer(player1); + game.addPlayer(player2); + game.addPlayer(player3); + game.addPlayer(player4); + + game.setTeamsScoreAsync(false); + + verify(player1).setScores(100, 0); + verify(player2).setScores(100, 0); + verify(player3).setScores(200, 0); + verify(player4).setScores(200, 0); + } } diff --git a/src/test/java/com/leflat/jass/server/CommonTests.java b/src/test/java/com/leflat/jass/server/CommonTests.java index cf58d81..20bf883 100644 --- a/src/test/java/com/leflat/jass/server/CommonTests.java +++ b/src/test/java/com/leflat/jass/server/CommonTests.java @@ -94,12 +94,12 @@ public void team_score_test() { ans.add(new Announcement(Announcement.THREE_CARDS, new Card(12))); Card.atout = Card.COLOR_HEART; - team.addAnnoucementScore(ans); + team.addAnnouncementScore(ans); assertEquals(170, team.getScore()); team.resetScore(); Card.atout = Card.COLOR_SPADE; - team.addAnnoucementScore(ans); + team.addAnnouncementScore(ans); assertEquals(340, team.getScore()); assertFalse(team.hasWon());