thisweek_core/
ordering.rs

1pub type Result<T> = std::result::Result<T, String>;
2
3pub trait Ordering {
4    fn get_keys(&self) -> Vec<Option<String>>;
5    // fn get_ordering_key_of_posision(&self, i: usize) -> Result<Option<String>>;
6    fn set_ordering_key_of_posision(&mut self, i: usize, key: Option<String>) -> Result<()>;
7    // fn get_posision_of_id(&self, id: i32) -> Result<usize>;
8    fn get_ordering_key_of_id(&self, id: i32) -> Option<Option<String>>;
9    fn new_ordering_finished(&self);
10
11    fn get_key_pos_of_id(&self, id: i32) -> Option<(String, usize)> {
12        let ordering_key = self.get_ordering_key_of_id(id)??;
13        let pos = self
14            .get_keys()
15            .iter()
16            .position(|key| *key == Some(ordering_key.clone()))?;
17        Some((ordering_key, pos))
18    }
19
20    fn needs_reordering(&self) -> bool {
21        let mut fix = false;
22        for item_key in self.get_keys() {
23            if item_key.is_none() {
24                fix = true;
25                break;
26            }
27        }
28        fix
29    }
30
31    fn new_ordering(&mut self) {
32        println!("reordering all items...");
33        let mut top = String::from("");
34        let bot = String::from("");
35        let mut i: usize = 0;
36        loop {
37            let new_key = midstring::mid_string(&top, &bot);
38            if self
39                .set_ordering_key_of_posision(i, Some(new_key.clone()))
40                .is_err()
41            {
42                break;
43            }
44            i += 1;
45            top = new_key;
46        }
47        self.new_ordering_finished();
48    }
49
50    fn check_and_fix_ordering(&mut self) {
51        let fix = self.needs_reordering();
52        if fix {
53            // println!("fixing some invalid ordering keys...");
54            // println!("items before ordering: {:?}", self);
55            self.new_ordering();
56            // println!("items after ordering: {:?}", self);
57        } else {
58            // println!("ordering seems ok");
59        }
60    }
61
62    fn get_new_ordering_key(&self, after_id: Option<i32>) -> String {
63        // after_id: None: canculate based on adding new key after the last item
64        // after_id: Some: canculate based on adding new key after the provided id
65        let last_key = self
66            .get_keys()
67            .last()
68            .map(|x| x.to_owned())
69            .unwrap_or(None)
70            .unwrap_or("".to_string());
71        if let Some(id) = after_id {
72            self.generate_key_for_after_id(id).unwrap_or("".into())
73        } else {
74            midstring::mid_string(&last_key, "")
75        }
76    }
77
78    fn generate_key_for_after_id(&self, id: i32) -> Result<String> {
79        let (key, pos) = self
80            .get_key_pos_of_id(id)
81            .ok_or("invalid id or key".to_string())?;
82        let next_key = self
83            .get_keys()
84            .get(pos + 1)
85            .map(|x| x.to_owned())
86            .unwrap_or(Some(String::new()))
87            .ok_or("invalid_key".to_string())?
88            .clone();
89        Ok(midstring::mid_string(&key, &next_key))
90    }
91
92    fn generate_key_for_move_up_with_id(&mut self, id: i32) -> Result<String> {
93        let key = self
94            .get_ordering_key_of_id(id)
95            .ok_or("invalid id".to_string())?
96            .ok_or("invalid key".to_string())?;
97        self.generate_key_for_move_up_with_key(key)
98    }
99
100    fn generate_key_for_move_up_with_key(&mut self, key: String) -> Result<String> {
101        // reordering logic:
102        // get the ordering-keys of two previous items
103        // generate new key and update
104        let prev_key;
105        let next_key;
106        let keys = self.get_keys();
107        if let Some(pos) = keys.iter().position(|k| *k == Some(key.clone())) {
108            if pos == 0 {
109                // already first item
110                return Ok(keys[pos].clone().unwrap_or("".to_string()));
111            } else if pos == 1 {
112                prev_key = "".to_string();
113                next_key = keys[pos - 1].clone().unwrap_or("".to_string());
114            } else {
115                // pos > 2
116                prev_key = keys[pos - 2].clone().unwrap_or("".to_string());
117                next_key = keys[pos - 1].clone().unwrap_or("".to_string());
118            }
119            Ok(midstring::mid_string(&prev_key, &next_key))
120        } else {
121            Err("invalid key".to_string())
122        }
123    }
124
125    fn generate_key_for_move_down_with_id(&mut self, id: i32) -> Result<String> {
126        let key = self
127            .get_ordering_key_of_id(id)
128            .ok_or("invalid id".to_string())?
129            .ok_or("invalid key".to_string())?;
130        self.generate_key_for_move_down_with_key(key)
131    }
132
133    fn generate_key_for_move_down_with_key(&mut self, key: String) -> Result<String> {
134        // reordering logic:
135        // get the ordering-keys of two next items
136        // generate new key and update
137        let prev_key;
138        let next_key;
139        let keys = self.get_keys();
140        let length = keys.len();
141        if let Some(pos) = keys.iter().position(|k| *k == Some(key.clone())) {
142            if pos == length - 1 {
143                // already last item
144                return Ok(keys[pos].clone().unwrap_or("".to_string()));
145            } else if pos == length - 2 {
146                prev_key = keys[pos + 1].clone().unwrap_or("".to_string());
147                next_key = "".to_string();
148            } else {
149                // pos < length - 2
150                prev_key = keys[pos + 1].clone().unwrap_or("".to_string());
151                next_key = keys[pos + 2].clone().unwrap_or("".to_string());
152            }
153            Ok(midstring::mid_string(&prev_key, &next_key))
154        } else {
155            Err("invalid key".to_string())
156        }
157    }
158
159    fn generate_key_for_reordering_item_index(
160        &self,
161        src_index: usize,
162        dest_index: usize,
163    ) -> Result<String> {
164        let keys = self.get_keys();
165
166        // Validate indices
167        if src_index >= keys.len() || dest_index >= keys.len() {
168            return Err("Index out of bounds".into());
169        }
170        if src_index == dest_index {
171            return Err("Source and destination indices are the same".into());
172        }
173
174        if dest_index == 0 {
175            // Moving to the very top
176            let next_key = keys[0].as_ref().ok_or("Invalid key at index 0")?;
177            return Ok(midstring::mid_string("", next_key));
178        }
179
180        if dest_index == keys.len() - 1 {
181            // Moving to the very bottom
182            let prev_key = keys[dest_index]
183                .as_ref()
184                .ok_or("Invalid key at last index")?;
185            return Ok(midstring::mid_string(prev_key, ""));
186        }
187
188        // For all other cases
189        let prev_key;
190        let next_key;
191        if dest_index < src_index {
192            prev_key = keys[dest_index - 1]
193                .as_ref()
194                .ok_or("Invalid previous key")?;
195            next_key = keys[dest_index].as_ref().ok_or("Invalid next key")?;
196        } else {
197            prev_key = keys[dest_index].as_ref().ok_or("Invalid previous key")?;
198            next_key = keys[dest_index + 1].as_ref().ok_or("Invalid next key")?;
199        }
200
201        Ok(midstring::mid_string(prev_key, next_key))
202    }
203
204    // fn generate_key_for_reordering_item_index(
205    //     &mut self,
206    //     src_index: usize,
207    //     dest_index: usize,
208    // ) -> Result<String> {
209    //     // generate new key and update
210    //     let prev_key;
211    //     let next_key;
212    //     let keys = self.get_keys();
213    //     let dest_key = keys.get(dest_index)??;
214    //     let before_dest_key = keys.get(dest_index - 1).unwrap_or("".to_string().clone());
215    //     let after_dest_key = keys.get(dest_index + 1).unwrap_or("".to_string().clone());
216    //     if dest_index < src_index {
217    //         // moving up
218    //         Ok(midstring::mid_string(before_dest_key, dest_key))
219    //     } else if dest_index > src_index {
220    //         // moving down
221    //         Ok(midstring::mid_string(dest_key, after_dest_key))
222    //     } else {
223    //         Err("failed generating reordering item index key".into())
224    //     }
225    // }
226}