diff --git a/src/routes/analysis/+page.svelte b/src/routes/analysis/+page.svelte index e88841d..e085577 100644 --- a/src/routes/analysis/+page.svelte +++ b/src/routes/analysis/+page.svelte @@ -46,6 +46,7 @@ fixedCooldownReductions?: (CooldownReduction | null)[]; allBlueNodes?: boolean[]; generationBonusOverrides?: (number | null)[]; + songScoreBonusOverride?: number | null; leaderCharacterId: string; leaderOutfitCardId: string; }; @@ -96,6 +97,7 @@ let fixedCooldownReductions: (CooldownReduction | null)[] = selectedCardIds.map(() => null); let allBlueNodes = selectedCardIds.map(() => false); let generationBonusOverrides: (number | null)[] = selectedCardIds.map(() => null); + let songScoreBonusOverride: number | null = null; let leaderCharacterId = leaderMembers[0]?.characterId ?? ''; let leaderOutfitCardId = leaderMembers[0]?.id ?? ''; let worker: Worker | null = null; @@ -141,7 +143,10 @@ $: boardEffects = calculateBoardEffects(boardSummary, effectiveMemberBoards, selectedSourceCards, leaderCharacterId, selectedChart, { placements: boardCards, cards: connectionCards - }, { generationBonusByCardId }); + }, { + generationBonusByCardId, + ...(songScoreBonusOverride === null ? {} : { directSongScoreBonusPercent: songScoreBonusOverride }) + }); $: memoryPermil = memoryParameterPermil(memoryCount, memorySummary.effects); $: unitPower = (() => { try { @@ -180,6 +185,7 @@ fixedCooldownReductions, allBlueNodes, generationBonusOverrides, + songScoreBonusOverride, leaderCharacterId, leaderOutfitCardId } satisfies SavedAnalysisState; @@ -192,6 +198,7 @@ fixedCooldownReductions, allBlueNodes, generationBonusOverrides, + songScoreBonusOverride, leaderCharacterId, leaderOutfitCardId }); @@ -301,6 +308,7 @@ if (!legacy && state.schemaVersion !== 2) return; if (typeof state.songId === 'string' && songs.some((song) => song.id === state.songId)) selectedSongId = state.songId; if (state.difficulty === 'hard' || state.difficulty === 'expert') difficulty = state.difficulty; + songScoreBonusOverride = normalizeSongScoreBonusOverride(state.songScoreBonusOverride); if (Array.isArray(state.cardIds) && state.cardIds.length === 5) { const restoredCards = state.cardIds.map((id) => cardById.get(id)).filter((card): card is CardRow => Boolean(card)); @@ -380,6 +388,19 @@ result = null; } + function normalizeSongScoreBonusOverride(value: unknown): number | null { + if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) return null; + return Math.min(10, value); + } + + function updateSongScoreBonusOverride(input: HTMLInputElement): void { + const parsed = Number(input.value); + if (input.value.trim() === '' || !Number.isFinite(parsed) || parsed < 0) input.value = ''; + if (parsed > 10) input.value = '10'; + songScoreBonusOverride = input.value === '' ? null : Math.min(10, parsed); + result = null; + } + function boardsForSelectedCards( storedBoards: MemberBoards, cardIds: readonly string[], @@ -439,7 +460,10 @@ const localBoardEffects = calculateBoardEffects(boardSummary, effectiveMemberBoards, selectedSourceCards, leaderCharacterId, chartSummary, { placements, cards: connectionCards - }, { generationBonusByCardId }); + }, { + generationBonusByCardId, + ...(songScoreBonusOverride === null ? {} : { directSongScoreBonusPercent: songScoreBonusOverride }) + }); const localUnitPower = calculateUnitPower(selectedCardIds.map((id, index) => ({ card: cardById.get(id)!, awakening: selectedAwakenings[index] })), leaderOutfit, localBoardEffects, memoryPermil, memberPowerUpPercent); @@ -776,8 +800,11 @@ +
자동 계산 종합력{overallPower.toLocaleString('ko-KR')}
-
길이 {selectedChart?.durationSeconds ?? 0}초노트 {selectedChart?.totalNotes?.toLocaleString('ko-KR') ?? 0}개1노트 {Math.ceil(perfectNoteScore).toLocaleString('ko-KR')}점 · {scoreCalibrationLabel}{#if boardEffects.directSongScoreBonusPercent > 0}가창 보너스 {boardEffects.directSongScoreBonusPercent}%{/if}
+
길이 {selectedChart?.durationSeconds ?? 0}초노트 {selectedChart?.totalNotes?.toLocaleString('ko-KR') ?? 0}개1노트 {Math.ceil(perfectNoteScore).toLocaleString('ko-KR')}점 · {scoreCalibrationLabel}{#if boardEffects.directSongScoreBonusPercent > 0 || songScoreBonusOverride !== null}가창 보너스 {boardEffects.directSongScoreBonusPercent}%{songScoreBonusOverride === null ? '' : ' · 덮어쓰기'}{/if}
@@ -835,7 +862,7 @@
{/each} -

‘파란 노드 전체’를 사용하지 않으면 사용자 데이터에 저장된 해당 멤버의 보드를 사용합니다. 기수 보너스는 빈칸이면 실제 보드 수치를 사용하고, 숫자를 입력하면 해당 값으로 대체합니다.

+

‘파란 노드 전체’를 사용하지 않으면 사용자 데이터에 저장된 해당 멤버의 보드를 사용합니다. 기수 보너스와 가창 보너스 덮어쓰기는 빈칸이면 실제 보드 수치를 사용하고, 숫자를 입력하면 해당 값으로 대체합니다.

+