Spaces:
Running
Running
File size: 3,467 Bytes
e85a399 60943f3 603b5b4 60943f3 603b5b4 60943f3 e85a399 60943f3 e85a399 60943f3 e85a399 60943f3 e85a399 60943f3 e85a399 60943f3 e85a399 60943f3 e85a399 60943f3 e85a399 60943f3 603b5b4 60943f3 e85a399 60943f3 e85a399 60943f3 603b5b4 60943f3 e85a399 60943f3 e85a399 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | import { useCallback, useEffect, useRef, useState } from "react";
import PyodideWorker from "./pyodide.worker.ts?worker";
import type { ComparisonTrajectory, PlotData, Settings, WorkerMessage } from "./types.ts";
export default function usePyodide(initialSettings: Settings) {
const [comparison, setComparison] = useState<ComparisonTrajectory[]>([]);
const [comparisonBusy, setComparisonBusy] = useState(false);
const comparisonRequest = useRef(0);
const compare = useCallback((settings: Settings[], ids: number[], iteration: number) => {
setComparisonBusy(true);
workerRef.current?.postMessage({ type: "COMPARE", requestId: ++comparisonRequest.current, settings, ids, iteration });
}, []);
const [plotData, setPlotData] = useState<PlotData>({});
const [currentIteration, setCurrentIteration] = useState(0);
const [isLoading, setIsLoading] = useState<boolean>(true);
const workerRef = useRef<Worker | null>(null);
const plotDataRef = useRef<PlotData>({});
const currentIterationRef = useRef(0);
function selectIteration(iteration: number) {
currentIterationRef.current = iteration;
setCurrentIteration(iteration);
}
const sendInit = useCallback((settings: Settings) => {
if (workerRef.current) {
workerRef.current.postMessage({ type: "INIT", settings });
}
}, []);
const sendNextStep = useCallback(() => {
const lastPlottedIteration = Math.max((plotDataRef.current.trajectoryValues?.x.length ?? 1) - 1, 0);
if (currentIterationRef.current < lastPlottedIteration) {
selectIteration(currentIterationRef.current + 1);
return;
}
if (workerRef.current) {
workerRef.current.postMessage({ type: "NEXT_STEP" });
}
}, []);
const sendPrevStep = useCallback(() => {
selectIteration(Math.max(currentIterationRef.current - 1, 0));
}, []);
const sendReset = useCallback(() => {
selectIteration(0);
}, []);
useEffect(() => {
const worker = new PyodideWorker();
workerRef.current = worker;
worker.onmessage = (event) => {
const message = event.data as WorkerMessage;
if (message.type === "COMPARISON_RESULT") {
if (message.requestId === comparisonRequest.current) {
setComparison(message.trajectories);
setComparisonBusy(false);
}
} else if (message.type === "READY") {
console.log("Pyodide is ready");
setIsLoading(false);
sendInit(initialSettings);
} else if (message.type === "RESULT") {
// todo data validation / type
setPlotData((prevData) => {
const nextData = {
functionValues: message.data.functionValues || prevData.functionValues,
trajectoryValues: message.data.trajectoryValues || prevData.trajectoryValues,
};
plotDataRef.current = nextData;
if (message.data.trajectoryValues) {
const lastIteration = Math.max(message.data.trajectoryValues.x.length - 1, 0);
if (lastIteration <= 0 || lastIteration > currentIterationRef.current) {
selectIteration(lastIteration);
}
}
return nextData;
});
}
};
return () => {
worker.terminate();
};
}, []);
return {
comparison, comparisonBusy, compare,
isLoading,
plotData,
currentIteration,
sendInit: sendInit,
sendReset: sendReset,
sendNextStep: sendNextStep,
sendPrevStep: sendPrevStep,
}
}
|