diff --git a/src/main/java/com/chwipoClova/common/exception/ExceptionCode.java b/src/main/java/com/chwipoClova/common/exception/ExceptionCode.java index 8a63727..d734734 100644 --- a/src/main/java/com/chwipoClova/common/exception/ExceptionCode.java +++ b/src/main/java/com/chwipoClova/common/exception/ExceptionCode.java @@ -67,7 +67,9 @@ public enum ExceptionCode { API_TOKEN_COUNT_FAIL("985", "토큰 계산기 호출 실패"), - API_QA_NULL("986", "질문 API 결과가 비어있습니다.") + API_QA_NULL("986", "질문 API 결과가 비어있습니다."), + + API_TOKEN_COUNT_OVER("987", "토큰 최대 개수를 넘었습니다."), ; diff --git a/src/main/java/com/chwipoClova/common/utils/ApiUtils.java b/src/main/java/com/chwipoClova/common/utils/ApiUtils.java index bb19a65..76fdc6e 100644 --- a/src/main/java/com/chwipoClova/common/utils/ApiUtils.java +++ b/src/main/java/com/chwipoClova/common/utils/ApiUtils.java @@ -72,7 +72,7 @@ public class ApiUtils { @Transactional public String callApi(URI apiUrl, HttpEntity entity) { String resultData = null; - String resultMessage = null; + String resultMessage; Long userId = null; Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication.getPrincipal() instanceof UserDetailsImpl) { @@ -163,7 +163,7 @@ public boolean countTokenLimitCk(String text, int limitCnt) { String count = countToken(text); int tokenCnt = Integer.parseInt(count); if (tokenCnt >= limitCnt) { - throw new CommonException(ExceptionCode.API_TOKEN_COUNT_FAIL.getMessage(), ExceptionCode.API_TOKEN_COUNT_FAIL.getCode()); + throw new CommonException(ExceptionCode.API_TOKEN_COUNT_OVER.getMessage(), ExceptionCode.API_TOKEN_COUNT_OVER.getCode()); } else { return true; } diff --git a/src/main/java/com/chwipoClova/feedback/request/FeedbackInsertReq.java b/src/main/java/com/chwipoClova/feedback/request/FeedbackInsertReq.java index c2e197b..b0751fa 100644 --- a/src/main/java/com/chwipoClova/feedback/request/FeedbackInsertReq.java +++ b/src/main/java/com/chwipoClova/feedback/request/FeedbackInsertReq.java @@ -1,5 +1,6 @@ package com.chwipoClova.feedback.request; +import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -15,4 +16,8 @@ public class FeedbackInsertReq { @Schema(description = "답변", example = "답변1", name = "answer") private String answer; + @Hidden + @Schema(description = "apiNum", example = "1", name = "apiNum") + private Long apiNum; + } diff --git a/src/main/java/com/chwipoClova/feedback/service/FeedbackService.java b/src/main/java/com/chwipoClova/feedback/service/FeedbackService.java index 8140406..70150ab 100644 --- a/src/main/java/com/chwipoClova/feedback/service/FeedbackService.java +++ b/src/main/java/com/chwipoClova/feedback/service/FeedbackService.java @@ -4,6 +4,7 @@ import com.chwipoClova.common.exception.ExceptionCode; import com.chwipoClova.common.response.CommonResponse; import com.chwipoClova.common.response.MessageCode; +import com.chwipoClova.common.utils.ApiUtils; import com.chwipoClova.feedback.entity.Feedback; import com.chwipoClova.feedback.entity.FeedbackEditor; import com.chwipoClova.feedback.repository.FeedbackRepository; @@ -42,27 +43,20 @@ public class FeedbackService { private final UserRepository userRepository; + private final ApiUtils apiUtils; + @Transactional - public CommonResponse insertFeedback(List feedbackInsertListReq) throws IOException { + public CommonResponse insertFeedback(String allAnswerData, List feedbackInsertListReq) throws IOException { // TODO 피드백 연동 필요함 답변이 있는 경우만 전달하자 - // 테스트 데이터 - List feedBackApiListRes = new ArrayList<>(); - feedbackInsertListReq.stream().forEach(feedbackInsertReq -> { - Long qaId = feedbackInsertReq.getQaId(); - FeedBackApiRes feedBackApiRes = new FeedBackApiRes(); - feedBackApiRes.setQaId(qaId); - feedBackApiRes.setType(1); - feedBackApiRes.setContent("피드백1입니다."); - feedBackApiListRes.add(feedBackApiRes); - FeedBackApiRes feedBackApiRes2 = new FeedBackApiRes(); - feedBackApiRes2.setQaId(qaId); - feedBackApiRes2.setType(2); - feedBackApiRes2.setContent("피드백2입니다."); - feedBackApiListRes.add(feedBackApiRes2); - }); + // 키워드 + String apiKeywordRst = apiUtils.keyword(allAnswerData); - insertAllFeedback(feedBackApiListRes); + // 모범답안 + String apiBestRst = apiUtils.best(allAnswerData); + + // 피드백 매핑 + setApiFeedbackData(apiKeywordRst, apiBestRst, feedbackInsertListReq); return new CommonResponse<>(MessageCode.OK.getCode(), null, MessageCode.OK.getMessage()); } @@ -155,4 +149,62 @@ public void insertAllFeedback(List feedBackApiListRes) { public void deleteFeedback(Long qaId) { feedbackRepository.deleteByQaQaId(qaId); } + + private void setApiFeedbackData(String apiKeywordRst, String apiBestRst, List feedbackInsertListReq) { + List feedbackList = new ArrayList<>(); + String[] splitKeywordList = apiKeywordRst.split("\n"); + + // 키워드 가공 + for (String splitSummary : splitKeywordList) { + if (splitSummary.indexOf(".") != -1) { + String num = splitSummary.substring(0, splitSummary.indexOf(".")); + if (org.apache.commons.lang3.StringUtils.isNumeric(num)) { + String content = splitSummary.substring(splitSummary.indexOf(".")).trim(); + + FeedbackListRes feedbackListRes = FeedbackListRes.builder() + .qaId(Long.parseLong(num)) + .type(1) + .content(content) + .build(); + feedbackList.add(feedbackListRes); + } + } + } + + // 모법답안 가공 + String[] splitBestList = apiBestRst.split("\n"); + for (String splitSummary : splitBestList) { + if (splitSummary.indexOf(".") != -1) { + String num = splitSummary.substring(0, splitSummary.indexOf(".")); + if (org.apache.commons.lang3.StringUtils.isNumeric(num)) { + String content = splitSummary.substring(splitSummary.indexOf(".")).trim(); + + FeedbackListRes feedbackListRes = FeedbackListRes.builder() + .qaId(Long.parseLong(num)) + .type(2) + .content(content) + .build(); + feedbackList.add(feedbackListRes); + } + } + } + + List feedBackApiListRes = new ArrayList<>(); + feedbackInsertListReq.stream().forEach(feedbackInsertReq -> { + + Long qaId = feedbackInsertReq.getQaId(); + Long apiNum = feedbackInsertReq.getApiNum(); + + feedbackList.stream().forEach(feedback -> { + if (apiNum == feedback.getQaId()) { + FeedBackApiRes feedBackApiRes = new FeedBackApiRes(); + feedBackApiRes.setQaId(qaId); + feedBackApiRes.setType(feedback.getType()); + feedBackApiRes.setContent(feedback.getContent()); + feedBackApiListRes.add(feedBackApiRes); + } + }); + insertAllFeedback(feedBackApiListRes); + }); + } } diff --git a/src/main/java/com/chwipoClova/interview/entity/Interview.java b/src/main/java/com/chwipoClova/interview/entity/Interview.java index b4eaa86..1ca454d 100644 --- a/src/main/java/com/chwipoClova/interview/entity/Interview.java +++ b/src/main/java/com/chwipoClova/interview/entity/Interview.java @@ -66,11 +66,13 @@ public void prePersist() { public InterviewEditor.InterviewEditorBuilder toEditor() { return InterviewEditor.builder() - .status(status); + .status(status) + .feedback(feedback); } public void edit(InterviewEditor interviewEditor) { status = interviewEditor.getStatus(); + feedback = interviewEditor.getFeedback(); } } diff --git a/src/main/java/com/chwipoClova/interview/entity/InterviewEditor.java b/src/main/java/com/chwipoClova/interview/entity/InterviewEditor.java index d497880..00e762c 100644 --- a/src/main/java/com/chwipoClova/interview/entity/InterviewEditor.java +++ b/src/main/java/com/chwipoClova/interview/entity/InterviewEditor.java @@ -9,8 +9,11 @@ public class InterviewEditor { private Integer status; + private String feedback; + @Builder - public InterviewEditor(Integer status) { + public InterviewEditor(Integer status, String feedback) { this.status = status; + this.feedback = feedback; } } diff --git a/src/main/java/com/chwipoClova/qa/response/QaListForFeedbackRes.java b/src/main/java/com/chwipoClova/qa/response/QaListForFeedbackRes.java index c8f6dce..3c493c9 100644 --- a/src/main/java/com/chwipoClova/qa/response/QaListForFeedbackRes.java +++ b/src/main/java/com/chwipoClova/qa/response/QaListForFeedbackRes.java @@ -31,7 +31,7 @@ public class QaListForFeedbackRes { private Date modifyDate; @Schema(description = "피드백1 키워드", example = "키워드", name = "keyword") - private String keyword; + private List keyword; @Schema(description = "피드백2 모법답안", example = "AI 답변", name = "bestAnswer") private String bestAnswer; diff --git a/src/main/java/com/chwipoClova/qa/service/QaService.java b/src/main/java/com/chwipoClova/qa/service/QaService.java index a93fa61..d8d555d 100644 --- a/src/main/java/com/chwipoClova/qa/service/QaService.java +++ b/src/main/java/com/chwipoClova/qa/service/QaService.java @@ -29,13 +29,11 @@ import org.springframework.transaction.annotation.Transactional; import java.io.IOException; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; @RequiredArgsConstructor @@ -95,7 +93,10 @@ public CommonResponse insertAnswer(QaAnswerInsertReq qaAnswerInsertReq) throws I Qa lastQa = qaRepository.findFirstByInterviewInterviewIdOrderByQaIdDesc(interviewId); Long lastQaId = lastQa.getQaId(); + StringBuilder stringBuilder = new StringBuilder(); AtomicBoolean lastCkAtomic = new AtomicBoolean(false); + + AtomicLong answerCnt = new AtomicLong(); qaAnswerDataInsertReqList.stream().forEach(qaAnswerDataInsertReq -> { String answer = qaAnswerDataInsertReq.getAnswer(); @@ -111,11 +112,17 @@ public CommonResponse insertAnswer(QaAnswerInsertReq qaAnswerInsertReq) throws I lastCkAtomic.set(true); } + answerCnt.getAndIncrement(); + + stringBuilder.append(answerCnt.get() + ". " + qa.getAnswer()); + stringBuilder.append("\n"); + // 피드백 정보 FeedbackInsertReq feedbackInsertReq = new FeedbackInsertReq(); feedbackInsertReq.setQaId(qa.getQaId()); feedbackInsertReq.setAnswer(qa.getAnswer()); feedbackInsertReq.setQuestion(qa.getQuestion()); + feedbackInsertReq.setApiNum(answerCnt.get()); feedbackInsertListReq.add(feedbackInsertReq); } }); @@ -123,26 +130,25 @@ public CommonResponse insertAnswer(QaAnswerInsertReq qaAnswerInsertReq) throws I // 마지막 답변이 있을 경우 면접 완료 처리 및 피드백 생성 Boolean lastCk = lastCkAtomic.get(); if (lastCk) { - // 면접관의 속마음 - //apiUtils.feel(); - // 키워드 + String allAnswerData = stringBuilder.toString().trim(); + // 면접관의 속마음 + String apiFeelRst = apiUtils.feel(allAnswerData); - // 모범답안 - - // 피드백 요청 및 등록 - feedbackService.insertFeedback(feedbackInsertListReq); + feedbackService.insertFeedback(allAnswerData, feedbackInsertListReq); // 면접 완료 처리 InterviewEditor.InterviewEditorBuilder editorBuilder = interview.toEditor(); - InterviewEditor interviewEditor = editorBuilder.status(1).build(); + InterviewEditor interviewEditor = editorBuilder.status(1).feedback(apiFeelRst).build(); interview.edit(interviewEditor); } return new CommonResponse<>(MessageCode.OK.getCode(), null, MessageCode.OK.getMessage()); } + + public List selectQaList(Long interviewId) { List qaListResList = new ArrayList<>(); @@ -166,13 +172,21 @@ public List selectQaListForFeedback(Long interviewId) { List qaListRes = selectQaList(interviewId); List listForFeedbackResList = new ArrayList<>(); + AtomicReference> atomicListRef = new AtomicReference<>(new ArrayList<>()); + qaListRes.stream().forEach(qaListRes1 -> { AtomicReference feedback1 = new AtomicReference<>(""); AtomicReference feedback2 = new AtomicReference<>(""); feedbackService.selectFeedbackList(qaListRes1.getQaId()).stream().forEach(feedbackListRes -> { Integer type = feedbackListRes.getType(); if (type == 1) { - feedback1.set(feedbackListRes.getContent()); + // 키워드는 ,로 분리 + String keyword = feedbackListRes.getContent(); + String[] keywordArray = keyword.split(","); + + for (String key : keywordArray) { + addElement(atomicListRef, key); + } } else if (type == 2) { feedback2.set(feedbackListRes.getContent()); } @@ -185,7 +199,7 @@ public List selectQaListForFeedback(Long interviewId) { .answer(qaListRes1.getAnswer()) .regDate(qaListRes1.getRegDate()) .modifyDate(qaListRes1.getModifyDate()) - .keyword(feedback1.get()) + .keyword(atomicListRef.get()) .bestAnswer(feedback2.get()) .build(); listForFeedbackResList.add(qalistForFeedbackRes); @@ -290,4 +304,16 @@ private List getApiQaList(String apiQaRst) { return apiQaList; } + + // 원자적으로 리스트에 요소를 추가하는 메소드 + private static void addElement(AtomicReference> atomicListRef, String element) { + List oldList; + List newList; + + do { + oldList = atomicListRef.get(); + newList = new ArrayList<>(oldList); + newList.add(element); + } while (!atomicListRef.compareAndSet(oldList, newList)); + } }