Skip to content

Commit 106ab1c

Browse files
authored
Merge pull request #52 from Zeff01/feature/rock-paper-scissors
feat(rps): add functionality for playing with bot for single player
2 parents d75835f + 998fa6b commit 106ab1c

8 files changed

Lines changed: 897 additions & 174 deletions

File tree

backend/src/config/socket-server.ts

Lines changed: 124 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -8,158 +8,160 @@ let ioServer: Server | undefined;
88
export const roomManager = new RoomManager();
99

1010
export function initializeSocket(server: HTTPServer) {
11-
const io = new Server(server, {
12-
cors: {
13-
origin: process.env.CORS_ORIGIN || "*",
14-
methods: ["GET", "POST"],
15-
},
16-
});
17-
18-
ioServer = io;
19-
20-
roomManager.clearAllRooms();
21-
22-
io.on("connection", (socket) => {
23-
const userId = (socket.handshake.query.userId as string) || (socket.handshake.headers["user-id"] as string);
24-
25-
if (userId) {
26-
userSocketMap.set(userId, socket.id);
27-
}
11+
const io = new Server(server, {
12+
cors: {
13+
origin: process.env.CORS_ORIGIN || "*",
14+
methods: ["GET", "POST"],
15+
},
16+
});
2817

29-
logger.info(`A user connected ${socket.id}`);
18+
ioServer = io;
3019

31-
socket.emit("rooms:list", roomManager.listRooms());
20+
//roomManager.clearAllRooms();
3221

33-
socket.on("room:create", (data: { roomName?: string }) => {
34-
try {
35-
const room = roomManager.createRoom(socket.id, data?.roomName);
36-
socket.join(room.id);
22+
io.on("connection", (socket) => {
23+
const userId =
24+
(socket.handshake.query.userId as string) ||
25+
(socket.handshake.headers["user-id"] as string);
3726

38-
socket.emit("room:created", {
39-
success: true,
40-
room: roomManager.getRoomInfo(room.id),
41-
});
27+
if (userId) {
28+
userSocketMap.set(userId, socket.id);
29+
}
4230

43-
logger.info(`Created room ${room.id} for user ${socket.id}`);
44-
io.emit("rooms:list", roomManager.listRooms());
45-
} catch (err) {
46-
logger.error("Error creating room", { error: err });
47-
socket.emit("room:error", { message: "Failed to create room" });
48-
}
49-
});
31+
logger.info(`A user connected ${socket.id}`);
5032

51-
socket.on("room:join", (data: { roomId: string }) => {
52-
try {
53-
const success = roomManager.joinRoom(data.roomId, socket.id);
54-
console.log("joinRoom result:", data, success);
33+
socket.emit("rooms:list", roomManager.listRooms());
5534

56-
if (!success) {
57-
socket.emit("room:error", { message: "Room not found" });
58-
return;
59-
}
35+
socket.on("room:create", (data: { roomName?: string }) => {
36+
try {
37+
const room = roomManager.createRoom(socket.id, data?.roomName);
38+
socket.join(room.id);
6039

61-
socket.join(data.roomId);
40+
socket.emit("room:created", {
41+
success: true,
42+
room: roomManager.getRoomInfo(room.id),
43+
});
6244

63-
socket.emit("room:joined", {
64-
success: true,
65-
room: roomManager.getRoomInfo(data.roomId),
45+
logger.info(`Created room ${room.id} for user ${socket.id}`);
46+
io.emit("rooms:list", roomManager.listRooms());
47+
} catch (err) {
48+
logger.error("Error creating room", { error: err });
49+
socket.emit("room:error", { message: "Failed to create room" });
50+
}
6651
});
6752

68-
// Notify others in the room
69-
socket.to(data.roomId).emit("player:joined", {
70-
playerId: socket.id,
71-
room: roomManager.getRoomInfo(data.roomId),
53+
socket.on("room:join", (data: { roomId: string }) => {
54+
try {
55+
const success = roomManager.joinRoom(data.roomId, socket.id);
56+
console.log("joinRoom result:", data, success);
57+
58+
if (!success) {
59+
socket.emit("room:error", { message: "Room not found" });
60+
return;
61+
}
62+
63+
socket.join(data.roomId);
64+
65+
socket.emit("room:joined", {
66+
success: true,
67+
room: roomManager.getRoomInfo(data.roomId),
68+
});
69+
70+
// Notify others in the room
71+
socket.to(data.roomId).emit("player:joined", {
72+
playerId: socket.id,
73+
room: roomManager.getRoomInfo(data.roomId),
74+
});
75+
76+
// Broadcast updated room list
77+
io.emit("rooms:list", roomManager.listRooms());
78+
} catch (err) {
79+
logger.error("Error joining room", { error: err });
80+
socket.emit("room:error", { message: "Failed to join room" });
81+
}
7282
});
7383

74-
// Broadcast updated room list
75-
io.emit("rooms:list", roomManager.listRooms());
76-
} catch (err) {
77-
logger.error("Error joining room", { error: err });
78-
socket.emit("room:error", { message: "Failed to join room" });
79-
}
80-
});
81-
82-
socket.on("room:leave", (data: { roomId: string }) => {
83-
try {
84-
roomManager.leaveRoom(data.roomId, socket.id);
85-
socket.leave(data.roomId);
86-
87-
socket.emit("room:left", { success: true });
88-
89-
// Notify others in the room
90-
socket.to(data.roomId).emit("player:left", {
91-
playerId: socket.id,
92-
room: roomManager.getRoomInfo(data.roomId),
84+
socket.on("room:leave", (data: { roomId: string }) => {
85+
try {
86+
roomManager.leaveRoom(data.roomId, socket.id);
87+
socket.leave(data.roomId);
88+
89+
socket.emit("room:left", { success: true });
90+
91+
// Notify others in the room
92+
socket.to(data.roomId).emit("player:left", {
93+
playerId: socket.id,
94+
room: roomManager.getRoomInfo(data.roomId),
95+
});
96+
97+
// Broadcast updated room list
98+
io.emit("rooms:list", roomManager.listRooms());
99+
} catch (err) {
100+
logger.error("Error leaving room", { error: err });
101+
socket.emit("room:error", { message: "Failed to leave room" });
102+
}
93103
});
94104

95-
// Broadcast updated room list
96-
io.emit("rooms:list", roomManager.listRooms());
97-
} catch (err) {
98-
logger.error("Error leaving room", { error: err });
99-
socket.emit("room:error", { message: "Failed to leave room" });
100-
}
101-
});
105+
socket.on("rooms:get", () => {
106+
socket.emit("rooms:list", roomManager.listRooms());
107+
});
102108

103-
socket.on("rooms:get", () => {
104-
socket.emit("rooms:list", roomManager.listRooms());
105-
});
109+
socket.on("room:get", (data: { roomId: string }) => {
110+
const roomInfo = roomManager.getRoomInfo(data.roomId);
111+
if (roomInfo) {
112+
socket.emit("room:info", roomInfo);
113+
} else {
114+
socket.emit("room:error", { message: "Room not found" });
115+
}
116+
});
106117

107-
socket.on("room:get", (data: { roomId: string }) => {
108-
const roomInfo = roomManager.getRoomInfo(data.roomId);
109-
if (roomInfo) {
110-
socket.emit("room:info", roomInfo);
111-
} else {
112-
socket.emit("room:error", { message: "Room not found" });
113-
}
114-
});
118+
// CHAT MESSAGES
115119

116-
// CHAT MESSAGES
120+
socket.on("chat message", (msg) => {
121+
try {
122+
logger.info("Message received from backend", { message: msg });
123+
io.emit("chat message", msg);
124+
} catch (err) {
125+
logger.error("Error handling chat message", { error: err });
126+
}
127+
});
117128

118-
socket.on("chat message", (msg) => {
119-
try {
120-
logger.info("Message received from backend", { message: msg });
121-
io.emit("chat message", msg);
122-
} catch (err) {
123-
logger.error("Error handling chat message", { error: err });
124-
}
125-
});
129+
// DISCONNECT HANDLING
126130

127-
// DISCONNECT HANDLING
131+
socket.on("disconnect", (reason) => {
132+
logger.info(`User ${socket.id} disconnected`, { reason });
128133

129-
socket.on("disconnect", (reason) => {
130-
logger.info(`User ${socket.id} disconnected`, { reason });
134+
// Find and leave any room the player was in
135+
const playerRoom = roomManager.getPlayerRoom(socket.id);
136+
if (playerRoom) {
137+
roomManager.leaveRoom(playerRoom.id, socket.id);
131138

132-
// Find and leave any room the player was in
133-
const playerRoom = roomManager.getPlayerRoom(socket.id);
134-
if (playerRoom) {
135-
roomManager.leaveRoom(playerRoom.id, socket.id);
139+
// Notify others in the room
140+
socket.to(playerRoom.id).emit("player:left", {
141+
playerId: socket.id,
142+
room: roomManager.getRoomInfo(playerRoom.id),
143+
});
136144

137-
// Notify others in the room
138-
socket.to(playerRoom.id).emit("player:left", {
139-
playerId: socket.id,
140-
room: roomManager.getRoomInfo(playerRoom.id),
145+
// Broadcast updated room list
146+
io.emit("rooms:list", roomManager.listRooms());
147+
}
141148
});
142149

143-
// Broadcast updated room list
144-
io.emit("rooms:list", roomManager.listRooms());
145-
}
150+
socket.on("error", (err) => {
151+
logger.error("Socket Error", { error: err });
152+
});
146153
});
147154

148-
socket.on("error", (err) => {
149-
logger.error("Socket Error", { error: err });
155+
io.on("connect_error", (err) => {
156+
logger.error("Global socket connection error", { error: err });
150157
});
151-
});
152-
153-
io.on("connect_error", (err) => {
154-
logger.error("Global socket connection error", { error: err });
155-
});
156158

157-
return io;
159+
return io;
158160
}
159161

160162
export const getIO = (): Server => {
161-
if (!ioServer) {
162-
throw new Error("Socket.io not initialized! Call initSocket first.");
163-
}
164-
return ioServer;
163+
if (!ioServer) {
164+
throw new Error("Socket.io not initialized! Call initSocket first.");
165+
}
166+
return ioServer;
165167
};

frontend/TASK.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,19 +120,19 @@ This document contains step-by-step tasks for implementing the frontend UI for C
120120

121121
- [x] Create choice selection interface
122122
- [x] Design choice buttons (rock/paper/scissors)
123-
- [ ] Add choice animation
124-
- [ ] Create result display
125-
- [ ] Show round history
126-
- [ ] Design score tracker
123+
- [x] Add choice animation
124+
- [x] Create result display
125+
- [x] Show round history
126+
- [x] Design score tracker
127127

128128
### TASK-F302: Rock Paper Scissors Game Page
129129

130130
- [x] Create game page route
131-
- [ ] Implement choice selection
131+
- [x] Implement choice selection
132132
- [ ] Add countdown timer
133-
- [ ] Display both players' choices
134-
- [ ] Show round winner
135-
- [ ] Track best-of-N series
133+
- [x] Display both players' choices
134+
- [x] Show round winner
135+
- [x] Track best-of-N series
136136

137137
### TASK-F303: Rock Paper Scissors Multiplayer
138138

0 commit comments

Comments
 (0)