1use std::time::SystemTime;
2
3use rand::random;
4
5pub use types::Face;
6use utils::rot;
7
8use crate::utils::make_svg;
9
10mod utils;
11mod types;
12mod resvg;
13
14const CUBE_OPERATIONS_CODE: [char; 12] = [
15 'F', 'f', 'B', 'b', 'L', 'l', 'R', 'r', 'U', 'u', 'D', 'd'];
16
17pub struct Cube {
18 pub start_time: u128,
19 pub last_step: String,
20 pub front: Face,
21 pub back: Face,
22 pub left: Face,
23 pub right: Face,
24 pub up: Face,
25 pub down: Face,
26}
27impl Cube {
28 pub fn new() -> Cube {
29 let start_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_millis();
30 let last_step = String::from("");
31 Cube {
32 start_time,
33 last_step,
34 front: [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
35 back: [[10, 11, 12], [13, 14, 15], [16, 17, 18]],
36 left: [[19, 20, 21], [22, 23, 24], [25, 26, 27]],
37 right: [[28, 29, 30], [31, 32, 33], [34, 35, 36]],
38 up: [[37, 38, 39], [40, 41, 42], [43, 44, 45]],
39 down: [[46, 47, 48], [49, 50, 51], [52, 53, 54]],
40 }
41 }
42 pub fn reset(&mut self) {
43 self.start_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_millis();
44 self.front = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
45 self.back = [[10, 11, 12], [13, 14, 15], [16, 17, 18]];
46 self.left = [[19, 20, 21], [22, 23, 24], [25, 26, 27]];
47 self.right = [[28, 29, 30], [31, 32, 33], [34, 35, 36]];
48 self.up = [[37, 38, 39], [40, 41, 42], [43, 44, 45]];
49 self.down = [[46, 47, 48], [49, 50, 51], [52, 53, 54]];
50 }
51
52 fn rot_front(&mut self, rev: bool) {
53 let temp_left = self.left;
54 let temp_up = self.up[2];
55 let temp_right = self.right;
56 self.front = rot(self.front, rev);
57 let temp_down = self.down[0];
58 if rev {
59 for i in 0..3 {
60 self.left[i][2] = temp_up[2 - i];
61 self.right[i][0] = temp_down[2 - i];
62 self.up[2][i] = temp_right[i][0];
63 self.down[0][i] = temp_left[i][2];
64 }
65 } else {
66 for i in 0..3 {
67 self.left[i][2] = temp_down[i];
68 self.right[i][0] = temp_up[i];
69 self.up[2][i] = temp_left[2 - i][2];
70 self.down[0][i] = temp_right[2 - i][0];
71 }
72 }
73 }
74 fn rot_back(&mut self, rev: bool) {
75 let temp_left = self.left;
76 let temp_up = self.up[0];
77 let temp_right = self.right;
78 self.back = rot(self.back, rev);
79 let temp_down = self.down[2];
80 if rev {
81 for i in 0..3 {
82 self.left[i][0] = temp_down[i];
83 self.right[i][2] = temp_up[i];
84 self.up[0][i] = temp_left[2 - i][0];
85 self.down[2][i] = temp_right[2 - i][2];
86 }
87 } else {
88 for i in 0..3 {
89 self.left[i][0] = temp_up[2 - i];
90 self.right[i][2] = temp_down[2 - i];
91 self.up[0][i] = temp_right[i][2];
92 self.down[2][i] = temp_left[i][0];
93 }
94 }
95 }
96 fn rot_left(&mut self, rev: bool) {
97 let temp_front = self.front;
98 let temp_up = self.up;
99 let temp_back = self.back;
100 let temp_down = self.down;
101 self.left = rot(self.left, rev);
102 if rev {
103 for i in 0..3 {
104 self.front[i][0] = temp_down[i][0];
105 self.back[i][2] = temp_up[2 - i][0];
106 self.down[i][0] = temp_back[2 - i][2];
107 self.up[i][0] = temp_front[i][0];
108 }
109 } else {
110 for i in 0..3 {
111 self.front[i][0] = temp_up[i][0];
112 self.up[i][0] = temp_back[2 - i][2];
113 self.back[i][2] = temp_down[2 - i][0];
114 self.down[i][0] = temp_front[i][0];
115 }
116 }
117 }
118 fn rot_right(&mut self, rev: bool) {
119 let temp_front = self.front;
120 let temp_up = self.up;
121 let temp_back = self.back;
122 let temp_down = self.down;
123 self.right = rot(self.right, rev);
124 if rev {
125 for i in 0..3 {
126 self.front[i][2] = temp_up[i][2];
127 self.back[i][0] = temp_down[2 - i][2];
128 self.down[i][2] = temp_front[i][2];
129 self.up[i][2] = temp_back[2 - i][0];
130 }
131 } else {
132 for i in 0..3 {
133 self.front[i][2] = temp_down[i][2];
134 self.up[i][2] = temp_front[i][2];
135 self.back[i][0] = temp_up[2 - i][2];
136 self.down[i][2] = temp_back[2 - i][0];
137 }
138 }
139 }
140 fn rot_up(&mut self, rev: bool) {
141 let temp_front = self.front;
142 let temp_left = self.left;
143 let temp_back = self.back;
144 let temp_right = self.right;
145 self.up = rot(self.up, rev);
146 if rev {
147 for i in 0..3 {
148 self.front[0][i] = temp_left[0][i];
149 self.left[0][i] = temp_back[0][i];
150 self.back[0][i] = temp_right[0][i];
151 self.right[0][i] = temp_front[0][i];
152 }
153 } else {
154 for i in 0..3 {
155 self.front[0][i] = temp_right[0][i];
156 self.left[0][i] = temp_front[0][i];
157 self.back[0][i] = temp_left[0][i];
158 self.right[0][i] = temp_back[0][i];
159 }
160 }
161 }
162 fn rot_down(&mut self, rev: bool) {
163 let temp_front = self.front;
164 let temp_left = self.left;
165 let temp_back = self.back;
166 let temp_right = self.right;
167 self.down = rot(self.down, rev);
168 if rev {
169 for i in 0..3 {
170 self.front[2][i] = temp_right[2][i];
171 self.left[2][i] = temp_front[2][i];
172 self.back[2][i] = temp_left[2][i];
173 self.right[2][i] = temp_back[2][i];
174 }
175 } else {
176 for i in 0..3 {
177 self.front[2][i] = temp_left[2][i];
178 self.left[2][i] = temp_back[2][i];
179 self.back[2][i] = temp_right[2][i];
180 self.right[2][i] = temp_front[2][i];
181 }
182 }
183 }
184
185 pub fn is_solved(&self) -> bool {
186 for i in 0..3 {
187 for j in 0..3 {
188 match self.front[i][j] {
189 1..=9 => (),
190 _ => return false,
191 }
192 match self.back[i][j] {
193 10..=18 => (),
194 _ => return false,
195 }
196 match self.left[i][j] {
197 19..=27 => (),
198 _ => return false,
199 }
200 match self.right[i][j] {
201 28..=36 => (),
202 _ => return false,
203 }
204 match self.up[i][j] {
205 37..=45 => (),
206 _ => return false,
207 }
208 match self.down[i][j] {
209 46..=54 => (),
210 _ => return false,
211 }
212 }
213 }
214 true
215 }
216
217 pub fn rot(&mut self, operation: char) {
218 match operation {
219 'F' => self.rot_front(true),
220 'f' => self.rot_front(false),
221 'B' => self.rot_back(true),
222 'b' => self.rot_back(false),
223 'L' => self.rot_left(true),
224 'l' => self.rot_left(false),
225 'R' => self.rot_right(true),
226 'r' => self.rot_right(false),
227 'U' => self.rot_up(true),
228 'u' => self.rot_up(false),
229 'D' => self.rot_down(true),
230 'd' => self.rot_down(false),
231 _ => (),
232 }
233 }
234
235 pub fn scramble(&mut self, steps: u32) {
236 for _ in 0..steps {
237 let operation = random::<u8>() % 12;
238 self.rot(CUBE_OPERATIONS_CODE[operation as usize]);
239 }
240 }
241
242 pub fn rots(&mut self, operations: &str) {
243 self.last_step.clear();
244 for operation in operations.chars() {
245 if CUBE_OPERATIONS_CODE.contains(&operation) {
246 self.rot(operation);
247 self.last_step.push(operation);
248 }
249 }
250 }
251
252 pub fn get_svg(&self) -> String {
253 let cube: [[[i8; 3]; 3]; 9] = [self.left, self.front, self.up, self.down, self.right, self.back, self.front, self.up, self.right];
254 make_svg(cube)
255 }
256
257 pub fn get_svg_base64_png(&self) -> String {
258 let svg = self.get_svg();
259 resvg::render(svg)
260 }
261}
262
263#[cfg(test)]
264mod tests {
265 use super::*;
266
267 #[test]
268 fn it_works_rot_front() {
269 let mut cube = Cube::new();
270 cube.rot_front(false);
271
272 assert_eq!(cube.left, [
277 [19, 20, 46],
278 [22, 23, 47],
279 [25, 26, 48]]);
280 assert_eq!(cube.up, [
285 [37, 38, 39],
286 [40, 41, 42],
287 [27, 24, 21]]);
288 assert_eq!(cube.right, [
293 [43, 29, 30],
294 [44, 32, 33],
295 [45, 35, 36]]);
296 assert_eq!(cube.down, [
301 [34, 31, 28],
302 [49, 50, 51],
303 [52, 53, 54]]);
304 }
305 #[test]
306 fn it_works_rot_front_rev() {
307 let mut cube = Cube::new();
308 cube.rot_front(true);
309 assert_eq!(cube.left, [
314 [19, 20, 45],
315 [22, 23, 44],
316 [25, 26, 43]]);
317 assert_eq!(cube.up, [
322 [37, 38, 39],
323 [40, 41, 42],
324 [28, 31, 34]]);
325 assert_eq!(cube.right, [
330 [48, 29, 30],
331 [47, 32, 33],
332 [46, 35, 36]]);
333 assert_eq!(cube.down, [
338 [21, 24, 27],
339 [49, 50, 51],
340 [52, 53, 54]]);
341 }
342
343 #[test]
344 fn it_works_rot_back() {
345 let mut cube = Cube::new();
346 cube.rot_back(false);
347 assert_eq!(cube.left, [
352 [39, 20, 21],
353 [38, 23, 24],
354 [37, 26, 27]]);
355 assert_eq!(cube.up, [
360 [30, 33, 36],
361 [40, 41, 42],
362 [43, 44, 45]]);
363 assert_eq!(cube.right, [
368 [28, 29, 54],
369 [31, 32, 53],
370 [34, 35, 52]]);
371 assert_eq!(cube.down, [
376 [46, 47, 48],
377 [49, 50, 51],
378 [19, 22, 25]]);
379 }
380 #[test]
381 fn it_works_rot_back_rev() {
382 let mut cube = Cube::new();
383 cube.rot_back(true);
384 assert_eq!(cube.left, [
389 [52, 20, 21],
390 [53, 23, 24],
391 [54, 26, 27]]);
392 assert_eq!(cube.up, [
397 [25, 22, 19],
398 [40, 41, 42],
399 [43, 44, 45]]);
400 assert_eq!(cube.right, [
405 [28, 29, 37],
406 [31, 32, 38],
407 [34, 35, 39]]);
408 assert_eq!(cube.down, [
413 [46, 47, 48],
414 [49, 50, 51],
415 [36, 33, 30]]);
416 }
417 #[test]
418 fn it_works_rot_left() {
419 let mut cube = Cube::new();
420 cube.rot_left(false);
421 assert_eq!(cube.up, [
426 [18, 38, 39],
427 [15, 41, 42],
428 [12, 44, 45]]);
429 assert_eq!(cube.down, [
434 [1, 47, 48],
435 [4, 50, 51],
436 [7, 53, 54]]);
437 assert_eq!(cube.front, [
442 [37, 2, 3],
443 [40, 5, 6],
444 [43, 8, 9]]);
445 assert_eq!(cube.back, [
450 [10, 11, 52],
451 [13, 14, 49],
452 [16, 17, 46]]);
453 }
454
455 #[test]
456 fn it_works_rot_left_rev() {
457 let mut cube = Cube::new();
458 cube.rot_left(true);
459 assert_eq!(cube.up, [
464 [1, 38, 39],
465 [4, 41, 42],
466 [7, 44, 45]]);
467 assert_eq!(cube.down, [
472 [18, 47, 48],
473 [15, 50, 51],
474 [12, 53, 54]]);
475 assert_eq!(cube.front, [
480 [46, 2, 3],
481 [49, 5, 6],
482 [52, 8, 9]]);
483 assert_eq!(cube.back, [
488 [10, 11, 43],
489 [13, 14, 40],
490 [16, 17, 37]]);
491 }
492 #[test]
493 fn it_works_rot_right() {
494 let mut cube = Cube::new();
495 cube.rot_right(false);
496 assert_eq!(cube.up, [
501 [37, 38, 3],
502 [40, 41, 6],
503 [43, 44, 9]]);
504 assert_eq!(cube.down, [
509 [46, 47, 16],
510 [49, 50, 13],
511 [52, 53, 10]]);
512 assert_eq!(cube.front, [
517 [1, 2, 48],
518 [4, 5, 51],
519 [7, 8, 54]]);
520 assert_eq!(cube.back, [
525 [45, 11, 12],
526 [42, 14, 15],
527 [39, 17, 18]]);
528 }
529 #[test]
530 fn it_works_rot_right_rev() {
531 let mut cube = Cube::new();
532 cube.rot_right(true);
533 assert_eq!(cube.up, [
538 [37, 38, 16],
539 [40, 41, 13],
540 [43, 44, 10]]);
541 assert_eq!(cube.down, [
546 [46, 47, 3],
547 [49, 50, 6],
548 [52, 53, 9]]);
549 assert_eq!(cube.front, [
554 [1, 2, 39],
555 [4, 5, 42],
556 [7, 8, 45]]);
557 assert_eq!(cube.back, [
562 [54, 11, 12],
563 [51, 14, 15],
564 [48, 17, 18]]);
565 }
566 #[test]
567 fn it_works_rot_up() {
568 let mut cube = Cube::new();
569 cube.rot_up(false);
570 assert_eq!(cube.front, [
575 [28, 29, 30],
576 [4, 5, 6],
577 [7, 8, 9]]);
578 assert_eq!(cube.back, [
583 [19, 20, 21],
584 [13, 14, 15],
585 [16, 17, 18]]);
586 assert_eq!(cube.left, [
591 [1, 2, 3],
592 [22, 23, 24],
593 [25, 26, 27]]);
594 assert_eq!(cube.right, [
599 [10, 11, 12],
600 [31, 32, 33],
601 [34, 35, 36]]);
602 }
603 #[test]
604 fn it_works_rot_up_rev() {
605 let mut cube = Cube::new();
606 cube.rot_up(true);
607 assert_eq!(cube.front, [
612 [19, 20, 21],
613 [4, 5, 6],
614 [7, 8, 9]]);
615 assert_eq!(cube.back, [
620 [28, 29, 30],
621 [13, 14, 15],
622 [16, 17, 18]]);
623 assert_eq!(cube.left, [
628 [10, 11, 12],
629 [22, 23, 24],
630 [25, 26, 27]]);
631 assert_eq!(cube.right, [
636 [1, 2, 3],
637 [31, 32, 33],
638 [34, 35, 36]]);
639 }
640 #[test]
641 fn it_works_rot_down() {
642 let mut cube = Cube::new();
643 cube.rot_down(false);
644 assert_eq!(cube.front, [
649 [1, 2, 3],
650 [4, 5, 6],
651 [25, 26, 27]]);
652 assert_eq!(cube.back, [
657 [10, 11, 12],
658 [13, 14, 15],
659 [34, 35, 36]]);
660 assert_eq!(cube.left, [
665 [19, 20, 21],
666 [22, 23, 24],
667 [16, 17, 18]]);
668 assert_eq!(cube.right, [
673 [28, 29, 30],
674 [31, 32, 33],
675 [7, 8, 9]]);
676 }
677 #[test]
678 fn it_works_rot_down_rev() {
679 let mut cube = Cube::new();
680 cube.rot_down(true);
681 assert_eq!(cube.front, [
686 [1, 2, 3],
687 [4, 5, 6],
688 [34, 35, 36]]);
689 assert_eq!(cube.back, [
694 [10, 11, 12],
695 [13, 14, 15],
696 [25, 26, 27]]);
697 assert_eq!(cube.left, [
702 [19, 20, 21],
703 [22, 23, 24],
704 [7, 8, 9]]);
705 assert_eq!(cube.right, [
710 [28, 29, 30],
711 [31, 32, 33],
712 [16, 17, 18]]);
713 }
714 #[test]
715 fn it_works_is_solved() {
716 let mut cube = Cube::new();
717 cube.rot_back(false);
718 cube.rot_back(true);
719 assert_eq!(cube.is_solved(), true);
720 cube.rot_back(true);
721 assert_eq!(cube.is_solved(), false);
722 }
723
724 #[test]
725 fn it_works_rot() {
726 let mut cube = Cube::new();
727 cube.rot('F');
728 cube.rot('f');
729 assert_eq!(cube.is_solved(), true);
730 }
731
732 #[test]
733 fn it_works_get_svg() {
734 let mut cube = Cube::new();
735 cube.get_svg();
736 assert_eq!(true, true)
737 }
738
739 #[test]
740 fn it_works_get_svg_base64_png() {
741 let mut cube = Cube::new();
742 let base64 = cube.get_svg_base64_png();
743 println!("{}", base64);
744 assert_eq!(true, true)
745 }
746}