feat: made a basic version of inferredBeliefNode without all functionality

full reduce and connection logic is still missing

ref: N25B-433
This commit is contained in:
JGerla
2026-01-12 15:34:44 +01:00
parent 5385bd72b1
commit 0a4940bdd0
11 changed files with 303 additions and 17 deletions

View File

@@ -0,0 +1,153 @@
import {
type NodeProps,
Position,
type Node,
} from '@xyflow/react';
import {useState} from "react";
import { Toolbar } from '../components/NodeComponents.tsx';
import styles from '../../VisProg.module.css';
import switchStyles from './InferredBeliefNode.module.css';
import {MultiConnectionHandle, SingleConnectionHandle} from "../components/RuleBasedHandle.tsx";
import {allowOnlyConnectionsFromType} from "../HandleRules.ts";
import useFlowStore from "../VisProgStores.tsx";
import type {BasicBeliefType} from "./BasicBeliefNode.tsx";
/**
* The default data structure for an InferredBelief node
*/
export type InferredBeliefNodeData = {
label: string;
droppable: boolean;
inferredBelief: Belief;
hasReduce: boolean;
};
type Belief = InferredBelief | BasicBeliefType;
type InferredBelief = {
id: string;
left: Belief | undefined,
operator: "AND" | "OR"
right: Belief | undefined
};
// helper validation function for InferredBelief objects
// const isValidInferredBelief = (inferredBelief: InferredBelief) : boolean => {
// return !(inferredBelief.left && inferredBelief.right);
// };
export type InferredBeliefNode = Node<InferredBeliefNodeData>;
/**
* 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 InferredBeliefConnectionTarget(_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 InferredBeliefConnectionSource(_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 InferredBeliefDisconnectionTarget(_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 InferredBeliefDisconnectionSource(_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 InferredBeliefNode(props: NodeProps<InferredBeliefNode>) {
const data = props.data;
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: {
...data.inferredBelief,
operator: enforceAllBeliefs ? "AND" : "OR",
}
});
}
// TODO define node
return (
<>
<Toolbar nodeId={props.id} allowDelete={true}/>
<div className={`${styles.defaultNode} ${styles.nodeInferredBelief}`}>
<label className={switchStyles.operatorSwitch}>
<input
type="checkbox"
checked={enforceAllBeliefs}
onChange={onToggle}
/>
<div className={switchStyles.switchVisual}></div>
<div className={switchStyles.switchLabels}>
<span title={"Belief is fulfilled if either of the supplied beliefs is true"}>OR</span>
<span title={"Belief is fulfilled if all of the supplied beliefs are true"}>AND</span>
</div>
</label>
{/* outgoing connections */}
<MultiConnectionHandle type="source" position={Position.Right} id="source" rules={[
allowOnlyConnectionsFromType(["norm", "trigger"]),
]}/>
{/* incoming connections */}
<SingleConnectionHandle type="target" position={Position.Left} style={{top: '30%'}} id="beliefLeft" rules={[
allowOnlyConnectionsFromType(["basic_belief", "inferred_belief"]),
]}/>
<SingleConnectionHandle type="target" position={Position.Left} style={{top: '70%'}} id="beliefRight" rules={[
allowOnlyConnectionsFromType(["basic_belief", "inferred_belief"]),
]}/>
</div>
</>
);
};
/**
* 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 InferredBeliefReduce(node: Node, _nodes: Node[]) {
//const data = node.data as InferredBeliefNodeData;
const result: Record<string, unknown> = {
id: node.id,
};
// TODO define reduce
return result
}