use super::elapsed_timer::{reset_timer_field, ElapsedTimer};
use crate::{BehaviorNode, Context, NodeStatus};
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::time::Duration;
macro_rules! from_json_with_duration {
($config:ident) => {
pub fn from_json(config: Value) -> anyhow::Result<Self> {
let cfg: $config = serde_json::from_value(config)?;
Ok(Self {
duration: Duration::from_secs_f64(cfg.duration_secs),
timer: ElapsedTimer::default(),
})
}
};
}
#[derive(Debug, Default)]
pub struct TimerNode {
duration: Duration,
timer: ElapsedTimer,
}
#[derive(Debug, Serialize, Deserialize)]
struct TimerConfig {
duration_secs: f64,
}
impl TimerNode {
from_json_with_duration!(TimerConfig);
}
#[async_trait]
impl BehaviorNode for TimerNode {
async fn tick(&mut self, _ctx: &Context) -> anyhow::Result<NodeStatus> {
if self.timer.elapsed_since_start(self.duration) {
Ok(NodeStatus::Success)
} else {
Ok(NodeStatus::Running)
}
}
reset_timer_field!(timer);
fn name(&self) -> &str {
"TimerNode"
}
}
#[derive(Debug)]
pub struct IdleNode;
impl IdleNode {
pub fn from_json(_config: Value) -> anyhow::Result<Self> {
Ok(Self)
}
}
#[async_trait]
impl BehaviorNode for IdleNode {
async fn tick(&mut self, _ctx: &Context) -> anyhow::Result<NodeStatus> {
Ok(NodeStatus::Success)
}
fn name(&self) -> &str {
"IdleNode"
}
}
#[derive(Debug, Default)]
pub struct PauseNode {
duration: Duration,
timer: ElapsedTimer,
}
#[derive(Debug, Serialize, Deserialize)]
struct PauseConfig {
duration_secs: f64,
}
impl PauseNode {
from_json_with_duration!(PauseConfig);
}
#[async_trait]
impl BehaviorNode for PauseNode {
async fn tick(&mut self, _ctx: &Context) -> anyhow::Result<NodeStatus> {
if !self.timer.is_running() {
tracing::debug!("PauseNode: starting pause for {:?}", self.duration);
}
if self.timer.elapsed_since_start(self.duration) {
tracing::debug!("PauseNode: pause complete");
Ok(NodeStatus::Success)
} else {
Ok(NodeStatus::Running)
}
}
reset_timer_field!(timer);
fn name(&self) -> &str {
"PauseNode"
}
}