use std::collections::HashMap;
use std::sync::LazyLock;
use super::lexicon::Forms;
pub(crate) fn plural(n: u64, forms: &Forms) -> &'static str {
plural_of(n, forms.one, forms.few, forms.many)
}
pub(crate) fn plural_of<'a>(n: u64, one: &'a str, few: &'a str, many: &'a str) -> &'a str {
if n % 10 == 1 && n % 100 != 11 {
one
} else if (2..=4).contains(&(n % 10)) && !(12..=14).contains(&(n % 100)) {
few
} else {
many
}
}
pub(crate) fn feminine_last(words: &mut [String]) {
if let Some(last) = words.last_mut() {
match last.as_str() {
"один" => *last = "одна".into(),
"два" => *last = "дві".into(),
_ => {}
}
}
}
pub(crate) fn neuter_last(words: &mut [String]) {
if let Some(last) = words.last_mut() {
if last == "один" {
*last = "одне".into();
}
}
}
fn map(pairs: &[(&'static str, &'static str)]) -> HashMap<&'static str, &'static str> {
pairs.iter().copied().collect()
}
#[rustfmt::skip]
pub(crate) static CARDINAL_TO_ORDINAL: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
map(&[
("нуль", "нульовий"), ("один", "перший"), ("одна", "перший"), ("два", "другий"),
("дві", "другий"), ("три", "третій"), ("чотири", "четвертий"), ("п'ять", "п'ятий"),
("шість", "шостий"), ("сім", "сьомий"), ("вісім", "восьмий"), ("дев'ять", "дев'ятий"),
("десять", "десятий"), ("одинадцять", "одинадцятий"), ("дванадцять", "дванадцятий"),
("тринадцять", "тринадцятий"), ("чотирнадцять", "чотирнадцятий"),
("п'ятнадцять", "п'ятнадцятий"), ("шістнадцять", "шістнадцятий"),
("сімнадцять", "сімнадцятий"), ("вісімнадцять", "вісімнадцятий"),
("дев'ятнадцять", "дев'ятнадцятий"), ("двадцять", "двадцятий"), ("тридцять", "тридцятий"),
("сорок", "сороковий"), ("п'ятдесят", "п'ятдесятий"), ("шістдесят", "шістдесятий"),
("сімдесят", "сімдесятий"), ("вісімдесят", "вісімдесятий"), ("дев'яносто", "дев'яностий"),
("сто", "сотий"), ("двісті", "двохсотий"), ("триста", "трьохсотий"),
("чотириста", "чотирьохсотий"), ("п'ятсот", "п'ятисотий"), ("шістсот", "шестисотий"),
("сімсот", "семисотий"), ("вісімсот", "восьмисотий"), ("дев'ятсот", "дев'ятисотий"),
("тисяча", "тисячний"), ("тисячі", "тисячний"), ("тисяч", "тисячний"),
])
});
#[rustfmt::skip]
pub(crate) static CASE_FORMS: LazyLock<HashMap<&'static str, [&'static str; 4]>> = LazyLock::new(|| {
[
("нуль", ["нуля", "нулю", "нулем", "нулі"]),
("один", ["одного", "одному", "одним", "одному"]),
("одна", ["однієї", "одній", "однією", "одній"]),
("два", ["двох", "двом", "двома", "двох"]),
("дві", ["двох", "двом", "двома", "двох"]),
("три", ["трьох", "трьом", "трьома", "трьох"]),
("чотири", ["чотирьох", "чотирьом", "чотирма", "чотирьох"]),
("п'ять", ["п'яти", "п'яти", "п'ятьма", "п'яти"]),
("шість", ["шести", "шести", "шістьма", "шести"]),
("сім", ["семи", "семи", "сьома", "семи"]),
("вісім", ["восьми", "восьми", "вісьмома", "восьми"]),
("дев'ять", ["дев'яти", "дев'яти", "дев'ятьма", "дев'яти"]),
("десять", ["десяти", "десяти", "десятьма", "десяти"]),
("одинадцять", ["одинадцяти", "одинадцяти", "одинадцятьма", "одинадцяти"]),
("дванадцять", ["дванадцяти", "дванадцяти", "дванадцятьма", "дванадцяти"]),
("тринадцять", ["тринадцяти", "тринадцяти", "тринадцятьма", "тринадцяти"]),
("чотирнадцять", ["чотирнадцяти", "чотирнадцяти", "чотирнадцятьма", "чотирнадцяти"]),
("п'ятнадцять", ["п'ятнадцяти", "п'ятнадцяти", "п'ятнадцятьма", "п'ятнадцяти"]),
("шістнадцять", ["шістнадцяти", "шістнадцяти", "шістнадцятьма", "шістнадцяти"]),
("сімнадцять", ["сімнадцяти", "сімнадцяти", "сімнадцятьма", "сімнадцяти"]),
("вісімнадцять", ["вісімнадцяти", "вісімнадцяти", "вісімнадцятьма", "вісімнадцяти"]),
("дев'ятнадцять", ["дев'ятнадцяти", "дев'ятнадцяти", "дев'ятнадцятьма", "дев'ятнадцяти"]),
("двадцять", ["двадцяти", "двадцяти", "двадцятьма", "двадцяти"]),
("тридцять", ["тридцяти", "тридцяти", "тридцятьма", "тридцяти"]),
("сорок", ["сорока", "сорока", "сорока", "сорока"]),
("п'ятдесят", ["п'ятдесяти", "п'ятдесяти", "п'ятдесятьма", "п'ятдесяти"]),
("шістдесят", ["шістдесяти", "шістдесяти", "шістдесятьма", "шістдесяти"]),
("сімдесят", ["сімдесяти", "сімдесяти", "сімдесятьма", "сімдесяти"]),
("вісімдесят", ["вісімдесяти", "вісімдесяти", "вісімдесятьма", "вісімдесяти"]),
("дев'яносто", ["дев'яноста", "дев'яноста", "дев'яноста", "дев'яноста"]),
("сто", ["ста", "ста", "ста", "ста"]),
("двісті", ["двохсот", "двомстам", "двомастами", "двохстах"]),
("триста", ["трьохсот", "трьомстам", "трьомастами", "трьохстах"]),
("чотириста", ["чотирьохсот", "чотирьомстам", "чотирмастами", "чотирьохстах"]),
("п'ятсот", ["п'ятисот", "п'ятистам", "п'ятьмастами", "п'ятистах"]),
("шістсот", ["шестисот", "шестистам", "шістьмастами", "шестистах"]),
("сімсот", ["семисот", "семистам", "сьомастами", "семистах"]),
("вісімсот", ["восьмисот", "восьмистам", "вісьмомастами", "восьмистах"]),
("дев'ятсот", ["дев'ятисот", "дев'ятистам", "дев'ятьмастами", "дев'ятистах"]),
("тисяча", ["тисячі", "тисячі", "тисячею", "тисячі"]),
("тисячі", ["тисяч", "тисячам", "тисячами", "тисячах"]),
("тисяч", ["тисяч", "тисячам", "тисячами", "тисячах"]),
("мільйон", ["мільйона", "мільйону", "мільйоном", "мільйоні"]),
("мільйони", ["мільйонів", "мільйонам", "мільйонами", "мільйонах"]),
("мільйонів", ["мільйонів", "мільйонам", "мільйонами", "мільйонах"]),
("мільярд", ["мільярда", "мільярду", "мільярдом", "мільярді"]),
("мільярди", ["мільярдів", "мільярдам", "мільярдами", "мільярдах"]),
("мільярдів", ["мільярдів", "мільярдам", "мільярдами", "мільярдах"]),
]
.into_iter()
.collect()
});
#[rustfmt::skip]
pub(crate) static COMPOUND_PREFIX_FORMS: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
map(&[
("один", "одно"), ("одна", "одно"), ("два", "дво"), ("дві", "дво"), ("три", "три"),
("чотири", "чотири"), ("п'ять", "п'яти"), ("шість", "шести"), ("сім", "семи"),
("вісім", "восьми"), ("дев'ять", "дев'яти"), ("десять", "десяти"),
("одинадцять", "одинадцяти"), ("дванадцять", "дванадцяти"), ("тринадцять", "тринадцяти"),
("чотирнадцять", "чотирнадцяти"), ("п'ятнадцять", "п'ятнадцяти"),
("шістнадцять", "шістнадцяти"), ("сімнадцять", "сімнадцяти"),
("вісімнадцять", "вісімнадцяти"), ("дев'ятнадцять", "дев'ятнадцяти"),
("двадцять", "двадцяти"), ("тридцять", "тридцяти"), ("сорок", "сорока"),
("п'ятдесят", "п'ятдесяти"), ("шістдесят", "шістдесяти"), ("сімдесят", "сімдесяти"),
("вісімдесят", "вісімдесяти"), ("дев'яносто", "дев'яносто"), ("сто", "сто"),
("двісті", "двохсот"), ("триста", "трьохсот"), ("чотириста", "чотирьохсот"),
("п'ятсот", "п'ятисот"), ("шістсот", "шестисот"), ("сімсот", "семисот"),
("вісімсот", "восьмисот"), ("дев'ятсот", "дев'ятисот"), ("тисяча", "тисячо"),
("тисячі", "тисячо"), ("тисяч", "тисячо"),
])
});
pub(crate) const fn pronunciation(letter: char) -> Option<&'static str> {
Some(match letter {
'А' => "а",
'Б' => "бе",
'В' => "ве",
'Г' => "ге",
'Ґ' => "ґе",
'Д' => "де",
'Е' => "е",
'Є' => "є",
'Ж' => "же",
'З' => "зе",
'И' => "и",
'І' => "і",
'Ї' => "ї",
'Й' => "йот",
'К' => "ка",
'Л' => "ел",
'М' => "ем",
'Н' => "ен",
'О' => "о",
'П' => "пе",
'Р' => "ер",
'С' => "ес",
'Т' => "те",
'У' => "у",
'Ф' => "еф",
'Х' => "ха",
'Ц' => "це",
'Ч' => "че",
'Ш' => "ша",
'Щ' => "ща",
'Ь' => "м'який знак",
'Ю' => "ю",
'Я' => "я",
_ => return None,
})
}
#[rustfmt::skip]
pub(crate) static TRANSLITERATION: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
map(&[
("a", "а"), ("b", "б"), ("c", "к"), ("d", "д"), ("e", "е"), ("f", "ф"), ("g", "г"),
("h", "г"), ("i", "і"), ("j", "дж"), ("k", "к"), ("l", "л"), ("m", "м"), ("n", "н"),
("o", "о"), ("p", "п"), ("q", "к"), ("r", "р"), ("s", "с"), ("t", "т"), ("u", "у"),
("v", "в"), ("w", "в"), ("x", "кс"), ("y", "и"), ("z", "з"), ("sh", "ш"), ("ch", "ч"),
("zh", "ж"), ("kh", "х"), ("ts", "ц"), ("yu", "ю"), ("ya", "я"), ("ye", "є"), ("yi", "ї"),
("oo", "у"), ("ee", "і"), ("sch", "щ"),
])
});
#[rustfmt::skip]
static ENDINGS: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
map(&[
("nom_n", "е"), ("nom_f", "а"), ("nom_pl", "і"), ("gen", "ого"), ("dat", "ому"),
("prep", "ому"), ("loc", "ому"), ("pl", "их"), ("loc_pl", "их"), ("acc_f", "у"),
("gen_f", "ої"), ("ins", "им"), ("ins_f", "ою"), ("ins_pl", "ими"), ("loc_f", "ій"),
])
});
#[rustfmt::skip]
static SOFT_ENDINGS: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
map(&[
("nom_n", "є"), ("nom_f", "я"), ("gen", "ього"), ("dat", "ьому"), ("prep", "ьому"),
("loc", "ьому"), ("pl", "іх"), ("loc_pl", "іх"), ("acc_f", "ю"), ("gen_f", "ьої"),
("ins", "ім"), ("ins_f", "ьою"), ("ins_pl", "іми"),
])
});
pub(crate) fn inflect_ordinal(stem: &str, form: &str) -> String {
if form == "nom_m" {
return stem.to_owned();
}
let Some(ending) = ENDINGS.get(form) else {
return stem.to_owned();
};
let (base, soft) = if let Some(base) = stem.strip_suffix("ій") {
(base, true)
} else if let Some(base) = stem.strip_suffix("ий") {
(base, false)
} else {
(stem, false)
};
let ending = if soft { SOFT_ENDINGS.get(form).unwrap_or(ending) } else { ending };
format!("{base}{ending}")
}