Skip to content

Commit 4b9378c

Browse files
committed
Merge boards and contests in JS app
1 parent 35243a3 commit 4b9378c

26 files changed

+302
-186
lines changed

player/src/main/java/eu/solven/kumite/app/player/KumitePlayer.java

+8-6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import eu.solven.kumite.contest.ContestView;
1111
import eu.solven.kumite.game.GameSearchParameters;
1212
import eu.solven.kumite.game.IGameMetadataConstants;
13+
import eu.solven.kumite.player.PlayerContestStatus;
1314
import eu.solven.kumite.player.PlayerRawMovesHolder;
1415
import lombok.AllArgsConstructor;
1516
import lombok.NonNull;
@@ -54,11 +55,12 @@ public void playOptimizationGames(UUID playerId) {
5455
// Process each contest
5556
.flatMap(contestView -> {
5657
UUID contestId = contestView.getContestId();
58+
PlayerContestStatus playerStatus = contestView.getPlayerStatus();
5759

58-
if (contestView.getPlayingPlayer().isPlayerHasJoined()) {
60+
if (playerStatus.isPlayerHasJoined()) {
5961
log.info("Received board for already joined contestId={}", contestId);
6062
return Mono.empty();
61-
} else if (contestView.getPlayingPlayer().isPlayerCanJoin()) {
63+
} else if (contestView.getPlayerStatus().isPlayerCanJoin()) {
6264
log.info("Received board for joinable contestId={}", contestId);
6365
return kumiteServer.joinContest(playerId, contestId)
6466
// We load the board again once we are signed-up
@@ -77,7 +79,7 @@ public void playOptimizationGames(UUID playerId) {
7779
}
7880

7981
Mono<PlayerRawMovesHolder> exampleMoves =
80-
kumiteServer.getExampleMoves(joinedContestView.getPlayingPlayer().getPlayerId(), contestId);
82+
kumiteServer.getExampleMoves(joinedContestView.getPlayerStatus().getPlayerId(), contestId);
8183

8284
return exampleMoves.flatMap(moves -> {
8385
Optional<Map<String, ?>> selectedMove = selectMove(joinedContestView.getBoard(), moves);
@@ -127,10 +129,10 @@ public void play1v1(UUID playerId) {
127129
.flatMap(contestView -> {
128130
UUID contestId = contestView.getContestId();
129131

130-
if (contestView.getPlayingPlayer().isPlayerHasJoined()) {
132+
if (contestView.getPlayerStatus().isPlayerHasJoined()) {
131133
log.info("Received board for already joined contestId={}", contestId);
132134
return Mono.empty();
133-
} else if (contestView.getPlayingPlayer().isPlayerCanJoin()) {
135+
} else if (contestView.getPlayerStatus().isPlayerCanJoin()) {
134136
log.info("Received board for joinable contestId={}", contestId);
135137
return kumiteServer.joinContest(playerId, contestId)
136138
.flatMap(playingPlayer -> kumiteServer.loadBoard(contestId, playerId));
@@ -150,7 +152,7 @@ public void play1v1(UUID playerId) {
150152
}
151153

152154
Mono<PlayerRawMovesHolder> exampleMoves =
153-
kumiteServer.getExampleMoves(joinedContestView.getPlayingPlayer().getPlayerId(), contestId);
155+
kumiteServer.getExampleMoves(joinedContestView.getPlayerStatus().getPlayerId(), contestId);
154156
Mono<ContestView> monoContestViewPostMove = exampleMoves.flatMap(moves -> {
155157
Optional<Map<String, ?>> optSelectedMove = selectMove(joinedContestView.getBoard(), moves);
156158

player/src/main/java/eu/solven/kumite/app/server/IKumiteServer.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
import eu.solven.kumite.game.GameMetadata;
1010
import eu.solven.kumite.game.GameSearchParameters;
1111
import eu.solven.kumite.leaderboard.LeaderBoardRaw;
12+
import eu.solven.kumite.player.PlayerContestStatus;
1213
import eu.solven.kumite.player.PlayerRawMovesHolder;
13-
import eu.solven.kumite.player.PlayingPlayer;
1414
import reactor.core.publisher.Flux;
1515
import reactor.core.publisher.Mono;
1616

@@ -21,7 +21,7 @@ public interface IKumiteServer {
2121

2222
Mono<ContestView> loadBoard(UUID playerId, UUID contestId);
2323

24-
Mono<PlayingPlayer> joinContest(UUID playerId, UUID contestId);
24+
Mono<PlayerContestStatus> joinContest(UUID playerId, UUID contestId);
2525

2626
Mono<PlayerRawMovesHolder> getExampleMoves(UUID playerId, UUID contestId);
2727

player/src/main/java/eu/solven/kumite/app/server/KumiteWebclientServer.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
import eu.solven.kumite.game.GameMetadata;
1616
import eu.solven.kumite.game.GameSearchParameters;
1717
import eu.solven.kumite.leaderboard.LeaderBoardRaw;
18+
import eu.solven.kumite.player.PlayerContestStatus;
1819
import eu.solven.kumite.player.PlayerRawMovesHolder;
19-
import eu.solven.kumite.player.PlayingPlayer;
2020
import lombok.extern.slf4j.Slf4j;
2121
import reactor.core.publisher.Flux;
2222
import reactor.core.publisher.Mono;
@@ -105,7 +105,7 @@ public Mono<ContestView> loadBoard(UUID playerId, UUID contestId) {
105105
}
106106

107107
@Override
108-
public Mono<PlayingPlayer> joinContest(UUID playerId, UUID contestId) {
108+
public Mono<PlayerContestStatus> joinContest(UUID playerId, UUID contestId) {
109109
RequestBodySpec spec = webClient.post()
110110
.uri(uriBuilder -> uriBuilder.path("/api/board/player")
111111
.queryParam("player_id", playerId)
@@ -116,7 +116,7 @@ public Mono<PlayingPlayer> joinContest(UUID playerId, UUID contestId) {
116116
if (!r.statusCode().is2xxSuccessful()) {
117117
throw new IllegalArgumentException("Request rejected: " + r.statusCode());
118118
}
119-
return r.bodyToMono(PlayingPlayer.class);
119+
return r.bodyToMono(PlayerContestStatus.class);
120120
});
121121
}
122122

public/src/main/java/eu/solven/kumite/contest/ContestDynamicMetadata.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class ContestDynamicMetadata {
2121

2222
// Should we return the actual list of players?
2323
@NonNull
24-
Set<UUID> players;
24+
Set<UUID> contenders;
2525

2626
boolean acceptingPlayers;
2727
boolean requiringPlayers;

public/src/main/java/eu/solven/kumite/contest/ContestView.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import java.util.Map;
44
import java.util.UUID;
55

6-
import eu.solven.kumite.player.PlayingPlayer;
6+
import eu.solven.kumite.player.PlayerContestStatus;
77
import lombok.Builder;
88
import lombok.NonNull;
99
import lombok.Value;
@@ -23,7 +23,7 @@ public class ContestView {
2323
UUID contestId;
2424

2525
@NonNull
26-
PlayingPlayer playingPlayer;
26+
PlayerContestStatus playerStatus;
2727

2828
@NonNull
2929
ContestDynamicMetadata dynamicMetadata;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package eu.solven.kumite.player;
2+
3+
import java.util.UUID;
4+
5+
import lombok.Builder;
6+
import lombok.NonNull;
7+
import lombok.Value;
8+
import lombok.extern.jackson.Jacksonized;
9+
10+
/**
11+
* A participating player and its status relatively to a contest.
12+
*
13+
* @author Benoit Lacelle
14+
*
15+
*/
16+
@Value
17+
@Builder
18+
@Jacksonized
19+
public class PlayerContestStatus {
20+
@NonNull
21+
UUID playerId;
22+
23+
// We may introduce a contenderId. Through it is unclear how to manage it given this may also represent a viewer, or
24+
// a previewer
25+
26+
// Has joined as a contender, not a viewer
27+
boolean playerHasJoined;
28+
// Can join as a contender
29+
boolean playerCanJoin;
30+
// Any player own by the account is viewing
31+
boolean accountIsViewing;
32+
33+
public static PlayerContestStatus contender(UUID playerId) {
34+
return PlayerContestStatus.builder().playerId(playerId).playerHasJoined(true).build();
35+
}
36+
37+
public static PlayerContestStatus viewer(UUID playerId) {
38+
return PlayerContestStatus.builder().playerId(playerId).accountIsViewing(true).build();
39+
}
40+
}

public/src/main/java/eu/solven/kumite/player/PlayingPlayer.java

-35
This file was deleted.

server/src/main/java/eu/solven/kumite/board/BoardHandler.java

+6-4
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import eu.solven.kumite.game.GamesRegistry;
2323
import eu.solven.kumite.player.ContestPlayersRegistry;
2424
import eu.solven.kumite.player.KumitePlayer;
25-
import eu.solven.kumite.player.PlayingPlayer;
25+
import eu.solven.kumite.player.PlayerContestStatus;
2626
import lombok.AllArgsConstructor;
2727
import lombok.NonNull;
2828
import lombok.extern.slf4j.Slf4j;
@@ -57,7 +57,7 @@ public Mono<ServerResponse> getBoard(ServerRequest request) {
5757

5858
Contest contestMetadata = contest.get(0);
5959

60-
PlayingPlayer playingPlayer = contestPlayersRegistry.getPlayingPlayer(playerId, contestMetadata);
60+
PlayerContestStatus playingPlayer = contestPlayersRegistry.getPlayingPlayer(playerId, contestMetadata);
6161

6262
IKumiteBoard board = boardsRegistry.makeDynamicBoardHolder(contestId).get();
6363

@@ -67,7 +67,9 @@ public Mono<ServerResponse> getBoard(ServerRequest request) {
6767
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(contestView));
6868
}
6969

70-
private ContestView makeContestView(Contest contestMetadata, PlayingPlayer playingPlayer, IKumiteBoard board) {
70+
private ContestView makeContestView(Contest contestMetadata,
71+
PlayerContestStatus playingPlayer,
72+
IKumiteBoard board) {
7173
UUID viewPlayerId;
7274
if (playingPlayer.isPlayerHasJoined()) {
7375
viewPlayerId = playingPlayer.getPlayerId();
@@ -82,7 +84,7 @@ private ContestView makeContestView(Contest contestMetadata, PlayingPlayer playi
8284
ContestDynamicMetadata dynamicMetadata = Contest.snapshot(contestMetadata).getDynamicMetadata();
8385
ContestView contestView = ContestView.builder()
8486
.contestId(contestMetadata.getContestId())
85-
.playingPlayer(playingPlayer)
87+
.playerStatus(playingPlayer)
8688
.board(new ObjectMapper().convertValue(boardView, Map.class))
8789
.dynamicMetadata(dynamicMetadata)
8890

server/src/main/java/eu/solven/kumite/contest/Contest.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public class Contest implements IContest {
3838
@NonNull
3939
IHasGameover gameover;
4040

41+
// These are the contenders of the contest
4142
@Override
4243
public List<KumitePlayer> getPlayers() {
4344
return players.getPlayers();
@@ -61,7 +62,7 @@ public static ContestMetadataRaw snapshot(Contest contest) {
6162
.acceptingPlayers(contest.isAcceptingPlayers())
6263
.requiringPlayers(contest.isRequiringPlayers())
6364
.gameOver(contest.isGameOver())
64-
.players(contest.getPlayers().stream().map(p -> p.getPlayerId()).collect(Collectors.toSet()))
65+
.contenders(contest.getPlayers().stream().map(p -> p.getPlayerId()).collect(Collectors.toSet()))
6566
.build())
6667
.build();
6768
}

server/src/main/java/eu/solven/kumite/contest/ContestSearchHandler.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,9 @@ public Mono<ServerResponse> generateContest(ServerRequest request) {
8686
}
8787

8888
Contest registeredContest = contestsRegistry.registerContest(game, constantMetadata, board);
89+
ContestMetadataRaw snapshot = Contest.snapshot(registeredContest);
8990

90-
return ServerResponse.ok()
91-
.contentType(MediaType.APPLICATION_JSON)
92-
.body(BodyInserters.fromValue(registeredContest));
91+
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(snapshot));
9392
});
9493
}
9594

server/src/main/java/eu/solven/kumite/game/opposition/tictactoe/TicTacToeBoard.java

+9
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,13 @@ private boolean hasLeftMove() {
161161
return false;
162162
}
163163

164+
@Override
165+
public String getBoardSvg() {
166+
return "KumiteTicTacToeBoardState";
167+
}
168+
169+
@Override
170+
public String getMoveSvg() {
171+
return "KumiteTicTacToeBoardMove";
172+
}
164173
}

server/src/main/java/eu/solven/kumite/lifecycle/BoardLifecycleManager.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,18 @@ public void registerPlayer(Contest contest, PlayerJoinRaw playerRegistrationRaw)
9595
UUID contestId = contest.getContestId();
9696
executeBoardChange(contestId, () -> {
9797
contestPlayersRegistry.registerPlayer(contest, playerRegistrationRaw);
98+
9899
if (!playerRegistrationRaw.isViewer()) {
99100
IKumiteBoard board = boardRegistry.makeDynamicBoardHolder(contestId).get();
100-
board.registerPlayer(playerRegistrationRaw.getPlayerId());
101+
try {
102+
board.registerPlayer(playerRegistrationRaw.getPlayerId());
103+
} catch (Throwable t) {
104+
// What should we do about contestPlayersRegistry? Remove the player? Force gameOver? Drop
105+
// contestPlayersRegistry and rely only on the board?
106+
throw new IllegalStateException(
107+
"Issue after registering a player, but before registering it on the board",
108+
t);
109+
}
101110
}
102111
});
103112
}

server/src/main/java/eu/solven/kumite/player/ContestPlayersRegistry.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public boolean isRegisteredPlayer(UUID contestId, UUID playerId) {
100100
return contestToPlayingPlayers.getOrDefault(contestId, Set.of()).contains(playerId);
101101
}
102102

103-
public PlayingPlayer getPlayingPlayer(UUID playerId, Contest contestMetadata) {
103+
public PlayerContestStatus getPlayingPlayer(UUID playerId, Contest contestMetadata) {
104104
UUID contestId = contestMetadata.getContestId();
105105

106106
boolean playerHasJoined = isRegisteredPlayer(contestId, playerId);
@@ -128,7 +128,7 @@ public PlayingPlayer getPlayingPlayer(UUID playerId, Contest contestMetadata) {
128128
}
129129
}
130130

131-
PlayingPlayer playingPlayer = PlayingPlayer.builder()
131+
PlayerContestStatus playingPlayer = PlayerContestStatus.builder()
132132
.playerId(playerId)
133133
.playerHasJoined(playerHasJoined)
134134
.playerCanJoin(playerCanJoin)

server/src/main/java/eu/solven/kumite/player/PlayerMovesHandler.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public Mono<ServerResponse> registerPlayer(ServerRequest request) {
4949
boardLifecycleManager.registerPlayer(contest, playerJoinRaw);
5050

5151
boolean isViewer = playerJoinRaw.isViewer();
52-
PlayingPlayer playingPlayer = PlayingPlayer.builder()
52+
PlayerContestStatus playingPlayer = PlayerContestStatus.builder()
5353
.playerId(playerId)
5454

5555
.playerHasJoined(!isViewer)
@@ -97,7 +97,7 @@ public Mono<ServerResponse> playMove(ServerRequest request) {
9797

9898
ContestView view = ContestView.builder()
9999
.contestId(contestId)
100-
.playingPlayer(PlayingPlayer.player(playerId))
100+
.playerStatus(PlayerContestStatus.contender(playerId))
101101
.board(objectMapper.convertValue(boardViewPostMove, Map.class))
102102
.dynamicMetadata(Contest.snapshot(contest).getDynamicMetadata())
103103
.build();

server/src/main/resources/static/ui/js/board-renderers/kumite-tictactoe-board-state.js

+20-2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,24 @@ export default {
3737

3838
const positions = board.positions;
3939

40+
for (let i = 1; i < 3; i++) {
41+
const hLine = new Line(
42+
16,
43+
(height / 3) * i,
44+
width - 16,
45+
(height / 3) * i,
46+
);
47+
renderer.scene.add(hLine);
48+
49+
const vLine = new Line(
50+
(width / 3) * i,
51+
16,
52+
(width / 3) * i,
53+
height - 16,
54+
);
55+
renderer.scene.add(vLine);
56+
}
57+
4058
for (let i = 0; i < 9; i++) {
4159
const char = positions.charAt(i);
4260

@@ -56,12 +74,12 @@ export default {
5674
const circle = new Circle(width * city.x, height * city.y, 1);
5775
group.add(circle);
5876
} else {
59-
return;
77+
// Nothing to render on not played positions
6078
}
6179

6280
renderer.scene.add(group);
63-
renderer.render();
6481
}
82+
renderer.render();
6583
});
6684

6785
return {

0 commit comments

Comments
 (0)