|
@@ -9,20 +9,12 @@ import VideoPlayer from "./VideoPlayer";
|
|
|
import AudioPlayer from "./AudioPlayer";
|
|
|
import { IExerciseItem } from "../types";
|
|
|
import { Howl } from "howler";
|
|
|
+import { useTimer } from "../hooks";
|
|
|
|
|
|
const Timer = ({ training }: { training: ITraining }) => {
|
|
|
- const tickPeriod = 100;
|
|
|
+ const [time, timer] = useTimer({ tickPeriod: 100 });
|
|
|
|
|
|
- const timeout: {
|
|
|
- current: ReturnType<typeof setTimeout> | undefined;
|
|
|
- } = useRef();
|
|
|
-
|
|
|
- const [time, setTime] = useState(0);
|
|
|
const [state, setState] = useState({
|
|
|
- running: false,
|
|
|
- startTime: 0,
|
|
|
- stopTime: 0,
|
|
|
- timeBuffer: 0,
|
|
|
exerciseList: [] as IExerciseItem[],
|
|
|
totalTime: 0
|
|
|
});
|
|
@@ -31,20 +23,26 @@ const Timer = ({ training }: { training: ITraining }) => {
|
|
|
new Howl({
|
|
|
src: ["/media/ROSIE.mp3"],
|
|
|
sprite: {
|
|
|
- ttt: [114, 2956]
|
|
|
+ ttt: [114, 2956 - 114],
|
|
|
+ five: [10211, 10883 - 10211],
|
|
|
+ four: [11292, 11873 - 11292],
|
|
|
+ three: [12251, 12809 - 12251],
|
|
|
+ two: [13208, 13930 - 13208],
|
|
|
+ one: [14376, 14948 - 14376],
|
|
|
+ go: [18219, 18735 - 18219],
|
|
|
+ rest: [18988, 19615 - 18988]
|
|
|
}
|
|
|
})
|
|
|
);
|
|
|
|
|
|
useEffect(() => {
|
|
|
//console.log("effect 1");
|
|
|
+ rosie.current.play("ttt");
|
|
|
const exerciseList = getExerciseList(training.blocks);
|
|
|
const totalTime = getTrainingTime(exerciseList);
|
|
|
setState({ ...state, exerciseList, totalTime });
|
|
|
- rosie.current.play("ttt");
|
|
|
}, [training]);
|
|
|
|
|
|
- const trainingOver = time >= state.totalTime;
|
|
|
//console.log("is it over?", time, state.totalTime, trainingOver);
|
|
|
|
|
|
const {
|
|
@@ -52,46 +50,40 @@ const Timer = ({ training }: { training: ITraining }) => {
|
|
|
previousExercise,
|
|
|
nextExercise,
|
|
|
exerciseTime
|
|
|
- } = getPosition(state.exerciseList, time);
|
|
|
-
|
|
|
- const video: { current: VideoJsPlayer | undefined } = useRef();
|
|
|
- //const audio: { current: Howl | undefined } = useRef();
|
|
|
+ } = getPosition(state.exerciseList, timer.time);
|
|
|
+ //console.log("aaa", time, currentExercise);
|
|
|
|
|
|
useEffect(() => {
|
|
|
- //console.log("effect 2", time);
|
|
|
- if (!state.running) return;
|
|
|
- timeout.current = setTimeout(tick, tickPeriod - state.timeBuffer);
|
|
|
- setState({ ...state, timeBuffer: 0 });
|
|
|
- }, [time, state.running]);
|
|
|
-
|
|
|
- function tick() {
|
|
|
- setTime((Date.now() - state.startTime) / 1000);
|
|
|
+ const countdown = currentExercise
|
|
|
+ ? currentExercise.duration + currentExercise.offset - timer.intTime + 1
|
|
|
+ : 0;
|
|
|
+ if (timer.running && rosie.current) {
|
|
|
+ if (countdown === 5) rosie.current.play("five");
|
|
|
+ else if (countdown === 4) rosie.current.play("four");
|
|
|
+ else if (countdown === 3) rosie.current.play("three");
|
|
|
+ else if (countdown === 2) rosie.current.play("two");
|
|
|
+ else if (countdown === 1) rosie.current.play("one");
|
|
|
+ if (exerciseTime < 1) {
|
|
|
+ if (currentExercise && currentExercise.exercise === "Rest")
|
|
|
+ rosie.current.play("rest");
|
|
|
+ else rosie.current.play("go");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, [time, timer.running]);
|
|
|
|
|
|
- if (trainingOver) stopTimer();
|
|
|
- }
|
|
|
+ const video: { current: VideoJsPlayer | undefined } = useRef();
|
|
|
+ //const audio: { current: Howl | undefined } = useRef();
|
|
|
|
|
|
function startTimer() {
|
|
|
- if (trainingOver) return;
|
|
|
- setState({
|
|
|
- ...state,
|
|
|
- running: true,
|
|
|
- startTime: state.startTime + Date.now() - state.stopTime
|
|
|
- });
|
|
|
+ if (time >= state.totalTime) return;
|
|
|
+ timer.start();
|
|
|
if (video.current) video.current.play();
|
|
|
//if (audio.current) audio.current.play();
|
|
|
//console.log("Timer started.");
|
|
|
}
|
|
|
|
|
|
function stopTimer() {
|
|
|
- if (timeout.current) clearTimeout(timeout.current);
|
|
|
-
|
|
|
- setState({
|
|
|
- ...state,
|
|
|
- running: false,
|
|
|
- stopTime: Date.now(),
|
|
|
- timeBuffer: Date.now() - state.startTime
|
|
|
- });
|
|
|
-
|
|
|
+ timer.stop();
|
|
|
if (video.current) video.current.pause();
|
|
|
//if (audio.current) audio.current.pause();
|
|
|
//console.log("stopped");
|
|
@@ -99,21 +91,13 @@ const Timer = ({ training }: { training: ITraining }) => {
|
|
|
|
|
|
function forward() {
|
|
|
if (nextExercise) {
|
|
|
- setState({
|
|
|
- ...state,
|
|
|
- startTime: state.startTime + 1000 * (time - nextExercise.offset)
|
|
|
- });
|
|
|
- setTime((Date.now() - state.startTime) / 1000);
|
|
|
+ timer.setTime(nextExercise.offset);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function back() {
|
|
|
if (previousExercise) {
|
|
|
- setState({
|
|
|
- ...state,
|
|
|
- startTime: state.startTime + 1000 * (time - previousExercise.offset)
|
|
|
- });
|
|
|
- setTime((Date.now() - state.startTime) / 1000);
|
|
|
+ timer.setTime(previousExercise.offset);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -125,10 +109,8 @@ const Timer = ({ training }: { training: ITraining }) => {
|
|
|
{/*<label htmlFor="rest">Rest</label>
|
|
|
<input type="number" min="25" max="60" step="5" defaultValue="25" />*/}
|
|
|
<button onClick={back}>back</button>
|
|
|
- <button
|
|
|
- onClick={state.running ? () => stopTimer() : () => startTimer()}
|
|
|
- >
|
|
|
- {state.running ? "stop" : "start"}
|
|
|
+ <button onClick={timer.running ? stopTimer : startTimer}>
|
|
|
+ {timer.running ? "stop" : "start"}
|
|
|
</button>
|
|
|
<button onClick={forward}>forward</button>
|
|
|
</div>
|
|
@@ -137,10 +119,11 @@ const Timer = ({ training }: { training: ITraining }) => {
|
|
|
seconds={
|
|
|
currentExercise ? currentExercise.duration - exerciseTime : 0
|
|
|
}
|
|
|
- totalPercent={time / state.totalTime}
|
|
|
+ totalPercent={timer.time / state.totalTime}
|
|
|
exercisePercent={
|
|
|
exerciseTime / (currentExercise ? currentExercise.duration : 1)
|
|
|
}
|
|
|
+ onClick={timer.running ? stopTimer : startTimer}
|
|
|
/>
|
|
|
<div className="header">current exercise</div>
|
|
|
<div className="exercise">
|
|
@@ -151,6 +134,11 @@ const Timer = ({ training }: { training: ITraining }) => {
|
|
|
{nextExercise ? nextExercise.exercise : "😎"}
|
|
|
</div>
|
|
|
<VideoPlayer
|
|
|
+ src={
|
|
|
+ currentExercise && currentExercise.video
|
|
|
+ ? currentExercise.video
|
|
|
+ : ""
|
|
|
+ }
|
|
|
getVideoHandle={(videoHandle: VideoJsPlayer) =>
|
|
|
(video.current = videoHandle)
|
|
|
}
|