본문 바로가기
일기/항해99

[항해99 6기] 실전프로젝트 2주차 - 상대방 평가

by 고구밍 2022. 5. 7.

 

채팅 10분 이내 응답시 보너스를 주는 로직을 짜보자

 

 

댓글 entity

 

댓글목록 entity

 

접근법)

chatroom의 Id값을 찾아야 된다는 가정하여 코드를 만들었습니다.

다행히도 프론트에서 상대의 ID값을 주기로 하였습니다.

 

1. 채팅목록 레포지토리

Param으로부터 유저ID와 상대ID를 받아서, 요청하였습니다.

@Query문에

requesterId(요청자 아이디) = 유저아이디

acceptorId(수신자 아이디) = 상대아이디

 

// 내가 요청한 채팅방
@Query("SELECT cr FROM ChatRoom cr WHERE cr.requesterId =:userId AND  cr.acceptorId = :opponentUserId")
ChatRoom findMyRequestChatRoom(@Param("userId") Long userId, @Param("opponentUserId") Long opponentUserId);

 

반대일 경우도 있을 수 있기 때문에  else문을 통해서 반대의 경우에도 조회하는 쿼리문을 만들었습니다.

// 내가 요청받은 채팅방
@Query("SELECT cr FROM ChatRoom cr WHERE cr.requesterId = :opponentUserId AND cr.acceptorId = :userId")
ChatRoom findMyAcceptorIdChatRoom(@Param("userId") Long userId, @Param("opponentUserId") Long opponentUserId);

 

평가하기 서비스

// 내 포지션이 바이어라면 -> roomId를 모를 떄
if (myPosition.equals("buyer")) {
    chatRoomChek = chatRoomRepository.findMyRequestChatRoom(user.getId(), opponentUserId);
    // 내포지션이 셀러라면
} else {
    chatRoomChek = chatRoomRepository.findMyAcceptorIdChatRoom(user.getId(), opponentUserId);
}

 

 

2. 채팅 레포지토리

조건1 : 유저Id조건2 : 채팅룸Id을 조회하였습니다.

나의 메시지 목록과 상대의 마세지 목록을 리스트로 조회하였습니다.

// 내가 요청받은 채팅방
    @Query("SELECT cm FROM ChatMessage cm WHERE cm.userId =:userId AND cm.roomId =:roomId")
    List<ChatMessage> findMyChatMessage(@Param("userId") Long userId, @Param("roomId") Long roomId);

 

평가하기 서비스

Long chatRoomId = chatRoomChek.getId();
Long myUserId = user.getId();
myMessageList = chatMessageRepository.findMyChatMessage(myUserId , chatRoomId);
opponentMessageList = chatMessageRepository.findMyChatMessage(opponentUserId, chatRoomId);

 

3. 최초의 메시지 시간을 조회한다.

1번째 메시지를 참고하기위해서 for문을 통해서 cnt값이 1일 경우 break를 하여

firstMyTime과 firstOppoentTime을 조회하여 -> ChronoUnit.MINUTES.between(조건1, 조건2)을 통해서

조건1과 조건2사이의 시간차이를 구하였다.

-> if문을 통해서 minut값이 10이하일 경우 true값을 반환하고, 아닐경우는 false값을 반환하여

-> 이후 보너스 점수를 줄 수 있는 가능성을 열어 놓았다.

 

걱정)

=> 본인은 아직 웹소켓의 개념을 잘 모르기 때문에 H2콘솔을 통해서 직접 데이터를 입력하였는데,

=> 실제로 테스트를 하게 되었을 때 어떤 오류가 발생할 지는 미지수이다.

// 각자의 최초 메시지의 시간을 조회한다
int cnt = 0;
LocalDateTime firstMyTime = null;
LocalDateTime firstOppoentTime = null;
for (ChatMessage myChat : myMessageList) {
    System.out.println("내 첫메시지 내용 : " + myChat.getMessage());
    firstMyTime = myChat.getCreatedAt();
    cnt++;
    if (cnt == 1) {
        break;
    }
}
cnt = 0;
for (ChatMessage opponetChat : opponentMessageList) {
    System.out.println("상대의 첫 메시지 내용 : " + opponetChat.getMessage());
    firstOppoentTime = opponetChat.getCreatedAt();
    cnt++;
    if (cnt == 1) {
        break;
    }
}

System.out.println("내 첫메시지 : " + firstMyTime.getMinute());
Long minute = ChronoUnit.MINUTES.between(firstMyTime, firstOppoentTime);

