feat: release version 1.0.7
This commit is contained in:
@@ -10,12 +10,14 @@
|
||||
import { releasedSongCharts } from '$lib/data/song-release.ts';
|
||||
import AnalysisResultView from '$lib/components/AnalysisResultView.svelte';
|
||||
import PresetManager from '$lib/components/PresetManager.svelte';
|
||||
import SongPicker from '$lib/components/SongPicker.svelte';
|
||||
import {
|
||||
additionalAwakeningsRequired,
|
||||
calculateBoardEffects,
|
||||
calculateUnitPower,
|
||||
combinationSearchLimits,
|
||||
countOptimizationCandidates,
|
||||
effectiveActiveProbability,
|
||||
generateAnchoredCombinationCandidates,
|
||||
generateCombinationCandidates,
|
||||
memoryParameterPermil,
|
||||
@@ -146,6 +148,7 @@
|
||||
$: songs = Array.from(new Map(charts.map((chart) => [chart.songId, { id: chart.songId, title: chart.title }])).values());
|
||||
$: if (!songs.some((song) => song.id === selectedSongId)) selectedSongId = songs[0]?.id ?? '';
|
||||
$: selectedChart = charts.find((chart) => chart.songId === selectedSongId && chart.difficulty === difficulty);
|
||||
$: scoreCalibrationLabel = selectedChart?.scoreCalibrationSource === 'measured' ? '실측값' : '추정값';
|
||||
$: baselineChartMetadata = baselineState
|
||||
? charts.find((chart) => chart.songId === baselineState!.songId && chart.difficulty === baselineState!.difficulty)
|
||||
: undefined;
|
||||
@@ -492,7 +495,7 @@
|
||||
function roughSkillValues(card: CardRow) {
|
||||
const adapted = toOptimizerCard(card, awakeningForCard(card), [0], [card]);
|
||||
const activeValue = adapted.active.scoreUpPercent * adapted.active.durationSeconds /
|
||||
Math.max(1, adapted.active.cooldownSeconds) * ((adapted.active.probabilityPercent ?? 100) / 100);
|
||||
Math.max(1, adapted.active.cooldownSeconds) * effectiveActiveProbability(adapted);
|
||||
const specialValue = adapted.special.scoreUpPercent * adapted.special.durationSeconds / 100;
|
||||
return { adapted, activeValue, specialValue };
|
||||
}
|
||||
@@ -502,7 +505,7 @@
|
||||
const skillPotential = cards.reduce((sum, card) => {
|
||||
const adapted = toOptimizerCard(card, awakeningForCard(card), [0], cards);
|
||||
const activeValue = adapted.active.scoreUpPercent * adapted.active.durationSeconds /
|
||||
Math.max(1, adapted.active.cooldownSeconds) * ((adapted.active.probabilityPercent ?? 100) / 100);
|
||||
Math.max(1, adapted.active.cooldownSeconds) * effectiveActiveProbability(adapted);
|
||||
const specialValue = adapted.special.scoreUpPercent * adapted.special.durationSeconds / 100;
|
||||
const activationValue = (adapted.special.activationRateUpPercent ?? 0) * adapted.special.durationSeconds / 100;
|
||||
const passiveValue = (adapted.passiveScoreSupportEffects ?? []).reduce((effectSum, effect) =>
|
||||
@@ -687,12 +690,12 @@
|
||||
const activationRate = boardEffects.activationRateUpByCardId[card.id] ?? 0;
|
||||
return {
|
||||
...adapted,
|
||||
active: { ...adapted.active, probabilityPercent: (adapted.active.probabilityPercent ?? 100) * (1 + activationRate / 100) },
|
||||
active: { ...adapted.active, activationRateUpPercent: activationRate },
|
||||
scoreSupportPercent: power.outfitScoreSupportPercent + boardEffects.scoreSupportPercent
|
||||
};
|
||||
});
|
||||
const skillPotential = optimizerCards.reduce((sum, card) => sum +
|
||||
card.active.scoreUpPercent * card.active.durationSeconds / Math.max(1, card.active.cooldownSeconds) * ((card.active.probabilityPercent ?? 100) / 100) +
|
||||
card.active.scoreUpPercent * card.active.durationSeconds / Math.max(1, card.active.cooldownSeconds) * effectiveActiveProbability(card) +
|
||||
card.special.scoreUpPercent * card.special.durationSeconds / 100 +
|
||||
(card.scoreSupportPercent ?? 0) +
|
||||
(card.passiveScoreSupportEffects ?? []).reduce((effectSum, effect) => effectSum + effect.percent * (effect.target === 'all' ? 5 : effect.targetCount ?? 1), 0), 0);
|
||||
@@ -748,7 +751,7 @@
|
||||
const activationRate = boardEffects.activationRateUpByCardId[card.id] ?? 0;
|
||||
return {
|
||||
...adapted,
|
||||
active: { ...adapted.active, probabilityPercent: (adapted.active.probabilityPercent ?? 100) * (1 + activationRate / 100) },
|
||||
active: { ...adapted.active, activationRateUpPercent: activationRate },
|
||||
scoreSupportPercent: power.outfitScoreSupportPercent + boardEffects.scoreSupportPercent
|
||||
};
|
||||
});
|
||||
@@ -1035,9 +1038,9 @@
|
||||
<section class="panel" aria-labelledby="conditions-title">
|
||||
<div class="section-title"><div><span>01</span><h2 id="conditions-title">탐색 조건</h2></div><strong>{ownedCardsOnly ? '보유 5성 대상' : '5성 전체 대상'}</strong></div>
|
||||
<div class="song-fields">
|
||||
<label>악곡<select bind:value={selectedSongId} on:change={() => result = null}>{#each songs as song}<option value={song.id}>{song.title}</option>{/each}</select></label>
|
||||
<div class="song-picker-field"><SongPicker {charts} {difficulty} bind:value={selectedSongId} on:change={() => result = null} /></div>
|
||||
<label>난이도<select bind:value={difficulty} on:change={() => result = null}><option value="expert">Expert</option><option value="hard">Hard</option></select></label>
|
||||
<div class="chart-meta"><span>길이 {selectedChart?.durationSeconds ?? 0}초</span><span>노트 {selectedChart?.totalNotes?.toLocaleString('ko-KR') ?? 0}개</span></div>
|
||||
<div class="chart-meta"><span>길이 {selectedChart?.durationSeconds ?? 0}초</span><span>노트 {selectedChart?.totalNotes?.toLocaleString('ko-KR') ?? 0}개</span><span>점수 계수 · {scoreCalibrationLabel}</span></div>
|
||||
</div>
|
||||
<div class="candidate-fields">
|
||||
<div class="candidate-awakening">
|
||||
@@ -1199,8 +1202,9 @@
|
||||
label { display: grid; gap: 7px; color: #8f98a8; font-size: 14px; font-weight: 750; }
|
||||
select, .number-input { width: 100%; min-width: 0; height: 42px; padding: 0 12px; border: 1px solid #343c49; border-radius: 9px; color: #e8ebf1; background: #11151b; font: inherit; }
|
||||
select:focus, .number-input:focus, .generation-input:focus { border-color: #d86f9c; outline: 3px solid rgb(216 111 156 / 14%); }
|
||||
.song-fields { display: grid; grid-template-columns: minmax(0, 2fr) clamp(110px, 11vw, 170px) minmax(220px, .8fr); align-items: end; gap: 12px; margin-top: 22px; }
|
||||
.chart-meta { display: flex; align-items: center; gap: 8px; height: 42px; }
|
||||
.song-fields { display: grid; grid-template-columns: minmax(0, 4fr) clamp(110px, 11vw, 170px) minmax(220px, .8fr); align-items: start; gap: 12px; margin-top: 22px; }
|
||||
.song-picker-field { min-width: 0; }
|
||||
.chart-meta { display: flex; align-items: center; gap: 8px; height: 42px; margin-top: 25px; }
|
||||
.chart-meta span { padding: 7px 9px; border-radius: 7px; color: #adb5c2; background: #202631; font-size: 13px; white-space: nowrap; }
|
||||
.candidate-fields { display: grid; grid-template-columns: clamp(130px, 12vw, 180px) clamp(260px, 24vw, 380px); gap: 9px; margin-top: 18px; }
|
||||
.candidate-awakening { display: grid; gap: 7px; color: #8f98a8; font-size: 14px; font-weight: 750; }
|
||||
@@ -1305,7 +1309,7 @@
|
||||
main { width: calc(100% - 24px); padding-top: var(--page-content-top); }
|
||||
.panel { padding: 17px; }
|
||||
.song-fields { grid-template-columns: 1fr 100px; }
|
||||
.chart-meta { grid-column: 1 / -1; height: auto; }
|
||||
.chart-meta { grid-column: 1 / -1; height: auto; margin-top: 0; }
|
||||
.candidate-fields { grid-template-columns: 1fr; }
|
||||
.fixed-column-headings { display: none; }
|
||||
.fixed-field { grid-template-columns: minmax(0, 1fr) 102px; }
|
||||
|
||||
Reference in New Issue
Block a user