일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
- 격파르타장점
- 프로그래머스제일작은수
- java map 출력
- java set 출력
- java map
- java list 출력
- java set 저장
- 격파르타비전공자
- 격파르타합격후기
- 노베이스부트캠프
- 코딩부트캠프후기
- 항해99후기
- java기본자료형
- 컴파일
- 프로그래머스
- javaJRE
- java참조자료형
- 비전공자sqld
- javaJVM
- java알고리즘
- java list 저장
- java 자료구조 활용
- java map 저장
- 항해15기
- 격파르타후기
- sqld자격증합격
- java알고리즘문제풀이
- java최솟값구하기
- 작은수제거하기
- 인터프린터언어
- Today
- Total
코딩과 결혼합니다
[Game_Crew] 유저 평점 기능 본문
⭐게임크루 프로젝트의 핵심 기능 : 유저 평점 기능
WHY?
유저들이 보다 우수한 게임 경험을 가질 수 있도록 돕기 위해 유저들이 게임 파트너를 선택하는 데에 유용한 참고자료를 제공하려 한다.
HOW?
게임을 함께 했던 유저들의 매너, 참여도, 실력, 재미, 친화력 등을 평가하여 종합 점수를 생성한다. 이 평점은 다른 유저들에게 제공되며, 게임 파트너를 선택하는 데 도움을 준다.
'유저 평점'이라는 기능을 도입하여 게임 크루 구성원들 간의 상호 신뢰도를 높이고, 원활한 게임 플레이를 위한 소통과 협력을 촉진하는 역할을 하고자 한다. 이 기능을 통해 게임크루 프로젝트는 유저들에게 더 나은 게임 경험을 제공하게 된다.
📌유저 평점 등록
//유저의 평점을 DB에 등록하는 API
@PostMapping("/rating/{evaluated_user}")
public MessageResponseDto registrationOfRatings(@RequestBody UserRatingRequestDto userRatingRequestDto,
@AuthenticationPrincipal UserDetailsImpl userDetails,
@PathVariable Long evaluated_user){
if (userRepository.findById(evaluated_user).isEmpty()) throw new CustomException(ErrorMessage.NON_EXISTENT_USER, HttpStatus.BAD_REQUEST, false);
User evaluator = userDetails.getUser();
ratingService.registrationOfRatings(userRatingRequestDto, evaluator, evaluated_user);
return new MessageResponseDto(Message.REGISTRATION_COMPLETED, HttpStatus.OK);
}
JWT 인증이 된 유저는 다른 유저와 게임 후에 평가를 할 수 있다.
evaluator(평가한 사람)은 @AuthenticationPrincipal UserDetailsImpl userDetails 를 통해서 user의 정보를 가져와주고,
evaluatedUser(평가 받은 사람) 는 @PathVariable 로 로그인이 안되어 있는 상태에서도 평가 받을 수 있게 하였다.
원래는 [userId]라는 key값으로 [rating]관련 테이블들과 연관관계를 맺으려 하였지만, 평가 받는 유저는 인증이 필요하지 않기 때문에 Long으로 값을 받아와야 해서 연관관계를 맺어줄 수 없었다. (User 클래스로 가져올 수 없음) 그래서 각각 따로 관리하고 로직을 적절하게 구현함으로써 DB에 저장하고 값을 불러오게끔 하였다.
✏️전적 테이블
@Entity
@Getter
@Setter
@NoArgsConstructor
public class RecordOfRatings{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
private Long id;
@Column(nullable = false)
private Long user; // 평가 받은 사람
@Column(nullable = false)
private Long evaluator; //평가한 사람
@Column(nullable = false)
private int manner;
@Column(nullable = false)
private int participation;
@Column(nullable = false)
private int gamingSkill;
@Column(nullable = false)
private int enjoyable;
@Column(nullable = false)
private int sociability;
@Column(nullable = false)
private double totalRating;
그동안 받았던 점수들을 확인할 수 있도록 RecordOfRatings 테이블을 구성하였다.
어떤 사람(evaluator)이 나(user)에게 점수를 어떻게 줬는지를 알 수 있도록!
✏️총 점수 테이블
@Entity
@Getter
@Setter
@NoArgsConstructor
public class TotalRating {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
private Long id;
@Column(nullable = false)
private Long evaluatedUserId; // 평가 받은 사람
@Column(nullable = false)
private double totalManner;
@Column(nullable = false)
private double totalParticipation;
@Column(nullable = false)
private double totalGamingSkill;
@Column(nullable = false)
private double totalEnjoyable;
@Column(nullable = false)
private double totalSociability;
@Column(nullable = false)
private double totalRating;
//...
public void setTotalManner(double totalManner) {
this.totalManner = Math.round(totalManner * 2) / 2.0;;
}
public void setTotalParticipation(double totalParticipation) {
this.totalParticipation = Math.round(totalParticipation * 2) / 2.0;;
}
public void setTotalGamingSkill(double totalGamingSkill) {
this.totalGamingSkill = Math.round(totalGamingSkill * 2) / 2.0;;
}
public void setTotalEnjoyable(double totalEnjoyable) {
this.totalEnjoyable = Math.round(totalEnjoyable * 2) / 2.0;;
}
public void setTotalSociability(double totalSociability) {
this.totalSociability = Math.round(totalSociability * 2) / 2.0;;
}
특정 유저의 총 점수를 나타내는 테이블로 유저 한 명당 딱 한 번만 DB에 저장될 것이고,set메서드로 계속해서 점수를 업데이트 시켜줄 것이다. 점수는 0.5점을 기준으로 하기 때문에 점수를 반올림해주는 메서드를 멤버변수마다 작성해준다.
✏️service
public void registrationOfRatings(UserRatingRequestDto userRatingRequestDto, User evaluator, Long evaluated_user) {
//request ...
Optional<TotalRating> checkRating = totalRatingRepository.findByEvaluatedUserId(evaluated_user);
if (checkRating.isEmpty()){
double totalRating = (double)(manner + participation + gamingSkill + enjoyable + sociability) / 5 ;
RecordOfRatings ratings = new RecordOfRatings(evaluated_user ,evaluatorId, manner, participation, gamingSkill, enjoyable, sociability, totalRating);
recordOfRatingsRepository.save(ratings);
TotalRating totalrating = new TotalRating(evaluated_user, manner, participation, gamingSkill, enjoyable, sociability, totalRating);
totalRatingRepository.save(totalrating);
totalRatingRepository( 총 평점 테이블 )에 입력받은 evaluated_user 가 없다면
recordOfRatingsRepository(전적) 와 totalRatingRepository(총 평점) 에 받은 값들을 그대로 저장해준다.
} else if (checkRating.isPresent()) {
TotalRating existingTotalRating = checkRating.get();
//있으면 저장된 점수 + 새로 들어온 점수 더하기 + /2
double totalManner = (existingTotalRating.getTotalManner() + manner)/2;
//...
double total =(totalManner + totalParticipation + totalGamingSkill + totalEnjoyable + totalSociability)/5;
existingTotalRating.setTotalManner(totalManner);
//...
existingTotalRating.setTotalRating(total);
double totalRating = (double)(manner + participation + gamingSkill + enjoyable + sociability) / 5 ;
RecordOfRatings ratings = new RecordOfRatings(evaluated_user ,evaluatorId, manner, participation, gamingSkill, enjoyable, sociability, totalRating);
recordOfRatingsRepository.save(ratings);
}
}
totalRatingRepository( 총 평점 테이블 )에 입력받은 evaluated_user 가 존재하면
이전의 점수에 새로 입력받은 점수를 합한 뒤 2로 나누어 준다. 그리고 set메서드로 정보를 업데이트 해준다.
마지막으로 RecordOfRatings에도 입력받은 값들을 저장해준다. 이렇게 업데이트 + 전적 저장을 반복한다.
📌유저 평점 조회
//유저의 평점을 가져오는 API
@GetMapping("/getRating/{evaluated_user}")
public UserTotalRatingResponseDto getUserRating(@PathVariable Long evaluated_user){
return ratingService.getUserRating(evaluated_user);
}
유저의 평점같은 경우에는 비로그인 유저도 확인할 수 있게 하였다. 마찬가지로 @PathVariable 로 평점을 조회하고 싶은 유저의 id를 입력받고
public UserTotalRatingResponseDto getUserRating(Long evaluated_user) {
Optional<TotalRating> checkUser= totalRatingRepository.findByEvaluatedUserId(evaluated_user);
if (checkUser.isEmpty()){
throw new CustomException(ErrorMessage.NON_EXISTENT_USER, HttpStatus.BAD_REQUEST, false);
}
TotalRating existingTotalRating = checkUser.get();
double totalManner = existingTotalRating.getTotalManner();
double totalParticipation = existingTotalRating.getTotalParticipation();
double totalGamingSkill = existingTotalRating.getTotalGamingSkill();
double totalEnjoyable =existingTotalRating.getTotalEnjoyable();
double totalSociability = existingTotalRating.getTotalSociability();
double total = existingTotalRating.getTotalRating();
return new UserTotalRatingResponseDto(totalManner, totalParticipation, totalGamingSkill, totalEnjoyable, totalSociability, total);
}
totalRatingRepository에서 값을 가져와 프런트로 넘겨준다.
✔️ 문제
위의 방식대로 평점을 낸다면 그동안 꾸준히 좋은 점수를 받다가 나쁜 점수를 한 번 받은 유저와, 그동안 나쁜 점수만 받다가 한 번 좋은 점수를 받은 유저와의 차이가 나지 않게 된다. 계속해서 이전 점수와 새로운 점수를 더해서 2로 나눌 뿐이기 때문이다.
✔️ 해결 방안
1. RecordRatingRepository에 평가한 시간을 추가한다.
2. 최근 전적들 최대 10개까지 모아서 더한 후에 평균을 낸다.
3. 10개가 안되는 전적을 가지고 있다면 (모든 점수들의 합 / 전적의 개수)를 해준다.
✔️ 문제2
중복되는 코드들이 많이 보인다. 일단은 프로젝트 기간이 얼마 안남았으니 MVP 기능을 끝낸 뒤에 리팩토링을 하여 코드의 가독성과 유지보수성을 높여야 겠다.
'코딩과 매일매일♥ > Game_Crew' 카테고리의 다른 글
[Game_Crew] 리팩토링 + 트러블슈팅 : 이메일 인증 코드 리팩토링 (0) | 2023.10.31 |
---|---|
[Game_Crew] 트러블슈팅 : 이메일 인증 완성 (0) | 2023.10.27 |
231026 - [Game_Crew]트러블슈팅 : CORS 설정하기 (0) | 2023.10.26 |
231025 - [Game_Crew]리팩토링 : Spring Security JWT 로그인 (0) | 2023.10.25 |
231025 - [Game_Crew]트러블슈팅 : 자동 배포 환경 구축 (0) | 2023.10.25 |