shared/domain/module/body/
memory.rs

1use crate::domain::module::{
2    body::{Body, BodyConvert, BodyExt, ThemeId, _groups::cards::*},
3    ModuleKind,
4};
5use serde::{Deserialize, Serialize};
6use std::collections::HashSet;
7
8/// The body for [`Memory`](crate::domain::module::ModuleKind::Memory) modules.
9#[derive(Default, Clone, Serialize, Deserialize, Debug)]
10pub struct ModuleData {
11    /// The content
12    pub content: Option<Content>,
13}
14
15/// The content for [`Memory`](crate::domain::module::ModuleKind::Memory) modules.
16#[derive(Default, Clone, Serialize, Deserialize, Debug)]
17pub struct Content {
18    /// The base content for all cards modules
19    pub base: BaseContent,
20    /// Settings for playback
21    pub player_settings: PlayerSettings,
22}
23
24/// Player settings
25#[derive(Default, Clone, Serialize, Deserialize, Debug)]
26pub struct PlayerSettings {
27    /// time limit in minutes
28    pub time_limit: Option<u32>,
29    /// amount of pairs to render
30    pub pairs_to_display: Option<u32>,
31}
32
33impl BodyExt<Mode, Step> for ModuleData {
34    fn as_body(&self) -> Body {
35        Body::MemoryGame(self.clone())
36    }
37
38    fn is_complete(&self) -> bool {
39        self.content
40            .as_ref()
41            .map_or(false, |content| content.base.is_valid())
42    }
43
44    fn kind() -> ModuleKind {
45        ModuleKind::Memory
46    }
47
48    fn new_with_mode_and_theme(mode: Mode, theme: ThemeId) -> Self {
49        ModuleData {
50            content: Some(Content {
51                base: BaseContent {
52                    mode,
53                    theme,
54                    ..Default::default()
55                },
56                ..Default::default()
57            }),
58        }
59    }
60
61    fn mode(&self) -> Option<Mode> {
62        self.content.as_ref().map(|c| c.base.mode.clone())
63    }
64
65    fn requires_choose_mode(&self) -> bool {
66        self.content.is_none()
67    }
68
69    fn set_editor_state_step(&mut self, step: Step) {
70        if let Some(content) = self.content.as_mut() {
71            content.base.editor_state.step = step;
72        }
73    }
74    fn set_editor_state_steps_completed(&mut self, steps_completed: HashSet<Step>) {
75        if let Some(content) = self.content.as_mut() {
76            content.base.editor_state.steps_completed = steps_completed;
77        }
78    }
79
80    fn get_editor_state_step(&self) -> Option<Step> {
81        self.content
82            .as_ref()
83            .map(|content| content.base.editor_state.step)
84    }
85
86    fn get_editor_state_steps_completed(&self) -> Option<HashSet<Step>> {
87        self.content
88            .as_ref()
89            .map(|content| content.base.editor_state.steps_completed.clone())
90    }
91
92    fn set_theme(&mut self, theme_id: ThemeId) {
93        if let Some(content) = self.content.as_mut() {
94            content.base.theme = theme_id;
95        }
96    }
97
98    fn get_theme(&self) -> Option<ThemeId> {
99        self.content.as_ref().map(|content| content.base.theme)
100    }
101}
102
103impl BodyConvert for ModuleData {
104    fn convertable_list() -> Vec<ModuleKind> {
105        vec![
106            ModuleKind::Matching,
107            ModuleKind::Flashcards,
108            ModuleKind::CardQuiz,
109        ]
110    }
111    fn convert_to_matching(&self) -> Result<super::matching::ModuleData, &'static str> {
112        Ok(super::matching::ModuleData {
113            content: self
114                .content
115                .as_ref()
116                .map(|content| super::matching::Content {
117                    base: content.base.clone(),
118                    player_settings: super::matching::PlayerSettings::default(),
119                }),
120        })
121    }
122    fn convert_to_flashcards(&self) -> Result<super::flashcards::ModuleData, &'static str> {
123        Ok(super::flashcards::ModuleData {
124            content: self
125                .content
126                .as_ref()
127                .map(|content| super::flashcards::Content {
128                    base: content.base.clone(),
129                    player_settings: super::flashcards::PlayerSettings::default(),
130                }),
131        })
132    }
133
134    fn convert_to_card_quiz(&self) -> Result<super::card_quiz::ModuleData, &'static str> {
135        Ok(super::card_quiz::ModuleData {
136            content: self
137                .content
138                .as_ref()
139                .map(|content| super::card_quiz::Content {
140                    base: content.base.clone(),
141                    player_settings: super::card_quiz::PlayerSettings::default(),
142                }),
143        })
144    }
145}
146
147impl TryFrom<Body> for ModuleData {
148    type Error = &'static str;
149
150    fn try_from(body: Body) -> Result<Self, Self::Error> {
151        match body {
152            Body::MemoryGame(data) => Ok(data),
153            _ => Err("cannot convert body to memory game!"),
154        }
155    }
156}