Skip to content

Commit

Permalink
accept challenge to start game
Browse files Browse the repository at this point in the history
  • Loading branch information
h908714124 committed Oct 7, 2024
1 parent 91f5ab4 commit 770f117
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 79 deletions.
48 changes: 31 additions & 17 deletions src/main/client/src/feature/lobby/Lobby.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
useRef,
useState,
useEffect,
useContext,
useCallback,
} from "react"
Expand Down Expand Up @@ -38,6 +39,7 @@ import {
import {
getZindex,
setNewGameOpen,
setOpenGameId,
handleLobbyClick,
closeLobbyPopup,
initialState,
Expand All @@ -59,26 +61,26 @@ export function Lobby() {
let [lobbyState, setLobbyState] = useState(initialState())
let zNewGame = getZindex(lobbyState, "newgame")
let [detail, setDetail] = useState("open")
let stompClient = useContext(StompContext)
let navigate = useNavigate()
let auth = useAuthStore(state => state.auth)
let newGameRef = useRef()
let onNewGame = useCallback((d) => doTry(async () => {
let response = await tfetch("/api/create", {
method: "POST",
headers: {
"Authorization": "Bearer " + auth.token,
"Content-Type": "application/json",
},
body: JSON.stringify(d),
let stompClient = useContext(StompContext)
let initialized = useRef()
useEffect(() => {
if (initialized.current) {
return
}
initialized.current = true
let sub = stompClient.subscribe("/topic/gamestart", (message) => {
let r = JSON.parse(message.body)
if (r.opponent === auth.name) {
navigate(base + "/game/" + r.id)
}
})
let sub = stompClient.subscribe("/topic/game/" + response.id, (message) => {
let game = JSON.parse(message.body)
navigate(base + "/game/" + game.id)
return () => {
sub.unsubscribe()
})
setLobbyState(closeLobbyPopup(lobbyState))
}), [auth.token, navigate, stompClient, lobbyState])
}
}, [auth, initialized, stompClient, navigate])
let onStartEdit = useCallback((d) => doTry(async () => {
let response = await tfetch("/api/start_edit", {
method: "POST",
Expand All @@ -100,7 +102,6 @@ export function Lobby() {
lobbyState={lobbyState}
setLobbyState={setLobbyState}
newGameRef={newGameRef}
onNewGame={onNewGame}
onStartEdit={onStartEdit} />
<button disabled={zNewGame !== 0} className={twJoin(
"ml-2 border-2 border-transparent px-4 py-2 rounded-lg",
Expand Down Expand Up @@ -131,10 +132,23 @@ export function Lobby() {
)
}

function NewGameDialog({zNewGame, lobbyState, setLobbyState, onNewGame, onStartEdit, newGameRef}) {
function NewGameDialog({zNewGame, lobbyState, setLobbyState, onStartEdit, newGameRef}) {
let dimRef = useRef(9)
let timeRef = useRef(10)
let [edit, setEdit] = useState(false)
let auth = useAuthStore(state => state.auth)
let onNewGame = useCallback((d) => doTry(async () => {
let response = await tfetch("/api/create", {
method: "POST",
headers: {
"Authorization": "Bearer " + auth.token,
"Content-Type": "application/json",
},
body: JSON.stringify(d),
})
let newState = closeLobbyPopup(lobbyState)
setLobbyState(setOpenGameId(newState, response.id))
}), [auth.token, lobbyState, setLobbyState])
return (
<form onSubmit={(e) => {
e.preventDefault()
Expand Down
44 changes: 19 additions & 25 deletions src/main/client/src/feature/lobby/OpenGames.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
useState,
useEffect,
useContext,
useCallback,
} from "react"
import {
FaAngleLeft,
Expand All @@ -15,9 +14,6 @@ import {
import {
twJoin,
} from "tailwind-merge"
import {
useNavigate,
} from "react-router-dom"
import {
Form,
} from "src/component/Form.jsx"
Expand All @@ -28,7 +24,6 @@ import {
BabyStone,
} from "src/component/BabyStone.jsx"
import {
base,
StompContext,
tfetch,
doTry,
Expand All @@ -37,6 +32,7 @@ import {
import {
getZindex,
getAcceptData,
closeLobbyPopup,
setAcceptDialogOpen,
} from "./lobbyState.js"
import {
Expand All @@ -47,7 +43,6 @@ export function OpenGames({lobbyState, setLobbyState}) {
let [openGames, setOpenGames] = useState([])
let acceptableGame = getAcceptData(lobbyState)
let stompClient = useContext(StompContext)
let navigate = useNavigate()
let auth = useAuthStore(state => state.auth)
let initialized = useRef()
let acceptDialogRef = useRef()
Expand All @@ -71,18 +66,7 @@ export function OpenGames({lobbyState, setLobbyState}) {
return () => {
sub1.unsubscribe()
}
}, [auth, initialized, stompClient, navigate])
let onAccept = useCallback((d) => doTry(async () => {
await tfetch("/api/accept", {
method: "POST",
headers: {
"Authorization": "Bearer " + auth.token,
"Content-Type": "application/json",
},
body: JSON.stringify(d),
})
navigate(base + "/game/" + d.game.id)
}), [auth, navigate])
}, [auth, initialized, stompClient])
return (
<div>
<div className="grid grid-cols-[max-content_max-content_max-content]">
Expand All @@ -96,10 +80,10 @@ export function OpenGames({lobbyState, setLobbyState}) {
key={game.id} />
))}
</div>
<AcceptDialog
<ChallengeDialog
lobbyState={lobbyState}
setLobbyState={setLobbyState}
acceptableGame={acceptableGame}
onAccept={onAccept}
acceptDialogRef={acceptDialogRef} />
</div>
)
Expand Down Expand Up @@ -138,18 +122,28 @@ function OpenGame({game, onClick}) {
)
}

function AcceptDialog({lobbyState, onAccept, acceptableGame, acceptDialogRef}) {
function ChallengeDialog({lobbyState, setLobbyState, acceptableGame, acceptDialogRef}) {
let [isFlip, setFlip] = useState(false)
let [handi, setHandi] = useState(1)
let auth = useAuthStore(state => state.auth)
let zAccept = getZindex(lobbyState, "accept")
return (
<Form
forwardedRef={acceptDialogRef}
onSubmit={() => onAccept({
game: acceptableGame?.game,
flip: isFlip,
handicap: handi === 1 ? 0 : handi,
onSubmit={() => doTry(async () => {
await tfetch("/api/challenge", {
method: "POST",
headers: {
"Authorization": "Bearer " + auth.token,
"Content-Type": "application/json",
},
body: JSON.stringify({
game: acceptableGame?.game,
flip: isFlip,
handicap: handi === 1 ? 0 : handi,
}),
})
setLobbyState(closeLobbyPopup(lobbyState))
})}
style={{
zIndex: zAccept,
Expand Down
44 changes: 21 additions & 23 deletions src/main/client/src/feature/lobby/Requests.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function Requests({lobbyState}) {
"Authorization": "Bearer " + auth.token,
},
})
setRequests(r.requests.filter(request => request.gameId === openGameId))
setRequests(r.requests)
})
let sub1 = stompClient.subscribe("/topic/lobby/requests", (message) => {
let r = JSON.parse(message.body)
Expand All @@ -53,10 +53,9 @@ export function Requests({lobbyState}) {
}
return (
<div>
<div className="grid grid-cols-[max-content_max-content_max-content_max-content]">
<div className="grid grid-cols-[max-content_max-content_max-content_max-content_max-content]">
{requests.map((request) => (
<Request
lobbyState={lobbyState}
request={request}
key={request.id} />
))}
Expand All @@ -65,45 +64,44 @@ export function Requests({lobbyState}) {
)
}

function Request({lobbyState, request}) {
function Request({request}) {
let navigate = useNavigate()
let auth = useAuthStore(state => state.auth)
let openGameId = lobbyState.openGameId
let classes = twJoin(
"contents",
"*:py-3",
"cursor-pointer *:hover:bg-sky-200 *:hover:text-black",
)
return (
<div
onClick={() => {
doTry(async () => {
let r = await tfetch("/api/lobby/start", {
await tfetch("/api/lobby/start", {
method: "POST",
headers: {
"method": "POST",
"Authorization": "Bearer " + auth.token,
"Content-Type": "application/json",
},
body: JSON.stringify({
gameId: openGameId,
request: request.id,
}),
body: JSON.stringify(request),
})
navigate(base + "/game/" + r.id)
navigate(base + "/game/" + request.game.id)
})
}}
className={classes}
key={request.id}>
className={twJoin(
"contents",
"*:py-3",
"cursor-pointer *:hover:bg-sky-200 *:hover:text-black",
)}
key={request.game.id}>
<div className="pl-3 pr-1 rounded-l-lg">
{request.white}
{request.flip ? "B" : "W"}: {request.opponent}
</div>
<div className="px-1">
{request.flip ? "W" : "B"}: {request.game.user}
</div>
<div className="px-1">
{request.black}
{request.game.dim}x{request.game.dim}
</div>
<div className="px-1">
{request.dim}x{request.dim}
T: {request.game.timesetting}
</div>
<div className="pl-1 pr-3 rounded-r-lg">
H{request.handi}
H: {request.handicap}
</div>
</div>
)
Expand Down
38 changes: 29 additions & 9 deletions src/main/java/com/bernd/GameController.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
import com.bernd.model.ViewGame;
import com.bernd.util.RandomString;
import com.bernd.util.SgfCreator;
import java.security.Principal;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
Expand All @@ -25,9 +29,6 @@
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.server.ResponseStatusException;

import java.security.Principal;
import java.time.LocalDate;

import static com.bernd.util.Auth.getPrincipal;
import static com.bernd.util.Util.COLORS;

Expand Down Expand Up @@ -140,24 +141,43 @@ public OpenGame newGame(@RequestBody OpenGame game) {
return result;
}

@PostMapping(value = "/api/accept", consumes = "application/json")
public ResponseEntity<?> accept(@RequestBody AcceptRequest acceptRequest) {
@PostMapping(value = "/api/lobby/start", consumes = "application/json")
public ResponseEntity<?> start(@RequestBody AcceptRequest acceptRequest) {
String principal = getPrincipal();
openGames.remove(principal);
OpenGame openGame = openGames.remove(acceptRequest.game().user());
Game fullGame = games.put(openGame.accept(principal, acceptRequest));
openGames.remove(acceptRequest.opponent());
OpenGame openGame = openGames.remove(principal);
Game fullGame = games.put(openGame.accept(acceptRequest));
activeGames.put(ActiveGame.fromGame(fullGame));
Chat chat = chats.get(openGame.id());

ChatMessage startMessage = ChatMessage.createStartMessage(chat, fullGame);
chat.messages().add(startMessage);
operations.convertAndSend("/topic/chat/" + chat.id(), startMessage);
operations.convertAndSend("/topic/game/" + fullGame.id(), fullGame.toView());
operations.convertAndSend("/topic/gamestart", Map.of(
"opponent", acceptRequest.opponent(),
"id", openGame.id()));
operations.convertAndSend("/topic/lobby/open_games", openGames.games());
operations.convertAndSend("/topic/lobby/active_games", activeGames.games());
return ResponseEntity.ok().build();
}

@ResponseBody
@PostMapping(value = "/api/challenge", consumes = "application/json")
public Map<String, List<AcceptRequest>> challenge(@RequestBody AcceptRequest acceptRequest) {
String principal = getPrincipal();
openGames.remove(principal);
OpenGame openGame = openGames.addRequest(acceptRequest.game().user(), acceptRequest, principal);
operations.convertAndSend("/topic/lobby/requests", Map.of("requests", openGame.requests()));
return Map.of("requests", openGame.requests());
}

@ResponseBody
@GetMapping(value = "/api/lobby/requests")
public Map<String, List<AcceptRequest>> getRequests() {
String principal = getPrincipal();
return Map.of("requests", openGames.getRequests(principal));
}

@GetMapping("/api/sgf/{id}/{black}_vs_{white}.sgf")
public ResponseEntity<String> getSgf(
@PathVariable String id) {
Expand Down
Loading

0 comments on commit 770f117

Please sign in to comment.