Files
Genarrative/src/games/bark-battle/domain/__tests__/BarkDetector.test.ts

84 lines
3.0 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { DEFAULT_BARK_BATTLE_CONFIG } from '../../application/BarkBattleConfig';
import { BarkDetector } from '../BarkDetector';
describe('BarkDetector', () => {
it('每个监测点只检测瞬时响度,超过阈值立即触发', () => {
const detector = new BarkDetector({
threshold: 0.45,
minBarkGapMs: DEFAULT_BARK_BATTLE_CONFIG.minBarkGapMs,
});
expect(detector.acceptSample({ atMs: 0, volume: 0.2 })).toEqual([]);
const events = detector.acceptSample({ atMs: 40, volume: 0.72 });
expect(events).toHaveLength(1);
expect(events[0]).toMatchObject({ side: 'player', atMs: 40, peakVolume: 0.72, durationMs: 0 });
});
it('持续噪音按冷却间隔触发,不需要等待响度回落', () => {
const detector = new BarkDetector({
threshold: 0.4,
minBarkGapMs: 250,
});
const allEvents = [
...detector.acceptSample({ atMs: 0, volume: 0.7 }),
...detector.acceptSample({ atMs: 100, volume: 0.72 }),
...detector.acceptSample({ atMs: 200, volume: 0.73 }),
...detector.acceptSample({ atMs: 300, volume: 0.75 }),
...detector.acceptSample({ atMs: 500, volume: 0.2 }),
...detector.acceptSample({ atMs: 560, volume: 0.76 }),
];
expect(allEvents.map((event) => event.atMs)).toEqual([0, 300, 560]);
});
it('低于阈值的背景噪音和冷却内峰值不计数,最短持续时长不再参与判断', () => {
const detector = new BarkDetector({
threshold: 0.5,
minBarkGapMs: 300,
});
expect(detector.acceptSample({ atMs: 0, volume: 0.48 })).toEqual([]);
expect(detector.acceptSample({ atMs: 20, volume: 0.9 })).toHaveLength(1);
expect(detector.acceptSample({ atMs: 60, volume: 0.95 })).toEqual([]);
expect(detector.acceptSample({ atMs: 320, volume: 0.88 })).toHaveLength(1);
expect(detector.acceptSample({ atMs: 420, volume: 0.2 })).toEqual([]);
});
it('支持 100ms 级别间隔的快速连续有效叫声', () => {
const detector = new BarkDetector({
threshold: 0.5,
minBarkGapMs: 100,
});
const allEvents = [
...detector.acceptSample({ atMs: 0, volume: 0.86 }),
...detector.acceptSample({ atMs: 60, volume: 0.9 }),
...detector.acceptSample({ atMs: 120, volume: 0.91 }),
...detector.acceptSample({ atMs: 180, volume: 0.92 }),
...detector.acceptSample({ atMs: 240, volume: 0.93 }),
];
expect(allEvents).toHaveLength(3);
expect(allEvents.map((event) => event.atMs)).toEqual([0, 120, 240]);
});
it('非有限音量会归零,超过 1 的音量会夹到 1', () => {
const detector = new BarkDetector({
threshold: 0.5,
minBarkGapMs: 100,
});
expect(detector.acceptSample({ atMs: 0, volume: Number.NaN })).toEqual([]);
expect(detector.acceptSample({ atMs: 120, volume: Number.POSITIVE_INFINITY })).toEqual([]);
const events = detector.acceptSample({ atMs: 240, volume: 2 });
expect(events).toHaveLength(1);
expect(events[0]?.peakVolume).toBe(1);
});
});