Skip to content

Commit 1ac6edc

Browse files
authored
feat : 레벨 다운 로직 추가 (#149)
1 parent ff81ea0 commit 1ac6edc

File tree

2 files changed

+75
-1
lines changed

2 files changed

+75
-1
lines changed

backend/src/main/java/com/back/domain/level/service/LevelUpService.java

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,5 +101,67 @@ public void checkAndProcessLevelUp(Member member) {
101101
}
102102
}
103103

104+
@Transactional
105+
public void checkLevelDown(Integer memberId, int xpBeforeRevoke, int revokedXp) {
106+
log.info("### [LEVELDOWN] START checkLevelDown for Member ID: {}", memberId);
107+
108+
Member member = memberRepository.findById(memberId)
109+
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND, "Member not found with id: " + memberId));
110+
111+
log.info(" [Current Status] Initial Level: {}, XP Before Revoke: {}, Revoked XP: {}",
112+
member.getLevel(), xpBeforeRevoke, revokedXp);
113+
114+
checkAndProcessLevelDown(member, xpBeforeRevoke, revokedXp);
115+
116+
memberRepository.save(member);
117+
118+
log.info("### [LEVELDOWN] END checkLevelDown. Final Level: {}, Final XP: {}, Final XP Req: {}",
119+
member.getLevel(), member.getXp(), member.getXpReq());
120+
}
121+
122+
private void checkAndProcessLevelDown(Member member, int xpBeforeRevoke, int revokedXp) {
123+
int currentLevel = member.getLevel();
124+
125+
// 레벨이 1보다 크고, XP가 0이 되어 롤백이 필요한 상황을 가정
126+
// (XP가 0이 아닌 다른 값이라면 레벨 다운이 필요 없다고 가정)
127+
while (currentLevel > 1 && member.getXp() == 0) {
128+
129+
int previousLevel = currentLevel - 1;
130+
131+
Optional<LevelXP> previousLevelXP = levelXPRepository.findById(previousLevel);
132+
133+
if (previousLevelXP.isEmpty()) {
134+
log.warn(" [LEVEL DOWN FAILED] Previous Level XP requirement not found for Level {}. Aborting rollback.", previousLevel);
135+
break;
136+
}
137+
138+
int xpToNextOfPreviousLevel = previousLevelXP.get().getXpToNext();
139+
140+
// 1. XP 복원 계산 (요청된 4990 XP로 복원되는 핵심 로직)
141+
// 복원 XP = (이전 레벨 요구 XP) + (회수 전 잔여 XP) - (회수된 XP)
142+
// 시나리오: 5000 + 390 - 400 = 4990
143+
int restoredXp = xpToNextOfPreviousLevel + xpBeforeRevoke - revokedXp;
144+
145+
// 2. 레벨 다운 처리
146+
currentLevel = previousLevel;
147+
member.setLevel(currentLevel);
148+
149+
// XP 복원 값 설정
150+
member.setXp(restoredXp);
151+
152+
log.info(" [LEVEL DOWN!] Member Leveled Down to {}. Restored XP: {}", currentLevel, restoredXp);
153+
154+
// 3. 다음 레벨 요구량(xpReq) 업데이트
155+
member.setXpReq(xpToNextOfPreviousLevel);
156+
log.info(" [XP Req Update] Next XP Required: {}", xpToNextOfPreviousLevel);
157+
158+
// 4. 레벨 다운 보상 회수 (필요하다면 로직 추가)
159+
// levelUpRewardService.revokeReward(member.getId(), previousLevel + 1);
160+
161+
// 단일 레벨 롤백만 처리하고 루프 종료
162+
break;
163+
}
164+
}
165+
104166

105167
}

backend/src/main/java/com/back/domain/reward/service/RewardService.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,21 @@ private void applyRewardContent(Member member, RewardContent content) {
191191
private void revokeRewardContent(Member member, RewardContent content) {
192192
switch (content.getContentType()) {
193193
case XP:
194-
member.setXp(Math.max(0, member.getXp() - content.getRewardValue()));
194+
// 1. XP 회수 전 값과 회수량을 저장
195+
int oldXp = member.getXp();
196+
int revokedXp = content.getRewardValue();
197+
198+
// 2. XP 감소 (0 미만 방지)
199+
member.setXp(Math.max(0, oldXp - revokedXp));
200+
201+
// 3. 레벨 다운 검사 로직 추가 및 인자 전달
202+
// XP가 실제로 감소했고, 회수량이 Level Up 경계를 넘어섰을 가능성이 있을 때만 호출
203+
if (member.getXp() < oldXp) {
204+
levelUpService.checkLevelDown(member.getId(), oldXp, revokedXp);
205+
}
195206
break;
196207

208+
197209
case MONEY:
198210
int newMoney = Math.max(0, member.getMoney() - content.getRewardValue());
199211
memberService.modifyMoney(member, newMoney);

0 commit comments

Comments
 (0)