1use crate::questionaire::{QuestionAnswerInput, QuestionEntry, QuestionAnswer} ;
2use anyhow::{anyhow, Result};
3use colored::Colorize;
4use serde::Serialize;
5
6use std::fs::{File, OpenOptions};
7use std::io::Write;
8use std::path::Path;
9use std::io::{BufRead, BufReader};
10
11
12pub trait QuestionairePersistence {
13 fn store_question(&mut self, entry: &QuestionEntry, data: &QuestionAnswerInput) -> Result<()>;
14 fn load(&mut self, source: Option<&str>) -> Result<()>;
15 fn import(&mut self, data_to_import: &Vec<QuestionAnswer>);
16 fn next_answer(&mut self) -> Option<QuestionAnswer>;
17 fn next_answer_id(&mut self) -> Option<String>;
18}
19
20pub struct FileQuestionairePersistence {
21 file: String,
22 data: Vec<QuestionAnswer>,
23 pub debug: bool,
24 current_pos: usize,
25}
26
27impl FileQuestionairePersistence {
28 pub fn new(file: &str) -> Result<FileQuestionairePersistence> {
29 let ret = FileQuestionairePersistence {
30 file: file.to_string(),
31 data: vec![],
32 debug: false,
33 current_pos: 0,
34 };
35 Ok(ret)
36 }
37
38 fn store<T: Serialize>(&mut self, id: &str, answer: &T) -> Result<()> {
39 let json_string = serde_json::to_string(answer).unwrap();
40 let txt = format!("{}={}",id, json_string);
41 if self.debug {
42 println!("{}", txt.blue().italic());
43 }
44 self.write_to_file(&txt)
45 }
46
47
48 fn write_to_file(&mut self, txt: &str) -> Result<()> {
49 let p = Path::new(&self.file);
50 let mut file = OpenOptions::new()
51 .append(true)
52 .create(true)
53 .open(p)?;
54 write!(file, "{}\n", txt)?;
55 Ok(())
56 }
57}
58
59impl QuestionairePersistence for FileQuestionairePersistence {
60 fn store_question(&mut self, entry: &QuestionEntry, data: &QuestionAnswerInput) -> Result<()> {
61 self.store(&entry.id, data)
64 }
65
66 fn load(&mut self, source: Option<&str>) -> Result<()> {
67 if let Some(file_path) = source {
68 self.data = load_tmp_file(&file_path)?;
69 Ok(())
70 } else {
71 Err(anyhow!("No source for loading given"))
72 }
73 }
74
75 fn import (&mut self, data_to_import: &Vec<QuestionAnswer>) {
76 for i in data_to_import {
77 self.data.push(i.clone());
78 }
79 }
80
81 fn next_answer(&mut self) -> Option<QuestionAnswer> {
82 if self.current_pos < self.data.len() {
83 let e = self.data.get(self.current_pos);
84 self.current_pos += 1;
85 if let Some(a) = e {
86 return Some(a.clone())
87 }
88 None
89 } else {
90 None
91 }
92 }
93
94 fn next_answer_id(&mut self) -> Option<String> {
95 if self.current_pos < self.data.len() {
96 let e = self.data.get(self.current_pos);
97 if let Some(a) = e {
98 Some(a.id.to_string())
99 } else {
100 None
101 }
102 } else {
103 None
104 }
105 }
106
107}
108
109pub struct NoPersistence {
110}
111
112impl NoPersistence {
113 pub fn new() -> Self {
114 NoPersistence{}
115 }
116}
117
118impl QuestionairePersistence for NoPersistence {
119 fn store_question(&mut self, _entry: &QuestionEntry, _data: &QuestionAnswerInput) -> Result<()> {
120 Ok(())
121 }
122
123 fn load(&mut self, _s: Option<&str>) -> Result<()> {
124 Err(anyhow!("Not supported"))
125 }
126
127 fn import(&mut self, _data_to_import: &Vec<QuestionAnswer>) {
128 }
129
130 fn next_answer(&mut self) -> Option<QuestionAnswer> {
131 None
132 }
133
134 fn next_answer_id(&mut self) -> Option<String> {
135 None
136 }
137
138}
139
140pub fn load_tmp_file(file_path: &str) -> Result<Vec<QuestionAnswer>> {
141 let file = File::open(file_path)?;
142 let reader = BufReader::new(file);
143
144 let mut ret: Vec<QuestionAnswer> = Vec::new();
145
146 for line in reader.lines() {
147 let line = line.unwrap();
148
149 let (id, json_str) = if let Some(index) = line.find("=") {
150 (&line[..index], &line[index+1..])
151 } else {
152 continue;
153 };
154 if let Ok(o) = serde_json::from_str::<QuestionAnswerInput>(&json_str) {
155 let qa = QuestionAnswer {
156 id: id.to_string(),
157 answer: o,
158 };
159 ret.push(qa);
160 }
161 }
162 Ok(ret)
163}
164
165#[cfg(test)]
166mod test {
167 use super::*;
168
169 #[test]
170 fn test_load_tmp_file() {
171 if let Ok(v) = load_tmp_file("res/tquest.tmp") {
172 assert_eq!(14, v.len());
173 v.iter().enumerate().for_each(|(index, a)| {
174 match index {
175 0 => assert_eq!("id01".to_string(), *a.id),
176 1 => assert_eq!("id02".to_string(), *a.id),
177 2 => assert_eq!("id03_01_01".to_string(), *a.id),
178 3 => assert_eq!("id03_01_02".to_string(), *a.id),
179 4 => assert_eq!("id03_01_01".to_string(), *a.id),
180 5 => assert_eq!("id03_01_02".to_string(), *a.id),
181 6 => assert_eq!("id04_01".to_string(), *a.id),
182 7 => assert_eq!("id04_02".to_string(), *a.id),
183 8 => assert_eq!("id04_03".to_string(), *a.id),
184 9 => assert_eq!("id04_04_01".to_string(), *a.id),
185 10 => assert_eq!("id04_04_02".to_string(), *a.id),
186 11 => assert_eq!("id04_01".to_string(), *a.id),
187 12 => assert_eq!("id04_02".to_string(), *a.id),
188 13 => assert_eq!("id04_03".to_string(), *a.id),
189 _ => panic!("more elements than expected"),
190 };
191 });
192 } else {
193 panic!("error while loading test file");
194 }
195 }
196
197 #[test]
198 fn test_next() {
199 let mut persistence = FileQuestionairePersistence::new("tmp/tquest.tmp").unwrap();
200 persistence.load(Some("res/tquest.tmp")).expect("error while loading old persistence file");
201 assert_eq!("id01".to_string(), persistence.next_answer_id().unwrap());
202 let _ = persistence.next_answer().unwrap();
203 assert_eq!("id02".to_string(), persistence.next_answer_id().unwrap());
204 let _ = persistence.next_answer().unwrap();
205 assert_eq!("id03_01_01".to_string(), persistence.next_answer_id().unwrap());
206 let _ = persistence.next_answer().unwrap();
207 assert_eq!("id03_01_02".to_string(), persistence.next_answer_id().unwrap());
208 let _ = persistence.next_answer().unwrap();
209 assert_eq!("id03_01_01".to_string(), persistence.next_answer_id().unwrap());
210 let _ = persistence.next_answer().unwrap();
211 assert_eq!("id03_01_02".to_string(), persistence.next_answer_id().unwrap());
212 let _ = persistence.next_answer().unwrap();
213 assert_eq!("id04_01".to_string(), persistence.next_answer_id().unwrap());
214 let _ = persistence.next_answer().unwrap();
215 assert_eq!("id04_02".to_string(), persistence.next_answer_id().unwrap());
216 let _ = persistence.next_answer().unwrap();
217 assert_eq!("id04_03".to_string(), persistence.next_answer_id().unwrap());
218 let _ = persistence.next_answer().unwrap();
219 assert_eq!("id04_04_01".to_string(), persistence.next_answer_id().unwrap());
220 let _ = persistence.next_answer().unwrap();
221 assert_eq!("id04_04_02".to_string(), persistence.next_answer_id().unwrap());
222 let _ = persistence.next_answer().unwrap();
223 assert_eq!("id04_01".to_string(), persistence.next_answer_id().unwrap());
224 let _ = persistence.next_answer().unwrap();
225 assert_eq!("id04_02".to_string(), persistence.next_answer_id().unwrap());
226 let _ = persistence.next_answer().unwrap();
227 assert_eq!("id04_03".to_string(), persistence.next_answer_id().unwrap());
228 let _ = persistence.next_answer().unwrap();
229 assert_eq!(None, persistence.next_answer_id());
230 assert_eq!(None, persistence.next_answer());
231 assert_eq!(None, persistence.next_answer_id());
232 assert_eq!(None, persistence.next_answer());
233 }
234}