use super::OCEL;
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct FlatCase {
pub case_id: String,
pub trace: Vec<String>,
pub event_ids: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct FlatLog {
pub object_type: String,
pub cases: Vec<FlatCase>,
}
pub fn flatten(ocel: &OCEL, object_type: &str) -> Result<FlatLog, String> {
if !ocel.object_types.iter().any(|t| t.name == object_type) {
return Err(format!(
"object type '{object_type}' is not declared in objectTypes"
));
}
let mut target_ids: Vec<&str> = ocel
.objects
.iter()
.filter(|o| o.object_type == object_type)
.map(|o| o.id.as_str())
.collect();
target_ids.sort_unstable();
let mut cases = Vec::with_capacity(target_ids.len());
for oid in target_ids {
let mut rows: Vec<(chrono::DateTime<chrono::FixedOffset>, &str, &str)> = ocel
.events
.iter()
.filter(|e| e.relationships.iter().any(|r| r.object_id == oid))
.map(|e| (e.time, e.id.as_str(), e.event_type.as_str()))
.collect();
rows.sort_by(|a, b| a.0.cmp(&b.0).then_with(|| a.1.cmp(b.1)));
let trace = rows.iter().map(|(_, _, ty)| ty.to_string()).collect();
let event_ids = rows.iter().map(|(_, id, _)| id.to_string()).collect();
cases.push(FlatCase {
case_id: oid.to_string(),
trace,
event_ids,
});
}
Ok(FlatLog {
object_type: object_type.to_string(),
cases,
})
}