bms_rs/bms/command/channel/
converter.rs1use std::collections::HashMap;
4
5use super::{Key, PlayerSide};
6use crate::bms::rng::JavaRandom;
7
8pub trait KeyConverter {
13 fn convert(&mut self, key: Key) -> Key;
15}
16
17pub trait PlayerSideKeyConverter {
22 fn convert(&mut self, pair: (PlayerSide, Key)) -> (PlayerSide, Key);
24}
25
26impl KeyMappingConvertMirror {
27 #[must_use]
29 pub const fn new(keys: Vec<Key>) -> Self {
30 Self { keys }
31 }
32}
33
34#[derive(Debug, Clone, PartialEq, Eq, Hash)]
36pub struct KeyMappingConvertMirror {
37 keys: Vec<Key>,
39}
40
41impl KeyConverter for KeyMappingConvertMirror {
42 fn convert(&mut self, key: Key) -> Key {
43 self.keys
44 .iter()
45 .position(|k| k == &key)
46 .and_then(|position| {
47 let mirror_index = self.keys.len().saturating_sub(position + 1);
48 self.keys.get(mirror_index)
49 })
50 .copied()
51 .unwrap_or(key)
52 }
53}
54
55#[derive(Debug, Clone)]
57pub struct KeyMappingConvertLaneRotateShuffle {
58 arrangement: HashMap<Key, Key>,
60}
61
62impl KeyMappingConvertLaneRotateShuffle {
63 #[must_use]
65 pub fn new(keys: &[Key], seed: i64) -> Self {
66 Self {
67 arrangement: Self::make_random(keys, seed),
68 }
69 }
70
71 fn make_random(keys: &[Key], seed: i64) -> HashMap<Key, Key> {
72 let mut rng = JavaRandom::new(seed);
73 let mut result: HashMap<Key, Key> = HashMap::new();
74 if keys.is_empty() {
75 return result;
76 }
77
78 let inc = rng.next_int_bound(2) == 1;
79 let start = rng.next_int_bound(keys.len() as i32 - 1) as usize + if inc { 1 } else { 0 };
80
81 let mut rlane = start;
82 for lane in 0..keys.len() {
83 result.insert(keys[lane], keys[rlane]);
84 rlane = if inc {
85 (rlane + 1) % keys.len()
86 } else {
87 (rlane + keys.len() - 1) % keys.len()
88 };
89 }
90 result
91 }
92}
93
94impl KeyConverter for KeyMappingConvertLaneRotateShuffle {
95 fn convert(&mut self, key: Key) -> Key {
96 self.arrangement.get(&key).copied().unwrap_or(key)
97 }
98}
99
100#[derive(Debug, Clone)]
104pub struct KeyMappingConvertLaneRandomShuffle {
105 arrangement: HashMap<Key, Key>,
107}
108
109impl KeyMappingConvertLaneRandomShuffle {
110 #[must_use]
112 pub fn new(keys: &[Key], seed: i64) -> Self {
113 Self {
114 arrangement: Self::make_random(keys, seed),
115 }
116 }
117
118 fn make_random(keys: &[Key], seed: i64) -> HashMap<Key, Key> {
119 let mut rng = JavaRandom::new(seed);
120 let mut result: HashMap<Key, Key> = HashMap::new();
121 if keys.is_empty() {
122 return result;
123 }
124
125 let mut l = keys.to_vec();
126 for &lane in keys {
127 let r = rng.next_int_bound(l.len() as i32) as usize;
128 result.insert(lane, l[r]);
129 l.remove(r);
130 }
131
132 result
133 }
134}
135
136impl KeyConverter for KeyMappingConvertLaneRandomShuffle {
137 fn convert(&mut self, key: Key) -> Key {
138 self.arrangement.get(&key).copied().unwrap_or(key)
139 }
140}
141
142#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
144pub struct KeyMappingConvertFlip;
145
146impl PlayerSideKeyConverter for KeyMappingConvertFlip {
147 fn convert(&mut self, pair: (PlayerSide, Key)) -> (PlayerSide, Key) {
148 let (side, key) = pair;
149 let flipped_side = match side {
150 PlayerSide::Player1 => PlayerSide::Player2,
151 PlayerSide::Player2 => PlayerSide::Player1,
152 };
153 (flipped_side, key)
154 }
155}
156
157#[cfg(test)]
158mod channel_mode_tests {
159 use super::*;
160
161 #[test]
162 fn test_key_converter_mirror() {
163 let mut converter =
165 KeyMappingConvertMirror::new(vec![Key::Key(1), Key::Key(2), Key::Key(3)]);
166
167 let keys = vec![
169 Key::Key(1),
170 Key::Key(2),
171 Key::Key(3),
172 Key::Key(4),
173 Key::Key(5),
174 ];
175
176 let expected_keys = vec![
178 Key::Key(3),
179 Key::Key(2),
180 Key::Key(1),
181 Key::Key(4),
182 Key::Key(5),
183 ];
184
185 let result: Vec<_> = keys.into_iter().map(|key| converter.convert(key)).collect();
186 assert_eq!(result, expected_keys);
187 }
188
189 fn parse_examples(examples_str: &[&str]) -> Vec<(Vec<usize>, i64)> {
191 examples_str
192 .iter()
193 .map(|s| {
194 let v = s.split_whitespace().collect::<Vec<_>>();
195 let [list, seed] = v.as_slice() else {
196 println!("{:?}", v);
197 panic!("Invalid input");
198 };
199 let list = list
200 .chars()
201 .map(|c| c.to_digit(10).unwrap() as usize)
202 .collect::<Vec<_>>();
203 let seed = seed.parse::<i64>().unwrap();
204 (list, seed)
205 })
206 .collect::<Vec<_>>()
207 }
208
209 fn key_to_value(key: Key) -> usize {
211 match key {
212 Key::Key(n) => n as usize,
213 Key::Scratch(n) => n as usize + 10,
214 Key::FootPedal => 20,
215 Key::FreeZone => 21,
216 }
217 }
218
219 fn run_shuffle_test_case<T>(
221 test_case_idx: usize,
222 expected_list: &[usize],
223 seed: i64,
224 keys: &[Key],
225 mut converter: T,
226 ) where
227 T: KeyConverter,
228 {
229 println!("Test case {}: seed = {}", test_case_idx, seed);
230
231 let result_values = keys
232 .iter()
233 .map(|&key| key_to_value(converter.convert(key)))
234 .collect::<Vec<_>>();
235
236 println!(" Expected: {:?}", expected_list);
237 println!(" Got: {:?}", result_values);
238 println!(" Match: {}", result_values == expected_list);
239
240 if result_values != expected_list {
241 println!(" FAILED!");
242 }
243 println!();
244 }
245
246 #[test]
250 fn test_random_shuffle() {
251 let examples_str = [
252 "1234567 4752",
253 "1234576 2498",
254 "4372615 12728",
255 "4372651 9734",
256 "4375126 139",
257 ];
258 let examples = parse_examples(&examples_str);
259 let init_keys = [
260 Key::Key(1),
261 Key::Key(2),
262 Key::Key(3),
263 Key::Key(4),
264 Key::Key(5),
265 Key::Key(6),
266 Key::Key(7),
267 ];
268
269 for (i, (list, seed)) in examples.iter().enumerate() {
270 let rnd = KeyMappingConvertLaneRandomShuffle::new(&init_keys, *seed);
271 run_shuffle_test_case(i, list, *seed, &init_keys, rnd);
272 }
273 }
274
275 #[test]
277 fn test_lane_rotate_shuffle() {
278 let examples_str = ["1765432 3581225"];
279 let examples = parse_examples(&examples_str);
280 let init_keys = [
281 Key::Key(1),
282 Key::Key(2),
283 Key::Key(3),
284 Key::Key(4),
285 Key::Key(5),
286 Key::Key(6),
287 Key::Key(7),
288 ];
289
290 for (i, (list, seed)) in examples.iter().enumerate() {
291 let rnd = KeyMappingConvertLaneRotateShuffle::new(&init_keys, *seed);
292 run_shuffle_test_case(i, list, *seed, &init_keys, rnd);
293 }
294 }
295
296 #[test]
298 fn test_player_side_key_converter_flip() {
299 let mut converter = KeyMappingConvertFlip;
300
301 let test_cases = vec![
303 (PlayerSide::Player1, Key::Key(1)),
304 (PlayerSide::Player2, Key::Key(2)),
305 (PlayerSide::Player1, Key::Scratch(1)),
306 (PlayerSide::Player2, Key::FreeZone),
307 ];
308
309 let input_pairs: Vec<_> = test_cases.clone();
311
312 let expected_pairs: Vec<_> = test_cases
313 .iter()
314 .map(|(side, key)| {
315 let flipped_side = match side {
316 PlayerSide::Player1 => PlayerSide::Player2,
317 PlayerSide::Player2 => PlayerSide::Player1,
318 };
319 (flipped_side, *key)
320 })
321 .collect();
322
323 let result: Vec<_> = input_pairs
324 .iter()
325 .map(|&pair| converter.convert(pair))
326 .collect();
327 assert_eq!(result, expected_pairs);
328
329 let result2: Vec<_> = result.iter().map(|&pair| converter.convert(pair)).collect();
330 assert_eq!(result2, input_pairs);
331 }
332}