konnektoren_core/challenges/
challenge_factory.rs1use crate::challenges::Base64Serializable;
2use crate::challenges::challenge::Challenge;
3use crate::challenges::challenge_config::ChallengeConfig;
4use crate::challenges::challenge_type::ChallengeType;
5use crate::challenges::error::{ChallengeError, Result};
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
9pub struct ChallengeFactory {
10 pub challenge_types: Vec<ChallengeType>,
11}
12
13impl Default for ChallengeFactory {
14 fn default() -> Self {
15 ChallengeFactory {
16 challenge_types: vec![
17 ChallengeType::default(),
18 serde_yaml::from_str(include_str!("../../assets/articles-1.yml")).unwrap(),
19 serde_yaml::from_str(include_str!("../../assets/past-tense.yml")).unwrap(),
20 serde_yaml::from_str(include_str!("../../assets/sentence_structure.yml")).unwrap(),
21 ],
22 }
23 }
24}
25
26impl ChallengeFactory {
27 pub fn new() -> Self {
28 ChallengeFactory {
29 challenge_types: vec![],
30 }
31 }
32
33 pub fn create_challenge(&self, challenge_config: &ChallengeConfig) -> Result<Challenge> {
34 let challenge_type = self
35 .challenge_types
36 .iter()
37 .find(|challenge_type| challenge_type.id() == challenge_config.challenge)
38 .ok_or(ChallengeError::ChallengeTypeNotFound)?;
39 Ok(Challenge::new(
40 &challenge_type.of_tasks(&challenge_config.tasks),
41 challenge_config,
42 ))
43 }
44
45 pub fn add_challenge_from_base64(&mut self, base64_data: &str) -> Result<()> {
46 let challenge_type = ChallengeType::from_base64(base64_data)?;
47 self.challenge_types.push(challenge_type);
48 Ok(())
49 }
50
51 pub fn export_challenge_to_base64(&self, challenge_id: &str) -> Result<String> {
52 let challenge_type = self
53 .challenge_types
54 .iter()
55 .find(|ct| ct.id() == challenge_id)
56 .ok_or_else(|| ChallengeError::ChallengeNotFound(challenge_id.to_string()))?;
57
58 challenge_type.to_base64()
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn create_challenge() {
68 let mut challenge_factory = ChallengeFactory::new();
69 let challenge_type = ChallengeType::default();
70 challenge_factory.challenge_types.push(challenge_type);
71 let challenge_config = ChallengeConfig {
72 challenge: "konnektoren".to_string(),
73 tasks: 2.into(),
74 ..Default::default()
75 };
76
77 let challenge = challenge_factory.create_challenge(&challenge_config);
78 match challenge.unwrap().challenge_type {
79 ChallengeType::MultipleChoice(dataset) => {
80 assert_eq!(dataset.questions.len(), 2);
81 }
82 _ => panic!("Invalid challenge type"),
83 }
84 }
85
86 #[test]
87 fn test_add_challenge_from_base64() {
88 let mut factory = ChallengeFactory::new();
89 let original_challenge = ChallengeType::default();
90
91 let base64_data = original_challenge.to_base64().unwrap();
93
94 factory.add_challenge_from_base64(&base64_data).unwrap();
96
97 assert_eq!(factory.challenge_types.len(), 1);
98 assert_eq!(factory.challenge_types[0].id(), original_challenge.id());
99 }
100
101 #[test]
102 fn test_export_challenge_to_base64() {
103 let factory = ChallengeFactory::default();
104 let base64_data = factory.export_challenge_to_base64("konnektoren").unwrap();
105 assert!(!base64_data.is_empty());
106 }
107}