Skip to content

Commit

Permalink
Merge pull request #115 from Happy-HOBAK/feat/#114
Browse files Browse the repository at this point in the history
[#114] 연령대와 성별에 따른 행복 종합 리포트 구축
  • Loading branch information
KkomSang authored May 31, 2024
2 parents 3397360 + dd8e9e0 commit 416bc67
Show file tree
Hide file tree
Showing 22 changed files with 246 additions and 102 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.hobak.happinessql.domain.record.repository;

import com.hobak.happinessql.domain.record.domain.Record;
import com.hobak.happinessql.domain.user.domain.Gender;
import com.hobak.happinessql.domain.user.domain.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
Expand All @@ -24,4 +25,9 @@ public interface RecordRepository extends JpaRepository<Record, Long> {
@Query("SELECT r FROM Record r WHERE r.user.userId != :userId")
List<Record> findAllExceptUser(@Param("userId") Long userId);

List<Record> findByUserGender(Gender gender);

List<Record> findByUserAgeBetween(int minAge, int maxAge);

List<Record> findByUserAgeBetweenAndUserGender(int minAge, int maxAge, Gender gender);
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,25 @@
import com.hobak.happinessql.domain.report.application.AverageHappinessService;
import com.hobak.happinessql.domain.report.application.TrendPopularActivityService;
import com.hobak.happinessql.domain.report.application.TrendRecommendService;
import com.hobak.happinessql.domain.report.application.TrendSummaryService;
import com.hobak.happinessql.domain.report.domain.AgeGroup;
import com.hobak.happinessql.domain.report.dto.AverageHappinessResponseDto;
import com.hobak.happinessql.domain.report.dto.SummaryResponseDto;
import com.hobak.happinessql.domain.report.dto.TrendPopularActivitiyResponseDto;
import com.hobak.happinessql.domain.report.dto.TrendRecommendActivityResponseDto;
import com.hobak.happinessql.domain.user.application.UserFindService;
import com.hobak.happinessql.domain.user.domain.Gender;
import com.hobak.happinessql.domain.user.domain.User;
import com.hobak.happinessql.global.response.DataResponseDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
Expand All @@ -29,6 +35,7 @@ public class TrendController {
private final AverageHappinessService averageHappinessService;
private final TrendPopularActivityService trendPopularActivityService;
private final TrendRecommendService trendRecommendService;
private final TrendSummaryService trendSummaryService;

@Operation(summary = "대한민국 평균 행복지수", description = "전체 유저의 평균 행복지수와 그에 따른 수준을 판단합니다.")
@GetMapping("/happiness")
Expand All @@ -50,4 +57,15 @@ public DataResponseDto<List<TrendRecommendActivityResponseDto>> getRecommendedAc
List<TrendRecommendActivityResponseDto> responseDto = trendRecommendService.getRecommendActivities(user);
return DataResponseDto.of(responseDto, "추천 활동을 성공적으로 조회했습니다.");
}

@Operation(summary = "연령대와 나이에 따른 행복 종합 리포트", description = "연령대와 나이를 쿼리 파라미터로 받아 그에 해당하는 행복 종합 리포트를 제공합니다. 만약 데이터가 없을 경우 data에 '아직은 데이터가 없습니다.' 문자열을 반환합니다.",
parameters = {@Parameter(name="ageGroup", description = "지정하지 않으면 전체 연령으로 자동 설정됩니다."),
@Parameter(name="gender", description = "gender를 지정하지 않으면 전체로 자동 설정됩니다.")
})
@GetMapping("/summary")
public DataResponseDto<Object> getSummary(@RequestParam(required = false) AgeGroup ageGroup, @RequestParam(required = false) Gender gender) {
SummaryResponseDto responseDto = trendSummaryService.getSummary(ageGroup, gender);
if(responseDto == null) return DataResponseDto.of("아직은 데이터가 없어요.", "행복 트렌드의 행복 종합 리포트를 성공적으로 조회했습니다.");
return DataResponseDto.of(responseDto, "행복 트렌드의 행복 종합 리포트를 성공적으로 조회했습니다.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.hobak.happinessql.domain.record.domain.Record;
import com.hobak.happinessql.domain.report.converter.ReportConverter;
import com.hobak.happinessql.domain.report.converter.TrendConverter;
import com.hobak.happinessql.domain.report.dto.ActivityHappinessResponseDto;
import com.hobak.happinessql.domain.report.dto.ActivityRankingResponseDto;
import com.hobak.happinessql.domain.report.dto.TrendRecommendActivityResponseDto;

import java.util.*;
Expand Down Expand Up @@ -40,13 +40,13 @@ public static String getHappiestActivity(List<Record> records) {
}
}

public static List<ActivityHappinessResponseDto> getActivityRankings(List<Record> records, int topCount) {
List<ActivityHappinessResponseDto> activityRankings = new ArrayList<>();
public static List<ActivityRankingResponseDto> getActivityRankings(List<Record> records, int topCount) {
List<ActivityRankingResponseDto> activityRankings = new ArrayList<>();

if (records == null || records.isEmpty()) {
// 데이터가 없는 경우에도 빈 ActivityHappinessDto 객체를 topCount만큼 추가
for (int i = 0; i < topCount; i++) {
activityRankings.add(ReportConverter.toActivityHappinessResponseDto(i + 1, null, null));
activityRankings.add(ReportConverter.toActivityRankingResponseDto(i + 1, null, null));
}
return activityRankings;
}
Expand All @@ -55,16 +55,16 @@ public static List<ActivityHappinessResponseDto> getActivityRankings(List<Record

// 만약 topCount보다 적게 선정된 경우, 나머지 빈 항목 추가
while (activityRankings.size() < topCount) {
activityRankings.add(ReportConverter.toActivityHappinessResponseDto(activityRankings.size() + 1, null, null));
activityRankings.add(ReportConverter.toActivityRankingResponseDto(activityRankings.size() + 1, null, null));
}

return activityRankings.stream()
.limit(topCount)
.collect(Collectors.toList());
}

public static List<ActivityHappinessResponseDto> getActivityRankings(List<Record> records) {
List<ActivityHappinessResponseDto> activityRankings = new ArrayList<>();
public static List<ActivityRankingResponseDto> getActivityRankings(List<Record> records) {
List<ActivityRankingResponseDto> activityRankings = new ArrayList<>();

// 활동 그룹화 및 이모지 매핑
Map<String, String> activityEmojiMap = getActivityEmojiMap(records);
Expand All @@ -81,7 +81,7 @@ public static List<ActivityHappinessResponseDto> getActivityRankings(List<Record
for (int i = 0; i < sortedActivities.size(); i++) {
String activity = sortedActivities.get(i);
String emoji = activityEmojiMap.get(activity); // 이모지 가져오기
ActivityHappinessResponseDto activityDto = ReportConverter.toActivityHappinessResponseDto(i + 1, activity, emoji);
ActivityRankingResponseDto activityDto = ReportConverter.toActivityRankingResponseDto(i + 1, activity, emoji);
activityRankings.add(activityDto);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.hobak.happinessql.domain.record.domain.Record;
import com.hobak.happinessql.domain.report.converter.ReportConverter;
import com.hobak.happinessql.domain.report.dto.LocationHappinessResponseDto;
import com.hobak.happinessql.domain.report.dto.LocationRankingResponseDto;

import java.util.*;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -38,29 +38,29 @@ public static String getHappiestLocation(List<Record> records) {
}
}

public static List<LocationHappinessResponseDto> getLocationRankings(List<Record> records, int topCount) {
List<LocationHappinessResponseDto> locationRankings = new ArrayList<>();
public static List<LocationRankingResponseDto> getLocationRankings(List<Record> records, int topCount) {
List<LocationRankingResponseDto> locationRankings = new ArrayList<>();
if (records == null || records.isEmpty()) {
// 데이터가 없는 경우에도 빈 LocationHappinessDto 객체를 topCount만큼 추가
for (int i = 0; i < topCount; i++) {
locationRankings.add(ReportConverter.toLocationHappinessResponseDto(i + 1, null));
locationRankings.add(ReportConverter.toLocationRankingResponseDto(i + 1, null));
}
return locationRankings;
}

locationRankings = getLocationRankings(records);
// 만약 topCount보다 적게 선정된 경우, 나머지 빈 항목 추가
while (locationRankings.size() < topCount) {
locationRankings.add(ReportConverter.toLocationHappinessResponseDto(locationRankings.size() + 1, null));
locationRankings.add(ReportConverter.toLocationRankingResponseDto(locationRankings.size() + 1, null));
}

return locationRankings.stream()
.limit(topCount)
.collect(Collectors.toList());
}

public static List<LocationHappinessResponseDto> getLocationRankings(List<Record> records) {
List<LocationHappinessResponseDto> locationRankings = new ArrayList<>();
public static List<LocationRankingResponseDto> getLocationRankings(List<Record> records) {
List<LocationRankingResponseDto> locationRankings = new ArrayList<>();

// 도시와 구를 기준으로 Record 그룹화
Map<String, List<Record>> locationRecordsMap = groupRecordsByLocation(records);
Expand All @@ -75,7 +75,7 @@ public static List<LocationHappinessResponseDto> getLocationRankings(List<Record
// 상위 N개의 위치 선정
for (int i = 0; i < sortedLocations.size(); i++) {
String location = sortedLocations.get(i);
LocationHappinessResponseDto locationDto = ReportConverter.toLocationHappinessResponseDto(i + 1, location);
LocationRankingResponseDto locationDto = ReportConverter.toLocationRankingResponseDto(i + 1, location);
locationRankings.add(locationDto);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.hobak.happinessql.domain.record.domain.Record;
import com.hobak.happinessql.domain.record.repository.RecordRepository;
import com.hobak.happinessql.domain.report.dto.ActivityHappinessResponseDto;
import com.hobak.happinessql.domain.report.dto.ActivityRankingResponseDto;
import com.hobak.happinessql.domain.user.domain.User;
import lombok.RequiredArgsConstructor;
import java.time.LocalDate;
Expand All @@ -17,20 +17,20 @@ public class ReportActivityRankingService {

private final RecordRepository recordRepository;

public List<ActivityHappinessResponseDto> getTop3AllHappiestActivities(User user) {
public List<ActivityRankingResponseDto> getTop3AllHappiestActivities(User user) {
List<Record> records = recordRepository.findAllByUser(user);
return ActivityHappinessAnalyzer.getActivityRankings(records, 3);
}

public List<ActivityHappinessResponseDto> getTop3AnnualHappiestActivities(User user) {
public List<ActivityRankingResponseDto> getTop3AnnualHappiestActivities(User user) {
int currentYear = LocalDate.now().getYear();
LocalDateTime startOfYear = LocalDateTime.of(currentYear, 1, 1, 0, 0);
LocalDateTime endOfYear = LocalDateTime.of(currentYear, 12, 31, 23, 59, 59);
List<Record> records = recordRepository.findAllByCreatedAtBetweenAndUser(startOfYear, endOfYear, user);
return ActivityHappinessAnalyzer.getActivityRankings(records, 3);
}

public List<ActivityHappinessResponseDto> getTop3MonthlyHappiestActivities(User user) {
public List<ActivityRankingResponseDto> getTop3MonthlyHappiestActivities(User user) {
LocalDate today = LocalDate.now();
LocalDate startOfMonth = today.withDayOfMonth(1);
LocalDate endOfMonth = today.withDayOfMonth(today.lengthOfMonth());
Expand All @@ -40,20 +40,20 @@ public List<ActivityHappinessResponseDto> getTop3MonthlyHappiestActivities(User
return ActivityHappinessAnalyzer.getActivityRankings(records, 3);
}

public List<ActivityHappinessResponseDto> getAllActivityRankings(User user) {
public List<ActivityRankingResponseDto> getAllActivityRankings(User user) {
List<Record> records = recordRepository.findAllByUser(user);
return ActivityHappinessAnalyzer.getActivityRankings(records);
}

public List<ActivityHappinessResponseDto> getYearlyActivityRankings(User user) {
public List<ActivityRankingResponseDto> getYearlyActivityRankings(User user) {
int currentYear = LocalDate.now().getYear();
LocalDateTime startOfYear = LocalDateTime.of(currentYear, 1, 1, 0, 0);
LocalDateTime endOfYear = LocalDateTime.of(currentYear, 12, 31, 23, 59, 59);
List<Record> records = recordRepository.findAllByCreatedAtBetweenAndUser(startOfYear, endOfYear, user);
return ActivityHappinessAnalyzer.getActivityRankings(records);
}

public List<ActivityHappinessResponseDto> getMonthlyActivityRankings(User user) {
public List<ActivityRankingResponseDto> getMonthlyActivityRankings(User user) {
LocalDate today = LocalDate.now();
LocalDate startOfMonth = LocalDate.now().withDayOfMonth(1);
LocalDate endOfMonth = LocalDate.now().withDayOfMonth(today.lengthOfMonth());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.hobak.happinessql.domain.record.domain.Record;
import com.hobak.happinessql.domain.record.repository.RecordRepository;
import com.hobak.happinessql.domain.report.dto.LocationHappinessResponseDto;
import com.hobak.happinessql.domain.report.dto.LocationRankingResponseDto;
import com.hobak.happinessql.domain.user.domain.User;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand All @@ -16,20 +16,20 @@
public class ReportLocationRankingService {
private final RecordRepository recordRepository;

public List<LocationHappinessResponseDto> getTop3AllHappiestLocations(User user) {
public List<LocationRankingResponseDto> getTop3AllHappiestLocations(User user) {
List<Record> records = recordRepository.findAllByUser(user);
return LocationHappinessAnalyzer.getLocationRankings(records, 3);
}

public List<LocationHappinessResponseDto> getTop3AnnualHappiestLocations(User user) {
public List<LocationRankingResponseDto> getTop3AnnualHappiestLocations(User user) {
int currentYear = LocalDate.now().getYear();
LocalDateTime startOfYear = LocalDateTime.of(currentYear, 1, 1, 0, 0);
LocalDateTime endOfYear = LocalDateTime.of(currentYear, 12, 31, 23, 59, 59);
List<Record> records = recordRepository.findAllByCreatedAtBetweenAndUser(startOfYear, endOfYear, user);
return LocationHappinessAnalyzer.getLocationRankings(records, 3);
}

public List<LocationHappinessResponseDto> getTop3MonthlyHappiestLocations(User user) {
public List<LocationRankingResponseDto> getTop3MonthlyHappiestLocations(User user) {
LocalDate today = LocalDate.now();
LocalDate startOfMonth = today.withDayOfMonth(1);
LocalDate endOfMonth = today.withDayOfMonth(today.lengthOfMonth());
Expand All @@ -39,20 +39,20 @@ public List<LocationHappinessResponseDto> getTop3MonthlyHappiestLocations(User u
return LocationHappinessAnalyzer.getLocationRankings(records, 3);
}

public List<LocationHappinessResponseDto> getAllLocationRankings(User user) {
public List<LocationRankingResponseDto> getAllLocationRankings(User user) {
List<Record> records = recordRepository.findAllByUser(user);
return LocationHappinessAnalyzer.getLocationRankings(records);
}

public List<LocationHappinessResponseDto> getYearlyLocationRankings(User user) {
public List<LocationRankingResponseDto> getYearlyLocationRankings(User user) {
int currentYear = LocalDate.now().getYear();
LocalDateTime startOfYear = LocalDateTime.of(currentYear, 1, 1, 0, 0);
LocalDateTime endOfYear = LocalDateTime.of(currentYear, 12, 31, 23, 59, 59);
List<Record> records = recordRepository.findAllByCreatedAtBetweenAndUser(startOfYear, endOfYear, user);
return LocationHappinessAnalyzer.getLocationRankings(records);
}

public List<LocationHappinessResponseDto> getMonthlyLocationRankings(User user) {
public List<LocationRankingResponseDto> getMonthlyLocationRankings(User user) {
LocalDate today = LocalDate.now();
LocalDate startOfMonth = LocalDate.now().withDayOfMonth(1);
LocalDate endOfMonth = LocalDate.now().withDayOfMonth(today.lengthOfMonth());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.hobak.happinessql.domain.record.repository.RecordRepository;
import com.hobak.happinessql.domain.report.converter.ReportConverter;
import com.hobak.happinessql.domain.report.domain.TimeOfDay;
import com.hobak.happinessql.domain.report.dto.ReportSummaryResponseDto;
import com.hobak.happinessql.domain.report.dto.SummaryResponseDto;
import com.hobak.happinessql.domain.user.domain.User;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand All @@ -20,12 +20,12 @@ public class ReportSummaryService {

private final RecordRepository recordRepository;

public ReportSummaryResponseDto getAllSummary(User user) {
public SummaryResponseDto getAllSummary(User user) {
List<Record> records = recordRepository.findAllByUser(user);
return generateReportSummary(records);
}

public ReportSummaryResponseDto getAnnualSummary(User user) {
public SummaryResponseDto getAnnualSummary(User user) {
int currentYear = LocalDate.now().getYear();
LocalDateTime startOfYear = LocalDateTime.of(currentYear, 1, 1, 0, 0);
LocalDateTime endOfYear = LocalDateTime.of(currentYear, 12, 31, 23, 59, 59);
Expand All @@ -34,7 +34,7 @@ public ReportSummaryResponseDto getAnnualSummary(User user) {
return generateReportSummary(annualRecords);
}

public ReportSummaryResponseDto getMonthlySummary(User user) {
public SummaryResponseDto getMonthlySummary(User user) {
LocalDate today = LocalDate.now();
LocalDateTime startOfMonth = today.withDayOfMonth(1).atStartOfDay();
LocalDateTime endOfMonth = today.withDayOfMonth(today.lengthOfMonth()).atTime(23, 59, 59);
Expand All @@ -43,11 +43,11 @@ public ReportSummaryResponseDto getMonthlySummary(User user) {
return generateReportSummary(monthlyRecords);
}

private ReportSummaryResponseDto generateReportSummary(List<Record> records) {
private SummaryResponseDto generateReportSummary(List<Record> records) {
String location = LocationHappinessAnalyzer.getHappiestLocation(records);
TimeOfDay timeOfDay = TimeOfDayHappinessAnalyzer.getHappiestTimeOfDay(records);
String activity = ActivityHappinessAnalyzer.getHappiestActivity(records);

return ReportConverter.toReportSummaryResponseDto(timeOfDay, location, activity);
return ReportConverter.toSummaryResponseDto(timeOfDay, location, activity);
}
}
Loading

0 comments on commit 416bc67

Please sign in to comment.