Add cookies and game deletions
This commit is contained in:
@@ -67,6 +67,8 @@ public class ChessController : ControllerBase
|
||||
isWhite = false;
|
||||
}
|
||||
|
||||
ScheduleRemoveGame(gameState.GameId, TimeSpan.FromDays(1));
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
Id = playerId,
|
||||
@@ -146,12 +148,12 @@ public class ChessController : ControllerBase
|
||||
if (result.IsCheckmate || result.IsStalemate)
|
||||
{
|
||||
// queue game removal
|
||||
_gameRemovalTasks.TryAdd(moveDto.GameId, Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromMinutes(1));
|
||||
_games.Remove(moveDto.GameId, out _);
|
||||
_gameRemovalTasks.Remove(moveDto.GameId, out _);
|
||||
}));
|
||||
ScheduleRemoveGame(gameState.GameId, TimeSpan.FromMinutes(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
// increase timeout if play continues.
|
||||
ScheduleRemoveGame(gameState.GameId, TimeSpan.FromDays(1));
|
||||
}
|
||||
|
||||
return Ok(result);
|
||||
@@ -189,4 +191,26 @@ public class ChessController : ControllerBase
|
||||
|
||||
return Ok(allMoves);
|
||||
}
|
||||
|
||||
private static void ScheduleRemoveGame(Guid id, TimeSpan delay)
|
||||
{
|
||||
if (_gameRemovalTasks.ContainsKey(id))
|
||||
{
|
||||
_gameRemovalTasks[id] = Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(delay);
|
||||
_games.Remove(id, out _);
|
||||
_gameRemovalTasks.Remove(id, out _);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_gameRemovalTasks.TryAdd(id, Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(delay);
|
||||
_games.Remove(id, out _);
|
||||
_gameRemovalTasks.Remove(id, out _);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,14 @@ public class ChessHub : Hub
|
||||
await Groups.AddToGroupAsync(Context.ConnectionId, gameId);
|
||||
}
|
||||
|
||||
public async Task MoveMade(string gameId, MoveResultDto moveResult)
|
||||
public async Task MoveMade(string gameId, MoveDto moveDto, MoveResultDto moveResult)
|
||||
{
|
||||
await Clients.OthersInGroup(gameId).SendAsync("ReceiveMoveUpdate", gameId, moveResult);
|
||||
await Clients.OthersInGroup(gameId).SendAsync("ReceiveMoveUpdate", gameId, moveDto, moveResult);
|
||||
}
|
||||
|
||||
public async Task LeaveWebsocketGroup(string gameId)
|
||||
{
|
||||
Console.WriteLine($"❌ Leaving group {gameId}");
|
||||
await Groups.RemoveFromGroupAsync(Context.ConnectionId, gameId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,4 +41,14 @@
|
||||
|
||||
#chessBoard.flipped {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.chessSquare.previous-start {
|
||||
box-sizing: border-box;
|
||||
border: 4px solid #ffd700; /* gold or whatever you like */
|
||||
}
|
||||
|
||||
.chessSquare.previous-end {
|
||||
box-sizing: border-box;
|
||||
border: 4px solid #ff8c00; /* orange */
|
||||
}
|
||||
@@ -4,6 +4,8 @@ let currentPlayerIsWhite = null;
|
||||
let signalRConnection = null;
|
||||
let selectedPiece = null;
|
||||
let legalMoves = [];
|
||||
let previousMoveStart = null;
|
||||
let previousMoveEnd = null;
|
||||
|
||||
async function startNewGame() {
|
||||
// Stop previous SignalR connection if needed
|
||||
@@ -19,35 +21,15 @@ async function startNewGame() {
|
||||
currentGameId = gameData.gameId;
|
||||
currentPlayerId = gameData.id;
|
||||
currentPlayerIsWhite = gameData.isWhite;
|
||||
previousMoveStart = null;
|
||||
previousMoveEnd = null;
|
||||
document.cookie = `chessGameId=${currentGameId}; path=/; max-age=86400`; // expires in 1 day
|
||||
document.cookie = `chessPlayerId=${currentPlayerId}; path=/; max-age=86400`;
|
||||
document.cookie = `chessPlayerIsWhite=${currentPlayerIsWhite}; path=/; max-age=86400`
|
||||
console.log("🆕 Game started:", currentGameId);
|
||||
|
||||
// Build and start SignalR connection
|
||||
signalRConnection = new signalR.HubConnectionBuilder()
|
||||
.withUrl("/chessHub")
|
||||
.configureLogging(signalR.LogLevel.Information)
|
||||
.build();
|
||||
|
||||
signalRConnection.onclose(err => {
|
||||
console.error("❌ SignalR connection closed:", err?.message);
|
||||
});
|
||||
|
||||
signalRConnection.on("ReceiveMoveUpdate", async (gameId, moveResultDto) => {
|
||||
if (gameId !== currentGameId) return;
|
||||
|
||||
const res = await fetch(`/api/chess/${gameId}`);
|
||||
const data = await res.json();
|
||||
renderPieces(data.pieces);
|
||||
|
||||
alertGameStatusChange(moveResultDto);
|
||||
});
|
||||
|
||||
try {
|
||||
await signalRConnection.start();
|
||||
console.log("✅ SignalR connected");
|
||||
await signalRConnection.invoke("JoinWebsocketGroup", currentGameId);
|
||||
} catch (err) {
|
||||
console.error("❌ SignalR failed to start or join:", err);
|
||||
}
|
||||
await setupSignalRConnection();
|
||||
|
||||
// Render initial state
|
||||
const gameState = await fetch(`/api/chess/${currentGameId}`);
|
||||
@@ -87,11 +69,23 @@ function renderPieces(pieces) {
|
||||
|
||||
for (let i = 0; i < 64; i++) {
|
||||
const square = document.getElementById(`square-${i}`);
|
||||
square.classList.remove("previous-start", "previous-end");
|
||||
|
||||
if (!square.classList.contains("legal")) {
|
||||
square.onclick = () => clearHighlights();
|
||||
}
|
||||
}
|
||||
|
||||
if (previousMoveStart && previousMoveEnd) {
|
||||
const [startRow, startCol] = flipCoordinates(...previousMoveStart);
|
||||
const [endRow, endCol] = flipCoordinates(...previousMoveEnd);
|
||||
|
||||
const startIndex = startRow * 8 + startCol;
|
||||
const endIndex = endRow * 8 + endCol;
|
||||
|
||||
document.getElementById(`square-${startIndex}`)?.classList.add("previous-start");
|
||||
document.getElementById(`square-${endIndex}`)?.classList.add("previous-end");
|
||||
}
|
||||
}
|
||||
|
||||
function getPieceImageUrl(piece) {
|
||||
@@ -164,6 +158,9 @@ async function handleMove(targetRow, targetCol) {
|
||||
PromotionChoice: null // optional
|
||||
};
|
||||
|
||||
previousMoveStart = [selectedPiece.row, selectedPiece.col];
|
||||
previousMoveEnd = [targetRow, targetCol];
|
||||
|
||||
const res = await fetch("/api/chess/move", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
@@ -184,7 +181,7 @@ async function handleMove(targetRow, targetCol) {
|
||||
selectedPiece = null;
|
||||
legalMoves = [];
|
||||
clearHighlights();
|
||||
await signalRConnection.invoke("MoveMade", currentGameId, moveResultDto);
|
||||
await signalRConnection.invoke("MoveMade", currentGameId, moveDto, moveResultDto);
|
||||
|
||||
alertGameStatusChange(moveResultDto);
|
||||
}
|
||||
@@ -208,7 +205,8 @@ function clearHighlights() {
|
||||
}
|
||||
|
||||
function alertGameStatusChange(moveResultDto) {
|
||||
setTimeout(() => {
|
||||
setTimeout(async () => {
|
||||
let gameOver = false;
|
||||
// 🟡 Optional: show check
|
||||
if (moveResultDto.isCheck) {
|
||||
console.log("🛑 Check!");
|
||||
@@ -222,6 +220,12 @@ function alertGameStatusChange(moveResultDto) {
|
||||
alert("🤝 Stalemate!");
|
||||
gameOver = true;
|
||||
}
|
||||
|
||||
if (gameOver) {
|
||||
await signalRConnection.invoke("LeaveWebsocketGroup", currentGameId);
|
||||
await signalRConnection.stop();
|
||||
signalRConnection = null;
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
|
||||
@@ -232,5 +236,68 @@ function flipCoordinates(row, col) {
|
||||
return [row, col];
|
||||
}
|
||||
|
||||
function getCookie(name) {
|
||||
const value = document.cookie.split('; ')
|
||||
.find(row => row.startsWith(name + '='));
|
||||
return value ? value.split('=')[1] : null;
|
||||
}
|
||||
|
||||
async function setupSignalRConnection() {
|
||||
signalRConnection = new signalR.HubConnectionBuilder()
|
||||
.withUrl("/chessHub")
|
||||
.configureLogging(signalR.LogLevel.Information)
|
||||
.build();
|
||||
|
||||
signalRConnection.onclose(err => {
|
||||
console.error("❌ SignalR connection closed:", err?.message);
|
||||
});
|
||||
|
||||
signalRConnection.on("ReceiveMoveUpdate", async (gameId, moveDto, moveResultDto) => {
|
||||
if (gameId !== currentGameId) return;
|
||||
|
||||
const res = await fetch(`/api/chess/${gameId}`);
|
||||
const data = await res.json();
|
||||
previousMoveStart = [moveDto.sourceRow, moveDto.sourceCol];
|
||||
previousMoveEnd = [moveDto.targetRow, moveDto.targetCol];
|
||||
renderPieces(data.pieces);
|
||||
|
||||
alertGameStatusChange(moveResultDto);
|
||||
});
|
||||
|
||||
try {
|
||||
await signalRConnection.start();
|
||||
console.log("✅ SignalR connected");
|
||||
await signalRConnection.invoke("JoinWebsocketGroup", currentGameId);
|
||||
} catch (err) {
|
||||
console.error("❌ SignalR failed to start or join:", err);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("chessLogic.js loaded");
|
||||
window.startNewGame = startNewGame;
|
||||
window.startNewGame = startNewGame;
|
||||
|
||||
window.addEventListener('load', async () => {
|
||||
const savedGameId = getCookie("chessGameId");
|
||||
const savedPlayerId = getCookie("chessPlayerId");
|
||||
const savedPlayerIsWhite = getCookie("chessPlayerIsWhite");
|
||||
|
||||
if (savedGameId && savedPlayerId) {
|
||||
try {
|
||||
const response = await fetch(`/api/chess/${savedGameId}`);
|
||||
if (response.ok) {
|
||||
console.log("🧠 Rejoining saved game...");
|
||||
currentGameId = savedGameId;
|
||||
currentPlayerId = savedPlayerId;
|
||||
currentPlayerIsWhite = (savedPlayerIsWhite === "true");
|
||||
|
||||
await setupSignalRConnection(); // use your existing SignalR connect logic
|
||||
const gameData = await response.json();
|
||||
renderPieces(gameData.pieces);
|
||||
} else {
|
||||
console.warn("Saved game not found or expired.");
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Failed to rejoin saved game:", err);
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user