feat: add combination search workflow
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/// <reference lib="webworker" />
|
||||
|
||||
import { optimizeExactOrderAndCooldowns } from '../engine/index.ts';
|
||||
import type { ExactOptimizeOptions, ExactSongChart, OptimizerCard } from '../engine/index.ts';
|
||||
import { countOptimizationCandidates, optimizeExactOrderAndCooldowns } from '../engine/index.ts';
|
||||
import type { ExactOptimizationResult, ExactOptimizeOptions, ExactSongChart, OptimizerCard } from '../engine/index.ts';
|
||||
|
||||
type OptimizeRequest = {
|
||||
type: 'optimize-exact';
|
||||
@@ -11,17 +11,57 @@ type OptimizeRequest = {
|
||||
directSongScoreBonusPercent?: number;
|
||||
};
|
||||
|
||||
self.onmessage = (event: MessageEvent<OptimizeRequest>) => {
|
||||
if (event.data.type !== 'optimize-exact') return;
|
||||
type CombinationCandidate = {
|
||||
cards: OptimizerCard[];
|
||||
overallPower: number;
|
||||
perfectNoteScore: number;
|
||||
directSongScoreBonusPercent?: number;
|
||||
};
|
||||
|
||||
type CombinationRequest = {
|
||||
type: 'optimize-combinations';
|
||||
candidates: CombinationCandidate[];
|
||||
chart: ExactSongChart;
|
||||
};
|
||||
|
||||
self.onmessage = (event: MessageEvent<OptimizeRequest | CombinationRequest>) => {
|
||||
|
||||
try {
|
||||
const options: ExactOptimizeOptions = {
|
||||
perfectNoteScore: event.data.perfectNoteScore,
|
||||
directSongScoreBonusPercent: event.data.directSongScoreBonusPercent,
|
||||
onProgress: (progress) => self.postMessage({ type: 'progress', progress })
|
||||
};
|
||||
const result = optimizeExactOrderAndCooldowns(event.data.cards, event.data.chart, options);
|
||||
self.postMessage({ type: 'result', result });
|
||||
if (event.data.type === 'optimize-exact') {
|
||||
const options: ExactOptimizeOptions = {
|
||||
perfectNoteScore: event.data.perfectNoteScore,
|
||||
directSongScoreBonusPercent: event.data.directSongScoreBonusPercent,
|
||||
onProgress: (progress) => self.postMessage({ type: 'progress', progress })
|
||||
};
|
||||
const result = optimizeExactOrderAndCooldowns(event.data.cards, event.data.chart, options);
|
||||
self.postMessage({ type: 'result', result });
|
||||
return;
|
||||
}
|
||||
|
||||
const totalCandidates = event.data.candidates.reduce((sum, candidate) => sum + countOptimizationCandidates(candidate.cards), 0);
|
||||
let completedCandidates = 0;
|
||||
let best: { result: ExactOptimizationResult; overallPower: number } | null = null;
|
||||
const rankings: { result: ExactOptimizationResult; overallPower: number }[] = [];
|
||||
for (const candidate of event.data.candidates) {
|
||||
const result = optimizeExactOrderAndCooldowns(candidate.cards, event.data.chart, {
|
||||
perfectNoteScore: candidate.perfectNoteScore,
|
||||
directSongScoreBonusPercent: candidate.directSongScoreBonusPercent,
|
||||
onProgress: (progress) => self.postMessage({
|
||||
type: 'progress',
|
||||
progress: { evaluatedCandidates: completedCandidates + progress.evaluatedCandidates, totalCandidates }
|
||||
})
|
||||
});
|
||||
completedCandidates += countOptimizationCandidates(candidate.cards);
|
||||
if (!best || result.theoreticalMaxScore > best.result.theoreticalMaxScore ||
|
||||
(result.theoreticalMaxScore === best.result.theoreticalMaxScore && result.expectedScore > best.result.expectedScore)) {
|
||||
best = { result, overallPower: candidate.overallPower };
|
||||
}
|
||||
rankings.push({ result, overallPower: candidate.overallPower });
|
||||
}
|
||||
if (!best) throw new Error('정밀 분석할 조합이 없습니다.');
|
||||
rankings.sort((left, right) => right.result.theoreticalMaxScore - left.result.theoreticalMaxScore ||
|
||||
right.result.expectedScore - left.result.expectedScore);
|
||||
self.postMessage({ type: 'combination-result', ...best, rankings: rankings.slice(0, 10) });
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
type: 'error',
|
||||
|
||||
Reference in New Issue
Block a user