Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion ServerlessFunction/buildspec-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ phases:
--capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND \
--no-confirm-changeset \
--no-fail-on-empty-changeset \
--parameter-overrides Environment=$ENVIRONMENT
--parameter-overrides \
Environment=$ENVIRONMENT \
ExistingCognitoUserPoolId=ap-northeast-2_ezDwzFCzR \
ExistingCognitoClientId=4ns077jcr1pkue2vvisr6qdpu5
- echo "Deployment completed on $(date)"

cache:
Expand Down
5 changes: 4 additions & 1 deletion ServerlessFunction/buildspec-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ phases:
--capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND \
--no-confirm-changeset \
--no-fail-on-empty-changeset \
--parameter-overrides Environment=$ENVIRONMENT
--parameter-overrides \
Environment=$ENVIRONMENT \
ExistingCognitoUserPoolId=ap-northeast-2_ezDwzFCzR \
ExistingCognitoClientId=4ns077jcr1pkue2vvisr6qdpu5
- echo "Deployment completed on $(date)"

cache:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import com.mzc.secondproject.serverless.domain.chatting.service.ChatMessageService;
import com.mzc.secondproject.serverless.domain.chatting.service.CommandService;
import com.mzc.secondproject.serverless.domain.chatting.service.GameService;
import com.mzc.secondproject.serverless.domain.user.model.User;
import com.mzc.secondproject.serverless.domain.user.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -44,6 +46,7 @@ public class WebSocketMessageHandler implements RequestHandler<Map<String, Objec
private final WebSocketBroadcaster broadcaster;
private final CommandService commandService;
private final GameService gameService;
private final UserService userService;

