#26 pharmacy: direction service - haversine formula

This commit is contained in:
haerong22
2022-12-15 00:36:09 +09:00
parent dcabb4c55a
commit 669e29704e
4 changed files with 159 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
package com.example.road.direction.entity;
import com.example.road.BaseTimeEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity(name = "direction")
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Getter
public class Direction extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// 고객
private String inputAddress;
private double inputLatitude;
private double inputLongitude;
// 약국
private String targetPharmacyName;
private String targetAddress;
private double targetLatitude;
private double targetLongitude;
// 거리
private double distance;
}

View File

@@ -0,0 +1,66 @@
package com.example.road.direction.service;
import com.example.road.api.dto.DocumentDto;
import com.example.road.direction.entity.Direction;
import com.example.road.pharmacy.service.PharmacySearchService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Slf4j
@Service
@RequiredArgsConstructor
public class DirectionService {
private static final int MAX_SEARCH_COUNT = 3;
private static final double RADIUS_KM = 10.0;
private final PharmacySearchService pharmacySearchService;
public List<Direction> buildDirectionList(DocumentDto documentDto) {
if (Objects.isNull(documentDto)) {
return Collections.emptyList();
}
return pharmacySearchService.searchPharmacyDtoList()
.stream().map(pharmacyDto ->
Direction.builder()
.inputAddress(documentDto.getAddressName())
.inputLatitude(documentDto.getLatitude())
.inputLongitude(documentDto.getLongitude())
.targetPharmacyName(pharmacyDto.getPharmacyName())
.targetAddress(pharmacyDto.getPharmacyAddress())
.targetLatitude(pharmacyDto.getLatitude())
.targetLongitude(pharmacyDto.getLongitude())
.distance(
calculateDistance(
documentDto.getLatitude(), documentDto.getLongitude(),
pharmacyDto.getLatitude(), pharmacyDto.getLongitude()
)
)
.build()
)
.filter(direction -> direction.getDistance() <= RADIUS_KM)
.sorted(Comparator.comparing(Direction::getDistance))
.limit(MAX_SEARCH_COUNT)
.collect(Collectors.toList());
}
// Haversine formula
private double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
lat1 = Math.toRadians(lat1);
lon1 = Math.toRadians(lon1);
lat2 = Math.toRadians(lat2);
lon2 = Math.toRadians(lon2);
double earthRadius = 6371; //Kilometers
return earthRadius * Math.acos(Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2));
}
}

View File

@@ -0,0 +1,19 @@
package com.example.road.pharmacy.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class PharmacyDto {
private Long id;
private String pharmacyName;
private String pharmacyAddress;
private double latitude;
private double longitude;
}

View File

@@ -0,0 +1,36 @@
package com.example.road.pharmacy.service;
import com.example.road.pharmacy.dto.PharmacyDto;
import com.example.road.pharmacy.entity.Pharmacy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Service
@RequiredArgsConstructor
public class PharmacySearchService {
private final PharmacyRepositoryService pharmacyRepositoryService;
public List<PharmacyDto> searchPharmacyDtoList() {
return pharmacyRepositoryService.findAll()
.stream()
.map(this::convertToPharmacyDto)
.collect(Collectors.toList());
}
private PharmacyDto convertToPharmacyDto(Pharmacy pharmacy) {
return PharmacyDto.builder()
.id(pharmacy.getId())
.pharmacyAddress(pharmacy.getPharmacyAddress())
.pharmacyName(pharmacy.getPharmacyName())
.latitude(pharmacy.getLatitude())
.longitude(pharmacy.getLongitude())
.build();
}
}