thisweek_core/
ordering.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
pub type Result<T> = std::result::Result<T, String>;

pub trait Ordering {
    fn get_keys(&self) -> Vec<Option<String>>;
    // fn get_ordering_key_of_posision(&self, i: usize) -> Result<Option<String>>;
    fn set_ordering_key_of_posision(&mut self, i: usize, key: Option<String>) -> Result<()>;
    // fn get_posision_of_id(&self, id: i32) -> Result<usize>;
    fn get_ordering_key_of_id(&self, id: i32) -> Option<Option<String>>;
    fn new_ordering_finished(&self);

    fn get_key_pos_of_id(&self, id: i32) -> Option<(String, usize)> {
        let ordering_key = self.get_ordering_key_of_id(id)??;
        let pos = self
            .get_keys()
            .iter()
            .position(|key| *key == Some(ordering_key.clone()))?;
        Some((ordering_key, pos))
    }

    fn needs_reordering(&self) -> bool {
        let mut fix = false;
        for item_key in self.get_keys() {
            if item_key.is_none() {
                fix = true;
                break;
            }
        }
        fix
    }

    fn new_ordering(&mut self) {
        println!("reordering all items...");
        let mut top = String::from("");
        let bot = String::from("");
        let mut i: usize = 0;
        loop {
            let new_key = midstring::mid_string(&top, &bot);
            if let Err(_) = self.set_ordering_key_of_posision(i, Some(new_key.clone())) {
                break;
            }
            i += 1;
            top = new_key;
        }
        self.new_ordering_finished();
    }

    fn check_and_fix_ordering(&mut self) {
        let fix = self.needs_reordering();
        if fix {
            // println!("fixing some invalid ordering keys...");
            // println!("items before ordering: {:?}", self);
            self.new_ordering();
            // println!("items after ordering: {:?}", self);
        } else {
            // println!("ordering seems ok");
        }
    }

    fn get_new_ordering_key(&self, after_id: Option<i32>) -> String {
        // after_id: None: canculate based on adding new key after the last item
        // after_id: Some: canculate based on adding new key after the provided id
        let last_key = self
            .get_keys()
            .last()
            .map(|x| x.to_owned())
            .unwrap_or(None)
            .unwrap_or("".to_string());
        if let Some(id) = after_id {
            self.generate_key_for_after_id(id).unwrap_or("".into())
        } else {
            midstring::mid_string(&last_key, "")
        }
    }

    fn generate_key_for_after_id(&self, id: i32) -> Result<String> {
        let (key, pos) = self
            .get_key_pos_of_id(id)
            .ok_or("invalid id or key".to_string())?;
        let next_key = self
            .get_keys()
            .get(pos + 1)
            .map(|x| x.to_owned())
            .unwrap_or(Some(String::new()))
            .ok_or("invalid_key".to_string())?
            .clone();
        Ok(midstring::mid_string(&key, &next_key))
    }

    fn generate_key_for_move_up_with_id(&mut self, id: i32) -> Result<String> {
        let key = self
            .get_ordering_key_of_id(id)
            .ok_or("invalid id".to_string())?
            .ok_or("invalid key".to_string())?;
        self.generate_key_for_move_up_with_key(key)
    }

    fn generate_key_for_move_up_with_key(&mut self, key: String) -> Result<String> {
        // reordering logic:
        // get the ordering-keys of two previous items
        // generate new key and update
        let prev_key;
        let next_key;
        let keys = self.get_keys();
        if let Some(pos) = keys.iter().position(|k| *k == Some(key.clone())) {
            if pos == 0 {
                // already first item
                return Ok(keys[pos].clone().unwrap_or("".to_string()));
            } else if pos == 1 {
                prev_key = "".to_string();
                next_key = keys[pos - 1].clone().unwrap_or("".to_string());
            } else {
                // pos > 2
                prev_key = keys[pos - 2].clone().unwrap_or("".to_string());
                next_key = keys[pos - 1].clone().unwrap_or("".to_string());
            }
            Ok(midstring::mid_string(&prev_key, &next_key))
        } else {
            Err("invalid key".to_string())
        }
    }

    fn generate_key_for_move_down_with_id(&mut self, id: i32) -> Result<String> {
        let key = self
            .get_ordering_key_of_id(id)
            .ok_or("invalid id".to_string())?
            .ok_or("invalid key".to_string())?;
        self.generate_key_for_move_down_with_key(key)
    }

    fn generate_key_for_move_down_with_key(&mut self, key: String) -> Result<String> {
        // reordering logic:
        // get the ordering-keys of two next items
        // generate new key and update
        let prev_key;
        let next_key;
        let keys = self.get_keys();
        let length = keys.len();
        if let Some(pos) = keys.iter().position(|k| *k == Some(key.clone())) {
            if pos == length - 1 {
                // already last item
                return Ok(keys[pos].clone().unwrap_or("".to_string()));
            } else if pos == length - 2 {
                prev_key = keys[pos + 1].clone().unwrap_or("".to_string());
                next_key = "".to_string();
            } else {
                // pos < length - 2
                prev_key = keys[pos + 1].clone().unwrap_or("".to_string());
                next_key = keys[pos + 2].clone().unwrap_or("".to_string());
            }
            Ok(midstring::mid_string(&prev_key, &next_key))
        } else {
            Err("invalid key".to_string())
        }
    }

    fn generate_key_for_reordering_item_index(
        &self,
        src_index: usize,
        dest_index: usize,
    ) -> Result<String> {
        let keys = self.get_keys();

        // Validate indices
        if src_index >= keys.len() || dest_index >= keys.len() {
            return Err("Index out of bounds".into());
        }
        if src_index == dest_index {
            return Err("Source and destination indices are the same".into());
        }

        if dest_index == 0 {
            // Moving to the very top
            let next_key = keys[0].as_ref().ok_or("Invalid key at index 0")?;
            return Ok(midstring::mid_string("", next_key));
        }

        if dest_index == keys.len() - 1 {
            // Moving to the very bottom
            let prev_key = keys[dest_index]
                .as_ref()
                .ok_or("Invalid key at last index")?;
            return Ok(midstring::mid_string(prev_key, ""));
        }

        // For all other cases
        let prev_key;
        let next_key;
        if dest_index < src_index {
            prev_key = keys[dest_index - 1]
                .as_ref()
                .ok_or("Invalid previous key")?;
            next_key = keys[dest_index].as_ref().ok_or("Invalid next key")?;
        } else {
            prev_key = keys[dest_index].as_ref().ok_or("Invalid previous key")?;
            next_key = keys[dest_index + 1].as_ref().ok_or("Invalid next key")?;
        }

        Ok(midstring::mid_string(prev_key, next_key))
    }

    // fn generate_key_for_reordering_item_index(
    //     &mut self,
    //     src_index: usize,
    //     dest_index: usize,
    // ) -> Result<String> {
    //     // generate new key and update
    //     let prev_key;
    //     let next_key;
    //     let keys = self.get_keys();
    //     let dest_key = keys.get(dest_index)??;
    //     let before_dest_key = keys.get(dest_index - 1).unwrap_or("".to_string().clone());
    //     let after_dest_key = keys.get(dest_index + 1).unwrap_or("".to_string().clone());
    //     if dest_index < src_index {
    //         // moving up
    //         Ok(midstring::mid_string(before_dest_key, dest_key))
    //     } else if dest_index > src_index {
    //         // moving down
    //         Ok(midstring::mid_string(dest_key, after_dest_key))
    //     } else {
    //         Err("failed generating reordering item index key".into())
    //     }
    // }
}