System.out.println("비투인 사이 시간 " + minute);
boolean chatTime = false;
if (minute <= 10) {
    chatTime = true;
    System.out.println("10분 이내인가 : " + chatTime);
}

 

 

 

// 성훈 - 상대 평점주기
    @Transactional
    public void gradeScore(GradeScoreRequestDto gradeScoreRequestDto, UserDetailsImpl userDetails) {
        User user = userRepository.findById(userDetails.getUserId()).orElseThrow(
                () -> new IllegalArgumentException("user not found")
        );


        // 상대 userId
        Long opponentUserId = gradeScoreRequestDto.getUserId();
        // 평가주기
        float gradeScore = gradeScoreRequestDto.getScore();
        // 상대찾기
        User opponentUser = userRepository.findById(opponentUserId).orElseThrow(() -> new IllegalArgumentException("user not found"));
        // 상대 등급
        String opponentDegree;
        // 상대의 총점수
        float opponentUserTotalGrade = opponentUser.getTotalGrade();
        // 상대 평가점수
        float opponentGrade;
        // 상대 평가자 수
        int opponentRaterCnt = opponentUser.getRaterCount();
        // 점수

        // 거래내역 조회
        Long barterId = gradeScoreRequestDto.getBarterId();
        Barter barter = barterRepository.findById(barterId).orElseThrow(() -> new IllegalArgumentException("barter not found"));

        System.out.println("거래상태 : " + barter.getStatus());
        System.out.println("2번째 예외처리 : " + opponentUserId);
        System.out.println("바이어아이디 : " + barter.getBuyerId());
        System.out.println("셀러아이디 : " + barter.getSellerId());


//        // 이미 평가를 완료한 경우
//        if (barter.getStatus() != 3) {
//            throw new ResponseStatusException(HttpStatus.NOT_ACCEPTABLE, "올바른 요청이 아닙니다");
//            // 거래내역의 상대 Id와 Request로 전달받은 상대방의 정보와 다를 경우
//        } else if ((opponentUserId != barter.getBuyerId()) && (opponentUserId != barter.getSellerId())) {
//            throw new ResponseStatusException(HttpStatus.NOT_ACCEPTABLE, "올바른 요청이 아닙니다");
//            // 자기 자신에게 점수를 줄 경우
//        } else if (opponentUserId == user.getId()) {
//            throw new ResponseStatusException(HttpStatus.NOT_ACCEPTABLE, "올바른 요청이 아닙니다");
//            // 거래가 완료되지 않았을 경우
//        } else if (barter.getStatus() == 0) {
//            throw new ResponseStatusException(HttpStatus.NOT_ACCEPTABLE, "올바른 요청이 아닙니다");
//        }

        //협의 중 -> 총점수 = 이전의 총점수 + 평가된 평점
        opponentUserTotalGrade = opponentUserTotalGrade + gradeScore;
        // 평가자수 +1
        opponentRaterCnt = opponentRaterCnt + 1;
        // 유저의 평균 평점
        opponentGrade = opponentUserTotalGrade / opponentRaterCnt;

        // 10분이네 응답 보너스
        // 내 포지션 확인
        String myPosition = null;
        if (barter.getSellerId().equals(opponentUserId)) {
            myPosition = "buyer";
        } else {
            myPosition = "seller";
        }

        System.out.println("내 포지션은 : " + myPosition);

        ChatRoom chatRoomChek;
        List<ChatMessage> myMessageList;
        List<ChatMessage> opponentMessageList;

        // 내 포지션이 바이어라면 -> roomId를 모를 떄
        if (myPosition.equals("buyer")) {
            chatRoomChek = chatRoomRepository.findMyRequestChatRoom(user.getId(), opponentUserId);
            // 내포지션이 셀러라면
        } else {
            chatRoomChek = chatRoomRepository.findMyAcceptorIdChatRoom(user.getId(), opponentUserId);
        }
        System.out.println("채팅방 아이디 " + chatRoomChek.getId());
        System.out.println("유저아이디 " + user.getId());
        System.out.println("상대 아이디 :" + opponentUserId);
        Long chatRoomId = chatRoomChek.getId();
        Long myUserId = user.getId();
        myMessageList = chatMessageRepository.findMyChatMessage(myUserId , chatRoomId);
        opponentMessageList = chatMessageRepository.findMyChatMessage(opponentUserId, chatRoomId);

        System.out.println("채팅방 아이디는 : " + chatRoomChek.getRequesterId());

        // 각자의 최초 메시지의 시간을 조회한다
        int cnt = 0;
        LocalDateTime firstMyTime = null;
        LocalDateTime firstOppoentTime = null;
        for (ChatMessage myChat : myMessageList) {
            System.out.println("내 첫메시지 내용 : " + myChat.getMessage());
            firstMyTime = myChat.getCreatedAt();
            cnt++;
            if (cnt == 1) {
                break;
            }
        }
        cnt = 0;
        for (ChatMessage opponetChat : opponentMessageList) {
            System.out.println("상대의 첫 메시지 내용 : " + opponetChat.getMessage());
            firstOppoentTime = opponetChat.getCreatedAt();
            cnt++;
            if (cnt == 1) {
                break;
            }
        }

        System.out.println("내 첫메시지 : " + firstMyTime.getMinute());
        Long minute = ChronoUnit.MINUTES.between(firstMyTime, firstOppoentTime);

        System.out.println("비투인 사이 시간 " + minute);
        boolean chatTime = false;
        if (minute <= 10) {
            chatTime = true;
            System.out.println("10분 이내인가 : " + chatTime);
        }
        //


        // 상대의 전체 점수에 1, 2은 - / 3은 0 / 4, 5은 +
        if (gradeScore <= 2) {
            opponentUserTotalGrade = opponentUserTotalGrade - (gradeScore - 3.0f);
        } else if (gradeScore >= 4) {
            opponentUserTotalGrade = opponentUserTotalGrade + (3 - gradeScore);
        }
        // 10분 이내 응답했을 때의 보너스
        if (chatTime) {
            opponentUserTotalGrade = opponentUserTotalGrade + 2.0f;
        }


        //임의로 넣어줌 -> 상의해야됨
        if (opponentUserTotalGrade >= 200.0f) {
            opponentDegree = "물물박사";
        } else if (opponentUserTotalGrade >= 100.0f) {
            opponentDegree = "물물석사";
        } else if (opponentUserTotalGrade >= 30.0f) {
            opponentDegree = "물물학사";
        } else if (opponentUserTotalGrade >= 10.0f) {
            opponentDegree = "물물학생";
        } else {
            opponentDegree = "물물어린이";
        }

        opponentUser.updateScore(
                opponentUserTotalGrade,
                opponentGrade,
                opponentRaterCnt,
                opponentDegree
        );

        // 거래완료인 상태가 아니면 예외처리


        String[] barterIdList = barter.getBarter().split(";");
        String[] buyerItemId = barterIdList[0].split(",");
        String sellerItemId = barterIdList[1];

        int status = 4;
        for (String eachBuyer : buyerItemId) {
            Long buyerId = Long.valueOf(eachBuyer);
            Item buyerItem = itemRepository.findById(buyerId).orElseThrow(
                    () -> new IllegalArgumentException("buyerItem not found"));
            buyerItem.statusUpdate(buyerItem.getId(), status);
        }
        //셀러(유저)의 물품을 찾아서 정보를 넣기
        Long sellerId = Long.parseLong(sellerItemId);
        Item sellerItem = itemRepository.findById(sellerId).orElseThrow(
                () -> new IllegalArgumentException("sellerItem not found")
        );
        sellerItem.statusUpdate(sellerItem.getId(), status);
        // 유저 정보를 업데이트 이후 status를 거래완료(3) -> 평가완료(4)으로 업데이트를 한다.
        barter.updateBarter(status);
    }
}

 

