using DNTPersianUtils.Core; using RMuseum.Models.Ganjoor; using RMuseum.Models.Ganjoor.ViewModels; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; namespace RMuseum.Services.Implementation { /// /// Language Utilitis /// public static class LanguageUtils { /// /// Persian Alphabet /// public const string PersianAlphabet = "آابپتثجچحخدذرزژسشصضطظعغفقکگلمنوهیئؤء"; /// /// English Alphabet /// public const string EnglishLowerCaseAlphabet = "abcdefghijklmnopqrstuvwxyz"; /// /// Check to see if input Contains Only Specific Characters /// /// /// /// /// public static string GetFirstNotMatchingCharacter(string input, string specfics, string additional = "") { string all = specfics + additional; foreach (char c in input) if (all.IndexOf(c) == -1) return (c + ""); return ""; } /// /// make text searchable /// /// /// public static string MakeTextSearchable(string text) { return text.Replace("‌", " ")//replace zwnj with space .Replace("ّ", "")//tashdid .Replace("َ", "")//a .Replace("ِ", "")//e .Replace("ُ", "")//o .Replace("ً", "")//an .Replace("ٍ", "")//en .Replace("ٌ", "")//on .Replace(".", "")//dot .Replace("،", "")//virgool .Replace("!", "") .Replace("؟", "") .Replace("ٔ", "")//ye .Replace(":", "") .Replace("ئ", "ی") .Replace("؛", "") .Replace(";", "") .Replace("*", "") .Replace(")", "") .Replace("(", "") .Replace("[", "") .Replace("]", "") .Replace("\"", "") .Replace("'", "") .Replace("«", "") .Replace("»", "") .Replace("ْ", "")//sokoon ; } public static string CleanTextForTransileration(string text) { if (string.IsNullOrEmpty(text)) return text; return text.Replace("‌", " ")//replace zwnj with space .Replace("ّ", "")//tashdid .Replace("َ", "")//a .Replace("ِ", "")//e .Replace("ُ", "")//o .Replace("ً", "")//an .Replace("ٍ", "")//en .Replace("ٌ", "")//on .Replace("ٔ", "")//ye .Replace("ْ", "")//sokoon ; } /// /// simple, best-effort Perso-Arabic -> Tajik Cyrillic letter substitution. /// NOT a linguistically correct transliteration: Perso-Arabic script does not /// write short vowels, so a letter-by-letter map cannot recover them (that's /// why a dedicated tool like persian-tajik.ir exists, and why the bulk of /// TajikGanjoor's content comes from real TajikPoems/TajikCats/TajikPoets rows /// rather than on-the-fly conversion). This exists only as a fallback for /// spots - like a neighbouring poem's excerpt on the next/previous nav - that /// don't have a proper Tajik translation in the database yet, so at least /// something in Cyrillic is shown instead of raw Perso-Arabic script. /// private static readonly Dictionary _persianToTajikMap = new Dictionary() { ['آ'] = "о", ['ا'] = "о", ['ب'] = "б", ['پ'] = "п", ['ت'] = "т", ['ث'] = "с", ['ج'] = "ҷ", ['چ'] = "ч", ['ح'] = "ҳ", ['خ'] = "х", ['د'] = "д", ['ذ'] = "з", ['ر'] = "р", ['ز'] = "з", ['ژ'] = "ж", ['س'] = "с", ['ش'] = "ш", ['ص'] = "с", ['ض'] = "з", ['ط'] = "т", ['ظ'] = "з", ['ع'] = "ъ", ['غ'] = "ғ", ['ف'] = "ф", ['ق'] = "қ", ['ک'] = "к", ['ك'] = "к", ['گ'] = "г", ['ل'] = "л", ['م'] = "м", ['ن'] = "н", ['و'] = "в", ['ه'] = "ҳ", ['ی'] = "ӣ", ['ي'] = "ӣ", ['ئ'] = "ъ", ['ؤ'] = "в", ['ء'] = "ъ", ['ة'] = "ат", ['؟'] = "?", ['،'] = ",", ['؛'] = ";", ['۰'] = "0", ['۱'] = "1", ['۲'] = "2", ['۳'] = "3", ['۴'] = "4", ['۵'] = "5", ['۶'] = "6", ['۷'] = "7", ['۸'] = "8", ['۹'] = "9", }; public static string TransliteratePersianToTajik(string text) { if (string.IsNullOrEmpty(text)) return text; text = CleanTextForTransileration(text); var sb = new System.Text.StringBuilder(text.Length); foreach (char c in text) { sb.Append(_persianToTajikMap.TryGetValue(c, out string mapped) ? mapped : c.ToString()); } return sb.ToString(); } public static string SameSoundLetters(string text) { return text.Replace("آ", "ا").Replace("ث", "س").Replace("ح", "ه").Replace("ذ", "ز").Replace("ص", "س").Replace("ض", "ز").Replace("ط", "ت").Replace("ظ", "ز").Replace("غ", "ق"); } private static string PrepareTextForFindingRhyme(string text) { return MakeTextSearchable(text) .Replace("لله", "للاه") .Replace("آ", "ا") .Replace("‍", "") .Replace("‏", "") .Replace("‌", "") .Replace(" ", "") .Trim(); } /// /// find rhyme /// /// /// /// /// /// public static GanjooRhymeAnalysisResult FindRhyme(List verses, bool secondPhase = false, bool bandCouplets = false, bool tryWholeVerses = false) { try { List verseTextList = verses.Count == 2 || tryWholeVerses ? verses.Select(v => v.Text).ToList() : bandCouplets ? verses.Where(v => v.VersePosition == VersePosition.CenteredVerse2).Select(v => v.Text).ToList() : verses.Where(v => v.VersePosition == VersePosition.Left).Select(v => v.Text).ToList(); if (verseTextList.Count > 1) { string rhyme = PrepareTextForFindingRhyme(verseTextList[0]); if (string.IsNullOrEmpty(rhyme)) { return new GanjooRhymeAnalysisResult() { Rhyme = "", FailVerse = verseTextList[0] }; } if (secondPhase) { if (rhyme.Length > 0 && rhyme[rhyme.Length - 1] == 'ی') rhyme = rhyme.Remove(rhyme.Length - 1); } for (int j = 1; j < verseTextList.Count; j++) { string verseText = PrepareTextForFindingRhyme(verseTextList[j]); if (secondPhase) { if (verseText.Length > 0 && verseText[verseText.Length - 1] == 'ی') { verseText = verseText.Remove(verseText.Length - 1); } } string oldRhyme = rhyme; rhyme = ""; int i = oldRhyme.Length - 1; while ( (oldRhyme[i] == verseText[verseText.Length - oldRhyme.Length + i]) || ( (oldRhyme[i] == 'ذ') && (verseText[verseText.Length - oldRhyme.Length + i] == 'د') ) || ( (oldRhyme[i] == 'د') && (verseText[verseText.Length - oldRhyme.Length + i] == 'ذ') ) || ( (oldRhyme[i] == 'ی') && (verseText[verseText.Length - oldRhyme.Length + i] == 'ا') ) || ( (oldRhyme[i] == 'ا') && (verseText[verseText.Length - oldRhyme.Length + i] == 'ی') ) || (oldRhyme[i] == verseText[verseText.Length - oldRhyme.Length + i]) || ( (oldRhyme[i] == 'پ') && (verseText[verseText.Length - oldRhyme.Length + i] == 'ب') ) || ( (oldRhyme[i] == 'ب') && (verseText[verseText.Length - oldRhyme.Length + i] == 'پ') ) || (oldRhyme[i] == 'ة') && (verseText[verseText.Length - oldRhyme.Length + i] == 'ت') || (oldRhyme[i] == 'ت') && (verseText[verseText.Length - oldRhyme.Length + i] == 'ة') ) { rhyme = oldRhyme[i] + rhyme; i--; if (i == -1) break; } if (rhyme.Length == 0) { if (verses.Count == 2 && verseTextList.Count == 2) { rhyme = PrepareTextForFindingRhyme(verseTextList[1]); if(rhyme.Length > 50) { rhyme = ""; } return new GanjooRhymeAnalysisResult() { Rhyme = rhyme, //rhyme.Length > 50 condition check removed to search using prosody meters FailVerse = "", }; } return new GanjooRhymeAnalysisResult() { Rhyme = "", FailVerse = verseText }; } } if (!secondPhase) { if (string.IsNullOrEmpty(rhyme)) { return FindRhyme(verses, true); } } ////rhyme.Length > 50 condition check removed to search using prosody meters /*if (rhyme.Length > 50) { return new GanjooRhymeAnalysisResult() { Rhyme = "", FailVerse = "", }; }*/ if (rhyme.Length > 50) { rhyme = ""; } return new GanjooRhymeAnalysisResult() { Rhyme = rhyme, FailVerse = "" }; } } catch { } return new GanjooRhymeAnalysisResult() { Rhyme = "", FailVerse = "" }; } /// /// format money /// /// /// public static string FormatMoney(decimal amount) { return amount.ToString("N0", new CultureInfo("fa-IR")).ToPersianNumbers(); } /// /// format datetime /// /// /// public static string FormatDate(DateTime dateTime) { return $"{dateTime.ToPersianYearMonthDay().Day.ToPersianNumbers()}م {PersianCulture.GetPersianMonthName(dateTime.ToPersianYearMonthDay().Month)} {dateTime.ToPersianYearMonthDay().Year.ToPersianNumbers()}"; } /// /// short date /// /// /// public static string FormatInShortDate(DateTime dateTime) { return dateTime.Year < 623 ? "" : $"{dateTime.ToPersianYearMonthDay().Year.ToPersianNumbers()}/{dateTime.ToPersianYearMonthDay().Month.ToString().PadLeft(2, '0').ToPersianNumbers()}/{dateTime.ToPersianYearMonthDay().Day.ToString().PadLeft(2, '0').ToPersianNumbers()}"; } } }