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

[Feature/#20] 감정 분석 레포트 상세 조회 기능 구현 #21

Merged
merged 1 commit into from
Nov 17, 2024
Merged
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
5 changes: 5 additions & 0 deletions src/main/java/LearnMate/dev/controller/ReportController.java
Original file line number Diff line number Diff line change
@@ -17,4 +17,9 @@ public class ReportController {
public ApiResponse<ReportResponse.ReportDto> getEmotionReport() {
return ApiResponse.onSuccessData("감정 분석 레포트 조회 성공", reportService.getEmotionReport());
}

@GetMapping("/detail")
public ApiResponse<ReportResponse.ReportDetailDto> getEmotionDetailReport() {
return ApiResponse.onSuccessData("감정 분석 상세 레포트 조회 성공", reportService.getEmotionDetailReport());
}
}
16 changes: 14 additions & 2 deletions src/main/java/LearnMate/dev/model/converter/ReportConverter.java
Original file line number Diff line number Diff line change
@@ -13,15 +13,27 @@ public static ReportResponse.ReportEmotionDto toReportEmotionDto(ReportResponse.
.count(emotionDto.getCount())
.build();
}
public static ReportResponse.ReportDto toReportDto(List<ReportResponse.EmotionDto> emotionDtoList) {

List<ReportResponse.ReportEmotionDto> reportEmotionDtoList = emotionDtoList.stream()
public static List<ReportResponse.ReportEmotionDto> toReportEmotionDtoList(List<ReportResponse.EmotionDto> emotionDtoList) {
return emotionDtoList.stream()
.map(ReportConverter::toReportEmotionDto)
.toList();
}

public static ReportResponse.ReportDto toReportDto(List<ReportResponse.ReportEmotionDto> reportEmotionDtoList) {
return ReportResponse.ReportDto.builder()
.emotionReport(reportEmotionDtoList)
.build();
}

public static ReportResponse.ReportDetailDto toReportDetailDto(List<ReportResponse.ReportEmotionDto> reportEmotionDtoList,
List<ReportResponse.EmotionOnDayDto> emotionOnDayDtoList,
List<ReportResponse.EmotionRankDto> emotionRankDtoList) {
return ReportResponse.ReportDetailDto.builder()
.emotionReport(reportEmotionDtoList)
.emotionOnDayList(emotionOnDayDtoList)
.emotionRankDtoList(emotionRankDtoList)
.build();
}

}
43 changes: 43 additions & 0 deletions src/main/java/LearnMate/dev/model/dto/response/ReportResponse.java
Original file line number Diff line number Diff line change
@@ -6,6 +6,8 @@
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

public class ReportResponse {
@@ -39,6 +41,35 @@ public static class ReportEmotionDto {

}

@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class EmotionOnDayDto {

private String emotion;
private String emoticon;
private String day;

public EmotionOnDayDto(EmotionSpectrum emotion, LocalDateTime date) {
this.emotion = emotion.getValue();
this.emoticon = emotion.getEmoticon();
this.day = date.format(DateTimeFormatter.ofPattern("MM/dd"));
}
}

@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class EmotionRankDto {

private String emotion;
private String emoticon;
private Long rank;

}

@Getter
@Builder
@AllArgsConstructor
@@ -49,6 +80,18 @@ public static class ReportDto {

}

@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class ReportDetailDto {

private List<ReportEmotionDto> emotionReport;
private List<EmotionOnDayDto> emotionOnDayList;
private List<EmotionRankDto> emotionRankDtoList;

}

}


12 changes: 12 additions & 0 deletions src/main/java/LearnMate/dev/repository/EmotionRepository.java
Original file line number Diff line number Diff line change
@@ -23,4 +23,16 @@ List<ReportResponse.EmotionDto> findEmotionDtoByUser(
@Param(value = "startDate") LocalDate startDate,
@Param(value = "endDate") LocalDate endDate,
@Param(value = "user") User user);

@Query("SELECT new LearnMate.dev.model.dto.response.ReportResponse$EmotionOnDayDto(e.emotion, e.createdAt) " +
"FROM Emotion e " +
"JOIN e.diary d " +
"WHERE d.user = :user " +
"AND DATE(e.createdAt) >= :startDate " +
"AND DATE(e.createdAt) <= :endDate " +
"ORDER BY e.createdAt asc ")
List<ReportResponse.EmotionOnDayDto> findEmotionOnDayDtoByUser(
@Param(value = "startDate") LocalDate startDate,
@Param(value = "endDate") LocalDate endDate,
@Param(value = "user") User user);
}
68 changes: 57 additions & 11 deletions src/main/java/LearnMate/dev/service/ReportService.java
Original file line number Diff line number Diff line change
@@ -15,10 +15,8 @@
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