채팅 메시지 레포지토리

package com.sparta.mulmul.repository.chat;

import com.sparta.mulmul.model.ChatMessage;
import com.sparta.mulmul.model.ChatRoom;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

public interface ChatMessageRepository extends JpaRepository<ChatMessage, Long> {
    ChatMessage findByUserId(Long oppentUserId);

    List<ChatMessage> findAllByRoomIdAndUserId(Long roomId, Long userId);

    // 내가 요청받은 채팅방
    @Query("SELECT cm FROM ChatMessage cm WHERE cm.userId =:userId AND cm.roomId =:roomId")
    List<ChatMessage> findMyChatMessage(@Param("userId") Long userId, @Param("roomId") Long roomId);
}

채팅룸 메시지 레포지토리

package com.sparta.mulmul.repository.chat;

import com.sparta.mulmul.model.ChatRoom;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;


public interface ChatRoomRepository extends JpaRepository<ChatRoom, Long> {
    ChatRoom findByRequesterIdAndAcceptorId(Long id, Long opponentUserId);

    // 성훈 - 내 아이템 찾기 (마이페이지)
    // 내가 요청한 채팅방
    @Query("SELECT cr FROM ChatRoom cr WHERE cr.requesterId =:userId AND  cr.acceptorId = :opponentUserId")
    ChatRoom findMyRequestChatRoom(@Param("userId") Long userId, @Param("opponentUserId") Long opponentUserId);


