M Cargo.lock => Cargo.lock +1 -1
@@ 306,7 306,7 @@ dependencies = [
[[package]]
name = "der_die_das"
-version = "0.2.1"
+version = "0.2.2"
dependencies = [
"clap",
"clap_complete_command",
M Cargo.toml => Cargo.toml +1 -1
@@ 1,6 1,6 @@
[package]
name = "der_die_das"
-version = "0.2.2"
+version = "0.2.3"
edition = "2021"
authors = ["Perma Alesheikh <me@prma.dev>"]
license = "EUPL-1.2"
M src/arugments.rs => src/arugments.rs +1 -0
@@ 60,6 60,7 @@ pub enum ListCommands {
#[derive(Clone, Debug, Subcommand)]
pub enum AskCommands {
Nouns,
+ Group,
}
#[derive(Clone, Debug, Subcommand)]
M src/commands.rs => src/commands.rs +63 -30
@@ 153,34 153,21 @@ impl StringValidator for ValidateLastWordShouldMatchTheSpelling {
}
}
-pub fn ask_next(storage: Storage, group_config: GroupConfig) -> Result<()> {
- let nouns = storage.all_nouns()?;
- let attempts = storage.all_attempts()?;
- let h = History { nouns, attempts };
-
- let chosen = if group_config.enable {
- h.next_with_group(group_config.threshold)
- } else {
- h.next()
- }
- .ok_or_eyre("there are no words available for asking. Have you added some?")?;
-
- let prompt = format!("{} {}\n>", "___".reversed(), chosen.0.word.reversed());
+fn ask_noun(storage: &Storage, noun: &Noun) -> Result<()> {
+ let prompt = format!("{} {}\n>", "___".reversed(), noun.word.reversed());
let resp = inquire::Text::new(&prompt)
- .with_help_message(&chosen.0.meaning)
+ .with_help_message(&noun.meaning)
.with_validators(&[
Box::new(ValidateShouldBeTwoWords {}),
Box::new(ValidateFirstWordShouldBeArticle {}),
- Box::new(ValidateLastWordShouldMatchTheSpelling(chosen.0.word)),
+ Box::new(ValidateLastWordShouldMatchTheSpelling(noun.word.to_owned())),
])
.prompt()?
.to_owned();
-
let resp: Vec<_> = resp.split_whitespace().collect();
if resp.len() != 2 {
return Err(eyre!("response is more than two words!"));
}
-
let article = match resp
.first()
.ok_or_eyre("something impossible happend!")?
@@ 194,14 181,12 @@ pub fn ask_next(storage: Storage, group_config: GroupConfig) -> Result<()> {
}?;
let now = time::OffsetDateTime::now_utc();
- if !chosen.0.articles.contains(&article) {
+ if !noun.articles.contains(&article) {
println!("{}", "Article did not match!".red());
println!(
"correct article(s) is(are):\t{}",
- chosen
- .0
- .articles
- .into_iter()
+ noun.articles
+ .iter()
.map(|s| s.to_string())
.collect::<Vec<_>>()
.join(", ")
@@ 211,35 196,83 @@ pub fn ask_next(storage: Storage, group_config: GroupConfig) -> Result<()> {
storage.save_attempt(Attempt {
id: now.unix_timestamp_nanos(),
at: now,
- for_word: chosen.0.id,
+ for_word: noun.id,
what_happened: der_die_das::attempt::AttemptResult::WrongArticle(article),
})?;
+ ask_noun(storage, noun)
} else {
storage.save_attempt(Attempt {
id: now.unix_timestamp_nanos(),
at: now,
- for_word: chosen.0.id,
+ for_word: noun.id,
what_happened: der_die_das::attempt::AttemptResult::Success,
})?;
println!("{}", "Correct!".green().bold());
- };
+ Ok(())
+ }
+}
+fn get_confidence(storage: &Storage, id: i128) -> Result<(Noun, u8)> {
let nouns = storage.all_nouns()?;
let attempts = storage.all_attempts()?;
let h = History { nouns, attempts };
- let word_with_new_confidence = h
- .confidence_map()
+ h.confidence_map()
.into_iter()
- .find(|(n, _)| n.id == chosen.0.id)
- .ok_or_eyre("Some how the word is not there any more!")?;
+ .find(|(n, _)| n.id == id)
+ .ok_or_eyre("Some how the word is not there any more!")
+}
+
+pub fn ask_next(storage: &Storage, group_config: GroupConfig) -> Result<()> {
+ let nouns = storage.all_nouns()?;
+ let attempts = storage.all_attempts()?;
+ let h = History { nouns, attempts };
+
+ let chosen = if group_config.enable {
+ h.next_with_group(group_config.threshold)
+ } else {
+ h.next()
+ }
+ .ok_or_eyre("there are no words available for asking. Have you added some?")?;
+
+ ask_noun(storage, &chosen.0)?;
+
+ let (_, conf) = get_confidence(storage, chosen.0.id)?;
+
println!(
"The confidence for the word is now at {}.",
- word_with_new_confidence.1.to_string().bold().reversed()
+ conf.to_string().bold().reversed()
);
Ok(())
}
+pub fn group_ask(storage: &Storage, group_config: GroupConfig) -> Result<()> {
+ let nouns = storage.all_nouns()?;
+ let attempts = storage.all_attempts()?;
+ let h = History { nouns, attempts };
+
+ let gr = h
+ .next_group(group_config.threshold)
+ .ok_or_eyre("You don't have any words yet.")?;
+
+ let number_of_words_in_gr = gr.len();
+ gr.into_iter().enumerate().try_for_each(|(i, (noun, _))| {
+ println!();
+ println!("{}/{}", (i + 1).bold(), number_of_words_in_gr);
+
+ ask_noun(storage, &noun)?;
+
+ let (_, conf) = get_confidence(storage, noun.id)?;
+
+ println!(
+ "The confidence for the word is now at {}.",
+ conf.to_string().bold().reversed()
+ );
+
+ Ok(())
+ })
+}
+
pub fn import_nouns(storage: Storage, at: PathBuf) -> Result<()> {
if !at.try_exists()? {
return Err(eyre!(format!(
M src/history.rs => src/history.rs +20 -0
@@ 69,6 69,25 @@ impl History {
sets.first().cloned()
}
+ pub fn next_group(&self, threshold: u8) -> Option<Vec<(Noun, u8)>> {
+ let sets = self.grouped_confidence_map();
+ if sets.is_empty() {
+ return None;
+ }
+ let under_threshold: HashMap<_, _> = sets
+ .into_iter()
+ .filter(|(_, nouns)| nouns.iter().any(|(_, c)| c <= &threshold))
+ .collect();
+
+ if under_threshold.is_empty() {
+ return self.next_group(u8::MAX);
+ }
+ let mut ks: Vec<_> = under_threshold.keys().collect();
+ ks.sort_unstable();
+ let mut left = under_threshold.get(ks.first()?.to_owned())?.to_owned();
+ left.sort_unstable_by_key(|s| s.1);
+ Some(left)
+ }
pub fn next_with_group(&self, threshold: u8) -> Option<(Noun, u8)> {
let sets = self.grouped_confidence_map();
@@ 84,6 103,7 @@ impl History {
if under_threshold.is_empty() {
return self.next_with_group(u8::MAX);
}
+
let mut ks: Vec<_> = under_threshold.keys().collect();
ks.sort_unstable();
let mut left = under_threshold.get(ks.first()?.to_owned())?.to_owned();
M src/main.rs => src/main.rs +2 -4
@@ 58,14 58,12 @@ fn main() -> Result<()> {
Commands::List(list_commands) => match list_commands {
arugments::ListCommands::Nouns => commands::list_nouns(storage),
},
- // Commands::Ask(ask_commands) => match ask_commands {
- // arugments::AskCommands::Nouns => commands::ask_noun(storage),
- // },
Commands::Import(import_commands) => match import_commands {
arugments::ImportCommands::Nouns { at } => commands::import_nouns(storage, at),
},
Commands::Ask(ask_commands) => match ask_commands {
- arugments::AskCommands::Nouns => commands::ask_next(storage, configs.group),
+ arugments::AskCommands::Nouns => commands::ask_next(&storage, configs.group),
+ arugments::AskCommands::Group => commands::group_ask(&storage, configs.group),
},
},
None => todo!(),