From b1374229f3eebc506f79212cb433100d6e8a13b1 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Mon, 29 Apr 2024 22:24:01 -0400 Subject: [PATCH] Calculate out the depth and width of each node --- otg/core/src/library.rs | 8 +- otg/core/src/types.rs | 210 +++++++++++++++++++++++++++++++++------- 2 files changed, 179 insertions(+), 39 deletions(-) diff --git a/otg/core/src/library.rs b/otg/core/src/library.rs index 135bb47..4fe5241 100644 --- a/otg/core/src/library.rs +++ b/otg/core/src/library.rs @@ -14,18 +14,18 @@ General Public License for more details. You should have received a copy of the GNU General Public License along with On the Grid. If not, see . */ -use crate::{Core}; +use crate::Core; use serde::{Deserialize, Serialize}; use sgf::GameRecord; #[derive(Clone, Debug, Serialize, Deserialize)] pub enum LibraryRequest { - ListGames + ListGames, } #[derive(Clone, Debug)] pub enum LibraryResponse { - Games(Vec) + Games(Vec), } async fn handle_list_games(model: &Core) -> LibraryResponse { @@ -39,10 +39,8 @@ async fn handle_list_games(model: &Core) -> LibraryResponse { } } - pub async fn handle(model: &Core, request: LibraryRequest) -> LibraryResponse { match request { LibraryRequest::ListGames => handle_list_games(model).await, } } - diff --git a/otg/core/src/types.rs b/otg/core/src/types.rs index 12153eb..fb1c364 100644 --- a/otg/core/src/types.rs +++ b/otg/core/src/types.rs @@ -3,7 +3,9 @@ use config::define_config; use config_derive::ConfigOption; use serde::{Deserialize, Serialize}; use sgf::GameTree; -use std::{cell::RefCell, collections::VecDeque, fmt, path::PathBuf, time::Duration}; +use std::{ + cell::RefCell, collections::{HashMap, VecDeque}, fmt, ops::Deref, path::PathBuf, time::Duration +}; use thiserror::Error; define_config! { @@ -242,19 +244,39 @@ pub struct Tree { struct DepthTree(slab_tree::Tree); +impl Deref for DepthTree { + type Target = slab_tree::Tree; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + #[derive(Debug)] pub struct SizeNode { - pub id: usize, node_id: slab_tree::NodeId, - parent: Option, + parent: Option, depth: usize, - width: RefCell>, - children: Vec, + width: usize, +} + +impl SizeNode { + pub fn position(&self) -> (usize, usize) { + (self.depth, self.width) + } } impl DepthTree { - /* - fn new(root: T) -> Self { + // My previous work to convert from a node tree to this tree-with-width dependend on the node tree + // being a recursive data structure. Now I need to find a way to convert a slab tree to this width + // tree. + // + // It all feels like a lot of custom weirdness. I shouldn't need a bunch of custom data structures, + // so I want to eliminate the "Tree" above and keep using the slab tree. I think I should be able + // to build these Node objects without needing a custom data structure. + fn new() -> Self { + Self(slab_tree::Tree::new()) + /* Tree { nodes: vec![Node { id: 0, @@ -265,8 +287,10 @@ impl DepthTree { children: vec![], }], } + */ } + /* pub fn node(&self, idx: usize) -> &T { &self.nodes[idx].node } @@ -293,13 +317,18 @@ impl DepthTree { */ pub fn max_depth(&self) -> usize { - unimplemented!() - /* - self.nodes.iter().fold( - 0, - |max, node| if node.depth > max { node.depth } else { max }, - ) - */ + self.0 + .root() + .unwrap() + .traverse_pre_order() + .fold(0, |max, node| { + println!("node depth: {}", node.data().depth); + if node.data().depth > max { + node.data().depth + } else { + max + } + }) } // Since I know the width of a node, now I want to figure out its placement in the larger @@ -317,8 +346,8 @@ impl DepthTree { // amounts to the position of the parent node. // // When drawing nodes, I don't know how to persist the level of indent. - pub fn position(&self, idx: usize) -> (usize, usize) { - unimplemented!() + + // unimplemented!() /* let node = &self.nodes[idx]; match node.parent { @@ -337,7 +366,6 @@ impl DepthTree { None => (0, 0), } */ - } /* // Given a node, do a postorder traversal to figure out the width of the node based on all of @@ -375,8 +403,88 @@ impl DepthTree { } impl<'a> From<&'a GameTree> for DepthTree { - fn from(root: &'a GameTree) -> Self { - unimplemented!() + fn from(tree: &'a GameTree) -> Self { + // Like in the conversion from SGF to GameTree, I need to traverse the entire tree one node + // at a time, keeping track of node ids as we go. I'm going to go with a depth-first + // traversal. When generating each node, I think I want to generate all of the details of + // the node as we go. + let source_root_node = tree.root(); + match source_root_node { + Some(source_root_node) => { + // Do the real work + // The id_map indexes from the source tree to the destination tree. Reverse + // indexing is accomplished by looking at the node_id in a node in the destination + // tree. + let mut id_map: HashMap = HashMap::new(); + let mut tree = slab_tree::Tree::new(); + + let mut iter = source_root_node.traverse_pre_order(); + let _ = iter.next().unwrap(); // we already know that the first element to be + // returned is the root node, and that the root node + // already exists. Otherwise we wouldn't even be in + // this branch. + + let dest_root_id = tree.set_root(SizeNode { + node_id: source_root_node.node_id(), + parent: None, + depth: 0, + width: 0, + }); + + id_map.insert(source_root_node.node_id(), dest_root_id); + + for source_node in iter { + let dest_parent_id = id_map + .get(&source_node.parent().unwrap().node_id()) + .unwrap(); + + let mut dest_parent = tree.get_mut(*dest_parent_id).unwrap(); + + let new_depth_node = SizeNode { + node_id: source_node.node_id(), + parent: Some(*dest_parent_id), + depth: 1 + dest_parent.data().depth, + width: dest_parent.data().width, + }; + + let new_node_id = dest_parent.append(new_depth_node).node_id(); + + match tree + .get(new_node_id) + .unwrap() + .prev_sibling() + .map(|node| node.data().width) + { + None => {} + Some(previous_width) => { + let mut new_node = tree.get_mut(new_node_id).unwrap(); + new_node.data().width = previous_width + 1; + } + } + + /* + let new_node = tree.get_mut(*dest_parent_id).unwrap().append(new_depth_node); + let previous_node = new_node.prev_sibling(); + + match previous_node { + None => {} + } + */ + + /* + match dest_noderef.prev_sibling() { + None => {} + Some(mut node) => { dest_noderef.data().width = node.data().width + 1 } + } + */ + + id_map.insert(source_node.node_id(), new_node_id); + } + + Self(tree) + } + None => Self::new(), + } } } @@ -510,7 +618,8 @@ mod test { .append(GameNode::MoveNode(MoveNode::new( sgf::Color::Black, Move::Move("dp".to_owned()), - ))).node_id(); + ))) + .node_id(); let node_c = game_tree .get_mut(node_b) @@ -518,7 +627,8 @@ mod test { .append(GameNode::MoveNode(MoveNode::new( sgf::Color::Black, Move::Move("dp".to_owned()), - ))).node_id(); + ))) + .node_id(); let node_d = game_tree .get_mut(node_c) @@ -526,7 +636,8 @@ mod test { .append(GameNode::MoveNode(MoveNode::new( sgf::Color::Black, Move::Move("dp".to_owned()), - ))).node_id(); + ))) + .node_id(); let node_e = game_tree .get_mut(node_c) @@ -534,7 +645,8 @@ mod test { .append(GameNode::MoveNode(MoveNode::new( sgf::Color::Black, Move::Move("dp".to_owned()), - ))).node_id(); + ))) + .node_id(); let node_f = game_tree .get_mut(node_c) @@ -542,7 +654,8 @@ mod test { .append(GameNode::MoveNode(MoveNode::new( sgf::Color::Black, Move::Move("dp".to_owned()), - ))).node_id(); + ))) + .node_id(); let node_g = game_tree .get_mut(node_a) @@ -550,7 +663,8 @@ mod test { .append(GameNode::MoveNode(MoveNode::new( sgf::Color::Black, Move::Move("dp".to_owned()), - ))).node_id(); + ))) + .node_id(); let node_h = game_tree .get_mut(node_a) @@ -558,7 +672,8 @@ mod test { .append(GameNode::MoveNode(MoveNode::new( sgf::Color::Black, Move::Move("dp".to_owned()), - ))).node_id(); + ))) + .node_id(); let _ = game_tree .get_mut(node_h) @@ -566,7 +681,8 @@ mod test { .append(GameNode::MoveNode(MoveNode::new( sgf::Color::Black, Move::Move("dp".to_owned()), - ))); + ))) + .node_id(); game_tree } @@ -575,6 +691,10 @@ mod test { fn it_can_calculate_depth_from_game_tree() { let game_tree = branching_tree(); let tree = DepthTree::from(&game_tree); + assert_eq!( + game_tree.root().unwrap().traverse_pre_order().count(), + tree.0.root().unwrap().traverse_pre_order().count() + ); assert_eq!(tree.max_depth(), 3); } @@ -582,13 +702,35 @@ mod test { fn it_calculates_horizontal_position_of_nodes() { let game_tree = branching_tree(); let tree = DepthTree::from(&game_tree); - assert_eq!(tree.position(2), (2, 0)); - assert_eq!(tree.position(1), (1, 0)); - assert_eq!(tree.position(0), (0, 0)); - assert_eq!(tree.position(4), (3, 1)); - assert_eq!(tree.position(5), (3, 2)); - assert_eq!(tree.position(6), (1, 3)); - assert_eq!(tree.position(7), (1, 4)); + + let node_a = tree.root().unwrap(); + assert_eq!(node_a.data().position(), (0, 0)); + + let node_b = node_a.first_child().unwrap(); + assert_eq!(node_b.data().position(), (1, 0)); + let node_g = node_b.next_sibling().unwrap(); + assert_eq!(node_g.data().position(), (1, 1)); + let node_h = node_g.next_sibling().unwrap(); + assert_eq!(node_h.data().position(), (1, 2)); + + let node_c = node_b.first_child().unwrap(); + assert_eq!(node_c.data().position(), (2, 0)); + + let node_d = node_c.first_child().unwrap(); + assert_eq!(node_d.data().position(), (3, 0)); + + let node_i = node_h.first_child().unwrap(); + assert_eq!(node_i.data().position(), (2, 2)); + + /* + assert_eq!(tree.position(test_tree.node_c), (2, 0)); + assert_eq!(tree.position(test_tree.node_b), (1, 0)); + assert_eq!(tree.position(test_tree.node_a), (0, 0)); + assert_eq!(tree.position(test_tree.node_d), (3, 1)); + assert_eq!(tree.position(test_tree.node_e), (3, 2)); + assert_eq!(tree.position(test_tree.node_f), (1, 3)); + assert_eq!(tree.position(test_tree.node_g), (1, 4)); + */ } #[ignore]