Decompiled source of RuInputTerminal v1.0.0

BepInEx/plugins/RUInputTerminal.dll

Decompiled 16 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("RUInputTerminal")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RUInputTerminal")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("a185a4da-d866-43e6-b1c1-cce10fdcd5a4")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace RuInputTerminalMod;

[BepInPlugin("maxteam.ruinputterminal", "RuInputTerminal", "1.6.2")]
public sealed class Plugin : BaseUnityPlugin
{
	public const string Guid = "maxteam.ruinputterminal";

	public const string Name = "RuInputTerminal";

	public const string Version = "1.6.2";

	internal static ManualLogSource Log;

	private void Awake()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		Log = ((BaseUnityPlugin)this).Logger;
		new Harmony("maxteam.ruinputterminal").PatchAll();
		Log.LogInfo((object)"RuInputTerminal loaded successfully.");
	}
}
internal sealed class TranslationEntry
{
	public string English { get; }

	public string Russian { get; }

	public string[] Aliases { get; }

	public TranslationEntry(string english, string russian, params string[] aliases)
	{
		English = english ?? string.Empty;
		Russian = russian ?? string.Empty;
		Aliases = aliases ?? Array.Empty<string>();
	}
}
internal sealed class PrefixCandidate
{
	public string Variant { get; }

	public string Canonical { get; }

	public PrefixCandidate(string variant, string canonical)
	{
		Variant = variant ?? string.Empty;
		Canonical = canonical ?? string.Empty;
	}
}
[HarmonyPatch(typeof(Terminal), "OnSubmit")]
internal static class TerminalOnSubmitPatch
{
	private static readonly Dictionary<char, char> RuToEnKeyboard = new Dictionary<char, char>
	{
		{ 'й', 'q' },
		{ 'ц', 'w' },
		{ 'у', 'e' },
		{ 'к', 'r' },
		{ 'е', 't' },
		{ 'н', 'y' },
		{ 'г', 'u' },
		{ 'ш', 'i' },
		{ 'щ', 'o' },
		{ 'з', 'p' },
		{ 'х', '[' },
		{ 'ъ', ']' },
		{ 'ф', 'a' },
		{ 'ы', 's' },
		{ 'в', 'd' },
		{ 'а', 'f' },
		{ 'п', 'g' },
		{ 'р', 'h' },
		{ 'о', 'j' },
		{ 'л', 'k' },
		{ 'д', 'l' },
		{ 'ж', ';' },
		{ 'э', '\'' },
		{ 'я', 'z' },
		{ 'ч', 'x' },
		{ 'с', 'c' },
		{ 'м', 'v' },
		{ 'и', 'b' },
		{ 'т', 'n' },
		{ 'ь', 'm' },
		{ 'б', ',' },
		{ 'ю', '.' },
		{ 'ё', '`' },
		{ '.', '/' }
	};

	private static readonly Dictionary<char, char> EnToRuKeyboard = BuildReverseMap(RuToEnKeyboard);

	private static readonly TranslationEntry[] CommandEntries = new TranslationEntry[12]
	{
		new TranslationEntry("store", "стор", "магазин"),
		new TranslationEntry("bestiary", "бестиарий"),
		new TranslationEntry("moons", "луна", "луны", "moon"),
		new TranslationEntry("view", "вью", "смотреть", "посмотреть"),
		new TranslationEntry("scan", "скан", "сканировать"),
		new TranslationEntry("ping", "пинг"),
		new TranslationEntry("confirm", "подтвердить", "да"),
		new TranslationEntry("deny", "отмена", "нет"),
		new TranslationEntry("sigurd", "сигурд"),
		new TranslationEntry("storage", "хранилище", "склад"),
		new TranslationEntry("help", "хелп", "помощь"),
		new TranslationEntry("other", "другое", "прочее")
	};

