Skip to content

Commit

Permalink
Merge pull request #155 from Team-Going/develop
Browse files Browse the repository at this point in the history
[release] v1.2.0 릴리즈
  • Loading branch information
SunwoongH authored Apr 5, 2024
2 parents 8e6f923 + 77ed7cb commit 1cf5ba3
Show file tree
Hide file tree
Showing 33 changed files with 648 additions and 140 deletions.
12 changes: 4 additions & 8 deletions doorip-api/src/main/java/org/doorip/common/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,9 @@ public abstract class Constants {
public static final String COMPLETE = "complete";
public static final String OUR = "our";
public static final String MY = "my";
public static final String STYLE_A = "style_a";
public static final String STYLE_B = "style_b";
public static final String STYLE_C = "style_c";
public static final String STYLE_D = "style_d";
public static final String STYLE_E = "style_e";
public static final int MIN_STYLE_RATE = 0;
public static final int MAX_STYLE_RATE = 100;
public static final int PROPENSITY_WEIGHT = 25;
public static final int MIN_PARTICIPANT_COUNT = 1;
public static final int MAX_PARTICIPANT_COUNT = 6;
public static final int TODO_OWNER_POSITION = 0;
public static final int START_STYLE_POS = 0;
public static final int END_STYLE_POS = 5;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
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>> rates = generateStyles();
List<List<Integer>> counts = generateStyles();
int participantCount = participants.size();
accumulateCounts(participants, counts);
List<String> bestPrefer = calculateBestPrefer(counts, participantCount);
calculateRatesAverage(rates, counts, participantCount);
return TripTendencyTestResult.of(bestPrefer, rates, counts);
}

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 accumulateCounts(List<Participant> participants, List<List<Integer>> counts) {
participants.forEach(participant -> {
accumulateCount(counts, participant.getStyleA(), 0);
accumulateCount(counts, participant.getStyleB(), 1);
accumulateCount(counts, participant.getStyleC(), 2);
accumulateCount(counts, participant.getStyleD(), 3);
accumulateCount(counts, participant.getStyleE(), 4);
});
}

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

private void calculateRatesAverage(List<List<Integer>> rates, List<List<Integer>> counts, int participantCount) {
double percentage = 100.0 / participantCount;
IntStream.range(INITIALIZATION, HIGH_RANGE_STYLES)
.forEach(i -> {
List<Integer> rate = rates.get(i);
List<Integer> count = counts.get(i);
IntStream.range(INITIALIZATION, HIGH_RANGE_STYLE)
.forEach(j -> rate.set(j, (int) Math.floor(count.get(j) * percentage)));
});
}

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

import lombok.AccessLevel;
import lombok.Builder;

import java.util.List;

@Builder(access = AccessLevel.PRIVATE)
public record TripTendencyTestResult(
List<String> bestPrefer,
List<List<Integer>> rates,
List<List<Integer>> counts
) {
public static TripTendencyTestResult of(List<String> bestPrefer, List<List<Integer>> rates, List<List<Integer>> counts) {
return TripTendencyTestResult.builder()
.bestPrefer(bestPrefer)
.rates(rates)
.counts(counts)
.build();
}
}
19 changes: 15 additions & 4 deletions doorip-api/src/main/java/org/doorip/trip/api/TodoApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import org.doorip.auth.UserId;
import org.doorip.common.BaseResponse;
import org.doorip.trip.dto.request.TodoCreateRequest;
import org.doorip.trip.dto.request.TodoCreateAndUpdateRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -30,7 +30,11 @@ public interface TodoApi {
content = @Content),
@ApiResponse(
responseCode = "400",
description = "여행 TODO를 생성하기 위해 최소 1명 이상의 배정자가 필요합니다.",
description = "여행 MY TODO의 배정자가 누락되었습니다.",
content = @Content),
@ApiResponse(
responseCode = "400",
description = "여행 MY TODO의 배정자 번호가 잘못되었습니다.",
content = @Content),
@ApiResponse(
responseCode = "401",
Expand Down Expand Up @@ -60,8 +64,10 @@ public interface TodoApi {
responseCode = "500",
description = "서버 내부 오류입니다.",
content = @Content)})
ResponseEntity<BaseResponse<?>> createTripTodo(@PathVariable final Long tripId,
@RequestBody final TodoCreateRequest request);
ResponseEntity<BaseResponse<?>> createTripTodo(@Parameter(hidden = true)
@UserId final Long userId,
@PathVariable final Long tripId,
@RequestBody final TodoCreateAndUpdateRequest request);

