feat: wire bark battle platform loop
Some checks failed
CI / verify (pull_request) Has been cancelled

This commit is contained in:
2026-05-14 18:20:46 +08:00
parent 8c6ec9e6e4
commit 1d7ef7e4b6
73 changed files with 7933 additions and 107 deletions

View File

@@ -1,5 +1,6 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import type { BarkBattlePublishedConfig } from '../../../../packages/shared/src/contracts/barkBattle';
import {
type BarkBattleConfig,
DEFAULT_BARK_BATTLE_CONFIG,
@@ -15,6 +16,9 @@ import { BarkBattleResultPanel } from './BarkBattleResultPanel';
type BarkBattleRuntimeShellProps = {
title?: string;
workId?: string;
publishedConfig?: BarkBattlePublishedConfig | null;
onExit?: () => void;
};
type DebugEvent = {
@@ -63,8 +67,39 @@ function isMicrophoneFailureReason(reason: unknown): reason is MicrophoneFailure
return typeof reason === 'string' && MICROPHONE_FAILURE_REASONS.has(reason as MicrophoneFailureReason);
}
export function BarkBattleRuntimeShell({ title = '汪汪声浪大作战' }: BarkBattleRuntimeShellProps) {
const [config, setConfig] = useState(DEFAULT_BARK_BATTLE_CONFIG);
function buildRuntimeConfigFromPublishedConfig(
publishedConfig?: BarkBattlePublishedConfig | null,
): BarkBattleConfig {
if (!publishedConfig) {
return DEFAULT_BARK_BATTLE_CONFIG;
}
const difficultyOverrides: Record<
BarkBattlePublishedConfig['difficultyPreset'],
Partial<BarkBattleConfig>
> = {
easy: { barkThreshold: 0.42, opponentBasePower: 0.16, drawThreshold: 10 },
normal: { barkThreshold: 0.5, opponentBasePower: 0.22, drawThreshold: 12 },
hard: { barkThreshold: 0.58, opponentBasePower: 0.3, drawThreshold: 14 },
};
return {
...DEFAULT_BARK_BATTLE_CONFIG,
...difficultyOverrides[publishedConfig.difficultyPreset],
};
}
export function BarkBattleRuntimeShell({
title = '汪汪声浪大作战',
workId,
publishedConfig,
onExit,
}: BarkBattleRuntimeShellProps) {
const initialConfig = useMemo(
() => buildRuntimeConfigFromPublishedConfig(publishedConfig),
[publishedConfig],
);
const [config, setConfig] = useState(initialConfig);
const controllerRef = useRef<BarkBattleController | null>(null);
if (!controllerRef.current) {
controllerRef.current = new BarkBattleController(config);
@@ -110,6 +145,12 @@ export function BarkBattleRuntimeShell({ title = '汪汪声浪大作战' }: Bark
microphoneSamplerRef.current = null;
}, []);
useEffect(() => {
setConfig(initialConfig);
controller.updateConfig(initialConfig);
syncSnapshot();
}, [controller, initialConfig, syncSnapshot]);
const startMicrophone = useCallback(async () => {
stopMicrophone();
try {
@@ -225,7 +266,11 @@ export function BarkBattleRuntimeShell({ title = '汪汪声浪大作战' }: Bark
<button type="button" onClick={startMock}></button>
<button type="button" onClick={finishNow}></button>
<button type="button" onClick={restart}></button>
{onExit ? <button type="button" onClick={onExit}></button> : null}
</div>
{workId ? (
<p className="bark-battle-debug-panel__work-id">{workId}</p>
) : null}
<div className="bark-battle-debug-metrics" aria-label="触发反馈">
<span className="bark-battle-debug-metrics__wide">{inputMode === 'microphone' ? '真实麦克风' : 'Mock 输入'}</span>
<span>{(liveInputVolume * 100).toFixed(0)}%</span>