	private static readonly TranslationEntry[] ContentEntries = new TranslationEntry[108]
	{
		new TranslationEntry("rend", "ренд"),
		new TranslationEntry("dine", "дайн"),
		new TranslationEntry("titan", "титан"),
		new TranslationEntry("assurance", "ассуранс"),
		new TranslationEntry("offense", "офенс", "офе", "offense"),
		new TranslationEntry("vow", "вау"),
		new TranslationEntry("march", "марч"),
		new TranslationEntry("adamance", "адамэнс", "адаманс"),
		new TranslationEntry("embrion", "эмбрион"),
		new TranslationEntry("artifice", "артифис"),
		new TranslationEntry("experimentation", "экспериментейшн"),
		new TranslationEntry("the company building", "здание компании", "company building", "company"),
		new TranslationEntry("bunker spiders", "бункерный паук", "паук", "spider"),
		new TranslationEntry("eyeless dogs", "слепая собака", "собака", "пёс", "dog"),
		new TranslationEntry("spore lizards", "споровая ящерица", "ящерица", "spore lizard"),
		new TranslationEntry("maneaters", "пожиратель", "пожиратель"),
		new TranslationEntry("backwater gunkfish", "болотный гункфиш", "гункфиш"),
		new TranslationEntry("forest keepers", "лесной хранитель", "хранитель", "forest keeper"),
		new TranslationEntry("baboon hawks", "бабуин-ястреб", "ястреб", "baboon hawk"),
		new TranslationEntry("roaming locusts", "бродячая саранча", "саранча", "locust"),
		new TranslationEntry("cadaver blooms", "трупоцвет", "трупоцвет", "cadaver"),
		new TranslationEntry("circuit bees", "электропчёлы", "пчела", "bee"),
		new TranslationEntry("manticoils", "мантикойл", "manticoil"),
		new TranslationEntry("thumpers", "топотун", "топотун", "thumper"),
		new TranslationEntry("snare fleas", "многоножка", "многоножка", "flea"),
		new TranslationEntry("earth leviathans", "левиафан", "левиафан", "leviathan"),
		new TranslationEntry("jesters", "шут", "шут", "джестер", "jester"),
		new TranslationEntry("kidnapper fox", "лиса-похититель", "лиса", "похититель", "fox"),
		new TranslationEntry("butlers", "дворецкий", "дворецкий", "butler"),
		new TranslationEntry("old birds", "старинная птица", "птица", "bird"),
		new TranslationEntry("brackens", "цветочник", "цветочник", "брэкен", "брекен", "bracken"),
		new TranslationEntry("coil-heads", "пружиноголовый", "coil head", "coilhead"),
		new TranslationEntry("hoarding bugs", "жук-собиратель", "жук собиратель", "bug"),
		new TranslationEntry("hygroderes", "слизь", "слизь", "slime"),
		new TranslationEntry("nutcrackers", "щелкунчик", "щелкунчик", "nutcracker"),
		new TranslationEntry("ghost girl", "девочка-призрак", "девочка призрак", "ghost girl", "ghost"),
		new TranslationEntry("mask hornets", "шершень в маске", "шершень", "hornet"),
		new TranslationEntry("barber", "цирюльник", "цирюльник", "барбер", "брабер"),
		new TranslationEntry("tulip snakes", "тюльпановая змея", "змея", "snake"),
		new TranslationEntry("feiopar", "скрытень"),
		new TranslationEntry("giant sapsucker", "большой сокосос", "сокосос", "sapsucker"),
		new TranslationEntry("vain shroud", "тщеславный саван", "саван"),
		new TranslationEntry("lasso man", "человек лассо", "лассо", "lasso man"),
		new TranslationEntry("flashlight", "фонарик"),
		new TranslationEntry("pro-flashlight", "про-фонарик", "про фонарик"),
		new TranslationEntry("shovel", "лопата"),
		new TranslationEntry("walkie-talkie", "рация", "рац"),
		new TranslationEntry("lockpicker", "взломщик замков"),
		new TranslationEntry("tzp-inhalant", "tzp-ингалятор", "tzp", "tzp inhalant"),
		new TranslationEntry("zap gun", "электрошокер", "шокер"),
		new TranslationEntry("stun grenade", "светошумовая граната", "flashbang"),
		new TranslationEntry("jetpack", "реактивный ранец", "джетпак"),
		new TranslationEntry("extension ladder", "выдвижная лестница", "лестница"),
		new TranslationEntry("boombox", "бумбокс", "магнитофон"),
		new TranslationEntry("weed killer", "убийца растений"),
		new TranslationEntry("belt bag", "поясная сумка"),
		new TranslationEntry("spray paint", "баллончик с краской", "краска"),
		new TranslationEntry("radar-booster", "радарный усилитель", "radar booster"),
		new TranslationEntry("inverse teleporter", "обратный телепортер"),
		new TranslationEntry("teleporter", "телепортер"),
		new TranslationEntry("signal translator", "транслятор сигналов"),
		new TranslationEntry("loud horn", "горн"),
		new TranslationEntry("company cruiser", "транспорт компании"),
		new TranslationEntry("decoy suit", "оранжевый костюм"),
		new TranslationEntry("brown suit", "коричневый костюм"),
		new TranslationEntry("green suit", "зелёный костюм"),
		new TranslationEntry("hazard suit", "защитный костюм"),
		new TranslationEntry("bee suit", "костюм пчелы"),
		new TranslationEntry("bunny suit", "костюм кролика"),
		new TranslationEntry("purple suit", "фиолетовый костюм"),
		new TranslationEntry("pajama suit", "пижамный костюм"),
		new TranslationEntry("bunkbeds", "двухъярусная кровать"),
		new TranslationEntry("file cabinet", "картотечный шкаф"),
		new TranslationEntry("cupboard", "шкаф для вещей", "шкаф"),
		new TranslationEntry("television", "телевизор", "tv"),
		new TranslationEntry("fridge", "холодильник"),
		new TranslationEntry("goldfish", "золотая рыбка"),
		new TranslationEntry("electric chair", "электрический стул"),
		new TranslationEntry("shower", "душ"),
		new TranslationEntry("toilet", "туалет"),
		new TranslationEntry("welcome mat", "коврик у входа"),
		new TranslationEntry("romantic table", "романтический столик"),
		new TranslationEntry("table", "обычный стол", "стол"),
		new TranslationEntry("record player", "проигрыватель пластинок"),
		new TranslationEntry("cozy lights", "уютная гирлянда", "гирлянда"),
		new TranslationEntry("jack-o-lantern", "тыква-фонарь", "тыква фонарь"),
		new TranslationEntry("plushie pajama man", "плюшевый пижамный человечек"),
		new TranslationEntry("sofa chair", "кресло-диван", "кресло диван"),
		new TranslationEntry("dog house", "будка для собаки"),
		new TranslationEntry("microwave", "микроволновка"),
		new TranslationEntry("disco ball", "диско-шар", "диско шар"),
		new TranslationEntry("classic painting", "классическая картина"),
		new TranslationEntry("first log", "первая запись"),
		new TranslationEntry("mummy", "мумия"),
		new TranslationEntry("swing of things", "размах событий"),
		new TranslationEntry("autopilot", "автопилот"),
		new TranslationEntry("behind the wall", "за стеной"),
		new TranslationEntry("goodbye", "прощай"),
		new TranslationEntry("screams", "крики"),
		new TranslationEntry("golden planet", "золотая планета"),
		new TranslationEntry("idea", "идея"),
		new TranslationEntry("nonsense", "бессмыслица"),
		new TranslationEntry("hiding", "сокрытие"),
		new TranslationEntry("real job", "настоящая работа"),
		new TranslationEntry("desmond", "десмонд"),
		new TranslationEntry("team synergy", "синергия команды"),
		new TranslationEntry("letter of resignation", "заявление об увольнении"),
		new TranslationEntry("work", "работа")
	};