@Service
@@ -29,32 +27,84 @@ public class ReportService {


/*
* user가 2주동안 겪은 각 감정의 개수를 리스트 형태로 반환
* user의 2주동안 나타난 각 감정의 개수를 리스트 형태로 반환
* @return
*/
public ReportResponse.ReportDto getEmotionReport() {
Long userId = getUserIdFromAuthentication();
User user = findUserById(userId);

LocalDate now = LocalDate.now();
LocalDate twoWeekAgo = now.minusDays(14);

// 2주동안 나타난 각 감정의 개수 반환
List<ReportResponse.EmotionDto> emotionDtoList = getEmotionDtoList(twoWeekAgo, now, user);
List<ReportResponse.ReportEmotionDto> reportEmotionDtoList = ReportConverter.toReportEmotionDtoList(emotionDtoList);

return ReportConverter.toReportDto(reportEmotionDtoList);
}

/*
* user의 2주동안 나타난 각 감정의 개수, 각 날짜에 나타난 감정, 가장 많이 나타난 감정 리스트를 반환
* @return
*/
public ReportResponse.ReportDetailDto getEmotionDetailReport() {
Long userId = getUserIdFromAuthentication();
User user = findUserById(userId);

LocalDate now = LocalDate.now();
LocalDate twoWeekAgo = now.minusDays(14);

// 각 감정의 개수
List<ReportResponse.EmotionDto> emotionDtoList = getEmotionDtoList(twoWeekAgo, now, user);
List<ReportResponse.ReportEmotionDto> reportEmotionDtoList = ReportConverter.toReportEmotionDtoList(emotionDtoList);

// 각 날짜에 나타난 감정
List<ReportResponse.EmotionOnDayDto> emotionOnDayDtoList = getEmotionOnDay(twoWeekAgo, now, user);

// 해당 기간동안 가장 많이 나타난 감정 3개
List<ReportResponse.EmotionRankDto> emotionRankDtoList = getEmotionRank(reportEmotionDtoList);

return ReportConverter.toReportDetailDto(reportEmotionDtoList, emotionOnDayDtoList, emotionRankDtoList);
}

private List<ReportResponse.EmotionDto> getEmotionDtoList(LocalDate startDate, LocalDate endDate, User user) {
List<ReportResponse.EmotionDto> emotionDtoList = emotionRepository.findEmotionDtoByUser(startDate, endDate, user);
return getDefaultEmotionDtoAndParse(emotionDtoList);
}

private List<ReportResponse.EmotionDto> getDefaultEmotionDtoAndParse(List<ReportResponse.EmotionDto> emotionDtoList) {
// 각 감정에 대한 결과 emotiondto를 mapping
Map<EmotionSpectrum, ReportResponse.EmotionDto> emotionDtoMap = emotionDtoList.stream()
.collect(Collectors.toMap(ReportResponse.EmotionDto::getEmotionSpectrum, dto -> dto));

// 0개 나타난 emotion dto 추가 및 정렬
List<ReportResponse.EmotionDto> completeEmotionList = Arrays.stream(EmotionSpectrum.values())
return Arrays.stream(EmotionSpectrum.values())
.map(emotionSpectrum -> emotionDtoMap.getOrDefault(
emotionSpectrum,
new ReportResponse.EmotionDto(emotionSpectrum, 0L) // 기본값으로 초기화된 DTO
))
.sorted(Comparator.comparingInt(ReportResponse.EmotionDto::getOrder)) // 정렬
.toList();
}

return ReportConverter.toReportDto(completeEmotionList);
private List<ReportResponse.EmotionOnDayDto> getEmotionOnDay(LocalDate startDate, LocalDate endDate, User user) {
return emotionRepository.findEmotionOnDayDtoByUser(startDate, endDate, user);
}

private List<ReportResponse.EmotionRankDto> getEmotionRank(List<ReportResponse.ReportEmotionDto> emotionDtoList) {
AtomicLong rankCounter = new AtomicLong(1);

return emotionDtoList.stream()
// count 기준 내림차순 정렬
.sorted(Comparator.comparingLong(ReportResponse.ReportEmotionDto::getCount).reversed())
.limit(3) // 상위 3개만 추출
.map(dto -> new ReportResponse.EmotionRankDto( // dto 변환
dto.getEmotion(),
dto.getEmoticon(),
rankCounter.getAndIncrement() // 랭크 할당
))
.toList();
}

private Long getUserIdFromAuthentication() {
@@ -66,8 +116,4 @@ private Long getUserIdFromAuthentication() {
private User findUserById(Long userId) {
return userRepository.findById(userId).orElseThrow(() -> new ApiException(ErrorStatus._USER_NOT_FOUND));
}

private List<ReportResponse.EmotionDto> getEmotionDtoList(LocalDate startDate, LocalDate endDate, User user) {
return emotionRepository.findEmotionDtoByUser(startDate, endDate, user);
}
}