-module(bt_runner). -include("bt_nodes.hrl"). -export([ run/3, preempt/3, clear_metadata/1 ]). %% clear metadata before running the node, then add it again based on result. %% better to do it here instead of individual handling in node runners %% just setting status for new, maybe will add rest of the stuff later on. -spec run( Node :: bt_node(), BB :: blackboard(), Event :: bt_event()) -> {Status :: bt_status(), NewNode :: bt_node(), NewBB :: blackboard()}. run(Node, BB, Event) when is_record(Node, sequence) -> {Status, NewNode, NewBB} = run_sequence:run(Node#sequence{metadata = undefined}, BB, Event), {Status, NewNode#sequence{metadata = #bt_metadata{status = Status}}, NewBB}; run(Node, BB, Event) when is_record(Node, decorator) -> {Status, NewNode, NewBB, Exception} = run_decorator:run(Node#decorator{metadata = undefined}, BB, Event), {Status, NewNode#decorator{metadata = #bt_metadata{status = Status, exception = Exception}}, NewBB}; run(Node, BB, Event) when is_record(Node, task) -> {Status, NewNode, NewBB, Exception} = run_task:run(Node#task{metadata = undefined}, BB, Event), {Status, NewNode#task{metadata = #bt_metadata{status = Status, exception = Exception}}, NewBB}. %% set metadata to undefined for all preempted nodes. actually no? because we sometimes run and preempt the same node %% in one cycle -spec preempt( Node :: bt_node(), BB :: blackboard(), ShouldCleanBB :: boolean()) -> {NewNode :: bt_node(), NewBB :: blackboard()}. preempt(Node, BB, ShouldCleanBB) when is_record(Node, sequence) -> run_sequence:preempt(Node, BB, ShouldCleanBB); preempt(Node, BB, ShouldCleanBB) when is_record(Node, decorator) -> run_decorator:preempt(Node, BB, ShouldCleanBB); preempt(Node, BB, ShouldCleanBB) when is_record(Node, task) -> run_task:preempt(Node, BB, ShouldCleanBB). %% defining clear metadata together for all nodes here only... -spec clear_metadata( Node :: bt_node() ) -> NewNode :: bt_node(). clear_metadata(Node) when is_record(Node, sequence) -> Node#sequence{metadata = undefined, children = [clear_metadata(Child) || Child <- Node#sequence.children]}; clear_metadata(Node) when is_record(Node, decorator) -> Node#decorator{metadata = undefined, child = clear_metadata(Node#decorator.child)}; clear_metadata(Node) when is_record(Node, task) -> Node#task{metadata = undefined}.