import { Dispatch, memo, SetStateAction, useCallback } from "react"; import { Statechart, stateDescription } from "../statecharts/abstract_syntax"; import { Mode, RaisedEvent, RT_Event } from "../statecharts/runtime_types"; import { formatTime } from "../util/util"; import { TimeMode, timeTravel } from "../statecharts/time"; import { TraceItem, TraceState } from "./App"; import { Environment } from "@/statecharts/environment"; type RTHistoryProps = { trace: TraceState|null, setTrace: Dispatch>; ast: Statechart, setTime: Dispatch>, showPlantTrace: boolean, } export function RTHistory({trace, setTrace, ast, setTime, showPlantTrace}: RTHistoryProps) { const onMouseDown = useCallback((idx: number, timestamp: number) => { setTrace(trace => trace && { ...trace, idx, }); setTime(time => timeTravel(time, timestamp, performance.now())); }, [setTrace, setTime]); if (trace === null) { return <>; } return trace.trace.map((item, i) => { const prevItem = trace.trace[i-1]; // @ts-ignore const isPlantStep = item.state?.sc === prevItem?.state?.sc; if (!showPlantTrace && isPlantStep) { return <> } return ; }); } function RTCause(props: {cause?: RT_Event}) { if (props.cause === undefined) { return <>{""}; } if (props.cause.kind === "timer") { return <>{""}; } else if (props.cause.kind === "input") { return <>{props.cause.name} } console.log(props.cause); throw new Error("unreachable"); } function RTEventParam(props: {param?: any}) { return <>{props.param !== undefined && <>({JSON.stringify(props.param)})}; } export const RTHistoryItem = memo(function RTHistoryItem({ast, idx, item, prevItem, isPlantStep, active, onMouseDown}: {idx: number, ast: Statechart, item: TraceItem, prevItem?: TraceItem, isPlantStep: boolean, active: boolean, onMouseDown: (idx: number, timestamp: number) => void}) { if (item.kind === "bigstep") { // @ts-ignore const newStates = item.state.sc.mode.difference(prevItem?.state.sc.mode || new Set()); return
onMouseDown(idx, item.simtime), [idx, item.simtime])}>
{formatTime(item.simtime)}  
{item.state.sc.outputEvents.length>0 && <>^ {item.state.sc.outputEvents.map((e:RaisedEvent) => {e.name})} }
; } else { // error item return
onMouseDown(idx, item.simtime), [idx, item.simtime])}>
{formatTime(item.simtime)}  
{item.cause}
{item.error.message}
; } }); function ShowEnvironment(props: {environment: Environment}) { return
{ [...props.environment.entries()] .filter(([variable]) => !variable.startsWith('_')) .map(([variable,value]) => `${variable.split('.').at(-1)}: ${JSON.stringify(value)}`).join(', ') }
; } function ShowMode(props: {mode: Mode, statechart: Statechart}) { const activeLeafs = getActiveLeafs(props.mode, props.statechart); return
{[...activeLeafs].map(uid => {stateDescription(props.statechart.uid2State.get(uid)!)})}
; } function getActiveLeafs(mode: Mode, sc: Statechart) { return new Set([...mode].filter(uid => // @ts-ignore sc.uid2State.get(uid)?.children?.length === 0 )); }