    // 내가 요청받은 채팅방
    @Query("SELECT cr FROM ChatRoom cr WHERE cr.requesterId = :opponentUserId AND cr.acceptorId = :userId")
    ChatRoom findMyAcceptorIdChatRoom(@Param("userId") Long userId, @Param("opponentUserId") Long opponentUserId);

}

 

 

출력결과

FALSE

더보기

거래상태 : 4
2번째 예외처리 : 2
바이어아이디 : 1
셀러아이디 : 2
내 포지션은 : buyer
Hibernate: select chatroom0_.room_id as room_id1_3_, chatroom0_.created_at as created_2_3_, chatroom0_.acceptor_id as acceptor3_3_, chatroom0_.acceptor_show as acceptor4_3_, chatroom0_.requester_id as requeste5_3_, chatroom0_.requester_show as requeste6_3_ from chat_room chatroom0_ where chatroom0_.requester_id=? and chatroom0_.acceptor_id=?
채팅방 아이디 1
유저아이디 1
상대 아이디 :2
Hibernate: select chatmessag0_.message_id as message_1_2_, chatmessag0_.created_at as created_2_2_, chatmessag0_.is_read as is_read3_2_, chatmessag0_.message as message4_2_, chatmessag0_.room_id as room_id5_2_, chatmessag0_.type as type6_2_, chatmessag0_.user_id as user_id7_2_ from chat_message chatmessag0_ where chatmessag0_.user_id=? and chatmessag0_.room_id=?
Hibernate: select chatmessag0_.message_id as message_1_2_, chatmessag0_.created_at as created_2_2_, chatmessag0_.is_read as is_read3_2_, chatmessag0_.message as message4_2_, chatmessag0_.room_id as room_id5_2_, chatmessag0_.type as type6_2_, chatmessag0_.user_id as user_id7_2_ from chat_message chatmessag0_ where chatmessag0_.user_id=? and chatmessag0_.room_id=?
채팅방 아이디는 : 1
내 첫메시지 내용 : ㅁㄴㅇㄹ
상대의 첫 메시지 내용 : ㅂㅈㄷㄱ
내 첫메시지 : 58
비투인 사이 시간 22

 

TRUE

더보기

거래상태 : 2
2번째 예외처리 : 2
바이어아이디 : 1
셀러아이디 : 2
내 포지션은 : buyer
Hibernate: select chatroom0_.room_id as room_id1_3_, chatroom0_.created_at as created_2_3_, chatroom0_.acceptor_id as acceptor3_3_, chatroom0_.acceptor_show as acceptor4_3_, chatroom0_.requester_id as requeste5_3_, chatroom0_.requester_show as requeste6_3_ from chat_room chatroom0_ where chatroom0_.requester_id=? and chatroom0_.acceptor_id=?
채팅방 아이디 1
유저아이디 1
상대 아이디 :2
Hibernate: select chatmessag0_.message_id as message_1_2_, chatmessag0_.created_at as created_2_2_, chatmessag0_.is_read as is_read3_2_, chatmessag0_.message as message4_2_, chatmessag0_.room_id as room_id5_2_, chatmessag0_.type as type6_2_, chatmessag0_.user_id as user_id7_2_ from chat_message chatmessag0_ where chatmessag0_.user_id=? and chatmessag0_.room_id=?
Hibernate: select chatmessag0_.message_id as message_1_2_, chatmessag0_.created_at as created_2_2_, chatmessag0_.is_read as is_read3_2_, chatmessag0_.message as message4_2_, chatmessag0_.room_id as room_id5_2_, chatmessag0_.type as type6_2_, chatmessag0_.user_id as user_id7_2_ from chat_message chatmessag0_ where chatmessag0_.user_id=? and chatmessag0_.room_id=?
채팅방 아이디는 : 1
내 첫메시지 내용 : ㅁㄴㅇㄹ
상대의 첫 메시지 내용 : ㅂㅈㄷㄱ
내 첫메시지 : 58
비투인 사이 시간 1
10분 이내인가 : true

 

채팅 웹소켓도입이후 새로 바뀐 ERD