	private static readonly List<PrefixCandidate> CommandCandidates = BuildCommandCandidates();

	private static readonly List<PrefixCandidate> ContentCandidates = BuildContentCandidates();

	private static readonly Dictionary<string, string> CommandExactMap = BuildExactMap(CommandCandidates);

	private static readonly Dictionary<string, string> ContentExactMap = BuildExactMap(ContentCandidates);

	[HarmonyPrefix]
	private static void Prefix(Terminal __instance)
	{
		if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.screenText == (Object)null)
		{
			return;
		}
		string text = __instance.screenText.text ?? string.Empty;
		int num = Mathf.Clamp(__instance.textAdded, 0, text.Length);
		if (num <= 0)
		{
			return;
		}
		string text2 = text.Substring(0, text.Length - num);
		string text3 = text.Substring(text.Length - num);
		if (!string.IsNullOrWhiteSpace(text3))
		{
			string text4 = ResolveUserInput(text3);
			__instance.screenText.text = text2 + text4;
			__instance.currentText = __instance.screenText.text;
			__instance.textAdded = text4.Length;
			__instance.screenText.caretPosition = __instance.screenText.text.Length;
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("[RuInputTerminal] '" + text3 + "' -> '" + text4 + "'"));
			}
		}
	}

	private static string ResolveUserInput(string input)
	{
		string text = NormalizeText(input);
		if (string.IsNullOrWhiteSpace(text))
		{
			return text;
		}
		if (TryResolveHotkey(text, out var command))
		{
			return command;
		}
		return ResolveAgainstCommands(text) ?? ResolveAgainstContent(text) ?? ResolveFuzzy(text, CommandCandidates, uniqueOnly: true) ?? ResolveFuzzy(text, ContentCandidates, uniqueOnly: true) ?? text;
	}

	private static bool TryResolveHotkey(string token, out string command)
	{
		switch (token)
		{
		case "c":
		case "с":
			command = "confirm";
			return true;
		case "d":
		case "в":
			command = "deny";
			return true;
		default:
			command = null;
			return false;
		}
	}

	private static string ResolveAgainstCommands(string token)
	{
		token = NormalizeText(token);
		if (token.Length == 0)
		{
			return null;
		}
		if (CommandExactMap.TryGetValue(token, out var value))
		{
			return value;
		}
		Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
		for (int i = 0; i < CommandCandidates.Count; i++)
		{
			string variant = CommandCandidates[i].Variant;
			if (!string.IsNullOrWhiteSpace(variant) && variant.StartsWith(token, StringComparison.OrdinalIgnoreCase))
			{
				string canonical = CommandCandidates[i].Canonical;
				if (!dictionary.TryGetValue(canonical, out var value2) || variant.Length < value2.Length)
				{
					dictionary[canonical] = variant;
				}
			}
		}
		if (dictionary.Count == 0)
		{
			return null;
		}
		string text = null;
		string text2 = null;
		foreach (KeyValuePair<string, string> item in dictionary)
		{
			if (text2 == null || item.Value.Length < text2.Length || (item.Value.Length == text2.Length && string.Compare(item.Key, text, StringComparison.OrdinalIgnoreCase) < 0))
			{
				text = item.Key;
				text2 = item.Value;
			}
		}
		return text;
	}

	private static string ResolveAgainstContent(string token)
	{
		token = NormalizeText(token);
		if (token.Length == 0)
		{
			return null;
		}
		if (ContentExactMap.TryGetValue(token, out var value))
		{
			return value;
		}
		return ResolveUniquePrefix(token, ContentCandidates);
	}

	private static string ResolveUniquePrefix(string token, List<PrefixCandidate> candidates)
	{
		if (string.IsNullOrWhiteSpace(token))
		{
			return null;
		}
		Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
		for (int i = 0; i < candidates.Count; i++)
		{
			string variant = candidates[i].Variant;
			if (!string.IsNullOrWhiteSpace(variant) && variant.StartsWith(token, StringComparison.OrdinalIgnoreCase))
			{
				string canonical = candidates[i].Canonical;
				if (!dictionary.ContainsKey(canonical) || variant.Length < dictionary[canonical].Length)
				{
					dictionary[canonical] = variant;
				}
			}
		}
		if (dictionary.Count != 1)
		{
			return null;
		}
		using (Dictionary<string, string>.Enumerator enumerator = dictionary.GetEnumerator())
		{
			if (enumerator.MoveNext())
			{
				return enumerator.Current.Key;
			}
		}
		return null;
	}

	private static string ResolveFuzzy(string token, List<PrefixCandidate> candidates, bool uniqueOnly)
	{
		token = NormalizeText(token);
		if (token.Length < 3)
		{
			return null;
		}
		Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
		for (int i = 0; i < candidates.Count; i++)
		{
			string variant = candidates[i].Variant;
			if (string.IsNullOrWhiteSpace(variant) || variant.StartsWith(token, StringComparison.OrdinalIgnoreCase) || token.StartsWith(variant, StringComparison.OrdinalIgnoreCase))
			{
				continue;
			}
			int fuzzyThreshold = GetFuzzyThreshold(token.Length, variant.Length);
			int num = LevenshteinDistance(token, variant, fuzzyThreshold);
			if (num >= 0 && num <= fuzzyThreshold)
			{
				string canonical = candidates[i].Canonical;
				if (!dictionary.TryGetValue(canonical, out var value) || num < value)
				{
					dictionary[canonical] = num;
				}
			}
		}
		string text = null;
		int num2 = int.MaxValue;
		int num3 = 0;
		foreach (KeyValuePair<string, int> item in dictionary)
		{
			int value2 = item.Value;
			if (value2 < num2)
			{
				num2 = value2;
				text = item.Key;
				num3 = 1;
			}
			else if (value2 == num2)
			{
				num3++;
			}
		}
		if (text == null)
		{
			return null;
		}
		if (uniqueOnly && num3 != 1)
		{
			return null;
		}
		return text;
	}

	private static int GetFuzzyThreshold(int aLen, int bLen)
	{
		if (Math.Min(aLen, bLen) <= 4)
		{
			return 1;
		}
		return 2;
	}

	private static int LevenshteinDistance(string a, string b, int maxDistance)
	{
		if (a == b)
		{
			return 0;
		}
		if (Math.Abs(a.Length - b.Length) > maxDistance)
		{
			return maxDistance + 1;
		}
		int length = a.Length;
		int length2 = b.Length;
		int[] array = new int[length2 + 1];
		int[] array2 = new int[length2 + 1];
		for (int i = 0; i <= length2; i++)
		{
			array[i] = i;
		}
		for (int j = 1; j <= length; j++)
		{
			array2[0] = j;
			int num = array2[0];
			char c = a[j - 1];
			for (int k = 1; k <= length2; k++)
			{
				int num2 = ((c != b[k - 1]) ? 1 : 0);
				int val = array[k] + 1;
				int val2 = array2[k - 1] + 1;
				int val3 = array[k - 1] + num2;
				int num3 = (array2[k] = Math.Min(Math.Min(val, val2), val3));
				if (num3 < num)
				{
					num = num3;
				}
			}
			if (num > maxDistance)
			{
				return maxDistance + 1;
			}
			int[] array3 = array;
			array = array2;
			array2 = array3;
		}
		return array[length2];
	}

	private static Dictionary<string, string> BuildExactMap(List<PrefixCandidate> candidates)
	{
		Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
		for (int i = 0; i < candidates.Count; i++)
		{
			string text = NormalizeText(candidates[i].Variant);
			if (text.Length != 0 && !dictionary.ContainsKey(text))
			{
				dictionary[text] = candidates[i].Canonical;
			}
		}
		return dictionary;
	}

	private static List<PrefixCandidate> BuildCommandCandidates()
	{
		List<PrefixCandidate> list = new List<PrefixCandidate>();
		for (int i = 0; i < CommandEntries.Length; i++)
		{
			TranslationEntry translationEntry = CommandEntries[i];
			AddCandidates(list, translationEntry.English, translationEntry.English);
			AddCandidates(list, translationEntry.Russian, translationEntry.English);
			for (int j = 0; j < translationEntry.Aliases.Length; j++)
			{
				AddCandidates(list, translationEntry.Aliases[j], translationEntry.English);
			}
		}
		return list;
	}

	private static List<PrefixCandidate> BuildContentCandidates()
	{
		List<PrefixCandidate> list = new List<PrefixCandidate>();
		for (int i = 0; i < ContentEntries.Length; i++)
		{
			TranslationEntry translationEntry = ContentEntries[i];
			AddCandidates(list, translationEntry.English, translationEntry.English);
			AddCandidates(list, translationEntry.Russian, translationEntry.English);
			for (int j = 0; j < translationEntry.Aliases.Length; j++)
			{
				AddCandidates(list, translationEntry.Aliases[j], translationEntry.English);
			}
		}
		return list;
	}

	private static void AddCandidates(List<PrefixCandidate> list, string text, string canonical)
	{
		foreach (string item in BuildLookupVariants(text))
		{
			if (item.Length > 0)
			{
				list.Add(new PrefixCandidate(item, canonical));
			}
		}
	}

	private static IEnumerable<string> BuildLookupVariants(string text)
	{
		HashSet<string> set = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		Add(text);
		Add(CollapseRepeatedLetters(text));
		Add(SingularizePhrase(text));
		string text2 = TransliterateRuToEnKeyboard(text);
		Add(text2);
		Add(CollapseRepeatedLetters(text2));
		Add(SingularizePhrase(text2));
		string text3 = TransliterateRuToLatinApprox(text);
		Add(text3);
		Add(CollapseRepeatedLetters(text3));
		Add(SingularizePhrase(text3));
		string text4 = TransliterateEnToRuKeyboard(text);
		Add(text4);
		Add(CollapseRepeatedLetters(text4));
		Add(SingularizePhrase(text4));
		return set;
		void Add(string s)
		{
			s = NormalizeText(s);
			if (s.Length > 0)
			{
				set.Add(s);
			}
		}
	}

	private static string CollapseRepeatedLetters(string text)
	{
		string text2 = NormalizeText(text);
		if (text2.Length == 0)
		{
			return text2;
		}
		StringBuilder stringBuilder = new StringBuilder(text2.Length);
		char c = '\0';
		foreach (char c2 in text2)
		{
			if (!char.IsLetter(c2) || c2 != c)
			{
				stringBuilder.Append(c2);
				c = c2;
			}
		}
		return stringBuilder.ToString();
	}

	private static string SingularizePhrase(string text)
	{
		string text2 = NormalizeText(text);
		if (text2.Length == 0)
		{
			return text2;
		}
		string[] array = text2.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
		for (int i = 0; i < array.Length; i++)
		{
			array[i] = SingularizeToken(array[i]);
		}
		return string.Join(" ", array);
	}

	private static string SingularizeToken(string token)
	{
		if (string.IsNullOrWhiteSpace(token))
		{
			return token;
		}
		string text = token.ToLowerInvariant();
		if (text.EndsWith("ция", StringComparison.Ordinal))
		{
			return text.Substring(0, text.Length - 2);
		}
		if (text.EndsWith("ия", StringComparison.Ordinal))
		{
			return text.Substring(0, text.Length - 2);
		}
		if (text.Length > 4 && text.EndsWith("ies", StringComparison.Ordinal))
		{
			return text.Substring(0, text.Length - 3) + "y";
		}
		if (text.Length > 3 && text.EndsWith("es", StringComparison.Ordinal))
		{
			return text.Substring(0, text.Length - 2);
		}
		if (text.Length > 3 && text.EndsWith("s", StringComparison.Ordinal) && !text.EndsWith("ss", StringComparison.Ordinal))
		{
			return text.Substring(0, text.Length - 1);
		}
		if (text.Length > 3 && (text.EndsWith("ы", StringComparison.Ordinal) || text.EndsWith("и", StringComparison.Ordinal) || text.EndsWith("а", StringComparison.Ordinal) || text.EndsWith("я", StringComparison.Ordinal)))
		{
			return text.Substring(0, text.Length - 1);
		}
		return text;
	}

	private static string TransliterateRuToEnKeyboard(string text)
	{
		char[] array = text.ToCharArray();
		bool flag = false;
		for (int i = 0; i < array.Length; i++)
		{
			if (RuToEnKeyboard.TryGetValue(array[i], out var value))
			{
				array[i] = value;
				flag = true;
			}
		}
		if (!flag)
		{
			return text;
		}
		return new string(array);
	}

	private static string TransliterateRuToLatinApprox(string text)
	{
		if (string.IsNullOrWhiteSpace(text))
		{
			return string.Empty;
		}
		string text2 = text.ToLowerInvariant();
		text2 = text2.Replace("экс", "ex");
		text2 = text2.Replace("кс", "x");
		text2 = text2.Replace("щ", "shch");
		text2 = text2.Replace("ш", "sh");
		text2 = text2.Replace("ч", "ch");
		text2 = text2.Replace("ж", "zh");
		text2 = text2.Replace("ю", "yu");
		text2 = text2.Replace("я", "ya");
		text2 = text2.Replace("ё", "yo");
		StringBuilder stringBuilder = new StringBuilder(text2.Length * 2);
		foreach (char c in text2)
		{
			switch (c)
			{
			case 'а':
				stringBuilder.Append('a');
				break;
			case 'б':
				stringBuilder.Append('b');
				break;
			case 'в':
				stringBuilder.Append('v');
				break;
			case 'г':
				stringBuilder.Append('g');
				break;
			case 'д':
				stringBuilder.Append('d');
				break;
			case 'е':
				stringBuilder.Append('e');
				break;
			case 'з':
				stringBuilder.Append('z');
				break;
			case 'и':
				stringBuilder.Append('i');
				break;
			case 'й':
				stringBuilder.Append('y');
				break;
			case 'к':
				stringBuilder.Append('c');
				break;
			case 'л':
				stringBuilder.Append('l');
				break;
			case 'м':
				stringBuilder.Append('m');
				break;
			case 'н':
				stringBuilder.Append('n');
				break;
			case 'о':
				stringBuilder.Append('o');
				break;
			case 'п':
				stringBuilder.Append('p');
				break;
			case 'р':
				stringBuilder.Append('r');
				break;
			case 'с':
				stringBuilder.Append('s');
				break;
			case 'т':
				stringBuilder.Append('t');
				break;
			case 'у':
				stringBuilder.Append('u');
				break;
			case 'ф':
				stringBuilder.Append('f');
				break;
			case 'х':
				stringBuilder.Append('h');
				break;
			case 'ц':
				stringBuilder.Append('c');
				break;
			case 'ы':
				stringBuilder.Append('y');
				break;
			case 'э':
				stringBuilder.Append('e');
				break;
			default:
				stringBuilder.Append(c);
				break;
			case 'ъ':
			case 'ь':
				break;
			}
		}
		return stringBuilder.ToString();
	}

	private static string TransliterateEnToRuKeyboard(string text)
	{
		char[] array = text.ToCharArray();
		bool flag = false;
		for (int i = 0; i < array.Length; i++)
		{
			if (EnToRuKeyboard.TryGetValue(array[i], out var value))
			{
				array[i] = value;
				flag = true;
			}
		}
		if (!flag)
		{
			return text;
		}
		return new string(array);
	}

	private static Dictionary<char, char> BuildReverseMap(Dictionary<char, char> source)
	{
		Dictionary<char, char> dictionary = new Dictionary<char, char>();
		foreach (KeyValuePair<char, char> item in source)
		{
			if (!dictionary.ContainsKey(item.Value))
			{
				dictionary[item.Value] = item.Key;
			}
		}
		return dictionary;
	}

	private static string NormalizeText(string text)
	{
		if (string.IsNullOrWhiteSpace(text))
		{
			return string.Empty;
		}
		StringBuilder stringBuilder = new StringBuilder(text.Length);
		bool flag = false;
		string text2 = text.Trim().ToLowerInvariant();
		foreach (char c in text2)
		{
			if (char.IsLetterOrDigit(c))
			{
				stringBuilder.Append(c);
				flag = false;
			}
			else if ((c == ' ' || c == '_' || c == '-') && !flag)
			{
				stringBuilder.Append(' ');
				flag = true;
			}
		}
		return stringBuilder.ToString().Trim();
	}
}