Skip to content

Commit f4b2935

Browse files
authored
Merge pull request #6 from DevKor-github/feature/midpoint-timematrix
Feature/ 중간 지점 계산 API 및 계산 로직 구현
2 parents 5b9f131 + 52656a0 commit f4b2935

19 files changed

Lines changed: 530 additions & 37 deletions

build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,14 @@ dependencies {
2727
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
2828
implementation 'org.springframework.boot:spring-boot-starter-security'
2929
implementation 'org.springframework.boot:spring-boot-starter-web'
30+
implementation 'org.springframework.boot:spring-boot-starter-webflux'
3031
compileOnly 'org.projectlombok:lombok'
3132
runtimeOnly 'com.mysql:mysql-connector-j'
3233
annotationProcessor 'org.projectlombok:lombok'
3334
testImplementation 'org.springframework.boot:spring-boot-starter-test'
3435
testImplementation 'org.springframework.security:spring-security-test'
36+
testImplementation 'org.mockito:mockito-core:5.11.0'
37+
testImplementation 'org.mockito:mockito-junit-jupiter:5.11.0'
3538
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
3639
implementation 'org.mapstruct:mapstruct:1.5.5.Final'
3740
annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final'

src/main/java/com/ODG/ODG_back/controller/MidpointController.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.ODG.ODG_back.controller;
22

3+
import com.ODG.ODG_back.dto.midpoint.response.MidpointResponseDto;
34
import com.ODG.ODG_back.service.MidpointService;
45
import com.ODG.ODG_back.strategy.MidpointStrategyType;
56
import lombok.RequiredArgsConstructor;
@@ -14,8 +15,8 @@ public class MidpointController {
1415
private final MidpointService midpointService;
1516

1617
@GetMapping
17-
public ResponseEntity<?>getRecommendedMidpoints(@PathVariable String inviteCode,
18-
@RequestParam MidpointStrategyType strategyType) {
18+
public ResponseEntity<MidpointResponseDto> getRecommendedMidpoints(@PathVariable String inviteCode,
19+
@RequestParam MidpointStrategyType strategyType) {
1920
return ResponseEntity.ok(midpointService.getRecommendedMidpoints(inviteCode, strategyType));
2021
}
2122

src/main/java/com/ODG/ODG_back/domain/Midpoint.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
package com.ODG.ODG_back.domain;
22

33
import jakarta.persistence.*;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Getter;
7+
import lombok.NoArgsConstructor;
48

59
import java.math.BigDecimal;
610
import java.util.List;
711

812
@Entity
13+
@Getter
14+
@Builder
15+
@NoArgsConstructor
16+
@AllArgsConstructor
917
public class Midpoint {
1018

1119
@Id

src/main/java/com/ODG/ODG_back/domain/Participant.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public class Participant {
3131

3232
private BigDecimal latitude;
3333
private BigDecimal longitude;
34-
34+
3535
@ManyToOne
3636
private Meeting meeting;
3737
}

src/main/java/com/ODG/ODG_back/domain/RecommendedMidpoint.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
import jakarta.persistence.*;
44
import lombok.Getter;
5+
import lombok.NoArgsConstructor;
56

67
import java.time.LocalDateTime;
78

89
@Entity
910
@Getter
11+
@NoArgsConstructor
1012
public class RecommendedMidpoint {
1113

1214
@Id
@@ -24,4 +26,13 @@ public class RecommendedMidpoint {
2426

2527
@ManyToOne
2628
private Midpoint midpoint;
29+
30+
public RecommendedMidpoint(Long id, double score, int rank, LocalDateTime recommendedAt, Meeting meeting, Midpoint midpoint) {
31+
this.id = id;
32+
this.score = score;
33+
this.rank = rank;
34+
this.recommendedAt = recommendedAt;
35+
this.meeting = meeting;
36+
this.midpoint = midpoint;
37+
}
2738
}
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package com.ODG.ODG_back.external.google;
22

3-
import java.math.BigDecimal;
3+
import com.ODG.ODG_back.domain.enums.TransportType;
4+
45
import java.util.List;
56

67
public interface GoogleMatrixApiClient {
7-
int[][] getTimeMatrix(List<List<BigDecimal>> origins, List<List<BigDecimal>> destinations);
8+
int[][] getTimeMatrix(List<String> origins, List<String> destinations, TransportType transport);
89
}
Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,55 @@
11
package com.ODG.ODG_back.external.google;
22

3+
import com.ODG.ODG_back.domain.enums.TransportType;
34
import org.springframework.beans.factory.annotation.Value;
45
import org.springframework.stereotype.Component;
5-
import org.springframework.web.client.RestTemplate;
6+
import org.springframework.web.reactive.function.client.WebClient;
67

7-
import java.math.BigDecimal;
88
import java.util.List;
9+
import java.util.Map;
10+
11+
import static com.ODG.ODG_back.external.google.parser.GoogleMatrixResponseParser.parseTimeMatrix;
912

1013
@Component("googleMatrixApiClient")
1114
public class GoogleMatrixApiClientImpl implements GoogleMatrixApiClient {
1215

13-
@Value("{google.api.key}")
14-
private String googleApiKey;
16+
private final String googleApiKey;
17+
private final WebClient webClient;
1518

16-
private final RestTemplate restTemplate = new RestTemplate();
19+
public GoogleMatrixApiClientImpl(WebClient.Builder builder, @Value("${google.api.key}") String googleApiKey) {
20+
this.webClient = builder.build();
21+
this.googleApiKey = googleApiKey;
22+
}
1723

1824
@Override
19-
public int[][] getTimeMatrix(List<List<BigDecimal>> origins, List<List<BigDecimal>> destinations) {
20-
return new int[0][];
25+
public int[][] getTimeMatrix(List<String> origins, List<String> destinations, TransportType transport) {
26+
27+
String url = buildUrl(origins, destinations, transport);
28+
Map<String, Object> response = fetchApiResponse(url);
29+
30+
return parseTimeMatrix(response, origins.size(), destinations.size());
31+
}
32+
33+
private String buildUrl(List<String> origins, List<String> destinations, TransportType transport) {
34+
35+
String originsParam = String.join("|", origins);
36+
String destinationsParam = String.join("|", destinations);
37+
String mode = transport == TransportType.CAR ? "driving" : "transit";
38+
39+
String url = String.format(
40+
"https://maps.googleapis.com/maps/api/distancematrix/json?" +
41+
"origins=%s&destinations=%s&mode=%s&key=%s",
42+
originsParam, destinationsParam, mode, googleApiKey
43+
);
44+
45+
return url;
46+
}
47+
48+
private Map<String, Object> fetchApiResponse(String url) {
49+
return webClient.get()
50+
.uri(url)
51+
.retrieve()
52+
.bodyToMono(Map.class)
53+
.block();
2154
}
2255
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.ODG.ODG_back.external.google.parser;
2+
3+
import java.util.List;
4+
import java.util.Map;
5+
6+
public class GoogleMatrixResponseParser {
7+
public static int[][] parseTimeMatrix(Map<String, Object> response, int originSize, int destinationSize) {
8+
List<Map<String, Object>> rows = (List<Map<String, Object>>) response.get("rows");
9+
10+
int[][] timeMatrix = new int[originSize][destinationSize];
11+
12+
for (int i = 0; i < originSize; i++) {
13+
Map<String, Object> row = rows.get(i);
14+
List<Map<String, Object>> elements = (List<Map<String, Object>>) row.get("elements");
15+
16+
for (int j = 0; j < destinationSize; j++) {
17+
Map<String, Object> element = elements.get(j);
18+
Map<String, Object> duration = (Map<String, Object>) element.get("duration");
19+
20+
if (duration != null) {
21+
timeMatrix[i][j] = (int) duration.get("value");
22+
} else {
23+
timeMatrix[i][j] = Integer.MAX_VALUE; // unreachable destination
24+
}
25+
}
26+
}
27+
return timeMatrix;
28+
}
29+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.ODG.ODG_back.mapper;
2+
3+
import com.ODG.ODG_back.domain.Midpoint;
4+
import com.ODG.ODG_back.dto.midpoint.response.MidpointResponseDto;
5+
import org.mapstruct.Mapper;
6+
import org.mapstruct.Mapping;
7+
8+
@Mapper(componentModel = "spring")
9+
public interface MidpointMapper {
10+
11+
@Mapping(source = "id", target = "midpointId")
12+
MidpointResponseDto toDto(Midpoint midpoint);
13+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.ODG.ODG_back.repository;
2+
3+
import com.ODG.ODG_back.domain.Midpoint;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
6+
public interface MidpointRepository extends JpaRepository<Midpoint, Long> {
7+
}

0 commit comments

Comments
 (0)