Feat: Money is now saved in the Higshcore list.
Furthermore if two people win the pot both will get added to the highscore list
This commit is contained in:
+11
-5
@@ -60,12 +60,9 @@ public class GetGameStateResponse extends SuccessResponse {
|
||||
builder.param("WINNER", winnerIndex);
|
||||
|
||||
List<String> winnerNames = computeWinnerNames(state, game);
|
||||
int potPerWinner = computePotPerWinner(state, winnerNames.size());
|
||||
|
||||
for (String name : winnerNames) {
|
||||
builder.param("WINNER_NAME", name);
|
||||
}
|
||||
builder.param("POT_PER_WINNER", potPerWinner);
|
||||
|
||||
appendWinnerToHighscoresIfFinished(state, winnerNames);
|
||||
appendHighscoreEntries(builder);
|
||||
@@ -92,13 +89,22 @@ public class GetGameStateResponse extends SuccessResponse {
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep ordering stable, avoid duplicate writes for the same winner in one hand.
|
||||
// Keep ordering stable and persist tied winners as a single shared highscore
|
||||
// entry. Compute the per-winner share here (pot is split equally among
|
||||
// winners)
|
||||
int potPerWinner = computePotPerWinner(state, winnerNames.size());
|
||||
Set<String> uniqueWinners = new LinkedHashSet<>(winnerNames);
|
||||
List<String> formattedWinners = new ArrayList<>();
|
||||
for (String name : uniqueWinners) {
|
||||
if (name != null && !name.isBlank()) {
|
||||
HighscoreService.getInstance().appendWinner(name);
|
||||
formattedWinners.add(name + " (" + Math.max(0, potPerWinner) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
if (!formattedWinners.isEmpty()) {
|
||||
HighscoreService.getInstance()
|
||||
.appendFormattedEntry(String.join(", ", formattedWinners));
|
||||
}
|
||||
}
|
||||
|
||||
private static Player findPlayerByIndex(GameState state, int winnerIndex) {
|
||||
|
||||
+57
-3
@@ -18,6 +18,7 @@ public final class HighscoreService {
|
||||
private static final DateTimeFormatter DISPLAY_FORMATTER =
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault());
|
||||
private static final int MAX_RETURNED_ENTRIES = 100;
|
||||
private static final int MIN_MONEY_COLUMN_COUNT = 3;
|
||||
private static final String LINE_SEPARATOR = "\t";
|
||||
|
||||
private final Path storagePath;
|
||||
@@ -32,6 +33,11 @@ public final class HighscoreService {
|
||||
}
|
||||
|
||||
public synchronized void appendWinner(String winnerName) {
|
||||
appendWinner(winnerName, 0);
|
||||
}
|
||||
|
||||
/** Append a winner with an optional money value (money may be 0). */
|
||||
public synchronized void appendWinner(String winnerName, int money) {
|
||||
if (winnerName == null) {
|
||||
return;
|
||||
}
|
||||
@@ -41,6 +47,44 @@ public final class HighscoreService {
|
||||
return;
|
||||
}
|
||||
|
||||
String line;
|
||||
if (money > 0) {
|
||||
line =
|
||||
Instant.now()
|
||||
+ LINE_SEPARATOR
|
||||
+ sanitized
|
||||
+ LINE_SEPARATOR
|
||||
+ money
|
||||
+ System.lineSeparator();
|
||||
} else {
|
||||
// Keep legacy two-column format for backward compatibility
|
||||
line = Instant.now() + LINE_SEPARATOR + sanitized + System.lineSeparator();
|
||||
}
|
||||
|
||||
try {
|
||||
Files.createDirectories(storagePath.getParent());
|
||||
Files.writeString(
|
||||
storagePath,
|
||||
line,
|
||||
StandardCharsets.UTF_8,
|
||||
StandardOpenOption.CREATE,
|
||||
StandardOpenOption.APPEND);
|
||||
} catch (IOException ignored) {
|
||||
// Highscore persistence must never break the game state response path.
|
||||
}
|
||||
}
|
||||
|
||||
/** Append a preformatted highscore entry such as "Lars (1000), Jona (1000)". */
|
||||
public synchronized void appendFormattedEntry(String entryText) {
|
||||
if (entryText == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String sanitized = sanitizeName(entryText);
|
||||
if (sanitized.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String line = Instant.now() + LINE_SEPARATOR + sanitized + System.lineSeparator();
|
||||
|
||||
try {
|
||||
@@ -74,15 +118,25 @@ public final class HighscoreService {
|
||||
if (raw == null || raw.isBlank()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String[] parts = raw.split(LINE_SEPARATOR, 2);
|
||||
// Support both legacy format (TIMESTAMP \t NAME) and new format (TIMESTAMP \t
|
||||
// NAME \t MONEY)
|
||||
String[] parts = raw.split(LINE_SEPARATOR);
|
||||
if (parts.length < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
Instant ts = Instant.parse(parts[0].trim());
|
||||
String display = DISPLAY_FORMATTER.format(ts) + " | " + parts[1].trim();
|
||||
String name = parts[1].trim();
|
||||
String display = DISPLAY_FORMATTER.format(ts) + " | " + name;
|
||||
if (parts.length >= MIN_MONEY_COLUMN_COUNT) {
|
||||
try {
|
||||
int money = Integer.parseInt(parts[2].trim());
|
||||
display = display + " | $" + money;
|
||||
} catch (NumberFormatException nfe) {
|
||||
// ignore malformed money
|
||||
}
|
||||
}
|
||||
formatted.add(display);
|
||||
} catch (Exception ignored) {
|
||||
// Skip malformed lines and keep all valid entries.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
|
||||
<AnchorPane xmlns="http://javafx.com"
|
||||
<AnchorPane fx:id="rootPane" xmlns="http://javafx.com"
|
||||
xmlns:fx="http://javafx.com"
|
||||
fx:controller="ch.unibas.dmi.dbis.cs108.casono.client.ui.lobbyui.CasinomainuiController"
|
||||
styleClass="anchor-pane-bg"
|
||||
|
||||
Reference in New Issue
Block a user