Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] user stat 결과 경험치를 %로 치환해서 응답 #90

Merged
merged 6 commits into from
Feb 6, 2024
Merged

[FEAT] user stat 결과 경험치를 %로 치환해서 응답 #90

merged 6 commits into from
Feb 6, 2024

Conversation

05AM
Copy link
Member

@05AM 05AM commented Jan 25, 2024

☀️ 작업 사항

  • 경험치 계산, 레벨 업 등의 프로세스를 user 클래스 내부로 이동
  • user 멤버변수 experience -> expPoint로 이름 변경
  • room id가 null일 경우 room을 찾을 수 없어 notification 전송 메소드에서 에러가 발생하기 때문에 null 검사 로직 추가

☀️ 참고 사항

  • 변경된 user 멤버변수 이름은 이후에 db에 반영할 예정입니다.

@05AM 05AM added the FEATURE 새로운 기능 label Jan 25, 2024
@05AM 05AM requested a review from hye-on January 25, 2024 15:13
@05AM 05AM self-assigned this Jan 25, 2024
Copy link
Contributor

@hye-on hye-on left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이번주에 클린코드 읽었더니 변수이름에 초점이 많이 맞춰지네요 ㅋㅋㅋ
고생하셨습니다. 👍

@@ -56,7 +57,7 @@ public LoginRes socialLogin(SocialLoginReq socialLoginReq) {
.email(socialUserRes.getEmail())
.accessToken(accessToken)
.avatarId(userAvatarService.getUserAvatarId(user.getId()))
.userStat(userService.getUserStat(user))
.userStat(UserStat.from(user))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

함수이름을 from이라고 지은 이유가 궁금해요!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

정적 팩토리 메소드로 인수인 user에서 정보를 가져와 생성한다는 의미를 담았습니다.
from은 주로 하나의 매개변수를 받을 때 사용하는 네이밍 입니다.

https://velog.io/@saint6839/%EC%A0%95%EC%A0%81-%ED%8C%A9%ED%86%A0%EB%A6%AC-%EB%A9%94%EC%84%9C%EB%93%9C-%EB%84%A4%EC%9D%B4%EB%B0%8D-%EB%B0%A9%EC%8B%9D

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그렇군요 👍

Comment on lines 105 to 109
UserStat userStat = missionService.afterMissionComplete(userId, missionLogCreateReq);
notificationService.sendNotificationToUsersInRoom(missionLogCreateReq.getAlarmId(), userId);
// TODO: 비즈니스 로직 제거하기
if (Objects.nonNull(missionLogCreateReq.getRoomId())) {
notificationService.sendNotificationToUsersInRoom(missionLogCreateReq.getAlarmId(), userId);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// TODO: 비즈니스 로직 제거하기
->
저번 코드 리뷰에서 오해가 있어서 컨트롤러에 옮겼었는데
노티를 보내는 부분을 다시 afterMissionComplete에 옮기면 어떨까요? (@transactional이 걸리긴 해요)

Copy link
Member Author

@05AM 05AM Jan 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분은 조금 더 알아본 후에 답장을 달겠습니다! 📌
조언 받아보고 시일 안에 업데이트 하겠습니다!!

Comment on lines 132 to 147
@Transactional
public UserStat afterMissionComplete(int userId, MissionLogCreateReq req) {
createMissionLog(userId, req);
return userService.userProgress(userId);
}

// TODO : 미션 수행 기록 추가 + REQUEST 수정하기
public void createMissionLog(int userId, MissionLogCreateReq req) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new BaseException(Status.USER_NOT_FOUND));

createMissionLog(user, req);
userService.userProgress(user);

return UserStat.from(user);
}

// TODO : 미션 수행 기록 추가 + REQUEST 수정하기
public void createMissionLog(User user, MissionLogCreateReq req) {
Alarm alarm = alarmRepository.findById(req.getAlarmId())
.orElseThrow(() -> new BaseException(Status.ALARM_NOT_FOUND));

Copy link
Contributor

@hye-on hye-on Jan 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

createMissionLog에 userId를 넘기던 것을 왜 user를 넘기게 수정한 것인지 궁금해요

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

afterMissionComplete에 user를 조회하는 코드가 이미 존재해서 코드 중복을 줄였습니다!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아하 근데 이전 afterMissionComplete에 user를 조회하는 코드가 없어보여요!
(이전 코드가 더 좋다는게 아니라 궁금해서 물어보는 겁니다!)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오잉 저번부터 왜 이전 코드가 전부 안 보이는지 모르겠지만 원래는 아래 코드였습니다.

// TODO : 미션 수행 기록 추가 + REQUEST 수정하기
    public void createMissionLog(int userId, MissionLogCreateReq req) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new BaseException(Status.USER_NOT_FOUND));

        Alarm alarm = alarmRepository.findById(req.getAlarmId())
                .orElseThrow(() -> new BaseException(Status.ALARM_NOT_FOUND));

        Room room = Objects.isNull(req.getRoomId())
                ? null
                : roomRepository.findById(req.getRoomId())
                        .orElseThrow(() -> new BaseException(Status.ROOM_NOT_FOUND));

        MissionLog missionLog = MissionLog.builder()
                .alarmName(alarm.getName())
                .missionPicLink(req.getMissionPicLink())
                .user(user)
                .room(room)
                .build();

        missionLogRepository.save(missionLog);
    }

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아하 근데 createMissionLog 말고 afterMissionComplete 말씀하신거
아니였나요??

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

