reactive_graph_std_numeric/behaviour/entity/operation/
behaviour_f64.rs1use reactive_graph_behaviour_model_api::behaviour_validator;
2use reactive_graph_behaviour_model_api::prelude::*;
3use reactive_graph_behaviour_model_impl::entity_behaviour;
4use reactive_graph_graph::prelude::*;
5use reactive_graph_reactive_model_impl::ReactiveEntity;
6use serde_json::Value;
7use serde_json::json;
8use uuid::Uuid;
9
10use reactive_graph_std_numeric_model::NumericOperationProperties::LHS;
11use reactive_graph_std_result_model::ResultNumberF64Properties::RESULT;
12
13use crate::behaviour::as_f64;
14use crate::behaviour::entity::operation::function::NumericOperationF64Function;
15
16entity_behaviour!(
17 NumericOperationF64,
18 NumericOperationF64Factory,
19 NumericOperationF64Fsm,
20 NumericOperationF64BehaviourTransitions,
21 NumericOperationF64Validator,
22 f,
23 NumericOperationF64Function
24);
25
26behaviour_validator!(NumericOperationF64Validator, Uuid, ReactiveEntity, LHS.as_ref(), RESULT.as_ref());
27
28impl BehaviourInit<Uuid, ReactiveEntity> for NumericOperationF64BehaviourTransitions {
29 fn init(&self) -> Result<(), BehaviourInitializationFailed> {
30 let lhs = self.reactive_instance.get(LHS).and_then(as_f64).ok_or(BehaviourInitializationFailed {})?;
31 let f = self.f;
32 let initial_value = f(lhs);
33 self.reactive_instance.set(RESULT, json!(initial_value));
34 Ok(())
35 }
36}
37
38impl BehaviourConnect<Uuid, ReactiveEntity> for NumericOperationF64BehaviourTransitions {
39 fn connect(&self) -> Result<(), BehaviourConnectFailed> {
40 let reactive_instance = self.property_observers.reactive_instance.clone();
41 let f = self.f;
42 self.property_observers.observe_with_handle(LHS.as_ref(), move |v: &Value| {
43 if let Some(v) = as_f64(v.clone()) {
44 reactive_instance.set(RESULT, json!(f(v)));
45 }
46 });
47 Ok(())
48 }
49}
50
51impl BehaviourShutdown<Uuid, ReactiveEntity> for NumericOperationF64BehaviourTransitions {}
52impl BehaviourTransitions<Uuid, ReactiveEntity> for NumericOperationF64BehaviourTransitions {}
53
54#[cfg(test)]
55mod tests {
56 use std::sync::Arc;
57
58 use reactive_graph_behaviour_model_api::BehaviourFactory;
59 use reactive_graph_behaviour_model_api::BehaviourFsm;
60 use reactive_graph_behaviour_model_api::BehaviourTypeId;
61 use reactive_graph_graph::prelude::*;
62 use reactive_graph_reactive_model_impl::ReactiveEntity;
63 use uuid::Uuid;
64
65 use reactive_graph_std_numeric_model::NumericOperationF64;
66
67 use crate::behaviour::entity::operation::behaviour_f64::NumericOperationF64Factory;
68 use crate::behaviour::entity::operation::function::*;
69 use crate::behaviour::entity::operation::tests::numeric_operation;
70
71 #[test]
72 fn numeric_operation_behaviour_test() {
73 let nv: f64 = -0.5;
74 let nz: f64 = -0.0;
75 let pz: f64 = 0.0;
76 let pv: f64 = 0.5;
77
78 for (behaviour_ty, f) in NUMERIC_OPERATIONS_F64.iter() {
79 let entity_ty = EntityTypeId::new_from_type(behaviour_ty.namespace(), behaviour_ty.type_name());
80
81 let expected = f(nv);
83 let result = test_numeric_operation_behaviour(behaviour_ty, &entity_ty, nv);
84 println!("{}({}) | {:?} | {:?}", entity_ty, nv, expected, result);
85 if !expected.is_nan() {
86 assert_eq!(expected, result.unwrap());
87 } else {
88 assert!(result.is_none());
89 }
90
91 let expected = f(nz);
93 let result = test_numeric_operation_behaviour(behaviour_ty, &entity_ty, nz);
94 println!("{}({}) | {:?} | {:?}", entity_ty, nz, expected, result);
95 if !expected.is_infinite() {
96 assert_eq!(expected, result.unwrap());
97 } else {
98 assert!(result.is_none());
99 }
100
101 let expected = f(pz);
103 let result = test_numeric_operation_behaviour(behaviour_ty, &entity_ty, pz);
104 println!("{}({}) | {:?} | {:?}", entity_ty, pz, expected, result);
105 if !expected.is_infinite() {
106 assert_eq!(expected, result.unwrap());
107 } else {
108 assert!(result.is_none());
109 }
110
111 let expected = f(pv);
113 let result = test_numeric_operation_behaviour(behaviour_ty, &entity_ty, pv);
114 println!("{}({}) | {:?} | {:?}", entity_ty, pv, expected, result);
115 assert_eq!(expected, result.unwrap());
116 }
117 }
118
119 fn test_numeric_operation_behaviour(behaviour_ty: &BehaviourTypeId, entity_ty: &EntityTypeId, v: f64) -> Option<f64> {
120 let behaviour = create_numeric_operation_behaviour(behaviour_ty, entity_ty);
121 let reactive_instance = behaviour.get_reactive_instance();
122 let numeric_operation = NumericOperationF64::from(reactive_instance.clone());
123 numeric_operation.lhs(v);
124 numeric_operation.result()
125 }
126
127 fn create_numeric_operation_behaviour(
128 behaviour_ty: &BehaviourTypeId,
129 entity_ty: &EntityTypeId,
130 ) -> Arc<dyn BehaviourFsm<Uuid, ReactiveEntity> + Send + Sync> {
131 let reactive_instance = numeric_operation(entity_ty);
132 let not_function = NUMERIC_OPERATIONS_F64.get(&behaviour_ty).expect("Failed to get function");
133 let not_factory = NumericOperationF64Factory::new(behaviour_ty.clone(), not_function.clone());
134 not_factory.create(reactive_instance.clone()).expect("Failed to create behaviour")
135 }
136}