-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
[FEAT] 가까워지기 API 구현
- Loading branch information
Showing
12 changed files
with
469 additions
and
8 deletions.
There are no files selected for viewing
47 changes: 47 additions & 0 deletions
47
umbba-api/src/main/java/sopt/org/umbba/api/controller/closer/CloserController.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,47 @@ | ||
package sopt.org.umbba.api.controller.closer; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.web.bind.annotation.*; | ||
import sopt.org.umbba.api.config.jwt.JwtProvider; | ||
import sopt.org.umbba.api.controller.closer.dto.request.TodayCloserAnswerRequestDto; | ||
import sopt.org.umbba.api.controller.closer.dto.response.TodayCloserQnAResponseDto; | ||
import sopt.org.umbba.api.service.closer.CloserService; | ||
import sopt.org.umbba.common.exception.SuccessType; | ||
import sopt.org.umbba.common.exception.dto.ApiResponse; | ||
|
||
import javax.validation.Valid; | ||
import java.security.Principal; | ||
|
||
import static sopt.org.umbba.common.exception.SuccessType.ANSWER_TODAY_CLOSER_QUESTION_SUCCESS; | ||
import static sopt.org.umbba.common.exception.SuccessType.PASS_TO_NEXT_CLOSER_QUESTION_SUCCESS; | ||
|
||
@Slf4j | ||
@RestController | ||
@RequestMapping("/closer") | ||
@RequiredArgsConstructor | ||
public class CloserController { | ||
|
||
private final CloserService closerService; | ||
|
||
@GetMapping("/today") | ||
@ResponseStatus(HttpStatus.OK) | ||
public ApiResponse<TodayCloserQnAResponseDto> getTodayCloserQnA(Principal principal) { | ||
return ApiResponse.success(SuccessType.GET_TODAY_CLOSER_QNA_SUCCESS, closerService.getTodayCloserQnA(JwtProvider.getUserFromPrincial(principal))); | ||
} | ||
|
||
@PatchMapping("/answer") | ||
@ResponseStatus(HttpStatus.OK) | ||
public ApiResponse<?> answerTodayCloserQnA(Principal principal, @Valid @RequestBody final TodayCloserAnswerRequestDto request) { | ||
closerService.answerTodayCloserQnA(JwtProvider.getUserFromPrincial(principal), request); | ||
return ApiResponse.success(ANSWER_TODAY_CLOSER_QUESTION_SUCCESS); | ||
} | ||
|
||
@PatchMapping("/next") | ||
@ResponseStatus(HttpStatus.OK) | ||
public ApiResponse<?> passToNextCloserQnA(Principal principal) { | ||
closerService.passToNextCloserQnA(JwtProvider.getUserFromPrincial(principal)); | ||
return ApiResponse.success(PASS_TO_NEXT_CLOSER_QUESTION_SUCCESS); | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
...in/java/sopt/org/umbba/api/controller/closer/dto/request/TodayCloserAnswerRequestDto.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,26 @@ | ||
package sopt.org.umbba.api.controller.closer.dto.request; | ||
|
||
import com.fasterxml.jackson.databind.PropertyNamingStrategies; | ||
import com.fasterxml.jackson.databind.annotation.JsonNaming; | ||
import lombok.AccessLevel; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
import javax.validation.constraints.Max; | ||
import javax.validation.constraints.Min; | ||
|
||
@Getter | ||
@NoArgsConstructor(access = AccessLevel.PRIVATE) | ||
@AllArgsConstructor(access = AccessLevel.PRIVATE) | ||
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) | ||
public class TodayCloserAnswerRequestDto { | ||
|
||
@Min(value = 1, message = "답변은 1 혹은 2여야 합니다.") | ||
@Max(value = 2, message = "답변은 1 혹은 2여야 합니다.") | ||
int answer; | ||
|
||
public static TodayCloserAnswerRequestDto of (int answer) { | ||
return new TodayCloserAnswerRequestDto(answer); | ||
} | ||
} |
70 changes: 70 additions & 0 deletions
70
...ain/java/sopt/org/umbba/api/controller/closer/dto/response/TodayCloserQnAResponseDto.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,70 @@ | ||
package sopt.org.umbba.api.controller.closer.dto.response; | ||
|
||
import com.fasterxml.jackson.databind.PropertyNamingStrategies; | ||
import com.fasterxml.jackson.databind.annotation.JsonNaming; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import sopt.org.umbba.domain.domain.closer.CloserQnA; | ||
import sopt.org.umbba.domain.domain.closer.CloserQuestion; | ||
|
||
@Getter | ||
@Builder | ||
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) | ||
public class TodayCloserQnAResponseDto { | ||
|
||
private Long closerQnaId; | ||
|
||
private int responseCase; | ||
|
||
private String balanceQuestion; | ||
private String choiceAnswer1; | ||
private String choiceAnswer2; | ||
|
||
private String myChoice; | ||
private String opponentChoice; | ||
|
||
public static TodayCloserQnAResponseDto of(CloserQnA closerQna, int responseCase, boolean isMeChild) { | ||
|
||
CloserQuestion closerQuestion = closerQna.getCloserQuestion(); | ||
int myAnswer; | ||
int opponentAnswer; | ||
if (isMeChild) { | ||
myAnswer = closerQna.getChildAnswer(); | ||
opponentAnswer = closerQna.getParentAnswer(); | ||
} else { | ||
myAnswer = closerQna.getParentAnswer(); | ||
opponentAnswer = closerQna.getChildAnswer(); | ||
} | ||
|
||
String myChoice; | ||
if (myAnswer == 0) { | ||
myChoice = null; | ||
} else if (myAnswer == 1) { | ||
myChoice = closerQuestion.getChoiceAnswer1(); | ||
} else { | ||
myChoice = closerQuestion.getChoiceAnswer2(); | ||
} | ||
String opponentChoice; | ||
if (opponentAnswer == 0) { | ||
opponentChoice = null; | ||
} else if (opponentAnswer == 1) { | ||
opponentChoice = closerQuestion.getChoiceAnswer1(); | ||
} else { | ||
opponentChoice = closerQuestion.getChoiceAnswer2(); | ||
} | ||
|
||
if (responseCase == 3 && (myAnswer != opponentAnswer)) { | ||
responseCase = 4; | ||
} | ||
|
||
return TodayCloserQnAResponseDto.builder() | ||
.closerQnaId(closerQna.getId()) | ||
.responseCase(responseCase) | ||
.balanceQuestion(closerQuestion.getBalanceQuestion()) | ||
.choiceAnswer1(closerQuestion.getChoiceAnswer1()) | ||
.choiceAnswer2(closerQuestion.getChoiceAnswer2()) | ||
.myChoice(myChoice) | ||
.opponentChoice(opponentChoice) | ||
.build(); | ||
} | ||
} |
143 changes: 143 additions & 0 deletions
143
umbba-api/src/main/java/sopt/org/umbba/api/service/closer/CloserService.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,143 @@ | ||
package sopt.org.umbba.api.service.closer; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import sopt.org.umbba.api.controller.closer.dto.request.TodayCloserAnswerRequestDto; | ||
import sopt.org.umbba.api.controller.closer.dto.response.TodayCloserQnAResponseDto; | ||
import sopt.org.umbba.common.exception.ErrorType; | ||
import sopt.org.umbba.common.exception.model.CustomException; | ||
import sopt.org.umbba.domain.domain.closer.CloserQnA; | ||
import sopt.org.umbba.domain.domain.closer.CloserQuestion; | ||
import sopt.org.umbba.domain.domain.closer.repository.CloserQnARepository; | ||
import sopt.org.umbba.domain.domain.closer.repository.CloserQuestionRepository; | ||
import sopt.org.umbba.domain.domain.parentchild.Parentchild; | ||
import sopt.org.umbba.domain.domain.user.User; | ||
import sopt.org.umbba.domain.domain.user.repository.UserRepository; | ||
|
||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
@Slf4j | ||
@Service | ||
@RequiredArgsConstructor | ||
@Transactional(readOnly = true) | ||
public class CloserService { | ||
|
||
private final UserRepository userRepository; | ||
private final CloserQuestionRepository closerQuestionRepository; | ||
private final CloserQnARepository closerQnARepository; | ||
|
||
public TodayCloserQnAResponseDto getTodayCloserQnA(Long userId) { | ||
User user = getUserById(userId); | ||
Parentchild parentchild = user.getParentChild(); | ||
if (parentchild == null) { | ||
throw new CustomException(ErrorType.USER_HAVE_NO_PARENTCHILD); | ||
} | ||
|
||
if (user.isMeChild()) { | ||
int closerCount = parentchild.getCloserChildCount(); | ||
CloserQnA todayQnA = parentchild.getCloserQnaList().get(closerCount); | ||
|
||
if (!todayQnA.isChildAnswer()) { // Case 1 (내가 답변하지 않은 경우) | ||
return TodayCloserQnAResponseDto.of(todayQnA, 1, true); | ||
} else if (!todayQnA.isParentAnswer()) { // Case 2 (상대가 답변하지 않은 경우) | ||
return TodayCloserQnAResponseDto.of(todayQnA, 2, true); | ||
} else { // Case 3,4 (둘다 답변한 경우) | ||
return TodayCloserQnAResponseDto.of(todayQnA, 3, true); | ||
} | ||
|
||
} else { | ||
int closerCount = parentchild.getCloserParentCount(); | ||
CloserQnA todayQnA = parentchild.getCloserQnaList().get(closerCount); | ||
|
||
if (!todayQnA.isParentAnswer()) { // Case 1 (내가 답변하지 않은 경우) | ||
return TodayCloserQnAResponseDto.of(todayQnA, 1, false); | ||
} else if (!todayQnA.isChildAnswer()) { // Case 2 (상대가 답변하지 않은 경우) | ||
return TodayCloserQnAResponseDto.of(todayQnA, 2, false); | ||
} else { // Case 3,4 (둘다 답변한 경우) | ||
return TodayCloserQnAResponseDto.of(todayQnA, 3, false); | ||
} | ||
} | ||
} | ||
|
||
@Transactional | ||
public void answerTodayCloserQnA(Long userId, TodayCloserAnswerRequestDto request) { | ||
User user = getUserById(userId); | ||
Parentchild parentchild = user.getParentChild(); | ||
if (parentchild == null) { | ||
throw new CustomException(ErrorType.USER_HAVE_NO_PARENTCHILD); | ||
} | ||
|
||
if (user.isMeChild()) { | ||
int closerCount = parentchild.getCloserChildCount(); | ||
CloserQnA todayQnA = parentchild.getCloserQnaList().get(closerCount); | ||
|
||
todayQnA.saveChildAnswer(request.getAnswer()); | ||
} else { | ||
int closerCount = parentchild.getCloserParentCount(); | ||
CloserQnA todayQnA = parentchild.getCloserQnaList().get(closerCount); | ||
|
||
todayQnA.saveParentAnswer(request.getAnswer()); | ||
} | ||
} | ||
|
||
@Transactional | ||
public void passToNextCloserQnA(Long userId) { | ||
User user = getUserById(userId); | ||
Parentchild parentchild = user.getParentChild(); | ||
if (parentchild == null) { | ||
throw new CustomException(ErrorType.USER_HAVE_NO_PARENTCHILD); | ||
} | ||
|
||
if (user.isMeChild()) { | ||
if (parentchild.getCloserChildCount() < parentchild.getCloserParentCount()) { | ||
parentchild.addCloserChildCount(); | ||
} else if (parentchild.getCloserChildCount() == parentchild.getCloserParentCount()) { | ||
parentchild.addCloserChildCount(); | ||
CloserQuestion newCloserQuestion = closerQuestionRepository.findRandomExceptIds(getCloserQuestionIds(parentchild)) | ||
.orElseThrow(() -> new CustomException(ErrorType.NOT_FOUND_CLOSER_QUESTION)); | ||
CloserQnA newCloserQnA = CloserQnA.builder() | ||
.closerQuestion(newCloserQuestion) | ||
.isParentAnswer(false) | ||
.isChildAnswer(false) | ||
.build(); | ||
closerQnARepository.save(newCloserQnA); | ||
parentchild.addCloserQna(newCloserQnA); | ||
} else { | ||
throw new CustomException(ErrorType.INVALID_COUNT_STATUS); | ||
} | ||
} else { | ||
if (parentchild.getCloserParentCount() < parentchild.getCloserChildCount()) { | ||
parentchild.addCloserParentCount(); | ||
} else if (parentchild.getCloserParentCount() == parentchild.getCloserChildCount()) { | ||
parentchild.addCloserParentCount(); | ||
CloserQuestion newCloserQuestion = closerQuestionRepository.findRandomExceptIds(getCloserQuestionIds(parentchild)) | ||
.orElseThrow(() -> new CustomException(ErrorType.NOT_FOUND_CLOSER_QUESTION)); | ||
CloserQnA newCloserQnA = CloserQnA.builder() | ||
.closerQuestion(newCloserQuestion) | ||
.isParentAnswer(false) | ||
.isChildAnswer(false) | ||
.build(); | ||
closerQnARepository.save(newCloserQnA); | ||
parentchild.addCloserQna(newCloserQnA); | ||
} else { | ||
throw new CustomException(ErrorType.INVALID_COUNT_STATUS); | ||
} | ||
} | ||
} | ||
|
||
private static List<Long> getCloserQuestionIds(Parentchild parentchild) { | ||
return parentchild.getCloserQnaList().stream() | ||
.map(closerQnA -> closerQnA.getCloserQuestion().getId()) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
private User getUserById(Long userId) { | ||
|
||
return userRepository.findById(userId).orElseThrow( | ||
() -> new CustomException(ErrorType.INVALID_USER) | ||
); | ||
} | ||
} |
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
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
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
Oops, something went wrong.