feat: streamline search results and open captured analyses
Publish GitHub Pages output / publish (push) Successful in 54s
Publish GitHub Pages output / publish (push) Successful in 54s
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { ANALYSIS_TRANSFER_KEY, parseAnalysisTransfer, transferredAnalysisKey } from '$lib/models/analysis-transfer.ts';
|
||||
import { onMount, tick } from 'svelte';
|
||||
import LeaderSongRanking from '$lib/components/LeaderSongRanking.svelte';
|
||||
import { analytics } from '$lib/analytics.ts';
|
||||
@@ -119,6 +120,8 @@
|
||||
let pendingSimulationContext: SimulationContext | null = null;
|
||||
let resultInputKey = '';
|
||||
let pendingInputKey = '';
|
||||
let transferredResult = false;
|
||||
let transferredSource = '조합 탐색';
|
||||
let simulationBase: ExactOptimizationResult | null = null;
|
||||
let simulatedResult: ExactOptimizationResult | null = null;
|
||||
let excludedActiveWindows: SkillWindow[] = [];
|
||||
@@ -334,11 +337,46 @@
|
||||
analysisReady = true;
|
||||
}
|
||||
|
||||
if (mode === 'analysis') {
|
||||
try {
|
||||
const raw = sessionStorage.getItem(ANALYSIS_TRANSFER_KEY);
|
||||
if (raw) {
|
||||
const transfer = parseAnalysisTransfer(raw);
|
||||
restoreAnalysisState(JSON.stringify({ ...transfer.capture.settings, schemaVersion: 2 }));
|
||||
// Let hydration finish before mounting the result's reactive timeline.
|
||||
void tick().then(async () => {
|
||||
if (!mounted) return;
|
||||
result = transfer.result;
|
||||
resultCapture = transfer.capture;
|
||||
resultInputKey = transferredAnalysisKey(transfer.capture);
|
||||
achievementProbabilities = transfer.achievementProbabilities;
|
||||
simulationContext = { cards: transfer.cards, chart: transfer.chart, options: {
|
||||
perfectNoteScore: transfer.result.perfectNoteScore,
|
||||
directSongScoreBonusPercent: transfer.directSongScoreBonusPercent
|
||||
} };
|
||||
transferredResult = true;
|
||||
transferredSource = transfer.source === 'rating' ? '리더 레이팅' : '조합 탐색';
|
||||
await tick();
|
||||
requestAnimationFrame(() => {
|
||||
if (!mounted) return;
|
||||
const heading = document.getElementById('result-title');
|
||||
heading?.focus({ preventScroll: true });
|
||||
heading?.scrollIntoView({ behavior: 'instant', block: 'start' });
|
||||
});
|
||||
});
|
||||
sessionStorage.removeItem(ANALYSIS_TRANSFER_KEY);
|
||||
}
|
||||
} catch (error) {
|
||||
errorMessage = error instanceof Error ? error.message : '조합 탐색 결과를 읽지 못했습니다.';
|
||||
}
|
||||
}
|
||||
|
||||
worker = createScoreOptimizerWorker();
|
||||
worker.onmessage = (event) => {
|
||||
if (event.data.type === 'progress') progress = event.data.progress;
|
||||
if (event.data.type === 'result') {
|
||||
result = event.data.result;
|
||||
transferredResult = false;
|
||||
resultCapture = pendingCapture;
|
||||
resultInputKey = pendingInputKey;
|
||||
simulationContext = pendingSimulationContext;
|
||||
@@ -568,24 +606,13 @@
|
||||
throw new Error('서로 다른 멤버 5명과 성장 설정을 확인해 주세요.');
|
||||
}
|
||||
return { cards: context.cards, overallPower: context.unitPower.overallPower,
|
||||
directSongScoreBonusPercent: context.boardEffects.directSongScoreBonusPercent };
|
||||
}
|
||||
|
||||
async function showRatingResult(chart: NonNullable<typeof selectedChart>, rankingResult: ExactOptimizationResult, power: number, probabilities: ScoreAchievementProbabilities) {
|
||||
ratingResultKey = ratingInputKey;
|
||||
selectedSongId = chart.songId;
|
||||
difficulty = chart.difficulty as DifficultyKey;
|
||||
result = rankingResult;
|
||||
achievementProbabilities = probabilities;
|
||||
clearConnectionOptimizationProposal();
|
||||
await tick();
|
||||
resultCapture = structuredClone({
|
||||
settings: presetSnapshot,
|
||||
growth: { collection, memberBoards, boardCards, memoryCount, memberPowerUpPercent },
|
||||
title: chart.title, durationSeconds: chart.durationSeconds, overallPower: power,
|
||||
analyzedAt: new Date().toISOString()
|
||||
});
|
||||
document.getElementById('result-title')?.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
directSongScoreBonusPercent: context.boardEffects.directSongScoreBonusPercent,
|
||||
capture: structuredClone({
|
||||
settings: { ...presetSnapshot, songId: chart.songId, difficulty: chart.difficulty as DifficultyKey, songScoreBonusOverride: 10 },
|
||||
growth: { collection, memberBoards, boardCards, memoryCount, memberPowerUpPercent },
|
||||
title: chart.title, durationSeconds: chart.durationSeconds, overallPower: context.unitPower.overallPower,
|
||||
analyzedAt: new Date().toISOString()
|
||||
}) };
|
||||
}
|
||||
|
||||
function connectionSocketName(memberId: string, socketId: string): string {
|
||||
@@ -1068,12 +1095,13 @@
|
||||
{#if mode === 'rating'}
|
||||
<LeaderSongRanking {charts} leaderId={leaderCharacterId} leaderName={leaderMember?.name ?? ''}
|
||||
now={releaseNow} inputKey={ratingInputKey} disabled={!analysisReady || running || connectionOptimizationRunning || candidateCount === 0}
|
||||
getContext={ratingContext} onSelect={showRatingResult} />
|
||||
getContext={ratingContext} />
|
||||
{/if}
|
||||
|
||||
{#if mode === 'analysis' || result}
|
||||
<section class="panel result" aria-labelledby="result-title">
|
||||
<div class="section-title"><div><span>{mode === 'rating' ? '03' : '02'}</span><h2 id="result-title">분석 결과</h2></div></div>
|
||||
<div class="section-title"><div><span>{mode === 'rating' ? '03' : '02'}</span><h2 id="result-title" tabindex="-1">분석 결과</h2></div></div>
|
||||
{#if transferredResult}<p class="board-guide">{transferredSource} 당시의 계산 결과입니다. 다시 분석하면 현재 사용자 데이터를 적용합니다.</p>{/if}
|
||||
{#if resultStale || pendingStale}<p class="stale-warning" role="status">입력 조건 또는 사용자 데이터가 변경되었습니다. {resultStale ? '아래는 이전 조건의 결과입니다. ' : ''}{pendingStale ? '진행 중인 분석은 시작 당시 조건으로 계속 계산합니다. ' : ''}최신 조건을 적용하려면 다시 분석해 주세요.</p>{/if}
|
||||
{#if mode === 'analysis' && resultCapture}<p class="board-guide"><strong>{resultCapture.title} · {difficultyLabel(resultCapture.settings.difficulty)}</strong> · 분석 당시 종합력 {resultCapture.overallPower.toLocaleString('ko-KR')}</p>{/if}
|
||||
{#if mode === 'rating' && result}<p class="board-guide"><strong>{selectedChart?.title} · {difficultyLabel(difficulty)}</strong> · 종합력 {overallPower.toLocaleString('ko-KR')} · 가창 보너스 10%</p>{/if}
|
||||
@@ -1247,6 +1275,7 @@
|
||||
</main>
|
||||
|
||||
<style>
|
||||
#result-title { scroll-margin-top: 90px; }
|
||||
.stale-warning { margin: 14px 0; padding: 11px 14px; border: 1px solid #665333; border-radius: 9px; color: #edcf92; background: #292319; font-size: 13px; line-height: 1.6; }
|
||||
main { width: min(var(--page-max-width), calc(100% - var(--page-gutter))); margin: 0 auto; padding: var(--page-content-top) 0 80px; }
|
||||
.page-header { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; margin-bottom: var(--page-header-bottom); }
|
||||
|
||||
Reference in New Issue
Block a user