Feat: Add highscore client protocol integration (Issue #110) #292

Merged
jona.walpert merged 1 commits from feat/highscore-client-protocol into main 2026-04-21 18:04:04 +02:00
4 changed files with 65 additions and 1 deletions
@@ -10,6 +10,7 @@ import java.util.List;
public class GameState { public class GameState {
public List<Player> players = new ArrayList<>(); public List<Player> players = new ArrayList<>();
public List<Card> communityCards = new ArrayList<>(); public List<Card> communityCards = new ArrayList<>();
public List<String> highscoreEntries = new ArrayList<>();
public String phase; public String phase;
public int pot; public int pot;
@@ -155,6 +155,10 @@ public class GameClient {
s.winnerIndex = intVal(l); s.winnerIndex = intVal(l);
yield true; yield true;
} }
case String l when l.startsWith("HIGHSCORE=") -> {
s.highscoreEntries.add(value(l));
yield true;
}
default -> false; default -> false;
}; };
} }
@@ -81,6 +81,30 @@ public class LobbyClient {
throw new RuntimeException("No LOBBY_ID in response: " + lines); throw new RuntimeException("No LOBBY_ID in response: " + lines);
} }
/**
* Fetches the global highscores from the server.
*
* @return list of formatted highscore entries, newest entries at the end
*/
public List<String> getHighscores() {
List<String> lines = client.processCommand("GET_HIGHSCORES");
List<RequestParameter> params = ClientService.convertToRequestParameters(lines);
List<String> entries = new ArrayList<>();
for (RequestParameter p : params) {
if ("HIGHSCORE".equalsIgnoreCase(p.key())) {
entries.add(p.value());
}
}
return entries;
}
/** Clears all global highscores on the server. */
public void clearHighscores() {
client.processCommand("CLEAR_HIGHSCORES");
}
/** /**
* Request the server to return the id of the lobby that the client is currently in. * Request the server to return the id of the lobby that the client is currently in.
* *
@@ -8,6 +8,7 @@ import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.player.Player;
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.player.PlayerId; import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.player.PlayerId;
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.state.GamePhase; import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.state.GamePhase;
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.state.GameState; import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.state.GameState;
import ch.unibas.dmi.dbis.cs108.casono.server.domain.highscore.HighscoreService;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.RequestContext; import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.RequestContext;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.SuccessResponse; import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.SuccessResponse;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBody; import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBody;
@@ -50,7 +51,11 @@ public class GetGameStateResponse extends SuccessResponse {
builder.param("CURRENT_BET", computeGlobalCurrentBet(state)); builder.param("CURRENT_BET", computeGlobalCurrentBet(state));
builder.param("DEALER", state.getDealerIndex()); builder.param("DEALER", state.getDealerIndex());
builder.param("ACTIVE_PLAYER", state.getCurrentPlayerIndex()); builder.param("ACTIVE_PLAYER", state.getCurrentPlayerIndex());
builder.param("WINNER", computeWinnerIndex(state, game)); int winnerIndex = computeWinnerIndex(state, game);
builder.param("WINNER", winnerIndex);
appendWinnerToHighscoresIfFinished(state, winnerIndex);
appendHighscoreEntries(builder);
appendCommunityCards(builder, state); appendCommunityCards(builder, state);
@@ -59,6 +64,36 @@ public class GetGameStateResponse extends SuccessResponse {
return builder.build(); return builder.build();
} }
private static void appendWinnerToHighscoresIfFinished(GameState state, int winnerIndex) {
if (winnerIndex < 0 || state.getPhase() != GamePhase.FINISHED) {
return;
}
Player winner = findPlayerByIndex(state, winnerIndex);
if (winner == null || winner.getId() == null || winner.getId().value() == null) {
return;
}
HighscoreService.getInstance().appendWinner(winner.getId().value());
}
private static Player findPlayerByIndex(GameState state, int winnerIndex) {
int currentIndex = 0;
for (Player player : state.getPlayers()) {
if (currentIndex == winnerIndex) {
return player;
}
currentIndex++;
}
return null;
}
private static void appendHighscoreEntries(ResponseBodyBuilder builder) {
for (String entry : HighscoreService.getInstance().readFormattedEntries()) {
builder.param("HIGHSCORE", entry);
}
}
private static int computeWinnerIndex(GameState state, GameController game) { private static int computeWinnerIndex(GameState state, GameController game) {
GamePhase phase = state.getPhase(); GamePhase phase = state.getPhase();
if (phase != GamePhase.SHOWDOWN && phase != GamePhase.FINISHED) { if (phase != GamePhase.SHOWDOWN && phase != GamePhase.FINISHED) {