Skip to main content

manabrew_engine/card/
card_changed_words.rs

1//! Changed-word replacement table (Java parity: `CardChangedWords`).
2
3use std::collections::{BTreeMap, HashMap};
4
5#[derive(Debug, Clone)]
6struct WordHolder {
7    old_word: String,
8    new_word: String,
9    clear: bool,
10}
11
12impl WordHolder {
13    fn clear_entry() -> Self {
14        Self {
15            old_word: String::new(),
16            new_word: String::new(),
17            clear: true,
18        }
19    }
20
21    fn replacement(old_word: &str, new_word: &str) -> Self {
22        Self {
23            old_word: old_word.to_string(),
24            new_word: new_word.to_string(),
25            clear: false,
26        }
27    }
28}
29
30#[derive(Debug, Clone, Default)]
31pub struct CardChangedWords {
32    map: BTreeMap<(u64, u64), WordHolder>,
33    is_dirty: bool,
34    result_cache: HashMap<String, String>,
35}
36
37impl CardChangedWords {
38    pub fn add_empty(&mut self, timestamp: u64, static_id: u64) -> u64 {
39        self.map
40            .insert((timestamp, static_id), WordHolder::clear_entry());
41        self.is_dirty = true;
42        timestamp
43    }
44
45    pub fn add(
46        &mut self,
47        timestamp: u64,
48        static_id: u64,
49        original_word: &str,
50        new_word: &str,
51    ) -> u64 {
52        self.map.insert(
53            (timestamp, static_id),
54            WordHolder::replacement(original_word, new_word),
55        );
56        self.is_dirty = true;
57        timestamp
58    }
59
60    pub fn remove(&mut self, timestamp: u64, static_id: u64) -> bool {
61        let removed = self.map.remove(&(timestamp, static_id)).is_some();
62        if removed {
63            self.is_dirty = true;
64        }
65        removed
66    }
67
68    pub fn clear(&mut self) {
69        self.map.clear();
70        self.result_cache.clear();
71        self.is_dirty = true;
72    }
73
74    pub fn resolved_map(&mut self) -> &HashMap<String, String> {
75        if self.is_dirty {
76            self.result_cache.clear();
77            for holder in self.map.values() {
78                if holder.clear {
79                    self.result_cache.clear();
80                    continue;
81                }
82
83                let replacements: Vec<(String, String)> = self
84                    .result_cache
85                    .iter()
86                    .filter(|(_, v)| v.as_str() == holder.old_word)
87                    .map(|(k, _)| (k.clone(), holder.new_word.clone()))
88                    .collect();
89                for (k, v) in replacements {
90                    self.result_cache.insert(k, v);
91                }
92
93                self.result_cache
94                    .insert(holder.old_word.clone(), holder.new_word.clone());
95            }
96            self.is_dirty = false;
97        }
98        &self.result_cache
99    }
100}