aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoris2023-03-05 20:28:56 +0100
committerJoris2023-03-05 20:28:56 +0100
commit8987c94b3654dd4ef40bea6745886a514bfa4532 (patch)
treeccd951adea4c57583f0c247f8b073c125d884bc8
parentae652a37ec2db6782565a9e843bc967e060d3906 (diff)
downloadflashcards-8987c94b3654dd4ef40bea6745886a514bfa4532.tar.gz
flashcards-8987c94b3654dd4ef40bea6745886a514bfa4532.tar.bz2
flashcards-8987c94b3654dd4ef40bea6745886a514bfa4532.zip
Show phonetics if present when answer is correct
-rw-r--r--README.md4
-rw-r--r--src/gui/message.rs7
-rw-r--r--src/gui/mod.rs9
-rw-r--r--src/gui/question.rs95
4 files changed, 79 insertions, 36 deletions
diff --git a/README.md b/README.md
index 1a20b8e..6941979 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# Getting started
```bash
-nix develop --command bin/watch.sh
+nix develop --command bin/dev-server.sh
```
# Screenshot
@@ -22,7 +22,7 @@ Cards are created from a plain text `./deck` file:
- good moorning : bonjour
- alternative 1 | alternative 2 : choix 1 | choix 2
-- cat (indication) : chat
+- cat (indication) : chat [ʃa]
```
# Backlog
diff --git a/src/gui/message.rs b/src/gui/message.rs
index f0d826a..61f57ba 100644
--- a/src/gui/message.rs
+++ b/src/gui/message.rs
@@ -1,6 +1,6 @@
use crate::gui::util;
-use crossterm::event::{self, Event, KeyCode, KeyModifiers};
use anyhow::Result;
+use crossterm::event::{self, Event, KeyCode, KeyModifiers};
use tui::{
backend::Backend,
layout::{Alignment, Constraint, Direction, Layout},
@@ -32,7 +32,10 @@ pub fn show<B: Backend>(
if wait {
if let Event::Key(key) = event::read()? {
- if key.code == KeyCode::Char('q') || key.code == KeyCode::Char('c') && key.modifiers.contains(KeyModifiers::CONTROL) {
+ if key.code == KeyCode::Char('q')
+ || key.code == KeyCode::Char('c')
+ && key.modifiers.contains(KeyModifiers::CONTROL)
+ {
break;
}
}
diff --git a/src/gui/mod.rs b/src/gui/mod.rs
index 1053de1..b500706 100644
--- a/src/gui/mod.rs
+++ b/src/gui/mod.rs
@@ -4,10 +4,10 @@ pub mod util;
use crate::{db, space_repetition, util::time};
use anyhow::Result;
+use crossterm::terminal;
use rusqlite::Connection;
use std::io::Stdout;
use tui::{backend::CrosstermBackend, Terminal};
-use crossterm::{terminal};
pub type Term = Terminal<CrosstermBackend<Stdout>>;
@@ -36,7 +36,12 @@ pub fn start(
loop {
let now = time::seconds_since_unix_epoch()?;
- let title = title(deck_name, answers, db::count_available(conn).unwrap_or(0), hide_progress);
+ let title = title(
+ deck_name,
+ answers,
+ db::count_available(conn).unwrap_or(0),
+ hide_progress,
+ );
match db::pick_random_ready(conn) {
Some(card) => match question::ask(term, &title, &card)? {
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> {