import { type NodeProps, Position, type Node, } from '@xyflow/react'; import { Toolbar } from '../components/NodeComponents'; import styles from '../../VisProg.module.css'; import {MultiConnectionHandle} from "../components/RuleBasedHandle.tsx"; import {allowOnlyConnectionsFromType} from "../HandleRules.ts"; import useFlowStore from '../VisProgStores'; import { TextField } from '../../../../components/TextField'; import { MultilineTextField } from '../../../../components/MultilineTextField'; /** * The default data structure for a BasicBelief node * * Represents configuration for a node that activates when a specific condition is met, * such as keywords being spoken or emotions detected. * * @property label: the display label of this BasicBelief node. * @property droppable: Whether this node can be dropped from the toolbar (default: true). * @property BasicBeliefType - The type of BasicBelief ("keywords" or a custom string). * @property BasicBeliefs - The list of keyword BasicBeliefs (if applicable). * @property hasReduce - Whether this node supports reduction logic. */ export type BasicBeliefNodeData = { label: string; droppable: boolean; belief: BasicBeliefType; hasReduce: boolean; }; // These are all the types a basic belief could be. type BasicBeliefType = Keyword | Semantic | DetectedObject | Emotion type Keyword = { type: "keyword", id: string, value: string, label: "Keyword said:"}; type Semantic = { type: "semantic", id: string, value: string, description: string, label: "Detected with LLM:"}; type DetectedObject = { type: "object", id: string, value: string, label: "Object found:"}; type Emotion = { type: "emotion", id: string, value: string, label: "Emotion recognised:"}; export type BasicBeliefNode = Node /** * This function is called whenever a connection is made with this node type as the target * @param _thisNode the node of this node type which function is called * @param _sourceNodeId the source of the received connection */ export function BasicBeliefConnectionTarget(_thisNode: Node, _sourceNodeId: string) { // no additional connection logic exists yet } /** * This function is called whenever a connection is made with this node type as the source * @param _thisNode the node of this node type which function is called * @param _targetNodeId the target of the created connection */ export function BasicBeliefConnectionSource(_thisNode: Node, _targetNodeId: string) { // no additional connection logic exists yet } /** * This function is called whenever a connection is disconnected with this node type as the target * @param _thisNode the node of this node type which function is called * @param _sourceNodeId the source of the disconnected connection */ export function BasicBeliefDisconnectionTarget(_thisNode: Node, _sourceNodeId: string) { // no additional connection logic exists yet } /** * This function is called whenever a connection is disconnected with this node type as the source * @param _thisNode the node of this node type which function is called * @param _targetNodeId the target of the diconnected connection */ export function BasicBeliefDisconnectionSource(_thisNode: Node, _targetNodeId: string) { // no additional connection logic exists yet } /** * Defines how a BasicBelief node should be rendered * @param props - Node properties provided by React Flow, including `id` and `data`. * @returns The rendered BasicBeliefNode React element (React.JSX.Element). */ export default function BasicBeliefNode(props: NodeProps) { const data = props.data; const {updateNodeData} = useFlowStore(); const updateValue = (value: string) => updateNodeData(props.id, {...data, belief: {...data.belief, value: value}}); const label_input_id = `basic_belief_${props.id}_label_input`; type BeliefString = BasicBeliefType["type"]; function updateBeliefType(newType: BeliefString) { updateNodeData(props.id, { ...data, belief: { ...data.belief, type: newType, value: newType === "emotion" ? emotionOptions[0] : data.belief.value, }, }); } const setBeliefDescription = (value: string) => { updateNodeData(props.id, {...data, belief: {...data.belief, description: value}}); } // Use this const emotionOptions = ["Happy", "Angry", "Sad", "Cheerful"] let placeholder = "" let wrapping = "" switch (props.data.belief.type) { case ("keyword"): placeholder = "keyword..." wrapping = '"' break; case ("semantic"): placeholder = "description..." wrapping = '"' break; case ("object"): placeholder = "object..." break; case ("emotion"): // TODO: emotion should probably be a drop-down menu rather than a string // So this placeholder won't hold for always placeholder = "emotion..." break; default: break; } return ( <>
{wrapping} {data.belief.type === "emotion" && ( )} {data.belief.type !== "emotion" && ()} {wrapping}
{data.belief.type === "semantic" && (
)}
); }; /** * Reduces each BasicBelief, including its children down into its core data. * @param node - The BasicBelief node to reduce. * @param _nodes - The list of all nodes in the current flow graph. * @returns A simplified object containing the node label and its list of BasicBeliefs. */ export function BasicBeliefReduce(node: Node, _nodes: Node[]) { const data = node.data as BasicBeliefNodeData; const result: Record = { id: node.id, }; switch (data.belief.type) { case "emotion": result["emotion"] = data.belief.value; break; case "keyword": result["keyword"] = data.belief.value; break; case "object": result["object"] = data.belief.value; break; case "semantic": result["name"] = data.belief.value; result["description"] = data.belief.description; break; default: break; } return result }