From ab621f0217cc2ed5790b8fe182b6552c5a9ac7f8 Mon Sep 17 00:00:00 2001 From: Colton Pierson Date: Fri, 8 Nov 2024 12:45:03 -0800 Subject: [PATCH] grouping visualization working as expected --- .../execution/execution/execution_graph.rs | 3 +- .../execution/execution/execution_state.rs | 3 +- .../src/sdk/chidori_runtime_instance.rs | 7 +- toolchain/chidori-debugger/src/graph.rs | 10 +-- .../src/graph_range_collector.rs | 64 +++++++++++++++++-- 5 files changed, 66 insertions(+), 21 deletions(-) diff --git a/toolchain/chidori-core/src/execution/execution/execution_graph.rs b/toolchain/chidori-core/src/execution/execution/execution_graph.rs index 8becfff..fb2173e 100644 --- a/toolchain/chidori-core/src/execution/execution/execution_graph.rs +++ b/toolchain/chidori-core/src/execution/execution/execution_graph.rs @@ -201,8 +201,7 @@ impl ExecutionGraph { } pub fn get_state_at_id(&self, id: ExecutionNodeId) -> Option { - let state_id_to_state = self.execution_node_id_to_state.clone(); - state_id_to_state.get(&id).map(|x| x.clone()) + self.execution_node_id_to_state.get(&id).map(|x| x.clone()) } /// Performs a depth first traversal of the execution graph to resolve the combined diff --git a/toolchain/chidori-core/src/execution/execution/execution_state.rs b/toolchain/chidori-core/src/execution/execution/execution_state.rs index 66cbc6a..090815a 100644 --- a/toolchain/chidori-core/src/execution/execution/execution_state.rs +++ b/toolchain/chidori-core/src/execution/execution/execution_state.rs @@ -469,11 +469,10 @@ impl ExecutionState { operation_node.name.as_ref() .and_then(|name| s.operation_name_to_id.get(name).copied()) .unwrap_or_else(|| { - let new_id = Uuid::now_v7(); if let Some(name) = &operation_node.name { s.operation_name_to_id.insert(name.clone(), op_id); } - new_id + op_id }); operation_node.id = op_id; s.cells_by_id.insert(op_id, operation_node.cell.clone()); diff --git a/toolchain/chidori-core/src/sdk/chidori_runtime_instance.rs b/toolchain/chidori-core/src/sdk/chidori_runtime_instance.rs index 9991d82..36f24d7 100644 --- a/toolchain/chidori-core/src/sdk/chidori_runtime_instance.rs +++ b/toolchain/chidori-core/src/sdk/chidori_runtime_instance.rs @@ -203,11 +203,6 @@ impl ChidoriRuntimeInstance { UserInteractionMessage::ReloadCells => { self.reload_cells().await?; }, - UserInteractionMessage::FetchStateAt(id) => { - let state = self.db.get_state_at_id(id).unwrap(); - let sender = self.runtime_event_sender.as_mut().unwrap(); - sender.send(EventsFromRuntime::StateAtId(id, state)).unwrap(); - }, UserInteractionMessage::RevertToState(id) => { if let Some(id) = id { self.execution_head_state_id = id; @@ -276,6 +271,7 @@ impl ChidoriRuntimeInstance { Ok(state) } + #[cfg(test)] pub fn get_state_at_current_execution_head(&self) -> ExecutionState { self.db.get_state_at_id(self.execution_head_state_id).unwrap() } @@ -348,7 +344,6 @@ pub enum UserInteractionMessage { SetPlaybackState(PlaybackState), RevertToState(Option), ReloadCells, - FetchStateAt(ExecutionNodeId), MutateCell(CellHolder), Shutdown, PushChatMessage(String), diff --git a/toolchain/chidori-debugger/src/graph.rs b/toolchain/chidori-debugger/src/graph.rs index 7c7a189..f74843a 100644 --- a/toolchain/chidori-debugger/src/graph.rs +++ b/toolchain/chidori-debugger/src/graph.rs @@ -728,7 +728,7 @@ fn save_image_to_png(image: &Image) { } fn generate_noodle_path(elements: &[ElementDimensions], noodle_width: f32, nesting_depth: usize) -> (Path, Vec) { - let left_offset = nesting_depth as f32 * -30.0 - 30.0; + let left_offset = nesting_depth as f32 * noodle_width * -6.0 - 30.0; let mut path_builder = PathBuilder::new(); let mut all_points = Vec::new(); @@ -984,7 +984,7 @@ fn generate_contour_path_for_range(range: &StateRange) -> (Path, Vec = range_id_to_entity_id.keys().cloned().collect(); @@ -1439,7 +1440,7 @@ fn egui_graph_node( ui.label("Eval Failure"); } EnclosedState::Open => { - ui.set_min_width(1000.0); + ui.set_min_width(800.0); ui.label("Executing"); egui_execution_state( ui, @@ -1451,6 +1452,7 @@ fn egui_graph_node( for (_, value) in state.state.iter() { let image_paths = crate::util::find_matching_strings(&value.output.clone().unwrap(), r"(?i)\.(png|jpe?g)$"); for (img_path, _) in image_paths { + // TODO: cache this based on node and the path let texture = if let Some(cached_texture) = node_image_texture_cache.get(&img_path) { cached_texture.clone() } else { @@ -1555,7 +1557,7 @@ fn generate_tree_layout( let mut topo = petgraph::visit::Topo::new(&execution_graph); while let Some(x) = topo.next(&execution_graph) { if let Some(node) = &execution_graph.node_weight(x) { - let dims = node_dimensions.entry(**node).or_insert((1000.0, 300.0)); + let dims = node_dimensions.entry(**node).or_insert((800.0, 300.0)); let mut width = dims.0; let mut height = dims.1; let tree_node = crate::tidy_tree::Node::new(x.index(), (width) as f64, (height) as f64, Some(Orientation::Vertical)); diff --git a/toolchain/chidori-debugger/src/graph_range_collector.rs b/toolchain/chidori-debugger/src/graph_range_collector.rs index 3f8afc2..c97faec 100644 --- a/toolchain/chidori-debugger/src/graph_range_collector.rs +++ b/toolchain/chidori-debugger/src/graph_range_collector.rs @@ -1,3 +1,4 @@ +use std::cmp::Ordering; use petgraph::prelude::{Dfs, StableGraph}; use chidori_core::execution::execution::execution_graph::ChronologyId; use petgraph::graph::NodeIndex; @@ -14,6 +15,7 @@ pub struct StateRange { path: Vec, // Maximum depth of nested paths contained within this path pub(crate) nesting_depth: usize, + pub is_explicit_close: bool, } impl StateRange { @@ -60,7 +62,7 @@ impl RangeCollector { if let Some(state) = chidori_state.get_execution_state_at_id(node_weight) { if matches!(state.evaluating_enclosed_state, EnclosedState::Close(_)) { if state.resolving_execution_node_state_id == chronology_id { - potential_endpoints.push(node); + potential_endpoints.push((node, true)); } } } @@ -68,12 +70,15 @@ impl RangeCollector { // If no outgoing edges, consider it an endpoint if graph.neighbors_directed(node, Outgoing).count() == 0 { - potential_endpoints.push(node); + potential_endpoints.push((node, false)); } } + // Sort by node index + potential_endpoints.sort_by(|a, b| { + a.0.cmp(&b.0) + }); // Remove duplicates from potential_endpoints - potential_endpoints.sort(); potential_endpoints.dedup(); for end_idx in potential_endpoints { @@ -83,16 +88,14 @@ impl RangeCollector { self.collect_path_recursive( graph, start_idx, - end_idx, + end_idx.0, + end_idx.1, &mut visited, &mut current_path, dimensions_map, &chronology_id, ); } - - // After collecting all paths, calculate nesting depths - // self.calculate_nesting_depths(); } fn collect_path_recursive( @@ -100,6 +103,7 @@ impl RangeCollector { graph: &StableGraph, current: NodeIndex, target: NodeIndex, + is_explicit_close: bool, visited: &mut HashSet, current_path: &mut Vec, dimensions_map: &HashMap, @@ -123,6 +127,7 @@ impl RangeCollector { let range = StateRange { start_chronology_id: *chronology_id, end_chronology_id: *target_chronology_id, + is_explicit_close, elements, path: current_path.clone(), nesting_depth: 0, // Will be calculated later @@ -136,6 +141,7 @@ impl RangeCollector { graph, neighbor, target, + is_explicit_close, visited, current_path, dimensions_map, @@ -149,14 +155,58 @@ impl RangeCollector { visited.remove(¤t); } + + pub(crate) fn remove_implicitly_ended_ranges(&mut self) { + // Group ranges by start chronology IDs + let mut range_groups: HashMap> = HashMap::new(); + + // First, group all ranges by their start and end IDs + for range in self.ranges.drain(..) { + let key = range.start_chronology_id; + range_groups.entry(key).or_default().push(range); + } + + // Process each group + for ranges in range_groups.values() { + // Check if there's an explicitly closed range in the group + let explicit_ranges: Vec<_> = ranges.iter() + .filter(|r| r.is_explicit_close) + .collect(); + + if !explicit_ranges.is_empty() { + // If there are explicit ranges, only keep the first explicit one + self.ranges.push(explicit_ranges[0].clone()); + } else { + // If no explicit ranges, keep all ranges in the group + self.ranges.extend(ranges.iter().cloned()); + } + } + + // Sort ranges by start_chronology_id for consistent ordering + self.ranges.sort_by_key(|r| r.start_chronology_id); + } + pub(crate) fn calculate_nesting_depths(&mut self) { // For each path, count how many other paths are fully contained within it + self.ranges.sort_by(|a, b| { + if a.elements.len() > b.elements.len() { + Ordering::Greater + } else if a.elements.len() < b.elements.len() { + Ordering::Less + } else { + Ordering::Equal + } + }); for i in 0..self.ranges.len() { let mut max_contained_depth = 0; let parent_path = &self.ranges[i].path; + // compare path with all other paths for j in 0..self.ranges.len() { + + // skip the same path if i != j { + let child_path = &self.ranges[j].path; // Check if child_path is completely contained within parent_path