1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use crate::engine::EvaluationOptions;
use crate::handler::tree::{GraphResponse, GraphTree, GraphTreeConfig};
use crate::loader::{DecisionLoader, NoopLoader};
use crate::model::DecisionContent;
use anyhow::Context;
use serde_json::Value;
use std::sync::Arc;

pub struct Decision<L>
where
    L: DecisionLoader,
{
    content: Arc<DecisionContent>,
    loader: Arc<L>,
}

impl From<DecisionContent> for Decision<NoopLoader> {
    fn from(value: DecisionContent) -> Self {
        Self {
            content: value.into(),
            loader: NoopLoader::default().into(),
        }
    }
}

impl From<Arc<DecisionContent>> for Decision<NoopLoader> {
    fn from(value: Arc<DecisionContent>) -> Self {
        Self {
            content: value,
            loader: NoopLoader::default().into(),
        }
    }
}

impl<L> Decision<L>
where
    L: DecisionLoader,
{
    pub fn with_loader<NL>(self, loader: Arc<NL>) -> Decision<NL>
    where
        NL: DecisionLoader,
    {
        Decision {
            loader,
            content: self.content,
        }
    }

    pub async fn evaluate(&self, context: &Value) -> Result<GraphResponse, anyhow::Error> {
        self.evaluate_with_opts(context, Default::default()).await
    }

    pub async fn evaluate_with_opts(
        &self,
        context: &Value,
        options: EvaluationOptions,
    ) -> Result<GraphResponse, anyhow::Error> {
        let tree = GraphTree::new(GraphTreeConfig {
            max_depth: options.max_depth.unwrap_or(5),
            trace: options.trace.unwrap_or_default(),
            loader: self.loader.clone(),
            iteration: 0,
            content: &self.content,
        });

        tree.connect()?;
        tree.evaluate(context)
            .await
            .context("Failed to revaluate graph")
    }
}