Skip to content

Commit 770f117

Browse files
committed
accept challenge to start game
1 parent 91f5ab4 commit 770f117

File tree

6 files changed

+131
-79
lines changed

6 files changed

+131
-79
lines changed

src/main/client/src/feature/lobby/Lobby.jsx

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
useRef,
33
useState,
4+
useEffect,
45
useContext,
56
useCallback,
67
} from "react"
@@ -38,6 +39,7 @@ import {
3839
import {
3940
getZindex,
4041
setNewGameOpen,
42+
setOpenGameId,
4143
handleLobbyClick,
4244
closeLobbyPopup,
4345
initialState,
@@ -59,26 +61,26 @@ export function Lobby() {
5961
let [lobbyState, setLobbyState] = useState(initialState())
6062
let zNewGame = getZindex(lobbyState, "newgame")
6163
let [detail, setDetail] = useState("open")
62-
let stompClient = useContext(StompContext)
6364
let navigate = useNavigate()
6465
let auth = useAuthStore(state => state.auth)
6566
let newGameRef = useRef()
66-
let onNewGame = useCallback((d) => doTry(async () => {
67-
let response = await tfetch("/api/create", {
68-
method: "POST",
69-
headers: {
70-
"Authorization": "Bearer " + auth.token,
71-
"Content-Type": "application/json",
72-
},
73-
body: JSON.stringify(d),
67+
let stompClient = useContext(StompContext)
68+
let initialized = useRef()
69+
useEffect(() => {
70+
if (initialized.current) {
71+
return
72+
}
73+
initialized.current = true
74+
let sub = stompClient.subscribe("/topic/gamestart", (message) => {
75+
let r = JSON.parse(message.body)
76+
if (r.opponent === auth.name) {
77+
navigate(base + "/game/" + r.id)
78+
}
7479
})
75-
let sub = stompClient.subscribe("/topic/game/" + response.id, (message) => {
76-
let game = JSON.parse(message.body)
77-
navigate(base + "/game/" + game.id)
80+
return () => {
7881
sub.unsubscribe()
79-
})
80-
setLobbyState(closeLobbyPopup(lobbyState))
81-
}), [auth.token, navigate, stompClient, lobbyState])
82+
}
83+
}, [auth, initialized, stompClient, navigate])
8284
let onStartEdit = useCallback((d) => doTry(async () => {
8385
let response = await tfetch("/api/start_edit", {
8486
method: "POST",
@@ -100,7 +102,6 @@ export function Lobby() {
100102
lobbyState={lobbyState}
101103
setLobbyState={setLobbyState}
102104
newGameRef={newGameRef}
103-
onNewGame={onNewGame}
104105
onStartEdit={onStartEdit} />
105106
<button disabled={zNewGame !== 0} className={twJoin(
106107
"ml-2 border-2 border-transparent px-4 py-2 rounded-lg",
@@ -131,10 +132,23 @@ export function Lobby() {
131132
)
132133
}
133134

134-
function NewGameDialog({zNewGame, lobbyState, setLobbyState, onNewGame, onStartEdit, newGameRef}) {
135+
function NewGameDialog({zNewGame, lobbyState, setLobbyState, onStartEdit, newGameRef}) {
135136
let dimRef = useRef(9)
136137
let timeRef = useRef(10)
137138
let [edit, setEdit] = useState(false)
139+
let auth = useAuthStore(state => state.auth)
140+
let onNewGame = useCallback((d) => doTry(async () => {
141+
let response = await tfetch("/api/create", {
142+
method: "POST",
143+
headers: {
144+
"Authorization": "Bearer " + auth.token,
145+
"Content-Type": "application/json",
146+
},
147+
body: JSON.stringify(d),
148+
})
149+
let newState = closeLobbyPopup(lobbyState)
150+
setLobbyState(setOpenGameId(newState, response.id))
151+
}), [auth.token, lobbyState, setLobbyState])
138152
return (
139153
<form onSubmit={(e) => {
140154
e.preventDefault()

src/main/client/src/feature/lobby/OpenGames.jsx

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {
33
useState,
44
useEffect,
55
useContext,
6-
useCallback,
76
} from "react"
87
import {
98
FaAngleLeft,
@@ -15,9 +14,6 @@ import {
1514
import {
1615
twJoin,
1716
} from "tailwind-merge"
18-
import {
19-
useNavigate,
20-
} from "react-router-dom"
2117
import {
2218
Form,
2319
} from "src/component/Form.jsx"
@@ -28,7 +24,6 @@ import {
2824
BabyStone,
2925
} from "src/component/BabyStone.jsx"
3026
import {
31-
base,
3227
StompContext,
3328
tfetch,
3429
doTry,
@@ -37,6 +32,7 @@ import {
3732
import {
3833
getZindex,
3934
getAcceptData,
35+
closeLobbyPopup,
4036
setAcceptDialogOpen,
4137
} from "./lobbyState.js"
4238
import {
@@ -47,7 +43,6 @@ export function OpenGames({lobbyState, setLobbyState}) {
4743
let [openGames, setOpenGames] = useState([])
4844
let acceptableGame = getAcceptData(lobbyState)
4945
let stompClient = useContext(StompContext)
50-
let navigate = useNavigate()
5146
let auth = useAuthStore(state => state.auth)
5247
let initialized = useRef()
5348
let acceptDialogRef = useRef()
@@ -71,18 +66,7 @@ export function OpenGames({lobbyState, setLobbyState}) {
7166
return () => {
7267
sub1.unsubscribe()
7368
}
74-
}, [auth, initialized, stompClient, navigate])
75-
let onAccept = useCallback((d) => doTry(async () => {
76-
await tfetch("/api/accept", {
77-
method: "POST",
78-
headers: {
79-
"Authorization": "Bearer " + auth.token,
80-
"Content-Type": "application/json",
81-
},
82-
body: JSON.stringify(d),
83-
})
84-
navigate(base + "/game/" + d.game.id)
85-
}), [auth, navigate])
69+
}, [auth, initialized, stompClient])
8670
return (
8771
<div>
8872
<div className="grid grid-cols-[max-content_max-content_max-content]">
@@ -96,10 +80,10 @@ export function OpenGames({lobbyState, setLobbyState}) {
9680
key={game.id} />
9781
))}
9882
</div>
99-
<AcceptDialog
83+
<ChallengeDialog
10084
lobbyState={lobbyState}
85+
setLobbyState={setLobbyState}
10186
acceptableGame={acceptableGame}
102-
onAccept={onAccept}
10387
acceptDialogRef={acceptDialogRef} />
10488
</div>
10589
)
@@ -138,18 +122,28 @@ function OpenGame({game, onClick}) {
138122
)
139123
}
140124

141-
function AcceptDialog({lobbyState, onAccept, acceptableGame, acceptDialogRef}) {
125+
function ChallengeDialog({lobbyState, setLobbyState, acceptableGame, acceptDialogRef}) {
142126
let [isFlip, setFlip] = useState(false)
143127
let [handi, setHandi] = useState(1)
144128
let auth = useAuthStore(state => state.auth)
145129
let zAccept = getZindex(lobbyState, "accept")
146130
return (
147131
<Form
148132
forwardedRef={acceptDialogRef}
149-
onSubmit={() => onAccept({
150-
game: acceptableGame?.game,
151-
flip: isFlip,
152-
handicap: handi === 1 ? 0 : handi,
133+
onSubmit={() => doTry(async () => {
134+
await tfetch("/api/challenge", {
135+
method: "POST",
136+
headers: {
137+
"Authorization": "Bearer " + auth.token,
138+
"Content-Type": "application/json",
139+
},
140+
body: JSON.stringify({
141+
game: acceptableGame?.game,
142+
flip: isFlip,
143+
handicap: handi === 1 ? 0 : handi,
144+
}),
145+
})
146+
setLobbyState(closeLobbyPopup(lobbyState))
153147
})}
154148
style={{
155149
zIndex: zAccept,

src/main/client/src/feature/lobby/Requests.jsx

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export function Requests({lobbyState}) {
3838
"Authorization": "Bearer " + auth.token,
3939
},
4040
})
41-
setRequests(r.requests.filter(request => request.gameId === openGameId))
41+
setRequests(r.requests)
4242
})
4343
let sub1 = stompClient.subscribe("/topic/lobby/requests", (message) => {
4444
let r = JSON.parse(message.body)
@@ -53,10 +53,9 @@ export function Requests({lobbyState}) {
5353
}
5454
return (
5555
<div>
56-
<div className="grid grid-cols-[max-content_max-content_max-content_max-content]">
56+
<div className="grid grid-cols-[max-content_max-content_max-content_max-content_max-content]">
5757
{requests.map((request) => (
5858
<Request
59-
lobbyState={lobbyState}
6059
request={request}
6160
key={request.id} />
6261
))}
@@ -65,45 +64,44 @@ export function Requests({lobbyState}) {
6564
)
6665
}
6766

68-
function Request({lobbyState, request}) {
67+
function Request({request}) {
6968
let navigate = useNavigate()
7069
let auth = useAuthStore(state => state.auth)
71-
let openGameId = lobbyState.openGameId
72-
let classes = twJoin(
73-
"contents",
74-
"*:py-3",
75-
"cursor-pointer *:hover:bg-sky-200 *:hover:text-black",
76-
)
7770
return (
7871
<div
7972
onClick={() => {
8073
doTry(async () => {
81-
let r = await tfetch("/api/lobby/start", {
74+
await tfetch("/api/lobby/start", {
75+
method: "POST",
8276
headers: {
83-
"method": "POST",
8477
"Authorization": "Bearer " + auth.token,
78+
"Content-Type": "application/json",
8579
},
86-
body: JSON.stringify({
87-
gameId: openGameId,
88-
request: request.id,
89-
}),
80+
body: JSON.stringify(request),
9081
})
91-
navigate(base + "/game/" + r.id)
82+
navigate(base + "/game/" + request.game.id)
9283
})
9384
}}
94-
className={classes}
95-
key={request.id}>
85+
className={twJoin(
86+
"contents",
87+
"*:py-3",
88+
"cursor-pointer *:hover:bg-sky-200 *:hover:text-black",
89+
)}
90+
key={request.game.id}>
9691
<div className="pl-3 pr-1 rounded-l-lg">
97-
{request.white}
92+
{request.flip ? "B" : "W"}: {request.opponent}
93+
</div>
94+
<div className="px-1">
95+
{request.flip ? "W" : "B"}: {request.game.user}
9896
</div>
9997
<div className="px-1">
100-
{request.black}
98+
{request.game.dim}x{request.game.dim}
10199
</div>
102100
<div className="px-1">
103-
{request.dim}x{request.dim}
101+
T: {request.game.timesetting}
104102
</div>
105103
<div className="pl-1 pr-3 rounded-r-lg">
106-
H{request.handi}
104+
H: {request.handicap}
107105
</div>
108106
</div>
109107
)

src/main/java/com/bernd/GameController.java

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
import com.bernd.model.ViewGame;
1313
import com.bernd.util.RandomString;
1414
import com.bernd.util.SgfCreator;
15+
import java.security.Principal;
16+
import java.time.LocalDate;
17+
import java.util.List;
18+
import java.util.Map;
1519
import org.springframework.http.HttpStatus;
1620
import org.springframework.http.MediaType;
1721
import org.springframework.http.ResponseEntity;
@@ -25,9 +29,6 @@
2529
import org.springframework.web.bind.annotation.ResponseBody;
2630
import org.springframework.web.server.ResponseStatusException;
2731

28-
import java.security.Principal;
29-
import java.time.LocalDate;
30-
3132
import static com.bernd.util.Auth.getPrincipal;
3233
import static com.bernd.util.Util.COLORS;
3334

@@ -140,24 +141,43 @@ public OpenGame newGame(@RequestBody OpenGame game) {
140141
return result;
141142
}
142143

143-
@PostMapping(value = "/api/accept", consumes = "application/json")
144-
public ResponseEntity<?> accept(@RequestBody AcceptRequest acceptRequest) {
144+
@PostMapping(value = "/api/lobby/start", consumes = "application/json")
145+
public ResponseEntity<?> start(@RequestBody AcceptRequest acceptRequest) {
145146
String principal = getPrincipal();
146-
openGames.remove(principal);
147-
OpenGame openGame = openGames.remove(acceptRequest.game().user());
148-
Game fullGame = games.put(openGame.accept(principal, acceptRequest));
147+
openGames.remove(acceptRequest.opponent());
148+
OpenGame openGame = openGames.remove(principal);
149+
Game fullGame = games.put(openGame.accept(acceptRequest));
149150
activeGames.put(ActiveGame.fromGame(fullGame));
150151
Chat chat = chats.get(openGame.id());
151152

152153
ChatMessage startMessage = ChatMessage.createStartMessage(chat, fullGame);
153154
chat.messages().add(startMessage);
154155
operations.convertAndSend("/topic/chat/" + chat.id(), startMessage);
155-
operations.convertAndSend("/topic/game/" + fullGame.id(), fullGame.toView());
156+
operations.convertAndSend("/topic/gamestart", Map.of(
157+
"opponent", acceptRequest.opponent(),
158+
"id", openGame.id()));
156159
operations.convertAndSend("/topic/lobby/open_games", openGames.games());
157160
operations.convertAndSend("/topic/lobby/active_games", activeGames.games());
158161
return ResponseEntity.ok().build();
159162
}
160163

164+
@ResponseBody
165+
@PostMapping(value = "/api/challenge", consumes = "application/json")
166+
public Map<String, List<AcceptRequest>> challenge(@RequestBody AcceptRequest acceptRequest) {
167+
String principal = getPrincipal();
168+
openGames.remove(principal);
169+
OpenGame openGame = openGames.addRequest(acceptRequest.game().user(), acceptRequest, principal);
170+
operations.convertAndSend("/topic/lobby/requests", Map.of("requests", openGame.requests()));
171+
return Map.of("requests", openGame.requests());
172+
}
173+
174+
@ResponseBody
175+
@GetMapping(value = "/api/lobby/requests")
176+
public Map<String, List<AcceptRequest>> getRequests() {
177+
String principal = getPrincipal();
178+
return Map.of("requests", openGames.getRequests(principal));
179+
}
180+
161181
@GetMapping("/api/sgf/{id}/{black}_vs_{white}.sgf")
162182
public ResponseEntity<String> getSgf(
163183
@PathVariable String id) {

0 commit comments

Comments
 (0)