ssr_algorithms/super_memory_2/
mod.rs

1use 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}