konnektoren_core/challenges/vocabulary/
mod.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, JsonSchema)]
5pub struct Vocabulary {
6    /// Unique identifier for the vocabulary set
7    pub id: String,
8    /// Display name of the vocabulary set
9    pub name: String,
10    /// Description of the vocabulary set
11    pub description: String,
12    /// Optional icon identifier
13    pub icon: Option<String>,
14    /// Language code
15    pub lang: String,
16    /// List of vocabulary items
17    pub items: Vec<VocabularyItem>,
18}
19
20impl Default for Vocabulary {
21    fn default() -> Self {
22        let data = include_str!("../../../assets/vocabulary_default.yml");
23        serde_yaml::from_str(data).unwrap()
24    }
25}
26
27#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default, JsonSchema)]
28pub struct VocabularyItem {
29    /// Item identifier
30    pub id: usize,
31    /// The word or phrase
32    pub text: String,
33    /// Translation of the word
34    pub translation: Option<String>,
35    /// Optional icon identifier
36    pub icon: Option<String>,
37    /// Phonetic pronunciation
38    pub phonetic: Option<String>,
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44
45    #[test]
46    fn new_vocabulary() {
47        let id = "vocab-test".to_string();
48        let name = "Test Vocabulary".to_string();
49        let description = "A test vocabulary set".to_string();
50        let icon = Some("fa-solid fa-book".to_string());
51        let lang = "en".to_string();
52        let items = vec![
53            VocabularyItem {
54                id: 0,
55                text: "hello".to_string(),
56                translation: Some("hola".to_string()),
57                icon: Some("fa-solid fa-hand-wave".to_string()),
58                phonetic: Some("/həˈloʊ/".to_string()),
59            },
60            VocabularyItem {
61                id: 1,
62                text: "world".to_string(),
63                translation: Some("mundo".to_string()),
64                icon: Some("fa-solid fa-globe".to_string()),
65                phonetic: Some("/wɜːrld/".to_string()),
66            },
67        ];
68
69        let vocabulary = Vocabulary {
70            id: id.clone(),
71            name: name.clone(),
72            description: description.clone(),
73            icon: icon.clone(),
74            lang: lang.clone(),
75            items: items.clone(),
76        };
77
78        assert_eq!(vocabulary.id, id);
79        assert_eq!(vocabulary.name, name);
80        assert_eq!(vocabulary.description, description);
81        assert_eq!(vocabulary.icon, icon);
82        assert_eq!(vocabulary.lang, lang);
83        assert_eq!(vocabulary.items.len(), 2);
84        assert_eq!(vocabulary.items, items);
85    }
86
87    #[test]
88    fn test_vocabulary_deserialization() {
89        let yaml = r#"
90        id: "basic-greetings"
91        name: "Basic Greetings"
92        description: "Learn common greeting words"
93        icon: "fa-solid fa-hand-wave"
94        lang: "de"
95        items:
96          - id: 0
97            text: "Hallo"
98            translation: "Hello"
99            icon: "fa-solid fa-hand-wave"
100            phonetic: "/ˈhalo/"
101          - id: 1
102            text: "Tschüss"
103            translation: "Goodbye"
104            icon: "fa-solid fa-hand-peace"
105            phonetic: "/tʃyːs/"
106        "#;
107
108        let vocabulary: Vocabulary = serde_yaml::from_str(yaml).unwrap();
109        assert_eq!(vocabulary.id, "basic-greetings");
110        assert_eq!(vocabulary.name, "Basic Greetings");
111        assert_eq!(vocabulary.description, "Learn common greeting words");
112        assert_eq!(vocabulary.icon, Some("fa-solid fa-hand-wave".to_string()));
113        assert_eq!(vocabulary.lang, "de");
114        assert_eq!(vocabulary.items.len(), 2);
115
116        let first_item = &vocabulary.items[0];
117        assert_eq!(first_item.id, 0);
118        assert_eq!(first_item.text, "Hallo");
119        assert_eq!(first_item.translation, Some("Hello".to_string()));
120        assert_eq!(first_item.icon, Some("fa-solid fa-hand-wave".to_string()));
121        assert_eq!(first_item.phonetic, Some("/ˈhalo/".to_string()));
122
123        let second_item = &vocabulary.items[1];
124        assert_eq!(second_item.id, 1);
125        assert_eq!(second_item.text, "Tschüss");
126        assert_eq!(second_item.translation, Some("Goodbye".to_string()));
127        assert_eq!(second_item.icon, Some("fa-solid fa-hand-peace".to_string()));
128        assert_eq!(second_item.phonetic, Some("/tʃyːs/".to_string()));
129    }
130
131    #[test]
132    fn test_vocabulary_item_default() {
133        let item = VocabularyItem::default();
134        assert_eq!(item.id, 0);
135        assert_eq!(item.text, "");
136        assert_eq!(item.translation, None);
137        assert_eq!(item.icon, None);
138        assert_eq!(item.phonetic, None);
139    }
140
141    #[test]
142    fn test_vocabulary_item_partial_data() {
143        let yaml = r#"
144        id: "minimal-vocab"
145        name: "Minimal Vocabulary"
146        description: "Vocabulary with minimal data"
147        lang: "en"
148        items:
149          - id: 0
150            text: "example"
151          - id: 1
152            text: "test"
153            translation: "prueba"
154        "#;
155
156        let vocabulary: Vocabulary = serde_yaml::from_str(yaml).unwrap();
157        assert_eq!(vocabulary.items.len(), 2);
158
159        let first_item = &vocabulary.items[0];
160        assert_eq!(first_item.text, "example");
161        assert_eq!(first_item.translation, None);
162        assert_eq!(first_item.icon, None);
163        assert_eq!(first_item.phonetic, None);
164
165        let second_item = &vocabulary.items[1];
166        assert_eq!(second_item.text, "test");
167        assert_eq!(second_item.translation, Some("prueba".to_string()));
168        assert_eq!(second_item.icon, None);
169        assert_eq!(second_item.phonetic, None);
170    }
171
172    #[test]
173    fn default_vocabulary() {
174        let vocabulary = Vocabulary::default();
175        assert_eq!(vocabulary.id, "vocabulary-example");
176        assert_eq!(vocabulary.name, "Basic German Vocabulary");
177        assert_eq!(
178            vocabulary.description,
179            "Learn essential German words with pronunciation"
180        );
181        assert_eq!(vocabulary.icon, Some("fa-solid fa-book-open".to_string()));
182        assert_eq!(vocabulary.lang, "de");
183        assert!(!vocabulary.items.is_empty());
184    }
185
186    #[test]
187    fn serialize_vocabulary() {
188        let vocabulary = Vocabulary {
189            id: "test-vocab".to_string(),
190            name: "Test".to_string(),
191            description: "Test vocabulary".to_string(),
192            icon: Some("fa-solid fa-test".to_string()),
193            lang: "en".to_string(),
194            items: vec![VocabularyItem {
195                id: 0,
196                text: "word".to_string(),
197                translation: Some("palabra".to_string()),
198                icon: None,
199                phonetic: None,
200            }],
201        };
202
203        let json = serde_json::to_string(&vocabulary).unwrap();
204        let deserialized: Vocabulary = serde_json::from_str(&json).unwrap();
205        assert_eq!(vocabulary, deserialized);
206    }
207}