-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
281 additions
and
1 deletion.
There are no files selected for viewing
37 changes: 37 additions & 0 deletions
37
src/main/java/ai/softeer/caecae/findinggame/api/FindingGamePlayController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package ai.softeer.caecae.findinggame.api; | ||
|
||
import ai.softeer.caecae.findinggame.domain.dto.request.AnswerRequestDto; | ||
import ai.softeer.caecae.findinggame.domain.dto.request.RegistWinnerRequestDto; | ||
import ai.softeer.caecae.findinggame.domain.dto.response.AnswerResponseDto; | ||
import ai.softeer.caecae.findinggame.domain.dto.response.RegistWinnerResponseDto; | ||
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<SuccessResponse<AnswerResponseDto>> checkAnswer(@RequestBody AnswerRequestDto req) { | ||
return SuccessResponse.of(SuccessCode.OK, findingGamePlayService.checkAnswer(req)); | ||
} | ||
|
||
@PostMapping("/regist") | ||
public ResponseEntity<SuccessResponse<RegistWinnerResponseDto>> registWinner(@RequestBody RegistWinnerRequestDto req) { | ||
return SuccessResponse.of(SuccessCode.OK, findingGamePlayService.registWinner(req)); | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
src/main/java/ai/softeer/caecae/findinggame/domain/dto/request/AnswerRequestDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package ai.softeer.caecae.findinggame.domain.dto.request; | ||
|
||
import java.util.List; | ||
|
||
public record AnswerRequestDto( | ||
List<CoordDto> answerList | ||
) { | ||
} |
7 changes: 7 additions & 0 deletions
7
src/main/java/ai/softeer/caecae/findinggame/domain/dto/request/CoordDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package ai.softeer.caecae.findinggame.domain.dto.request; | ||
|
||
public record CoordDto( | ||
int coordX, | ||
int coordY | ||
) { | ||
} |
7 changes: 7 additions & 0 deletions
7
src/main/java/ai/softeer/caecae/findinggame/domain/dto/request/RegistWinnerRequestDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package ai.softeer.caecae.findinggame.domain.dto.request; | ||
|
||
public record RegistWinnerRequestDto( | ||
String ticketId, | ||
String phone | ||
) { | ||
} |
14 changes: 14 additions & 0 deletions
14
src/main/java/ai/softeer/caecae/findinggame/domain/dto/response/AnswerResponseDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<CoordDto> correctAnswerList, | ||
String ticketId, | ||
Long startTime | ||
) { | ||
} |
9 changes: 9 additions & 0 deletions
9
src/main/java/ai/softeer/caecae/findinggame/domain/dto/response/RegistWinnerResponseDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package ai.softeer.caecae.findinggame.domain.dto.response; | ||
|
||
import lombok.Builder; | ||
|
||
@Builder | ||
public record RegistWinnerResponseDto( | ||
boolean success | ||
) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 2 additions & 0 deletions
2
src/main/java/ai/softeer/caecae/findinggame/domain/entity/FindingGameWinnerId.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
src/main/java/ai/softeer/caecae/findinggame/repository/FindingGameRedisRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<String, Object> 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); | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
src/main/java/ai/softeer/caecae/findinggame/repository/FindingGameWinnerRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<FindingGameWinner, Integer> { | ||
} |
114 changes: 114 additions & 0 deletions
114
src/main/java/ai/softeer/caecae/findinggame/service/FindingGamePlayService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
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.RegistWinnerRequestDto; | ||
import ai.softeer.caecae.findinggame.domain.dto.response.AnswerResponseDto; | ||
import ai.softeer.caecae.findinggame.domain.dto.response.RegistWinnerResponseDto; | ||
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; | ||
|
||
/** | ||
* 사용자가 보낸 정답을 채점하고 모두 맞으면 선착순 인원에 들었는지 확인하는 서비스 로직 | ||
* | ||
* @param req | ||
* @return | ||
*/ | ||
public AnswerResponseDto checkAnswer(AnswerRequestDto req) { | ||
// 정답 판단 | ||
List<CoordDto> answerList = req.answerList(); // 사용자가 보낸 리스트 | ||
List<CoordDto> correctList = new ArrayList<>(); // 정답 리스트 | ||
correctList.add(new CoordDto(10, 10)); // 임시 정답 데이터 | ||
correctList.add(new CoordDto(30, 30)); // TODO: 정답 정보 가져와야함 | ||
List<CoordDto> 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 <= 900) { // TODO: 정답 범위 _ 수정 요망 | ||
correctAnswerList.add(correct); | ||
count++; | ||
correctList.remove(correct); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
// 정답 개수가 0이거나 1 || 남은 선착순 자리 체크 | ||
if (count != 2 || findingGameRedisRepository.increaseCount() > 315L) { // TODO: 오늘 선착순 인원 정보 가져와야함 | ||
if (count == 2) 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 RegistWinnerResponseDto registWinner(RegistWinnerRequestDto req) { | ||
String ticketId = req.ticketId(); | ||
Long startTime = findingGameRedisRepository.getWinnerStartTime(ticketId); | ||
if (startTime == null) return RegistWinnerResponseDto.builder().success(false).build(); // 목록에 없으면 | ||
log.info("사용자 시작시간: {}", startTime); | ||
Long endTime = System.currentTimeMillis() - 1000L; // 1초 지연 허용 | ||
if (endTime - startTime > 1000L * 60 * 3) { // 3분 초과 - 실패 및 당첨자 제외 | ||
findingGameRedisRepository.decreaseCount(); | ||
findingGameRedisRepository.deleteWinner(ticketId); | ||
return RegistWinnerResponseDto.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 RegistWinnerResponseDto.builder().success(true).build(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters