121 lines
4.4 KiB
JavaScript

const { v4: uuidv4 } = require('uuid');
const { logger } = require('../../utils/logger');
module.exports = function(io, socket, gameState) {
socket.on('registerPlayer', function(data) {
try {
const rating = data.rating;
const nickname = data.nickname;
gameState.playerRating.set(socket.id, rating);
gameState.nickname.set(socket.id, nickname);
logger.info(`플레이어 등록: ID ${socket.id}, 닉네임: ${nickname}, 급수 ${rating}`);
// 급수에 따른 매칭 진행
findMatch(socket, rating, nickname);
} catch (err) {
logger.error(`플레이어 등록 중 오류: ${err}`);
socket.emit('error', { message: "플레이어 등록 중 오류가 발생했습니다." });
}
});
const switchToAI = (roomId, socket) => {
// 대기방 목록에서 제거
gameState.rooms = gameState.rooms.filter(room => room.roomId !== roomId);
// 플레이어 매칭 정보 제거
gameState.playerRating.delete(socket.id);
gameState.nickname.delete(socket.id);
gameState.matchingTimeouts.delete(socket.id);
socket.emit('switchAI', {
message: "타임아웃 AI로 전환"
});
}
const findMatch = (socket, playerRating, nickname) => {
let matchedRoom = null;
// 1. 같은 급수의 방 찾기
matchedRoom = gameState.rooms.find(room =>
Math.abs(gameState.playerRating.get(room.hostId) - playerRating) === 0);
// 2. 같은 급수 방이 없으면 ±1급 범위로 확장
if (!matchedRoom) {
matchedRoom = gameState.rooms.find(room =>
Math.abs(gameState.playerRating.get(room.hostId) - playerRating) <= 1);
}
if (matchedRoom) {
const roomId = matchedRoom.roomId;
// 매칭된 방은 대기 목록에서 제거
gameState.rooms = gameState.rooms.filter(room => room.roomId !== roomId);
// 방 입장
socket.join(roomId);
gameState.socketRooms.set(socket.id, roomId);
// 흑백 여부 결정 50% 확률
let isHostFirst = Math.random() < 0.5;
// 클라이언트에게 방 정보 전송 (상대 급수 정보 포함)
socket.emit('joinRoom', {
roomId: roomId,
opponentRating: gameState.playerRating.get(matchedRoom.hostId),
opponentNickname: gameState.nickname.get(matchedRoom.hostId),
opponentImageIndex: gameState.imageIndex.get(matchedRoom.hostId),
isBlack: !isHostFirst
});
// 상대방에게 게임 시작 알림 (내 닉네임과 급수 정보 포함)
socket.to(roomId).emit('startGame', {
opponentId: socket.id,
opponentRating: playerRating,
opponentNickname: nickname,
isBlack: isHostFirst
});
logger.info(`매칭 성공: ${socket.id}(${playerRating}급) - ${matchedRoom.hostId}(${gameState.playerRating.get(matchedRoom.hostId)}급)`);
}
// 4. 매칭된 방이 없으면 새 방 생성
else {
const roomId = uuidv4();
socket.join(roomId);
gameState.rooms.push({
roomId: roomId,
hostId: socket.id,
rating: playerRating
});
gameState.socketRooms.set(socket.id, roomId);
socket.emit('createRoom', {
roomId: roomId,
message: "대기 중... 비슷한 상대를 찾고 있습니다."
});
logger.info(`대기방 생성: ID ${socket.id}, 급수 ${playerRating}, 방 ID ${roomId}`);
// 10초 타임아웃 설정
const timeoutId = setTimeout(() => {
logger.info("타이머 종료, 15초 경과");
// 타임 아웃 AI로 던지기
// 아직 방에 혼자인지 확인
const room = gameState.rooms.find(r => r.roomId === roomId);
if (room) {
// 방이 남아 있으면 매칭 전임
logger.info("방이 남아 있어 방 삭제 후 AI로 전달");
switchToAI(roomId, socket);
}
},15000)
// 타임아웃 ID 저장
gameState.matchingTimeouts.set(socket.id, timeoutId);
}
}
};