@Operation(
summary = "여행 TODO 전체 조회 API",
Expand Down Expand Up @@ -128,6 +134,10 @@ ResponseEntity<BaseResponse<?>> getTripTodos(@Parameter(hidden = true)
responseCode = "401",
description = "액세스 토큰이 만료되었습니다. 재발급 받아주세요.",
content = @Content),
@ApiResponse(
responseCode = "404",
description = "존재하지 않는 여행입니다.",
content = @Content),
@ApiResponse(
responseCode = "404",
description = "존재하지 않는 여행 TODO입니다.",
Expand All @@ -142,6 +152,7 @@ ResponseEntity<BaseResponse<?>> getTripTodos(@Parameter(hidden = true)
content = @Content)})
ResponseEntity<BaseResponse<?>> getTripTodo(@Parameter(hidden = true)
@UserId final Long userId,
@PathVariable final Long tripId,
@PathVariable final Long todoId);

@Operation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import org.doorip.common.ApiResponseUtil;
import org.doorip.common.BaseResponse;
import org.doorip.message.SuccessMessage;
import org.doorip.trip.dto.request.TodoCreateRequest;
import org.doorip.trip.dto.request.TodoCreateAndUpdateRequest;
import org.doorip.trip.dto.response.TodoDetailGetResponse;
import org.doorip.trip.dto.response.TodoGetResponse;
import org.doorip.trip.service.TodoService;
Expand All @@ -23,9 +23,10 @@ public class TodoApiController implements TodoApi {

@PostMapping("/{tripId}/todos")
@Override
public ResponseEntity<BaseResponse<?>> createTripTodo(@PathVariable final Long tripId,
@RequestBody final TodoCreateRequest request) {
todoService.createTripTodo(tripId, request);
public ResponseEntity<BaseResponse<?>> createTripTodo(@UserId final Long userId,
@PathVariable final Long tripId,
@RequestBody final TodoCreateAndUpdateRequest request) {
todoService.createTripTodo(userId, tripId, request);
return ApiResponseUtil.success(SuccessMessage.CREATED);
}

Expand All @@ -39,14 +40,24 @@ public ResponseEntity<BaseResponse<?>> getTripTodos(@UserId final Long userId,
return ApiResponseUtil.success(SuccessMessage.OK, response);
}

@GetMapping("/todos/{todoId}")
@GetMapping("/{tripId}/todos/{todoId}")
@Override
public ResponseEntity<BaseResponse<?>> getTripTodo(@UserId final Long userId,
@PathVariable final Long tripId,
@PathVariable final Long todoId) {
final TodoDetailGetResponse response = todoService.getTripTodo(userId, todoId);
final TodoDetailGetResponse response = todoService.getTripTodo(userId, tripId, todoId);
return ApiResponseUtil.success(SuccessMessage.OK, response);
}

@PatchMapping("/{tripId}/todos/{todoId}")
public ResponseEntity<BaseResponse<?>> updateTripTodo(@UserId final Long userId,
@PathVariable final Long tripId,
@PathVariable final Long todoId,
@RequestBody final TodoCreateAndUpdateRequest request) {
todoService.updateTripTodo(userId, tripId, todoId, request);
return ApiResponseUtil.success(SuccessMessage.OK);
}

@DeleteMapping("/todos/{todoId}")
@Override
public ResponseEntity<BaseResponse<?>> deleteTripTodo(@PathVariable final Long todoId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

import lombok.RequiredArgsConstructor;
import org.doorip.auth.UserId;
import org.doorip.common.BaseResponse;
import org.doorip.common.ApiResponseUtil;
import org.doorip.common.BaseResponse;
import org.doorip.message.SuccessMessage;
import org.doorip.trip.dto.request.TripCreateRequest;
import org.doorip.trip.dto.request.TripEntryRequest;
import org.doorip.trip.dto.request.TripUpdateRequest;
import org.doorip.trip.dto.request.TripVerifyRequest;
import org.doorip.trip.dto.request.ParticipantUpdateRequest;
import org.doorip.trip.dto.response.*;
import org.doorip.trip.service.TripDetailService;
import org.doorip.trip.service.TripService;
Expand All @@ -34,7 +36,7 @@ public ResponseEntity<BaseResponse<?>> createTrip(@UserId final Long userId,
@Override
public ResponseEntity<BaseResponse<?>> getTrips(@UserId final Long userId,
@RequestParam final String progress) {
final TripGetResponse response = tripService.getTrips(userId, progress);
final TripsGetResponse response = tripService.getTrips(userId, progress);
return ApiResponseUtil.success(SuccessMessage.OK, response);
}

Expand Down Expand Up @@ -77,4 +79,41 @@ public ResponseEntity<BaseResponse<?>> getParticipants(@UserId final Long userId
final TripParticipantGetResponse response = tripDetailService.getParticipants(userId, tripId);
return ApiResponseUtil.success(SuccessMessage.OK, response);
}

@PatchMapping("/{tripId}/leave")
public ResponseEntity<BaseResponse<?>> leaveTrip(@UserId final Long userId,
@PathVariable final Long tripId) {
tripDetailService.leaveTrip(userId, tripId);
return ApiResponseUtil.success(SuccessMessage.OK);
}

@GetMapping("/{tripId}")
public ResponseEntity<BaseResponse<?>> getTrip(@PathVariable final Long tripId,
@UserId final Long userId) {
final TripGetResponse response = tripService.getTrip(userId, tripId);
return ApiResponseUtil.success(SuccessMessage.OK, response);
}

@PatchMapping("/{tripId}")
public ResponseEntity<BaseResponse<?>> updateTrip(@PathVariable final Long tripId,
@UserId final Long userId,
@RequestBody final TripUpdateRequest request) {
tripService.updateTrip(userId, tripId, request);
return ApiResponseUtil.success(SuccessMessage.OK);
}

@PatchMapping("/{tripId}/participant")
public ResponseEntity<BaseResponse<?>> updateParticipant(@PathVariable final Long tripId,
@UserId final Long userId,
@RequestBody final ParticipantUpdateRequest request) {
tripDetailService.updateParticipant(userId, tripId, request);
return ApiResponseUtil.success(SuccessMessage.OK);
}

@GetMapping("/participants/{participantId}")
public ResponseEntity<BaseResponse<?>> getParticipantProfile(@PathVariable final Long participantId,
@UserId final Long userId) {
final TripParticipantProfileResponse response = tripDetailService.getParticipantProfile(userId, participantId);
return ApiResponseUtil.success(SuccessMessage.OK, response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.doorip.trip.dto.request;

public record ParticipantUpdateRequest(
int styleA,
int styleB,
int styleC,
int styleD,
int styleE
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import java.time.LocalDate;
import java.util.List;

public record TodoCreateRequest(
public record TodoCreateAndUpdateRequest(
String title,
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy.MM.dd", timezone = "Asia/Seoul")
LocalDate endDate,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.doorip.trip.dto.request;

import com.fasterxml.jackson.annotation.JsonFormat;
import java.time.LocalDate;

public record TripUpdateRequest(
String title,
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy.MM.dd", timezone = "Asia/Seoul")
LocalDate startDate,
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy.MM.dd", timezone = "Asia/Seoul")
LocalDate endDate
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.doorip.trip.dto.response;

import lombok.AccessLevel;
import lombok.Builder;
import org.doorip.trip.domain.Participant;

@Builder(access = AccessLevel.PRIVATE)
public record TodoDetailAllocatorResponse(
Long participantId,
String name,
boolean isOwner,
boolean isAllocated
) {
public static TodoDetailAllocatorResponse of(String name, boolean isOwner, boolean isAllocated, Participant participant) {
return TodoDetailAllocatorResponse.builder()
.participantId(participant.getId())
.name(name)
.isOwner(isOwner)
.isAllocated(isAllocated)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ public record TodoDetailGetResponse(
String title,
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy.MM.dd", timezone = "Asia/Seoul")
LocalDate endDate,
List<TodoAllocatorResponse> allocators,
List<TodoDetailAllocatorResponse> allocators,
String memo,
boolean secret
) {
public static TodoDetailGetResponse of(Todo todo, List<TodoAllocatorResponse> allocators) {
public static TodoDetailGetResponse of(Todo todo, List<TodoDetailAllocatorResponse> allocators) {
return TodoDetailGetResponse.builder()
.title(todo.getTitle())
.endDate(todo.getEndDate())
Expand Down
Loading

0 comments on commit 1cf5ba3

Please sign in to comment.