diff options
Diffstat (limited to 'src/gui/question.rs')
-rw-r--r-- | src/gui/question.rs | 95 |
1 files changed, 65 insertions, 30 deletions
diff --git a/src/gui/question.rs b/src/gui/question.rs index abb8fd7..1c44272 100644 --- a/src/gui/question.rs +++ b/src/gui/question.rs @@ -29,11 +29,7 @@ pub enum Response { Answered { difficulty: Difficulty }, } -pub fn ask<B: Backend>( - terminal: &mut Terminal<B>, - title: &str, - card: &Card, -) -> Result<Response> { +pub fn ask<B: Backend>(terminal: &mut Terminal<B>, title: &str, card: &Card) -> Result<Response> { let mut state = State { input: String::new(), answer: Answer::Write, @@ -81,10 +77,11 @@ pub fn ask<B: Backend>( .style(match state.answer { Answer::Write => Style::default(), Answer::Difficulty { difficulty: _ } => { - if is_correct(&state.input, &card.responses) { - Style::default().fg(Color::Green) - } else { - Style::default().fg(Color::Red) + match check_response(&state.input, &card.responses) { + CheckResponse::Correct { phonetics: _ } => { + Style::default().fg(Color::Green) + } + CheckResponse::Incorrect => Style::default().fg(Color::Red), } } }) @@ -97,12 +94,17 @@ pub fn ask<B: Backend>( difficulty: selected, } = state.answer { - if !is_correct(&state.input, &card.responses) { - let paragraph = Paragraph::new(util::center_vertically( - chunks[3], - &serialization::words_to_line(&card.responses), - )) - .alignment(Alignment::Center); + let maybe_indication: Option<String> = + match check_response(&state.input, &card.responses) { + CheckResponse::Correct { phonetics } => phonetics, + CheckResponse::Incorrect => { + Some(serialization::words_to_line(&card.responses)) + } + }; + + if let Some(indication) = maybe_indication { + let paragraph = Paragraph::new(util::center_vertically(chunks[3], &indication)) + .alignment(Alignment::Center); f.render_widget(paragraph, chunks[3]); }; @@ -138,10 +140,9 @@ pub fn ask<B: Backend>( match state.answer { Answer::Write => match key.code { KeyCode::Enter => { - let difficulty = if is_correct(&state.input, &card.responses) { - Difficulty::Good - } else { - Difficulty::Again + let difficulty = match check_response(&state.input, &card.responses) { + CheckResponse::Correct { phonetics: _ } => Difficulty::Good, + CheckResponse::Incorrect => Difficulty::Again, }; state.answer = Answer::Difficulty { difficulty } } @@ -150,7 +151,8 @@ pub fn ask<B: Backend>( if c == 'u' { state.input.clear(); } else if c == 'w' { - let mut words = state.input.split_whitespace().collect::<Vec<&str>>(); + let mut words = + state.input.split_whitespace().collect::<Vec<&str>>(); if !words.is_empty() { words.truncate(words.len() - 1); let joined_words = words.join(" "); @@ -162,7 +164,9 @@ pub fn ask<B: Backend>( } } else { state.input.push(c); - if is_correct(&state.input, &card.responses) { + if let CheckResponse::Correct { phonetics: _ } = + check_response(&state.input, &card.responses) + { state.answer = Answer::Difficulty { difficulty: Difficulty::Good, } @@ -205,19 +209,50 @@ pub fn ask<B: Backend>( } } -fn is_correct(input: &str, responses: &[String]) -> bool { - // Remove whitespaces - let input = input +enum CheckResponse { + Incorrect, + Correct { phonetics: Option<String> }, +} + +fn check_response(input: &str, responses: &[String]) -> CheckResponse { + let input = remove_whitespaces(input); + + responses + .iter() + .find(|r| remove_indications_and_phonetics(r) == input) + .map(|r| CheckResponse::Correct { + phonetics: extract_phonetics(r), + }) + .unwrap_or(CheckResponse::Incorrect) +} + +fn remove_whitespaces(input: &str) -> String { + input .split_whitespace() .map(|word| word.trim()) .collect::<Vec<&str>>() - .join(" "); + .join(" ") +} - responses - .iter() - .map(|r| r.split('(').collect::<Vec<&str>>()[0].trim()) - .map(|r| r.split('[').collect::<Vec<&str>>()[0].trim()) - .any(|x| x == input) +fn remove_indications_and_phonetics(response: &str) -> &str { + response + .split(|c| c == '(' || c == '[') + .collect::<Vec<&str>>()[0] + .trim() +} + +fn extract_phonetics(response: &str) -> Option<String> { + let s1 = response.split('[').collect::<Vec<&str>>(); + if s1.len() == 2 { + let s2 = s1[1].split(']').collect::<Vec<&str>>(); + if s2.len() > 1 { + Some(format!("[{}]", s2[0])) + } else { + None + } + } else { + None + } } fn relative_element<T: Clone + PartialEq>(xs: &[T], x: &T, ri: i32) -> Option<T> { |