Skip to content

Commit

Permalink
feat: 매칭 서비스 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
hjk0761 committed Jul 19, 2024
1 parent 1e1d95e commit d5d2578
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 57 deletions.
10 changes: 5 additions & 5 deletions backend/src/main/java/corea/exception/ExceptionType.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

public enum ExceptionType {

SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR,"서버에 문제가 발생했습니다."),
SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "서버에 문제가 발생했습니다."),
MEMBER_NOT_FOUND(HttpStatus.BAD_REQUEST, "해당 멤버를 찾을 수 없습니다."),
ROOM_NOT_FOUND(HttpStatus.BAD_REQUEST, "방을 찾을 수 없습니다."),
NOT_FOUND_ERROR(HttpStatus.NOT_FOUND,"해당하는 값이 없습니다."),
AUTHORIZATION_ERROR(HttpStatus.UNAUTHORIZED,"인증에 실패했습니다."),
ALREADY_APPLY(HttpStatus.BAD_REQUEST,"해당 방에 이미 참여했습니다"),
;
NOT_FOUND_ERROR(HttpStatus.NOT_FOUND, "해당하는 값이 없습니다."),
AUTHORIZATION_ERROR(HttpStatus.UNAUTHORIZED, "인증에 실패했습니다."),
ALREADY_APPLY(HttpStatus.BAD_REQUEST, "해당 방에 이미 참여했습니다"),
PARTICIPANT_SIZE_LACK(HttpStatus.BAD_REQUEST, "참여 인원 수가 부족합니다.");

private final HttpStatus httpStatus;
private final String message;
Expand Down
6 changes: 6 additions & 0 deletions backend/src/main/java/corea/matching/domain/MatchResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,18 @@ public class MatchResult {
private long roomId;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "fromMemberId", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
private Member fromMember;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "toMemberId", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
private Member toMember;

private String prLink;

private boolean isReviewed;

public MatchResult(long roomId, Member fromMember, Member toMember, String prLink) {
this(null, roomId, fromMember, toMember, prLink, false);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package corea.matching.repository;

import corea.matching.domain.MatchResult;
import org.springframework.data.jpa.repository.JpaRepository;

public interface MatchResultRepository extends JpaRepository<MatchResult, Long> {
}
31 changes: 0 additions & 31 deletions backend/src/main/java/corea/matching/service/Matching.java

This file was deleted.

62 changes: 41 additions & 21 deletions backend/src/main/java/corea/member/service/MatchingService.java
Original file line number Diff line number Diff line change
@@ -1,35 +1,55 @@
package corea.member.service;

import corea.exception.CoreaException;
import corea.exception.ExceptionType;
import corea.matching.domain.MatchResult;
import corea.matching.domain.Pair;
import corea.matching.domain.Participation;
import corea.matching.service.Matching;
import corea.member.entity.MatchedGroup;
import corea.matching.repository.MatchedGroupRepository;
import lombok.AllArgsConstructor;
import corea.matching.domain.PlainRandomMatching;
import corea.matching.repository.MatchResultRepository;
import corea.member.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@AllArgsConstructor
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class MatchingService {

private final MatchedGroupRepository matchedGroupRepository;
private final Matching matching;
private final PlainRandomMatching plainRandomMatching;
private final MatchResultRepository matchResultRepository;
private final MemberRepository memberRepository;

public void matchMaking(final List<Participation> participations, final int matchingSize) {
final ArrayList<Long> memberIds = new ArrayList<>(participations.stream()
public void matchMaking(List<Participation> participations, int matchingSize) {
validateParticipationSize(participations, matchingSize);
List<Long> memberIds = participations.stream()
.map(Participation::getMemberId)
.toList()
);

final Map<Long, List<Long>> results = matching.matchGroup(memberIds, matchingSize);
results.entrySet()
.stream()
.flatMap(entry -> entry.getValue()
.stream()
.map(memberId -> new MatchedGroup(entry.getKey(), memberId)))
.forEach(matchedGroupRepository::save);
.toList();

long roomId = participations.get(0).getRoomId();

List<Pair> results = plainRandomMatching.matchPairs(memberIds, matchingSize);

results.stream()
.map(pair -> new MatchResult(
roomId,
memberRepository.findById(pair.getFromMemberId()).orElseThrow(
() -> new CoreaException(ExceptionType.MEMBER_NOT_FOUND, String.format(String.format("%d에 해당하는 멤버가 없습니다.", pair.getFromMemberId())))
),
memberRepository.findById(pair.getToMemberId()).orElseThrow(
() -> new CoreaException(ExceptionType.MEMBER_NOT_FOUND, String.format(String.format("%d에 해당하는 멤버가 없습니다.", pair.getToMemberId())))
),
null))
//TODO: prLink 차후 수정
.forEach(matchResultRepository::save);
}

private void validateParticipationSize(List<Participation> participations, int matchingSize) {
if (participations.size() <= matchingSize) {
throw new CoreaException(ExceptionType.PARTICIPANT_SIZE_LACK);
}
}
}
21 changes: 21 additions & 0 deletions backend/src/test/java/corea/fixture/ParticipationFixture.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package corea.fixture;

import corea.matching.domain.Participation;

import java.util.List;

public class ParticipationFixture {

public static List<Participation> PARTICIPATIONS_EIGHT() {
return List.of(
new Participation(1L, 1L),
new Participation(1L, 2L),
new Participation(1L, 3L),
new Participation(1L, 4L),
new Participation(1L, 5L),
new Participation(1L, 6L),
new Participation(1L, 7L),
new Participation(1L, 8L)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package corea.member.service;

import config.ServiceTest;
import corea.exception.CoreaException;
import corea.fixture.MemberFixture;
import corea.fixture.ParticipationFixture;
import corea.matching.domain.Participation;
import corea.member.repository.MemberRepository;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

@ServiceTest
class MatchingServiceTest {

@Autowired
private MatchingService matchingService;

@Autowired
private MemberRepository memberRepository;

@Test
@DisplayName("인원 수가 매칭 사이즈보다 큰 경우 매칭을 수행한다.")
void matchMaking() {
List<Participation> participations = new ArrayList<>();
int matchingSize = 3;

for (int i = 0; i < 4; i++) {
participations.add(new Participation(1L, memberRepository.save(MemberFixture.MEMBER_DOMAIN()).getId()));
participations.add(new Participation(1L, memberRepository.save(MemberFixture.MEMBER_MANAGER()).getId()));
}

assertThatCode(() -> matchingService.matchMaking(participations, matchingSize))
.doesNotThrowAnyException();
}

@Test
@DisplayName("매칭을 수행할 때에, 인원 수가 매칭 사이즈보다 작거나 같으면 예외를 발생한다.")
void matchMakingLackOfParticipationException() {
List<Participation> participations = ParticipationFixture.PARTICIPATIONS_EIGHT();
int matchingSize = 9;

assertThatThrownBy(() -> matchingService.matchMaking(participations, matchingSize))
.isInstanceOf(CoreaException.class)
.hasMessage("참여 인원 수가 부족합니다.");
}
}
1 change: 1 addition & 0 deletions backend/src/test/resources/clear.sql
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
DELETE FROM MATCH_RESULT;
DELETE FROM MEMBER;
DELETE FROM ROOM;

0 comments on commit d5d2578

Please sign in to comment.