2025-07-10 15:02:14 +02:00
|
|
|
//! Definitions for generating graphs from a simulation.
|
|
|
|
|
|
2025-07-07 22:45:02 +02:00
|
|
|
use petgraph::{Graph, Directed};
|
2025-07-05 14:54:43 +02:00
|
|
|
use std::collections::HashMap;
|
2025-07-26 16:46:48 +02:00
|
|
|
use super::structure::{RSlabel, RSsystem, RSset};
|
2025-07-05 14:54:43 +02:00
|
|
|
use super::support_structures::TransitionsIterator;
|
2025-07-13 17:28:13 +02:00
|
|
|
use super::translator::{self, IdType};
|
2025-07-07 01:25:38 +02:00
|
|
|
use std::rc::Rc;
|
2025-07-05 14:54:43 +02:00
|
|
|
|
2025-07-16 00:05:14 +02:00
|
|
|
|
|
|
|
|
pub type RSgraph = Graph<RSsystem, RSlabel, Directed, u32>;
|
2025-07-07 22:45:02 +02:00
|
|
|
|
2025-07-10 15:02:14 +02:00
|
|
|
/// Creates a graph starting from a system as root node
|
2025-07-05 14:54:43 +02:00
|
|
|
pub fn digraph(
|
|
|
|
|
system: RSsystem
|
2025-07-07 22:45:02 +02:00
|
|
|
) -> Result<RSgraph, String> {
|
|
|
|
|
let mut graph = Graph::default();
|
2025-07-05 14:54:43 +02:00
|
|
|
let node = graph.add_node(system.clone());
|
|
|
|
|
|
|
|
|
|
let mut association = HashMap::new();
|
|
|
|
|
association.insert(system.clone(), node);
|
|
|
|
|
|
|
|
|
|
let mut stack = vec![system];
|
|
|
|
|
let mut current;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while !stack.is_empty() {
|
|
|
|
|
// depth first
|
|
|
|
|
current = stack.pop().unwrap();
|
|
|
|
|
let current_node = *association.get(¤t).unwrap();
|
|
|
|
|
|
2025-07-09 19:34:15 +02:00
|
|
|
for (label, next) in TransitionsIterator::from(¤t)? {
|
2025-07-05 14:54:43 +02:00
|
|
|
// if not already visited
|
|
|
|
|
let next_node = association.entry(next.clone()).or_insert_with(|| {
|
|
|
|
|
stack.push(next.clone());
|
|
|
|
|
graph.add_node(next)
|
|
|
|
|
});
|
|
|
|
|
graph.add_edge(current_node, *next_node, label);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Ok(graph)
|
|
|
|
|
}
|
2025-07-07 01:25:38 +02:00
|
|
|
|
2025-07-16 16:20:29 +02:00
|
|
|
|
|
|
|
|
pub fn common_entities(
|
|
|
|
|
graph: &RSgraph
|
|
|
|
|
) -> RSset {
|
|
|
|
|
graph.node_references().fold(
|
|
|
|
|
None,
|
|
|
|
|
|acc, node|
|
|
|
|
|
match acc {
|
|
|
|
|
None => Some(node.1.available_entities.clone()),
|
|
|
|
|
Some(acc) => Some(node.1.available_entities.intersection(&acc))
|
|
|
|
|
}
|
|
|
|
|
).unwrap_or(RSset::new())
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-07 01:25:38 +02:00
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
// helper functions
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Nodes -----------------------------------------------------------------------
|
|
|
|
|
|
2025-07-09 19:34:15 +02:00
|
|
|
/// Helper structure that specifies what information to display for nodes.
|
2025-07-12 15:32:21 +02:00
|
|
|
#[derive(Clone)]
|
2025-07-07 01:25:38 +02:00
|
|
|
pub enum GraphMapNodes {
|
2025-07-26 19:43:20 +02:00
|
|
|
String { string: String },
|
2025-07-07 01:25:38 +02:00
|
|
|
Hide,
|
|
|
|
|
Entities,
|
|
|
|
|
MaskEntities { mask: RSset },
|
2025-07-16 16:20:29 +02:00
|
|
|
ExcludeEntities { mask: RSset },
|
2025-07-07 01:25:38 +02:00
|
|
|
Context,
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-12 15:32:21 +02:00
|
|
|
type GraphMapNodesFnTy =
|
|
|
|
|
dyn Fn(petgraph::prelude::NodeIndex, &RSsystem) -> String;
|
2025-07-09 19:34:15 +02:00
|
|
|
/// Helper structure that holds a formatting function from node as RSsystem to
|
|
|
|
|
/// string
|
2025-07-07 01:25:38 +02:00
|
|
|
pub struct GraphMapNodesTy {
|
2025-07-26 19:43:20 +02:00
|
|
|
functions: Vec<Box<GraphMapNodesFnTy>>,
|
|
|
|
|
translator: Rc<translator::Translator>
|
2025-07-07 01:25:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-07-26 19:43:20 +02:00
|
|
|
impl<const N: usize> From<([GraphMapNodes; N], Rc<translator::Translator>)> for GraphMapNodesTy {
|
|
|
|
|
fn from(value: ([GraphMapNodes; N], Rc<translator::Translator>)) -> Self {
|
|
|
|
|
Self::from((value.0.to_vec(), value.1))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-26 20:16:32 +02:00
|
|
|
impl From<(&[GraphMapNodes], Rc<translator::Translator>)> for GraphMapNodesTy {
|
|
|
|
|
fn from(value: (&[GraphMapNodes], Rc<translator::Translator>)) -> Self {
|
2025-07-26 19:43:20 +02:00
|
|
|
Self::from((value.0.to_vec(), value.1))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<(Vec<GraphMapNodes>, Rc<translator::Translator>)> for GraphMapNodesTy {
|
|
|
|
|
fn from(value: (Vec<GraphMapNodes>, Rc<translator::Translator>)) -> Self {
|
2025-07-07 01:25:38 +02:00
|
|
|
use GraphMapNodes::*;
|
2025-07-26 16:46:48 +02:00
|
|
|
use super::format_helpers::graph_map_nodes_ty_from::*;
|
|
|
|
|
|
2025-07-26 19:43:20 +02:00
|
|
|
let mut new = GraphMapNodesTy {functions: vec![], translator: value.1};
|
|
|
|
|
|
|
|
|
|
for f in value.0 {
|
2025-07-07 01:25:38 +02:00
|
|
|
match f {
|
2025-07-26 19:43:20 +02:00
|
|
|
String { string } => {
|
|
|
|
|
new.functions.push(format_string(string.clone()));
|
|
|
|
|
}
|
2025-07-07 01:25:38 +02:00
|
|
|
Hide => {
|
2025-07-26 19:43:20 +02:00
|
|
|
new.functions.push(format_hide(
|
|
|
|
|
Rc::clone(&new.translator)
|
|
|
|
|
));
|
2025-07-07 01:25:38 +02:00
|
|
|
},
|
|
|
|
|
Entities => {
|
2025-07-26 19:43:20 +02:00
|
|
|
new.functions.push(format_entities(
|
|
|
|
|
Rc::clone(&new.translator)
|
|
|
|
|
));
|
2025-07-07 01:25:38 +02:00
|
|
|
},
|
|
|
|
|
MaskEntities { mask } => {
|
2025-07-26 19:43:20 +02:00
|
|
|
new.functions.push(format_mask_entities(
|
|
|
|
|
Rc::clone(&new.translator),
|
|
|
|
|
mask.clone()
|
|
|
|
|
));
|
2025-07-07 01:25:38 +02:00
|
|
|
},
|
2025-07-16 16:20:29 +02:00
|
|
|
ExcludeEntities { mask } => {
|
2025-07-26 19:43:20 +02:00
|
|
|
new.functions.push(format_exclude_entities(
|
|
|
|
|
Rc::clone(&new.translator),
|
|
|
|
|
mask.clone()
|
|
|
|
|
));
|
2025-07-16 16:20:29 +02:00
|
|
|
}
|
2025-07-07 01:25:38 +02:00
|
|
|
Context => {
|
2025-07-26 19:43:20 +02:00
|
|
|
new.functions.push(format_context(
|
|
|
|
|
Rc::clone(&new.translator)
|
|
|
|
|
));
|
2025-07-07 01:25:38 +02:00
|
|
|
},
|
|
|
|
|
};
|
2025-07-26 19:43:20 +02:00
|
|
|
}
|
2025-07-07 01:25:38 +02:00
|
|
|
|
2025-07-26 19:43:20 +02:00
|
|
|
new
|
2025-07-07 01:25:38 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-26 19:43:20 +02:00
|
|
|
impl GraphMapNodesTy {
|
|
|
|
|
pub fn generate<'a>(
|
2025-07-26 20:01:46 +02:00
|
|
|
self
|
2025-07-26 20:16:32 +02:00
|
|
|
) -> Box<GraphMapNodesFnTy>
|
2025-07-26 19:43:20 +02:00
|
|
|
{
|
2025-07-26 20:16:32 +02:00
|
|
|
let mut accumulator: Box<GraphMapNodesFnTy> =
|
2025-07-26 20:01:46 +02:00
|
|
|
super::format_helpers::graph_map_nodes_ty_from::format_hide(
|
|
|
|
|
Rc::clone(&self.translator)
|
|
|
|
|
);
|
|
|
|
|
for f in self.functions {
|
|
|
|
|
accumulator = Box::new(move |i, n| {
|
|
|
|
|
(accumulator)(i, n)
|
|
|
|
|
+ &f(i, n)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
accumulator
|
2025-07-07 01:25:38 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-26 19:43:20 +02:00
|
|
|
|
2025-07-07 01:25:38 +02:00
|
|
|
// Edges -----------------------------------------------------------------------
|
|
|
|
|
|
2025-07-09 19:34:15 +02:00
|
|
|
/// Helper structure that specifies what information to display for edges
|
2025-07-12 15:32:21 +02:00
|
|
|
#[derive(Clone)]
|
2025-07-07 01:25:38 +02:00
|
|
|
pub enum GraphMapEdges {
|
2025-07-26 20:01:46 +02:00
|
|
|
String { string: String },
|
2025-07-07 01:25:38 +02:00
|
|
|
Hide,
|
|
|
|
|
Products,
|
|
|
|
|
MaskProducts { mask: RSset },
|
|
|
|
|
Entities,
|
|
|
|
|
MaskEntities { mask: RSset },
|
|
|
|
|
Context,
|
|
|
|
|
MaskContext { mask: RSset },
|
|
|
|
|
Union,
|
|
|
|
|
MaskUnion { mask: RSset },
|
|
|
|
|
Difference,
|
|
|
|
|
MaskDifference { mask: RSset },
|
|
|
|
|
EntitiesDeleted,
|
|
|
|
|
MaskEntitiesDeleted { mask: RSset },
|
|
|
|
|
EntitiesAdded,
|
|
|
|
|
MaskEntitiesAdded { mask: RSset },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type GraphMapEdgesFnTy = dyn Fn(petgraph::prelude::EdgeIndex, &RSlabel) -> String;
|
2025-07-09 19:34:15 +02:00
|
|
|
/// Helper structure that holds a formatting function from node as RSsystem to
|
|
|
|
|
/// string
|
2025-07-07 01:25:38 +02:00
|
|
|
pub struct GraphMapEdgesTy {
|
2025-07-26 20:16:32 +02:00
|
|
|
functions: Vec<Box<GraphMapEdgesFnTy>>,
|
2025-07-26 20:01:46 +02:00
|
|
|
translator: Rc<translator::Translator>
|
2025-07-07 01:25:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-07-26 20:16:32 +02:00
|
|
|
impl<const N: usize> From<([GraphMapEdges; N], Rc<translator::Translator>)> for GraphMapEdgesTy {
|
|
|
|
|
fn from(value: ([GraphMapEdges; N], Rc<translator::Translator>)) -> Self {
|
|
|
|
|
Self::from((value.0.to_vec(), value.1))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<(&[GraphMapEdges], Rc<translator::Translator>)> for GraphMapEdgesTy {
|
|
|
|
|
fn from(value: (&[GraphMapEdges], Rc<translator::Translator>)) -> Self {
|
|
|
|
|
Self::from((value.0.to_vec(), value.1))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<(Vec<GraphMapEdges>, Rc<translator::Translator>)> for GraphMapEdgesTy {
|
|
|
|
|
fn from(value: (Vec<GraphMapEdges>, Rc<translator::Translator>)) -> Self {
|
2025-07-07 01:25:38 +02:00
|
|
|
use GraphMapEdges::*;
|
2025-07-26 16:46:48 +02:00
|
|
|
use super::format_helpers::graph_map_edges_ty_from::*;
|
|
|
|
|
|
2025-07-26 20:16:32 +02:00
|
|
|
let mut new = GraphMapEdgesTy {functions: vec![], translator: value.1};
|
|
|
|
|
|
|
|
|
|
for f in value.0 {
|
2025-07-07 01:25:38 +02:00
|
|
|
match f {
|
2025-07-26 20:01:46 +02:00
|
|
|
String { string } => {
|
2025-07-26 20:16:32 +02:00
|
|
|
new.functions.push(format_string(
|
|
|
|
|
Rc::clone(&new.translator), string))
|
2025-07-26 20:01:46 +02:00
|
|
|
}
|
2025-07-07 01:25:38 +02:00
|
|
|
Hide => {
|
2025-07-26 20:16:32 +02:00
|
|
|
new.functions.push(format_hide(
|
|
|
|
|
Rc::clone(&new.translator)
|
|
|
|
|
))
|
2025-07-07 01:25:38 +02:00
|
|
|
},
|
|
|
|
|
Products => {
|
2025-07-26 20:16:32 +02:00
|
|
|
new.functions.push(format_products(
|
|
|
|
|
Rc::clone(&new.translator)
|
|
|
|
|
))
|
2025-07-07 01:25:38 +02:00
|
|
|
},
|
|
|
|
|
MaskProducts { mask } => {
|
2025-07-26 20:16:32 +02:00
|
|
|
new.functions.push(format_mask_products(
|
|
|
|
|
Rc::clone(&new.translator), mask))
|
2025-07-07 01:25:38 +02:00
|
|
|
},
|
|
|
|
|
Entities => {
|
2025-07-26 20:16:32 +02:00
|
|
|
new.functions.push(format_entities(
|
|
|
|
|
Rc::clone(&new.translator)
|
|
|
|
|
))
|
2025-07-07 01:25:38 +02:00
|
|
|
},
|
|
|
|
|
MaskEntities { mask } => {
|
2025-07-26 20:16:32 +02:00
|
|
|
new.functions.push(format_mask_entities(
|
|
|
|
|
Rc::clone(&new.translator), mask))
|
2025-07-07 01:25:38 +02:00
|
|
|
},
|
|
|
|
|
Context => {
|
2025-07-26 20:16:32 +02:00
|
|
|
new.functions.push(format_context(
|
|
|
|
|
Rc::clone(&new.translator)
|
|
|
|
|
))
|
2025-07-07 01:25:38 +02:00
|
|
|
},
|
|
|
|
|
MaskContext { mask } => {
|
2025-07-26 20:16:32 +02:00
|
|
|
new.functions.push(format_mask_context(
|
|
|
|
|
Rc::clone(&new.translator), mask))
|
2025-07-07 01:25:38 +02:00
|
|
|
},
|
|
|
|
|
Union => {
|
2025-07-26 20:16:32 +02:00
|
|
|
new.functions.push(format_union(
|
|
|
|
|
Rc::clone(&new.translator)
|
|
|
|
|
))
|
2025-07-07 01:25:38 +02:00
|
|
|
},
|
|
|
|
|
MaskUnion { mask } => {
|
2025-07-26 20:16:32 +02:00
|
|
|
new.functions.push(format_mask_union(
|
|
|
|
|
Rc::clone(&new.translator), mask))
|
2025-07-07 01:25:38 +02:00
|
|
|
},
|
|
|
|
|
Difference => {
|
2025-07-26 20:16:32 +02:00
|
|
|
new.functions.push(format_difference(
|
|
|
|
|
Rc::clone(&new.translator)
|
|
|
|
|
))
|
2025-07-07 01:25:38 +02:00
|
|
|
},
|
|
|
|
|
MaskDifference { mask } => {
|
2025-07-26 20:16:32 +02:00
|
|
|
new.functions.push(format_mask_difference(
|
|
|
|
|
Rc::clone(&new.translator), mask))
|
2025-07-07 01:25:38 +02:00
|
|
|
},
|
|
|
|
|
EntitiesDeleted => {
|
2025-07-26 20:16:32 +02:00
|
|
|
new.functions.push(format_entities_deleted(
|
|
|
|
|
Rc::clone(&new.translator)
|
|
|
|
|
))
|
2025-07-07 01:25:38 +02:00
|
|
|
},
|
|
|
|
|
MaskEntitiesDeleted { mask } => {
|
2025-07-26 20:16:32 +02:00
|
|
|
new.functions.push(format_mask_entities_deleted(
|
|
|
|
|
Rc::clone(&new.translator), mask))
|
2025-07-07 01:25:38 +02:00
|
|
|
},
|
|
|
|
|
EntitiesAdded => {
|
2025-07-26 20:16:32 +02:00
|
|
|
new.functions.push(format_entities_added(
|
|
|
|
|
Rc::clone(&new.translator)
|
|
|
|
|
))
|
2025-07-07 01:25:38 +02:00
|
|
|
},
|
|
|
|
|
MaskEntitiesAdded { mask } => {
|
2025-07-26 20:16:32 +02:00
|
|
|
new.functions.push(format_mask_entities_added(
|
|
|
|
|
Rc::clone(&new.translator), mask))
|
2025-07-07 01:25:38 +02:00
|
|
|
},
|
|
|
|
|
};
|
2025-07-26 20:16:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
new
|
2025-07-07 01:25:38 +02:00
|
|
|
}
|
2025-07-26 20:16:32 +02:00
|
|
|
}
|
2025-07-07 01:25:38 +02:00
|
|
|
|
2025-07-26 20:16:32 +02:00
|
|
|
impl GraphMapEdgesTy {
|
|
|
|
|
pub fn generate(
|
|
|
|
|
self
|
|
|
|
|
) -> Box<GraphMapEdgesFnTy> {
|
|
|
|
|
let mut accumulator: Box<GraphMapEdgesFnTy> =
|
|
|
|
|
super::format_helpers::graph_map_edges_ty_from::format_hide(
|
|
|
|
|
Rc::clone(&self.translator)
|
|
|
|
|
);
|
|
|
|
|
for f in self.functions {
|
|
|
|
|
accumulator = Box::new(move |i, n| {
|
|
|
|
|
(accumulator)(i, n)
|
|
|
|
|
+ &f(i, n)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
accumulator
|
2025-07-07 01:25:38 +02:00
|
|
|
}
|
|
|
|
|
}
|
2025-07-07 22:45:02 +02:00
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
2025-07-26 20:01:46 +02:00
|
|
|
// Color Nodes & Edges
|
2025-07-07 22:45:02 +02:00
|
|
|
// -----------------------------------------------------------------------------
|
2025-07-26 16:46:48 +02:00
|
|
|
use petgraph::visit::{IntoEdgeReferences, IntoNodeReferences};
|
2025-07-07 22:45:02 +02:00
|
|
|
|
|
|
|
|
type RSdotGraph = Graph<String, String, Directed, u32>;
|
|
|
|
|
type RSformatNodeTy =
|
2025-07-13 17:28:13 +02:00
|
|
|
dyn Fn(
|
|
|
|
|
&RSdotGraph,
|
|
|
|
|
<&RSdotGraph as IntoNodeReferences>::NodeRef
|
|
|
|
|
) -> Option<String>;
|
2025-07-07 22:45:02 +02:00
|
|
|
|
2025-07-13 17:28:13 +02:00
|
|
|
#[derive(Clone, Copy)]
|
|
|
|
|
pub enum OperationType {
|
|
|
|
|
Equals,
|
|
|
|
|
Subset,
|
|
|
|
|
SubsetEqual,
|
|
|
|
|
Superset,
|
|
|
|
|
SupersetEqual
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl OperationType {
|
|
|
|
|
pub fn evaluate(&self, a: &RSset, b: &RSset) -> bool {
|
|
|
|
|
match self {
|
|
|
|
|
Self::Equals => {
|
|
|
|
|
a.is_subset(b) && b.is_subset(a)
|
|
|
|
|
},
|
|
|
|
|
Self::Subset => {
|
|
|
|
|
a.is_subset(b) && !b.is_subset(a)
|
|
|
|
|
},
|
|
|
|
|
Self::SubsetEqual => {
|
|
|
|
|
a.is_subset(b)
|
|
|
|
|
},
|
|
|
|
|
Self::Superset => {
|
|
|
|
|
b.is_subset(a) && !a.is_subset(b)
|
|
|
|
|
},
|
|
|
|
|
Self::SupersetEqual => {
|
|
|
|
|
b.is_subset(a)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub enum ContextColorConditional {
|
|
|
|
|
Nill,
|
|
|
|
|
RecursiveIdentifier(IdType),
|
|
|
|
|
EntitySet(OperationType, RSset),
|
|
|
|
|
NonDeterministicChoice,
|
|
|
|
|
Summation,
|
|
|
|
|
WaitEntity
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub enum NodeColorConditional {
|
|
|
|
|
ContextConditional(ContextColorConditional),
|
|
|
|
|
EntitiesConditional(OperationType, RSset)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct NodeColor {
|
|
|
|
|
pub conditionals: Vec<(NodeColorConditional, String)>,
|
|
|
|
|
pub base_color: String
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-13 18:14:35 +02:00
|
|
|
pub fn node_formatter_base_color(
|
|
|
|
|
base_color: String
|
|
|
|
|
) -> String
|
|
|
|
|
{
|
|
|
|
|
", fillcolor=".to_string() + &base_color
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-26 16:46:48 +02:00
|
|
|
|
2025-07-13 17:28:13 +02:00
|
|
|
pub fn node_formatter(
|
|
|
|
|
original_graph: Rc<RSgraph>,
|
|
|
|
|
rule: NodeColorConditional,
|
|
|
|
|
color: String,
|
|
|
|
|
star: Option<IdType>,
|
2025-07-07 22:45:02 +02:00
|
|
|
) -> Box<RSformatNodeTy>
|
|
|
|
|
{
|
2025-07-26 16:46:48 +02:00
|
|
|
use super::format_helpers::node_formatter::*;
|
2025-07-13 17:28:13 +02:00
|
|
|
match rule {
|
|
|
|
|
NodeColorConditional::ContextConditional(ccc) => {
|
|
|
|
|
match ccc {
|
|
|
|
|
ContextColorConditional::Nill => {
|
2025-07-26 16:46:48 +02:00
|
|
|
format_nill(original_graph, color, star)
|
2025-07-13 17:28:13 +02:00
|
|
|
},
|
|
|
|
|
ContextColorConditional::RecursiveIdentifier(s) => {
|
2025-07-26 16:46:48 +02:00
|
|
|
format_recursive_identifier(original_graph, color, star, s)
|
2025-07-13 17:28:13 +02:00
|
|
|
},
|
|
|
|
|
ContextColorConditional::EntitySet(ot, set) => {
|
2025-07-26 16:46:48 +02:00
|
|
|
format_entity_set(original_graph, color, star, ot, set)
|
2025-07-13 17:28:13 +02:00
|
|
|
},
|
|
|
|
|
ContextColorConditional::NonDeterministicChoice => {
|
2025-07-26 16:46:48 +02:00
|
|
|
format_non_deterministic_choice(original_graph, color, star)
|
2025-07-13 17:28:13 +02:00
|
|
|
},
|
|
|
|
|
ContextColorConditional::Summation => {
|
2025-07-26 16:46:48 +02:00
|
|
|
format_summation(original_graph, color, star)
|
2025-07-13 17:28:13 +02:00
|
|
|
},
|
|
|
|
|
ContextColorConditional::WaitEntity => {
|
2025-07-26 16:46:48 +02:00
|
|
|
format_wait_entity(original_graph, color, star)
|
2025-07-13 17:28:13 +02:00
|
|
|
},
|
2025-07-07 22:45:02 +02:00
|
|
|
}
|
2025-07-13 17:28:13 +02:00
|
|
|
},
|
|
|
|
|
NodeColorConditional::EntitiesConditional(ot, set) => {
|
2025-07-26 16:46:48 +02:00
|
|
|
format_entities_conditional(original_graph, color, star, ot, set)
|
2025-07-13 17:28:13 +02:00
|
|
|
},
|
|
|
|
|
}
|
2025-07-07 22:45:02 +02:00
|
|
|
}
|
|
|
|
|
|
2025-07-13 19:08:39 +02:00
|
|
|
type RSformatEdgeTy =
|
|
|
|
|
dyn Fn(
|
|
|
|
|
&RSdotGraph,
|
|
|
|
|
<&RSdotGraph as IntoEdgeReferences>::EdgeRef
|
|
|
|
|
) -> Option<String>;
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub enum EdgeColorConditional {
|
|
|
|
|
Entities(OperationType, RSset),
|
|
|
|
|
Context(OperationType, RSset),
|
|
|
|
|
T(OperationType, RSset),
|
|
|
|
|
Reactants(OperationType, RSset),
|
|
|
|
|
ReactantsAbsent(OperationType, RSset),
|
|
|
|
|
Inhibitors(OperationType, RSset),
|
|
|
|
|
InhibitorsPresent(OperationType, RSset),
|
|
|
|
|
Products(OperationType, RSset),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct EdgeColor {
|
|
|
|
|
pub conditionals: Vec<(EdgeColorConditional, String)>,
|
|
|
|
|
pub base_color: String
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn edge_formatter_base_color(
|
|
|
|
|
base_color: String
|
|
|
|
|
) -> String
|
|
|
|
|
{
|
2025-07-13 19:32:11 +02:00
|
|
|
", color=".to_string() + &base_color
|
2025-07-13 19:08:39 +02:00
|
|
|
}
|
|
|
|
|
|
2025-07-26 16:46:48 +02:00
|
|
|
|
2025-07-13 17:28:13 +02:00
|
|
|
pub fn edge_formatter(
|
2025-07-13 19:08:39 +02:00
|
|
|
original_graph: Rc<RSgraph>,
|
|
|
|
|
rule: EdgeColorConditional,
|
|
|
|
|
color: String,
|
2025-07-07 22:45:02 +02:00
|
|
|
) -> Box<RSformatEdgeTy>
|
|
|
|
|
{
|
2025-07-26 16:46:48 +02:00
|
|
|
use super::format_helpers::edge_formatter::*;
|
2025-07-13 19:08:39 +02:00
|
|
|
match rule {
|
|
|
|
|
EdgeColorConditional::Entities(ot, set) => {
|
2025-07-26 16:46:48 +02:00
|
|
|
format_entities(original_graph, color, ot, set)
|
2025-07-13 19:08:39 +02:00
|
|
|
},
|
|
|
|
|
EdgeColorConditional::Context(ot, set) => {
|
2025-07-26 16:46:48 +02:00
|
|
|
format_context(original_graph, color, ot, set)
|
2025-07-13 19:08:39 +02:00
|
|
|
},
|
|
|
|
|
EdgeColorConditional::T(ot, set) => {
|
2025-07-26 16:46:48 +02:00
|
|
|
format_t(original_graph, color, ot, set)
|
2025-07-13 19:08:39 +02:00
|
|
|
},
|
|
|
|
|
EdgeColorConditional::Reactants(ot, set) => {
|
2025-07-26 16:46:48 +02:00
|
|
|
format_reactants(original_graph, color, ot, set)
|
2025-07-13 19:08:39 +02:00
|
|
|
},
|
|
|
|
|
EdgeColorConditional::ReactantsAbsent(ot, set) => {
|
2025-07-26 16:46:48 +02:00
|
|
|
format_reactants_absent(original_graph, color, ot, set)
|
2025-07-13 19:08:39 +02:00
|
|
|
},
|
|
|
|
|
EdgeColorConditional::Inhibitors(ot, set) => {
|
2025-07-26 16:46:48 +02:00
|
|
|
format_inhibitors(original_graph, color, ot, set)
|
2025-07-13 19:08:39 +02:00
|
|
|
},
|
|
|
|
|
EdgeColorConditional::InhibitorsPresent(ot, set) => {
|
2025-07-26 16:46:48 +02:00
|
|
|
format_inhibitors_present(original_graph, color, ot, set)
|
2025-07-13 19:08:39 +02:00
|
|
|
},
|
|
|
|
|
EdgeColorConditional::Products(ot, set) => {
|
2025-07-26 16:46:48 +02:00
|
|
|
format_products(original_graph, color, ot, set)
|
2025-07-13 19:08:39 +02:00
|
|
|
},
|
|
|
|
|
}
|
2025-07-07 22:45:02 +02:00
|
|
|
}
|