diff --git a/src/main/java/ai/softeer/caecae/findinggame/api/FindingGamePlayController.java b/src/main/java/ai/softeer/caecae/findinggame/api/FindingGamePlayController.java new file mode 100644 index 0000000..4674ee8 --- /dev/null +++ b/src/main/java/ai/softeer/caecae/findinggame/api/FindingGamePlayController.java @@ -0,0 +1,44 @@ +package ai.softeer.caecae.findinggame.api; + +import ai.softeer.caecae.findinggame.domain.dto.request.AnswerRequestDto; +import ai.softeer.caecae.findinggame.domain.dto.request.RegisterWinnerRequestDto; +import ai.softeer.caecae.findinggame.domain.dto.response.AnswerResponseDto; +import ai.softeer.caecae.findinggame.domain.dto.response.RegisterWinnerResponseDto; +import ai.softeer.caecae.findinggame.service.FindingGamePlayService; +import ai.softeer.caecae.global.dto.response.SuccessResponse; +import ai.softeer.caecae.global.enums.SuccessCode; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/finding") +public class FindingGamePlayController { + private final FindingGamePlayService findingGamePlayService; + + /** + * 참여자가 게임의 정답을 보냄 + * + * @param req + * @return + */ + @PostMapping("/answer") + public ResponseEntity> checkAnswer(@RequestBody AnswerRequestDto req) { + return SuccessResponse.of(SuccessCode.OK, findingGamePlayService.checkAnswer(req)); + } + + /** + * 선착순에 든 참여자가 전화번호를 입력 + * + * @param req + * @return + */ + @PostMapping("/register") + public ResponseEntity> registWinner(@RequestBody RegisterWinnerRequestDto req) { + return SuccessResponse.of(SuccessCode.OK, findingGamePlayService.registWinner(req)); + } +} diff --git a/src/main/java/ai/softeer/caecae/findinggame/domain/dto/request/AnswerRequestDto.java b/src/main/java/ai/softeer/caecae/findinggame/domain/dto/request/AnswerRequestDto.java new file mode 100644 index 0000000..6b2d4e5 --- /dev/null +++ b/src/main/java/ai/softeer/caecae/findinggame/domain/dto/request/AnswerRequestDto.java @@ -0,0 +1,8 @@ +package ai.softeer.caecae.findinggame.domain.dto.request; + +import java.util.List; + +public record AnswerRequestDto( + List answerList +) { +} diff --git a/src/main/java/ai/softeer/caecae/findinggame/domain/dto/request/CoordDto.java b/src/main/java/ai/softeer/caecae/findinggame/domain/dto/request/CoordDto.java new file mode 100644 index 0000000..a59008e --- /dev/null +++ b/src/main/java/ai/softeer/caecae/findinggame/domain/dto/request/CoordDto.java @@ -0,0 +1,7 @@ +package ai.softeer.caecae.findinggame.domain.dto.request; + +public record CoordDto( + int coordX, + int coordY +) { +} diff --git a/src/main/java/ai/softeer/caecae/findinggame/domain/dto/request/RegisterWinnerRequestDto.java b/src/main/java/ai/softeer/caecae/findinggame/domain/dto/request/RegisterWinnerRequestDto.java new file mode 100644 index 0000000..da205e8 --- /dev/null +++ b/src/main/java/ai/softeer/caecae/findinggame/domain/dto/request/RegisterWinnerRequestDto.java @@ -0,0 +1,7 @@ +package ai.softeer.caecae.findinggame.domain.dto.request; + +public record RegisterWinnerRequestDto( + String ticketId, + String phone +) { +} diff --git a/src/main/java/ai/softeer/caecae/findinggame/domain/dto/response/AnswerResponseDto.java b/src/main/java/ai/softeer/caecae/findinggame/domain/dto/response/AnswerResponseDto.java new file mode 100644 index 0000000..c817a6b --- /dev/null +++ b/src/main/java/ai/softeer/caecae/findinggame/domain/dto/response/AnswerResponseDto.java @@ -0,0 +1,14 @@ +package ai.softeer.caecae.findinggame.domain.dto.response; + +import ai.softeer.caecae.findinggame.domain.dto.request.CoordDto; +import lombok.Builder; + +import java.util.List; + +@Builder +public record AnswerResponseDto( + List correctAnswerList, + String ticketId, + Long startTime +) { +} diff --git a/src/main/java/ai/softeer/caecae/findinggame/domain/dto/response/RegisterWinnerResponseDto.java b/src/main/java/ai/softeer/caecae/findinggame/domain/dto/response/RegisterWinnerResponseDto.java new file mode 100644 index 0000000..685124d --- /dev/null +++ b/src/main/java/ai/softeer/caecae/findinggame/domain/dto/response/RegisterWinnerResponseDto.java @@ -0,0 +1,9 @@ +package ai.softeer.caecae.findinggame.domain.dto.response; + +import lombok.Builder; + +@Builder +public record RegisterWinnerResponseDto( + boolean success +) { +} diff --git a/src/main/java/ai/softeer/caecae/findinggame/domain/entity/FindingGameWinner.java b/src/main/java/ai/softeer/caecae/findinggame/domain/entity/FindingGameWinner.java index 959d15c..e587316 100644 --- a/src/main/java/ai/softeer/caecae/findinggame/domain/entity/FindingGameWinner.java +++ b/src/main/java/ai/softeer/caecae/findinggame/domain/entity/FindingGameWinner.java @@ -3,8 +3,15 @@ import ai.softeer.caecae.global.entity.BaseEntity; import ai.softeer.caecae.user.domain.entity.User; import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.NoArgsConstructor; @Entity +@Builder +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) @IdClass(FindingGameWinnerId.class) public class FindingGameWinner extends BaseEntity { @Id diff --git a/src/main/java/ai/softeer/caecae/findinggame/domain/entity/FindingGameWinnerId.java b/src/main/java/ai/softeer/caecae/findinggame/domain/entity/FindingGameWinnerId.java index 94fbdf8..9cbd162 100644 --- a/src/main/java/ai/softeer/caecae/findinggame/domain/entity/FindingGameWinnerId.java +++ b/src/main/java/ai/softeer/caecae/findinggame/domain/entity/FindingGameWinnerId.java @@ -1,9 +1,11 @@ package ai.softeer.caecae.findinggame.domain.entity; import ai.softeer.caecae.user.domain.entity.User; +import lombok.NoArgsConstructor; import java.io.Serializable; +@NoArgsConstructor public class FindingGameWinnerId implements Serializable { private User user; private FindingGame findingGame; diff --git a/src/main/java/ai/softeer/caecae/findinggame/repository/FindingGameRedisRepository.java b/src/main/java/ai/softeer/caecae/findinggame/repository/FindingGameRedisRepository.java new file mode 100644 index 0000000..49418be --- /dev/null +++ b/src/main/java/ai/softeer/caecae/findinggame/repository/FindingGameRedisRepository.java @@ -0,0 +1,66 @@ +package ai.softeer.caecae.findinggame.repository; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Repository; + +@Slf4j +@Repository +@RequiredArgsConstructor +public class FindingGameRedisRepository { + private final static String TICKET_KEY = "ticket"; + private final static String COUNT_KEY = "count"; + private final static String WINNER_KEY = "winner"; + private final RedisTemplate redisTemplate; + + /** + * 당첨자 수 증가 + * + * @return 현재 당첨자 수 값 + */ + public Long increaseCount() { + return redisTemplate.opsForValue().increment(COUNT_KEY); + } + + /** + * 당첨자 수 감소 + * + * @return 현재 당첨자 수 값 + */ + public Long decreaseCount() { + return redisTemplate.opsForValue().decrement(COUNT_KEY); + } + + + /** + * 선착순에 들은 참여자를 위너 목록에 추가한다. + * + * @param ticketId + * @return 시작 시간 + */ + public Long addWinner(String ticketId) { + Long startTime = System.currentTimeMillis(); + redisTemplate.opsForHash().put(WINNER_KEY, ticketId, startTime); + return startTime; + } + + /** + * 위너 목록에서 참여자를 삭제한다. + * + * @param ticketId + */ + public void deleteWinner(String ticketId) { + redisTemplate.opsForHash().delete(WINNER_KEY, ticketId); + } + + /** + * TicketID를 가진 참여자의 입력 시작 시간을 가져온다. + * + * @param ticketId + * @return + */ + public Long getWinnerStartTime(String ticketId) { + return (Long) redisTemplate.opsForHash().get(WINNER_KEY, ticketId); + } +} diff --git a/src/main/java/ai/softeer/caecae/findinggame/repository/FindingGameWinnerRepository.java b/src/main/java/ai/softeer/caecae/findinggame/repository/FindingGameWinnerRepository.java new file mode 100644 index 0000000..4d23181 --- /dev/null +++ b/src/main/java/ai/softeer/caecae/findinggame/repository/FindingGameWinnerRepository.java @@ -0,0 +1,9 @@ +package ai.softeer.caecae.findinggame.repository; + +import ai.softeer.caecae.findinggame.domain.entity.FindingGameWinner; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface FindingGameWinnerRepository extends JpaRepository { +} diff --git a/src/main/java/ai/softeer/caecae/findinggame/service/FindingGamePlayService.java b/src/main/java/ai/softeer/caecae/findinggame/service/FindingGamePlayService.java new file mode 100644 index 0000000..d96a039 --- /dev/null +++ b/src/main/java/ai/softeer/caecae/findinggame/service/FindingGamePlayService.java @@ -0,0 +1,122 @@ +package ai.softeer.caecae.findinggame.service; + +import ai.softeer.caecae.findinggame.domain.dto.request.AnswerRequestDto; +import ai.softeer.caecae.findinggame.domain.dto.request.CoordDto; +import ai.softeer.caecae.findinggame.domain.dto.request.RegisterWinnerRequestDto; +import ai.softeer.caecae.findinggame.domain.dto.response.AnswerResponseDto; +import ai.softeer.caecae.findinggame.domain.dto.response.RegisterWinnerResponseDto; +import ai.softeer.caecae.findinggame.domain.entity.FindingGameWinner; +import ai.softeer.caecae.findinggame.repository.FindingGameDbRepository; +import ai.softeer.caecae.findinggame.repository.FindingGameRedisRepository; +import ai.softeer.caecae.findinggame.repository.FindingGameWinnerRepository; +import ai.softeer.caecae.user.domain.entity.User; +import ai.softeer.caecae.user.repository.UserRepository; +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@Slf4j +@Service +@RequiredArgsConstructor +public class FindingGamePlayService { + private final FindingGameRedisRepository findingGameRedisRepository; + private final FindingGameDbRepository findingGameDbRepository; + private final FindingGameWinnerRepository findingGameWinnerRepository; + private final UserRepository userRepository; + + private final int MAX_ANSWER_COUNT = 2; + private final int ANSWER_RANGE = 900; + private final long CONSTRAINT_TIME = 1000L * 60 * 3; + + /** + * 사용자가 보낸 정답을 채점하고 모두 맞으면 선착순 인원에 들었는지 확인하는 서비스 로직 + * + * @param req + * @return + */ + public AnswerResponseDto checkAnswer(AnswerRequestDto req) { + // 정답 판단 + List answerList = req.answerList(); // 사용자가 보낸 리스트 + List correctList = new ArrayList<>(); // 정답 리스트 + correctList.add(new CoordDto(10, 10)); // 임시 정답 데이터 + correctList.add(new CoordDto(30, 30)); // TODO: 정답 정보 가져와야함 + List correctAnswerList = new ArrayList<>(); // 사용자에게 보낼 채점한 리스트 + int count = 0; + for (CoordDto answer : answerList) { + int x = answer.coordX(), y = answer.coordY(); + log.info("X: {}, Y: {}", x, y); + for (CoordDto correct : correctList) { + int cx = correct.coordX(), cy = correct.coordY(); + int diff = (x - cx) * (x - cx) + (y - cy) * (y - cy); // 점과 점 사이의 거리 제곱 공식 + if (diff <= ANSWER_RANGE) { // TODO: 정답 범위 _ 수정 요망 + correctAnswerList.add(correct); + count++; + correctList.remove(correct); + break; + } + } + } + + // 정답 개수가 0이거나 1 || 남은 선착순 자리 체크 + if (count != MAX_ANSWER_COUNT || findingGameRedisRepository.increaseCount() > 315L) { // TODO: 오늘 선착순 인원 정보 가져와야함 + if (count == MAX_ANSWER_COUNT) findingGameRedisRepository.decreaseCount(); + return AnswerResponseDto.builder() + .correctAnswerList(correctAnswerList) + .ticketId("") + .startTime(-1L) + .build(); + } + + // TicketId 생성 + String ticketId = UUID.randomUUID().toString(); + Long startTime = findingGameRedisRepository.addWinner(ticketId); + return AnswerResponseDto.builder() + .correctAnswerList(correctAnswerList) + .ticketId(ticketId) + .startTime(startTime) + .build(); + } + + /** + * 선착순에 든 사용자가 전화번호를 입력했을 때 처리하는 서비스 로직 + * + * @param req + * @return 정답 리스트와 선착순 참가자 등록 정보 + */ + @Transactional + public RegisterWinnerResponseDto registWinner(RegisterWinnerRequestDto req) { + String ticketId = req.ticketId(); + Long startTime = findingGameRedisRepository.getWinnerStartTime(ticketId); + if (startTime == null) return RegisterWinnerResponseDto.builder().success(false).build(); // 목록에 없으면 + log.info("사용자 시작시간: {}", startTime); + Long endTime = System.currentTimeMillis() - 1000L; // 1초 지연 허용 + if (endTime - startTime > CONSTRAINT_TIME) { // 3분 초과 - 실패 및 당첨자 제외 + findingGameRedisRepository.decreaseCount(); + findingGameRedisRepository.deleteWinner(ticketId); + return RegisterWinnerResponseDto.builder() + .success(false) + .build(); + } + Integer gameId = 1; + String phone = req.phone(); + findingGameDbRepository.findById(gameId); + FindingGameWinner winner = FindingGameWinner.builder() + .user(userRepository.findByPhone(phone).orElseGet(() -> userRepository.save( + User.builder() + .phone(phone) + .build() + ))) + .findingGame(findingGameDbRepository.findById(gameId).get()) + .build(); + findingGameWinnerRepository.save(winner); + findingGameRedisRepository.deleteWinner(ticketId); + return RegisterWinnerResponseDto.builder() + .success(true) + .build(); + } +} diff --git a/src/main/java/ai/softeer/caecae/findinggame/service/FindingGameService.java b/src/main/java/ai/softeer/caecae/findinggame/service/FindingGameService.java index 9bad899..f0f0650 100644 --- a/src/main/java/ai/softeer/caecae/findinggame/service/FindingGameService.java +++ b/src/main/java/ai/softeer/caecae/findinggame/service/FindingGameService.java @@ -1,17 +1,14 @@ package ai.softeer.caecae.findinggame.service; import ai.softeer.caecae.findinggame.domain.dto.FindingGameDailyInfo; +import ai.softeer.caecae.findinggame.domain.dto.response.FindingGameInfoResponseDto; import ai.softeer.caecae.findinggame.domain.entity.FindingGame; -import ai.softeer.caecae.findinggame.domain.enums.AnswerType; import ai.softeer.caecae.findinggame.repository.FindGameDbRepository; -import ai.softeer.caecae.racinggame.domain.dto.request.RegisterFindingGamePeriodRequestDto; -import ai.softeer.caecae.findinggame.domain.dto.response.FindingGameInfoResponseDto; -import ai.softeer.caecae.racinggame.domain.dto.response.RegisterFindingGamePeriodResponseDto; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.time.LocalDate; +import java.time.Clock; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -20,54 +17,8 @@ @RequiredArgsConstructor public class FindingGameService { private final FindGameDbRepository findGameDbRepository; - - /** - * 어드민이 숨은캐스퍼찾기 게임 기간을 등록하는 로직 - * - * @param req 게임 시작 날짜 - * @return 게임 시작 날짜, 종료 날짜(+6일) - */ - @Transactional - public RegisterFindingGamePeriodResponseDto registerFindingGamePeriod(RegisterFindingGamePeriodRequestDto req) { - List findingGames = findGameDbRepository.findAll(); - // 등록된 게임 정보가 없으면 생성하기 - if (findingGames.isEmpty()) { - findingGames = initFindingGames(); - } - - // 게임 정보 기간 업데이트 - LocalDate date = req.startDate(); - for (FindingGame findingGame : findingGames) { - findingGame.updateFindingGamePeriod( - date.atTime(15, 15), - date.plusDays(1).atTime(14, 15) - ); - date = date.plusDays(1); - } - - - findGameDbRepository.saveAll(findingGames); - - return RegisterFindingGamePeriodResponseDto.builder() - .startDate(req.startDate()) - .endDate(req.startDate().plusDays(6)) - .build(); - } - - // 7개의 숨은캐스퍼찾기 게임 정보 객체 초기화 - private List initFindingGames() { - List findingGames = new ArrayList<>(); - for (int day = 0; day < 7; day++) { - findingGames.add( - FindingGame.builder() - .questionImageUrl("no-image") - .numberOfWinners(315) - .answerType(AnswerType.UNSELECTED) - .build()); - } - return findingGames; - } - + private final Clock clock; // 테스트코드 의존성 주입을 위한 빈 + /** * 전체 게임 정보와, 최근/다음 게임의 인덱스를 반환하는 로직 * @@ -76,12 +27,11 @@ private List initFindingGames() { @Transactional(readOnly = true) public FindingGameInfoResponseDto getFindingGameInfo() { List findingGames = findGameDbRepository.findAllByOrderByStartTime(); - int recentGameIndex = -1; int nextGameIndex = -1; for (int i = 0; i < findingGames.size(); i++) { FindingGame findingGame = findingGames.get(i); - if (findingGame.getStartTime().isBefore(LocalDateTime.now())) { + if (findingGame.getStartTime().isBefore(LocalDateTime.now(clock))) { recentGameIndex = i; } } @@ -108,4 +58,12 @@ public FindingGameInfoResponseDto getFindingGameInfo() { .nextGameIndex(nextGameIndex) .build(); } + + // 테스트용 + public LocalDateTime testUtcClockInstant() { + findGameDbRepository.findAllByOrderByStartTime(); + return LocalDateTime.now(clock); + } + } + diff --git a/src/main/java/ai/softeer/caecae/global/config/TimeConfig.java b/src/main/java/ai/softeer/caecae/global/config/TimeConfig.java new file mode 100644 index 0000000..5ffbb50 --- /dev/null +++ b/src/main/java/ai/softeer/caecae/global/config/TimeConfig.java @@ -0,0 +1,22 @@ +package ai.softeer.caecae.global.config; + +import jakarta.annotation.PostConstruct; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.time.Clock; +import java.util.TimeZone; + +@Configuration +public class TimeConfig { + + @Bean + public Clock clock() { + return Clock.systemDefaultZone(); + } + + @PostConstruct + void started() { + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Seoul")); + } +} \ No newline at end of file diff --git a/src/main/java/ai/softeer/caecae/user/domain/entity/User.java b/src/main/java/ai/softeer/caecae/user/domain/entity/User.java index 77164f1..1c3c459 100644 --- a/src/main/java/ai/softeer/caecae/user/domain/entity/User.java +++ b/src/main/java/ai/softeer/caecae/user/domain/entity/User.java @@ -9,7 +9,7 @@ @Getter @Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor public class User extends BaseEntity { @Id diff --git a/src/test/java/ai/softeer/caecae/findinggame/service/FindingGameServiceTest.java b/src/test/java/ai/softeer/caecae/findinggame/service/FindingGameServiceTest.java new file mode 100644 index 0000000..c4e6dc6 --- /dev/null +++ b/src/test/java/ai/softeer/caecae/findinggame/service/FindingGameServiceTest.java @@ -0,0 +1,162 @@ +package ai.softeer.caecae.findinggame.service; + +import ai.softeer.caecae.findinggame.domain.dto.response.FindingGameInfoResponseDto; +import ai.softeer.caecae.findinggame.domain.entity.FindingGame; +import ai.softeer.caecae.findinggame.domain.enums.AnswerType; +import ai.softeer.caecae.findinggame.repository.FindGameDbRepository; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.time.Clock; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.List; +import java.util.TimeZone; + +import static org.mockito.BDDMockito.given; + +@ExtendWith(MockitoExtension.class) +class FindingGameServiceTest { + + @InjectMocks + private FindingGameService findingGameService; + + @Mock + private FindGameDbRepository findGameDbRepository; + + @Mock + private Clock clock; + + // 7일치의 숨은그림찾기 게임 정보 + private final List findingGames = new ArrayList<>(); + private static LocalDateTime integrityDateTime; + + + @BeforeAll + static void timeSetUp() { + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Seoul")); + integrityDateTime = LocalDateTime.of(2024, 5, 5, 10, 10); + } + + @BeforeEach + void setUp() { + // 8/1 ~ 8/7 게임 + LocalDateTime baseTime = LocalDateTime.of(2024, 8, 1, 15, 15); + for (int day = 0; day < 7; day++) { + findingGames.add( + FindingGame.builder() + .id(day + 1) + .questionImageUrl("url") + .startTime(baseTime.plusDays(day)) + .endTime(baseTime.plusDays(day + 1).minusHours(1)) + .numberOfWinners(315) + .answerType(AnswerType.PIXEL) + .build() + ); + } + + Mockito.when(findGameDbRepository.findAllByOrderByStartTime()).thenReturn(findingGames); + + given(clock.getZone()).willReturn(ZoneId.systemDefault()); + } + + @Test + @DisplayName("LocalDateTime과 비교하여, Clock.instant의 시간에 TimeZone의 시차가 적용되는지 테스트 하기 - 같은 시간") + void testUtcClockInstant1() { + // Given + given(clock.instant()).willReturn(Instant.parse("2024-05-05T10:10:00Z")); + + // When + // Clock을 사용하여 LocalDateTime 생성 + LocalDateTime time = findingGameService.testUtcClockInstant(); + + // Then + Assertions.assertThat(time).isNotEqualTo(integrityDateTime); + } + + @Test + @DisplayName("LocalDateTime과 Clock.instant의 시간에 UTC+9의 시차가 적용되는지 테스트 하기 - UTC+9") + void testUtcClockInstant2() { + // Given + given(clock.instant()).willReturn(Instant.parse("2024-05-05T10:10:00Z").minusSeconds(9 * 3600)); + + // When + // Clock을 사용하여 LocalDateTime 생성 + LocalDateTime time = findingGameService.testUtcClockInstant(); + + // Then + Assertions.assertThat(time).isEqualTo(integrityDateTime); + } + + + @Test + @DisplayName("Given_일주일치 게임 정보 입력 When_게임 시작 전 Then_최근게임 인덱스가 -1") + void getFindingGameInfo_1() { + // Given + // LocalDateTime.now()에서 사용할 clock 객체 모킹 + given(clock.instant()).willReturn(Instant.parse("2024-08-01T09:00:00Z").minusSeconds(9 * 3600)); + + // When + FindingGameInfoResponseDto findingGameInfo = findingGameService.getFindingGameInfo(); + + // Then + Assertions.assertThat(findingGameInfo).isNotNull(); + Assertions.assertThat(findingGameInfo.recentGameIndex()).isEqualTo(-1); + Assertions.assertThat(findingGameInfo.nextGameIndex()).isEqualTo(0); + } + + @Test + @DisplayName("Given_일주일치 게임 정보 입력 When_게임 진행 중(첫날) Then_최근게임 인덱스가 0") + void getFindingGameInfo_2() { + // Given + // LocalDateTime.now()에서 사용할 clock 객체 모킹 + given(clock.instant()).willReturn(Instant.parse("2024-08-01T17:00:00Z").minusSeconds(9 * 3600)); + + // When + FindingGameInfoResponseDto findingGameInfo = findingGameService.getFindingGameInfo(); + + // Then + Assertions.assertThat(findingGameInfo).isNotNull(); + Assertions.assertThat(findingGameInfo.recentGameIndex()).isEqualTo(0); + Assertions.assertThat(findingGameInfo.nextGameIndex()).isEqualTo(1); + } + + @Test + @DisplayName("Given_일주일치 게임 정보 입력 When_게임 진행 중(마지막날) Then_최근게임 인덱스가 6") + void getFindingGameInfo_3() { + // Given + // LocalDateTime.now()에서 사용할 clock 객체 모킹 + given(clock.instant()).willReturn(Instant.parse("2024-08-08T10:00:00Z").minusSeconds(9 * 3600)); + + // When + FindingGameInfoResponseDto findingGameInfo = findingGameService.getFindingGameInfo(); + + // Then + Assertions.assertThat(findingGameInfo).isNotNull(); + Assertions.assertThat(findingGameInfo.recentGameIndex()).isEqualTo(6); + Assertions.assertThat(findingGameInfo.nextGameIndex()).isEqualTo(-1); + } + + @Test + @DisplayName("Given_일주일치 게임 정보 입력 When_게임 진행 종료 Then_다음게임 인덱스가 -1") + void getFindingGameInfo_4() { + // Given + // LocalDateTime.now()에서 사용할 clock 객체 모킹 + given(clock.instant()).willReturn(Instant.parse("2032-08-08T16:00:00Z").minusSeconds(9 * 3600)); + + // When + FindingGameInfoResponseDto findingGameInfo = findingGameService.getFindingGameInfo(); + + // Then + Assertions.assertThat(findingGameInfo).isNotNull(); + Assertions.assertThat(findingGameInfo.recentGameIndex()).isEqualTo(6); + Assertions.assertThat(findingGameInfo.nextGameIndex()).isEqualTo(-1); + } +} \ No newline at end of file