diff --git a/sgf/src/game.rs b/sgf/src/game.rs index 4579ed4..afda856 100644 --- a/sgf/src/game.rs +++ b/sgf/src/game.rs @@ -1,17 +1,33 @@ use crate::{Color, Position}; use uuid::Uuid; -pub trait Node { - fn path_to_node<'a>(&'a self, id: Uuid) -> Vec<&'a GameNode>; - fn add_child<'a>(&'a mut self, node: GameNode) -> &'a GameNode; - fn add_annotation(&mut self, label: String, note: String); -} - +#[derive(Clone, Debug, PartialEq)] pub enum GameNode { MoveNode(MoveNode), SetupNode(SetupNode), } +pub trait Node { + fn children<'a>(&'a self) -> Vec<&'a GameNode>; + + /// Provide a pre-order traversal of all of the nodes in the game tree. + fn nodes<'a>(&'a self) -> Vec<&'a GameNode> { + self.children() + .iter() + .map(|node| { + let mut children = node.nodes(); + let mut v = vec![*node]; + v.append(&mut children); + v + }) + .flatten() + .collect::>() + } + + fn add_child<'a>(&'a mut self, node: GameNode) -> &'a mut GameNode; + fn add_annotation(&mut self, label: String, note: String); +} + impl GameNode { fn id(&self) -> Uuid { match self { @@ -26,12 +42,25 @@ impl GameNode { } impl Node for GameNode { - fn path_to_node<'a>(&'a self, id: Uuid) -> Vec<&'a GameNode> { - unimplemented!() + fn children<'a>(&'a self) -> Vec<&'a GameNode> { + match self { + GameNode::MoveNode(node) => node.children(), + GameNode::SetupNode(node) => node.children(), + } } - fn add_child<'a>(&'a mut self, node: GameNode) -> &'a GameNode { - unimplemented!() + fn nodes<'a>(&'a self) -> Vec<&'a GameNode> { + match self { + GameNode::MoveNode(node) => node.nodes(), + GameNode::SetupNode(node) => node.nodes(), + } + } + + fn add_child<'a>(&'a mut self, new_node: GameNode) -> &'a mut GameNode { + match self { + GameNode::MoveNode(node) => node.add_child(new_node), + GameNode::SetupNode(node) => node.add_child(new_node), + } } fn add_annotation(&mut self, label: String, note: String) { @@ -49,22 +78,18 @@ impl GameTree { Self { children: vec![] } } - fn nodes<'a>(&'a self) -> impl Iterator { - vec![].into_iter() - } - - fn add_child<'a>(&'a mut self, node: GameNode) -> &'a GameNode { - // self.children.push(node); - unimplemented!() + fn add_child<'a>(&'a mut self, node: GameNode) -> &'a mut GameNode { + self.children.push(node); + self.children.last_mut().unwrap() } } impl Node for GameTree { - fn path_to_node<'a>(&'a self, id: Uuid) -> Vec<&'a GameNode> { - unimplemented!() + fn children<'a>(&'a self) -> Vec<&'a GameNode> { + self.children.iter().collect::>() } - fn add_child<'a>(&'a mut self, node: GameNode) -> &'a GameNode { + fn add_child<'a>(&'a mut self, node: GameNode) -> &'a mut GameNode { unimplemented!() } @@ -73,6 +98,7 @@ impl Node for GameTree { } } +#[derive(Clone, Debug, PartialEq)] pub struct MoveNode { id: Uuid, @@ -96,12 +122,13 @@ impl MoveNode { } impl Node for MoveNode { - fn path_to_node<'a>(&'a self, id: Uuid) -> Vec<&'a GameNode> { - unimplemented!() + fn children<'a>(&'a self) -> Vec<&'a GameNode> { + self.children.iter().collect::>() } - fn add_child<'a>(&'a mut self, node: GameNode) -> &'a GameNode { - unimplemented!() + fn add_child<'a>(&'a mut self, node: GameNode) -> &'a mut GameNode { + self.children.push(node); + self.children.last_mut().unwrap() } fn add_annotation(&mut self, label: String, note: String) { @@ -109,6 +136,7 @@ impl Node for MoveNode { } } +#[derive(Clone, Debug, PartialEq)] pub struct SetupNode { id: Uuid, @@ -129,11 +157,11 @@ impl SetupNode { } impl Node for SetupNode { - fn path_to_node<'a>(&'a self, id: Uuid) -> Vec<&'a GameNode> { - unimplemented!() + fn children<'a>(&'a self) -> Vec<&'a GameNode> { + self.children.iter().collect::>() } - fn add_child<'a>(&'a mut self, node: GameNode) -> &'a GameNode { + fn add_child<'a>(&'a mut self, node: GameNode) -> &'a mut GameNode { unimplemented!() } @@ -165,17 +193,22 @@ mod test { #[test] fn it_can_create_an_empty_game_tree() { let tree = GameTree::new(); - assert_eq!(tree.nodes().count(), 0); + assert_eq!(tree.nodes().len(), 0); } #[test] fn it_can_add_moves_to_a_game() { let mut tree = GameTree::new(); - let node = MoveNode::new(Color::Black, Position {}); - let mut node = tree.add_child(GameNode::MoveNode(node)); - let new_node = MoveNode::new(Color::White, Position {}); - node.add_child(new_node); + let first_move = MoveNode::new(Color::Black, Position {}); + let first_ = tree.add_child(GameNode::MoveNode(first_move.clone())); + let second_move = MoveNode::new(Color::White, Position {}); + first_.add_child(GameNode::MoveNode(second_move.clone())); + + let nodes = tree.nodes(); + assert_eq!(nodes.len(), 2); + assert_eq!(nodes[0].id(), first_move.id); + assert_eq!(nodes[1].id(), second_move.id); } #[test] diff --git a/sgf/src/lib.rs b/sgf/src/lib.rs index 0ea5bee..fd5a72d 100644 --- a/sgf/src/lib.rs +++ b/sgf/src/lib.rs @@ -18,11 +18,13 @@ pub enum Error { InvalidSgf(VerboseNomError), } +#[derive(Clone, Debug, PartialEq)] pub enum Color { Black, White, } +#[derive(Clone, Debug, PartialEq)] pub struct Position {} #[derive(Debug)]