shared/domain/module/body/
flashcards.rs1use crate::domain::module::{
2 body::{Body, BodyConvert, BodyExt, ModeExt, ThemeId, _groups::cards::*},
3 ModuleKind,
4};
5use serde::{Deserialize, Serialize};
6use std::collections::HashSet;
7
8#[derive(Default, Clone, Serialize, Deserialize, Debug)]
10pub struct ModuleData {
11 pub content: Option<Content>,
13}
14
15#[derive(Default, Clone, Serialize, Deserialize, Debug)]
17pub struct Content {
18 pub base: BaseContent,
20 pub player_settings: PlayerSettings,
22}
23
24#[derive(Default, Clone, Serialize, Deserialize, Debug)]
26pub struct PlayerSettings {
27 pub display_mode: DisplayMode,
29
30 #[serde(default)]
32 pub view_pairs: Option<u32>,
33
34 #[serde(default)]
36 pub swap: bool,
37}
38
39#[derive(Clone, Copy, Serialize, Deserialize, Debug, Eq, PartialEq)]
41pub enum DisplayMode {
42 Single,
44 Double,
46}
47
48impl Default for DisplayMode {
49 fn default() -> Self {
50 Self::Double
51 }
52}
53
54impl DisplayMode {
55 pub fn as_str_id(&self) -> &'static str {
57 match self {
58 Self::Single => "single",
59 Self::Double => "double",
60 }
61 }
62}
63
64impl BodyExt<Mode, Step> for ModuleData {
65 fn as_body(&self) -> Body {
66 Body::Flashcards(self.clone())
67 }
68
69 fn choose_mode_list() -> Vec<Mode> {
70 Mode::get_list()
71 .into_iter()
72 .filter(|mode| *mode != Mode::Duplicate)
73 .collect()
74 }
75
76 fn is_complete(&self) -> bool {
77 self.content
78 .as_ref()
79 .map_or(false, |content| content.base.is_valid())
80 }
81
82 fn kind() -> ModuleKind {
83 ModuleKind::Flashcards
84 }
85
86 fn new_with_mode_and_theme(mode: Mode, theme: ThemeId) -> Self {
87 ModuleData {
88 content: Some(Content {
89 base: BaseContent {
90 mode,
91 theme,
92 ..Default::default()
93 },
94 ..Default::default()
95 }),
96 }
97 }
98
99 fn mode(&self) -> Option<Mode> {
100 self.content.as_ref().map(|c| c.base.mode.clone())
101 }
102
103 fn requires_choose_mode(&self) -> bool {
104 self.content.is_none()
105 }
106
107 fn set_editor_state_step(&mut self, step: Step) {
108 if let Some(content) = self.content.as_mut() {
109 content.base.editor_state.step = step;
110 }
111 }
112 fn set_editor_state_steps_completed(&mut self, steps_completed: HashSet<Step>) {
113 if let Some(content) = self.content.as_mut() {
114 content.base.editor_state.steps_completed = steps_completed;
115 }
116 }
117
118 fn get_editor_state_step(&self) -> Option<Step> {
119 self.content
120 .as_ref()
121 .map(|content| content.base.editor_state.step)
122 }
123
124 fn get_editor_state_steps_completed(&self) -> Option<HashSet<Step>> {
125 self.content
126 .as_ref()
127 .map(|content| content.base.editor_state.steps_completed.clone())
128 }
129
130 fn set_theme(&mut self, theme_id: ThemeId) {
131 if let Some(content) = self.content.as_mut() {
132 content.base.theme = theme_id;
133 }
134 }
135
136 fn get_theme(&self) -> Option<ThemeId> {
137 self.content.as_ref().map(|content| content.base.theme)
138 }
139}
140
141impl BodyConvert for ModuleData {
142 fn convertable_list() -> Vec<ModuleKind> {
143 vec![
144 ModuleKind::Memory,
145 ModuleKind::Matching,
146 ModuleKind::CardQuiz,
147 ]
148 }
149 fn convert_to_memory(&self) -> Result<super::memory::ModuleData, &'static str> {
150 Ok(super::memory::ModuleData {
151 content: self.content.as_ref().map(|content| super::memory::Content {
152 base: content.base.clone(),
153 player_settings: super::memory::PlayerSettings::default(),
154 }),
155 })
156 }
157 fn convert_to_matching(&self) -> Result<super::matching::ModuleData, &'static str> {
158 Ok(super::matching::ModuleData {
159 content: self
160 .content
161 .as_ref()
162 .map(|content| super::matching::Content {
163 base: content.base.clone(),
164 player_settings: super::matching::PlayerSettings::default(),
165 }),
166 })
167 }
168
169 fn convert_to_card_quiz(&self) -> Result<super::card_quiz::ModuleData, &'static str> {
170 Ok(super::card_quiz::ModuleData {
171 content: self
172 .content
173 .as_ref()
174 .map(|content| super::card_quiz::Content {
175 base: content.base.clone(),
176 player_settings: super::card_quiz::PlayerSettings::default(),
177 }),
178 })
179 }
180}
181
182impl TryFrom<Body> for ModuleData {
183 type Error = &'static str;
184
185 fn try_from(body: Body) -> Result<Self, Self::Error> {
186 match body {
187 Body::Flashcards(data) => Ok(data),
188 _ => Err("cannot convert body to flashcards!"),
189 }
190 }
191}