added sync point after trump determination

main
Jonah Bauer 3 years ago
parent c89026c6e1
commit 640443abbc

@ -7,6 +7,7 @@ object Log4j2 {
const val api = "$group:log4j-api:$version" const val api = "$group:log4j-api:$version"
const val core = "$group:log4j-core:$version" const val core = "$group:log4j-core:$version"
const val slf4j = "$group:log4j-slf4j-impl:$version" const val slf4j = "$group:log4j-slf4j-impl:$version"
const val jul = "$group:log4j-jul:$version"
} }
object Lombok { object Lombok {
@ -86,7 +87,7 @@ object JavaWebSocket {
} }
object SpringBoot { object SpringBoot {
const val version = "2.6.1" const val version = "2.6.2"
const val group = "org.springframework.boot" const val group = "org.springframework.boot"
const val plugin = group const val plugin = group
const val starterWebsocket = "$group:spring-boot-starter-websocket" const val starterWebsocket = "$group:spring-boot-starter-websocket"

@ -0,0 +1,53 @@
package eu.jonahbauer.wizard.core.machine.states;
import eu.jonahbauer.wizard.common.messages.observer.TimeoutMessage;
import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage;
import eu.jonahbauer.wizard.common.messages.player.ContinueMessage;
import eu.jonahbauer.wizard.common.messages.player.PlayerMessage;
import eu.jonahbauer.wizard.core.machine.Game;
import eu.jonahbauer.wizard.core.machine.GameState;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import static eu.jonahbauer.wizard.common.messages.observer.UserInputMessage.Action.SYNC;
import static eu.jonahbauer.wizard.core.machine.states.GameData.PLAYERS;
public abstract class SyncState extends GameState {
private final transient Set<UUID> ready = new HashSet<>();
public SyncState(GameData data) {
super(data);
}
@Override
public Optional<GameState> onEnter(Game game) {
game.notify(new UserInputMessage(null, SYNC, getSyncTimeout(game, true)));
return syncTimeout(game);
}
@Override
public Optional<GameState> onMessage(Game game, UUID player, PlayerMessage message) {
if (message instanceof ContinueMessage) {
ready.add(player);
if (ready.size() == get(PLAYERS).size()) {
return Optional.of(getNextState());
} else {
return Optional.empty();
}
} else {
return super.onMessage(game, player, message);
}
}
@Override
public Optional<GameState> onTimeout(Game game) {
game.notify(new TimeoutMessage());
return Optional.of(getNextState());
}
protected abstract GameState getNextState();
}

@ -103,6 +103,6 @@ public final class DeterminingTrump extends RoundState {
} else { } else {
game.notify(new TrumpMessage(get(TRUMP_CARD), trumpSuit)); game.notify(new TrumpMessage(get(TRUMP_CARD), trumpSuit));
} }
return transition(new Predicting(data)); return transition(new TrumpDetermined(data));
} }
} }

