From b9de00c5f378a6ca0521d46d00080270e00a69fd Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 18 Dec 2023 12:58:09 +0200 Subject: [PATCH 1/3] feature: get_children_ids_recursive --- src/lib.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 853c25f7..2a5bfc28 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -104,6 +104,30 @@ impl Contract { .unwrap_or_else(|| panic!("Parent id {} not found", post_id)) } + pub fn get_children_ids_recursive(&self, post_id: Option) -> Vec { + near_sdk::log!("get_children_ids_recursive"); + let post_id = post_id.unwrap_or(ROOT_POST_ID); + + fn get_children_recursive_helper( + post_id: PostId, + post_to_children: &LookupMap>, + ) -> Vec { + post_to_children + .get(&post_id) + .map(|children_ids| { + let mut result = Vec::new(); + for child_id in children_ids { + result.push(child_id); + result.extend(get_children_recursive_helper(child_id, post_to_children)); + } + result + }) + .unwrap_or_else(|| panic!("Parent id {} not found", post_id)) + } + + get_children_recursive_helper(post_id, &self.post_to_children) + } + pub fn get_parent_id(&self, post_id: PostId) -> Option { near_sdk::log!("get_parent_id"); let res = self @@ -631,11 +655,10 @@ mod tests { use crate::access_control::members::{ActionType, Member, MemberMetadata}; use crate::access_control::rules::Rule; - use crate::community::{AddOn, Community, CommunityAddOn, CommunityInputs}; - use crate::post::PostBody; - use near_sdk::store::vec; + use crate::community::{AddOn, CommunityAddOn, CommunityInputs}; + use crate::post::{Post, PostBody}; use near_sdk::test_utils::{get_created_receipts, VMContextBuilder}; - use near_sdk::{testing_env, AccountId, MockedBlockchain, VMContext}; + use near_sdk::{testing_env, AccountId, VMContext}; use regex::Regex; use super::Contract; @@ -666,6 +689,36 @@ mod tests { .build() } + #[test] + pub fn test_get_children_ids_recursive() { + let context = get_context(false); + testing_env!(context); + let mut contract = Contract::new(); + + let body: PostBody = near_sdk::serde_json::from_str( + r#" + { + "name": "title", + "description": "Hello", + "post_type": "Idea", + "idea_version": "V1" + }"#, + ) + .unwrap(); + contract.add_post(None, body.clone(), HashSet::new()); + + // An imaginary top post representing the landing page. + let all_posts = contract.get_posts(None); + let post = Post::from(all_posts[0].clone()); + assert_eq!(post.id, 0); + + contract.add_post(Some(0), body.clone(), HashSet::new()); + contract.add_post(Some(1), body.clone(), HashSet::new()); + + let all_children = contract.get_children_ids_recursive(Some(0)); + assert_eq!(all_children.len(), 2); + } + #[test] pub fn test_add_post_with_mention() { let context = get_context(false); From fac6a8876e49503971d66b875e318e8937ea2193 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 20 Dec 2023 12:33:46 +0200 Subject: [PATCH 2/3] add more nested comments to the post --- src/lib.rs | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1a928b65..c86c11f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -112,7 +112,9 @@ impl Contract { post_id: PostId, post_to_children: &LookupMap>, ) -> Vec { - post_to_children + near_sdk::log!("test"); + + return post_to_children .get(&post_id) .map(|children_ids| { let mut result = Vec::new(); @@ -122,7 +124,7 @@ impl Contract { } result }) - .unwrap_or_else(|| panic!("Parent id {} not found", post_id)) + .unwrap_or_else(|| panic!("Parent id {} not found", post_id)); } get_children_recursive_helper(post_id, &self.post_to_children) @@ -597,7 +599,7 @@ mod tests { use crate::community::{AddOn, CommunityAddOn, CommunityInputs}; use crate::post::{Post, PostBody}; use near_sdk::test_utils::{get_created_receipts, VMContextBuilder}; - use near_sdk::{testing_env, AccountId, VMContext}; + use near_sdk::{testing_env, AccountId, Gas, VMContext}; use regex::Regex; use super::Contract; @@ -644,6 +646,16 @@ mod tests { }"#, ) .unwrap(); + + let commentBody: PostBody = near_sdk::serde_json::from_str( + r#" + { + "description": "Interesting comment", + "post_type": "Comment", + "comment_version": "V2" + }"#, + ) + .unwrap(); contract.add_post(None, body.clone(), HashSet::new()); // An imaginary top post representing the landing page. @@ -651,11 +663,20 @@ mod tests { let post = Post::from(all_posts[0].clone()); assert_eq!(post.id, 0); - contract.add_post(Some(0), body.clone(), HashSet::new()); - contract.add_post(Some(1), body.clone(), HashSet::new()); + contract.add_post(Some(0), commentBody.clone(), HashSet::new()); + contract.add_post(Some(1), commentBody.clone(), HashSet::new()); + let context = get_context(false); + testing_env!(context); + contract.add_post(Some(1), commentBody.clone(), HashSet::new()); + contract.add_post(Some(2), commentBody.clone(), HashSet::new()); + contract.add_post(Some(3), commentBody.clone(), HashSet::new()); + let context = get_context(false); + testing_env!(context); + contract.add_post(Some(3), commentBody.clone(), HashSet::new()); + contract.add_post(Some(3), commentBody.clone(), HashSet::new()); let all_children = contract.get_children_ids_recursive(Some(0)); - assert_eq!(all_children.len(), 2); + assert_eq!(all_children.len(), 7); } #[test] From 57de9efc976545bd4f294495b41b4a6f3db42437 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 21 Dec 2023 11:33:06 +0200 Subject: [PATCH 3/3] replace recursive fn with an iterative one --- src/lib.rs | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c86c11f6..a6f3142e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -104,30 +104,21 @@ impl Contract { .unwrap_or_else(|| panic!("Parent id {} not found", post_id)) } - pub fn get_children_ids_recursive(&self, post_id: Option) -> Vec { - near_sdk::log!("get_children_ids_recursive"); - let post_id = post_id.unwrap_or(ROOT_POST_ID); + pub fn get_all_children_ids(&self, post_id: Option) -> Vec { + let mut result = Vec::new(); + let mut stack = Vec::new(); + + let start_post_id = post_id.unwrap_or(ROOT_POST_ID); + stack.push(start_post_id); - fn get_children_recursive_helper( - post_id: PostId, - post_to_children: &LookupMap>, - ) -> Vec { - near_sdk::log!("test"); - - return post_to_children - .get(&post_id) - .map(|children_ids| { - let mut result = Vec::new(); - for child_id in children_ids { - result.push(child_id); - result.extend(get_children_recursive_helper(child_id, post_to_children)); - } - result - }) - .unwrap_or_else(|| panic!("Parent id {} not found", post_id)); + while let Some(current_post_id) = stack.pop() { + if let Some(children_ids) = self.post_to_children.get(¤t_post_id) { + result.extend(children_ids.iter().cloned()); + stack.extend(children_ids.iter().cloned()); + } } - get_children_recursive_helper(post_id, &self.post_to_children) + result } pub fn get_parent_id(&self, post_id: PostId) -> Option { @@ -631,7 +622,7 @@ mod tests { } #[test] - pub fn test_get_children_ids_recursive() { + pub fn test_get_all_children_ids() { let context = get_context(false); testing_env!(context); let mut contract = Contract::new(); @@ -675,7 +666,7 @@ mod tests { contract.add_post(Some(3), commentBody.clone(), HashSet::new()); contract.add_post(Some(3), commentBody.clone(), HashSet::new()); - let all_children = contract.get_children_ids_recursive(Some(0)); + let all_children = contract.get_all_children_ids(Some(0)); assert_eq!(all_children.len(), 7); }