Skip to content

Commit

Permalink
Fix: 평균페이스를 서버에서 계산하도록 수정 (#259)
Browse files Browse the repository at this point in the history
* Feat: RunningRecordMetricsDtoForAdd 추가

- 기존 RunningRecordMetricsDto에서 평균 페이스 필드 값이 없는 DTO

* Feat: 러닝 저장 시 평균페이스 계산해서 정장하는 것으로 수정

- 평균페이스 계산 함수 추가
- 저장 시 평균페이스 계산 함수 호출 후 평균페이스 계산해서 저장

* Test: 러닝의 평균 페이스가 올바르게 계산되었는지 확인

* Rename: ~DtoForAdd에서 이름 ~ForAddDto로 파일명 변경

* Fix: 평균페이스 계산 로직 서비스 단에서 Pace의 from() 메서드로 이동

* Fix: 거리, 러닝 시간이 0일 경우 Pace(0, 0)으로 지정
  • Loading branch information
hee9841 authored Oct 14, 2024
1 parent ea23065 commit 17dbdc4
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.dnd.runus.domain.challenge.achievement.ChallengeAchievementRecord;
import com.dnd.runus.domain.challenge.achievement.ChallengeAchievementRepository;
import com.dnd.runus.domain.common.Coordinate;
import com.dnd.runus.domain.common.Pace;
import com.dnd.runus.domain.goalAchievement.GoalAchievement;
import com.dnd.runus.domain.goalAchievement.GoalAchievementRepository;
import com.dnd.runus.domain.level.Level;
Expand Down Expand Up @@ -179,7 +180,9 @@ public RunningRecordAddResultResponse addRunningRecord(long memberId, RunningRec
.distanceMeter(request.runningData().distanceMeter())
.duration(request.runningData().runningTime())
.calorie(request.runningData().calorie())
.averagePace(request.runningData().averagePace())
.averagePace(Pace.from(
request.runningData().distanceMeter(),
request.runningData().runningTime()))
.route(route)
.build());

Expand Down
16 changes: 16 additions & 0 deletions src/main/java/com/dnd/runus/domain/common/Pace.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;

import java.time.Duration;

import static com.dnd.runus.global.constant.MetricsConversionFactor.METERS_IN_A_KILOMETER;
import static com.dnd.runus.global.constant.MetricsConversionFactor.SECONDS_PER_MINUTE;

/**
Expand All @@ -26,6 +29,19 @@ public static Pace ofSeconds(int seconds) {
return new Pace(minute, second);
}

public static Pace from(int distanceMeter, Duration runningTime) {
if (distanceMeter == 0 || runningTime.equals(Duration.ZERO)) {
return new Pace(0, 0);
}

double paceOfSecondPerMeter = (double) runningTime.toSeconds() / distanceMeter;
double paceOfMinutePerKilometer = (paceOfSecondPerMeter * METERS_IN_A_KILOMETER) / SECONDS_PER_MINUTE;
int minute = (int) Math.floor(paceOfMinutePerKilometer);
int second = (int) Math.floor((paceOfMinutePerKilometer - minute) * SECONDS_PER_MINUTE);

return new Pace(minute, second);
}

@JsonCreator
public static Pace from(String pace) {
// e.g. 5'30" or 5’30”
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.dnd.runus.presentation.v1.running.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import java.time.Duration;

public record RunningRecordMetricsForAddDto(
@Schema(description = "멈춘 시간을 제외한 실제로 달린 시간", example = "123:45:56", format = "HH:mm:ss")
Duration runningTime,
@Schema(description = "달린 거리(m)", example = "1000")
int distanceMeter,
@Schema(description = "소모 칼로리(kcal)", example = "100")
double calorie
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.dnd.runus.global.constant.RunningEmoji;
import com.dnd.runus.global.exception.BusinessException;
import com.dnd.runus.global.exception.type.ErrorType;
import com.dnd.runus.presentation.v1.running.dto.RunningRecordMetricsDto;
import com.dnd.runus.presentation.v1.running.dto.RunningRecordMetricsForAddDto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
Expand Down Expand Up @@ -34,7 +34,7 @@ public record RunningRecordRequest(
@Schema(description = "목표 달성 모드, normal: 목표 설정X, challenge: 챌린지, goal: 개인 목표")
RunningAchievementMode achievementMode,
@NotNull
RunningRecordMetricsDto runningData
RunningRecordMetricsForAddDto runningData
) {
public RunningRecordRequest {
if (startAt.isAfter(endAt)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import com.dnd.runus.global.constant.MemberRole;
import com.dnd.runus.global.constant.RunningEmoji;
import com.dnd.runus.global.exception.NotFoundException;
import com.dnd.runus.presentation.v1.running.dto.RunningRecordMetricsDto;
import com.dnd.runus.presentation.v1.running.dto.RunningRecordMetricsForAddDto;
import com.dnd.runus.presentation.v1.running.dto.request.RunningAchievementMode;
import com.dnd.runus.presentation.v1.running.dto.request.RunningRecordRequest;
import com.dnd.runus.presentation.v1.running.dto.request.RunningRecordWeeklySummaryType;
Expand Down Expand Up @@ -209,7 +209,7 @@ void addRunningRecord_challenge() {
null,
null,
RunningAchievementMode.CHALLENGE,
new RunningRecordMetricsDto(new Pace(5, 30), Duration.ofSeconds(10_100), 10_000, 500.0));
new RunningRecordMetricsForAddDto(Duration.ofSeconds(10_100), 10_000, 500.0));

Member member = new Member(MemberRole.USER, "nickname1");
RunningRecord expected = createRunningRecord(request, member);
Expand Down Expand Up @@ -249,7 +249,7 @@ void addRunningRecord_goal_time_success() {
null,
1200,
RunningAchievementMode.GOAL,
new RunningRecordMetricsDto(new Pace(5, 30), Duration.ofSeconds(10_100), 10_000, 500.0));
new RunningRecordMetricsForAddDto(Duration.ofSeconds(10_100), 10_000, 500.0));

Member member = new Member(MemberRole.USER, "nickname1");
RunningRecord expected = createRunningRecord(request, member);
Expand Down Expand Up @@ -288,7 +288,7 @@ void addRunningRecord_goal_time_fail() {
null,
20_000,
RunningAchievementMode.GOAL,
new RunningRecordMetricsDto(new Pace(5, 30), Duration.ofSeconds(10_100), 10_000, 500.0));
new RunningRecordMetricsForAddDto(Duration.ofSeconds(10_100), 10_000, 500.0));

Member member = new Member(MemberRole.USER, "nickname1");
RunningRecord expected = createRunningRecord(request, member);
Expand Down Expand Up @@ -327,7 +327,7 @@ void addRunningRecord_goal_distance() {
5_000,
null,
RunningAchievementMode.GOAL,
new RunningRecordMetricsDto(new Pace(5, 30), Duration.ofSeconds(10_100), 10_000, 500.0));
new RunningRecordMetricsForAddDto(Duration.ofSeconds(10_100), 10_000, 500.0));

Member member = new Member(MemberRole.USER, "nickname1");
RunningRecord expected = createRunningRecord(request, member);
Expand Down Expand Up @@ -366,7 +366,7 @@ void addRunningRecord_goal_distance_same_value() {
10_000,
null,
RunningAchievementMode.GOAL,
new RunningRecordMetricsDto(new Pace(5, 30), Duration.ofSeconds(10_100), 10_000, 500.0));
new RunningRecordMetricsForAddDto(Duration.ofSeconds(10_100), 10_000, 500.0));

Member member = new Member(MemberRole.USER, "nickname1");
RunningRecord expected = createRunningRecord(request, member);
Expand All @@ -390,6 +390,35 @@ void addRunningRecord_goal_distance_same_value() {
assertTrue(response.goal().isSuccess());
}

@Test
@DisplayName("러닝의 페이스가 올바르게 계산되었는지 확인한다.")
void addRunningRecord_check_cal_pace() {
// given
RunningRecordRequest request = new RunningRecordRequest(
LocalDateTime.of(2021, 1, 1, 12, 10, 30),
LocalDateTime.of(2021, 1, 1, 13, 12, 10),
"start location",
"end location",
RunningEmoji.VERY_GOOD,
null,
null,
null,
RunningAchievementMode.NORMAL,
new RunningRecordMetricsForAddDto(Duration.ofSeconds(1_668), 3_280, 500.0));

Member member = new Member(MemberRole.USER, "nickname1");
RunningRecord expected = createRunningRecord(request, member);

given(memberRepository.findById(1L)).willReturn(Optional.of(member));
given(runningRecordRepository.save(expected)).willReturn(expected);

// when
RunningRecordAddResultResponse response = runningRecordService.addRunningRecord(1L, request);

// then
assertEquals(new Pace(8, 28), response.runningData().averagePace());
}

@Test
@DisplayName("이번 달, 달린 키로 수, 러닝 레벨을 조회한다.")
void getMonthlyRunningSummery() {
Expand Down Expand Up @@ -494,6 +523,7 @@ void getWeeklySummary_Duration() {
}

private RunningRecord createRunningRecord(RunningRecordRequest request, Member member) {

return RunningRecord.builder()
.member(member)
.startAt(request.startAt().atZone(defaultZoneOffset))
Expand All @@ -504,7 +534,9 @@ private RunningRecord createRunningRecord(RunningRecordRequest request, Member m
.distanceMeter(request.runningData().distanceMeter())
.duration(request.runningData().runningTime())
.calorie(request.runningData().calorie())
.averagePace(request.runningData().averagePace())
.averagePace(Pace.from(
request.runningData().distanceMeter(),
request.runningData().runningTime()))
.route(List.of(new Coordinate(0, 0, 0), new Coordinate(0, 0, 0)))
.build();
}
Expand Down

0 comments on commit 17dbdc4

Please sign in to comment.