createMissionLog()에도 user를 조회하는 로직이 있었는데 afterMissionComplte()에서 공통으로 조회하고 createMissionLog()에서 중복되는 로직이 빠졌습니다.

@@ -67,7 +67,7 @@ public class User {
private Integer level;

@Column(name = "experience")
private Integer experience;
private Integer expPoint;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p3 : 아래도 포인트가 있어서 헷갈릴 것같아요!
혹시 다른 후보가 뭐가 있었나요??

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

chatGPT를 참고했습니다!
expPercentage와 expBar 등의 이름은 경험치가 몇 %인지와 관련된 변수 이름이고,
expPoint는 정수형 변수에 맞는 이름이라고 생각해 선택하게 되었습니다.

그냥 계산한 결과인 expPercent만을 변수로 하지 않고 expPoint를 저장한 이유는 전자로 구현할 경우 계산식이 복잡해지고, 이후 부동소수점끼리 계산할 때 오류가 발생할 수 있다고 생각했습니다.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아하 int로 저장한거 좋은것같아요!
근데 point가 이미 있어서 exPoint하고 좀 헷갈리는것 같기도 하네요!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오타이실거라고 생각하지만, exPoint는 아니고 expPoint입니다.
exp는 게임에서 주로 사용하는 줄임말로 experience의 약자입니다.

많이 헷갈리신다면 point를 골드나 투게덥만의 화폐 이름으로 바꿔도 괜찮을 것 같습니다.
만약 생각하시는 변수명 예시가 있다면 추천해주시면 감사하겠습니다.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아 네네 잘못적었네요
그냥 경험옆에 양을 의미하는 변수를 추가하는거 좋은 것같아요👍

포인트를 말씀하신대로 바꿔도 좋고 (디자인에 포인트 부분에 코인그림이 있으니까 골드도 좋은것같아요!) experienceAmount 도 생각나네요!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://en.wikipedia.org/wiki/Experience_point

exp Point 는 보통 게임에서 자주 사용되는 도메인 용어로 해당 코드에서도 사용되는게 적합한 것 같습니다.
대신 추후에 point를 다른 이름으로 변경하겠습니다!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋아요 👍 👍

Comment on lines 124 to +126
public boolean checkUserLevelUpAvailable(int threshold) {
return this.getExperience() >= threshold;
return this.getExpPoint() >= threshold;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

어떤 역할을하는 함수인지 궁금해요

Copy link
Member Author

@05AM 05AM Jan 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

함수명처럼 user의 levelup이 가능한지 판단하는 함수입니다!
혹시 어떤 부분이 이해하기 어려웠는지 알려주실 수 있나요?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

available 뜻때문에 헷갈렸어요!

Comment on lines 16 to 26
private final int point;

private UserStat(User user) {
this.level = user.getLevel();
this.expPercentage = user.calculateExpPercentage();
this.point = user.getPoint();
}

public static UserStat from(User user) {
return new UserStat(user);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Comment on lines +143 to +145
public int calculateLevelUpThreshold() {
return 10 + 16 * (level - 1);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

지금 위에 코드보니까 경험치가 10씩 증가하는데
임계치는 10 , 26, 42, 58 ,,, 식으로 증가하네요
100,150,200 이런식으로 딱 떨어지게 할 수도 있는데

임계치를 이렇게 설계하신 이유가 있는지 궁금해요!

(혹은 나중에 정책이 바뀔수도 있으니까 일반적인 경우로 설정하신건지 궁금하네요!)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

딱 떨어지면 경험치 바가 항상 몇 등분으로 나눠지는게 흥미롭지 않아 보여서 일부러 16을 더했습니다.
threshold와 획득하는 경험치는 몇 번의 테스트를 해본 결과 적당하다고 생각하는 수치로 정했습니다.
ex) 1레벨은 1번하면 레벨업
2레벨은 2번하면 레벨업
...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아하 그랬군요
이 정책이 최종발표때 급하게 만들어져서 공유가 안된 것 같아요.
(혹시 다른 팀원하고이야기 했었었나요??)
이번주 회의때 같이 이야기해 보면 좋을 것 같습니다!

예시처럼 빨리 레벨업 되는게 적당해서 좋은 것 같아요 👍

05AM added 4 commits February 6, 2024 10:15
- experience -> exp_point
- point -> coin
- 메서드, DTO 이름 수정
- 알림 전송 메서드를 `afterMissionComplete` 내부로 이동
- try-catch 문으로 알림 전송에 실패했을 때 예외처리
@05AM 05AM requested a review from hye-on February 6, 2024 01:26
Comment on lines 129 to +131
public AlarmType determineAlarmType() {
return Objects.isNull(room) ? AlarmType.PERSONAL : AlarmType.GROUP;
return isRoomAlarm() ? AlarmType.GROUP : AlarmType.PERSONAL;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 👍

Comment on lines 52 to +54
// TODO: 디버그용 삭제
System.out.println();
System.out.println("탐지할 객체 = " + object);
System.out.println("[감지된 객체]");
log.info("탐지할 객체 = " + object);
log.info("[감지된 객체]");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

훨씬 좋네요!

.experience(DEFAULT_USER_EXPERIENCE)
.point(DEFAULT_USER_POINT)
.expPoint(DEFAULT_USER_EXPERIENCE)
.coin(DEFAULT_USER_POINT)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DEFAULT_USER_POINT -> DEFAULT_USER_COIN 부탁해요!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네 고치고 머지하겠습니다!

@05AM 05AM merged commit af19414 into Wake-up-together-TogetUp:main Feb 6, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
FEATURE 새로운 기능
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants