Skip to content

Commit

Permalink
house keeping
Browse files Browse the repository at this point in the history
  • Loading branch information
pfichtner committed Sep 16, 2023
1 parent 9555128 commit 24bbf25
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 45 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
## Connected n
Eine Umgebung zur Ausführung von Spielen, bei welchem es das Ziel ist, Steine in einer vertikalen, horizontalen oder diagonalen Reihe zu platzieren. Das Spiel wird von dem hier bereitgestellten Server ausgeführt. Die Spieler kommunizieren mit dem Server unter Verwendung eines einfachen textbasierten Protokolls über UDP.

Das Spielprinzip basiert auf [4 Gewinnt](https://de.wikipedia.org/wiki/Vier_gewinnt) bzw. [connect four](https://en.wikipedia.org/wiki/Connect_Four). Die Brettgröße sowie die Anzahl verbundener Steine kann konfiguriert werden.
Das Spielprinzip basiert auf [4 Gewinnt](https://de.wikipedia.org/wiki/Vier_gewinnt) bzw. [connect four](https://en.wikipedia.org/wiki/Connect_Four). Die Brettgröße sowie die Anzahl zu verbindender Steine kann konfiguriert werden.

Die Idee für diese Coding Challenge wurde schamlos von Jan Ernsting (Mäxchen), welcher nach eigenen Angaben schamlos von Nicolas Botzet und Steven Collins (Poker) kopierte, kopiert. :-D

Expand Down
3 changes: 1 addition & 2 deletions core/src/main/java/org/ase/fourwins/season/Match.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@

@Value
public class Match<T> {
private final T team1;
private final T team2;
T team1, team2;
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,17 @@ public class DefaultTournament implements Tournament {
static final class CoffeebreakGame implements Game {

static final String COFFEE_BREAK_WIN_MESSAGE = "coffee break";

private static final BoardInfo boardInfo = BoardInfo.builder().columns(0).rows(0).build();

private final Player other;

@Getter
private final GameId id;

@Override
public BoardInfo getBoardInfo() {
return BoardInfo.builder().columns(0).rows(0).build();
return boardInfo;
}

@Override
Expand Down Expand Up @@ -114,12 +118,13 @@ private List<Player> addCoffeeBreakPlayer(List<Player> players) {
private Game newGame(Match<Player> match) {
// TODO change gameId to "<season>/<gameNo>"
GameId gameId = GameId.random();
if (isCoffeBreak(match.getTeam1())) {
return new CoffeebreakGame(match.getTeam2(), gameId);
} else if (isCoffeBreak(match.getTeam2())) {
return new CoffeebreakGame(match.getTeam1(), gameId);
}
return new DefaultGame(moveListener, makeBoard(), gameId, match.getTeam1(), match.getTeam2());
Player team1 = match.getTeam1();
Player team2 = match.getTeam2();
boolean team1IsCoffeBreak = isCoffeBreak(team1);
boolean team2IsCoffeBreak = isCoffeBreak(team2);
return team1IsCoffeBreak || team2IsCoffeBreak //
? new CoffeebreakGame(team1IsCoffeBreak ? team2 : team1, gameId) //
: new DefaultGame(moveListener, makeBoard(), gameId, team1, team2);
}

private static boolean isCoffeBreak(Player player) {
Expand Down
57 changes: 22 additions & 35 deletions udp/src/test/java/org/ase/fourwins/udp/server/MainTest.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package org.ase.fourwins.udp.server;

import static com.github.stefanbirkner.systemlambda.SystemLambda.withEnvironmentVariable;
import static java.lang.Long.MAX_VALUE;
import static java.time.Duration.ofSeconds;
import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.stream.Collectors.joining;
import static org.ase.fourwins.udp.server.UdpServer.MAX_CLIENT_NAME_LENGTH;
Expand Down Expand Up @@ -46,23 +44,25 @@
import org.ase.fourwins.udp.udphelper.UdpCommunicator;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.stubbing.Answer;
import org.mockito.verification.VerificationMode;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

public class MainTest {

private static final Duration TIMEOUT = ofSeconds(10);

@RequiredArgsConstructor
private static class BaseClient {

@Getter
protected final String name;
protected final UdpCommunicator communicator;

public BaseClient(String name, String remoteHost, int remotePort) throws IOException {
this.name = name;
this.communicator = new UdpCommunicator(remoteHost, remotePort);
this(name, new UdpCommunicator(remoteHost, remotePort));
}

void send(String message) throws IOException {
Expand Down Expand Up @@ -177,41 +177,41 @@ void clientCanConnectToServer() throws IOException {
}

@Test
void canHandleEmptyCorruptedRegisterMessage() throws IOException {
void acceptLongName() throws IOException {
runMainInBackground();
setupInfiniteSeason(tournament);
assertTimeoutPreemptively(TIMEOUT, () -> {
new DummyClient("1", "localhost", serverPort) {
protected void register() throws IOException {
send("REGISTER;");
}
}.assertReceived("NO_NAME_GIVEN");
String longestAllowedName = nameOfLength(MAX_CLIENT_NAME_LENGTH);
newClientWithName(longestAllowedName).assertReceived(welcomed(longestAllowedName));
assertTournamentNotStartet();
});
}

@Test
void acceptLongName() throws IOException {
void denyTooLongName() throws IOException {
runMainInBackground();
setupInfiniteSeason(tournament);
assertTimeoutPreemptively(TIMEOUT, () -> {
String longestAllowedName = nameOfLength(MAX_CLIENT_NAME_LENGTH);
newClientWithName(longestAllowedName).assertReceived(welcomed(longestAllowedName));
String tooLongName = nameOfLength(MAX_CLIENT_NAME_LENGTH + 1);
newClientWithName(tooLongName).assertReceived("NAME_TOO_LONG");
assertTournamentNotStartet();
});
}

@Test
void denyTooLongName() throws IOException {
void denyEmptyName() throws IOException {
runMainInBackground();
setupInfiniteSeason(tournament);
assertTimeoutPreemptively(TIMEOUT, () -> {
String tooLongName = nameOfLength(MAX_CLIENT_NAME_LENGTH + 1);
newClientWithName(tooLongName).assertReceived("NAME_TOO_LONG");
newClientWithName(emptyName()).assertReceived("NO_NAME_GIVEN");
assertTournamentNotStartet();
});
}

private String emptyName() {
return "";
}

private DummyClient newClientWithName(String name) throws IOException {
return new DummyClient(name, "localhost", serverPort);
}
Expand All @@ -220,17 +220,6 @@ private DummyClient newPlayingClientWithName(String name) throws IOException {
return new PlayingClient(name, "localhost", serverPort, -1);
}

@Test
void denyEmptyName() throws IOException {
runMainInBackground();
setupInfiniteSeason(tournament);
assertTimeoutPreemptively(TIMEOUT, () -> {
String emptyName = "";
newClientWithName(emptyName).assertReceived("NO_NAME_GIVEN");
assertTournamentNotStartet();
});
}

@Test
void afterSecondClientConnectsTheTournamentIsStarted() throws IOException {
runMainInBackground();
Expand All @@ -251,10 +240,8 @@ void whenMinPlayerIsOneAfterFirstClientConnectsTheTournamentIsStarted() throws I
runMainInBackground();
assertTimeoutPreemptively(TIMEOUT, () -> {
DummyClient client1 = newClientWithName("1");
DummyClient client2 = newClientWithName("2");

assertWelcomed(client1);
assertWelcomed(client2);
assertTournamentStartet();
});
}
Expand Down Expand Up @@ -371,12 +358,11 @@ private void tournamentOfBoardWithState(Board board) {
tournamentOfState(board.gameState());
}

@SuppressWarnings("unchecked")
@SuppressWarnings({ "unchecked", "rawtypes" })
private void tournamentOfState(GameState gameState) {
ArgumentCaptor<Collection<Player>> playerCaptor = ArgumentCaptor.forClass(Collection.class);
ArgumentCaptor<Consumer<GameState>> consumerCaptor = ArgumentCaptor.forClass(Consumer.class);
doAnswer(s -> callGameEnded(gameState, playerCaptor.getValue())).when(tournament)
.playSeason(playerCaptor.capture(), consumerCaptor.capture());
Answer answer = s -> callGameEnded(gameState, playerCaptor.getValue());
doAnswer(answer).when(tournament).playSeason(playerCaptor.capture(), any(Consumer.class));
}

private Object callGameEnded(GameState gameState, Collection<Player> players) {
Expand All @@ -402,8 +388,9 @@ private static void setupInfiniteSeason(Tournament mock) {

private static void waitForever() {
try {
while (true) {
DAYS.sleep(MAX_VALUE);
Object object = new Object();
synchronized (object) {
object.wait();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
Expand Down

0 comments on commit 24bbf25

Please sign in to comment.