public WebSocketMessageHandler() {
this.chatMessageService = new ChatMessageService();
Expand All @@ -53,6 +56,7 @@ public WebSocketMessageHandler() {
this.broadcaster = new WebSocketBroadcaster();
this.commandService = new CommandService();
this.gameService = new GameService();
this.userService = new UserService();
}

@Override
Expand Down Expand Up @@ -155,6 +159,21 @@ private Map<String, Object> handleRegularMessage(String connectionId, MessagePay
// 일반 메시지 저장 및 브로드캐스트
String messageId = UUID.randomUUID().toString();
String now = Instant.now().toString();

// 닉네임 조회
String nickname = "Unknown";
try {
// DB에서 유저 정보(닉네임) 가져오기
User user = userService.getUserProfile(payload.userId);
if (user != null && user.getNickname() != null) {
nickname = user.getNickname();
} else {
// 혹시 없으면 UUID 사용
nickname = payload.userId;
}
} catch (Exception e) {
nickname = payload.userId;
}

ChatMessage message = ChatMessage.builder()
.pk("ROOM#" + payload.roomId)
Expand All @@ -166,6 +185,7 @@ private Map<String, Object> handleRegularMessage(String connectionId, MessagePay
.messageId(messageId)
.roomId(payload.roomId)
.userId(payload.userId)
.nickname(nickname)
.content(payload.content)
.messageType(messageType)
.createdAt(now)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class ChatMessage {
private String messageId;
private String roomId;
private String userId;
private String nickname;
private String content;
private String messageType; // TEXT, IMAGE, VOICE, AI_RESPONSE
private String createdAt;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@
public class GameSettings {
@Builder.Default
private Integer maxRounds = 5;

@Builder.Default
private Integer roundTimeLimit = 60;


@Builder.Default
private Integer turnTimeLimit = 15; // 끝말잇기용 턴 시간 제한

@Builder.Default
private Boolean autoDeleteOnEnd = false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public class WordChainSession {
private Character nextLetter; // 다음 사람이 시작해야 할 글자
private Long turnStartTime;
private Integer timeLimit; // 현재 라운드 시간 제한 (초)
private Integer baseTurnTimeLimit; // 사용자 설정 기본 턴 시간 (초)

// 플레이어 관리
private List<String> players; // 전체 플레이어 (순서대로)
Expand Down Expand Up @@ -182,10 +183,27 @@ public String getWinner() {

/**
* 시간 제한 계산 (라운드에 따라 점점 빨라짐)
* Round 1-2: 15초, Round 3-4: 13초, Round 5-6: 11초, Round 7-8: 9초, Round 9+: 8초
* 기본값 15초에서 시작하여 2라운드마다 2초씩 감소, 최소 8초
*/
public static int calculateTimeLimit(int round) {
return Math.max(8, 15 - ((round - 1) / 2) * 2);
return calculateTimeLimit(round, 15);
}

/**
* 시간 제한 계산 (기본 시간 제한 기준)
* 설정된 기본 시간에서 시작하여 2라운드마다 1초씩 감소, 최소 (baseTimeLimit / 2)초
*/
public static int calculateTimeLimit(int round, int baseTimeLimit) {
int minTimeLimit = Math.max(5, baseTimeLimit / 2);
return Math.max(minTimeLimit, baseTimeLimit - ((round - 1) / 2));
}

/**
* 세션의 기본 시간 제한을 기준으로 다음 라운드 시간 계산
*/
public int getNextRoundTimeLimit(int nextRound) {
int base = baseTurnTimeLimit != null ? baseTurnTimeLimit : 15;
return calculateTimeLimit(nextRound, base);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.mzc.secondproject.serverless.domain.chatting.service;

import com.mzc.secondproject.serverless.domain.chatting.model.ChatRoom;
import com.mzc.secondproject.serverless.domain.chatting.model.Connection;
import com.mzc.secondproject.serverless.domain.chatting.model.GameSettings;
import com.mzc.secondproject.serverless.domain.chatting.model.WordChainSession;
import com.mzc.secondproject.serverless.domain.chatting.repository.ChatRoomRepository;
import com.mzc.secondproject.serverless.domain.chatting.repository.ConnectionRepository;
import com.mzc.secondproject.serverless.domain.chatting.repository.WordChainSessionRepository;
import com.mzc.secondproject.serverless.domain.user.model.User;
Expand Down Expand Up @@ -29,23 +32,27 @@ public class WordChainService {

private final WordChainSessionRepository sessionRepository;
private final ConnectionRepository connectionRepository;
private final ChatRoomRepository chatRoomRepository;
private final UserRepository userRepository;
private final DictionaryService dictionaryService;
private final Random random;

public WordChainService() {
this(new WordChainSessionRepository(),
new ConnectionRepository(),
new ChatRoomRepository(),
new UserRepository(),
new DictionaryService());
}

public WordChainService(WordChainSessionRepository sessionRepository,
ConnectionRepository connectionRepository,
ChatRoomRepository chatRoomRepository,
UserRepository userRepository,
DictionaryService dictionaryService) {
this.sessionRepository = sessionRepository;
this.connectionRepository = connectionRepository;
this.chatRoomRepository = chatRoomRepository;
this.userRepository = userRepository;
this.dictionaryService = dictionaryService;
this.random = new Random();
Expand All @@ -67,6 +74,17 @@ public GameStartResult startGame(String roomId, String userId) {
return GameStartResult.error("최소 2명 이상 필요합니다.");
}

// 방 정보에서 gameSettings 조회
Optional<ChatRoom> optRoom = chatRoomRepository.findById(roomId);
int baseTurnTimeLimit = 15; // 기본값
if (optRoom.isPresent()) {
ChatRoom room = optRoom.get();
GameSettings settings = room.getGameSettings();
if (settings != null && settings.getTurnTimeLimit() != null) {
baseTurnTimeLimit = settings.getTurnTimeLimit();
}
}

// 플레이어 순서 랜덤 셔플
List<String> players = connections.stream()
.map(Connection::getUserId)
Expand All @@ -81,7 +99,7 @@ public GameStartResult startGame(String roomId, String userId) {
String sessionId = UUID.randomUUID().toString();
String now = Instant.now().toString();
long currentTime = System.currentTimeMillis();
int timeLimit = WordChainSession.calculateTimeLimit(1);
int timeLimit = baseTurnTimeLimit; // 사용자 설정 턴 시간 사용

WordChainSession session = WordChainSession.builder()
.pk("WORDCHAIN#" + sessionId)
Expand All @@ -100,6 +118,7 @@ public GameStartResult startGame(String roomId, String userId) {
.nextLetter(nextLetter)
.turnStartTime(currentTime)
.timeLimit(timeLimit)
.baseTurnTimeLimit(baseTurnTimeLimit)
.players(players)
.activePlayers(new ArrayList<>(players))
.eliminatedPlayers(new ArrayList<>())
Expand Down Expand Up @@ -171,7 +190,7 @@ public WordSubmitResult submitWord(String roomId, String userId, String word) {
char nextLetter = normalizedWord.charAt(normalizedWord.length() - 1);
String nextPlayerId = session.getNextPlayerId();
int nextRound = session.getCurrentRound() + 1;
int nextTimeLimit = WordChainSession.calculateTimeLimit(nextRound);
int nextTimeLimit = session.getNextRoundTimeLimit(nextRound);

session.setCurrentRound(nextRound);
session.setCurrentWord(normalizedWord);
Expand Down Expand Up @@ -227,7 +246,7 @@ private WordSubmitResult handleTimeout(WordChainSession session, String userId)
// 다음 턴 준비
String nextPlayerId = session.getNextPlayerId();
int nextRound = session.getCurrentRound() + 1;
int nextTimeLimit = WordChainSession.calculateTimeLimit(nextRound);
int nextTimeLimit = session.getNextRoundTimeLimit(nextRound);

session.setCurrentRound(nextRound);
session.setCurrentPlayerId(nextPlayerId);
Expand Down
Loading