From e8bfdaaa30456bf10f91c768d9d9c06f76e746a3 Mon Sep 17 00:00:00 2001 From: sepia Date: Tue, 22 Jul 2025 20:58:13 -0500 Subject: [PATCH] Refactor request messages --- public/scripts/send-ws-messages.js | 72 +++--- src/messages.ts | 49 ++-- src/web-socket-handler.tsx | 380 +++++++++++------------------ 3 files changed, 195 insertions(+), 306 deletions(-) diff --git a/public/scripts/send-ws-messages.js b/public/scripts/send-ws-messages.js index 73f0ed0..8eb6e0c 100644 --- a/public/scripts/send-ws-messages.js +++ b/public/scripts/send-ws-messages.js @@ -17,51 +17,63 @@ document.addEventListener('htmx:wsConfigSend', function (e) { }; } else if (e.target.id == 'takeback-button') { e.detail.parameters = { - type: 'request_takeback', + type: 'takeback', + action: 'request', }; } else if (e.target.id == 'accept-takeback-button') { e.detail.parameters = { - type: 'accept_takeback', + type: 'takeback', + action: 'accept', }; } else if (e.target.id == 'decline-takeback-button') { e.detail.parameters = { - type: 'decline_takeback', - }; - } else if (e.target.id == 'draw-button') { - e.detail.parameters = { - type: 'request_draw', - }; - } else if (e.target.id == 'accept-draw-button') { - e.detail.parameters = { - type: 'accept_draw', - }; - } else if (e.target.id == 'decline-draw-button') { - e.detail.parameters = { - type: 'decline_draw', - }; - } else if (e.target.id == 'rematch-button') { - e.detail.parameters = { - type: 'request_rematch', - }; - } else if (e.target.id == 'accept-rematch-button') { - e.detail.parameters = { - type: 'accept_rematch', - }; - } else if (e.target.id == 'decline-rematch-button') { - e.detail.parameters = { - type: 'decline_rematch', + type: 'takeback', + action: 'decline', }; } else if (e.target.id == 'cancel-takeback-request-button') { e.detail.parameters = { - type: 'cancel_takeback_request', + type: 'takeback', + action: 'cancel', + }; + } else if (e.target.id == 'draw-button') { + e.detail.parameters = { + type: 'draw', + action: 'request', + }; + } else if (e.target.id == 'accept-draw-button') { + e.detail.parameters = { + type: 'draw', + action: 'accept', + }; + } else if (e.target.id == 'decline-draw-button') { + e.detail.parameters = { + type: 'draw', + action: 'decline', }; } else if (e.target.id == 'cancel-draw-request-button') { e.detail.parameters = { - type: 'cancel_draw_request', + type: 'draw', + action: 'cancel', + }; + } else if (e.target.id == 'rematch-button') { + e.detail.parameters = { + type: 'rematch', + action: 'request', + }; + } else if (e.target.id == 'accept-rematch-button') { + e.detail.parameters = { + type: 'rematch', + action: 'accept', + }; + } else if (e.target.id == 'decline-rematch-button') { + e.detail.parameters = { + type: 'rematch', + action: 'decline', }; } else if (e.target.id == 'cancel-rematch-request-button') { e.detail.parameters = { - type: 'cancel_rematch_request', + type: 'rematch', + action: 'cancel', }; } }); diff --git a/src/messages.ts b/src/messages.ts index 5fe19d0..6b7f26b 100644 --- a/src/messages.ts +++ b/src/messages.ts @@ -1,20 +1,13 @@ +export type ActionType = 'request' | 'accept' | 'decline' | 'cancel'; + export interface Message { type: | 'make_move' | 'resign' - | 'request_takeback' - | 'accept_takeback' - | 'decline_takeback' - | 'request_draw' - | 'accept_draw' - | 'decline_draw' - | 'request_rematch' - | 'accept_rematch' - | 'decline_rematch' - | 'redirect_to_game' - | 'cancel_takeback_request' - | 'cancel_draw_request' - | 'cancel_rematch_request'; + | 'takeback' + | 'draw' + | 'rematch' + | 'redirect_to_game'; } export interface MakeMoveMessage extends Message { @@ -24,30 +17,18 @@ export interface MakeMoveMessage extends Message { export interface ResignationMessage extends Message {} -export interface RequestTakebackMessage extends Message {} +export interface TakebackMessage extends Message { + action: ActionType; +} -export interface AcceptTakebackMessage extends Message {} +export interface DrawMessage extends Message { + action: ActionType; +} -export interface DeclineTakebackMessage extends Message {} - -export interface RequestDrawMessage extends Message {} - -export interface AcceptDrawMessage extends Message {} - -export interface DeclineDrawMessage extends Message {} - -export interface RequestRematchMessage extends Message {} - -export interface AcceptRematchMessage extends Message {} - -export interface DeclineRematchMessage extends Message {} +export interface RematchMessage extends Message { + action: ActionType; +} export interface RedirectToGameMessage extends Message { gameId: string; } - -export interface CancelTakebackRequestMessage extends Message {} - -export interface CancelDrawRequestMessage extends Message {} - -export interface CancelRematchRequestMessage extends Message {} diff --git a/src/web-socket-handler.tsx b/src/web-socket-handler.tsx index 73fc599..7691fd8 100644 --- a/src/web-socket-handler.tsx +++ b/src/web-socket-handler.tsx @@ -6,19 +6,10 @@ import { Message, MakeMoveMessage, ResignationMessage, - RequestTakebackMessage, - AcceptTakebackMessage, - DeclineTakebackMessage, - RequestDrawMessage, - AcceptDrawMessage, - DeclineDrawMessage, - RequestRematchMessage, - AcceptRematchMessage, - DeclineRematchMessage, + TakebackMessage, + DrawMessage, + RematchMessage, RedirectToGameMessage, - CancelTakebackRequestMessage, - CancelDrawRequestMessage, - CancelRematchRequestMessage, } from './messages'; import { v4 as uuidv4 } from 'uuid'; @@ -271,58 +262,16 @@ class GameServer { this.handleResignation(conn, message as ResignationMessage); break; } - case 'request_takeback': { - this.handleRequestTakeback(conn, message as RequestTakebackMessage); + case 'takeback': { + this.handleTakebackMessage(conn, message as TakebackMessage); break; } - case 'accept_takeback': { - this.handleAcceptTakeback(conn, message as AcceptTakebackMessage); + case 'draw': { + this.handleDrawMessage(conn, message as DrawMessage); break; } - case 'decline_takeback': { - this.handleDeclineTakeback(conn, message as DeclineTakebackMessage); - break; - } - case 'request_draw': { - this.handleRequestDraw(conn, message as RequestDrawMessage); - break; - } - case 'accept_draw': { - this.handleAcceptDraw(conn, message as AcceptDrawMessage); - break; - } - case 'decline_draw': { - this.handleDeclineDraw(conn, message as DeclineDrawMessage); - break; - } - case 'request_rematch': { - this.handleRequestRematch(conn, message as RequestRematchMessage); - break; - } - case 'accept_rematch': { - this.handleAcceptRematch(conn, message as AcceptRematchMessage); - break; - } - case 'decline_rematch': { - this.handleDeclineRematch(conn, message as DeclineRematchMessage); - break; - } - case 'cancel_takeback_request': { - this.handleCancelTakebackRequest( - conn, - message as CancelTakebackRequestMessage, - ); - break; - } - case 'cancel_draw_request': { - this.handleCancelDrawRequest(conn, message as CancelDrawRequestMessage); - break; - } - case 'cancel_rematch_request': { - this.handleCancelRematchRequest( - conn, - message as CancelRematchRequestMessage, - ); + case 'rematch': { + this.handleRematchMessage(conn, message as RematchMessage); break; } } @@ -411,18 +360,133 @@ class GameServer { console.log(`Player ${conn.id} resigned from game ${this.id}`); } - private handleRequestTakeback( + private handleTakebackMessage( conn: PlayerConnection, - message: RequestTakebackMessage, + message: TakebackMessage, ): void { if (this.gomoku.status !== 'playing') { conn.sendMessage( 'error', - 'You can only request a takeback in an active game.', + 'You can only perform this action in an active game.', ); return; } + switch (message.action) { + case 'request': + this.handleRequestTakeback(conn); + break; + case 'accept': + if (!this.takebackRequesterId) { + conn.sendMessage('error', 'No takeback has been requested.'); + return; + } + this.handleAcceptTakeback(); + break; + case 'decline': + if (!this.takebackRequesterId) { + conn.sendMessage('error', 'No takeback has been requested.'); + return; + } + this.handleDeclineTakeback(); + break; + case 'cancel': + if (this.takebackRequesterId !== conn.id) { + conn.sendMessage( + 'error', + 'You are not the one who requested a takeback.', + ); + return; + } + this.handleCancelTakebackRequest(); + break; + } + } + private handleDrawMessage( + conn: PlayerConnection, + message: DrawMessage, + ): void { + if (this.gomoku.status !== 'playing') { + conn.sendMessage( + 'error', + 'You can only perform this action in an active game.', + ); + return; + } + switch (message.action) { + case 'request': + this.handleRequestDraw(conn); + break; + case 'accept': + if (!this.drawRequesterId) { + conn.sendMessage('error', 'No draw has been requested.'); + return; + } + this.handleAcceptDraw(); + break; + case 'decline': + if (!this.drawRequesterId) { + conn.sendMessage('error', 'No draw has been requested.'); + return; + } + this.handleDeclineDraw(); + break; + case 'cancel': + if (this.drawRequesterId !== conn.id) { + conn.sendMessage( + 'error', + 'You are not the one who requested a draw.', + ); + return; + } + this.handleCancelDrawRequest(); + break; + } + } + + private handleRematchMessage( + conn: PlayerConnection, + message: RematchMessage, + ): void { + if (this.gomoku.status !== 'finished') { + conn.sendMessage( + 'error', + 'You can only perform this action in a finished game.', + ); + return; + } + switch (message.action) { + case 'request': + this.handleRequestRematch(conn); + break; + case 'accept': + if (!this.rematchRequesterId) { + conn.sendMessage('error', 'No rematch has been requested.'); + return; + } + this.handleAcceptRematch(); + break; + case 'decline': + if (!this.rematchRequesterId) { + conn.sendMessage('error', 'No rematch has been requested.'); + return; + } + this.handleDeclineRematch(); + break; + case 'cancel': + if (this.rematchRequesterId !== conn.id) { + conn.sendMessage( + 'error', + 'You are not the one who requested a rematch.', + ); + return; + } + this.handleCancelRematchRequest(); + break; + } + } + + private handleRequestTakeback(conn: PlayerConnection): void { if (this.gomoku.history.length === 0) { conn.sendMessage('error', 'There are no moves to take back.'); return; @@ -436,23 +500,7 @@ class GameServer { this.broadcastButtons(); } - private handleAcceptTakeback( - conn: PlayerConnection, - message: AcceptTakebackMessage, - ): void { - if (this.gomoku.status !== 'playing') { - conn.sendMessage( - 'error', - 'You can only accept a takeback in an active game.', - ); - return; - } - - if (!this.takebackRequesterId) { - conn.sendMessage('error', 'No takeback has been requested.'); - return; - } - + private handleAcceptTakeback(): void { this.gomoku.undoMove(); this.takebackRequesterId = null; this.broadcastBoard(); @@ -460,38 +508,12 @@ class GameServer { this.broadcastTitle(); } - private handleDeclineTakeback( - conn: PlayerConnection, - message: DeclineTakebackMessage, - ): void { - if (this.gomoku.status !== 'playing') { - conn.sendMessage( - 'error', - 'You can only decline a takeback in an active game.', - ); - return; - } - - if (!this.takebackRequesterId) { - conn.sendMessage('error', 'No takeback has been requested.'); - return; - } - + private handleDeclineTakeback(): void { this.takebackRequesterId = null; this.broadcastButtons(); } - private handleRequestDraw( - conn: PlayerConnection, - message: RequestDrawMessage, - ): void { - if (this.gomoku.status !== 'playing') { - conn.sendMessage( - 'error', - 'You can only request a draw in an active game.', - ); - return; - } + private handleRequestDraw(conn: PlayerConnection): void { if (this.takebackRequesterId) { conn.sendMessage('error', 'A takeback has already been requested.'); return; @@ -501,23 +523,7 @@ class GameServer { this.broadcastButtons(); } - private handleAcceptDraw( - conn: PlayerConnection, - message: AcceptDrawMessage, - ): void { - if (this.gomoku.status !== 'playing') { - conn.sendMessage( - 'error', - 'You can only accept a draw in an active game.', - ); - return; - } - - if (!this.drawRequesterId) { - conn.sendMessage('error', 'No draw has been requested.'); - return; - } - + private handleAcceptDraw(): void { this.gomoku.declareDraw(); this.drawRequesterId = null; this.broadcastBoard(); @@ -525,60 +531,17 @@ class GameServer { this.broadcastTitle(); } - private handleDeclineDraw( - conn: PlayerConnection, - message: DeclineDrawMessage, - ): void { - if (this.gomoku.status !== 'playing') { - conn.sendMessage( - 'error', - 'You can only decline a draw in an active game.', - ); - return; - } - - if (!this.drawRequesterId) { - conn.sendMessage('error', 'No draw has been requested.'); - return; - } - + private handleDeclineDraw(): void { this.drawRequesterId = null; this.broadcastButtons(); } - private handleRequestRematch( - conn: PlayerConnection, - message: RequestRematchMessage, - ): void { - if (this.gomoku.status !== 'finished') { - conn.sendMessage( - 'error', - 'You can only request a rematch in a finished game.', - ); - return; - } - + private handleRequestRematch(conn: PlayerConnection): void { this.rematchRequesterId = conn.id; this.broadcastButtons(); } - private handleAcceptRematch( - conn: PlayerConnection, - message: AcceptRematchMessage, - ): void { - if (this.gomoku.status !== 'finished') { - conn.sendMessage( - 'error', - 'You can only accept a rematch in a finished game.', - ); - return; - } - - if (!this.rematchRequesterId) { - conn.sendMessage('error', 'No rematch has been requested.'); - return; - } - + private handleAcceptRematch(): void { const newGameId = this.webSocketHandler.createGame( undefined, this.whitePlayerId, @@ -593,89 +556,22 @@ class GameServer { }); } - private handleDeclineRematch( - conn: PlayerConnection, - message: DeclineRematchMessage, - ): void { - if (this.gomoku.status !== 'finished') { - conn.sendMessage( - 'error', - 'You can only decline a rematch in a finished game.', - ); - return; - } - - if (!this.rematchRequesterId) { - conn.sendMessage('error', 'No rematch has been requested.'); - return; - } - + private handleDeclineRematch(): void { this.rematchRequesterId = null; this.broadcastButtons(); } - private handleCancelTakebackRequest( - conn: PlayerConnection, - message: CancelTakebackRequestMessage, - ): void { - if (this.gomoku.status !== 'playing') { - conn.sendMessage( - 'error', - 'You can only cancel a takeback request in an active game.', - ); - return; - } - - if (this.takebackRequesterId !== conn.id) { - conn.sendMessage( - 'error', - 'You are not the one who requested a takeback.', - ); - return; - } - + private handleCancelTakebackRequest(): void { this.takebackRequesterId = null; this.broadcastButtons(); } - private handleCancelDrawRequest( - conn: PlayerConnection, - message: CancelDrawRequestMessage, - ): void { - if (this.gomoku.status !== 'playing') { - conn.sendMessage( - 'error', - 'You can only cancel a draw request in an active game.', - ); - return; - } - - if (this.drawRequesterId !== conn.id) { - conn.sendMessage('error', 'You are not the one who requested a draw.'); - return; - } - + private handleCancelDrawRequest(): void { this.drawRequesterId = null; this.broadcastButtons(); } - private handleCancelRematchRequest( - conn: PlayerConnection, - message: CancelRematchRequestMessage, - ): void { - if (this.gomoku.status !== 'finished') { - conn.sendMessage( - 'error', - 'You can only cancel a rematch request in a finished game.', - ); - return; - } - - if (this.rematchRequesterId !== conn.id) { - conn.sendMessage('error', 'You are not the one who requested a rematch.'); - return; - } - + private handleCancelRematchRequest(): void { this.rematchRequesterId = null; this.broadcastButtons(); }