forked from CSID-DGU/2024-2-OSSProj-Running-Machines-04
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
82933ac
commit 944c8b0
Showing
6 changed files
with
220 additions
and
0 deletions.
There are no files selected for viewing
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
40 changes: 40 additions & 0 deletions
40
src/backend/src/main/java/RunningMachines/R2R/domain/home/controller/HomeController.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,40 @@ | ||
package RunningMachines.R2R.domain.home.controller; | ||
|
||
import RunningMachines.R2R.domain.home.service.HomeService; | ||
import RunningMachines.R2R.domain.user.service.AuthCommandService; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
import java.util.Map; | ||
|
||
@RestController | ||
@RequestMapping("/home") | ||
@RequiredArgsConstructor | ||
public class HomeController { | ||
private final HomeService homeService; | ||
private final AuthCommandService authCommandService; | ||
|
||
@GetMapping("/user") | ||
public ResponseEntity<Map<String, Object>> getDailyUserRecords() { | ||
// 현재 로그인한 사용자 ID 가져오기 | ||
Long userId = authCommandService.getCurrentUser().getId(); | ||
// 일일 기록 데이터 가져오기 | ||
Map<String, Object> response = homeService.getDailyUserRecord(userId); | ||
return ResponseEntity.ok(response); | ||
} | ||
|
||
/** | ||
* 주간 크루 기록 조회 | ||
* @return 주간 거리 랭킹 및 페이스 랭킹 | ||
*/ | ||
@GetMapping("/crews") | ||
public ResponseEntity<Map<String, Object>> getWeeklyCrewRecords() { | ||
// 주간 크루 기록 데이터 가져오기 | ||
Map<String, Object> response = homeService.getWeeklyCrewRecords(); | ||
return ResponseEntity.ok(response); | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
src/backend/src/main/java/RunningMachines/R2R/domain/home/dto/CrewRankResponseDto.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,15 @@ | ||
package RunningMachines.R2R.domain.home.dto; | ||
|
||
import lombok.Builder; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
@Builder | ||
public class CrewRankResponseDto { | ||
private Long crewId; | ||
private String crewName; | ||
private String crewProfileUrl; | ||
private String value; | ||
private double totalDistance; | ||
private double averagePace; | ||
} |
14 changes: 14 additions & 0 deletions
14
src/backend/src/main/java/RunningMachines/R2R/domain/home/dto/HomePageResponseDto.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,14 @@ | ||
package RunningMachines.R2R.domain.home.dto; | ||
|
||
import lombok.Builder; | ||
import lombok.Getter; | ||
|
||
import java.util.List; | ||
|
||
@Getter | ||
@Builder | ||
public class HomePageResponseDto { | ||
private TodayRunResponseDto todayRun; | ||
private List<CrewRankResponseDto> topDistanseCrews; | ||
private List<CrewRankResponseDto> topPaceCrews; | ||
} |
12 changes: 12 additions & 0 deletions
12
src/backend/src/main/java/RunningMachines/R2R/domain/home/dto/TodayRunResponseDto.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,12 @@ | ||
package RunningMachines.R2R.domain.home.dto; | ||
|
||
import lombok.Builder; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
@Builder | ||
public class TodayRunResponseDto { | ||
private double totalDistance; | ||
private String averagePace; | ||
private int totalDuration; | ||
} |
128 changes: 128 additions & 0 deletions
128
src/backend/src/main/java/RunningMachines/R2R/domain/home/service/HomeService.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,128 @@ | ||
package RunningMachines.R2R.domain.home.service; | ||
|
||
import RunningMachines.R2R.domain.course.entity.UserCourse; | ||
import RunningMachines.R2R.domain.course.repository.UserCourseRepository; | ||
import RunningMachines.R2R.domain.crew.common.entity.Crew; | ||
import RunningMachines.R2R.domain.crew.common.entity.CrewUser; | ||
import RunningMachines.R2R.domain.crew.common.repository.CrewRepository; | ||
import RunningMachines.R2R.domain.user.entity.User; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.time.LocalDate; | ||
import java.time.LocalDateTime; | ||
import java.time.LocalTime; | ||
import java.time.temporal.ChronoField; | ||
import java.util.*; | ||
import java.util.stream.Collectors; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class HomeService { | ||
private final UserCourseRepository userCourseRepository; | ||
private final CrewRepository crewRepository; | ||
|
||
public Map<String, Object> getWeeklyCrewRecords() { | ||
// Define start and end of the current week | ||
LocalDateTime startOfWeek = LocalDate.now().with(ChronoField.DAY_OF_WEEK, 1).atStartOfDay(); | ||
LocalDateTime endOfWeek = startOfWeek.plusDays(6).with(LocalTime.MAX); | ||
|
||
// Fetch all crews | ||
List<Crew> crews = crewRepository.findAll(); | ||
|
||
// Calculate rankings for distance and pace | ||
List<Map<String, Object>> distanceRankings = new ArrayList<>(); | ||
List<Map<String, Object>> paceRankings = new ArrayList<>(); | ||
|
||
for (Crew crew : crews) { | ||
// Get all users in the crew | ||
List<User> crewUsers = crew.getCrewUsers().stream() | ||
.map(cu -> cu.getUser()) | ||
.collect(Collectors.toList()); | ||
|
||
// Calculate total distance and total duration | ||
double totalDistance = crewUsers.stream() | ||
.flatMap(user -> userCourseRepository.findByUserIdAndDateRange(user.getId(), startOfWeek, endOfWeek).stream()) | ||
.mapToDouble(UserCourse::getDistance) | ||
.sum(); | ||
|
||
int totalDuration = crewUsers.stream() | ||
.flatMap(user -> userCourseRepository.findByUserIdAndDateRange(user.getId(), startOfWeek, endOfWeek).stream()) | ||
.mapToInt(UserCourse::getDuration) | ||
.sum(); | ||
|
||
String averagePace = formatPace(totalDistance, totalDuration); | ||
|
||
// Add to distance ranking | ||
Map<String, Object> distanceRanking = new HashMap<>(); | ||
distanceRanking.put("crewId", crew.getId()); | ||
distanceRanking.put("title", crew.getTitle()); | ||
distanceRanking.put("image", crew.getImages() != null ? crew.getImages().getImageUrl() : null); | ||
distanceRanking.put("distance", String.format("%.2fKM", totalDistance)); | ||
distanceRankings.add(distanceRanking); | ||
|
||
// Add to pace ranking | ||
Map<String, Object> paceRanking = new HashMap<>(); | ||
paceRanking.put("crewId", crew.getId()); | ||
paceRanking.put("title", crew.getTitle()); | ||
paceRanking.put("image", crew.getImages() != null ? crew.getImages().getImageUrl() : null); | ||
paceRanking.put("averagePace", averagePace); | ||
paceRankings.add(paceRanking); | ||
} | ||
|
||
// Sort rankings | ||
distanceRankings.sort(Comparator.comparing((Map<String, Object> m) -> Double.parseDouble(m.get("distance").toString().replace("KM", ""))).reversed()); | ||
paceRankings.sort(Comparator.comparing((Map<String, Object> m) -> parsePaceToSeconds(m.get("averagePace").toString()))); | ||
|
||
// Prepare the response | ||
Map<String, Object> response = new HashMap<>(); | ||
response.put("distanceRankings", distanceRankings.stream().limit(3).collect(Collectors.toList())); | ||
response.put("paceRankings", paceRankings.stream().limit(3).collect(Collectors.toList())); | ||
|
||
return response; | ||
} | ||
|
||
public Map<String, Object> getDailyUserRecord(Long userId) { | ||
// Define start and end of the current day | ||
LocalDateTime startOfDay = LocalDate.now().atStartOfDay(); | ||
LocalDateTime endOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MAX); | ||
|
||
// Fetch the user's daily records | ||
List<UserCourse> userCourses = userCourseRepository.findByUserIdAndDateRange(userId, startOfDay, endOfDay); | ||
|
||
// Calculate total distance, total duration, and average pace | ||
double totalDistance = userCourses.stream().mapToDouble(UserCourse::getDistance).sum(); | ||
int totalDuration = userCourses.stream().mapToInt(UserCourse::getDuration).sum(); // duration in minutes | ||
String averagePace = formatPace(totalDistance, totalDuration); | ||
|
||
// Prepare the response | ||
Map<String, Object> response = new HashMap<>(); | ||
response.put("totalDistance", String.format("%.2fKM", totalDistance)); | ||
response.put("totalDuration", formatDuration(totalDuration)); | ||
response.put("averagePace", averagePace); | ||
|
||
return response; | ||
} | ||
|
||
private String formatPace(double totalDistance, int totalDuration) { | ||
if (totalDistance <= 0) return "0'00''"; | ||
int totalSeconds = (int) (totalDuration * 60 / totalDistance); | ||
int minutes = totalSeconds / 60; | ||
int seconds = totalSeconds % 60; | ||
return String.format("%d'%02d''", minutes, seconds); | ||
} | ||
|
||
private int parsePaceToSeconds(String pace) { | ||
String[] parts = pace.split("[']"); | ||
int minutes = Integer.parseInt(parts[0]); | ||
int seconds = Integer.parseInt(parts[1].replace("''", "")); | ||
return minutes * 60 + seconds; | ||
} | ||
|
||
private String formatDuration(int totalMinutes) { | ||
int hours = totalMinutes / 60; | ||
int minutes = totalMinutes % 60; | ||
return String.format("%dh %02dm", hours, minutes); | ||
} | ||
} | ||
|