style: added documentation to the InferredBelief Node

ref: N25B-433
This commit is contained in:
JGerla
2026-01-13 09:24:57 +01:00
parent 2d9f430a30
commit f8f0f12128

View File

@@ -6,13 +6,14 @@ import {
} from '@xyflow/react'; } from '@xyflow/react';
import {useState} from "react"; import {useState} from "react";
import { Toolbar } from '../components/NodeComponents.tsx'; import { Toolbar } from '../components/NodeComponents.tsx';
import styles from '../../VisProg.module.css';
import {type HandleRule, type RuleResult, ruleResult} from "../HandleRuleLogic.ts"; import {type HandleRule, type RuleResult, ruleResult} from "../HandleRuleLogic.ts";
import {BeliefReduce} from "./BeliefReduce.ts"; import {BeliefReduce} from "./BeliefReduce.ts";
import switchStyles from './InferredBeliefNode.module.css';
import {MultiConnectionHandle, SingleConnectionHandle} from "../components/RuleBasedHandle.tsx"; import {MultiConnectionHandle, SingleConnectionHandle} from "../components/RuleBasedHandle.tsx";
import {allowOnlyConnectionsFromType} from "../HandleRules.ts"; import {allowOnlyConnectionsFromType} from "../HandleRules.ts";
import useFlowStore from "../VisProgStores.tsx"; import useFlowStore from "../VisProgStores.tsx";
import styles from '../../VisProg.module.css';
import switchStyles from './InferredBeliefNode.module.css';
/** /**
* The default data structure for an InferredBelief node * The default data structure for an InferredBelief node
@@ -24,6 +25,11 @@ export type InferredBeliefNodeData = {
hasReduce: boolean; hasReduce: boolean;
}; };
/**
* stores a boolean to represent the operator
* and a left and right BeliefNode (can be both an inferred and a basic belief)
* in the form of their corresponding id's
*/
type InferredBelief = { type InferredBelief = {
left: string | undefined, left: string | undefined,
operator: boolean, operator: boolean,
@@ -82,17 +88,28 @@ export function InferredBeliefDisconnectionSource(_thisNode: Node, _targetNodeId
} }
/** /**
* This rule makes it impossible to connect Inferred belief nodes * makes it impossible to connect Inferred belief nodes
* if the connection would create a looping connection between inferred beliefs * if the connection would create a cyclical connection between inferred beliefs
*/ */
const noBeliefCycles : HandleRule = (connection, _): RuleResult => { const noBeliefCycles : HandleRule = (connection, _): RuleResult => {
const { nodes, edges } = useFlowStore.getState(); const { nodes, edges } = useFlowStore.getState();
const defaultErrorMessage = "Cyclical connection exists between inferred beliefs";
function checkForCycle(targetNodeId: string, current: string) : RuleResult { /**
const outgoingBeliefs = getOutgoers({id: current}, nodes, edges).filter(node => node.type === 'inferred_belief'); * recursively checks for cyclical connections between InferredBelief nodes
*
* to check for a cycle provide the source of an attempted connection as the targetNode for the cycle check,
* the currentNodeId should be initialised with the id of the targetNode of the attempted connection.
*
* @param {string} targetNodeId - the id of the node we are looking for as the endpoint of a cyclical connection
* @param {string} currentNodeId - the id of the node we are checking for outgoing connections to the provided target node
* @returns {RuleResult}
*/
function checkForCycle(targetNodeId: string, currentNodeId: string) : RuleResult {
const outgoingBeliefs = getOutgoers({id: currentNodeId}, nodes, edges).filter(node => node.type === 'inferred_belief');
if (outgoingBeliefs.length === 0) return ruleResult.satisfied; if (outgoingBeliefs.length === 0) return ruleResult.satisfied;
if (outgoingBeliefs.some(node => node.id === targetNodeId)) return ruleResult if (outgoingBeliefs.some(node => node.id === targetNodeId)) return ruleResult
.notSatisfied("Cyclical connection exists between inferred beliefs"); .notSatisfied(defaultErrorMessage);
const next = outgoingBeliefs.map(node => checkForCycle(targetNodeId, node.id)).find(result => !result.isSatisfied); const next = outgoingBeliefs.map(node => checkForCycle(targetNodeId, node.id)).find(result => !result.isSatisfied);
return next return next
@@ -101,15 +118,15 @@ const noBeliefCycles : HandleRule = (connection, _): RuleResult => {
} }
return connection.source === connection.target return connection.source === connection.target
? ruleResult.notSatisfied("Cyclical connection exists between inferred beliefs") ? ruleResult.notSatisfied(defaultErrorMessage)
: checkForCycle(connection.source, connection.target); : checkForCycle(connection.source, connection.target);
} }
/** /**
* Defines how a BasicBelief node should be rendered * Defines how an InferredBelief node should be rendered
* @param props - Node properties provided by React Flow, including `id` and `data`. * @param {NodeProps<InferredBeliefNode>} props - Node properties provided by React Flow, including `id` and `data`.
* @returns The rendered BasicBeliefNode React element (React.JSX.Element). * @returns The rendered InferredBeliefNode React element. (React.JSX.Element)
*/ */
export default function InferredBeliefNode(props: NodeProps<InferredBeliefNode>) { export default function InferredBeliefNode(props: NodeProps<InferredBeliefNode>) {
const data = props.data; const data = props.data;
@@ -117,6 +134,7 @@ export default function InferredBeliefNode(props: NodeProps<InferredBeliefNode>)
// start of as an AND operator, true: "AND", false: "OR" // start of as an AND operator, true: "AND", false: "OR"
const [enforceAllBeliefs, setEnforceAllBeliefs] = useState(true); const [enforceAllBeliefs, setEnforceAllBeliefs] = useState(true);
// used to toggle operator
function onToggle() { function onToggle() {
setEnforceAllBeliefs(!enforceAllBeliefs); setEnforceAllBeliefs(!enforceAllBeliefs);
@@ -128,11 +146,12 @@ export default function InferredBeliefNode(props: NodeProps<InferredBeliefNode>)
} }
}); });
} }
return ( return (
<> <>
<Toolbar nodeId={props.id} allowDelete={true}/> <Toolbar nodeId={props.id} allowDelete={true}/>
<div className={`${styles.defaultNode} ${styles.nodeInferredBelief}`}> <div className={`${styles.defaultNode} ${styles.nodeInferredBelief}`}>
{/* The checkbox used to toggle the operator between 'AND' and 'OR' */}
<label className={switchStyles.operatorSwitch}> <label className={switchStyles.operatorSwitch}>
<input <input
type="checkbox" type="checkbox"
@@ -169,8 +188,8 @@ export default function InferredBeliefNode(props: NodeProps<InferredBeliefNode>)
/** /**
* Reduces each BasicBelief, including its children down into its core data. * Reduces each BasicBelief, including its children down into its core data.
* @param node - The BasicBelief node to reduce. * @param {Node} node - The BasicBelief node to reduce.
* @param nodes - The list of all nodes in the current flow graph. * @param {Node[]} nodes - The list of all nodes in the current flow graph.
* @returns A simplified object containing the node label and its list of BasicBeliefs. * @returns A simplified object containing the node label and its list of BasicBeliefs.
*/ */
export function InferredBeliefReduce(node: Node, nodes: Node[]) { export function InferredBeliefReduce(node: Node, nodes: Node[]) {
@@ -187,5 +206,6 @@ export function InferredBeliefReduce(node: Node, nodes: Node[]) {
operator: data.inferredBelief.operator ? "AND" : "OR", operator: data.inferredBelief.operator ? "AND" : "OR",
right: BeliefReduce(rightBelief, nodes), right: BeliefReduce(rightBelief, nodes),
}; };
return result return result
} }