From 2fcab686c414e8d29d16cd51a2158065985758a0 Mon Sep 17 00:00:00 2001 From: Miquel Sabaté Solà Date: Thu, 15 Jan 2026 12:27:38 +0100 Subject: Ask for the inflection of nouns when practicing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miquel Sabaté Solà --- lib/mihi/src/lib.rs | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) (limited to 'lib') diff --git a/lib/mihi/src/lib.rs b/lib/mihi/src/lib.rs index 4d337b9..ea7839e 100644 --- a/lib/mihi/src/lib.rs +++ b/lib/mihi/src/lib.rs @@ -658,6 +658,60 @@ pub fn select_relevant_words( Ok(res) } +/// Select a set of words except for the ones passed in the `excluded` +/// vector. It also accepts a set of boolean `flags` as with functions like +/// `select_relevant_words`. +pub fn select_words_except(excluded: &[Word], flags: &Vec) -> Result, String> { + let ids = excluded.iter().map(|w| w.id).collect::>(); + let placeholders = ids.iter().map(|_| "?").collect::>().join(", "); + + let conn = get_connection()?; + let mut stmt = conn + .prepare( + format!( + "SELECT id, enunciated, particle, language_id, declension_id, conjugation_id, \ + kind, category, regular, locative, gender, suffix, translation, \ + succeeded, steps, flags, weight \ + FROM words \ + WHERE id NOT IN ({}) AND category IN ({}, {}) AND translation != '{{}}' {} \ + ORDER BY weight DESC, succeeded ASC, updated_at DESC + LIMIT 5", + placeholders, + Category::Noun as isize, + Category::Adjective as isize, + flags_clause(flags) + ) + .as_str(), + ) + .unwrap(); + + let mut it = stmt.query(rusqlite::params_from_iter(ids)).unwrap(); + let mut res = vec![]; + while let Some(row) = it.next().unwrap() { + res.push(Word { + id: row.get(0).unwrap(), + enunciated: row.get(1).unwrap(), + particle: row.get(2).unwrap(), + language: row.get::(3).unwrap().try_into()?, + declension_id: row.get(4).unwrap(), + conjugation_id: row.get(5).unwrap(), + kind: row.get(6).unwrap(), + category: row.get::(7).unwrap().try_into()?, + regular: row.get(8).unwrap(), + locative: row.get(9).unwrap(), + gender: row.get::(10).unwrap().try_into()?, + suffix: row.get(11).unwrap(), + translation: serde_json::from_str(&row.get::(12).unwrap()).unwrap(), + succeeded: row.get(13).unwrap(), + steps: row.get(14).unwrap(), + flags: serde_json::from_str(&row.get::(15).unwrap()).unwrap(), + weight: row.get(16).unwrap(), + }); + } + + Ok(res) +} + pub fn update_success(word: &Word, success: isize, steps: isize) -> Result<(), String> { let conn = get_connection()?; @@ -1148,6 +1202,60 @@ fn case_str_to_i(key: &str) -> Result { } } +/// Returns a string which describes the enunciate of the given `word` as +/// inflected considering the singular/plural declension `row`. +pub fn get_inflected_from(word: &Word, row: &[DeclensionInfo; 2]) -> String { + if word.is_flag_set("onlysingular") { + row[0].inflected.join("/") + } else if word.is_flag_set("onlyplural") { + row[1].inflected.join("/") + } else { + format!( + "{}, {}", + row[0].inflected.join("/"), + row[1].inflected.join("/") + ) + } +} + +/// Returns the declension table of the given `word` by assuming it's a noun. +pub fn get_noun_table(word: &Word) -> Result { + let gender = match word.gender { + Gender::MasculineOrFeminine => Gender::Masculine as usize, + _ => word.gender as usize, + }; + group_declension_inflections(word, &word.kind, gender) +} + +/// Returns the declension tables for each gender of the given `word` by +/// assuming it's an adjective. +pub fn get_adjective_table(word: &Word) -> Result<[DeclensionTable; 3], String> { + // Unless the word is a special "unus nauta" variant, force 1/2 declension + // adjectives in the feminine to grab the "a" kind. + let kind_f = if word.kind.as_str() == "unusnauta" { + &word.kind + } else { + match word.declension_id { + Some(1 | 2) => &"a".to_string(), + _ => &word.kind, + } + }; + + let kind_n = if word.kind == "us" { + &"um".to_owned() + } else { + &word.kind + }; + + Ok([ + group_declension_inflections(word, &word.kind, Gender::Masculine as usize)?, + group_declension_inflections(word, kind_f, Gender::Feminine as usize)?, + group_declension_inflections(word, kind_n, Gender::Neuter as usize)?, + ]) +} + +/// Returns the declension table for the given `word` by using the given `kind` +/// and `gender`. pub fn group_declension_inflections( word: &Word, kind: &String, -- cgit v1.2.3