use crate::rule::{EvalFn, ExecuteFn, Rule, RuleContext, RuleResult};
pub struct BestFirstRule {
children: Vec<Box<dyn Rule>>,
eval_fn: Option<EvalFn>,
pre_execute_fn: Option<ExecuteFn>,
execute_fn: Option<ExecuteFn>,
post_execute_fn: Option<ExecuteFn>,
}
impl BestFirstRule {
pub fn new() -> Self {
BestFirstRule {
children: Vec::new(),
eval_fn: None,
pre_execute_fn: None,
execute_fn: None,
post_execute_fn: None,
}
}
pub fn set_eval_fn<F>(&mut self, f: F) -> &mut Self
where
F: Fn(&RuleContext) -> RuleResult<bool> + 'static,
{
self.eval_fn = Some(Box::new(f));
self
}
pub fn set_pre_execute_fn<F>(&mut self, f: F) -> &mut Self
where
F: Fn(&mut RuleContext) -> RuleResult<()> + 'static,
{
self.pre_execute_fn = Some(Box::new(f));
self
}
pub fn set_execute_fn<F>(&mut self, f: F) -> &mut Self
where
F: Fn(&mut RuleContext) -> RuleResult<()> + 'static,
{
self.execute_fn = Some(Box::new(f));
self
}
pub fn set_post_execute_fn<F>(&mut self, f: F) -> &mut Self
where
F: Fn(&mut RuleContext) -> RuleResult<()> + 'static,
{
self.post_execute_fn = Some(Box::new(f));
self
}
}
impl Rule for BestFirstRule {
fn evaluate(&self, context: &RuleContext) -> RuleResult<bool> {
match &self.eval_fn {
Some(f) => f(context),
None => Ok(true), }
}
fn execute(&mut self, context: &mut RuleContext) -> RuleResult<()> {
if let Some(f) = &self.pre_execute_fn {
f(context)?;
}
if let Some(f) = &self.execute_fn {
f(context)?;
}
if let Some(f) = &self.post_execute_fn {
f(context)?;
}
Ok(())
}
fn children(&self) -> &[Box<dyn Rule>] {
&self.children
}
fn children_mut(&mut self) -> &mut Vec<Box<dyn Rule>> {
&mut self.children
}
fn add_child(&mut self, child: Box<dyn Rule>) -> RuleResult<()> {
self.children.push(child);
Ok(())
}
fn fire(&mut self, context: &mut RuleContext) -> RuleResult<bool> {
if self.evaluate(context)? {
self.execute(context)?;
for child in &mut self.children {
if child.evaluate(context)? {
child.fire(context)?;
return Ok(true);
}
}
Ok(true)
} else {
Ok(false)
}
}
}
impl Default for BestFirstRule {
fn default() -> Self {
Self::new()
}
}