From 71513153710c41088fbac42ac5e4cd05ad86345e Mon Sep 17 00:00:00 2001 From: caadiq Date: Thu, 16 Apr 2026 00:48:00 +0900 Subject: [PATCH] =?UTF-8?q?=EC=8B=AC=EB=B3=BC=20=EA=B3=84=EC=82=B0?= =?UTF-8?q?=EA=B8=B0:=20=ED=9A=A8=EA=B3=BC=EC=A0=81=20=EB=A7=8C=EB=A0=99?= =?UTF-8?q?=20=EC=B2=98=EB=A6=AC=20+=20=EC=84=B1=EC=9E=A5=EC=B9=98=20casca?= =?UTF-8?q?de=20=EA=B3=84=EC=82=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 성장치가 만렙까지 cascade 가능한 경우(effectivelyMax) 완료로 취급: 성장치에 (MAX) 표기, 남은 심볼/남은 일수/예상 완료일 '-', 입력/일퀘 버튼 비활성 - 체납 메소/남은 심볼을 성장치 cascade 방식으로 재계산: 여러 레벨을 한 번에 올릴 수 있는 경우도 정확히 반영 Co-Authored-By: Claude Opus 4.6 (1M context) --- frontend/src/features/symbol/Symbol.jsx | 94 ++++++++++++++++--------- 1 file changed, 62 insertions(+), 32 deletions(-) diff --git a/frontend/src/features/symbol/Symbol.jsx b/frontend/src/features/symbol/Symbol.jsx index 3636d0a..a08a412 100644 --- a/frontend/src/features/symbol/Symbol.jsx +++ b/frontend/src/features/symbol/Symbol.jsx @@ -120,7 +120,6 @@ function SymbolCard({ symbol, equipped, charId }) { const growth = progress?.growth ?? 0 const requireGrowth = symbol.levels?.find((l) => l.level === level)?.required_count || 0 const isMax = equipped && level >= symbol.max_level - const interactable = equipped && !isMax // 남은 심볼: 현재 레벨→만렙 까지 필요한 심볼 총합 (현재 성장치 차감) // 필요 메소: 현재 레벨→만렙 까지 필요한 메소 총합 @@ -128,19 +127,25 @@ function SymbolCard({ symbol, equipped, charId }) { const { remainingSymbols, remainingMeso, arrearMeso } = useMemo(() => { if (!equipped || !symbol.levels?.length) return { remainingSymbols: 0, remainingMeso: 0, arrearMeso: 0 } let sym = 0, meso = 0, arr = 0 + // 체납: 현재 성장치로 올릴 수 있는 레벨까지 누적 + let arrLv = level, arrG = growth + while (arrLv < symbol.max_level) { + const req = symbol.levels.find((l) => l.level === arrLv)?.required_count + const cost = symbol.levels.find((l) => l.level === arrLv)?.meso_cost + if (req == null || cost == null || arrG < req) break + arr += cost + arrG -= req + arrLv += 1 + } + let g = growth for (const l of symbol.levels) { if (l.level < level) continue - if (l.level === level) { - sym += Math.max(l.required_count - growth, 0) - meso += l.meso_cost - if (growth >= l.required_count) arr += l.meso_cost - } else { - sym += l.required_count - meso += l.meso_cost - } + sym += Math.max(l.required_count - g, 0) + g = Math.max(g - l.required_count, 0) + meso += l.meso_cost } return { remainingSymbols: sym, remainingMeso: meso, arrearMeso: arr } - }, [equipped, level, growth, symbol.levels]) + }, [equipped, level, growth, symbol.levels, symbol.max_level]) // 현재 성장치로 도달 가능한 최대 레벨 (연속 체납 반영) const reachableLevel = useMemo(() => { @@ -156,6 +161,10 @@ function SymbolCard({ symbol, equipped, charId }) { return lv }, [equipped, isMax, level, growth, symbol.levels, symbol.max_level]) + // 성장치로 만렙까지 도달 가능하지만 레벨업은 안 한 상태 + const effectivelyMax = equipped && !isMax && reachableLevel >= symbol.max_level + const interactable = equipped && !isMax && !effectivelyMax + // 남은 일수/예상 완료일 const { days: daysLeft, date: completeDate } = useMemo(() => { if (!equipped || isMax) return { days: null, date: null } @@ -192,7 +201,7 @@ function SymbolCard({ symbol, equipped, charId }) { / {symbol.max_level} - {equipped && !isMax && ( + {equipped && !isMax && !effectivelyMax && (