From b869f7c0718673e11e7b1a7865fd1b94dbf58aff Mon Sep 17 00:00:00 2001 From: JGerla Date: Mon, 12 Jan 2026 16:44:25 +0100 Subject: [PATCH] feat: added reduce and connection logic A rule still needs to be added to the inferred belief handles to prevent cyclical inferredBeliefs, but aside from that logic ifs finished. ref: N25B-433 --- .../visualProgrammingUI/nodes/BeliefReduce.ts | 12 +++ .../nodes/InferredBeliefNode.default.ts | 3 +- .../nodes/InferredBeliefNode.tsx | 73 +++++++++++++------ .../visualProgrammingUI/nodes/NormNode.tsx | 7 +- .../visualProgrammingUI/nodes/TriggerNode.tsx | 6 +- 5 files changed, 70 insertions(+), 31 deletions(-) create mode 100644 src/pages/VisProgPage/visualProgrammingUI/nodes/BeliefReduce.ts diff --git a/src/pages/VisProgPage/visualProgrammingUI/nodes/BeliefReduce.ts b/src/pages/VisProgPage/visualProgrammingUI/nodes/BeliefReduce.ts new file mode 100644 index 0000000..0710fe7 --- /dev/null +++ b/src/pages/VisProgPage/visualProgrammingUI/nodes/BeliefReduce.ts @@ -0,0 +1,12 @@ +import { type Node } from '@xyflow/react'; +import {BasicBeliefReduce} from "./BasicBeliefNode.tsx"; +import {InferredBeliefReduce} from "./InferredBeliefNode.tsx"; + +export function BeliefReduce(beliefNode: Node, nodes: Node[]) { + switch (beliefNode.type) { + case 'basic_belief': + return BasicBeliefReduce(beliefNode, nodes); + case 'inferred_belief': + return InferredBeliefReduce(beliefNode, nodes); + } +} \ No newline at end of file diff --git a/src/pages/VisProgPage/visualProgrammingUI/nodes/InferredBeliefNode.default.ts b/src/pages/VisProgPage/visualProgrammingUI/nodes/InferredBeliefNode.default.ts index ce86fb8..71f9f6b 100644 --- a/src/pages/VisProgPage/visualProgrammingUI/nodes/InferredBeliefNode.default.ts +++ b/src/pages/VisProgPage/visualProgrammingUI/nodes/InferredBeliefNode.default.ts @@ -8,9 +8,8 @@ export const InferredBeliefNodeDefaults: InferredBeliefNodeData = { label: "Inferred Belief", droppable: true, inferredBelief: { - id: "", left: undefined, - operator: "OR", + operator: true, right: undefined }, hasReduce: true, diff --git a/src/pages/VisProgPage/visualProgrammingUI/nodes/InferredBeliefNode.tsx b/src/pages/VisProgPage/visualProgrammingUI/nodes/InferredBeliefNode.tsx index 7cbf06f..70062f2 100644 --- a/src/pages/VisProgPage/visualProgrammingUI/nodes/InferredBeliefNode.tsx +++ b/src/pages/VisProgPage/visualProgrammingUI/nodes/InferredBeliefNode.tsx @@ -2,10 +2,12 @@ import { type NodeProps, Position, type Node, + getConnectedEdges } from '@xyflow/react'; import {useState} from "react"; import { Toolbar } from '../components/NodeComponents.tsx'; import styles from '../../VisProg.module.css'; +import {BeliefReduce} from "./BeliefReduce.ts"; import switchStyles from './InferredBeliefNode.module.css'; import {MultiConnectionHandle, SingleConnectionHandle} from "../components/RuleBasedHandle.tsx"; import {allowOnlyConnectionsFromType} from "../HandleRules.ts"; @@ -20,18 +22,26 @@ import type {BasicBeliefType} from "./BasicBeliefNode.tsx"; export type InferredBeliefNodeData = { label: string; droppable: boolean; - inferredBelief: Belief; + inferredBelief: InferredBelief; hasReduce: boolean; }; -type Belief = InferredBelief | BasicBeliefType; + + +type Belief = ReducedInferredBelief | BasicBeliefType; + +type ReducedInferredBelief = { + id: string, + left: Belief, + operator: "AND" | "OR" + right: Belief +}; type InferredBelief = { - id: string; - left: Belief | undefined, - operator: "AND" | "OR" - right: Belief | undefined -}; + left: string | undefined, + operator: boolean, + right: string | undefined, +} // helper validation function for InferredBelief objects // const isValidInferredBelief = (inferredBelief: InferredBelief) : boolean => { @@ -47,7 +57,17 @@ export type InferredBeliefNode = Node; * @param _sourceNodeId the source of the received connection */ export function InferredBeliefConnectionTarget(_thisNode: Node, _sourceNodeId: string) { - // no additional connection logic exists yet + const data = _thisNode.data as InferredBeliefNodeData; + + if ((useFlowStore.getState().nodes.find((node) => node.id === _sourceNodeId + && ['basic_belief', 'inferred_belief'].includes(node.type!))) + ) { + const connectedEdges = getConnectedEdges([_thisNode], useFlowStore.getState().edges); + switch(connectedEdges.find(edge => edge.source === _sourceNodeId)?.targetHandle){ + case 'beliefLeft': data.inferredBelief.left = _sourceNodeId; break; + case 'beliefRight': data.inferredBelief.right = _sourceNodeId; break; + } + } } /** @@ -65,7 +85,10 @@ export function InferredBeliefConnectionSource(_thisNode: Node, _targetNodeId: s * @param _sourceNodeId the source of the disconnected connection */ export function InferredBeliefDisconnectionTarget(_thisNode: Node, _sourceNodeId: string) { - // no additional connection logic exists yet + const data = _thisNode.data as InferredBeliefNodeData; + + if (_sourceNodeId === data.inferredBelief.left) data.inferredBelief.left = undefined; + if (_sourceNodeId === data.inferredBelief.right) data.inferredBelief.right = undefined; } /** @@ -87,19 +110,18 @@ export default function InferredBeliefNode(props: NodeProps) const { updateNodeData } = useFlowStore(); // start of as an AND operator, true: "AND", false: "OR" const [enforceAllBeliefs, setEnforceAllBeliefs] = useState(true); + function onToggle() { setEnforceAllBeliefs(!enforceAllBeliefs); + updateNodeData(props.id, { ...data, - belief: { + inferredBelief: { ...data.inferredBelief, - operator: enforceAllBeliefs ? "AND" : "OR", + operator: enforceAllBeliefs, } }); } - - // TODO define node - return ( <> @@ -108,7 +130,7 @@ export default function InferredBeliefNode(props: NodeProps)