#![allow(dead_code, unused_imports, unused_variables)]
use crate::{state::State, Behavior, Float, Select, Sequence, BT};
use petgraph::{graph::Graph, stable_graph::NodeIndex, Direction::Outgoing};
use std::{collections::VecDeque, fmt::Debug};
#[derive(Debug, Clone)]
pub(crate) enum NodeType<A> {
Root,
Wait(Float),
WaitForever,
Action(A),
Invert,
AlwaysSucceed,
Select,
If,
Sequence,
WhileAll,
While,
WhenAll,
WhenAny,
After,
Race,
}
impl<A: Clone + Debug, K: Debug> BT<A, K> {
pub(crate) fn dfs_recursive(
graph: &mut Graph<NodeType<A>, u32, petgraph::Directed>,
behavior: Behavior<A>,
parent_node: NodeIndex,
) {
match behavior {
Behavior::Action(action) => {
let node_id = graph.add_node(NodeType::Action(action));
graph.add_edge(parent_node, node_id, 1);
}
Behavior::Invert(ev) => {
let node_id = graph.add_node(NodeType::Invert);
graph.add_edge(parent_node, node_id, 1);
Self::dfs_recursive(graph, *ev, node_id)
}
Behavior::AlwaysSucceed(ev) => {
let node_id = graph.add_node(NodeType::AlwaysSucceed);
graph.add_edge(parent_node, node_id, 1);
Self::dfs_recursive(graph, *ev, node_id)
}
Behavior::Wait(dt) => {
let node_id = graph.add_node(NodeType::Wait(dt));
graph.add_edge(parent_node, node_id, 1);
}
Behavior::WaitForever => {
let node_id = graph.add_node(NodeType::WaitForever);
graph.add_edge(parent_node, node_id, 1);
}
Behavior::If(condition, success, failure) => {
let node_id = graph.add_node(NodeType::If);
graph.add_edge(parent_node, node_id, 1);
let left = *condition;
Self::dfs_recursive(graph, left, node_id);
let middle = *success;
Self::dfs_recursive(graph, middle, node_id);
let right = *failure;
Self::dfs_recursive(graph, right, node_id);
}
Behavior::Select(sel) => {
let node_id = graph.add_node(NodeType::Select);
graph.add_edge(parent_node, node_id, 1);
for b in sel {
Self::dfs_recursive(graph, b, node_id)
}
}
Behavior::Sequence(seq) => {
let node_id = graph.add_node(NodeType::Sequence);
graph.add_edge(parent_node, node_id, 1);
for b in seq {
Self::dfs_recursive(graph, b, node_id)
}
}
Behavior::While(ev, seq) => {
let node_id = graph.add_node(NodeType::While);
graph.add_edge(parent_node, node_id, 1);
let left = *ev;
Self::dfs_recursive(graph, left, node_id);
let right = Sequence(seq);
Self::dfs_recursive(graph, right, node_id)
}
Behavior::WhileAll(ev, seq) => {
let node_id = graph.add_node(NodeType::WhileAll);
graph.add_edge(parent_node, node_id, 1);
let left = *ev;
Self::dfs_recursive(graph, left, node_id);
let right = Sequence(seq);
Self::dfs_recursive(graph, right, node_id)
}
Behavior::WhenAll(all) => {
let node_id = graph.add_node(NodeType::WhenAll);
graph.add_edge(parent_node, node_id, 1);
for b in all {
Self::dfs_recursive(graph, b, node_id)
}
}
Behavior::WhenAny(any) => {
let node_id = graph.add_node(NodeType::WhenAny);
graph.add_edge(parent_node, node_id, 1);
for b in any {
Self::dfs_recursive(graph, b, node_id)
}
}
Behavior::After(after_all) => {
let node_id = graph.add_node(NodeType::After);
graph.add_edge(parent_node, node_id, 1);
for b in after_all {
Self::dfs_recursive(graph, b, node_id)
}
}
Behavior::Race(behaviors) => {
let node_id = graph.add_node(NodeType::Race);
graph.add_edge(parent_node, node_id, 1);
for b in behaviors {
Self::dfs_recursive(graph, b, node_id)
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::visualizer::tests::TestActions::{Dec, Inc};
use crate::Behavior::{
Action, After, AlwaysSucceed, If, Invert, Select, Sequence, Wait, WaitForever, WhenAll, WhenAny, While,
};
use crate::Status::{self, Success};
use crate::{ActionArgs, Event, UpdateArgs};
use petgraph::dot::{Config, Dot};
use petgraph::Graph;
use std::collections::HashMap;
#[derive(Clone, Debug)]
enum TestActions {
Inc,
Dec,
}
fn tick(mut acc: i32, dt: Float, bt: &mut BT<TestActions, HashMap<String, i32>>) -> (i32, Status, Float) {
let e: Event = UpdateArgs { dt }.into();
let (s, t) = bt
.tick(&e, &mut |args, blackboard| match args.action {
TestActions::Inc => {
acc += 1;
(Success, args.dt)
}
TestActions::Dec => {
acc -= 1;
(Success, args.dt)
}
})
.unwrap();
(acc, s, t)
}
#[test]
fn test_viz_sequence_and_action() {
use petgraph::dot::{Config, Dot};
use petgraph::Graph;
let behavior = Sequence(vec![
Action(Dec),
Action(Dec),
Sequence(vec![Action(Inc), Sequence(vec![Action(Inc)])]),
]);
let h: HashMap<String, i32> = HashMap::new();
let mut bt = BT::new(behavior, h);
let (_, g) = bt.get_graphviz_with_graph_instance();
println!("{:?}", Dot::with_config(&g, &[Config::EdgeNoLabel]));
assert_eq!(g.edge_count(), 7);
assert_eq!(g.node_count(), 8);
}
#[test]
fn test_viz_select_and_action() {
let behavior = Select(vec![
Action(Dec),
Select(vec![Action(Inc), Sequence(vec![Action(Inc), Action(Dec)]), Action(Inc)]),
Action(Dec),
]);
let h: HashMap<String, i32> = HashMap::new();
let mut bt = BT::new(behavior, h);
let (_, g) = bt.get_graphviz_with_graph_instance();
println!("{:?}", Dot::with_config(&g, &[Config::EdgeNoLabel]));
assert_eq!(g.edge_count(), 9);
assert_eq!(g.node_count(), 10);
}
#[test]
fn test_viz_sequence_action_wait() {
let behavior = Sequence(vec![
Action(Dec),
Wait(10.0),
Action(Dec),
Select(vec![Wait(5.0), Sequence(vec![Action(Inc), Action(Dec)])]),
]);
let h: HashMap<String, i32> = HashMap::new();
let mut bt = BT::new(behavior, h);
let (_, g) = bt.get_graphviz_with_graph_instance();
println!("{:?}", Dot::with_config(&g, &[Config::EdgeNoLabel]));
assert_eq!(g.edge_count(), 9);
assert_eq!(g.node_count(), 10);
}
#[test]
fn test_viz_while() {
let behavior = While(Box::new(Wait(50.0)), vec![Wait(0.5), Action(Inc), Wait(0.5)]);
let h: HashMap<String, i32> = HashMap::new();
let mut bt = BT::new(behavior, h);
let (_, g) = bt.get_graphviz_with_graph_instance();
println!("{:?}", Dot::with_config(&g, &[Config::EdgeNoLabel]));
assert_eq!(g.edge_count(), 6);
assert_eq!(g.node_count(), 7);
}
#[test]
fn test_viz_while_wait_forever() {
let behavior = While(Box::new(WaitForever), vec![Wait(0.5), Action(Inc), WaitForever]);
let h: HashMap<String, i32> = HashMap::new();
let mut bt = BT::new(behavior, h);
let (_, g) = bt.get_graphviz_with_graph_instance();
println!("{:?}", Dot::with_config(&g, &[Config::EdgeNoLabel]));
assert_eq!(g.edge_count(), 6);
assert_eq!(g.node_count(), 7);
}
#[test]
fn test_viz_while_select_sequence_wait() {
let behavior = While(
Box::new(Select(vec![
Wait(5.0),
Sequence(vec![Action(Inc), Action(Dec)]),
Action(Inc),
])),
vec![Wait(0.5), Action(Inc), Wait(0.5)],
);
let h: HashMap<String, i32> = HashMap::new();
let mut bt = BT::new(behavior, h);
let (_, g) = bt.get_graphviz_with_graph_instance();
println!("{:?}", Dot::with_config(&g, &[Config::EdgeNoLabel]));
assert_eq!(g.edge_count(), 11);
assert_eq!(g.node_count(), 12);
}
#[test]
fn test_invert() {
let behavior = Sequence(vec![Invert(Box::new(Action(Inc))), Action(Dec)]);
let h: HashMap<String, i32> = HashMap::new();
let mut bt = BT::new(behavior, h);
let (_, g) = bt.get_graphviz_with_graph_instance();
println!("{:?}", Dot::with_config(&g, &[Config::EdgeNoLabel]));
assert_eq!(g.edge_count(), 4);
assert_eq!(g.node_count(), 5);
}
#[test]
fn test_sequence_invert_select() {
let behavior = Sequence(vec![
Action(Dec),
Action(Dec),
Invert(Box::new(Select(vec![Action(Inc), Action(Dec)]))),
Action(Dec),
]);
let h: HashMap<String, i32> = HashMap::new();
let mut bt = BT::new(behavior, h);
let (_, g) = bt.get_graphviz_with_graph_instance();
println!("{:?}", Dot::with_config(&g, &[Config::EdgeNoLabel]));
assert_eq!(g.edge_count(), 8);
assert_eq!(g.node_count(), 9);
}
#[test]
fn test_always_succeed() {
let behavior = Sequence(vec![AlwaysSucceed(Box::new(Action(Inc))), Action(Dec)]);
let h: HashMap<String, i32> = HashMap::new();
let mut bt = BT::new(behavior, h);
let (_, g) = bt.get_graphviz_with_graph_instance();
println!("{:?}", Dot::with_config(&g, &[Config::EdgeNoLabel]));
assert_eq!(g.edge_count(), 4);
assert_eq!(g.node_count(), 5);
}
#[test]
fn test_sequence_always_succeed_select() {
let behavior = Sequence(vec![
Action(Dec),
Action(Dec),
AlwaysSucceed(Box::new(Select(vec![Action(Inc), Action(Dec)]))),
Action(Dec),
]);
let h: HashMap<String, i32> = HashMap::new();
let mut bt = BT::new(behavior, h);
let (_, g) = bt.get_graphviz_with_graph_instance();
println!("{:?}", Dot::with_config(&g, &[Config::EdgeNoLabel]));
assert_eq!(g.edge_count(), 8);
assert_eq!(g.node_count(), 9);
}
#[test]
fn test_complex_while_select_sequence() {
let _while = While(
Box::new(Select(vec![Wait(5.0), Sequence(vec![Action(Inc), Action(Dec)])])),
vec![Wait(0.5), Action(Inc), Action(Inc)],
);
let seq = Sequence(vec![Action(Inc), Action(Dec)]);
let behavior = Select(vec![_while, Action(Inc), seq, Action(Dec)]);
let h: HashMap<String, i32> = HashMap::new();
let mut bt = BT::new(behavior, h);
let (_, g) = bt.get_graphviz_with_graph_instance();
println!("{:?}", Dot::with_config(&g, &[Config::EdgeNoLabel]));
assert_eq!(g.edge_count(), 16);
assert_eq!(g.node_count(), 17);
}
#[test]
fn test_while_invert() {
let _while = While(
Box::new(Select(vec![Wait(5.0), Sequence(vec![Action(Inc), Action(Dec)])])),
vec![Wait(0.5), Action(Inc), Invert(Box::new(Wait(0.5)))],
);
let _select = Sequence(vec![Action(Inc), Action(Dec)]);
let behavior = Select(vec![Invert(Box::new(_while)), _select, Action(Inc), Action(Dec)]);
let h: HashMap<String, i32> = HashMap::new();
let mut bt = BT::new(behavior, h);
let (_, g) = bt.get_graphviz_with_graph_instance();
println!("{:?}", Dot::with_config(&g, &[Config::EdgeNoLabel]));
assert_eq!(g.edge_count(), 18);
assert_eq!(g.node_count(), 19);
}
#[test]
fn test_if() {
let condition = Sequence(vec![AlwaysSucceed(Box::new(Action(Inc))), Action(Dec)]);
let behavior = If(
Box::new(condition),
Box::new(Action(Inc)), Box::new(Action(Dec)), );
let h: HashMap<String, i32> = HashMap::new();
let mut bt = BT::new(behavior, h);
let (_, g) = bt.get_graphviz_with_graph_instance();
println!("{:?}", Dot::with_config(&g, &[Config::EdgeNoLabel]));
assert_eq!(g.edge_count(), 7);
assert_eq!(g.node_count(), 8);
}
#[test]
fn test_whenall_invert_whenany() {
let behavior = WhenAll(vec![
Action(Dec),
Action(Dec),
Invert(Box::new(WhenAny(vec![Action(Inc), Action(Dec)]))),
Action(Dec),
]);
let h: HashMap<String, i32> = HashMap::new();
let mut bt = BT::new(behavior, h);
let (_, g) = bt.get_graphviz_with_graph_instance();
println!("{:?}", Dot::with_config(&g, &[Config::EdgeNoLabel]));
assert_eq!(g.edge_count(), 8);
assert_eq!(g.node_count(), 9);
}
#[test]
fn test_viz_after_action_wait() {
let behavior = After(vec![
Action(Dec),
Wait(10.0),
Action(Dec),
WhenAny(vec![Wait(5.0), After(vec![Action(Inc), Action(Dec)])]),
]);
let h: HashMap<String, i32> = HashMap::new();
let mut bt = BT::new(behavior, h);
let (_, g) = bt.get_graphviz_with_graph_instance();
println!("{:?}", Dot::with_config(&g, &[Config::EdgeNoLabel]));
assert_eq!(g.edge_count(), 9);
assert_eq!(g.node_count(), 10);
}
}