using System.Text; using System.Text.RegularExpressions; using Content.Server.Chat.Systems; namespace Content.Server._White.TTS; // ReSharper disable once InconsistentNaming public sealed partial class TTSSystem { private void OnTransformSpeech(TransformSpeechEvent args) { if (!_isEnabled) return; args.Message = args.Message.Replace("+", ""); } private string Sanitize(string text) { text = text.Trim(); text = Regex.Replace(text, @"Ё", "Е"); text = Regex.Replace(text, @"[^a-zA-Zа-яА-ЯёЁ0-9,\-,+, ,?,!,.]", ""); text = Regex.Replace(text, @"[a-zA-Z]", ReplaceLat2Cyr, RegexOptions.Multiline | RegexOptions.IgnoreCase); text = Regex.Replace(text, @"(? WordReplacement = new Dictionary() { {"нт", "Эн Тэ"}, {"смо", "Эс Мэ О"}, {"гп", "Гэ Пэ"}, {"рд", "Эр Дэ"}, {"гсб", "Гэ Эс Бэ"}, {"гв", "Гэ Вэ"}, {"нр", "Эн Эр"}, {"срп", "Эс Эр Пэ"}, {"цк", "Цэ Каа"}, {"рнд", "Эр Эн Дэ"}, {"сб", "Эс Бэ"}, {"рцд", "Эр Цэ Дэ"}, {"брпд", "Бэ Эр Пэ Дэ"}, {"рпд", "Эр Пэ Дэ"}, {"рпед", "Эр Пед"}, {"тсф", "Тэ Эс Эф"}, {"срт", "Эс Эр Тэ"}, {"обр", "О Бэ Эр"}, {"кпк", "Кэ Пэ Каа"}, {"пда", "Пэ Дэ А"}, {"id", "Ай Ди"}, {"мщ", "Эм Ще"}, {"вт", "Вэ Тэ"}, {"ерп", "Йе Эр Пэ"}, {"се", "Эс Йе"}, {"апц", "А Пэ Цэ"}, {"лкп", "Эл Ка Пэ"}, {"см", "Эс Эм"}, {"ека", "Йе Ка"}, {"ка", "Кэ А"}, {"бса", "Бэ Эс Аа"}, {"тк", "Тэ Ка"}, {"бфл", "Бэ Эф Эл"}, {"бщ", "Бэ Щэ"}, {"кк", "Кэ Ка"}, {"ск", "Эс Ка"}, {"зк", "Зэ Ка"}, {"ерт", "Йе Эр Тэ"}, {"вкд", "Вэ Ка Дэ"}, {"нтр", "Эн Тэ Эр"}, {"пнт", "Пэ Эн Тэ"}, {"авд", "А Вэ Дэ"}, {"пнв", "Пэ Эн Вэ"}, {"ссд", "Эс Эс Дэ"}, {"кпб", "Кэ Пэ Бэ"}, {"сссп", "Эс Эс Эс Пэ"}, {"крб", "Ка Эр Бэ"}, {"бд", "Бэ Дэ"}, {"сст", "Эс Эс Тэ"}, {"скс", "Эс Ка Эс"}, {"икн", "И Ка Эн"}, {"нсс", "Эн Эс Эс"}, {"емп", "Йе Эм Пэ"}, {"бс", "Бэ Эс"}, {"цкс", "Цэ Ка Эс"}, {"срд", "Эс Эр Дэ"}, {"жпс", "Джи Пи Эс"}, {"gps", "Джи Пи Эс"}, {"ннксс", "Эн Эн Ка Эс Эс"}, {"ss", "Эс Эс"}, {"сс", "Эс Эс"}, {"тесла", "тэсла"}, {"трейзен", "трэйзэн"}, {"нанотрейзен", "нанотрэйзэн"}, {"рпзд", "Эр Пэ Зэ Дэ"}, {"кз", "Кэ Зэ"}, }; private static readonly IReadOnlyDictionary ReverseTranslit = new Dictionary() { {"a", "а"}, {"b", "б"}, {"v", "в"}, {"g", "г"}, {"d", "д"}, {"e", "е"}, {"je", "ё"}, {"zh", "ж"}, {"z", "з"}, {"i", "и"}, {"y", "й"}, {"k", "к"}, {"l", "л"}, {"m", "м"}, {"n", "н"}, {"o", "о"}, {"p", "п"}, {"r", "р"}, {"s", "с"}, {"t", "т"}, {"u", "у"}, {"f", "ф"}, {"h", "х"}, {"c", "ц"}, {"x", "кс"}, {"ch", "ч"}, {"sh", "ш"}, {"jsh", "щ"}, {"hh", "ъ"}, {"ih", "ы"}, {"jh", "ь"}, {"eh", "э"}, {"ju", "ю"}, {"ja", "я"}, }; } // Source: https://codelab.ru/s/csharp/digits2phrase public static class NumberConverter { private static readonly string[] Frac20Male = { "", "один", "два", "три", "четыре", "пять", "шесть", "семь", "восемь", "девять", "десять", "одиннадцать", "двенадцать", "тринадцать", "четырнадцать", "пятнадцать", "шестнадцать", "семнадцать", "восемнадцать", "девятнадцать" }; private static readonly string[] Frac20Female = { "", "одна", "две", "три", "четыре", "пять", "шесть", "семь", "восемь", "девять", "десять", "одиннадцать", "двенадцать", "тринадцать", "четырнадцать", "пятнадцать", "шестнадцать", "семнадцать", "восемнадцать", "девятнадцать" }; private static readonly string[] Hunds = { "", "сто", "двести", "триста", "четыреста", "пятьсот", "шестьсот", "семьсот", "восемьсот", "девятьсот" }; private static readonly string[] Tens = { "", "десять", "двадцать", "тридцать", "сорок", "пятьдесят", "шестьдесят", "семьдесят", "восемьдесят", "девяносто" }; public static string NumberToText(long value, bool male = true) { if (value >= (long)Math.Pow(10, 15)) return String.Empty; if (value == 0) return "ноль"; var str = new StringBuilder(); if (value < 0) { str.Append("минус"); value = -value; } value = AppendPeriod(value, 1000000000000, str, "триллион", "триллиона", "триллионов", true); value = AppendPeriod(value, 1000000000, str, "миллиард", "миллиарда", "миллиардов", true); value = AppendPeriod(value, 1000000, str, "миллион", "миллиона", "миллионов", true); value = AppendPeriod(value, 1000, str, "тысяча", "тысячи", "тысяч", false); var hundreds = (int)(value / 100); if (hundreds != 0) AppendWithSpace(str, Hunds[hundreds]); var less100 = (int)(value % 100); var frac20 = male ? Frac20Male : Frac20Female; if (less100 < 20) AppendWithSpace(str, frac20[less100]); else { var tens = less100 / 10; AppendWithSpace(str, Tens[tens]); var less10 = less100 % 10; if (less10 != 0) str.Append(" " + frac20[less100%10]); } return str.ToString(); } private static void AppendWithSpace(StringBuilder stringBuilder, string str) { if (stringBuilder.Length > 0) stringBuilder.Append(" "); stringBuilder.Append(str); } private static long AppendPeriod( long value, long power, StringBuilder str, string declension1, string declension2, string declension5, bool male) { var thousands = (int)(value / power); if (thousands > 0) { AppendWithSpace(str, NumberToText(thousands, male, declension1, declension2, declension5)); return value % power; } return value; } private static string NumberToText( long value, bool male, string valueDeclensionFor1, string valueDeclensionFor2, string valueDeclensionFor5) { return NumberToText(value, male) + " " + GetDeclension((int)(value % 10), valueDeclensionFor1, valueDeclensionFor2, valueDeclensionFor5); } private static string GetDeclension(int val, string one, string two, string five) { var t = (val % 100 > 20) ? val % 10 : val % 20; switch (t) { case 1: return one; case 2: case 3: case 4: return two; default: return five; } } }