Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] 방 설정 변경에 검증 로직 추가 #219

Merged
merged 6 commits into from
Aug 20, 2024
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
71 changes: 27 additions & 44 deletions backend/src/main/java/ddangkong/domain/room/Room.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import ddangkong.domain.balance.content.Category;
import ddangkong.exception.BadRequestException;
import jakarta.persistence.Column;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
Expand All @@ -19,14 +20,9 @@
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Room {

private static final int DEFAULT_TOTAL_ROUND = 5;
private static final int MIN_TOTAL_ROUND = 3;
private static final int MAX_TOTAL_ROUND = 10;
private static final int MAX_MEMBER_COUNT = 12;
private static final int MIN_TIME_LIMIT_MSEC = 10_000;
private static final int MAX_TIME_LIMIT_MSEC = 30_000;
private static final int START_ROUND = 1;
private static final int ALLOWED_ROUND_GAP = 1;
private static final int MAX_MEMBER_COUNT = 12;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand All @@ -35,57 +31,26 @@ public class Room {
@Column(nullable = false, unique = true)
private String uuid;

@Column(nullable = false)
private int totalRound;

@Column(nullable = false)
private int currentRound;

@Column(nullable = false)
private int timeLimit;
@Embedded
private RoomSetting roomSetting;

@Column(nullable = false)
@Enumerated(EnumType.STRING)
private RoomStatus status;

@Column(nullable = false)
@Enumerated(EnumType.STRING)
private Category category;

public Room(String uuid, int totalRound, int currentRound, int timeLimit, RoomStatus status, Category category) {
public Room(String uuid, int currentRound, RoomStatus status, RoomSetting roomSetting) {
this.uuid = uuid;
this.totalRound = totalRound;
this.currentRound = currentRound;
this.timeLimit = timeLimit;
this.status = status;
this.category = category;
this.roomSetting = roomSetting;
}

public static Room createNewRoom() {
String uuid = UUID.randomUUID().toString().replace("-", "");

return new Room(uuid, DEFAULT_TOTAL_ROUND, START_ROUND, MAX_TIME_LIMIT_MSEC, RoomStatus.READY,
Category.IF);
}

public void updateTimeLimit(int timeLimit) {
if (timeLimit < MIN_TIME_LIMIT_MSEC || timeLimit > MAX_TIME_LIMIT_MSEC) {
throw new BadRequestException("시간 제한은 %dms 이상, %dms 이하만 가능합니다. requested timeLimit: %d"
.formatted(MIN_TIME_LIMIT_MSEC, MAX_TIME_LIMIT_MSEC, timeLimit));
}
this.timeLimit = timeLimit;
}

public void updateTotalRound(int totalRound) {
if (totalRound < MIN_TOTAL_ROUND || totalRound > MAX_TOTAL_ROUND) {
throw new BadRequestException("총 라운드는 %d 이상, %d 이하만 가능합니다. requested totalRound: %d"
.formatted(MIN_TOTAL_ROUND, MAX_TOTAL_ROUND, totalRound));
}
this.totalRound = totalRound;
}

public void updateCategory(Category category) {
this.category = category;
return new Room(uuid, START_ROUND, RoomStatus.READY, RoomSetting.createNewRoomSetting());
}

public void startGame() {
Expand Down Expand Up @@ -138,11 +103,11 @@ private void validateRound(int round) {
}

private boolean isFinalRound() {
return currentRound == totalRound;
return roomSetting.isFinalRound(currentRound);
}

public boolean isAllRoundFinished() {
return currentRound == totalRound && status.isGameFinish();
return roomSetting.isFinalRound(currentRound) && status.isGameFinish();
}

public void reset() {
Expand All @@ -156,4 +121,22 @@ public void reset() {
public boolean isFull(long memberCountInRoom) {
return memberCountInRoom == MAX_MEMBER_COUNT;
}

public void updateRoomSetting(RoomSetting roomSetting) {
this.roomSetting.updateTimeLimit(roomSetting.getTimeLimit());
this.roomSetting.updateTotalRound(roomSetting.getTotalRound());
this.roomSetting.updateCategory(roomSetting.getCategory());
}

public int getTotalRound() {
return roomSetting.getTotalRound();
}

public Category getCategory() {
return roomSetting.getCategory();
}

public int getTimeLimit() {
return roomSetting.getTimeLimit();
}
}
63 changes: 62 additions & 1 deletion backend/src/main/java/ddangkong/domain/room/RoomSetting.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,82 @@
package ddangkong.domain.room;

import ddangkong.domain.balance.content.Category;
import ddangkong.exception.BadRequestException;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import java.util.List;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
// todo embeddable
@Embeddable
@EqualsAndHashCode
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class RoomSetting {

private static final int DEFAULT_TOTAL_ROUND = 5;
private static final int MIN_TOTAL_ROUND = 3;
private static final int MAX_TOTAL_ROUND = 10;
private static final List<Integer> ALLOWED_TIME_LIMIT = List.of(5_000, 10_000, 15_000);
private static final int DEFAULT_TIME_LIMIT_MSEC = 10_000;

@Column(nullable = false)
private int totalRound;

@Column(nullable = false)
private int timeLimit;

@Column(nullable = false)
@Enumerated(EnumType.STRING)
private Category category;

public static RoomSetting createNewRoomSetting() {
return new RoomSetting(DEFAULT_TOTAL_ROUND, DEFAULT_TIME_LIMIT_MSEC, Category.IF);
}

public RoomSetting(int totalRound, int timeLimit, Category category) {
validateTotalRound(totalRound);
validateTimeLimit(timeLimit);

this.totalRound = totalRound;
this.timeLimit = timeLimit;
this.category = category;
}

private void validateTotalRound(int totalRound) {
if (totalRound < MIN_TOTAL_ROUND || totalRound > MAX_TOTAL_ROUND) {
throw new BadRequestException("총 라운드는 %d 이상, %d 이하만 가능합니다. requested totalRound: %d"
.formatted(MIN_TOTAL_ROUND, MAX_TOTAL_ROUND, totalRound));
}
}

private void validateTimeLimit(int timeLimit) {
if (!ALLOWED_TIME_LIMIT.contains(timeLimit)) {
throw new BadRequestException("시간 제한은 %dms / %dms / %dms 만 가능합니다. requested timeLimit: %d"
.formatted(ALLOWED_TIME_LIMIT.get(0), ALLOWED_TIME_LIMIT.get(1), ALLOWED_TIME_LIMIT.get(2),
timeLimit));
}
}

public void updateTotalRound(int totalRound) {
validateTotalRound(totalRound);
this.totalRound = totalRound;
}

public void updateTimeLimit(int timeLimit) {
validateTimeLimit(timeLimit);
this.timeLimit = timeLimit;
}

public void updateCategory(Category category) {
this.category = category;
}

public boolean isFinalRound(int currentRound) {
return totalRound == currentRound;
}
}
6 changes: 2 additions & 4 deletions backend/src/main/java/ddangkong/service/room/RoomService.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public Room createRoom() {
return roomRepository.save(Room.createNewRoom());
}

@Transactional
@Transactional(readOnly = true)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

감사해용 ~

public Room getRoom(Long roomId) {
return roomRepository.findById(roomId)
.orElseThrow(() -> new BadRequestException("존재하지 않는 방입니다."));
Expand Down Expand Up @@ -48,9 +48,7 @@ public Room progressNextRound(Long roomId) {
@Transactional
public void updateRoomSetting(Long roomId, RoomSetting roomSetting) {
Room room = getRoom(roomId);
room.updateTimeLimit(roomSetting.getTimeLimit());
room.updateTotalRound(roomSetting.getTotalRound());
room.updateCategory(roomSetting.getCategory());
room.updateRoomSetting(roomSetting);
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import ddangkong.domain.balance.content.BalanceContent;
import ddangkong.domain.balance.content.Category;
import ddangkong.domain.room.Room;
import ddangkong.domain.room.RoomSetting;
import ddangkong.domain.room.RoomStatus;
import ddangkong.domain.room.balance.roomcontent.RoomContent;
import ddangkong.facade.room.dto.RoomInfoResponse;
Expand Down Expand Up @@ -78,7 +79,7 @@ class 밸런스_게임_방_정보_조회 {
assertAll(
() -> Assertions.assertThat(actual.members()).hasSize(5),
() -> Assertions.assertThat(actual.isGameStart()).isTrue(),
() -> Assertions.assertThat(actual.roomSetting().timeLimit()).isEqualTo(30000),
() -> Assertions.assertThat(actual.roomSetting().timeLimit()).isEqualTo(10_000),
() -> Assertions.assertThat(actual.roomSetting().totalRound()).isEqualTo(5)
);
}
Expand Down Expand Up @@ -227,8 +228,8 @@ class 방_초기화 {
@BeforeEach
void setUp() {
BalanceContent content = balanceContentRepository.save(new BalanceContent(Category.IF, "A vs B"));
room = roomRepository.save(new Room("roomResetSetUpUUID", 3, 3, 30,
RoomStatus.FINISH, Category.IF));
RoomSetting roomSetting = new RoomSetting(3, 10_000, Category.IF);
room = roomRepository.save(new Room("roomResetSetUpUUID", 3, RoomStatus.FINISH, roomSetting));
roomContentRepository.save(new RoomContent(room, content, 1, null));
roomContentRepository.save(new RoomContent(room, content, 2, null));
roomContentRepository.save(new RoomContent(room, content, 3, null));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class 현재_방의_내용_조회 {
Category.IF,
5,
2,
30_000, // TODO 추후 sec으로 변경
10_000, // TODO 추후 sec으로 변경
"민초 vs 반민초",
new BalanceOptionResponse(1L, "민초"),
new BalanceOptionResponse(2L, "반민초"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class 방_정보_조회 {
void 방_정보를_조회한다() throws Exception {
// given
int totalRound = 5;
int timeLimit = 30000;
int timeLimit = 10_000;
Category category = Category.IF;
RoomInfoResponse response = new RoomInfoResponse(
false,
Expand Down Expand Up @@ -134,7 +134,7 @@ class 방_설정_변경 {
void 방의_설정_정보를_변경한다() throws Exception {
// given
int totalRound = 5;
int timeLimit = 30_000;
int timeLimit = 10_000;
Category category = Category.IF;
RoomSettingRequest content = new RoomSettingRequest(totalRound, timeLimit, category);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class 방의_콘텐츠_조회 {
Category.IF,
5,
2,
30_000, // TODO sec 단위로 수정
10_000, // TODO sec 단위로 수정
"100억 빚 송강 vs 100억 부자 송강호",
firstOptionResponse,
secondOptionResponse
Expand Down
34 changes: 34 additions & 0 deletions backend/src/test/java/ddangkong/domain/room/RoomSettingTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package ddangkong.domain.room;

import static org.assertj.core.api.Assertions.assertThatThrownBy;

import ddangkong.domain.balance.content.Category;
import ddangkong.exception.BadRequestException;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

class RoomSettingTest {
@Nested
class 방_설정_변경 {
@ParameterizedTest
@ValueSource(ints = {2, 11})
void 라운드는_3이상_10이하_여야한다(int notValidTotalRound) {
// when & then
assertThatThrownBy(() -> new RoomSetting(notValidTotalRound, 5000, Category.IF))
.isExactlyInstanceOf(BadRequestException.class)
.hasMessage("총 라운드는 %d 이상, %d 이하만 가능합니다. requested totalRound: %d"
.formatted(3, 10, notValidTotalRound));
}

@ParameterizedTest
@ValueSource(ints = {5001, 10001, 15001})
void 시간_제한은_5000_10000_15000중_하나_여야한다(int notValidTimeLimit) {
// when & then
assertThatThrownBy(() -> new RoomSetting(5, notValidTimeLimit, Category.IF))
.isExactlyInstanceOf(BadRequestException.class)
.hasMessage("시간 제한은 %dms / %dms / %dms 만 가능합니다. requested timeLimit: %d"
.formatted(5000, 10000, 15000, notValidTimeLimit));
}
}
}
Loading