capability-skeleton-string 0.1.0

A robust library for managing skill tree skeletons using string-based nodes and bidirectional conversions between string and numeric formats.
Documentation
// ---------------- [ File: capability-skeleton-string/src/aggregate_child_spec.rs ]
crate::ix!();

/// Use this object to specify per-child optionality and toggle probability for a model branch within an `Aggregate` node.
///
#[derive(Eq,Default,AiJsonTemplateWithJustification,Builder,SaveLoad,Getters,Debug, Copy,Clone, PartialEq, Serialize, Deserialize, AiJsonTemplate)]
#[builder(pattern="owned", setter(into))]
#[getset(get = "pub")]
pub struct AggregateChildSpec {

    /// Set the `psome_likelihood` field to indicate the probability this child (if `optional`) is *something* as opposed to *nothing*.
    ///
    /// This field has no meaning if `optional` is *false.
    ///
    /// Values may be 0..100 inclusive. Values over this maximum will be clipped.
    ///
    #[serde(default)]
    #[serde(deserialize_with = "fuzzy_u8")]
    psome_likelihood: u8,

    /// Set the `optional` field to indicate whether or not this tree branch is *optional*.
    #[serde(default)]
    optional: bool,
}

impl FuzzyFromJsonValue for JustifiedAggregateChildSpec {
    fn fuzzy_from_json_value(value: &serde_json::Value)
        -> Result<Self, FuzzyFromJsonValueError>
    {
        trace!("(JustifiedAggregateChildSpec) Entering fuzzy_from_json_value => {}", value);

        // must be an object
        let obj = match value.as_object() {
            Some(m) => {
                trace!("(JustifiedAggregateChildSpec) Found object => proceed to parse fields");
                m
            }
            None => {
                error!("(JustifiedAggregateChildSpec) Not an object => fail");
                return Err(FuzzyFromJsonValueError::NotAnObject {
                    target_type: "JustifiedAggregateChildSpec",
                    actual: value.clone(),
                });
            }
        };

        // parse psome_likelihood as u8
        let psome_val = obj.get("psome_likelihood").ok_or_else(|| {
            error!("(JustifiedAggregateChildSpec) Missing 'psome_likelihood' => fail");
            FuzzyFromJsonValueError::MissingField {
                field_name: "psome_likelihood",
                target_type: "JustifiedAggregateChildSpec",
            }
        })?;
        let psome_likelihood = fuzzy_u8(psome_val).map_err(|e| {
            error!("(JustifiedAggregateChildSpec) Could not parse psome_likelihood => {:?}", e);
            FuzzyFromJsonValueError::Other {
                target_type: "JustifiedAggregateChildSpec",
                detail: e.to_string(),
            }
        })?;

        // parse optional as bool
        let optional_val = obj.get("optional").ok_or_else(|| {
            error!("(JustifiedAggregateChildSpec) Missing 'optional' => fail");
            FuzzyFromJsonValueError::MissingField {
                field_name: "optional",
                target_type: "JustifiedAggregateChildSpec",
            }
        })?;
        let optional_bool = match optional_val {
            serde_json::Value::Bool(b) => *b,
            other => {
                error!("(JustifiedAggregateChildSpec) 'optional' must be bool => got {:?}", other);
                return Err(FuzzyFromJsonValueError::Other {
                    target_type: "JustifiedAggregateChildSpec",
                    detail: format!("Expected 'optional' to be bool, got {:?}", other),
                });
            }
        };

        // parse the confidence & justification if present
        let psome_likelihood_confidence = obj.get("psome_likelihood_confidence")
            .and_then(|val| val.as_f64())
            .unwrap_or(0.0);
        let psome_likelihood_justification = obj.get("psome_likelihood_justification")
            .and_then(|val| val.as_str())
            .unwrap_or("no justification provided")
            .to_string();

        let optional_confidence = obj.get("optional_confidence")
            .and_then(|val| val.as_f64())
            .unwrap_or(0.0);
        let optional_justification = obj.get("optional_justification")
            .and_then(|val| val.as_str())
            .unwrap_or("no justification provided")
            .to_string();

        trace!("(JustifiedAggregateChildSpec) Successfully parsed => psome_likelihood={}, optional={}", 
            psome_likelihood, optional_bool);

        Ok(JustifiedAggregateChildSpec {
            psome_likelihood,
            psome_likelihood_confidence,
            psome_likelihood_justification,
            optional: optional_bool,
            optional_confidence,
            optional_justification,
        })
    }
}