Skip to content

Commit

Permalink
Merge pull request #43 from AmorGakCo/feat/#42
Browse files Browse the repository at this point in the history
Feat/#42
  • Loading branch information
songhaechan authored Sep 7, 2024
2 parents b31ff93 + b2d364a commit 5357264
Show file tree
Hide file tree
Showing 17 changed files with 305 additions and 68 deletions.
36 changes: 18 additions & 18 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -523,8 +523,8 @@ <h4 id="_그룹_등록_http_request"><a class="link" href="#_그룹_등록_http_
"name" : "AmorGakCo",
"description" : "모각코 합시다.",
"groupCapacity" : 3,
"beginAt" : "2024-08-27T23:28:12.865485",
"endAt" : "2024-08-28T02:28:12.865485",
"beginAt" : "2024-09-04T16:57:22.301368",
"endAt" : "2024-09-04T19:57:22.301368",
"latitude" : 37.5703901,
"longitude" : 126.9748397,
"address" : "서울특별시 종로구 신문로1가 23"
Expand Down Expand Up @@ -604,8 +604,8 @@ <h4 id="_그룹_단건_조회_모달창용_http_response"><a class="link" href="
"data" : {
"hostNickname" : "아모르겠고",
"hostImgUrl" : "https://fakeimg",
"beginAt" : "2024-08-27T23:28:12.711933",
"endAt" : "2024-08-28T02:28:12.711938",
"beginAt" : "2024-09-04T16:57:22.149485",
"endAt" : "2024-09-04T19:57:22.149489",
"groupCapacity" : 3,
"currentParticipants" : 3,
"address" : "서울특별시 종로구 신문로1가 23"
Expand Down Expand Up @@ -697,8 +697,8 @@ <h4 id="_그룹_단건_조회_상세페이지용_http_response"><a class="link"
"address" : "서울특별시 종로구 신문로1가 23",
"longitude" : 126.9748397,
"latitude" : 37.5703901,
"beginAt" : "2024-08-27T23:28:12.711933",
"endAt" : "2024-08-28T02:28:12.711938",
"beginAt" : "2024-09-04T16:57:22.149485",
"endAt" : "2024-09-04T19:57:22.149489",
"groupMembers" : [ {
"memberId" : 2,
"imgUrl" : "https://fakeimg",
Expand Down Expand Up @@ -1098,39 +1098,39 @@ <h4 id="_참여자의_모각코_참여_내역_http_response"><a class="link" hre
"groupId" : 4,
"name" : "AmorGakCo",
"address" : "서울특별시 종로구 신문로1가 23",
"beginAt" : "2024-08-27T23:28:15.06035",
"endAt" : "2024-08-28T02:28:15.060362"
"beginAt" : "2024-09-04T16:57:24.40491",
"endAt" : "2024-09-04T19:57:24.404916"
}, {
"groupId" : 5,
"name" : "AmorGakCo",
"address" : "서울특별시 종로구 신문로1가 23",
"beginAt" : "2024-08-27T23:28:15.06035",
"endAt" : "2024-08-28T02:28:15.060362"
"beginAt" : "2024-09-04T16:57:24.40491",
"endAt" : "2024-09-04T19:57:24.404916"
}, {
"groupId" : 6,
"name" : "AmorGakCo",
"address" : "서울특별시 종로구 신문로1가 23",
"beginAt" : "2024-08-27T23:28:15.06035",
"endAt" : "2024-08-28T02:28:15.060362"
"beginAt" : "2024-09-04T16:57:24.40491",
"endAt" : "2024-09-04T19:57:24.404916"
} ],
"InactivatedGroup" : [ {
"groupId" : 1,
"name" : "AmorGakCo",
"address" : "서울특별시 종로구 신문로1가 23",
"beginAt" : "2024-08-27T23:28:15.06035",
"endAt" : "2024-08-28T02:28:15.060362"
"beginAt" : "2024-09-04T16:57:24.40491",
"endAt" : "2024-09-04T19:57:24.404916"
}, {
"groupId" : 2,
"name" : "AmorGakCo",
"address" : "서울특별시 종로구 신문로1가 23",
"beginAt" : "2024-08-27T23:28:15.06035",
"endAt" : "2024-08-28T02:28:15.060362"
"beginAt" : "2024-09-04T16:57:24.40491",
"endAt" : "2024-09-04T19:57:24.404916"
}, {
"groupId" : 3,
"name" : "AmorGakCo",
"address" : "서울특별시 종로구 신문로1가 23",
"beginAt" : "2024-08-27T23:28:15.06035",
"endAt" : "2024-08-28T02:28:15.060362"
"beginAt" : "2024-09-04T16:57:24.40491",
"endAt" : "2024-09-04T19:57:24.404916"
} ]
}
}</code></pre>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ public enum ErrorCode {
VERIFICATION_DUPLICATED("309", "이미 인증이 완료된 회원입니다."),
PARTICIPANT_DUPLICATED("310", "중복된 회원입니다."),
EXCEED_GROUP_CAPACITY("311", "그룹 수용 인원을 초과합니다."),
PARTICIPATION_NOT_FOUND("312", "참여 요청을 조회할 수 없습니다.");
PARTICIPATION_NOT_FOUND("312", "참여 요청을 조회할 수 없습니다."),
INVALID_DIAGONAL_DISTANCE("313", "잘못된 그룹 검색 요청입니다. 위도 경도를 확인해주세요.");

private final String code;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,8 @@ public static IllegalAccessException duplicatedParticipant() {
public static IllegalAccessException exceedGroupCapacity() {
return new IllegalAccessException(ErrorCode.PARTICIPANT_DUPLICATED);
}

public static IllegalAccessException invalidDiagonalDistance() {
return new IllegalAccessException(ErrorCode.INVALID_DIAGONAL_DISTANCE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ public class GroupLocationController {
@GetMapping("/locations")
public GroupSearchResponse getLocations(
@ModelAttribute final GroupSearchRequest groupSearchRequest) {
return groupLocationService.getNearByGroups(groupSearchRequest);
return groupLocationService.findGroups(groupSearchRequest);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
import com.amorgakco.backend.group.dto.GroupSearchResponse;

public interface GroupLocationService {
GroupSearchResponse getNearByGroups(final GroupSearchRequest request);
GroupSearchResponse findGroups(final GroupSearchRequest request);
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
package com.amorgakco.backend.group.service;

import com.amorgakco.backend.global.GoogleS2Const;
import com.amorgakco.backend.group.dto.GroupSearchRequest;
import com.amorgakco.backend.group.dto.GroupSearchResponse;
import com.amorgakco.backend.group.repository.GroupRepository;
import com.amorgakco.backend.group.service.mapper.GroupMapper;
import com.google.common.geometry.S2CellId;
import com.google.common.geometry.S2LatLng;
import com.google.common.geometry.S2LatLngRect;
import com.google.common.geometry.S2RegionCoverer;
import com.amorgakco.backend.group.service.search.S2CellSearch;

import lombok.RequiredArgsConstructor;

import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

Expand All @@ -24,27 +19,10 @@ public class S2GroupLocationService implements GroupLocationService {

private final GroupRepository groupRepository;
private final GroupMapper groupMapper;
private final S2CellSearch s2CellSearch;

public GroupSearchResponse getNearByGroups(final GroupSearchRequest request) {
final S2LatLngRect s2LatLngRect = getRectangleRegion(request);
final S2RegionCoverer coverer =
S2RegionCoverer.builder()
.setMinLevel(GoogleS2Const.S2_CELL_LEVEL.getValue())
.setMaxLevel(GoogleS2Const.S2_CELL_LEVEL.getValue())
.build();
final ArrayList<S2CellId> cellIds = new ArrayList<>();
coverer.getCovering(s2LatLngRect, cellIds);
final List<String> cellTokens = cellIds.stream().map(S2CellId::toToken).toList();
return findCells(cellTokens);
}

private S2LatLngRect getRectangleRegion(final GroupSearchRequest request) {
return S2LatLngRect.fromPointPair(
S2LatLng.fromDegrees(request.southWestLat(), request.southWestLon()),
S2LatLng.fromDegrees(request.northEastLat(), request.northEastLon()));
}

private GroupSearchResponse findCells(final List<String> cellTokens) {
public GroupSearchResponse findGroups(final GroupSearchRequest request) {
final List<String> cellTokens = s2CellSearch.getCellTokens(request);
return groupRepository.findByCellToken(cellTokens).stream()
.map(groupMapper::toGroupLocation)
.collect(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.amorgakco.backend.group.service.search;

import com.amorgakco.backend.group.dto.GroupSearchRequest;
import com.google.common.geometry.S2LatLng;
import com.google.common.geometry.S2LatLngRect;

import org.springframework.stereotype.Component;

@Component
public class CityLevelSearchStrategy extends GroupSearchStrategy {

private static final double LATITUDE_SIZE = 0.07;
private static final double LONGITUDE_SIZE = 0.14;

@Override
public boolean isValid(final double diagonalSize) {
return diagonalSize > DiagonalDistanceConst.MAX_DISTANCE.getValue();
}

@Override
public S2LatLngRect createRectangle(final GroupSearchRequest request) {
return S2LatLngRect.fromCenterSize(
S2LatLng.fromDegrees(request.centerLat(), request.centerLon()),
S2LatLng.fromDegrees(LATITUDE_SIZE, LONGITUDE_SIZE));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.amorgakco.backend.group.service.search;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum DiagonalDistanceConst {
MAX_DISTANCE(14200),
MIN_DISTANCE(7500);

private final double value;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.amorgakco.backend.group.service.search;

import com.amorgakco.backend.group.dto.GroupSearchRequest;

import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class DongLevelSearchStrategy extends GroupSearchStrategy {

@Override
public boolean isValid(final double diagonalSize) {
return diagonalSize <= DiagonalDistanceConst.MIN_DISTANCE.getValue();
}

@Override
public List<String> selectCellTokens(final GroupSearchRequest request) {
return getCoveringCells(request);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.amorgakco.backend.group.service.search;

import com.amorgakco.backend.global.GoogleS2Const;
import com.amorgakco.backend.group.dto.GroupSearchRequest;
import com.google.common.geometry.S2CellId;
import com.google.common.geometry.S2LatLng;
import com.google.common.geometry.S2LatLngRect;
import com.google.common.geometry.S2RegionCoverer;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

public abstract class GroupSearchStrategy {
public abstract boolean isValid(double diagonalSize);

public S2LatLngRect createRectangle(final GroupSearchRequest request) {
return S2LatLngRect.fromPointPair(
S2LatLng.fromDegrees(request.southWestLat(), request.southWestLon()),
S2LatLng.fromDegrees(request.northEastLat(), request.northEastLon()));
}

protected final List<String> getCoveringCells(final GroupSearchRequest request) {
final S2LatLngRect rectangle = createRectangle(request);
final S2RegionCoverer coverer =
S2RegionCoverer.builder()
.setMinLevel(GoogleS2Const.S2_CELL_LEVEL.getValue())
.setMaxLevel(GoogleS2Const.S2_CELL_LEVEL.getValue())
.build();
final ArrayList<S2CellId> cellIds = new ArrayList<>();
coverer.getCovering(rectangle, cellIds);
return cellIds.stream().map(S2CellId::toToken).toList();
}

public List<String> selectCellTokens(final GroupSearchRequest request) {
final List<String> cellTokens = getCoveringCells(request);
return findHalfOfCells(cellTokens);
}

private List<String> findHalfOfCells(final List<String> cellTokens) {
return IntStream.range(0, cellTokens.size() - 1)
.filter(i -> i % 2 == 0)
.mapToObj(cellTokens::get)
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.amorgakco.backend.group.service.search;

import org.springframework.stereotype.Component;

@Component
public class GuLevelSearchStrategy extends GroupSearchStrategy {

@Override
public boolean isValid(final double diagonalSize) {
return DiagonalDistanceConst.MIN_DISTANCE.getValue() < diagonalSize
&& diagonalSize <= DiagonalDistanceConst.MAX_DISTANCE.getValue();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.amorgakco.backend.group.service.search;

import com.amorgakco.backend.global.exception.IllegalAccessException;
import com.amorgakco.backend.group.domain.location.LocationCalculator;
import com.amorgakco.backend.group.dto.GroupSearchRequest;

import lombok.RequiredArgsConstructor;

import org.springframework.stereotype.Component;

import java.util.List;

@RequiredArgsConstructor
@Component
public class S2CellSearch {

private final List<GroupSearchStrategy> searchStrategies;

public List<String> getCellTokens(final GroupSearchRequest request) {
final double diagonalDistance = getDiagonalDistance(request);
final GroupSearchStrategy groupSearchStrategy = getSearchStrategy(diagonalDistance);
return groupSearchStrategy.selectCellTokens(request);
}

private GroupSearchStrategy getSearchStrategy(final double diagonalDistance) {
return searchStrategies.stream()
.filter(s -> s.isValid(diagonalDistance))
.findFirst()
.orElseThrow(IllegalAccessException::invalidDiagonalDistance);
}

private double getDiagonalDistance(final GroupSearchRequest request) {
return LocationCalculator.getDistance(
request.southWestLon(),
request.southWestLat(),
request.northEastLon(),
request.northEastLat());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public void loadCookie(final HttpServletResponse response, final String token) {
private ResponseCookie makeCookie(final String token) {
return ResponseCookie.from(REFRESH_COOKIE_NAME, token)
.maxAge(REFRESH_COOKIE_AGE_SECONDS)
.secure(false)
.secure(true)
.httpOnly(true)
.path("/")
.build();
Expand Down
Loading

0 comments on commit 5357264

Please sign in to comment.