diff --git a/src/db/mod.rs b/src/db/mod.rs index ef07e2b..f34f524 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -40,7 +40,7 @@ pub(crate) enum QuestionKind { Translate { from: Language, to: Language }, } -#[derive(Serialize, Deserialize, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] pub(crate) enum QuestionResult { /// User knew it. Yes, diff --git a/src/quiz/mod.rs b/src/quiz/mod.rs index 2da1847..9995e0b 100644 --- a/src/quiz/mod.rs +++ b/src/quiz/mod.rs @@ -44,12 +44,16 @@ crate fn quiz(options: &MathemaOptions, language_str: &str, duration_min: i64) - let mut presentation = presentation::basic(); - let parentheticals = Regex::new(r"([^)]*)|\[[^]\]").unwrap(); + let parentheticals = Regex::new(r"\(.*\)").unwrap(); - for (uuid, question_kind) in cards { + let cards_len = cards.len(); + for ((uuid, question_kind), cards_remaining) in cards.into_iter().zip((1..=cards_len).rev()) { let quiz_duration = Utc::now().signed_duration_since(start_time); if quiz_duration > max_duration { - match presentation.quiz_expired(Utc::now().signed_duration_since(original_start_time))? { + match presentation.quiz_expired( + Utc::now().signed_duration_since(original_start_time), + cards_remaining, + )? { None => break, Some(minutes) => { start_time = Utc::now(); @@ -59,8 +63,9 @@ crate fn quiz(options: &MathemaOptions, language_str: &str, duration_min: i64) - } let card = repo.card(uuid); - let mut expected_responses: Vec<_> = card.lines_with_kind(question_kind.response_line_kind()) - .collect(); + let mut expected_responses: Vec<_> = card.lines_with_kind( + question_kind.response_line_kind(), + ).collect(); let prompt = Prompt { start_time, @@ -73,16 +78,16 @@ crate fn quiz(options: &MathemaOptions, language_str: &str, duration_min: i64) - let mut counter = 1; while let Some(user_response) = presentation.read_response(prompt, counter)? { - counter += 1; - expected_responses.retain(|r| { let r = parentheticals.replace_all(r, ""); - r != user_response + r.trim() != user_response }); - if expected_responses.is_empty() { + if counter >= expected_responses.len() { break; } + + counter += 1; } let result = if expected_responses.is_empty() { @@ -91,10 +96,13 @@ crate fn quiz(options: &MathemaOptions, language_str: &str, duration_min: i64) - presentation.read_result(prompt, &expected_responses)? }; let record = repo.database_mut().card_record_mut(uuid); - record.push_question_record(question_kind, QuestionRecord { - date: Utc::now(), - result: result, - }); + record.push_question_record( + question_kind, + QuestionRecord { + date: Utc::now(), + result: result, + }, + ); presentation.cleanup(); } diff --git a/src/quiz/presentation/basic.rs b/src/quiz/presentation/basic.rs index 945f660..bc177a5 100644 --- a/src/quiz/presentation/basic.rs +++ b/src/quiz/presentation/basic.rs @@ -22,12 +22,12 @@ impl Presentation for Basic { } fn read_response(&mut self, prompt: Prompt<'_>, index: usize) -> Fallible> { - print!("Response {}/{}: ", index, prompt.num_responses); + println!("Response {}/{}: ", index, prompt.num_responses); let mut buffer = String::new(); self.stdin.read_line(&mut buffer)?; let response_language = prompt.question_kind.response_language(); - let response = response_language.transliterate(&buffer); - if response != buffer { + let response = response_language.transliterate(buffer.trim()); + if response != buffer.trim() { println!(" (transliterated to `{}`)", response); } if response.is_empty() { @@ -48,28 +48,42 @@ impl Presentation for Basic { } loop { - print!("Did you know it (yes/almost/no)? "); + println!("Did you know it (yes/almost/no)? "); let mut buffer = String::new(); self.stdin.read_line(&mut buffer)?; - let buffer = buffer.to_lowercase(); + let buffer = buffer.trim().to_lowercase(); match &buffer[..] { "yes" | "y" => return Ok(QuestionResult::Yes), "almost" | "a" => return Ok(QuestionResult::Almost), "no" | "n" => return Ok(QuestionResult::No), - _ => { } + _ => {} } } } fn cleanup(&mut self) { + println!(); + println!(); + println!(); } - fn quiz_expired(&mut self, quiz_duration: Duration) -> Fallible> { + fn quiz_expired( + &mut self, + quiz_duration: Duration, + remaining_cards: usize, + ) -> Fallible> { println!("--------------------------------------------------"); - println!("{} minutes have expired since you started the quiz.", quiz_duration.num_minutes()); + println!( + "{} minutes have expired since you started the quiz.", + quiz_duration.num_minutes() + ); + println!( + "There are still {} cards left to go.", + remaining_cards, + ); loop { println!("If you want to stop, press enter."); - print!("Otherwise, type in how many more minutes: "); + println!("Otherwise, type in how many more minutes: "); let mut buffer = String::new(); self.stdin.read_line(&mut buffer)?; if buffer.is_empty() { @@ -79,7 +93,7 @@ impl Presentation for Basic { Ok(v) if v >= 0 => { return Ok(Some(v)); } - _ => { } + _ => {} } } } diff --git a/src/quiz/presentation/mod.rs b/src/quiz/presentation/mod.rs index 4bb8806..f3a7454 100644 --- a/src/quiz/presentation/mod.rs +++ b/src/quiz/presentation/mod.rs @@ -12,7 +12,11 @@ crate trait Presentation { /// Prompt user that `quiz_duration` time has been spent. Ask if /// they want to spend more time. - fn quiz_expired(&mut self, quiz_duration: Duration) -> Fallible>; + fn quiz_expired( + &mut self, + quiz_duration: Duration, + remaining_cards: usize, + ) -> Fallible>; } #[derive(Copy, Clone, Debug)]