@ -8,8 +8,12 @@ import java.util.UUID;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*; import static eu.jonahbauer.wizard.core.machine.states.GameData.*;
public abstract class RoundState extends GameState { public abstract class RoundState extends GameState {
public static GameData requirements(GameData data) {
return data.require(PLAYERS, ROUND, SCORE);
}
public RoundState(GameData data) { public RoundState(GameData data) {
super(data.require(PLAYERS, ROUND, SCORE)); super(requirements(data));
} }
protected UUID getDealer() { protected UUID getDealer() {

@ -1,52 +1,17 @@
package eu.jonahbauer.wizard.core.machine.states.round; package eu.jonahbauer.wizard.core.machine.states.round;
import eu.jonahbauer.wizard.common.messages.observer.TimeoutMessage;
import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage;
import eu.jonahbauer.wizard.common.messages.player.ContinueMessage;
import eu.jonahbauer.wizard.common.messages.player.PlayerMessage;
import eu.jonahbauer.wizard.core.machine.Game;
import eu.jonahbauer.wizard.core.machine.GameState; import eu.jonahbauer.wizard.core.machine.GameState;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.machine.states.GameData;
import eu.jonahbauer.wizard.core.machine.states.SyncState;
import java.util.HashSet; public final class StartingRound extends SyncState {
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import static eu.jonahbauer.wizard.common.messages.observer.UserInputMessage.Action.SYNC;
import static eu.jonahbauer.wizard.core.machine.states.GameData.PLAYERS;
public final class StartingRound extends RoundState {
private final transient Set<UUID> ready = new HashSet<>();
public StartingRound(GameData data) { public StartingRound(GameData data) {
super(data); super(RoundState.requirements(data));
}
@Override
public Optional<GameState> onEnter(Game game) {
game.notify(new UserInputMessage(null, SYNC, getSyncTimeout(game, true)));
return syncTimeout(game);
}
@Override
public Optional<GameState> onMessage(Game game, UUID player, PlayerMessage message) {
if (message instanceof ContinueMessage) {
ready.add(player);
if (ready.size() == get(PLAYERS).size()) {
return Optional.of(new Dealing(getData()));
} else {
return Optional.empty();
}
} else {
return super.onMessage(game, player, message);
}
} }
@Override @Override
public Optional<GameState> onTimeout(Game game) { protected GameState getNextState() {
game.notify(new TimeoutMessage()); return new Dealing(getData());
return Optional.of(new Dealing(getData()));
} }
} }

@ -0,0 +1,19 @@
package eu.jonahbauer.wizard.core.machine.states.round;
import eu.jonahbauer.wizard.core.machine.GameState;
import eu.jonahbauer.wizard.core.machine.states.GameData;
import eu.jonahbauer.wizard.core.machine.states.SyncState;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*;
public final class TrumpDetermined extends SyncState {
public TrumpDetermined(GameData data) {
super(RoundState.requirements(data).requireEach(PLAYERS, HANDS).require(PREDICTIONS, TRUMP_SUIT, CURRENT_PLAYER));
}
@Override
protected GameState getNextState() {
return new Predicting(getData());
}
}

@ -1,52 +1,18 @@
package eu.jonahbauer.wizard.core.machine.states.trick; package eu.jonahbauer.wizard.core.machine.states.trick;
import eu.jonahbauer.wizard.common.messages.observer.TimeoutMessage;
import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage;
import eu.jonahbauer.wizard.common.messages.player.ContinueMessage;
import eu.jonahbauer.wizard.common.messages.player.PlayerMessage;
import eu.jonahbauer.wizard.core.machine.Game;
import eu.jonahbauer.wizard.core.machine.states.GameData;
import eu.jonahbauer.wizard.core.machine.GameState; import eu.jonahbauer.wizard.core.machine.GameState;
import eu.jonahbauer.wizard.core.machine.states.GameData;
import eu.jonahbauer.wizard.core.machine.states.SyncState;
import eu.jonahbauer.wizard.core.machine.states.round.RoundState;
import java.util.HashSet; public final class StartingTrick extends SyncState {
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import static eu.jonahbauer.wizard.common.messages.observer.UserInputMessage.Action.SYNC;
import static eu.jonahbauer.wizard.core.machine.states.GameData.PLAYERS;
public final class StartingTrick extends TrickState {
private final transient Set<UUID> ready = new HashSet<>();
public StartingTrick(GameData data) { public StartingTrick(GameData data) {
super(data); super(RoundState.requirements(TrickState.requirements(data)));
}
@Override
public Optional<GameState> onEnter(Game game) {
game.notify(new UserInputMessage(null, SYNC, getSyncTimeout(game, true)));
return syncTimeout(game);
}
@Override
public Optional<GameState> onMessage(Game game, UUID player, PlayerMessage message) {
if (message instanceof ContinueMessage) {
ready.add(player);
if (ready.size() == get(PLAYERS).size()) {
return Optional.of(new PlayingCard(getData()));
} else {
return Optional.empty();
}
} else {
return super.onMessage(game, player, message);
}
} }
@Override @Override
public Optional<GameState> onTimeout(Game game) { protected GameState getNextState() {
game.notify(new TimeoutMessage()); return new PlayingCard(getData());
return Optional.of(new PlayingCard(getData()));
} }
} }

@ -6,12 +6,14 @@ import eu.jonahbauer.wizard.core.machine.states.round.RoundState;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*; import static eu.jonahbauer.wizard.core.machine.states.GameData.*;
public abstract class TrickState extends RoundState { public abstract class TrickState extends RoundState {
public static GameData requirements(GameData data) {
return data.requireEach(PLAYERS, HANDS)
.requireEach(PLAYERS, PREDICTIONS)
.require(TRUMP_SUIT, TRICK, TRICKS, CURRENT_PLAYER)
.keep(CLOUDED_PLAYER);
}
public TrickState(GameData data) { public TrickState(GameData data) {
super( super(requirements(data));
data.requireEach(PLAYERS, HANDS)
.requireEach(PLAYERS, PREDICTIONS)
.require(TRUMP_SUIT, TRICK, TRICKS, CURRENT_PLAYER)
.keep(CLOUDED_PLAYER)
);
} }
} }

@ -38,7 +38,7 @@ public class DeterminingTrumpTest {
@SuppressWarnings("SameParameterValue") @SuppressWarnings("SameParameterValue")
private Game performTest(GameConfiguration configuration, int round, Map<UUID, List<Card>> hands, Card trumpCard, MessageQueue queue) { private Game performTest(GameConfiguration configuration, int round, Map<UUID, List<Card>> hands, Card trumpCard, MessageQueue queue) {
Game game = spy(new Game(configuration, queue)); Game game = spy(new Game(configuration, queue));
doFinish().when(game).transition(any(Predicting.class)); doFinish().when(game).transition(any(TrumpDetermined.class));
queue.setGame(game); queue.setGame(game);
var playerList = List.of(players); var playerList = List.of(players);
@ -76,7 +76,7 @@ public class DeterminingTrumpTest {
InOrder order = inOrder(game); InOrder order = inOrder(game);
order.verify(game).notify(any(StateMessage.class)); // determining trump order.verify(game).notify(any(StateMessage.class)); // determining trump
order.verify(game).notify(argThat(msg -> msg instanceof TrumpMessage trump && trump.getCard() == Card.YELLOW_1 && trump.getSuit() == Card.Suit.YELLOW)); order.verify(game).notify(argThat(msg -> msg instanceof TrumpMessage trump && trump.getCard() == Card.YELLOW_1 && trump.getSuit() == Card.Suit.YELLOW));
order.verify(game).transition(any(Predicting.class)); // round is finished order.verify(game).transition(any(TrumpDetermined.class)); // round is finished
order.verify(game).notify(any(StateMessage.class)); // finish order.verify(game).notify(any(StateMessage.class)); // finish
order.verify(game, never()).notify(any()); order.verify(game, never()).notify(any());
order.verify(game, never()).notify(any(), any()); order.verify(game, never()).notify(any(), any());
@ -100,7 +100,7 @@ public class DeterminingTrumpTest {
InOrder order = inOrder(game); InOrder order = inOrder(game);
order.verify(game).notify(any(StateMessage.class)); // determining trump order.verify(game).notify(any(StateMessage.class)); // determining trump
order.verify(game).notify(argThat(msg -> msg instanceof TrumpMessage trump && trump.getCard() == Card.GREEN_JESTER && trump.getSuit() == Card.Suit.NONE)); order.verify(game).notify(argThat(msg -> msg instanceof TrumpMessage trump && trump.getCard() == Card.GREEN_JESTER && trump.getSuit() == Card.Suit.NONE));
order.verify(game).transition(any(Predicting.class)); order.verify(game).transition(any(TrumpDetermined.class));
order.verify(game).notify(any(StateMessage.class)); // finish order.verify(game).notify(any(StateMessage.class)); // finish
order.verify(game, never()).notify(any()); order.verify(game, never()).notify(any());
order.verify(game, never()).notify(any(), any()); order.verify(game, never()).notify(any(), any());
@ -127,7 +127,7 @@ public class DeterminingTrumpTest {
order.verify(game).notify(argThat(msg -> msg instanceof TrumpMessage trump && trump.getCard() == Card.BLUE_WIZARD && trump.getSuit() == null)); order.verify(game).notify(argThat(msg -> msg instanceof TrumpMessage trump && trump.getCard() == Card.BLUE_WIZARD && trump.getSuit() == null));
order.verify(game).notify(any(UserInputMessage.class)); // user input request order.verify(game).notify(any(UserInputMessage.class)); // user input request
order.verify(game).notify(argThat(msg -> msg instanceof TrumpMessage trump && trump.getCard() == Card.BLUE_WIZARD && trump.getSuit() == Card.Suit.GREEN)); order.verify(game).notify(argThat(msg -> msg instanceof TrumpMessage trump && trump.getCard() == Card.BLUE_WIZARD && trump.getSuit() == Card.Suit.GREEN));
order.verify(game).transition(any(Predicting.class)); order.verify(game).transition(any(TrumpDetermined.class));
order.verify(game).notify(any(StateMessage.class)); // finish order.verify(game).notify(any(StateMessage.class)); // finish
order.verify(game, never()).notify(any()); order.verify(game, never()).notify(any());
order.verify(game, never()).notify(any(), any()); order.verify(game, never()).notify(any(), any());
@ -156,7 +156,7 @@ public class DeterminingTrumpTest {
order.verify(game).notify(any(UserInputMessage.class)); // user input request order.verify(game).notify(any(UserInputMessage.class)); // user input request
order.verify(game).notify(argThat(msg -> msg instanceof TrumpMessage trump && trump.getCard() == Card.WEREWOLF && trump.getSuit() == Card.Suit.YELLOW)); order.verify(game).notify(argThat(msg -> msg instanceof TrumpMessage trump && trump.getCard() == Card.WEREWOLF && trump.getSuit() == Card.Suit.YELLOW));
order.verify(game).notify(eq(players[3]), any(HandMessage.class)); // swap trump card and werewolf order.verify(game).notify(eq(players[3]), any(HandMessage.class)); // swap trump card and werewolf
order.verify(game).transition(any(Predicting.class)); order.verify(game).transition(any(TrumpDetermined.class));
order.verify(game).notify(any(StateMessage.class)); // finish order.verify(game).notify(any(StateMessage.class)); // finish
order.verify(game, never()).notify(any()); order.verify(game, never()).notify(any());
order.verify(game, never()).notify(any(), any()); order.verify(game, never()).notify(any(), any());

@ -55,6 +55,7 @@ public class RoundTest {
@Test @Test
public void run_Simple() throws ExecutionException, InterruptedException { public void run_Simple() throws ExecutionException, InterruptedException {
MessageQueue queue = new MessageQueue() MessageQueue queue = new MessageQueue()
.sync(players)
.sync(players) .sync(players)
.addPrediction(players[3], 3) .addPrediction(players[3], 3)
.addPrediction(players[0], 0) .addPrediction(players[0], 0)
@ -113,6 +114,7 @@ public class RoundTest {
order.verify(game, atLeast(4)).notify(any(), any(HandMessage.class)); // hands order.verify(game, atLeast(4)).notify(any(), any(HandMessage.class)); // hands
order.verify(game).notify(any(StateMessage.class)); // determining_trump order.verify(game).notify(any(StateMessage.class)); // determining_trump
order.verify(game).notify(any(TrumpMessage.class)); // trump order.verify(game).notify(any(TrumpMessage.class)); // trump
order.verify(game).notify(any(StateMessage.class)); // trump_determined
for (int i = 0; i < players.length; i++) { for (int i = 0; i < players.length; i++) {
order.verify(game).notify(any(StateMessage.class)); // predicting order.verify(game).notify(any(StateMessage.class)); // predicting
order.verify(game).notify(any(UserInputMessage.class)); // user input order.verify(game).notify(any(UserInputMessage.class)); // user input
@ -148,6 +150,7 @@ public class RoundTest {
MessageQueue queue = new MessageQueue() MessageQueue queue = new MessageQueue()
.sync(players) .sync(players)
.addPickTrump(players[2], Card.Suit.YELLOW) .addPickTrump(players[2], Card.Suit.YELLOW)
.sync(players)
.addPrediction(players[3], 2) .addPrediction(players[3], 2)
.addPrediction(players[0], 2) .addPrediction(players[0], 2)
.addPrediction(players[1], 2) .addPrediction(players[1], 2)
@ -237,8 +240,9 @@ public class RoundTest {
order.verify(game).notify(any(StateMessage.class)); // determining trump order.verify(game).notify(any(StateMessage.class)); // determining trump
order.verify(game, times(2)).notify(any(TrumpMessage.class)); // werewolf order.verify(game, times(2)).notify(any(TrumpMessage.class)); // werewolf
order.verify(game).notify(any(UserInputMessage.class)); // user input order.verify(game).notify(any(UserInputMessage.class)); // user input
order.verify(game).notify(any(TrumpMessage.class)); // user input order.verify(game).notify(any(TrumpMessage.class)); // trump
order.verify(game).notify(any(), any(HandMessage.class)); // update hand order.verify(game).notify(any(), any(HandMessage.class)); // update hand
order.verify(game).notify(any(StateMessage.class)); // trump_determined
for (int i = 0; i < players.length; i++) { for (int i = 0; i < players.length; i++) {
order.verify(game).notify(any(StateMessage.class)); order.verify(game).notify(any(StateMessage.class));
order.verify(game).notify(any(UserInputMessage.class)); order.verify(game).notify(any(UserInputMessage.class));

@ -15,4 +15,10 @@ dependencies {
} }
implementation(SpringBoot.starterLog4j2) implementation(SpringBoot.starterLog4j2)
providedRuntime(SpringBoot.starterTomcat) providedRuntime(SpringBoot.starterTomcat)
// override vulnerable dependencies from spring-boot-starter-log4j2
implementation(Log4j2.api)
implementation(Log4j2.core)
implementation(Log4j2.slf4j)
implementation(Log4j2.jul)
} }

Loading…
Cancel
Save