use crate::{Bhv, Status};
#[derive(Clone)]
pub struct Inv<B: Bhv>(pub(crate) B);
#[derive(Clone)]
pub struct Pass<B: Bhv>(pub(crate) B);
#[derive(Clone)]
pub struct Fail<B: Bhv>(pub(crate) B);
#[derive(Clone)]
pub struct RunIf<B, C>
where
B: Bhv,
C: Fn(&B::Context) -> bool
{
pub(crate) bhv: B,
pub(crate) cond: C,
}
#[derive(Clone)]
pub struct Repeat<B: Bhv> {
pub(crate) bhv: B,
pub(crate) count: u32,
pub(crate) current: u32,
}
#[derive(Clone)]
pub struct RepeatUntil<B, C>
where
B: Bhv,
C: Fn(&B::Context) -> bool,
{
pub(crate) bhv: B,
pub(crate) cond: C,
pub(crate) checked_cond: bool,
}
#[derive(Clone)]
pub struct RepeatUntilPass<B: Bhv>(pub(crate) B);
#[derive(Clone)]
pub struct RepeatUntilFail<B: Bhv>(pub(crate) B);
impl<B: Bhv> Bhv for Inv<B> {
type Context = B::Context;
fn update(&mut self, ctx: &mut Self::Context) -> Status {
match self.0.update(ctx) {
Status::Running => Status::Running,
Status::Failure => Status::Success,
Status::Success => Status::Failure,
}
}
fn reset(&mut self, _status: Status) {
self.0.reset(_status)
}
}
impl<B: Bhv> Bhv for Pass<B> {
type Context = B::Context;
fn update(&mut self, ctx: &mut Self::Context) -> Status {
match self.0.update(ctx) {
Status::Failure => Status::Success,
s => s,
}
}
fn reset(&mut self, _status: Status) {
self.0.reset(_status)
}
}
impl<B: Bhv> Bhv for Fail<B> {
type Context = B::Context;
fn update(&mut self, ctx: &mut Self::Context) -> Status {
match self.0.update(ctx) {
Status::Success => Status::Failure,
s => s,
}
}
fn reset(&mut self, _status: Status) {
self.0.reset(_status)
}
}
impl<B, C> Bhv for RunIf<B, C>
where
B: Bhv,
C: Fn(&B::Context) -> bool,
{
type Context = B::Context;
fn update(&mut self, ctx: &mut Self::Context) -> Status {
if (self.cond)(ctx) {
self.bhv.update(ctx)
} else {
Status::Failure
}
}
#[inline]
fn reset(&mut self, _status: Status) { self.bhv.reset(_status) }
}
impl<B: Bhv> Bhv for Repeat<B> {
type Context = B::Context;
fn update(&mut self, ctx: &mut Self::Context) -> Status {
if self.current >= self.count {
self.bhv.update(ctx)
} else {
match self.bhv.update(ctx) {
Status::Running => {}
s => {
self.bhv.reset(s);
self.current += 1;
}
};
Status::Running
}
}
fn reset(&mut self, _status: Status) {
self.bhv.reset(_status);
self.current = 1;
}
}
impl<B, C> Bhv for RepeatUntil<B, C>
where
B: Bhv,
C: Fn(&B::Context) -> bool,
{
type Context = B::Context;
fn update(&mut self, ctx: &mut Self::Context) -> Status {
let s = self.bhv.update(ctx);
if s != Status::Running {
self.checked_cond = false;
self.bhv.reset(s);
}
if !self.checked_cond {
if (self.cond)(ctx) {
return Status::Success;
} else {
self.checked_cond = true;
}
}
Status::Running
}
fn reset(&mut self, _status: Status) {
self.bhv.reset(_status)
}
}
impl<B: Bhv> Bhv for RepeatUntilPass<B> {
type Context = B::Context;
fn update(&mut self, ctx: &mut Self::Context) -> Status {
match self.0.update(ctx) {
Status::Failure => {
self.0.reset(Status::Failure);
Status::Running
}
s => s,
}
}
fn reset(&mut self, _status: Status) {
self.0.reset(_status)
}
}
impl<B: Bhv> Bhv for RepeatUntilFail<B> {
type Context = B::Context;
fn update(&mut self, ctx: &mut Self::Context) -> Status {
match self.0.update(ctx) {
Status::Success => {
self.0.reset(Status::Success);
Status::Running
}
s => s,
}
}
fn reset(&mut self, _status: Status) {
self.0.reset(_status)
}
}