Skip to content

Commit 249789f

Browse files
committed
feat: 添加算法播放器Hook
1 parent 36051ad commit 249789f

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

src/hooks/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { useAlgorithmPlayer } from './useAlgorithmPlayer';

src/hooks/useAlgorithmPlayer.ts

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import { useState, useCallback, useEffect, useRef } from 'react';
2+
import type { AlgorithmStep, AlgorithmType } from '../types';
3+
import { generateDPSteps } from '../algorithms/dpAlgorithm';
4+
import { generateGreedyBinarySteps } from '../algorithms/greedyBinaryAlgorithm';
5+
6+
interface UseAlgorithmPlayerReturn {
7+
steps: AlgorithmStep[];
8+
currentStep: number;
9+
currentStepData: AlgorithmStep | null;
10+
isPlaying: boolean;
11+
speed: number;
12+
play: () => void;
13+
pause: () => void;
14+
nextStep: () => void;
15+
prevStep: () => void;
16+
reset: () => void;
17+
seek: (step: number) => void;
18+
setSpeed: (speed: number) => void;
19+
generateSteps: (data: number[], algorithmType: AlgorithmType) => void;
20+
}
21+
22+
export function useAlgorithmPlayer(): UseAlgorithmPlayerReturn {
23+
const [steps, setSteps] = useState<AlgorithmStep[]>([]);
24+
const [currentStep, setCurrentStep] = useState(0);
25+
const [isPlaying, setIsPlaying] = useState(false);
26+
const [speed, setSpeed] = useState(1);
27+
const intervalRef = useRef<number | null>(null);
28+
29+
// 生成算法步骤
30+
const generateSteps = useCallback((data: number[], algorithmType: AlgorithmType) => {
31+
const newSteps = algorithmType === 'dp'
32+
? generateDPSteps(data)
33+
: generateGreedyBinarySteps(data);
34+
setSteps(newSteps);
35+
setCurrentStep(0);
36+
setIsPlaying(false);
37+
}, []);
38+
39+
// 播放
40+
const play = useCallback(() => {
41+
if (currentStep >= steps.length - 1) {
42+
setCurrentStep(0);
43+
}
44+
setIsPlaying(true);
45+
}, [currentStep, steps.length]);
46+
47+
// 暂停
48+
const pause = useCallback(() => {
49+
setIsPlaying(false);
50+
}, []);
51+
52+
// 下一步
53+
const nextStep = useCallback(() => {
54+
setCurrentStep((prev) => Math.min(prev + 1, steps.length - 1));
55+
}, [steps.length]);
56+
57+
// 上一步
58+
const prevStep = useCallback(() => {
59+
setCurrentStep((prev) => Math.max(prev - 1, 0));
60+
}, []);
61+
62+
// 重置
63+
const reset = useCallback(() => {
64+
setCurrentStep(0);
65+
setIsPlaying(false);
66+
}, []);
67+
68+
// 跳转到指定步骤
69+
const seek = useCallback((step: number) => {
70+
setCurrentStep(Math.max(0, Math.min(step, steps.length - 1)));
71+
}, [steps.length]);
72+
73+
// 自动播放
74+
useEffect(() => {
75+
if (isPlaying) {
76+
const interval = 1000 / speed;
77+
intervalRef.current = window.setInterval(() => {
78+
setCurrentStep((prev) => {
79+
if (prev >= steps.length - 1) {
80+
setIsPlaying(false);
81+
return prev;
82+
}
83+
return prev + 1;
84+
});
85+
}, interval);
86+
} else {
87+
if (intervalRef.current) {
88+
clearInterval(intervalRef.current);
89+
intervalRef.current = null;
90+
}
91+
}
92+
93+
return () => {
94+
if (intervalRef.current) {
95+
clearInterval(intervalRef.current);
96+
}
97+
};
98+
}, [isPlaying, speed, steps.length]);
99+
100+
const currentStepData = steps[currentStep] || null;
101+
102+
return {
103+
steps,
104+
currentStep,
105+
currentStepData,
106+
isPlaying,
107+
speed,
108+
play,
109+
pause,
110+
nextStep,
111+
prevStep,
112+
reset,
113+
seek,
114+
setSpeed,
115+
generateSteps,
116+
};
117+
}

0 commit comments

Comments
 (0)