use crate::sketchbook::ids::{DatasetId, DynPropertyId, ObservationId};
use crate::sketchbook::properties::dynamic_props;
use crate::sketchbook::JsonSerde;
use dynamic_props::{DynProperty, DynPropertyType};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct GenericDynPropData {
pub formula: String,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct ExistsFixedPointData {
pub dataset: Option<String>,
pub observation: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct ExistsTrapSpaceData {
pub dataset: Option<String>,
pub observation: Option<String>,
pub minimal: bool,
pub nonpercolable: bool,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct ExistsTrajectoryData {
pub dataset: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct AttractorCountData {
pub minimal: usize,
pub maximal: usize,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct HasAttractorData {
pub dataset: Option<String>,
pub observation: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "variant")]
pub enum DynPropertyTypeData {
GenericDynProp(GenericDynPropData),
ExistsFixedPoint(ExistsFixedPointData),
ExistsTrapSpace(ExistsTrapSpaceData),
ExistsTrajectory(ExistsTrajectoryData),
AttractorCount(AttractorCountData),
HasAttractor(HasAttractorData),
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct DynPropertyData {
pub id: String,
pub name: String,
pub annotation: String,
#[serde(flatten)]
pub variant: DynPropertyTypeData,
}
impl<'de> JsonSerde<'de> for DynPropertyData {}
impl DynPropertyData {
pub fn new_generic(id: &str, name: &str, formula: &str, annotation: &str) -> DynPropertyData {
let variant = DynPropertyTypeData::GenericDynProp(GenericDynPropData {
formula: formula.to_string(),
});
Self::new_raw(id, name, variant, annotation)
}
pub fn from_property(id: &DynPropertyId, property: &DynProperty) -> DynPropertyData {
let name = property.get_name();
let annot = property.get_annotation();
let variant = match property.get_prop_data() {
DynPropertyType::GenericDynProp(p) => {
DynPropertyTypeData::GenericDynProp(GenericDynPropData {
formula: p.raw_formula.to_string(),
})
}
DynPropertyType::ExistsFixedPoint(p) => {
DynPropertyTypeData::ExistsFixedPoint(ExistsFixedPointData {
dataset: p.dataset.as_ref().map(|i| i.to_string()),
observation: p.observation.as_ref().map(|i| i.to_string()),
})
}
DynPropertyType::ExistsTrapSpace(p) => {
DynPropertyTypeData::ExistsTrapSpace(ExistsTrapSpaceData {
dataset: p.dataset.clone().map(|i| i.to_string()),
observation: p.observation.clone().map(|i| i.to_string()),
minimal: p.minimal,
nonpercolable: p.nonpercolable,
})
}
DynPropertyType::ExistsTrajectory(p) => {
DynPropertyTypeData::ExistsTrajectory(ExistsTrajectoryData {
dataset: p.dataset.as_ref().map(|i| i.to_string()),
})
}
DynPropertyType::HasAttractor(p) => {
DynPropertyTypeData::HasAttractor(HasAttractorData {
dataset: p.dataset.as_ref().map(|i| i.to_string()),
observation: p.observation.as_ref().map(|o| o.to_string()),
})
}
DynPropertyType::AttractorCount(p) => {
DynPropertyTypeData::AttractorCount(AttractorCountData {
minimal: p.minimal,
maximal: p.maximal,
})
}
};
Self::new_raw(id.as_str(), name, variant, annot)
}
pub fn to_property(&self) -> Result<DynProperty, String> {
let name = self.name.as_str();
let annot = self.annotation.as_str();
let property = match &self.variant {
DynPropertyTypeData::GenericDynProp(p) => {
DynProperty::try_mk_generic(name, &p.formula, annot)?
}
DynPropertyTypeData::ExistsFixedPoint(p) => DynProperty::mk_fixed_point(
name,
p.dataset.as_ref().and_then(|t| DatasetId::new(t).ok()),
p.observation
.as_ref()
.and_then(|t| ObservationId::new(t).ok()),
annot,
),
DynPropertyTypeData::ExistsTrapSpace(p) => DynProperty::mk_trap_space(
name,
p.dataset.as_ref().and_then(|t| DatasetId::new(t).ok()),
p.observation
.as_ref()
.and_then(|t| ObservationId::new(t).ok()),
p.minimal,
p.nonpercolable,
annot,
),
DynPropertyTypeData::ExistsTrajectory(p) => {
let dataset = p.dataset.as_ref().and_then(|t| DatasetId::new(t).ok());
DynProperty::mk_trajectory(name, dataset, annot)
}
DynPropertyTypeData::HasAttractor(p) => DynProperty::mk_has_attractor(
name,
p.dataset.as_ref().and_then(|t| DatasetId::new(t).ok()),
p.observation
.as_ref()
.and_then(|t| ObservationId::new(t).ok()),
annot,
),
DynPropertyTypeData::AttractorCount(p) => {
DynProperty::try_mk_attractor_count(name, p.minimal, p.maximal, annot)?
}
};
Ok(property)
}
fn new_raw(
id: &str,
name: &str,
variant: DynPropertyTypeData,
annotation: &str,
) -> DynPropertyData {
DynPropertyData {
id: id.to_string(),
name: name.to_string(),
annotation: annotation.to_string(),
variant,
}
}
}