import { useState } from "react"; import type { TimelineSnapshot } from "./Timeline"; import type { Graph } from "./types"; export interface RunResults { f?: number; // By input name; only those worked out so far derivatives: Record; } // What finished runs have found for this function at these input values, across modes and seeds export default function useRunResults(graph: Graph | null, { run, state, flow, iteration, lastIteration }: TimelineSnapshot): RunResults { const [saved, setSaved] = useState<{ key: string | null; results: RunResults }>({ key: null, results: { derivatives: {} } }); const key = graph && run ? JSON.stringify([graph, run.inputs]) : null; const results = saved.key === key ? saved.results : { derivatives: {} }; // Set during render, so a finished run's results show with its last frame if (graph && run && state && !flow && iteration === lastIteration) { const found = run.mode === "forward" ? { [run.seed]: state.derivatives[graph.output] } : Object.fromEntries(graph.inputs.map((name, i) => [name, state.derivatives[graph.nodes[i].id]])); const f = state.values[graph.output]; if (saved.key !== key || results.f !== f || Object.entries(found).some(([name, value]) => results.derivatives[name] !== value)) { setSaved({ key, results: { f, derivatives: { ...results.derivatives, ...found } } }); } } return results; }