{mode === 'rating' ? '리더 레이팅' : '배치 분석'} · 갤산기
01

분석 조건

{candidateCount.toLocaleString('ko-KR')}개 후보
{#if mode === 'analysis'}
자동 계산 종합력{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 || songScoreBonusOverride !== null} 가창 보너스 {boardEffects.directSongScoreBonusPercent}%{songScoreBonusOverride === null ? '' : ' · 덮어쓰기'} {/if} 인게임 1노트 {inGamePerfectNoteScore.toLocaleString('ko-KR')}점

인게임 1노트는 일반 PERFECT 기준으로 가창 보너스를 반영한 점수입니다. 스킬·콤보 보너스는 제외하며, 기본점수의 소수점을 유지해 보너스를 적용한 뒤 올림합니다.

{:else}

가창 보너스 10% 고정 · 모든 추천 대상 곡에 동일하게 적용합니다. 종합력과 스킬 효과는 각 곡의 가창 조건에 맞춰 계산합니다.

{/if}
{#each selectedCardIds as selectedId, slot}
개화 (0~5)
{selectedAwakenings[slot]}
빈도 감소 고정
{#each REDUCTION_LOCK_OPTIONS as reduction} {/each}
파란 노드 전체 기수 보너스 덮어쓰기 (0~900) updateGenerationBonus(slot, sanitizeGenerationBonusInput(event.currentTarget, generationBonusOverrides[slot] ?? null))}>
{/each}

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

리더 의상 효과

{leaderOutfitDescription || '적용할 수 있는 의상이 없습니다.'}

{#if mode === 'analysis'}

최대 레벨 기준 · 기본 {unitPower.baseParameterTotal.toLocaleString('ko-KR')} + 개화 {unitPower.potentialTotal.toLocaleString('ko-KR')} + 패시브 {unitPower.passiveTotal.toLocaleString('ko-KR')} + 의상 {unitPower.outfitTotal.toLocaleString('ko-KR')} + 보드 {unitPower.boardTotal.toLocaleString('ko-KR')} + 메모리 {unitPower.memoryTotal.toLocaleString('ko-KR')} ({memoryCount}개) + 멤버 강화 {unitPower.memberPowerUpTotal.toLocaleString('ko-KR')} ({memberPowerUpPercent.toLocaleString('ko-KR')}%)

{/if} {#if errorMessage}{/if} {#if mode === 'analysis'} {#if running}{/if} {/if}
{#if mode === 'rating'} {/if} {#if mode === 'analysis' || result}
{mode === 'rating' ? '03' : '02'}

분석 결과

{#if transferredResult}

{transferredSource} 당시의 계산 결과입니다. 다시 분석하면 현재 사용자 데이터를 적용합니다.

{/if} {#if resultStale || pendingStale}

입력 조건 또는 사용자 데이터가 변경되었습니다. {resultStale ? '아래는 이전 조건의 결과입니다. ' : ''}{pendingStale ? '진행 중인 분석은 시작 당시 조건으로 계속 계산합니다. ' : ''}최신 조건을 적용하려면 다시 분석해 주세요.

{/if} {#if mode === 'analysis' && resultCapture}

{resultCapture.title} · {difficultyLabel(resultCapture.settings.difficulty)} · 분석 당시 종합력 {resultCapture.overallPower.toLocaleString('ko-KR')}

{/if} {#if mode === 'rating' && result}

{selectedChart?.title} · {difficultyLabel(difficulty)} · 종합력 {overallPower.toLocaleString('ko-KR')} · 가창 보너스 10%

{/if} {#if result} {#if mode === 'analysis' && cooldownRankings.length > 0}

빈도 조합 상위 {cooldownRankings.length}개

빈도 감소 조합마다 최적의 스페셜 순서를 구해 최고점 내림차순으로 표시합니다. 확률은 각 조합의 최고점 기준이며, 결과를 선택하면 아래 상세 점수와 그래프에 반영됩니다.

{#each cooldownRankings as ranking, index} {/each}
순위카드별 빈도 감소최고점예상 점수100% 달성99.5% 이상99% 이상95% 이상
{#each ranking.result.formationOrder as cardId}
{resultCardName(cardId)} {ranking.result.cooldownReductions[cardId]}%
{/each}
{ranking.result.theoreticalMaxScore.toLocaleString('ko-KR')} {ranking.result.expectedScore.toLocaleString('ko-KR')} {probabilityLabel(ranking.achievementProbabilities?.maximum)} {probabilityLabel(ranking.achievementProbabilities?.atLeast995Percent)}{scoreThreshold(ranking.result.theoreticalMaxScore, 0.995)}점 이상 {probabilityLabel(ranking.achievementProbabilities?.atLeast99Percent)}{scoreThreshold(ranking.result.theoreticalMaxScore, 0.99)}점 이상 {probabilityLabel(ranking.achievementProbabilities?.atLeast95Percent)}{scoreThreshold(ranking.result.theoreticalMaxScore, 0.95)}점 이상
{/if}

추천 스페셜 발동 순서

    {#each result.order as cardId, slot}
  1. {slot + 1}{resultCardName(cardId)}쿨타임 {result.cooldownReductions[cardId]}% 감소
  2. {/each}
예상 점수{displayedResult!.expectedScore.toLocaleString('ko-KR')}
최고점 · 밀어치기 적용{displayedResult!.theoreticalMaxScore.toLocaleString('ko-KR')}
{#if displayedResult!.withoutSpecialStartBonusScore !== undefined}
최고점 · 밀어치기 미적용{displayedResult!.withoutSpecialStartBonusScore!.toLocaleString('ko-KR')}
{/if}
스킬 미발동 기준{result.baselineScore.toLocaleString('ko-KR')}

두 최고점은 모두 PERFECT 기준입니다. 밀어치기 적용은 스페셜 시작과 같은 시각의 수동 판정 노트를 발동 이후에 처리하여 새 스페셜 효과를 받는 경우, 미적용은 해당 노트가 새 효과를 받지 않는 경우입니다. 롱노트 중간·마지막 자동 판정은 밀어치기가 불가능하므로 두 경우 모두 시작 경계의 새 스페셜 효과를 받지 않습니다. 일부 수동 판정만 밀어치기하면 두 점수 사이가 됩니다. 예상 점수·그래프·달성 확률은 밀어치기 적용 기준입니다.

{#if !simulatedResult && (mode === 'analysis' || achievementProbabilities)}
최고점 100%{probabilityLabel(achievementProbabilities?.maximum)}
최고점의 99.5% 이상{probabilityLabel(achievementProbabilities?.atLeast995Percent)}{scoreThreshold(result.theoreticalMaxScore, 0.995)}점 이상
최고점의 99% 이상{probabilityLabel(achievementProbabilities?.atLeast99Percent)}{scoreThreshold(result.theoreticalMaxScore, 0.99)}점 이상
최고점의 95% 이상{probabilityLabel(achievementProbabilities?.atLeast95Percent)}{scoreThreshold(result.theoreticalMaxScore, 0.95)}점 이상

모든 노트를 PERFECT로 처리한다고 가정하고 액티브 발동 확률만 반영합니다. 100%는 정확 계산, 99.5%·99%·95% 이상은 25,000회 반복 계산값이며 최고점에 영향을 주지 않는 발동 실패는 100% 달성 확률을 낮추지 않습니다.

{/if}

연결 카드 최적화

활성 노드는 유지하며, 편성 멤버의 파란 영역 연결 카드는 반드시 인근의 큰 발동률 노드를 포함합니다. 편성 밖 멤버의 보드도 현재 편성의 점수에 기여하는 효과는 최적화에 반영합니다. 빠른 배정 후 중앙 카드 교체·교환과 노란 보너스 상한에 따른 이동·교환을 전체 배치 점수로 최대 3차례 보정하며, 전역 최적해를 보장하지 않습니다. 초기 추천보다 기존 배치가 좋으면 기존 배치에서 개선을 탐색합니다. 이 조건 안에서 최고점을 최우선으로 비교하고 최고점이 같으면 액티브 발동률 UP 합계를 비교합니다. 두 값이 모두 같으면 기존 연결 카드 배치를 우선 유지합니다. 조건을 충족할 수 없거나 최종 검증에서 최고점이 낮아지면 기존 배치를 유지합니다.

{#if connectionOptimizationSnapshot}{/if}

단, 활성 노란 홀로워크 노드를 증폭 중인 카드는 이론상 고점을 높이는 데 필요한 경우에만 이동합니다. 점수가 같으면 발동률 증가보다 해당 카드의 기존 배치를 우선 유지합니다.

{#if connectionOptimizationProgress}
{connectionOptimizationProgress.stage}{#if connectionOptimizationProgress.total > 0}{connectionOptimizationProgress.completed.toLocaleString('ko-KR')} / {connectionOptimizationProgress.total.toLocaleString('ko-KR')}{/if}
{#if connectionOptimizationProgress.total > 0}{/if}
{/if} {#if connectionOptimizationError}{/if} {#if connectionOptimizationProposal}
예상 점수 {connectionOptimizationProposal.beforeExpected.toLocaleString('ko-KR')} → {connectionOptimizationProposal.afterExpected.toLocaleString('ko-KR')}{connectionOptimizationProposal.afterExpected >= connectionOptimizationProposal.beforeExpected ? '+' : ''}{(connectionOptimizationProposal.afterExpected - connectionOptimizationProposal.beforeExpected).toLocaleString('ko-KR')} 이론상 고점 {connectionOptimizationProposal.beforeMaximum.toLocaleString('ko-KR')} → {connectionOptimizationProposal.afterMaximum.toLocaleString('ko-KR')}{connectionOptimizationProposal.afterMaximum >= connectionOptimizationProposal.beforeMaximum ? '+' : ''}{(connectionOptimizationProposal.afterMaximum - connectionOptimizationProposal.beforeMaximum).toLocaleString('ko-KR')} 액티브 발동률 UP 합계 {connectionOptimizationProposal.beforeActivationRateUp.toLocaleString('ko-KR', { maximumFractionDigits: 2 })}% → {connectionOptimizationProposal.afterActivationRateUp.toLocaleString('ko-KR', { maximumFractionDigits: 2 })}%{connectionOptimizationProposal.afterActivationRateUp >= connectionOptimizationProposal.beforeActivationRateUp ? '+' : ''}{(connectionOptimizationProposal.afterActivationRateUp - connectionOptimizationProposal.beforeActivationRateUp).toLocaleString('ko-KR', { maximumFractionDigits: 2 })}%p
{#if connectionOptimizationProposal.assignments.length > 0}
{#each connectionOptimizationProposal.assignments as assignment (`${assignment.memberId}:${assignment.socketId}`)} {@const member = boardMembers.find((item) => item.id === assignment.memberId)} {@const previousCard = assignment.previousCardId ? allCardById.get(assignment.previousCardId) : null} {@const card = assignment.cardId ? allCardById.get(assignment.cardId) : null} {member?.name ?? assignment.memberId} · {connectionSocketName(assignment.memberId, assignment.socketId)}{previousCard ? `${previousCard.rarity}★ ${cardLabel(previousCard)}` : '비어 있음'} → {card ? `${card.rarity}★ ${cardLabel(card)}` : '배치 해제'} {/each}
{:else}

이번 보정에서는 기존 배치보다 좋은 배치를 찾지 못했습니다.

{/if}
{/if}

스킬 발동과 노트 분포

멤버별 액티브와 실제 적용 구간, 스페셜 순서를 같은 시간축에서 비교합니다.

{#each result.order as cardId}{resultCardName(cardId)}{/each}
현재 설정 최고점{displayedResult!.theoreticalMaxScore.toLocaleString('ko-KR')}점
원래 최고점{result.theoreticalMaxScore.toLocaleString('ko-KR')}점
원래 대비 변화{signedScoreChange(displayedResult!.theoreticalMaxScore - result.theoreticalMaxScore)}
{#if mode === 'analysis'} {#if toggleScoreChanges.length}
토글별 최고점 변화 · {toggleScoreChanges.length}건

최근 조작부터 표시합니다. 각 변화량은 클릭 직전 설정과 비교하며, 겹친 액티브에 따라 달라집니다.

    {#each toggleScoreChanges as change}
  1. {#if change.window}{resultCardName(change.window.cardId)} · {formatSeconds(change.window.startSeconds)}~{formatSeconds(change.window.endSeconds)} · {change.excluded ? '미발동' : '복원'}{:else}모두 복원{/if} change.before}>{signedScoreChange(change.after - change.before)} {change.before.toLocaleString('ko-KR')} → {change.after.toLocaleString('ko-KR')}점
  2. {/each}
{/if}

카드별 색칠된 구간을 클릭하면 해당 액티브만 미발동으로 계산합니다. 다시 클릭하면 복원됩니다. 배치와 쿨타임은 유지됩니다. 점수에 영향을 주는 구간은 불투명하게 표시하며, 내부 색이 진하고 테두리가 굵을수록 현재 설정에서 토글할 때 최고점 변화가 큽니다. 빗금은 미발동 상태이며, 해당 구간은 복원 시 영향력을 표시합니다. {#if excludedActiveWindows.length} {excludedActiveWindows.length}회 미발동 적용 중 미발동 적용 중에는 달성 확률을 표시하지 않습니다. 분석 기록에는 원래 분석 결과가 저장됩니다. {/if}

{/if} {#if mode === 'analysis'}
액티브 발동 목록 · 눌러서 미발동/복원

작은 그래프 대신 아래 버튼으로도 조작할 수 있습니다. 미발동으로 설정한 구간은 다시 누르면 복원됩니다.

{#each result.activeWindows as window} {@const excluded = excludedActiveWindows.some((item) => item.cardId === window.cardId && item.startSeconds === window.startSeconds)} {@const impact = activeImpacts.get(activeWindowKey(window))} {/each}
{/if}

그래프를 좌우로 밀면 전체 시간대를 확인할 수 있습니다.

{#each result.order as cardId, slot}
{slot + 1}{resultCardName(cardId)}
{#each result.activeWindows.filter((window) => window.cardId === cardId) as window} {@const impact = activeImpacts.get(activeWindowKey(window))} {/each}
{/each}
최종 액티브
{#each displayedEffectiveActiveWindows as window} 1 ? ` · 최대 ${window.maxOverlapCount}명 중 가장 높은 효과` : ''}`} role="img" aria-label={`${resultCardName(window.cardId)} 액티브가 ${formatSeconds(window.startSeconds)}부터 ${formatSeconds(window.endSeconds)}까지 적용`} > {/each}
스페셜
{#each result.specialWindows as window} {/each}
{#if simulationContext} {/if} {:else}
조건을 선택하고 분석을 시작하면 최적 배치와 각 멤버의 쿨타임 감소량이 여기에 표시됩니다.
{/if}
{/if}