Skip to content

Commit c82a097

Browse files
committed
feat: 매칭 필터 ID 기반 관리 추가
1 parent 8f5ef21 commit c82a097

8 files changed

Lines changed: 634 additions & 18 deletions

File tree

src/main/java/com/example/rightbackend/matching/filter/controller/MatchingFilterController.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
import com.example.rightbackend.global.response.SuccessResponse;
66
import com.example.rightbackend.global.response.success.MatchingFilterSuccess;
77
import com.example.rightbackend.matching.filter.controller.dto.request.MatchingFilterRequest;
8+
import com.example.rightbackend.matching.filter.controller.dto.request.MatchingFilterIdsRequest;
89
import com.example.rightbackend.matching.filter.controller.dto.response.MatchingFilterResponse;
10+
import com.example.rightbackend.matching.filter.controller.dto.response.MatchingFilterIdsResponse;
911
import com.example.rightbackend.matching.filter.domain.MatchingFilter;
1012
import com.example.rightbackend.matching.filter.service.MatchingFilterService;
1113
import lombok.RequiredArgsConstructor;
@@ -32,4 +34,18 @@ public ResponseEntity<SuccessResponse<MatchingFilterResponse>> createOrUpdateMat
3234
MatchingFilter matchingFilter = matchingFilterService.createOrUpdateMatchingFilter(loginMember, request);
3335
return SuccessResponse.of(MatchingFilterSuccess.UPDATE_MATCHING_FILTER_SUCCESS, MatchingFilterResponse.from(matchingFilter));
3436
}
37+
38+
@GetMapping("/v2")
39+
public ResponseEntity<SuccessResponse<MatchingFilterIdsResponse>> getMatchingFilterWithIds(@Login LoginMember loginMember) {
40+
MatchingFilter matchingFilter = matchingFilterService.getMatchingFilter(loginMember);
41+
return SuccessResponse.of(MatchingFilterSuccess.GET_MATCHING_FILTER_SUCCESS, MatchingFilterIdsResponse.from(matchingFilter));
42+
}
43+
44+
@PostMapping("/v2")
45+
public ResponseEntity<SuccessResponse<MatchingFilterIdsResponse>> createOrUpdateMatchingFilterWithIds(
46+
@Login LoginMember loginMember,
47+
@RequestBody MatchingFilterIdsRequest request) {
48+
MatchingFilter matchingFilter = matchingFilterService.createOrUpdateMatchingFilterWithIds(loginMember, request);
49+
return SuccessResponse.of(MatchingFilterSuccess.UPDATE_MATCHING_FILTER_SUCCESS, MatchingFilterIdsResponse.from(matchingFilter));
50+
}
3551
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.example.rightbackend.matching.filter.controller.dto.request;
2+
3+
import java.util.List;
4+
import java.util.Map;
5+
6+
public record MatchingFilterIdsRequest(
7+
Integer minAge,
8+
Integer maxAge,
9+
Map<String, List<Integer>> idealFaceFeatureIds,
10+
Long regionId
11+
) {
12+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package com.example.rightbackend.matching.filter.controller.dto.response;
2+
3+
import com.example.rightbackend.matching.filter.domain.MatchingFilter;
4+
import com.example.rightbackend.matching.filter.domain.Region;
5+
import com.example.rightbackend.matching.filter.service.IdealFaceFeatureUtil;
6+
7+
import java.math.BigInteger;
8+
import java.util.List;
9+
import java.util.Map;
10+
11+
public record MatchingFilterIdsResponse(
12+
Long id,
13+
Integer minAge,
14+
Integer maxAge,
15+
BigInteger idealFaceFeaturesBitmask,
16+
Map<String, List<Integer>> idealFaceFeatureIds,
17+
List<FeatureWithId> idealFaceFeatures,
18+
RegionDto region
19+
) {
20+
public static MatchingFilterIdsResponse from(MatchingFilter matchingFilter) {
21+
RegionDto regionDto = null;
22+
if (matchingFilter.getRegion() != null) {
23+
regionDto = new RegionDto(
24+
matchingFilter.getRegion().getId(),
25+
matchingFilter.getRegion().getName()
26+
);
27+
}
28+
29+
Map<String, List<Integer>> featureIds = IdealFaceFeatureUtil.convertBitmaskToIds(matchingFilter.getIdealFaceFeaturesBitmask());
30+
31+
List<FeatureWithId> featuresWithIds = IdealFaceFeatureUtil.getFeatureInfosFromBitmask(matchingFilter.getIdealFaceFeaturesBitmask())
32+
.stream()
33+
.map(info -> new FeatureWithId(
34+
info.category(),
35+
info.code(),
36+
info.name(),
37+
info.index(),
38+
info.featureId()
39+
))
40+
.toList();
41+
42+
return new MatchingFilterIdsResponse(
43+
matchingFilter.getId(),
44+
matchingFilter.getMinAge(),
45+
matchingFilter.getMaxAge(),
46+
matchingFilter.getIdealFaceFeaturesBitmask(),
47+
featureIds,
48+
featuresWithIds,
49+
regionDto
50+
);
51+
}
52+
53+
public record RegionDto(
54+
Long id,
55+
String name
56+
) {
57+
public static RegionDto from(Region region) {
58+
return new RegionDto(
59+
region.getId(),
60+
region.getName()
61+
);
62+
}
63+
}
64+
65+
public record FeatureWithId(
66+
String category,
67+
String code,
68+
String name,
69+
int index,
70+
int featureId
71+
) {}
72+
}

src/main/java/com/example/rightbackend/matching/filter/service/IdealFaceFeatureUtil.java

Lines changed: 135 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,97 +7,147 @@
77
import java.util.HashMap;
88
import java.util.List;
99
import java.util.Map;
10+
import java.util.stream.Collectors;
1011

1112
public class IdealFaceFeatureUtil {
1213

1314
private static final Map<String, Integer> featureIndexMap = new HashMap<>();
1415
private static final List<FeatureInfo> featureInfoList = new ArrayList<>();
16+
private static final Map<String, Map<Integer, FeatureInfo>> categoryIdMap = new HashMap<>();
1517

1618
static {
1719
// 얼굴형
1820
int index = 0;
21+
Map<Integer, FeatureInfo> faceShapeMap = new HashMap<>();
1922
for (FaceShape value : FaceShape.values()) {
2023
featureIndexMap.put(value.name(), index);
21-
featureInfoList.add(new FeatureInfo("얼굴형", value.name(), value.getName(), index));
24+
FeatureInfo info = new FeatureInfo("FACE_SHAPE", value.name(), value.getName(), index, value.getId());
25+
featureInfoList.add(info);
26+
faceShapeMap.put(value.getId(), info);
2227
index++;
2328
}
29+
categoryIdMap.put("FACE_SHAPE", faceShapeMap);
2430

2531
// 눈 타입
32+
Map<Integer, FeatureInfo> eyeTypeMap = new HashMap<>();
2633
for (EyeType value : EyeType.values()) {
2734
featureIndexMap.put(value.name(), index);
28-
featureInfoList.add(new FeatureInfo("눈 타입", value.name(), value.getName(), index));
35+
FeatureInfo info = new FeatureInfo("EYE_TYPE", value.name(), value.getName(), index, value.getId());
36+
featureInfoList.add(info);
37+
eyeTypeMap.put(value.getId(), info);
2938
index++;
3039
}
40+
categoryIdMap.put("EYE_TYPE", eyeTypeMap);
3141

3242
// 눈 크기
43+
Map<Integer, FeatureInfo> eyeSizeMap = new HashMap<>();
3344
for (EyeSize value : EyeSize.values()) {
3445
featureIndexMap.put(value.name(), index);
35-
featureInfoList.add(new FeatureInfo("눈 크기", value.name(), value.getName(), index));
46+
FeatureInfo info = new FeatureInfo("EYE_SIZE", value.name(), value.getName(), index, value.getId());
47+
featureInfoList.add(info);
48+
eyeSizeMap.put(value.getId(), info);
3649
index++;
3750
}
51+
categoryIdMap.put("EYE_SIZE", eyeSizeMap);
3852

3953
// 입술 모양
54+
Map<Integer, FeatureInfo> lipShapeMap = new HashMap<>();
4055
for (LipShape value : LipShape.values()) {
4156
featureIndexMap.put(value.name(), index);
42-
featureInfoList.add(new FeatureInfo("입술 모양", value.name(), value.getName(), index));
57+
FeatureInfo info = new FeatureInfo("LIP_SHAPE", value.name(), value.getName(), index, value.getId());
58+
featureInfoList.add(info);
59+
lipShapeMap.put(value.getId(), info);
4360
index++;
4461
}
62+
categoryIdMap.put("LIP_SHAPE", lipShapeMap);
4563

4664
// 코 모양
65+
Map<Integer, FeatureInfo> noseShapeMap = new HashMap<>();
4766
for (NoseShape value : NoseShape.values()) {
4867
featureIndexMap.put(value.name(), index);
49-
featureInfoList.add(new FeatureInfo("코 모양", value.name(), value.getName(), index));
68+
FeatureInfo info = new FeatureInfo("NOSE_SHAPE", value.name(), value.getName(), index, value.getId());
69+
featureInfoList.add(info);
70+
noseShapeMap.put(value.getId(), info);
5071
index++;
5172
}
73+
categoryIdMap.put("NOSE_SHAPE", noseShapeMap);
5274

5375
// 턱 모양
76+
Map<Integer, FeatureInfo> jawShapeMap = new HashMap<>();
5477
for (JawShape value : JawShape.values()) {
5578
featureIndexMap.put(value.name(), index);
56-
featureInfoList.add(new FeatureInfo("턱 모양", value.name(), value.getName(), index));
79+
FeatureInfo info = new FeatureInfo("JAW_SHAPE", value.name(), value.getName(), index, value.getId());
80+
featureInfoList.add(info);
81+
jawShapeMap.put(value.getId(), info);
5782
index++;
5883
}
84+
categoryIdMap.put("JAW_SHAPE", jawShapeMap);
5985

6086
// 이마
87+
Map<Integer, FeatureInfo> foreheadMap = new HashMap<>();
6188
for (ForeHead value : ForeHead.values()) {
6289
featureIndexMap.put(value.name(), index);
63-
featureInfoList.add(new FeatureInfo("이마", value.name(), value.getName(), index));
90+
FeatureInfo info = new FeatureInfo("FOREHEAD", value.name(), value.getName(), index, value.getId());
91+
featureInfoList.add(info);
92+
foreheadMap.put(value.getId(), info);
6493
index++;
6594
}
95+
categoryIdMap.put("FOREHEAD", foreheadMap);
6696

6797
// 피부 톤
98+
Map<Integer, FeatureInfo> skinToneMap = new HashMap<>();
6899
for (SkinTone value : SkinTone.values()) {
69100
featureIndexMap.put(value.name(), index);
70-
featureInfoList.add(new FeatureInfo("피부 톤", value.name(), value.getName(), index));
101+
FeatureInfo info = new FeatureInfo("SKIN_TONE", value.name(), value.getName(), index, value.getId());
102+
featureInfoList.add(info);
103+
skinToneMap.put(value.getId(), info);
71104
index++;
72105
}
106+
categoryIdMap.put("SKIN_TONE", skinToneMap);
73107

74108
// 수염
109+
Map<Integer, FeatureInfo> beardMap = new HashMap<>();
75110
for (Beard value : Beard.values()) {
76111
featureIndexMap.put(value.name(), index);
77-
featureInfoList.add(new FeatureInfo("수염", value.name(), value.getName(), index));
112+
FeatureInfo info = new FeatureInfo("BEARD", value.name(), value.getName(), index, value.getId());
113+
featureInfoList.add(info);
114+
beardMap.put(value.getId(), info);
78115
index++;
79116
}
117+
categoryIdMap.put("BEARD", beardMap);
80118

81119
// 안경
120+
Map<Integer, FeatureInfo> glassMap = new HashMap<>();
82121
for (Glass value : Glass.values()) {
83122
featureIndexMap.put(value.name(), index);
84-
featureInfoList.add(new FeatureInfo("안경", value.name(), value.getName(), index));
123+
FeatureInfo info = new FeatureInfo("GLASS", value.name(), value.getName(), index, value.getId());
124+
featureInfoList.add(info);
125+
glassMap.put(value.getId(), info);
85126
index++;
86127
}
128+
categoryIdMap.put("GLASS", glassMap);
87129

88130
// 동물상
131+
Map<Integer, FeatureInfo> animalLookMap = new HashMap<>();
89132
for (AnimalLook value : AnimalLook.values()) {
90133
featureIndexMap.put(value.name(), index);
91-
featureInfoList.add(new FeatureInfo("동물상", value.name(), value.getName(), index));
134+
FeatureInfo info = new FeatureInfo("ANIMAL_LOOK", value.name(), value.getName(), index, value.getId());
135+
featureInfoList.add(info);
136+
animalLookMap.put(value.getId(), info);
92137
index++;
93138
}
139+
categoryIdMap.put("ANIMAL_LOOK", animalLookMap);
94140

95141
// 나이
142+
Map<Integer, FeatureInfo> ageMap = new HashMap<>();
96143
for (Age value : Age.values()) {
97144
featureIndexMap.put(value.name(), index);
98-
featureInfoList.add(new FeatureInfo("나이", value.name(), value.getName(), index));
145+
FeatureInfo info = new FeatureInfo("AGE", value.name(), value.getName(), index, value.getId());
146+
featureInfoList.add(info);
147+
ageMap.put(value.getId(), info);
99148
index++;
100149
}
150+
categoryIdMap.put("AGE", ageMap);
101151
}
102152

103153
public static Integer getFeatureIndex(String featureName) {
@@ -110,20 +160,88 @@ public static List<FeatureInfo> getAllFeatureInfos() {
110160

111161
public static List<FeatureInfo> getFeatureInfosFromBitmask(BigInteger bitmask) {
112162
List<FeatureInfo> selectedFeatures = new ArrayList<>();
113-
163+
114164
for (FeatureInfo featureInfo : featureInfoList) {
115165
if (bitmask.testBit(featureInfo.index())) {
116166
selectedFeatures.add(featureInfo);
117167
}
118168
}
119-
169+
120170
return selectedFeatures;
121171
}
122-
172+
173+
public static BigInteger convertIdsToBitmask(Map<String, List<Integer>> categoryIds) {
174+
BigInteger bitmask = BigInteger.ZERO;
175+
176+
for (Map.Entry<String, List<Integer>> entry : categoryIds.entrySet()) {
177+
String category = entry.getKey();
178+
List<Integer> ids = entry.getValue();
179+
Map<Integer, FeatureInfo> featureMap = categoryIdMap.get(category);
180+
181+
if (featureMap != null) {
182+
for (Integer id : ids) {
183+
FeatureInfo info = featureMap.get(id);
184+
if (info != null) {
185+
bitmask = bitmask.setBit(info.index());
186+
}
187+
}
188+
}
189+
}
190+
191+
return bitmask;
192+
}
193+
194+
public static Map<String, List<Integer>> convertBitmaskToIds(BigInteger bitmask) {
195+
Map<String, List<Integer>> result = new HashMap<>();
196+
197+
for (FeatureInfo info : featureInfoList) {
198+
if (bitmask.testBit(info.index())) {
199+
result.computeIfAbsent(info.category(), k -> new ArrayList<>())
200+
.add(info.featureId());
201+
}
202+
}
203+
204+
return result;
205+
}
206+
207+
public static List<FeatureInfo> getFeatureInfosByIds(Map<String, List<Integer>> categoryIds) {
208+
List<FeatureInfo> result = new ArrayList<>();
209+
210+
for (Map.Entry<String, List<Integer>> entry : categoryIds.entrySet()) {
211+
String category = entry.getKey();
212+
List<Integer> ids = entry.getValue();
213+
Map<Integer, FeatureInfo> featureMap = categoryIdMap.get(category);
214+
215+
if (featureMap != null) {
216+
for (Integer id : ids) {
217+
FeatureInfo info = featureMap.get(id);
218+
if (info != null) {
219+
result.add(info);
220+
}
221+
}
222+
}
223+
}
224+
225+
return result;
226+
}
227+
228+
public static FeatureInfo getFeatureInfoByNameAndCategory(String name, String category) {
229+
return featureInfoList.stream()
230+
.filter(info -> info.name().equals(name) && info.category().equals(category))
231+
.findFirst()
232+
.orElse(null);
233+
}
234+
123235
public record FeatureInfo(
124236
String category,
125237
String code,
126238
String name,
127-
int index
128-
) {}
239+
int index,
240+
int featureId
241+
) {
242+
// 기존 코드와의 호환성을 위한 생성자
243+
public FeatureInfo(String category, String code, String name, int index) {
244+
this(category, code, name, index, 0);
245+
}
246+
}
129247
}

0 commit comments

Comments
 (0)