diff --git a/src/main/java/org/sopt/sweet/domain/gift/controller/GiftApi.java b/src/main/java/org/sopt/sweet/domain/gift/controller/GiftApi.java index b87d7a9..1612c5b 100644 --- a/src/main/java/org/sopt/sweet/domain/gift/controller/GiftApi.java +++ b/src/main/java/org/sopt/sweet/domain/gift/controller/GiftApi.java @@ -11,6 +11,7 @@ import jakarta.validation.Valid; import org.sopt.sweet.domain.gift.dto.request.CreateGiftRequestDto; import org.sopt.sweet.domain.gift.dto.request.MyGiftsRequestDto; +import org.sopt.sweet.domain.gift.dto.request.TournamentScoreRequestDto; import org.sopt.sweet.global.common.SuccessResponse; import org.sopt.sweet.global.config.auth.UserId; import org.springframework.http.ResponseEntity; @@ -122,4 +123,62 @@ ResponseEntity> getTournamentGiftList( ) @PathVariable Long roomId ); + @Operation( + summary = "선물 토너먼트 점수 등록 API", + responses = { + @ApiResponse( + responseCode = "201", + content = @Content( + mediaType = "application/json", + schema = @Schema(implementation = SuccessResponse.class) + ) + ) + }, + security = @SecurityRequirement(name = "token") + ) + ResponseEntity> evaluateTournamentScore( + @Parameter( + description = "authorization token에서 얻은 userId, 임의입력하면 대체됩니다.", + required = true, + example = "12345" + ) @UserId Long userId, + @Valid @RequestBody TournamentScoreRequestDto tournamentScoreRequestDto + ); + + + @Operation( + summary = "토너먼트 정보 조회 API", + responses = { + @ApiResponse( + responseCode = "200", + content = @Content( + mediaType = "application/json", + schema = @Schema(implementation = SuccessResponse.class) + ) + ), + @ApiResponse( + responseCode = "404", + description = "토너먼트나 사용자가 존재하지 않음", + content = @Content + ), + @ApiResponse( + responseCode = "403", + description = "토너먼트 시작일이 지났거나 사용자가 방에 속해있지 않음", + content = @Content + ) + }, + security = @SecurityRequirement(name = "token") + ) + ResponseEntity> getTournamentInfo( + @Parameter( + description = "authorization token에서 얻은 userId, 임의입력하면 대체됩니다.", + required = true, + example = "12345" + ) @UserId Long userId, + @Parameter( + description = "조회하려는 토너먼트가 진행 중인 방의 ID", + required = true, + example = "2" + ) @PathVariable Long roomId + ); } diff --git a/src/main/java/org/sopt/sweet/domain/gift/controller/GiftController.java b/src/main/java/org/sopt/sweet/domain/gift/controller/GiftController.java index 2b2c07f..44534c9 100644 --- a/src/main/java/org/sopt/sweet/domain/gift/controller/GiftController.java +++ b/src/main/java/org/sopt/sweet/domain/gift/controller/GiftController.java @@ -3,8 +3,10 @@ import lombok.RequiredArgsConstructor; import org.sopt.sweet.domain.gift.dto.request.CreateGiftRequestDto; import org.sopt.sweet.domain.gift.dto.request.MyGiftsRequestDto; +import org.sopt.sweet.domain.gift.dto.request.TournamentScoreRequestDto; import org.sopt.sweet.domain.gift.dto.response.MyGiftsResponseDto; import org.sopt.sweet.domain.gift.dto.response.TournamentListsResponseDto; +import org.sopt.sweet.domain.gift.dto.response.TournamentInfoDto; import org.sopt.sweet.domain.gift.service.GiftService; import org.sopt.sweet.global.common.SuccessResponse; import org.sopt.sweet.global.config.auth.UserId; @@ -44,6 +46,19 @@ public ResponseEntity> getTournamentGiftList(@UserId Long use return SuccessResponse.ok(tournamentGiftList); } + @PostMapping("/tonermant-score") + public ResponseEntity> evaluateTournamentScore(@UserId Long userId, @RequestBody TournamentScoreRequestDto tournamentScoreRequestDto) { + giftService.evaluateTournamentScore(tournamentScoreRequestDto); + return SuccessResponse.created(null); + } + + @GetMapping("tournament-info/{roomId}") + public ResponseEntity> getTournamentInfo(@UserId Long userId, @PathVariable Long roomId) { + final TournamentInfoDto tournamentInfo = giftService.getTournamentInfo(userId, roomId); + return SuccessResponse.ok(tournamentInfo); + } + + } diff --git a/src/main/java/org/sopt/sweet/domain/gift/dto/request/TournamentScoreRequestDto.java b/src/main/java/org/sopt/sweet/domain/gift/dto/request/TournamentScoreRequestDto.java new file mode 100644 index 0000000..b4699d6 --- /dev/null +++ b/src/main/java/org/sopt/sweet/domain/gift/dto/request/TournamentScoreRequestDto.java @@ -0,0 +1,18 @@ +package org.sopt.sweet.domain.gift.dto.request; + +import lombok.Builder; +import org.sopt.sweet.domain.gift.dto.response.TournamentListsResponseDto; + +@Builder +public record TournamentScoreRequestDto( + Long firstPlaceGiftId, + Long secondPlaceGiftId +) { + public static TournamentScoreRequestDto of(Long firstPlaceGiftId, Long secondPlaceGiftId) { + return TournamentScoreRequestDto.builder() + .firstPlaceGiftId(firstPlaceGiftId) + .secondPlaceGiftId(secondPlaceGiftId) + .build(); + } + +} diff --git a/src/main/java/org/sopt/sweet/domain/gift/dto/response/TournamentInfoDto.java b/src/main/java/org/sopt/sweet/domain/gift/dto/response/TournamentInfoDto.java new file mode 100644 index 0000000..42bc0d6 --- /dev/null +++ b/src/main/java/org/sopt/sweet/domain/gift/dto/response/TournamentInfoDto.java @@ -0,0 +1,28 @@ +package org.sopt.sweet.domain.gift.dto.response; + +import lombok.Builder; +import org.sopt.sweet.domain.room.constant.TournamentDuration; + +import java.time.LocalDateTime; +@Builder +public record TournamentInfoDto( + LocalDateTime tournamentStartDate, + TournamentDuration tournamentDuration, + + int TotalParticipantsCount, + int ParticipantsCount + +) { + public static TournamentInfoDto of(LocalDateTime tournamentStartDate, + TournamentDuration tournamentDuration, + int TotalParticipantsCount, + int ParticipantsCount) { + return TournamentInfoDto.builder() + .tournamentStartDate(tournamentStartDate) + .tournamentDuration(tournamentDuration) + .TotalParticipantsCount(TotalParticipantsCount) + .ParticipantsCount(ParticipantsCount) + .build(); + } + +} diff --git a/src/main/java/org/sopt/sweet/domain/gift/entity/Gift.java b/src/main/java/org/sopt/sweet/domain/gift/entity/Gift.java index 608d4b5..78f32d2 100644 --- a/src/main/java/org/sopt/sweet/domain/gift/entity/Gift.java +++ b/src/main/java/org/sopt/sweet/domain/gift/entity/Gift.java @@ -48,4 +48,12 @@ public Gift(String url, String name, int cost, String imageUrl, Room room, Membe this.room = room; this.member = member; } + + public void setScore(int score) { + this.score = score; + } + + + + } diff --git a/src/main/java/org/sopt/sweet/domain/gift/repository/GiftRepository.java b/src/main/java/org/sopt/sweet/domain/gift/repository/GiftRepository.java index 2958d9d..80c9890 100644 --- a/src/main/java/org/sopt/sweet/domain/gift/repository/GiftRepository.java +++ b/src/main/java/org/sopt/sweet/domain/gift/repository/GiftRepository.java @@ -9,6 +9,7 @@ import org.springframework.data.repository.query.Param; import java.util.List; +import java.util.Optional; public interface GiftRepository extends JpaRepository { long countByRoomAndMember(Room room, Member member); @@ -19,4 +20,5 @@ public interface GiftRepository extends JpaRepository { List findLatestGiftsByRoomAndNotMember(@Param("room") Room room, @Param("member") Member member, Pageable pageable); List findByRoom(Room room); + } diff --git a/src/main/java/org/sopt/sweet/domain/gift/service/GiftService.java b/src/main/java/org/sopt/sweet/domain/gift/service/GiftService.java index cf58089..dbd1053 100644 --- a/src/main/java/org/sopt/sweet/domain/gift/service/GiftService.java +++ b/src/main/java/org/sopt/sweet/domain/gift/service/GiftService.java @@ -3,13 +3,16 @@ import lombok.RequiredArgsConstructor; import org.sopt.sweet.domain.gift.dto.request.CreateGiftRequestDto; import org.sopt.sweet.domain.gift.dto.request.MyGiftsRequestDto; +import org.sopt.sweet.domain.gift.dto.request.TournamentScoreRequestDto; import org.sopt.sweet.domain.gift.dto.response.MyGiftDto; import org.sopt.sweet.domain.gift.dto.response.MyGiftsResponseDto; import org.sopt.sweet.domain.gift.dto.response.TournamentListsResponseDto; +import org.sopt.sweet.domain.gift.dto.response.TournamentInfoDto; import org.sopt.sweet.domain.gift.entity.Gift; import org.sopt.sweet.domain.gift.repository.GiftRepository; import org.sopt.sweet.domain.member.entity.Member; import org.sopt.sweet.domain.member.repository.MemberRepository; +import org.sopt.sweet.domain.room.constant.TournamentDuration; import org.sopt.sweet.domain.room.entity.Room; import org.sopt.sweet.domain.room.entity.RoomMember; import org.sopt.sweet.domain.room.repository.RoomMemberRepository; @@ -36,6 +39,8 @@ public class GiftService { private final RoomRepository roomRepository; private final RoomMemberRepository roomMemberRepository; private static final int MAX_GIFT_COUNT = 2; + private static final int FIRST_PLACE_SCORE = 10; + private static final int SECOND_PLACE_SCORE= 5; public void createNewGift(Long memberId, CreateGiftRequestDto createGiftRequestDto) { Member member = findMemberByIdOrThrow(memberId); @@ -57,7 +62,7 @@ public MyGiftsResponseDto getMyGift(Long memberId, MyGiftsRequestDto myGiftsRequ return new MyGiftsResponseDto(myGiftsDtoList); } - public void deleteMyGift(Long memberId, Long giftId){ + public void deleteMyGift(Long memberId, Long giftId) { Member member = findMemberByIdOrThrow(memberId); Gift gift = findByIdOrThrow(giftId); validateMemberGiftOwner(member, gift); @@ -123,11 +128,17 @@ private Room findRoomByIdOrThrow(Long roomId) { .orElseThrow(() -> new EntityNotFoundException(ROOM_NOT_FOUND)); } + private Gift findByIdOrThrow(Long giftId) { return giftRepository.findById(giftId) .orElseThrow(() -> new EntityNotFoundException(GIFT_NOT_FOUND)); } + private Room findGiftByIdOrThrow(Long roomId) { + return roomRepository.findById(roomId) + .orElseThrow(() -> new EntityNotFoundException(GIFT_NOT_FOUND)); + } + @Transactional(readOnly = true) public List getTournamentGiftList(Long roomId) { @@ -142,4 +153,44 @@ private List mapGiftsToTournamentLists(List gi .collect(Collectors.toList()); } + public void evaluateTournamentScore(TournamentScoreRequestDto tournamentScoreRequestDto) { + + Gift firstPlaceGift = updateScore(tournamentScoreRequestDto.firstPlaceGiftId(), FIRST_PLACE_SCORE); + Gift secondPlaceGift = updateScore(tournamentScoreRequestDto.secondPlaceGiftId(), SECOND_PLACE_SCORE); + + giftRepository.save(firstPlaceGift); + giftRepository.save(secondPlaceGift); + } + + + private Gift updateScore(Long giftId, int score) { + Gift gift = findByIdOrThrow(giftId); + int newScore = gift.getScore() + score; + gift.setScore(newScore); + return gift; + } + + public TournamentInfoDto getTournamentInfo(Long memberId, Long roomId) { + Room room = findRoomByIdOrThrow(roomId); + + LocalDateTime tournamentStartDate = room.getTournamentStartDate(); + TournamentDuration tournamentDuration = room.getTournamentDuration(); + int totalParticipantsCount = room.getGifterNumber(); + + updateTournamentParticipation(memberId, roomId); + + int participatingMembersCount = roomMemberRepository.countByRoomIdAndTournamentParticipationIsTrue(roomId); + + return new TournamentInfoDto(tournamentStartDate, tournamentDuration, totalParticipantsCount, participatingMembersCount); + } + + public void updateTournamentParticipation(Long memberId, Long roomId) { + RoomMember roomMember = roomMemberRepository.findByRoomIdAndMemberId(roomId, memberId); + roomMember.setTournamentParticipation(true); + roomMemberRepository.save(roomMember); + } + + + + } \ No newline at end of file diff --git a/src/main/java/org/sopt/sweet/domain/room/entity/RoomMember.java b/src/main/java/org/sopt/sweet/domain/room/entity/RoomMember.java index da566f1..ed59a37 100644 --- a/src/main/java/org/sopt/sweet/domain/room/entity/RoomMember.java +++ b/src/main/java/org/sopt/sweet/domain/room/entity/RoomMember.java @@ -31,4 +31,8 @@ public RoomMember(Room room, Member member){ this.member = member; } + public void setTournamentParticipation(boolean tournamentParticipation) { + this.tournamentParticipation = tournamentParticipation; + } + } diff --git a/src/main/java/org/sopt/sweet/domain/room/repository/RoomMemberRepository.java b/src/main/java/org/sopt/sweet/domain/room/repository/RoomMemberRepository.java index 3140cc0..4f7eead 100644 --- a/src/main/java/org/sopt/sweet/domain/room/repository/RoomMemberRepository.java +++ b/src/main/java/org/sopt/sweet/domain/room/repository/RoomMemberRepository.java @@ -11,4 +11,7 @@ public interface RoomMemberRepository extends JpaRepository { Optional findByRoomAndMember(Room room, Member member); List findByRoomId(Long roomId); + + int countByRoomIdAndTournamentParticipationIsTrue(Long roomId); + RoomMember findByRoomIdAndMemberId(Long roomId, Long memberId); } diff --git a/src/main/java/org/sopt/sweet/domain/room/repository/RoomRepository.java b/src/main/java/org/sopt/sweet/domain/room/repository/RoomRepository.java index dc745a8..0286a4e 100644 --- a/src/main/java/org/sopt/sweet/domain/room/repository/RoomRepository.java +++ b/src/main/java/org/sopt/sweet/domain/room/repository/RoomRepository.java @@ -1,6 +1,7 @@ package org.sopt.sweet.domain.room.repository; import org.sopt.sweet.domain.room.entity.Room; +import org.sopt.sweet.domain.room.entity.RoomMember; import org.springframework.data.jpa.repository.JpaRepository; import java.util.Optional; @@ -9,4 +10,6 @@ public interface RoomRepository extends JpaRepository { boolean existsByInvitationCode(String invitationCode); Optional findByInvitationCode(String invitationCode); + + }