ssr_algorithms/super_memory_2/
mod.rs1use level::{Level, Quality};
2use s_text_input_f::{BlocksWithAnswer, ParagraphItem};
3use serde::{Deserialize, Serialize};
4use ssr_core::task::{level::TaskLevel, Task};
5use std::time::SystemTime;
6
7mod level;
8
9#[derive(Serialize, Deserialize)]
10pub struct WriteAnswer {
11 level: Level,
12 input_blocks: s_text_input_f::Blocks,
13 correct_answer: s_text_input_f::Response,
14}
15
16impl WriteAnswer {
17 pub fn new(
18 input_blocks: s_text_input_f::Blocks,
19 correct_answer: s_text_input_f::Response,
20 ) -> Self {
21 Self {
22 level: Default::default(),
23 input_blocks,
24 correct_answer,
25 }
26 }
27
28 fn gen_feedback_form(
29 &mut self,
30 user_answer: Vec<Vec<String>>,
31 directive: String,
32 qualities_strings: Vec<String>,
33 ) -> Vec<s_text_input_f::Block> {
34 let mut feedback = s_text_input_f::to_answered(
35 self.input_blocks.clone(),
36 user_answer,
37 self.correct_answer.clone(),
38 )
39 .into_iter()
40 .map(s_text_input_f::Block::Answered)
41 .collect::<Vec<_>>();
42 feedback.push(s_text_input_f::Block::Paragraph(vec![]));
43 feedback.push(s_text_input_f::Block::Paragraph(vec![ParagraphItem::Text(
44 directive,
45 )]));
46 feedback.push(s_text_input_f::Block::OneOf(qualities_strings));
47 feedback
48 }
49
50 fn get_feedback(
51 &mut self,
52 user_answer: Vec<Vec<String>>,
53 directive: String,
54 qualities_strings: Vec<String>,
55 interaction: &mut impl FnMut(
56 Vec<s_text_input_f::Block>,
57 ) -> Result<Vec<Vec<String>>, std::io::Error>,
58 qualities: [Quality; 3],
59 ) -> Result<Quality, std::io::Error> {
60 let feedback = self.gen_feedback_form(user_answer, directive, qualities_strings);
61 let user_feedback = interaction(feedback)?;
62 let i = s_text_input_f::response_as_one_of(user_feedback.last().unwrap().to_owned())
63 .unwrap()
64 .unwrap();
65 let quality = qualities[i];
66 Ok(quality)
67 }
68}
69
70impl Task<'_> for WriteAnswer {
71 type SharedState = ();
72
73 fn next_repetition(&self, shared: &(), retrievability_goal: f64) -> SystemTime {
74 self.level.next_repetition(shared, retrievability_goal)
75 }
76
77 fn complete(
78 &mut self,
79 _: &mut (),
80 _desired_retention: f64,
81 interaction: &mut impl FnMut(
82 s_text_input_f::Blocks,
83 ) -> std::io::Result<s_text_input_f::Response>,
84 ) -> std::io::Result<()> {
85 let user_answer = interaction(self.input_blocks.clone())?;
86 match s_text_input_f::eq_response(&user_answer, &self.correct_answer, true, false) {
87 false => {
88 const QUALITIES: [Quality; 3] = [
89 Quality::CompleteBlackout,
90 Quality::IncorrectResponseButCorrectRemembered,
91 Quality::IncorrectResponseAndSeemedEasyToRecall,
92 ];
93 let qualities_strings = vec![
94 "complete blackout".to_string(),
95 "incorrect response, but correct remembered".to_string(),
96 "incorrect response, but seemed easy to recall".to_string(),
97 ];
98 let directive = "Choose difficulty:".to_string();
99
100 let quality = self.get_feedback(
101 user_answer,
102 directive,
103 qualities_strings,
104 interaction,
105 QUALITIES,
106 )?;
107
108 self.level.update(&mut (), (SystemTime::now(), quality));
109 }
110 true => {
111 const QUALITIES: [Quality; 3] = [
112 Quality::CorrectResponseRecalledWithSeriousDifficulty,
113 Quality::CorrectResponseAfterHesitation,
114 Quality::PerfectResponse,
115 ];
116 let qualities_strings = vec![
117 "recalled with serious difficulty".to_string(),
118 "correct, but after hesitation".to_string(),
119 "perfect response".to_string(),
120 ];
121 let directive = "All answers correct! Choose difficulty:".to_string();
122
123 let quality = self.get_feedback(
124 user_answer,
125 directive,
126 qualities_strings,
127 interaction,
128 QUALITIES,
129 )?;
130
131 self.level.update(&mut (), (SystemTime::now(), quality));
132 }
133 }
134 Ok(())
135 }
136
137 fn new(input: s_text_input_f::BlocksWithAnswer) -> Self {
138 Self {
139 level: Default::default(),
140 input_blocks: input.blocks,
141 correct_answer: input.answer,
142 }
143 }
144
145 fn get_blocks(&self) -> s_text_input_f::BlocksWithAnswer {
146 BlocksWithAnswer {
147 blocks: self.input_blocks.clone(),
148 answer: self.correct_answer.clone(),
149 }
150 }
151}