Skip to content

Commit

Permalink
Merge pull request #147 from Team-Going/feature/146
Browse files Browse the repository at this point in the history
[feat] 여행 친구 전체 조회 API 스펙 및 비즈니스 로직 변경
  • Loading branch information
SunwoongH authored Mar 7, 2024
2 parents 17b15d0 + 3e134f8 commit 71af0eb
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 69 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package org.doorip.trip.actor;

import org.doorip.trip.domain.Participant;
import org.springframework.stereotype.Component;

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

@Component
public class TripTendencyTestActor {
private static final String TRIP_PLAN = "여행 계획";
private static final String TRIP_PLACE = "여행 장소";
private static final String RESTAURANT = "식당";
private static final String PICTURE = "사진";
private static final String TRIP_SCHEDULE = "여행 일정";
private static final int INITIALIZATION = 0;
private static final int HIGH_RANGE_STYLE = 3;
private static final int HIGH_RANGE_STYLES = 5;
private static final int CENTER_POS = 2;
private final Map<Integer, String> prefer = Map.of(
0, TRIP_PLAN,
1, TRIP_PLACE,
2, RESTAURANT,
3, PICTURE,
4, TRIP_SCHEDULE
);

public TripTendencyTestResult calculateTripTendencyTest(List<Participant> participants) {
List<List<Integer>> styles = generateStyles();
int participantCount = participants.size();
accumulateStyles(participants, styles);
List<String> bestPrefer = calculateBestPrefer(styles, participantCount);
calculateStyleAverage(styles, participantCount);
return TripTendencyTestResult.of(bestPrefer, styles);
}

private List<List<Integer>> generateStyles() {
List<List<Integer>> styles = new ArrayList<>();
IntStream.range(INITIALIZATION, HIGH_RANGE_STYLES)
.forEach(i -> styles.add(i, new ArrayList<>(Arrays.asList(INITIALIZATION, INITIALIZATION, INITIALIZATION))));
return styles;
}

private void accumulateStyles(List<Participant> participants, List<List<Integer>> styles) {
participants.forEach(participant -> {
accumulateStyle(styles, participant.getStyleA(), 0);
accumulateStyle(styles, participant.getStyleB(), 1);
accumulateStyle(styles, participant.getStyleC(), 2);
accumulateStyle(styles, participant.getStyleD(), 3);
accumulateStyle(styles, participant.getStyleE(), 4);
});
}

private List<String> calculateBestPrefer(List<List<Integer>> styles, int participantCount) {
List<String> bestPrefer = new ArrayList<>();
IntStream.range(INITIALIZATION, HIGH_RANGE_STYLES)
.forEach(i -> {
List<Integer> style = styles.get(i);
if (style.contains(participantCount)) {
bestPrefer.add(prefer.get(i));
}
});
return bestPrefer;
}

private void calculateStyleAverage(List<List<Integer>> styles, int participantCount) {
double percentage = 100.0 / participantCount;
styles.forEach(style ->
IntStream.range(INITIALIZATION, HIGH_RANGE_STYLE)
.forEach(i -> style.set(i, (int) Math.floor(style.get(i) * percentage))));
}

private void accumulateStyle(List<List<Integer>> styles, int styleValue, int pos) {
List<Integer> style = styles.get(pos);
if (styleValue < CENTER_POS) {
style.set(0, style.get(0) + 1);
} else if (styleValue == CENTER_POS) {
style.set(1, style.get(1) + 1);
} else {
style.set(2, style.get(2) + 1);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.doorip.trip.actor;

import java.util.List;

public record TripTendencyTestResult(
List<String> bestPrefer,
List<List<Integer>> styles
) {
public static TripTendencyTestResult of(List<String> bestPrefer, List<List<Integer>> styles) {
return new TripTendencyTestResult(bestPrefer, styles);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,19 @@

@Builder(access = AccessLevel.PRIVATE)
public record TripParticipantGetResponse(
List<String> bestPrefer,
List<TripParticipantResponse> participants,
List<TripStyleResponse> styles
) {
public static TripParticipantGetResponse of(List<Participant> participants, List<TripStyleResponse> styles) {
public static TripParticipantGetResponse of(List<String> bestPrefer, List<Participant> participants, List<List<Integer>> styles) {
return TripParticipantGetResponse.builder()
.bestPrefer(bestPrefer)
.participants(participants.stream()
.map(TripParticipantResponse::of)
.toList())
.styles(styles)
.styles(styles.stream()
.map(TripStyleResponse::from)
.toList())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public static TripParticipantResponse of(Participant participant) {
return TripParticipantResponse.builder()
.participantId(participant.getId())
.name(user.getName())
.result(user.getResult().getNumResult())
.result(user.getResult() == null ? -1 : user.getResult().getNumResult())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
package org.doorip.trip.dto.response;

import lombok.AccessLevel;
import lombok.Builder;
import java.util.List;

@Builder(access = AccessLevel.PRIVATE)
public record TripStyleResponse(
int rate,
boolean isLeft
List<Integer> rates
) {
public static TripStyleResponse of(int rate, boolean isLeft) {
return TripStyleResponse.builder()
.rate(rate)
.isLeft(isLeft)
.build();
public static TripStyleResponse from(List<Integer> rates) {
return new TripStyleResponse(rates);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@
import org.doorip.common.Constants;
import org.doorip.exception.EntityNotFoundException;
import org.doorip.message.ErrorMessage;
import org.doorip.trip.actor.TripTendencyTestActor;
import org.doorip.trip.actor.TripTendencyTestResult;
import org.doorip.trip.domain.*;
import org.doorip.trip.dto.request.ParticipantUpdateRequest;
import org.doorip.trip.dto.response.*;
import org.doorip.trip.dto.response.MyTodoResponse;
import org.doorip.trip.dto.response.OurTodoResponse;
import org.doorip.trip.dto.response.TripParticipantGetResponse;
import org.doorip.trip.dto.response.TripParticipantProfileResponse;
import org.doorip.trip.repository.ParticipantRepository;
import org.doorip.trip.repository.TodoRepository;
import org.doorip.trip.repository.TripRepository;
Expand All @@ -17,15 +22,16 @@

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.List;
import java.util.Objects;

import static java.lang.Math.round;
import static org.doorip.common.Constants.*;

@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class TripDetailService {
private final TripTendencyTestActor tripTendencyTestActor;
private final UserRepository userRepository;
private final TripRepository tripRepository;
private final TodoRepository todoRepository;
Expand Down Expand Up @@ -54,8 +60,8 @@ public TripParticipantGetResponse getParticipants(Long userId, Long tripId) {
List<Participant> participants = findTrip.getParticipants();
Participant ownerParticipant = getOwnerParticipant(userId, participants);
sortParticipants(participants, ownerParticipant);
List<TripStyleResponse> response = calculateAndGetPropensityAverageRates(participants);
return TripParticipantGetResponse.of(participants, response);
TripTendencyTestResult result = tripTendencyTestActor.calculateTripTendencyTest(participants);
return TripParticipantGetResponse.of(result.bestPrefer(), participants, result.styles());
}

@Transactional
Expand Down Expand Up @@ -87,12 +93,6 @@ public TripParticipantProfileResponse getParticipantProfile(Long userId, Long pa
return TripParticipantProfileResponse.of(participantUser, validatedResult, findParticipant, isOwner);
}

private Map<String, Integer> createDefaultPropensity() {
return new HashMap<>(Map.of(STYLE_A, MIN_STYLE_RATE, STYLE_B, MIN_STYLE_RATE,
STYLE_C, MIN_STYLE_RATE, STYLE_D, MIN_STYLE_RATE, STYLE_E, MIN_STYLE_RATE)) {
};
}

private int getIncompleteTodoCount(Long userId, Long tripId) {
return todoRepository.countTodoByTripIdAndUserIdAndProgress(tripId, userId, Progress.INCOMPLETE);
}
Expand Down Expand Up @@ -125,15 +125,6 @@ private int calculateTodoProgressRate(Long tripId) {
return round(((float) completeTodoCount / totalTodoCount) * 100);
}

private List<TripStyleResponse> calculateAndGetPropensityAverageRates(List<Participant> participants) {
int participantCount = participants.size();
Map<String, Integer> propensity = getDefaultPropensity(participants);
List<String> keys = sortPropensityKeys(propensity);
List<TripStyleResponse> response = new ArrayList<>();
calculateAndSetPropensityAverageRate(keys, propensity, participantCount, response);
return response;
}

private User getUser(Long userId) {
return userRepository.findById(userId)
.orElseThrow(() -> new EntityNotFoundException(ErrorMessage.USER_NOT_FOUND));
Expand Down Expand Up @@ -163,42 +154,6 @@ private boolean isOwnerParticipant(Long userId, User user) {
return Objects.equals(user.getId(), userId);
}

private Map<String, Integer> getDefaultPropensity(List<Participant> participants) {
Map<String, Integer> propensity = createDefaultPropensity();
participants.forEach(participant -> setDefaultPropensity(participant, propensity));
return propensity;
}

private List<String> sortPropensityKeys(Map<String, Integer> propensity) {
List<String> keys = new ArrayList<>(propensity.keySet());
Collections.sort(keys);
return keys;
}

private void calculateAndSetPropensityAverageRate(List<String> keys, Map<String, Integer> propensity, int participantCount, List<TripStyleResponse> response) {
keys.forEach(key -> {
int rate = round((float) propensity.get(key) / participantCount);
boolean isLeft = rate <= MAX_STYLE_RATE - rate;
rate = calculatePropensityWeight(isLeft, rate);
response.add(TripStyleResponse.of(rate, isLeft));
});
}

private void setDefaultPropensity(Participant participant, Map<String, Integer> propensity) {
propensity.put(STYLE_A, propensity.get(STYLE_A) + participant.getStyleA() * PROPENSITY_WEIGHT);
propensity.put(STYLE_B, propensity.get(STYLE_B) + participant.getStyleB() * PROPENSITY_WEIGHT);
propensity.put(STYLE_C, propensity.get(STYLE_C) + participant.getStyleC() * PROPENSITY_WEIGHT);
propensity.put(STYLE_D, propensity.get(STYLE_D) + participant.getStyleD() * PROPENSITY_WEIGHT);
propensity.put(STYLE_E, propensity.get(STYLE_E) + participant.getStyleE() * PROPENSITY_WEIGHT);
}

private int calculatePropensityWeight(boolean isLeft, int rate) {
if (isLeft) {
rate = MAX_STYLE_RATE - rate;
}
return rate;
}

private Participant getParticipantById(Long id) {
return participantRepository.findById(id)
.orElseThrow(() -> new EntityNotFoundException(ErrorMessage.PARTICIPANT_NOT_FOUND));
Expand Down

0 comments on commit 71af0eb

Please sign in to comment.