Skip to content

Commit

Permalink
feat: 통계 API 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
threeony committed Feb 3, 2024
1 parent 87b6a0f commit 6642f48
Show file tree
Hide file tree
Showing 8 changed files with 276 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@
public interface FeedRepository extends JpaRepository<Feed, Long> {

List<Feed> findAllByUserAndDateOrderByCreatedAtAsc(User user, LocalDate date);
Integer countByUserAndDate(User user, LocalDate date);
Integer countByUserAndDateAndIsChecked(User user, LocalDate date, Boolean t);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,8 @@
import com.onnoff.onnoff.domain.off.memoir.entity.MemoirAnswer;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface MemoirAnswerRepository extends JpaRepository<MemoirAnswer, Long> {
List<MemoirAnswer> findAllByMemoirId(Long memoirid);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@

public interface WorklogRepository extends JpaRepository<Worklog, Long> {
List<Worklog> findAllByUserAndDateOrderByCreatedAt(User user, LocalDate date);
Integer countByUserAndDate(User user, LocalDate date);
Integer countByUserAndDateAndIsChecked(User user, LocalDate date, Boolean t);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.onnoff.onnoff.domain.stats.controller;

import com.onnoff.onnoff.apiPayload.ApiResponse;
import com.onnoff.onnoff.domain.stats.dto.StatsResponseDTO;
import com.onnoff.onnoff.domain.stats.service.StatsService;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;

@RestController
@RequiredArgsConstructor
@RequestMapping("/stats")
public class StatsController {
private final StatsService statsService;

@GetMapping("/week")
@Operation(summary = "요일별 달성률")
public ApiResponse<StatsResponseDTO.WeekDTO> getWeekStats(){
return ApiResponse.onSuccess(statsService.getWeekStats());
}

@GetMapping("/month")
@Operation(summary = "월별 달성률")
public ApiResponse<StatsResponseDTO.MonthDTO> getMonthStats(){
return ApiResponse.onSuccess(statsService.getMonthStats(null));
}

@GetMapping("/month/prev")
@Operation(summary = "이전 달 달성률")
public ApiResponse<StatsResponseDTO.MonthDTO> moveToPrevMonth(@RequestParam(name = "date") LocalDate date){
return ApiResponse.onSuccess(statsService.getMonthStats(date.minusMonths(1)));
}

@GetMapping("/month/next")
@Operation(summary = "다음 달 달성률")
public ApiResponse<StatsResponseDTO.MonthDTO> moveToNextMonth(@RequestParam(name = "date") LocalDate date){
return ApiResponse.onSuccess(statsService.getMonthStats(date.plusMonths(1)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.onnoff.onnoff.domain.stats.converter;

import com.onnoff.onnoff.domain.stats.dto.StatsResponseDTO;

import java.time.LocalDate;
import java.util.List;

public class StatsConverter {
public static StatsResponseDTO.WeekDTO getWeekStatsDTO(LocalDate today, Double on, Double off,
Integer weekOfMonth, List<Double> weekStats){
StatsResponseDTO.WeekStatsDTO weekStatsDTO = StatsResponseDTO.WeekStatsDTO.builder()
.mon(weekStats.get(0))
.tue(weekStats.get(1))
.wed(weekStats.get(2))
.thu(weekStats.get(3))
.fri(weekStats.get(4))
.sat(weekStats.get(5))
.sun(weekStats.get(6))
.build();

return StatsResponseDTO.WeekDTO.builder()
.today(today)
.on(on)
.off(off)
.weekOfMonth(weekOfMonth)
.weekStatsDTO(weekStatsDTO)
.build();
}

public static StatsResponseDTO.MonthDTO getMonthStatsDTO(LocalDate date, Integer avg, List<StatsResponseDTO.MonthStatsDTO> monthStatsList){
return StatsResponseDTO.MonthDTO.builder()
.date(date)
.avg(avg)
.monthStatsList(monthStatsList)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.onnoff.onnoff.domain.stats.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDate;
import java.util.List;

public class StatsResponseDTO {

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class WeekStatsDTO{
Double mon;
Double tue;
Double wed;
Double thu;
Double fri;
Double sat;
Double sun;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class WeekDTO{
LocalDate today;
Double on;
Double off;
Integer weekOfMonth;
WeekStatsDTO weekStatsDTO;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class MonthStatsDTO{
LocalDate date;
Double rate;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class MonthDTO{
LocalDate date;
Integer avg;
List<MonthStatsDTO> monthStatsList;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.onnoff.onnoff.domain.stats.service;

import com.onnoff.onnoff.domain.stats.dto.StatsResponseDTO;

import java.time.LocalDate;

public interface StatsService {
StatsResponseDTO.WeekDTO getWeekStats();
StatsResponseDTO.MonthDTO getMonthStats(LocalDate date);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package com.onnoff.onnoff.domain.stats.service;

import com.onnoff.onnoff.auth.UserContext;
import com.onnoff.onnoff.domain.off.feed.repository.FeedRepository;
import com.onnoff.onnoff.domain.off.memoir.entity.Memoir;
import com.onnoff.onnoff.domain.off.memoir.entity.MemoirAnswer;
import com.onnoff.onnoff.domain.off.memoir.repository.MemoirAnswerRepository;
import com.onnoff.onnoff.domain.off.memoir.repository.MemoirRepository;
import com.onnoff.onnoff.domain.on.worklog.repository.WorklogRepository;
import com.onnoff.onnoff.domain.stats.converter.StatsConverter;
import com.onnoff.onnoff.domain.stats.dto.StatsResponseDTO;
import com.onnoff.onnoff.domain.user.User;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.WeekFields;
import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class StatsServiceImpl implements StatsService{
private final WorklogRepository worklogRepository;
private final FeedRepository feedRepository;
private final MemoirRepository memoirRepository;
private final MemoirAnswerRepository memoirAnswerRepository;

@Override
public StatsResponseDTO.WeekDTO getWeekStats(){
LocalDate today = LocalDate.now();

User user = UserContext.getUser();

Double on = worklogRepository.countByUserAndDateAndIsChecked(user, today, true) / worklogRepository.countByUserAndDate(user, today).doubleValue();
if(on.isNaN()) {
on = 0.0;
}
Double off = feedRepository.countByUserAndDateAndIsChecked(user, today, true) / feedRepository.countByUserAndDate(user, today).doubleValue();
if(off.isNaN()) {
off = 0.0;
}

WeekFields weekFields = WeekFields.of(DayOfWeek.MONDAY, 1);
Integer weekOfMonth = today.get(weekFields.weekOfMonth());

List<Double> weekStats = new ArrayList<>();
LocalDate monday = today.minusDays(today.getDayOfWeek().getValue() - 1);
for (int i=0; i<7; i++){
if(i > today.getDayOfWeek().getValue() - 1){
weekStats.add(0.0);
continue;
}
LocalDate date = monday.plusDays(i);
Double offW = feedRepository.countByUserAndDateAndIsChecked(user, date, true) / feedRepository.countByUserAndDate(user, date).doubleValue();
if(offW.isNaN()){
offW = 0.0;
}

weekStats.add(offW);
}

return StatsConverter.getWeekStatsDTO(today, on, off, weekOfMonth, weekStats);
}

@Override
public StatsResponseDTO.MonthDTO getMonthStats(LocalDate date){
if(date == null){
date = LocalDate.now();
}

Double avg = 0.0;

User user = UserContext.getUser();

List<StatsResponseDTO.MonthStatsDTO> monthStatsList = new ArrayList<>();
LocalDate localDate = date.minusDays(date.getDayOfMonth() - 1);
for(int i=0; i<date.lengthOfMonth(); i++){
int rate =0;

Memoir memoir = memoirRepository.findByUserAndDate(user, localDate.plusDays(i)).orElse(null);
if(memoir == null){
StatsResponseDTO.MonthStatsDTO stats = StatsResponseDTO.MonthStatsDTO.builder()
.date(localDate.plusDays(i))
.rate(0.0)
.build();
monthStatsList.add(stats);
continue;
}

if(memoir.getEmoticon() != null){
rate++;
}

List<MemoirAnswer> memoirAnswerList = memoirAnswerRepository.findAllByMemoirId(memoir.getId()).stream().toList();
for(MemoirAnswer memoirAnswer: memoirAnswerList){
if(memoirAnswer.getAnswer() != null){
rate++;
}
}

StatsResponseDTO.MonthStatsDTO stats = StatsResponseDTO.MonthStatsDTO.builder()
.date(localDate.plusDays(i))
.rate(rate / 4.0)
.build();
monthStatsList.add(stats);

avg += rate / 4.0 * 100;
}

if(date.equals(LocalDate.now())){
//이번달은 오늘 기준으로 계산
avg = avg / date.getDayOfMonth();
}
else{
//이외에는 한 달 기준으로 계산
avg = avg / date.lengthOfMonth();
}

return StatsConverter.getMonthStatsDTO(date, Integer.parseInt(String.valueOf(Math.round(avg))), monthStatsList);
}
}

0 comments on commit 6642f48

Please sign in to comment.