mecha10_behavior_runtime/actions/
timing.rs1use crate::{BehaviorNode, Context, NodeStatus};
4use async_trait::async_trait;
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7use std::time::{Duration, Instant};
8
9#[derive(Debug)]
24pub struct TimerNode {
25 duration: Duration,
26 start_time: Option<Instant>,
27}
28
29#[derive(Debug, Serialize, Deserialize)]
30struct TimerConfig {
31 duration_secs: f64,
32}
33
34impl TimerNode {
35 pub fn from_json(config: Value) -> anyhow::Result<Self> {
37 let cfg: TimerConfig = serde_json::from_value(config)?;
38 Ok(Self {
39 duration: Duration::from_secs_f64(cfg.duration_secs),
40 start_time: None,
41 })
42 }
43}
44
45#[async_trait]
46impl BehaviorNode for TimerNode {
47 async fn tick(&mut self, _ctx: &Context) -> anyhow::Result<NodeStatus> {
48 let now = Instant::now();
49
50 if self.start_time.is_none() {
52 self.start_time = Some(now);
53 }
54
55 if now.duration_since(self.start_time.unwrap()) >= self.duration {
57 Ok(NodeStatus::Success)
58 } else {
59 Ok(NodeStatus::Running)
60 }
61 }
62
63 async fn reset(&mut self) -> anyhow::Result<()> {
64 self.start_time = None;
65 Ok(())
66 }
67
68 fn name(&self) -> &str {
69 "TimerNode"
70 }
71}
72
73#[derive(Debug)]
87pub struct IdleNode;
88
89impl IdleNode {
90 pub fn from_json(_config: Value) -> anyhow::Result<Self> {
92 Ok(Self)
93 }
94}
95
96#[async_trait]
97impl BehaviorNode for IdleNode {
98 async fn tick(&mut self, _ctx: &Context) -> anyhow::Result<NodeStatus> {
99 Ok(NodeStatus::Success)
100 }
101
102 fn name(&self) -> &str {
103 "IdleNode"
104 }
105}
106
107#[derive(Debug)]
123pub struct PauseNode {
124 duration: Duration,
125 start_time: Option<Instant>,
126}
127
128#[derive(Debug, Serialize, Deserialize)]
129struct PauseConfig {
130 duration_secs: f64,
131}
132
133impl PauseNode {
134 pub fn from_json(config: Value) -> anyhow::Result<Self> {
136 let cfg: PauseConfig = serde_json::from_value(config)?;
137 Ok(Self {
138 duration: Duration::from_secs_f64(cfg.duration_secs),
139 start_time: None,
140 })
141 }
142}
143
144#[async_trait]
145impl BehaviorNode for PauseNode {
146 async fn tick(&mut self, _ctx: &Context) -> anyhow::Result<NodeStatus> {
147 let now = Instant::now();
148
149 if self.start_time.is_none() {
151 self.start_time = Some(now);
152 tracing::debug!("PauseNode: starting pause for {:?}", self.duration);
153 }
154
155 if now.duration_since(self.start_time.unwrap()) >= self.duration {
157 tracing::debug!("PauseNode: pause complete");
158 Ok(NodeStatus::Success)
159 } else {
160 Ok(NodeStatus::Running)
161 }
162 }
163
164 async fn reset(&mut self) -> anyhow::Result<()> {
165 self.start_time = None;
166 Ok(())
167 }
168
169 fn name(&self) -> &str {
170 "PauseNode"
171 }
172}