diff --git a/crates/loro-core/proptest-regressions/dag/test.txt b/crates/loro-core/proptest-regressions/dag/test.txt index 61c53206..1ea18bf9 100644 --- a/crates/loro-core/proptest-regressions/dag/test.txt +++ b/crates/loro-core/proptest-regressions/dag/test.txt @@ -5,3 +5,5 @@ # It is recommended to check this file in to source control so that # everyone who runs the test benefits from these saved cases. cc 6fa5e507d2f2f20cb7f5d8a40762b5dfbe9832884ba1ec4fdd98afb3618a1495 # shrinks to before_merged_insertions = [], after_merged_insertions = [] +cc 33ec71c1f62792545519d525dcd8cdd8a4a666640aada85fc78bfe2d2b92591d # shrinks to mut interactions = [Interaction { dag_idx: 0, merge_with: None, len: 1 }, Interaction { dag_idx: 1, merge_with: None, len: 2 }, Interaction { dag_idx: 1, merge_with: Some(0), len: 1 }] +cc cbbf51fd3f0bad25aede701c73321a1ead8738e3052655595bd29aa378bc0655 # shrinks to interactions = [Interaction { dag_idx: 1, merge_with: None, len: 3 }, Interaction { dag_idx: 1, merge_with: None, len: 3 }, Interaction { dag_idx: 4, merge_with: Some(1), len: 1 }, Interaction { dag_idx: 0, merge_with: None, len: 1 }, Interaction { dag_idx: 2, merge_with: Some(0), len: 1 }, Interaction { dag_idx: 0, merge_with: None, len: 1 }, Interaction { dag_idx: 2, merge_with: Some(0), len: 1 }, Interaction { dag_idx: 3, merge_with: Some(0), len: 1 }] diff --git a/crates/loro-core/src/dag.rs b/crates/loro-core/src/dag.rs index 41d06752..b67077c1 100644 --- a/crates/loro-core/src/dag.rs +++ b/crates/loro-core/src/dag.rs @@ -12,7 +12,7 @@ use std::{ }; use fxhash::{FxHashMap, FxHashSet}; -use rle::{HasLength, Sliceable}; +use rle::HasLength; use smallvec::SmallVec; mod iter; mod mermaid; @@ -22,7 +22,7 @@ mod test; use crate::{ change::Lamport, id::{ClientID, Counter, ID}, - span::{CounterSpan, HasId, HasIdSpan, HasLamport, HasLamportSpan, IdSpan}, + span::{HasId, HasIdSpan, HasLamport, HasLamportSpan, IdSpan}, version::{VersionVector, VersionVectorDiff}, }; @@ -119,7 +119,26 @@ impl DagUtils for T { #[inline(always)] fn find_path(&self, from: ID, to: ID) -> VersionVectorDiff { - find_path(&|id: ID| self.get(id), from, to) + let mut ans = VersionVectorDiff::default(); + _find_common_ancestor( + &|v| self.get(v), + from, + to, + &mut |span, node_type| { + // dbg!(span, node_type); + match node_type { + NodeType::A => ans.merge_left(span), + NodeType::B => ans.merge_right(span), + NodeType::Shared => { + ans.subtract_start_left(span); + ans.subtract_start_right(span); + } + } + }, + true, + ); + + ans } #[inline(always)] @@ -244,15 +263,25 @@ impl<'a> OrdIdSpan<'a> { D: DagNode + 'a, F: Fn(ID) -> Option<&'a D>, { - let m = get(id)?; - let diff = id.counter - m.id_start().counter; + let span = get(id)?; + let span_id = span.id_start(); Some(OrdIdSpan { - id: id.inc(-diff), - lamport: m.lamport_start(), - deps: m.deps(), - len: diff as usize + 1, + id: span_id, + lamport: span.lamport_start(), + deps: span.deps(), + len: (id.counter - span_id.counter) as usize + 1, }) } + + #[inline] + fn get_min(&self) -> OrdIdSpan<'a> { + OrdIdSpan { + id: self.id, + lamport: self.lamport, + deps: &self.deps[0..0], + len: 1, + } + } } #[inline(always)] @@ -261,60 +290,26 @@ where D: DagNode + 'a, F: Fn(ID) -> Option<&'a D>, { - _find_common_ancestor(get, a_id, b_id, &mut |_, _| {}) -} - -fn find_path<'a, F, D>(get: &'a F, left_id: ID, right_id: ID) -> VersionVectorDiff -where - D: DagNode + 'a, - F: Fn(ID) -> Option<&'a D>, -{ - let mut ans = VersionVectorDiff::default(); - let ancestors = - _find_common_ancestor( - get, - left_id, - right_id, - &mut |span, node_type| match node_type { - NodeType::A => ans.merge_left(span), - NodeType::B => ans.merge_right(span), - NodeType::Shared => {} - }, - ); - let vv: VersionVector = ancestors.into_iter().collect(); - for (client, span) in ans.to_left.iter_mut() { - if let Some(CounterSpan { from: _, to }) = vv.intersect_span(&IdSpan { - client_id: *client, - counter: *span, - }) { - span.from = to; - } - } - - for (client, span) in ans.to_right.iter_mut() { - if let Some(CounterSpan { from: _, to }) = vv.intersect_span(&IdSpan { - client_id: *client, - counter: *span, - }) { - span.from = to; - } - } - - ans + _find_common_ancestor(get, a_id, b_id, &mut |_, _| {}, false) + .into_iter() + .map(|x| ID::new(x.0, x.1)) + .collect() } +/// - deep whether keep searching until the min of non-shared node is found fn _find_common_ancestor<'a, F, D, G>( get: &'a F, a_id: ID, b_id: ID, notify: &mut G, -) -> SmallVec<[ID; 2]> + deep: bool, +) -> FxHashMap where D: DagNode + 'a, F: Fn(ID) -> Option<&'a D>, G: FnMut(IdSpan, NodeType), { - let mut ans: SmallVec<[ID; 2]> = SmallVec::new(); + let mut ans: FxHashMap = Default::default(); let mut queue: BinaryHeap<(OrdIdSpan, NodeType)> = BinaryHeap::new(); queue.push((OrdIdSpan::from_dag_node(a_id, get).unwrap(), NodeType::A)); queue.push((OrdIdSpan::from_dag_node(b_id, get).unwrap(), NodeType::B)); @@ -330,6 +325,7 @@ where // type count in the queue. if both are zero, we can stop let mut a_count = 1; let mut b_count = 1; + let mut min = None; while let Some((node, mut node_type)) = queue.pop() { match node_type { NodeType::A => a_count -= 1, @@ -337,9 +333,20 @@ where NodeType::Shared => {} } + if node_type != NodeType::Shared { + if let Some(min) = &mut min { + let node_start = node.get_min(); + if node_start < *min { + *min = node_start; + } + } else { + min = Some(node.get_min()) + } + } + // pop the same node in the queue while let Some((other_node, other_type)) = queue.peek() { - if node.id_last() == other_node.id_last() { + if node.id_span() == other_node.id_span() { if node_type == *other_type { match node_type { NodeType::A => a_count -= 1, @@ -351,10 +358,7 @@ where if visited.get(&node.id.client_id).map(|(_, t)| *t) != Some(NodeType::Shared) { - ans.push(ID { - client_id: node.id.client_id, - counter: other_node.id_last().counter, - }); + ans.insert(node.id.client_id, other_node.id_last().counter); } node_type = NodeType::Shared; } @@ -374,13 +378,12 @@ where // detect whether client is visited by other if let Some((ctr, visited_type)) = visited.get_mut(&node.id.client_id) { debug_assert!(*ctr >= node.id_last().counter); - if *visited_type != NodeType::Shared && *visited_type != node_type { + if *visited_type == NodeType::Shared { + node_type = NodeType::Shared; + } else if *visited_type != node_type { // if node_type is shared, ans should already contains it or its descendance if node_type != NodeType::Shared { - ans.push(ID { - client_id: node.id.client_id, - counter: node.id_last().counter, - }); + ans.insert(node.id.client_id, node.id_last().counter); } *visited_type = NodeType::Shared; node_type = NodeType::Shared; @@ -399,7 +402,10 @@ where NodeType::Shared => {} } - if a_count == 0 && b_count == 0 { + if a_count == 0 + && b_count == 0 + && (!deep || min.is_none() || &node <= min.as_ref().unwrap()) + { break; } diff --git a/crates/loro-core/src/dag/test.excalidraw b/crates/loro-core/src/dag/test.excalidraw index 2145b5fa..2dd98bfd 100644 --- a/crates/loro-core/src/dag/test.excalidraw +++ b/crates/loro-core/src/dag/test.excalidraw @@ -1557,36 +1557,36 @@ ] }, { - "id": "YlP9Bsi-02bMH0FiCjimk", "type": "text", - "x": 1338.8156749765176, - "y": -115.61648283257028, - "width": 95, - "height": 25, - "angle": 0, - "strokeColor": "#000000", - "backgroundColor": "transparent", + "version": 122, + "versionNonce": 429751435, + "isDeleted": false, + "id": "YlP9Bsi-02bMH0FiCjimk", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "solid", "roughness": 1, "opacity": 100, + "angle": 0, + "x": 1338.8156749765176, + "y": -115.61648283257028, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 95, + "height": 25, + "seed": 1642740997, "groupIds": [], "strokeSharpness": "sharp", - "seed": 1642740997, - "version": 122, - "versionNonce": 429751435, - "isDeleted": false, - "boundElements": null, + "boundElements": [], "updated": 1665999108632, "link": null, "locked": false, - "text": "Find Path", "fontSize": 20, "fontFamily": 1, + "text": "Find Path", + "baseline": 18, "textAlign": "left", "verticalAlign": "top", - "baseline": 18, "containerId": null, "originalText": "Find Path" }, @@ -2519,26 +2519,26 @@ ] }, { - "id": "RAMW_ipEM953UlAM_Ssxz", "type": "rectangle", - "x": 1350.6704030660512, - "y": 344.70290264798564, - "width": 36.1762450326662, - "height": 48.752847554257414, - "angle": 0, - "strokeColor": "#e67700", - "backgroundColor": "transparent", + "version": 159, + "versionNonce": 2061719141, + "isDeleted": false, + "id": "RAMW_ipEM953UlAM_Ssxz", "fillStyle": "hachure", "strokeWidth": 4, "strokeStyle": "solid", "roughness": 1, "opacity": 100, + "angle": 0, + "x": 1350.6704030660512, + "y": 344.70290264798564, + "strokeColor": "#e67700", + "backgroundColor": "transparent", + "width": 36.1762450326662, + "height": 48.752847554257414, + "seed": 1587333899, "groupIds": [], "strokeSharpness": "sharp", - "seed": 1587333899, - "version": 159, - "versionNonce": 2061719141, - "isDeleted": false, "boundElements": [ { "id": "D7U5Ron34tY9c82vBqDaB", @@ -2554,41 +2554,30 @@ "locked": false }, { - "id": "D7U5Ron34tY9c82vBqDaB", "type": "arrow", - "x": 1271.7067680107407, - "y": 291.8062141763761, - "width": 71.47415325338443, - "height": 54.12132202602021, - "angle": 0, - "strokeColor": "#d9480f", - "backgroundColor": "transparent", + "version": 559, + "versionNonce": 1003667755, + "isDeleted": false, + "id": "D7U5Ron34tY9c82vBqDaB", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "solid", "roughness": 1, "opacity": 100, + "angle": 0, + "x": 1271.7067680107407, + "y": 291.8062141763761, + "strokeColor": "#d9480f", + "backgroundColor": "transparent", + "width": 71.47415325338443, + "height": 54.12132202602021, + "seed": 981289323, "groupIds": [], "strokeSharpness": "round", - "seed": 981289323, - "version": 559, - "versionNonce": 1003667755, - "isDeleted": false, - "boundElements": null, + "boundElements": [], "updated": 1665999390660, "link": null, "locked": false, - "points": [ - [ - 0, - 0 - ], - [ - 71.47415325338443, - 54.12132202602021 - ] - ], - "lastCommittedPoint": null, "startBinding": { "focus": 0.5414720442395691, "gap": 10.186182476718557, @@ -2599,34 +2588,50 @@ "gap": 7.48948180192599, "elementId": "RAMW_ipEM953UlAM_Ssxz" }, + "lastCommittedPoint": null, "startArrowhead": null, - "endArrowhead": "arrow" + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 71.47415325338443, + 54.12132202602021 + ] + ] }, { - "id": "p4uOM1CtA_v2Pgf6ijK9W", "type": "arrow", - "x": 1816.8655741450823, - "y": 804.5549918935991, - "width": 4.425399877032078, - "height": 863.6896840333961, - "angle": 0, - "strokeColor": "#000000", - "backgroundColor": "transparent", + "version": 269, + "versionNonce": 618942405, + "isDeleted": false, + "id": "p4uOM1CtA_v2Pgf6ijK9W", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "solid", "roughness": 2, "opacity": 100, + "angle": 0, + "x": 1816.8655741450823, + "y": 804.5549918935991, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 4.425399877032078, + "height": 863.6896840333961, + "seed": 639832037, "groupIds": [], "strokeSharpness": "round", - "seed": 639832037, - "version": 269, - "versionNonce": 618942405, - "isDeleted": false, - "boundElements": null, + "boundElements": [], "updated": 1665999562059, "link": null, "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", "points": [ [ 0, @@ -2636,44 +2641,39 @@ 4.425399877032078, -863.6896840333961 ] - ], - "lastCommittedPoint": null, - "startBinding": null, - "endBinding": null, - "startArrowhead": null, - "endArrowhead": "arrow" + ] }, { - "id": "j8MvrQTIbxG8XlEdrUsHO", "type": "text", - "x": 1710.063519604042, - "y": -31.350809576339884, - "width": 80, - "height": 25, - "angle": 0, - "strokeColor": "#000000", - "backgroundColor": "transparent", + "version": 146, + "versionNonce": 1176320779, + "isDeleted": false, + "id": "j8MvrQTIbxG8XlEdrUsHO", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "solid", "roughness": 2, "opacity": 100, + "angle": 0, + "x": 1710.063519604042, + "y": -31.350809576339884, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 80, + "height": 25, + "seed": 786904971, "groupIds": [], "strokeSharpness": "sharp", - "seed": 786904971, - "version": 146, - "versionNonce": 1176320779, - "isDeleted": false, - "boundElements": null, + "boundElements": [], "updated": 1665999562059, "link": null, "locked": false, - "text": "Lamport", "fontSize": 20, "fontFamily": 1, + "text": "Lamport", + "baseline": 18, "textAlign": "left", "verticalAlign": "top", - "baseline": 18, "containerId": null, "originalText": "Lamport" }, @@ -2717,36 +2717,36 @@ "locked": false }, { - "id": "2ZLvwZY7jTj3Y7A867PUw", "type": "text", - "x": 907.8436350772699, - "y": 2.945826594468457, - "width": 200, - "height": 25, - "angle": 0, - "strokeColor": "#000000", - "backgroundColor": "transparent", + "version": 154, + "versionNonce": 973368485, + "isDeleted": false, + "id": "2ZLvwZY7jTj3Y7A867PUw", "fillStyle": "hachure", "strokeWidth": 4, "strokeStyle": "solid", "roughness": 2, "opacity": 100, + "angle": 0, + "x": 907.8436350772699, + "y": 2.945826594468457, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 200, + "height": 25, + "seed": 1748790533, "groupIds": [], "strokeSharpness": "sharp", - "seed": 1748790533, - "version": 154, - "versionNonce": 973368485, - "isDeleted": false, - "boundElements": null, + "boundElements": [], "updated": 1665999386751, "link": null, "locked": false, - "text": "Need to find all the", "fontSize": 20, "fontFamily": 1, + "text": "Need to find all the", + "baseline": 18, "textAlign": "left", "verticalAlign": "top", - "baseline": 18, "containerId": null, "originalText": "Need to find all the" }, @@ -2825,94 +2825,94 @@ "locked": false }, { - "id": "jhZwZVYHq9DVCoTsVfoNA", "type": "text", - "x": 920.1084297636246, - "y": 103.86982908128641, - "width": 55, - "height": 20, - "angle": 0, - "strokeColor": "#d9480f", - "backgroundColor": "transparent", + "version": 30, + "versionNonce": 1511383397, + "isDeleted": false, + "id": "jhZwZVYHq9DVCoTsVfoNA", "fillStyle": "hachure", "strokeWidth": 4, "strokeStyle": "solid", "roughness": 2, "opacity": 100, + "angle": 0, + "x": 920.1084297636246, + "y": 103.86982908128641, + "strokeColor": "#d9480f", + "backgroundColor": "transparent", + "width": 55, + "height": 20, + "seed": 1102244805, "groupIds": [], "strokeSharpness": "sharp", - "seed": 1102244805, - "version": 30, - "versionNonce": 1511383397, - "isDeleted": false, - "boundElements": null, + "boundElements": [], "updated": 1665999425042, "link": null, "locked": false, - "text": "From A", "fontSize": 16, "fontFamily": 1, + "text": "From A", + "baseline": 14, "textAlign": "left", "verticalAlign": "top", - "baseline": 14, "containerId": null, "originalText": "From A" }, { - "id": "nwkFN4UJbc5Jg4yZ0eNgs", "type": "text", - "x": 1041.1473326329826, - "y": 101.57709076329934, - "width": 56, - "height": 20, - "angle": 0, - "strokeColor": "#1864ab", - "backgroundColor": "transparent", + "version": 65, + "versionNonce": 1092051499, + "isDeleted": false, + "id": "nwkFN4UJbc5Jg4yZ0eNgs", "fillStyle": "hachure", "strokeWidth": 4, "strokeStyle": "solid", "roughness": 2, "opacity": 100, + "angle": 0, + "x": 1041.1473326329826, + "y": 101.57709076329934, + "strokeColor": "#1864ab", + "backgroundColor": "transparent", + "width": 56, + "height": 20, + "seed": 1781306661, "groupIds": [], "strokeSharpness": "sharp", - "seed": 1781306661, - "version": 65, - "versionNonce": 1092051499, - "isDeleted": false, - "boundElements": null, + "boundElements": [], "updated": 1665999423063, "link": null, "locked": false, - "text": "From B", "fontSize": 16, "fontFamily": 1, + "text": "From B", + "baseline": 14, "textAlign": "left", "verticalAlign": "top", - "baseline": 14, "containerId": null, "originalText": "From B" }, { - "id": "kIrTAwchInsTnq6LCV63N", "type": "text", - "x": 895.0964797797128, - "y": 397.1606789154389, - "width": 214, - "height": 20, - "angle": 0, - "strokeColor": "#000000", - "backgroundColor": "transparent", + "version": 72, + "versionNonce": 1161356325, + "isDeleted": false, + "id": "kIrTAwchInsTnq6LCV63N", "fillStyle": "hachure", "strokeWidth": 4, "strokeStyle": "solid", "roughness": 2, "opacity": 100, + "angle": 0, + "x": 895.0964797797128, + "y": 397.1606789154389, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 214, + "height": 20, + "seed": 167668933, "groupIds": [], "strokeSharpness": "sharp", - "seed": 167668933, - "version": 72, - "versionNonce": 1161356325, - "isDeleted": false, "boundElements": [ { "id": "KLyXLrCImVTQP_jU2EX9O", @@ -2922,40 +2922,49 @@ "updated": 1665999453592, "link": null, "locked": false, - "text": "This case is a little tricky", "fontSize": 16, "fontFamily": 1, + "text": "This case is a little tricky", + "baseline": 14, "textAlign": "left", "verticalAlign": "top", - "baseline": 14, "containerId": null, "originalText": "This case is a little tricky" }, { - "id": "KLyXLrCImVTQP_jU2EX9O", "type": "arrow", - "x": 1119.079507605672, - "y": 405.26356192336186, - "width": 205.11324147046594, - "height": 45.80272521494817, - "angle": 0, - "strokeColor": "#000000", - "backgroundColor": "transparent", + "version": 133, + "versionNonce": 974117669, + "isDeleted": false, + "id": "KLyXLrCImVTQP_jU2EX9O", "fillStyle": "hachure", "strokeWidth": 4, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, + "angle": 0, + "x": 1119.079507605672, + "y": 405.26356192336186, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 205.11324147046594, + "height": 45.80272521494817, + "seed": 459973771, "groupIds": [], "strokeSharpness": "round", - "seed": 459973771, - "version": 133, - "versionNonce": 974117669, - "isDeleted": false, - "boundElements": null, + "boundElements": [], "updated": 1665999478246, "link": null, "locked": false, + "startBinding": { + "elementId": "kIrTAwchInsTnq6LCV63N", + "focus": 0.714758414751021, + "gap": 9.983027825959198 + }, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", "points": [ [ 0, @@ -2965,50 +2974,1348 @@ 205.11324147046594, -45.80272521494817 ] + ] + }, + { + "type": "text", + "version": 179, + "versionNonce": 2109547, + "isDeleted": false, + "id": "SztschmDzOAjFuvTM-OuV", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "dashed", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 893.4248140652206, + "y": 439.769275660658, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 276, + "height": 40, + "seed": 332043691, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1665999553404, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "we need to slice it after we found\nthe nearest common ancestors", + "baseline": 34, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "we need to slice it after we found\nthe nearest common ancestors" + }, + { + "id": "Y9vqkX1na6vJDz7l4PspG", + "type": "rectangle", + "x": 207.46439441645236, + "y": 845.6472361162546, + "width": 62.180771530968855, + "height": 64.0268369575906, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 1456447841, + "version": 99, + "versionNonce": 1797908175, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "EJMwY_7pCh7jyDuzdJg6V" + }, + { + "id": "iBGHqUq7evqeBkhBGjpIY", + "type": "arrow" + }, + { + "id": "1FA4XZdv1alN1lHogHTl9", + "type": "arrow" + } + ], + "updated": 1666014868325, + "link": null, + "locked": false + }, + { + "id": "t51UcEh3ESlAROMlQggkd", + "type": "text", + "x": 150.87847590478498, + "y": 750.1418377874459, + "width": 609.5544837384108, + "height": 29.249255457697245, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 699369007, + "version": 135, + "versionNonce": 319012015, + "isDeleted": false, + "boundElements": null, + "updated": 1666014940136, + "link": null, + "locked": false, + "text": "What is the nearest common ancestors in this case?", + "fontSize": 23.399404366157817, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "baseline": 21.249255457697245, + "containerId": null, + "originalText": "What is the nearest common ancestors in this case?" + }, + { + "id": "OcZsyOg63jPy2vGYoS8dH", + "type": "rectangle", + "x": 197.62028593945422, + "y": 994.0831720435232, + "width": 55, + "height": 67.44040550860723, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 1580756303, + "version": 169, + "versionNonce": 998893615, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "BW_IPp1nyObkgC7Vu3OYp" + }, + { + "id": "iBGHqUq7evqeBkhBGjpIY", + "type": "arrow" + }, + { + "id": "WLEzhxAeQRhzi52ESFg-q", + "type": "arrow" + } + ], + "updated": 1666014878508, + "link": null, + "locked": false + }, + { + "id": "EJMwY_7pCh7jyDuzdJg6V", + "type": "text", + "x": 212.46439441645236, + "y": 865.1606545950499, + "width": 52, + "height": 23, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 546698977, + "version": 5, + "versionNonce": 2086433441, + "isDeleted": false, + "boundElements": null, + "updated": 1666014852921, + "link": null, + "locked": false, + "text": "A", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "baseline": 17, + "containerId": "Y9vqkX1na6vJDz7l4PspG", + "originalText": "A" + }, + { + "id": "BW_IPp1nyObkgC7Vu3OYp", + "type": "text", + "x": 202.62028593945422, + "y": 1015.3033747978269, + "width": 45, + "height": 23, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 1644625505, + "version": 40, + "versionNonce": 2073354625, + "isDeleted": false, + "boundElements": null, + "updated": 1666014857019, + "link": null, + "locked": false, + "text": "B", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "baseline": 17, + "containerId": "OcZsyOg63jPy2vGYoS8dH", + "originalText": "B" + }, + { + "id": "gCZ4PjyxtYNIC3EGFAKxA", + "type": "rectangle", + "x": 356.58493261190574, + "y": 974.517711358304, + "width": 54, + "height": 58, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 1573171983, + "version": 127, + "versionNonce": 752357121, + "isDeleted": false, + "boundElements": [ + { + "id": "1FA4XZdv1alN1lHogHTl9", + "type": "arrow" + }, + { + "id": "fOuTMdWLfJmuB2ov11q7v", + "type": "arrow" + }, + { + "type": "text", + "id": "86HkQ09dZUZF0MFiJVz63" + } + ], + "updated": 1666014933202, + "link": null, + "locked": false + }, + { + "id": "hLRIE0OQJr_P647NEGYUb", + "type": "rectangle", + "x": 339.35656242842015, + "y": 1187.155175856424, + "width": 63.38000584903011, + "height": 74.49416956838468, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 1700659777, + "version": 176, + "versionNonce": 732448207, + "isDeleted": false, + "boundElements": [ + { + "id": "WLEzhxAeQRhzi52ESFg-q", + "type": "arrow" + }, + { + "id": "fOuTMdWLfJmuB2ov11q7v", + "type": "arrow" + }, + { + "type": "text", + "id": "uc0dpPTx3z-Oih__yVi7r" + } + ], + "updated": 1666014933203, + "link": null, + "locked": false + }, + { + "id": "iBGHqUq7evqeBkhBGjpIY", + "type": "arrow", + "x": 238.39425275353517, + "y": 916.6475734194214, + "width": 3.4230113409226988, + "height": 64.07877230207362, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "round", + "seed": 355303279, + "version": 43, + "versionNonce": 654921825, + "isDeleted": false, + "boundElements": null, + "updated": 1666014866360, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -3.4230113409226988, + 64.07877230207362 + ] ], "lastCommittedPoint": null, "startBinding": { - "elementId": "kIrTAwchInsTnq6LCV63N", - "focus": 0.714758414751021, - "gap": 9.983027825959198 + "elementId": "Y9vqkX1na6vJDz7l4PspG", + "focus": -0.05859992602942486, + "gap": 6.973500345576213 + }, + "endBinding": { + "elementId": "OcZsyOg63jPy2vGYoS8dH", + "focus": 0.2503697342260085, + "gap": 13.356826322028098 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "1FA4XZdv1alN1lHogHTl9", + "type": "arrow", + "x": 280.2730259866174, + "y": 874.3827042892433, + "width": 108.9112565402437, + "height": 90.60251065896, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "round", + "seed": 958569537, + "version": 212, + "versionNonce": 829985711, + "isDeleted": false, + "boundElements": null, + "updated": 1666014933203, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 108.9112565402437, + 90.60251065896 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "Y9vqkX1na6vJDz7l4PspG", + "gap": 10.627860039196209, + "focus": -0.6558398277536983 + }, + "endBinding": { + "elementId": "gCZ4PjyxtYNIC3EGFAKxA", + "gap": 9.53249641010075, + "focus": 0.8392853510122925 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "WLEzhxAeQRhzi52ESFg-q", + "type": "arrow", + "x": 225.846817638945, + "y": 1073.1712589011736, + "width": 130.36469464909064, + "height": 104.34282846123074, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "round", + "seed": 974853505, + "version": 343, + "versionNonce": 1391199873, + "isDeleted": false, + "boundElements": null, + "updated": 1666014933203, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 130.36469464909064, + 104.34282846123074 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "OcZsyOg63jPy2vGYoS8dH", + "focus": 0.8039769929584992, + "gap": 11.647681349043125 + }, + "endBinding": { + "elementId": "hLRIE0OQJr_P647NEGYUb", + "focus": 0.5592314137305141, + "gap": 9.641088494019641 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "fOuTMdWLfJmuB2ov11q7v", + "type": "arrow", + "x": 383.2859330385243, + "y": 1039.3495698552904, + "width": 0.8019442573741458, + "height": 139.71785644664988, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "round", + "seed": 1093453345, + "version": 438, + "versionNonce": 854268481, + "isDeleted": false, + "boundElements": null, + "updated": 1666014933358, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -0.8019442573741458, + 139.71785644664988 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "gCZ4PjyxtYNIC3EGFAKxA", + "focus": 0.0034356344242915454, + "gap": 6.831858496986342 + }, + "endBinding": { + "elementId": "hLRIE0OQJr_P647NEGYUb", + "focus": 0.35034121969360427, + "gap": 8.087749554483707 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "86HkQ09dZUZF0MFiJVz63", + "type": "text", + "x": 361.58493261190574, + "y": 992.017711358304, + "width": 44, + "height": 23, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 1827546465, + "version": 77, + "versionNonce": 934616463, + "isDeleted": false, + "boundElements": null, + "updated": 1666014933202, + "link": null, + "locked": false, + "text": "1", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "baseline": 17, + "containerId": "gCZ4PjyxtYNIC3EGFAKxA", + "originalText": "1" + }, + { + "id": "uc0dpPTx3z-Oih__yVi7r", + "type": "text", + "x": 344.35656242842015, + "y": 1211.9022606406163, + "width": 53, + "height": 23, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 1503038895, + "version": 88, + "versionNonce": 1984103073, + "isDeleted": false, + "boundElements": null, + "updated": 1666014933203, + "link": null, + "locked": false, + "text": "2", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "baseline": 17, + "containerId": "hLRIE0OQJr_P647NEGYUb", + "originalText": "2" + }, + { + "id": "kI_tZyDto7LyRVi7fZo1b", + "type": "text", + "x": 458.5859491764503, + "y": 836.3733952089806, + "width": 268, + "height": 25, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 381074991, + "version": 244, + "versionNonce": 2076991297, + "isDeleted": false, + "boundElements": null, + "updated": 1666014941736, + "link": null, + "locked": false, + "text": "Is it just B? Or B and 2?", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "baseline": 18, + "containerId": null, + "originalText": "Is it just B? Or B and 2?" + }, + { + "id": "Ucbb53X_Dwn5QAY3EB0D8", + "type": "text", + "x": 459.9740392926316, + "y": 901.9771780808721, + "width": 254, + "height": 25, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 343812495, + "version": 163, + "versionNonce": 2136128609, + "isDeleted": false, + "boundElements": null, + "updated": 1666017750870, + "link": null, + "locked": false, + "text": "Should be both B and 2. ", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "baseline": 18, + "containerId": null, + "originalText": "Should be both B and 2. " + }, + { + "id": "cOQa-Eb9wSAJWzgq9aI7x", + "type": "text", + "x": 159.49974308895753, + "y": 1311.600682807928, + "width": 424, + "height": 25, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 1981785473, + "version": 50, + "versionNonce": 27195407, + "isDeleted": false, + "boundElements": null, + "updated": 1666017454170, + "link": null, + "locked": false, + "text": "How to tackle this case when finding path?", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "baseline": 18, + "containerId": null, + "originalText": "How to tackle this case when finding path?" + }, + { + "id": "hwOHW2_5-VmaE0Y21RH6I", + "type": "rectangle", + "x": 174.03219675428193, + "y": 1394.1222450159953, + "width": 49.409398183112216, + "height": 51.5151403321488, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 578415457, + "version": 43, + "versionNonce": 919340175, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "o2Bs8-53MFFZjUFarRyRN" + }, + { + "id": "qCbjrqfXeEu-zEq2Ffb3T", + "type": "arrow" + }, + { + "id": "R6d9DcWsOcD8YWu9N7JxL", + "type": "arrow" + } + ], + "updated": 1666017483844, + "link": null, + "locked": false + }, + { + "id": "o2Bs8-53MFFZjUFarRyRN", + "type": "text", + "x": 179.03219675428193, + "y": 1407.3798151820697, + "width": 39, + "height": 23, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 1451199681, + "version": 5, + "versionNonce": 2072121473, + "isDeleted": false, + "boundElements": null, + "updated": 1666017442450, + "link": null, + "locked": false, + "text": "A", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "baseline": 17, + "containerId": "hwOHW2_5-VmaE0Y21RH6I", + "originalText": "A" + }, + { + "id": "D36mTqaq_mm5bD6sonefu", + "type": "rectangle", + "x": 341.06570740140523, + "y": 1402.8757112588514, + "width": 52, + "height": 54.08830058153217, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 1613404719, + "version": 39, + "versionNonce": 149948207, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "PnMoL-isuYyODBEw1k2wf" + }, + { + "id": "NyiyA39uyFO2fv9N82bF4", + "type": "arrow" + } + ], + "updated": 1666017612566, + "link": null, + "locked": false + }, + { + "id": "PnMoL-isuYyODBEw1k2wf", + "type": "text", + "x": 346.06570740140523, + "y": 1417.4198615496175, + "width": 42, + "height": 23, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 467983471, + "version": 5, + "versionNonce": 2092292545, + "isDeleted": false, + "boundElements": null, + "updated": 1666017449029, + "link": null, + "locked": false, + "text": "B", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "baseline": 17, + "containerId": "D36mTqaq_mm5bD6sonefu", + "originalText": "B" + }, + { + "id": "qCbjrqfXeEu-zEq2Ffb3T", + "type": "arrow", + "x": 199.85822714717483, + "y": 1452.9508261303365, + "width": 40.22628499953339, + "height": 184.9087119391695, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "round", + "seed": 105061935, + "version": 74, + "versionNonce": 660435905, + "isDeleted": false, + "boundElements": null, + "updated": 1666017470026, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 40.22628499953339, + 184.9087119391695 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "hwOHW2_5-VmaE0Y21RH6I", + "focus": 0.20038022884771262, + "gap": 7.3134407821924015 }, "endBinding": null, "startArrowhead": null, "endArrowhead": "arrow" }, { - "id": "SztschmDzOAjFuvTM-OuV", - "type": "text", - "x": 893.4248140652206, - "y": 439.769275660658, - "width": 276, - "height": 40, + "id": "NyiyA39uyFO2fv9N82bF4", + "type": "arrow", + "x": 370.7066249163197, + "y": 1466.4917868555315, + "width": 113.29459329211295, + "height": 165.0694103466767, "angle": 0, "strokeColor": "#000000", "backgroundColor": "transparent", "fillStyle": "hachure", - "strokeWidth": 4, - "strokeStyle": "dashed", - "roughness": 2, + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "round", + "seed": 366695329, + "version": 41, + "versionNonce": 1777146145, + "isDeleted": false, + "boundElements": null, + "updated": 1666017474327, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -113.29459329211295, + 165.0694103466767 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "D36mTqaq_mm5bD6sonefu", + "focus": -0.6449918259980243, + "gap": 9.527775015147881 + }, + "endBinding": null, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "s54CZ5KG2aYjaNsp6G4VZ", + "type": "rectangle", + "x": 217.9317270272469, + "y": 1640.4751908734663, + "width": 63.21475702567511, + "height": 68.62547564180954, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, "opacity": 100, "groupIds": [], "strokeSharpness": "sharp", - "seed": 332043691, - "version": 179, - "versionNonce": 2109547, + "seed": 638536961, + "version": 65, + "versionNonce": 743628079, + "isDeleted": false, + "boundElements": [ + { + "id": "aw37qj_R25zNHnnWOQGPF", + "type": "arrow" + } + ], + "updated": 1666018038282, + "link": null, + "locked": false + }, + { + "id": "R6d9DcWsOcD8YWu9N7JxL", + "type": "arrow", + "x": 179.45235816032232, + "y": 1451.817691341617, + "width": 111.97732410022672, + "height": 94.94253110981413, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "round", + "seed": 1780700449, + "version": 50, + "versionNonce": 625597679, "isDeleted": false, "boundElements": null, - "updated": 1665999553404, + "updated": 1666017511261, "link": null, "locked": false, - "text": "we need to slice it after we found\nthe nearest common ancestors", - "fontSize": 16, - "fontFamily": 1, - "textAlign": "left", - "verticalAlign": "top", - "baseline": 34, - "containerId": null, - "originalText": "we need to slice it after we found\nthe nearest common ancestors" + "points": [ + [ + 0, + 0 + ], + [ + -111.97732410022672, + 94.94253110981413 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "hwOHW2_5-VmaE0Y21RH6I", + "focus": -0.3337409231098588, + "gap": 6.1803059934729845 + }, + "endBinding": { + "elementId": "Uu6icBmJsdOeGkGZzL7sU", + "focus": -0.6678530131421979, + "gap": 9.065078309754199 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "Uu6icBmJsdOeGkGZzL7sU", + "type": "rectangle", + "x": 36.14857854696129, + "y": 1555.8253007611854, + "width": 54.08830058153217, + "height": 59.489576407760524, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 1867485153, + "version": 63, + "versionNonce": 706063439, + "isDeleted": false, + "boundElements": [ + { + "id": "2-6tyGZ_ZmFG9B-mW7C21", + "type": "arrow" + }, + { + "id": "R6d9DcWsOcD8YWu9N7JxL", + "type": "arrow" + } + ], + "updated": 1666017507044, + "link": null, + "locked": false + }, + { + "id": "2-6tyGZ_ZmFG9B-mW7C21", + "type": "arrow", + "x": 69.80268177192295, + "y": 1626.4762548378305, + "width": 40.55206125129018, + "height": 95.98595939442657, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "round", + "seed": 803727777, + "version": 290, + "versionNonce": 240732783, + "isDeleted": false, + "boundElements": null, + "updated": 1666017507045, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -40.55206125129018, + 95.98595939442657 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "Uu6icBmJsdOeGkGZzL7sU", + "focus": -0.6031691429467954, + "gap": 11.161377668884597 + }, + "endBinding": { + "elementId": "kMzfHdkQJvza3Y7oH-Stk", + "focus": -0.780062894083163, + "gap": 7.828072832068642 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "kMzfHdkQJvza3Y7oH-Stk", + "type": "rectangle", + "x": 5.5633820414475395, + "y": 1730.2902870643259, + "width": 49.86265209859994, + "height": 320.63937404792387, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 1045724623, + "version": 108, + "versionNonce": 529250031, + "isDeleted": false, + "boundElements": [ + { + "id": "2-6tyGZ_ZmFG9B-mW7C21", + "type": "arrow" + }, + { + "id": "StiyyzlA2m4GVtTLr2uzG", + "type": "arrow" + }, + { + "id": "3HbM7P7WEUHkMZ9blj5wa", + "type": "arrow" + } + ], + "updated": 1666017561182, + "link": null, + "locked": false + }, + { + "id": "xG6Ryld1g4RsmlYfeyRyl", + "type": "rectangle", + "x": 4.930715117745535, + "y": 1894.3540402860144, + "width": 49.206378200133486, + "height": 156.04210319654658, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 441826383, + "version": 116, + "versionNonce": 1378166913, + "isDeleted": false, + "boundElements": [ + { + "id": "29BHND6z19Wd0fVvFoxsH", + "type": "arrow" + } + ], + "updated": 1666018042532, + "link": null, + "locked": false + }, + { + "id": "7avwsrGLRQ9zXDSv0w1np", + "type": "rectangle", + "x": 166.8651192156325, + "y": 1781.2294172122108, + "width": 24.806209083045587, + "height": 32.90812282238835, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 1685597185, + "version": 31, + "versionNonce": 1984895873, + "isDeleted": false, + "boundElements": [ + { + "id": "aw37qj_R25zNHnnWOQGPF", + "type": "arrow" + }, + { + "id": "9h36VDCVJrRu8C1CMjJtB", + "type": "arrow" + } + ], + "updated": 1666018040016, + "link": null, + "locked": false + }, + { + "id": "0uds6kbQkH4ArKucMh0Vg", + "type": "rectangle", + "x": 115.45857096740258, + "y": 1831.7105720496534, + "width": 33.93738692214151, + "height": 30.297191413380915, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "sharp", + "seed": 1820056143, + "version": 43, + "versionNonce": 511206561, + "isDeleted": false, + "boundElements": [ + { + "id": "9h36VDCVJrRu8C1CMjJtB", + "type": "arrow" + }, + { + "id": "29BHND6z19Wd0fVvFoxsH", + "type": "arrow" + } + ], + "updated": 1666018042532, + "link": null, + "locked": false + }, + { + "id": "aw37qj_R25zNHnnWOQGPF", + "type": "arrow", + "x": 241.67090085091502, + "y": 1720.7483478643207, + "width": 40.703145889786015, + "height": 49.39051260330052, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "round", + "seed": 1142455201, + "version": 38, + "versionNonce": 481825089, + "isDeleted": false, + "boundElements": null, + "updated": 1666018038282, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -40.703145889786015, + 49.39051260330052 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "s54CZ5KG2aYjaNsp6G4VZ", + "focus": -0.5010982988927215, + "gap": 11.647681349044774 + }, + "endBinding": { + "elementId": "7avwsrGLRQ9zXDSv0w1np", + "focus": -0.03852497283277824, + "gap": 11.090556744589435 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "9h36VDCVJrRu8C1CMjJtB", + "type": "arrow", + "x": 164.44776499969817, + "y": 1807.2348606133176, + "width": 17.138663679378624, + "height": 16.893151141822955, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "round", + "seed": 285622561, + "version": 27, + "versionNonce": 778246415, + "isDeleted": false, + "boundElements": null, + "updated": 1666018040016, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -17.138663679378624, + 16.893151141822955 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "7avwsrGLRQ9zXDSv0w1np", + "focus": 0.17632017043480894, + "gap": 2.417354215934324 + }, + "endBinding": { + "elementId": "0uds6kbQkH4ArKucMh0Vg", + "focus": -0.2529475107653309, + "gap": 7.582560294512859 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "29BHND6z19Wd0fVvFoxsH", + "type": "arrow", + "x": 111.12433040055146, + "y": 1855.3930891338857, + "width": 51.59068265139683, + "height": 34.503954316500995, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "strokeSharpness": "round", + "seed": 668671791, + "version": 44, + "versionNonce": 1864790511, + "isDeleted": false, + "boundElements": null, + "updated": 1666018042532, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -51.59068265139683, + 34.503954316500995 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "0uds6kbQkH4ArKucMh0Vg", + "focus": 0.2156267298677806, + "gap": 4.334240566851122 + }, + "endBinding": { + "elementId": "xG6Ryld1g4RsmlYfeyRyl", + "focus": -0.6606370592162203, + "gap": 5.396554431275604 + }, + "startArrowhead": null, + "endArrowhead": "arrow" } ], "appState": { diff --git a/crates/loro-core/src/dag/test.rs b/crates/loro-core/src/dag/test.rs index 2dbb13a5..30cc7200 100644 --- a/crates/loro-core/src/dag/test.rs +++ b/crates/loro-core/src/dag/test.rs @@ -1,5 +1,6 @@ #![cfg(test)] +use proptest::prelude::*; use std::cmp::Ordering; use super::*; @@ -123,7 +124,7 @@ impl TestDag { let counter = self.version_vec.entry(client_id).or_insert(0); let id = ID::new(client_id, *counter); *counter += len as Counter; - let deps = std::mem::replace(&mut self.frontier, vec![id]); + let deps = std::mem::replace(&mut self.frontier, vec![id.inc(len as Counter - 1)]); if deps.len() == 1 && deps[0].client_id == client_id { // can merge two op let arr = self.nodes.get_mut(&client_id).unwrap(); @@ -277,6 +278,21 @@ impl Interaction { } } +prop_compose! { + fn gen_interaction(num: usize) ( + dag_idx in 0..num, + merge_with in 0..num, + length in 1..10, + should_merge in 0..2 + ) -> Interaction { + Interaction { + dag_idx, + merge_with: if should_merge == 1 && merge_with != dag_idx { Some(merge_with) } else { None }, + len: length as usize, + } + } +} + fn preprocess(interactions: &mut [Interaction], num: i32) { for interaction in interactions.iter_mut() { interaction.dag_idx %= num as usize; @@ -414,7 +430,7 @@ mod get_version_vector { #[cfg(test)] mod find_path { - use crate::fx_map; + use crate::{fx_map, span::CounterSpan, tests::PROPTEST_FACTOR_10}; use super::*; @@ -486,14 +502,17 @@ mod find_path { ); } - fn proptest(dag_num: i32, interactions: &mut [Interaction]) { - preprocess(interactions, dag_num); + fn test_find_path( + dag_num: i32, + mut interactions: Vec, + ) -> Result<(), TestCaseError> { + preprocess(&mut interactions, dag_num); let mut dags = Vec::new(); for i in 0..dag_num { dags.push(TestDag::new(i as ClientID)); } - for interaction in interactions { + for interaction in interactions.iter_mut() { interaction.apply(&mut dags); } @@ -508,16 +527,99 @@ mod find_path { nodes.push((node, vv)); } + // println!("{}", a.mermaid()); for (i, (node, vv)) in nodes.iter().enumerate() { + if i > 3 { + break; + } + for (j, (other_node, other_vv)) in nodes.iter().enumerate() { if i == j { continue; } + let actual = a.find_path(node.id, other_node.id); - // let expected = find_path(*vv, *other_vv); - // assert_eq!(actual, expected); + let expected = vv.clone() - other_vv.clone(); + prop_assert_eq!( + actual, + expected, + "\ni={} j={} node={} other={}", + i, + j, + node.id, + other_node.id + ); } } + + Ok(()) + } + + #[test] + fn issue() { + if let Err(err) = test_find_path( + 5, + vec![ + Interaction { + dag_idx: 1, + merge_with: None, + len: 3, + }, + Interaction { + dag_idx: 1, + merge_with: None, + len: 3, + }, + Interaction { + dag_idx: 4, + merge_with: Some(1), + len: 1, + }, + Interaction { + dag_idx: 0, + merge_with: None, + len: 1, + }, + Interaction { + dag_idx: 2, + merge_with: Some(0), + len: 1, + }, + Interaction { + dag_idx: 0, + merge_with: None, + len: 1, + }, + Interaction { + dag_idx: 2, + merge_with: Some(0), + len: 1, + }, + Interaction { + dag_idx: 3, + merge_with: Some(0), + len: 1, + }, + ], + ) { + panic!("{}", err); + } + } + + proptest! { + #[test] + fn proptest_path( + interactions in prop::collection::vec(gen_interaction(5), 0..50 * PROPTEST_FACTOR_10), + ) { + test_find_path(5, interactions)?; + } + + #[test] + fn proptest_path_large( + interactions in prop::collection::vec(gen_interaction(10), 0..10 * PROPTEST_FACTOR_10 * PROPTEST_FACTOR_10 + 10), + ) { + test_find_path(10, interactions)?; + } } } @@ -619,7 +721,6 @@ mod find_common_ancestors { } mod find_common_ancestors_proptest { - use proptest::prelude::*; use crate::{ array_mut_ref, @@ -630,21 +731,6 @@ mod find_common_ancestors_proptest { use super::*; - prop_compose! { - fn gen_interaction(num: usize) ( - dag_idx in 0..num, - merge_with in 0..num, - length in 1..10, - should_merge in 0..2 - ) -> Interaction { - Interaction { - dag_idx, - merge_with: if should_merge == 1 && merge_with != dag_idx { Some(merge_with) } else { None }, - len: length as usize, - } - } - } - proptest! { #[test] fn test_2dags( diff --git a/crates/loro-core/src/version.rs b/crates/loro-core/src/version.rs index cdf26464..f645ed2f 100644 --- a/crates/loro-core/src/version.rs +++ b/crates/loro-core/src/version.rs @@ -56,6 +56,16 @@ impl VersionVectorDiff { merge(&mut self.to_right, span); } + #[inline] + pub fn subtract_start_left(&mut self, span: IdSpan) { + subtract_start(&mut self.to_left, span); + } + + #[inline] + pub fn subtract_start_right(&mut self, span: IdSpan) { + subtract_start(&mut self.to_right, span); + } + pub fn get_id_spans_left(&self) -> impl Iterator + '_ { self.to_left.iter().map(|(client_id, span)| IdSpan { client_id: *client_id, @@ -71,6 +81,14 @@ impl VersionVectorDiff { } } +fn subtract_start(m: &mut FxHashMap, target: IdSpan) { + if let Some(span) = m.get_mut(&target.client_id) { + if span.from < target.counter.to { + span.from = target.counter.to; + } + } +} + fn merge(m: &mut FxHashMap, target: IdSpan) { if let Some(span) = m.get_mut(&target.client_id) { span.from = span.from.min(target.counter.from);