Decompiled source of Better Auto Complete v0.9.1

BetterAutoComplete.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BetterAutoComplete.Core;
using FuzzySharp;
using FuzzySharp.Extractor;
using FuzzySharp.SimilarityRatio;
using FuzzySharp.SimilarityRatio.Scorer.Composite;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BetterAutoComplete")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BetterAutoComplete")]
[assembly: AssemblyTitle("BetterAutoComplete")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace BetterAutoComplete
{
	public static class AutoCompleteState
	{
		public static List<string> Matches = new List<string>();

		public static int MatchIndex = 0;

		public static string LastBaseText = null;

		public static void Reset()
		{
			Matches.Clear();
			MatchIndex = 0;
			LastBaseText = null;
		}
	}
	[BepInPlugin("Collin800.BetterAutocomplete", "BetterAutoComplete", "1.0")]
	public class Plugin : BaseUnityPlugin
	{
		private void Awake()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			SceneManager.sceneLoaded += OnSceneLoaded;
			Harmony val = new Harmony("Collin800.BetterAutocomplete");
			val.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"BetterAutoComplete has been loaded, yay!");
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
		}
	}
}
namespace BetterAutoComplete.Patches
{
	[HarmonyPatch(typeof(CommandConsole), "AutocompleteCommand")]
	public static class BetterAutoCompletePatch
	{
		private static bool Prefix(CommandConsole __instance)
		{
			CompletionContext completionContext = AutoCompleteParser.Parse(__instance.inputField.text, __instance);
			if (completionContext.SuggestionSource == null)
			{
				AutoCompleteState.Reset();
				return false;
			}
			if (AutoCompleteState.LastBaseText == completionContext.BaseText && AutoCompleteState.Matches.Contains(completionContext.TextToComplete))
			{
				int num = AutoCompleteState.Matches.IndexOf(completionContext.TextToComplete);
				AutoCompleteState.MatchIndex = (num + 1) % AutoCompleteState.Matches.Count;
			}
			else
			{
				AutoCompleteState.Reset();
				AutoCompleteState.LastBaseText = completionContext.BaseText;
				AutoCompleteState.Matches = SuggestionFinder.Find(completionContext.TextToComplete, completionContext.SuggestionSource);
			}
			if (AutoCompleteState.Matches.Count > 0)
			{
				string text = AutoCompleteState.Matches[AutoCompleteState.MatchIndex];
				__instance.inputField.text = completionContext.BaseText + text;
				__instance.inputField.caretPosition = __instance.inputField.text.Length;
			}
			return false;
		}
	}
}
namespace BetterAutoComplete.Core
{
	public static class AutoCompleteParser
	{
		public static CompletionContext Parse(string currentInput, CommandConsole consoleInstance)
		{
			string[] array = currentInput.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			if (array.Length == 0)
			{
				if (currentInput.Length > 0 && string.IsNullOrWhiteSpace(currentInput))
				{
					return new CompletionContext("", "", SuggestionSource.GetAllCommands(consoleInstance));
				}
				return new CompletionContext("", "", null);
			}
			List<string> argumentSuggestionsForCommand = SuggestionSource.GetArgumentSuggestionsForCommand(array[0]);
			if (argumentSuggestionsForCommand != null && (array.Length > 1 || currentInput.EndsWith(" ")))
			{
				string baseText;
				string textToComplete;
				if (currentInput.EndsWith(" "))
				{
					baseText = string.Join(" ", array) + " ";
					textToComplete = "";
				}
				else
				{
					baseText = string.Join(" ", array.Take(array.Length - 1)) + " ";
					textToComplete = array.Last();
				}
				return new CompletionContext(baseText, textToComplete, argumentSuggestionsForCommand);
			}
			return new CompletionContext("", array[0], SuggestionSource.GetAllCommands(consoleInstance));
		}
	}
	public class CompletionContext
	{
		public string BaseText { get; }

		public string TextToComplete { get; }

		public List<string> SuggestionSource { get; }

		public CompletionContext(string baseText, string textToComplete, List<string> suggestionSource)
		{
			BaseText = baseText;
			TextToComplete = textToComplete;
			SuggestionSource = suggestionSource;
		}
	}
	public static class SuggestionFinder
	{
		private const int MaxSuggestions = 10;

		private const int MinScoreThreshold = 60;

		public static List<string> Find(string query, List<string> source)
		{
			string query2 = query;
			if (source == null || !source.Any())
			{
				return new List<string>();
			}
			if (string.IsNullOrEmpty(query2))
			{
				return source.OrderBy((string s) => s).Take(10).ToList();
			}
			List<string> list = (from s in source
				where s.StartsWith(query2, StringComparison.OrdinalIgnoreCase)
				orderby s.Length
				select s).Take(10).ToList();
			if (list.Any())
			{
				return list;
			}
			IEnumerable<ExtractedResult<string>> source2 = Process.ExtractTop(query2, (IEnumerable<string>)source, (Func<string, string>)((string s) => s), ScorerCache.Get<WeightedRatioScorer>(), 10, 60);
			return source2.Select((ExtractedResult<string> r) => r.Value).ToList();
		}
	}
	public static class SuggestionSource
	{
		public static List<string> GetArgumentSuggestionsForCommand(string commandName)
		{
			if ((Object)(object)CL_GameManager.gMan == (Object)null || CL_AssetManager.instance == null)
			{
				return null;
			}
			string text = commandName.ToLower();
			string text2 = text;
			if (!(text2 == "spawnentity"))
			{
				if (text2 == "loadlevels")
				{
					return CL_AssetManager.instance.assetDatabase.levelPrefabs.Select((GameObject l) => ((Object)l).name.ToLower()).Distinct<string>(StringComparer.OrdinalIgnoreCase).ToList();
				}
				return null;
			}
			return CL_GameManager.gMan.gameEntityPrefabs.Select((GameEntity e) => ((Object)e).name.ToLower()).Distinct<string>(StringComparer.OrdinalIgnoreCase).ToList();
		}

		public static List<string> GetAllCommands(CommandConsole consoleInstance)
		{
			return ((AccessTools.Field(typeof(CommandConsole), "commandList").GetValue(consoleInstance) is List<Command> source) ? source.Select((Command c) => c.command.ToLower()).Distinct().ToList() : null) ?? new List<string>();
		}
	}
}

FuzzySharp.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using FuzzySharp.Edits;
using FuzzySharp.Extensions;
using FuzzySharp.Extractor;
using FuzzySharp.PreProcess;
using FuzzySharp.SimilarityRatio;
using FuzzySharp.SimilarityRatio.Scorer;
using FuzzySharp.SimilarityRatio.Scorer.Composite;
using FuzzySharp.SimilarityRatio.Scorer.Generic;
using FuzzySharp.SimilarityRatio.Scorer.StrategySensitive;
using FuzzySharp.SimilarityRatio.Scorer.StrategySensitive.Generic;
using FuzzySharp.SimilarityRatio.Strategy;
using FuzzySharp.SimilarityRatio.Strategy.Generic;
using FuzzySharp.Utils;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("Jacob Bayer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Fuzzy string matcher based on FuzzyWuzzy algorithm from SeatGeek")]
[assembly: AssemblyFileVersion("1.0.4.0")]
[assembly: AssemblyInformationalVersion("2.0.2+53b71acd66e53a4ff9f4229348de48295f99c0a5")]
[assembly: AssemblyProduct("FuzzySharp")]
[assembly: AssemblyTitle("FuzzySharp")]
[assembly: AssemblyVersion("1.0.4.0")]
namespace FuzzySharp
{
	public static class Fuzz
	{
		public static int Ratio(string input1, string input2)
		{
			return ScorerCache.Get<DefaultRatioScorer>().Score(input1, input2);
		}

		public static int Ratio(string input1, string input2, PreprocessMode preprocessMode)
		{
			return ScorerCache.Get<DefaultRatioScorer>().Score(input1, input2, preprocessMode);
		}

		public static int PartialRatio(string input1, string input2)
		{
			return ScorerCache.Get<PartialRatioScorer>().Score(input1, input2);
		}

		public static int PartialRatio(string input1, string input2, PreprocessMode preprocessMode)
		{
			return ScorerCache.Get<PartialRatioScorer>().Score(input1, input2, preprocessMode);
		}

		public static int TokenSortRatio(string input1, string input2)
		{
			return ScorerCache.Get<TokenSortScorer>().Score(input1, input2);
		}

		public static int TokenSortRatio(string input1, string input2, PreprocessMode preprocessMode)
		{
			return ScorerCache.Get<TokenSortScorer>().Score(input1, input2, preprocessMode);
		}

		public static int PartialTokenSortRatio(string input1, string input2)
		{
			return ScorerCache.Get<PartialTokenSortScorer>().Score(input1, input2);
		}

		public static int PartialTokenSortRatio(string input1, string input2, PreprocessMode preprocessMode)
		{
			return ScorerCache.Get<PartialTokenSortScorer>().Score(input1, input2, preprocessMode);
		}

		public static int TokenSetRatio(string input1, string input2)
		{
			return ScorerCache.Get<TokenSetScorer>().Score(input1, input2);
		}

		public static int TokenSetRatio(string input1, string input2, PreprocessMode preprocessMode)
		{
			return ScorerCache.Get<TokenSetScorer>().Score(input1, input2, preprocessMode);
		}

		public static int PartialTokenSetRatio(string input1, string input2)
		{
			return ScorerCache.Get<PartialTokenSetScorer>().Score(input1, input2);
		}

		public static int PartialTokenSetRatio(string input1, string input2, PreprocessMode preprocessMode)
		{
			return ScorerCache.Get<PartialTokenSetScorer>().Score(input1, input2, preprocessMode);
		}

		public static int TokenDifferenceRatio(string input1, string input2)
		{
			return ScorerCache.Get<TokenDifferenceScorer>().Score(input1, input2);
		}

		public static int TokenDifferenceRatio(string input1, string input2, PreprocessMode preprocessMode)
		{
			return ScorerCache.Get<TokenDifferenceScorer>().Score(input1, input2, preprocessMode);
		}

		public static int PartialTokenDifferenceRatio(string input1, string input2)
		{
			return ScorerCache.Get<PartialTokenDifferenceScorer>().Score(input1, input2);
		}

		public static int PartialTokenDifferenceRatio(string input1, string input2, PreprocessMode preprocessMode)
		{
			return ScorerCache.Get<PartialTokenDifferenceScorer>().Score(input1, input2, preprocessMode);
		}

		public static int TokenInitialismRatio(string input1, string input2)
		{
			return ScorerCache.Get<TokenInitialismScorer>().Score(input1, input2);
		}

		public static int TokenInitialismRatio(string input1, string input2, PreprocessMode preprocessMode)
		{
			return ScorerCache.Get<TokenInitialismScorer>().Score(input1, input2, preprocessMode);
		}

		public static int PartialTokenInitialismRatio(string input1, string input2)
		{
			return ScorerCache.Get<PartialTokenInitialismScorer>().Score(input1, input2);
		}

		public static int PartialTokenInitialismRatio(string input1, string input2, PreprocessMode preprocessMode)
		{
			return ScorerCache.Get<PartialTokenInitialismScorer>().Score(input1, input2);
		}

		public static int TokenAbbreviationRatio(string input1, string input2)
		{
			return ScorerCache.Get<TokenAbbreviationScorer>().Score(input1, input2);
		}

		public static int TokenAbbreviationRatio(string input1, string input2, PreprocessMode preprocessMode)
		{
			return ScorerCache.Get<TokenAbbreviationScorer>().Score(input1, input2, preprocessMode);
		}

		public static int PartialTokenAbbreviationRatio(string input1, string input2)
		{
			return ScorerCache.Get<PartialTokenAbbreviationScorer>().Score(input1, input2);
		}

		public static int PartialTokenAbbreviationRatio(string input1, string input2, PreprocessMode preprocessMode)
		{
			return ScorerCache.Get<PartialTokenAbbreviationScorer>().Score(input1, input2, preprocessMode);
		}

		public static int WeightedRatio(string input1, string input2)
		{
			return ScorerCache.Get<WeightedRatioScorer>().Score(input1, input2);
		}

		public static int WeightedRatio(string input1, string input2, PreprocessMode preprocessMode)
		{
			return ScorerCache.Get<WeightedRatioScorer>().Score(input1, input2, preprocessMode);
		}
	}
	public static class Levenshtein
	{
		private static EditOp[] GetEditOps<T>(T[] arr1, T[] arr2) where T : IEquatable<T>
		{
			return GetEditOps(arr1.Length, arr1, arr2.Length, arr2);
		}

		private static EditOp[] GetEditOps(string s1, string s2)
		{
			return GetEditOps(s1.Length, s1.ToCharArray(), s2.Length, s2.ToCharArray());
		}

		private static EditOp[] GetEditOps<T>(int len1, T[] c1, int len2, T[] c2) where T : IEquatable<T>
		{
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			while (len1 > 0 && len2 > 0 && c1[num].Equals(c2[num2]))
			{
				len1--;
				len2--;
				num++;
				num2++;
				num3++;
			}
			int o = num3;
			while (len1 > 0 && len2 > 0 && c1[num + len1 - 1].Equals(c2[num2 + len2 - 1]))
			{
				len1--;
				len2--;
			}
			len1++;
			len2++;
			int[] array = new int[len2 * len1];
			for (int i = 0; i < len2; i++)
			{
				array[i] = i;
			}
			for (int i = 1; i < len1; i++)
			{
				array[len2 * i] = i;
			}
			for (int i = 1; i < len1; i++)
			{
				int num4 = (i - 1) * len2;
				int num5 = i * len2;
				int num6 = num5 + len2 - 1;
				T val = c1[num + i - 1];
				int num7 = num2;
				int num8 = i;
				num5++;
				while (num5 <= num6)
				{
					int num9 = array[num4++] + ((!val.Equals(c2[num7++])) ? 1 : 0);
					num8++;
					if (num8 > num9)
					{
						num8 = num9;
					}
					num9 = array[num4] + 1;
					if (num8 > num9)
					{
						num8 = num9;
					}
					array[num5++] = num8;
				}
			}
			return EditOpsFromCostMatrix(len1, c1, num, num3, len2, c2, num2, o, array);
		}

		private static EditOp[] EditOpsFromCostMatrix<T>(int len1, T[] c1, int p1, int o1, int len2, T[] c2, int p2, int o2, int[] matrix) where T : IEquatable<T>
		{
			int num = 0;
			int num2 = matrix[len1 * len2 - 1];
			EditOp[] array = new EditOp[num2];
			int num3 = len1 - 1;
			int num4 = len2 - 1;
			int num5 = len1 * len2 - 1;
			while (num3 > 0 || num4 > 0)
			{
				if (num3 != 0 && num4 != 0 && matrix[num5] == matrix[num5 - len2 - 1] && c1[p1 + num3 - 1].Equals(c2[p2 + num4 - 1]))
				{
					num3--;
					num4--;
					num5 -= len2 + 1;
					num = 0;
					continue;
				}
				if (num < 0 && num4 != 0 && matrix[num5] == matrix[num5 - 1] + 1)
				{
					EditOp editOp = new EditOp();
					num2--;
					array[num2] = editOp;
					editOp.EditType = EditType.INSERT;
					editOp.SourcePos = num3 + o1;
					editOp.DestPos = --num4 + o2;
					num5--;
					continue;
				}
				if (num > 0 && num3 != 0 && matrix[num5] == matrix[num5 - len2] + 1)
				{
					EditOp editOp2 = new EditOp();
					num2--;
					array[num2] = editOp2;
					editOp2.EditType = EditType.DELETE;
					editOp2.SourcePos = --num3 + o1;
					editOp2.DestPos = num4 + o2;
					num5 -= len2;
					continue;
				}
				if (num3 != 0 && num4 != 0 && matrix[num5] == matrix[num5 - len2 - 1] + 1)
				{
					num2--;
					EditOp editOp3 = (array[num2] = new EditOp());
					editOp3.EditType = EditType.REPLACE;
					editOp3.SourcePos = --num3 + o1;
					editOp3.DestPos = --num4 + o2;
					num5 -= len2 + 1;
					num = 0;
					continue;
				}
				if (num == 0 && num4 != 0 && matrix[num5] == matrix[num5 - 1] + 1)
				{
					num2--;
					EditOp editOp4 = (array[num2] = new EditOp());
					editOp4.EditType = EditType.INSERT;
					editOp4.SourcePos = num3 + o1;
					editOp4.DestPos = --num4 + o2;
					num5--;
					num = -1;
					continue;
				}
				if (num == 0 && num3 != 0 && matrix[num5] == matrix[num5 - len2] + 1)
				{
					num2--;
					EditOp editOp5 = (array[num2] = new EditOp());
					editOp5.EditType = EditType.DELETE;
					editOp5.SourcePos = --num3 + o1;
					editOp5.DestPos = num4 + o2;
					num5 -= len2;
					num = 1;
					continue;
				}
				throw new InvalidOperationException("Cant calculate edit op");
			}
			return array;
		}

		public static MatchingBlock[] GetMatchingBlocks<T>(T[] s1, T[] s2) where T : IEquatable<T>
		{
			return GetMatchingBlocks(s1.Length, s2.Length, GetEditOps(s1, s2));
		}

		public static MatchingBlock[] GetMatchingBlocks(string s1, string s2)
		{
			return GetMatchingBlocks(s1.Length, s2.Length, GetEditOps(s1, s2));
		}

		public static MatchingBlock[] GetMatchingBlocks(int len1, int len2, OpCode[] ops)
		{
			int num = ops.Length;
			int num2 = 0;
			int num3 = 0;
			int num4 = num;
			while (num4-- != 0)
			{
				if (ops[num2].EditType == EditType.KEEP)
				{
					num3++;
					while (num4 != 0 && ops[num2].EditType == EditType.KEEP)
					{
						num4--;
						num2++;
					}
					if (num4 == 0)
					{
						break;
					}
				}
				num2++;
			}
			MatchingBlock[] array = new MatchingBlock[num3 + 1];
			int num5 = 0;
			num2 = 0;
			array[num5] = new MatchingBlock();
			num4 = num;
			while (num4 != 0)
			{
				if (ops[num2].EditType == EditType.KEEP)
				{
					array[num5].SourcePos = ops[num2].SourceBegin;
					array[num5].DestPos = ops[num2].DestBegin;
					while (num4 != 0 && ops[num2].EditType == EditType.KEEP)
					{
						num4--;
						num2++;
					}
					if (num4 == 0)
					{
						array[num5].Length = len1 - array[num5].SourcePos;
						num5++;
						break;
					}
					array[num5].Length = ops[num2].SourceBegin - array[num5].SourcePos;
					num5++;
					array[num5] = new MatchingBlock();
				}
				num4--;
				num2++;
			}
			MatchingBlock matchingBlock = new MatchingBlock
			{
				SourcePos = len1,
				DestPos = len2,
				Length = 0
			};
			array[num5] = matchingBlock;
			return array;
		}

		private static MatchingBlock[] GetMatchingBlocks(int len1, int len2, EditOp[] ops)
		{
			int num = ops.Length;
			int num2 = 0;
			int i = 0;
			int num3;
			int num4 = (num3 = 0);
			int num5 = num;
			while (num5 != 0)
			{
				for (; ops[i].EditType == EditType.KEEP; i++)
				{
					if (--num5 == 0)
					{
						break;
					}
				}
				if (num5 == 0)
				{
					break;
				}
				if (num4 < ops[i].SourcePos || num3 < ops[i].DestPos)
				{
					num2++;
					num4 = ops[i].SourcePos;
					num3 = ops[i].DestPos;
				}
				EditType editType = ops[i].EditType;
				switch (editType)
				{
				case EditType.REPLACE:
					do
					{
						num4++;
						num3++;
						num5--;
						i++;
					}
					while (num5 != 0 && ops[i].EditType == editType && num4 == ops[i].SourcePos && num3 == ops[i].DestPos);
					continue;
				case EditType.DELETE:
					do
					{
						num4++;
						num5--;
						i++;
					}
					while (num5 != 0 && ops[i].EditType == editType && num4 == ops[i].SourcePos && num3 == ops[i].DestPos);
					continue;
				case EditType.INSERT:
					break;
				default:
					continue;
				}
				do
				{
					num3++;
					num5--;
					i++;
				}
				while (num5 != 0 && ops[i].EditType == editType && num4 == ops[i].SourcePos && num3 == ops[i].DestPos);
			}
			if (num4 < len1 || num3 < len2)
			{
				num2++;
			}
			MatchingBlock[] array = new MatchingBlock[num2 + 1];
			i = 0;
			num4 = (num3 = 0);
			int num6 = 0;
			num5 = num;
			while (num5 != 0)
			{
				for (; ops[i].EditType == EditType.KEEP; i++)
				{
					if (--num5 == 0)
					{
						break;
					}
				}
				if (num5 == 0)
				{
					break;
				}
				if (num4 < ops[i].SourcePos || num3 < ops[i].DestPos)
				{
					MatchingBlock matchingBlock = new MatchingBlock();
					matchingBlock.SourcePos = num4;
					matchingBlock.DestPos = num3;
					matchingBlock.Length = ops[i].SourcePos - num4;
					num4 = ops[i].SourcePos;
					num3 = ops[i].DestPos;
					array[num6++] = matchingBlock;
				}
				EditType editType = ops[i].EditType;
				switch (editType)
				{
				case EditType.REPLACE:
					do
					{
						num4++;
						num3++;
						num5--;
						i++;
					}
					while (num5 != 0 && ops[i].EditType == editType && num4 == ops[i].SourcePos && num3 == ops[i].DestPos);
					continue;
				case EditType.DELETE:
					do
					{
						num4++;
						num5--;
						i++;
					}
					while (num5 != 0 && ops[i].EditType == editType && num4 == ops[i].SourcePos && num3 == ops[i].DestPos);
					continue;
				case EditType.INSERT:
					break;
				default:
					continue;
				}
				do
				{
					num3++;
					num5--;
					i++;
				}
				while (num5 != 0 && ops[i].EditType == editType && num4 == ops[i].SourcePos && num3 == ops[i].DestPos);
			}
			if (num4 < len1 || num3 < len2)
			{
				MatchingBlock matchingBlock2 = new MatchingBlock();
				matchingBlock2.SourcePos = num4;
				matchingBlock2.DestPos = num3;
				matchingBlock2.Length = len1 - num4;
				array[num6++] = matchingBlock2;
			}
			MatchingBlock matchingBlock3 = new MatchingBlock();
			matchingBlock3.SourcePos = len1;
			matchingBlock3.DestPos = len2;
			matchingBlock3.Length = 0;
			array[num6] = matchingBlock3;
			return array;
		}

		private static OpCode[] EditOpsToOpCodes(EditOp[] ops, int len1, int len2)
		{
			int num = ops.Length;
			int i = 0;
			int num2 = 0;
			int num3;
			int num4 = (num3 = 0);
			int num5 = num;
			EditType editType;
			while (num5 != 0)
			{
				for (; ops[i].EditType == EditType.KEEP; i++)
				{
					if (--num5 == 0)
					{
						break;
					}
				}
				if (num5 == 0)
				{
					break;
				}
				if (num4 < ops[i].SourcePos || num3 < ops[i].DestPos)
				{
					num2++;
					num4 = ops[i].SourcePos;
					num3 = ops[i].DestPos;
				}
				num2++;
				editType = ops[i].EditType;
				switch (editType)
				{
				case EditType.REPLACE:
					do
					{
						num4++;
						num3++;
						num5--;
						i++;
					}
					while (num5 != 0 && ops[i].EditType == editType && num4 == ops[i].SourcePos && num3 == ops[i].DestPos);
					continue;
				case EditType.DELETE:
					do
					{
						num4++;
						num5--;
						i++;
					}
					while (num5 != 0 && ops[i].EditType == editType && num4 == ops[i].SourcePos && num3 == ops[i].DestPos);
					continue;
				case EditType.INSERT:
					break;
				default:
					continue;
				}
				do
				{
					num3++;
					num5--;
					i++;
				}
				while (num5 != 0 && ops[i].EditType == editType && num4 == ops[i].SourcePos && num3 == ops[i].DestPos);
			}
			if (num4 < len1 || num3 < len2)
			{
				num2++;
			}
			OpCode[] array = new OpCode[num2];
			i = 0;
			num4 = (num3 = 0);
			int j = 0;
			for (num5 = num; num5 != 0; array[j].EditType = editType, array[j].SourceEnd = num4, array[j].DestEnd = num3, j++)
			{
				for (; ops[i].EditType == EditType.KEEP; i++)
				{
					if (--num5 == 0)
					{
						break;
					}
				}
				if (num5 == 0)
				{
					break;
				}
				OpCode opCode = (array[j] = new OpCode());
				opCode.SourceBegin = num4;
				opCode.DestBegin = num3;
				if (num4 < ops[i].SourcePos || num3 < ops[i].DestPos)
				{
					opCode.EditType = EditType.KEEP;
					int num6 = (opCode.SourceEnd = ops[i].SourcePos);
					num4 = num6;
					num6 = (opCode.DestEnd = ops[i].DestPos);
					num3 = num6;
					j++;
					OpCode opCode2 = (array[j] = new OpCode());
					opCode2.SourceBegin = num4;
					opCode2.DestBegin = num3;
				}
				editType = ops[i].EditType;
				switch (editType)
				{
				case EditType.REPLACE:
					do
					{
						num4++;
						num3++;
						num5--;
						i++;
					}
					while (num5 != 0 && ops[i].EditType == editType && num4 == ops[i].SourcePos && num3 == ops[i].DestPos);
					continue;
				case EditType.DELETE:
					do
					{
						num4++;
						num5--;
						i++;
					}
					while (num5 != 0 && ops[i].EditType == editType && num4 == ops[i].SourcePos && num3 == ops[i].DestPos);
					continue;
				case EditType.INSERT:
					break;
				default:
					continue;
				}
				do
				{
					num3++;
					num5--;
					i++;
				}
				while (num5 != 0 && ops[i].EditType == editType && num4 == ops[i].SourcePos && num3 == ops[i].DestPos);
			}
			if (num4 < len1 || num3 < len2)
			{
				if (array[j] == null)
				{
					array[j] = new OpCode();
				}
				array[j].EditType = EditType.KEEP;
				array[j].SourceBegin = num4;
				array[j].DestBegin = num3;
				array[j].SourceEnd = len1;
				array[j].DestEnd = len2;
				j++;
			}
			return array;
		}

		public static int EditDistance(string s1, string s2, int xcost = 0)
		{
			return EditDistance(s1.ToCharArray(), s2.ToCharArray(), xcost);
		}

		public static int EditDistance<T>(T[] c1, T[] c2, int xcost = 0) where T : IEquatable<T>
		{
			int num = 0;
			int num2 = 0;
			int num3 = c1.Length;
			int num4 = c2.Length;
			while (num3 > 0 && num4 > 0 && c1[num].Equals(c2[num2]))
			{
				num3--;
				num4--;
				num++;
				num2++;
			}
			while (num3 > 0 && num4 > 0 && c1[num + num3 - 1].Equals(c2[num2 + num4 - 1]))
			{
				num3--;
				num4--;
			}
			if (num3 == 0)
			{
				return num4;
			}
			if (num4 == 0)
			{
				return num3;
			}
			if (num3 > num4)
			{
				int num5 = num3;
				int num6 = num;
				num3 = num4;
				num4 = num5;
				num = num2;
				num2 = num6;
				T[] array = c2;
				c2 = c1;
				c1 = array;
			}
			if (num3 == 1)
			{
				if (xcost != 0)
				{
					return num4 + 1 - 2 * Memchr(c2, num2, c1[num], num4);
				}
				return num4 - Memchr(c2, num2, c1[num], num4);
			}
			num3++;
			num4++;
			int num7 = num3 >> 1;
			int[] array2 = new int[num4];
			int num8 = num4 - 1;
			for (int i = 0; i < num4 - ((xcost == 0) ? num7 : 0); i++)
			{
				array2[i] = i;
			}
			if (xcost != 0)
			{
				for (int i = 1; i < num3; i++)
				{
					int num9 = 1;
					T val = c1[num + i - 1];
					int num10 = num2;
					int num11 = i;
					int num12 = i;
					while (num9 <= num8)
					{
						num12 = ((!val.Equals(c2[num10++])) ? (num12 + 1) : (--num11));
						num11 = array2[num9];
						num11++;
						if (num12 > num11)
						{
							num12 = num11;
						}
						array2[num9++] = num12;
					}
				}
			}
			else
			{
				array2[0] = num3 - num7 - 1;
				for (int i = 1; i < num3; i++)
				{
					T val2 = c1[num + i - 1];
					int num14;
					int num15;
					int num18;
					int num17;
					if (i >= num3 - num7)
					{
						int num13 = i - (num3 - num7);
						num14 = num2 + num13;
						num15 = num13;
						int num16 = array2[num15++] + ((!val2.Equals(c2[num14++])) ? 1 : 0);
						num17 = array2[num15];
						num17++;
						num18 = num17;
						if (num17 > num16)
						{
							num17 = num16;
						}
						array2[num15++] = num17;
					}
					else
					{
						num15 = 1;
						num14 = num2;
						num18 = (num17 = i);
					}
					if (i <= num7 + 1)
					{
						num8 = num4 + i - num7 - 2;
					}
					while (num15 <= num8)
					{
						int num19 = --num18 + ((!val2.Equals(c2[num14++])) ? 1 : 0);
						num17++;
						if (num17 > num19)
						{
							num17 = num19;
						}
						num18 = array2[num15];
						num18++;
						if (num17 > num18)
						{
							num17 = num18;
						}
						array2[num15++] = num17;
					}
					if (i <= num7)
					{
						int num20 = --num18 + ((!val2.Equals(c2[num14])) ? 1 : 0);
						num17++;
						if (num17 > num20)
						{
							num17 = num20;
						}
						array2[num15] = num17;
					}
				}
			}
			return array2[num8];
		}

		private static int Memchr<T>(T[] haystack, int offset, T needle, int num) where T : IEquatable<T>
		{
			if (num != 0)
			{
				int num2 = 0;
				do
				{
					if (haystack[offset + num2].Equals(needle))
					{
						return 1;
					}
					num2++;
				}
				while (--num != 0);
			}
			return 0;
		}

		public static double GetRatio<T>(T[] input1, T[] input2) where T : IEquatable<T>
		{
			int num = input1.Length;
			int num2 = input2.Length;
			int num3 = num + num2;
			int num4 = EditDistance(input1, input2, 1);
			if (num4 != 0)
			{
				return (double)(num3 - num4) / (double)num3;
			}
			return 1.0;
		}

		public static double GetRatio<T>(IEnumerable<T> input1, IEnumerable<T> input2) where T : IEquatable<T>
		{
			T[] array = input1.ToArray();
			T[] array2 = input2.ToArray();
			int num = array.Length;
			int num2 = array2.Length;
			int num3 = num + num2;
			int num4 = EditDistance(array, array2, 1);
			if (num4 != 0)
			{
				return (double)(num3 - num4) / (double)num3;
			}
			return 1.0;
		}

		public static double GetRatio(string s1, string s2)
		{
			return GetRatio(s1.ToCharArray(), s2.ToCharArray());
		}
	}
	public static class Process
	{
		private static readonly IRatioScorer s_defaultScorer = ScorerCache.Get<WeightedRatioScorer>();

		private static readonly Func<string, string> s_defaultStringProcessor = StringPreprocessorFactory.GetPreprocessor(PreprocessMode.Full);

		public static IEnumerable<ExtractedResult<string>> ExtractAll(string query, IEnumerable<string> choices, Func<string, string> processor = null, IRatioScorer scorer = null, int cutoff = 0)
		{
			if (processor == null)
			{
				processor = s_defaultStringProcessor;
			}
			if (scorer == null)
			{
				scorer = s_defaultScorer;
			}
			return ResultExtractor.ExtractWithoutOrder(query, choices, processor, scorer, cutoff);
		}

		public static IEnumerable<ExtractedResult<T>> ExtractAll<T>(T query, IEnumerable<T> choices, Func<T, string> processor, IRatioScorer scorer = null, int cutoff = 0)
		{
			if (scorer == null)
			{
				scorer = s_defaultScorer;
			}
			return ResultExtractor.ExtractWithoutOrder(query, choices, processor, scorer, cutoff);
		}

		public static IEnumerable<ExtractedResult<string>> ExtractTop(string query, IEnumerable<string> choices, Func<string, string> processor = null, IRatioScorer scorer = null, int limit = 5, int cutoff = 0)
		{
			if (processor == null)
			{
				processor = s_defaultStringProcessor;
			}
			if (scorer == null)
			{
				scorer = s_defaultScorer;
			}
			return ResultExtractor.ExtractTop(query, choices, processor, scorer, limit, cutoff);
		}

		public static IEnumerable<ExtractedResult<T>> ExtractTop<T>(T query, IEnumerable<T> choices, Func<T, string> processor, IRatioScorer scorer = null, int limit = 5, int cutoff = 0)
		{
			if (scorer == null)
			{
				scorer = s_defaultScorer;
			}
			return ResultExtractor.ExtractTop(query, choices, processor, scorer, limit, cutoff);
		}

		public static IEnumerable<ExtractedResult<string>> ExtractSorted(string query, IEnumerable<string> choices, Func<string, string> processor = null, IRatioScorer scorer = null, int cutoff = 0)
		{
			if (processor == null)
			{
				processor = s_defaultStringProcessor;
			}
			if (scorer == null)
			{
				scorer = s_defaultScorer;
			}
			return ResultExtractor.ExtractSorted(query, choices, processor, scorer, cutoff);
		}

		public static IEnumerable<ExtractedResult<T>> ExtractSorted<T>(T query, IEnumerable<T> choices, Func<T, string> processor, IRatioScorer scorer = null, int cutoff = 0)
		{
			if (scorer == null)
			{
				scorer = s_defaultScorer;
			}
			return ResultExtractor.ExtractSorted(query, choices, processor, scorer, cutoff);
		}

		public static ExtractedResult<string> ExtractOne(string query, IEnumerable<string> choices, Func<string, string> processor = null, IRatioScorer scorer = null, int cutoff = 0)
		{
			if (processor == null)
			{
				processor = s_defaultStringProcessor;
			}
			if (scorer == null)
			{
				scorer = s_defaultScorer;
			}
			return ResultExtractor.ExtractOne(query, choices, processor, scorer, cutoff);
		}

		public static ExtractedResult<T> ExtractOne<T>(T query, IEnumerable<T> choices, Func<T, string> processor, IRatioScorer scorer = null, int cutoff = 0)
		{
			if (scorer == null)
			{
				scorer = s_defaultScorer;
			}
			return ResultExtractor.ExtractOne(query, choices, processor, scorer, cutoff);
		}

		public static ExtractedResult<string> ExtractOne(string query, params string[] choices)
		{
			return ResultExtractor.ExtractOne(query, choices, s_defaultStringProcessor, s_defaultScorer);
		}
	}
}
namespace FuzzySharp.Utils
{
	public abstract class Heap<T> : IEnumerable<T>, IEnumerable
	{
		private const int InitialCapacity = 0;

		private const int GrowFactor = 2;

		private const int MinGrow = 1;

		private int _capacity;

		private T[] _heap = new T[0];

		private int _tail;

		public int Count => _tail;

		public int Capacity => _capacity;

		protected Comparer<T> Comparer { get; }

		protected abstract bool Dominates(T x, T y);

		protected Heap()
			: this(Comparer<T>.Default)
		{
		}

		protected Heap(Comparer<T> comparer)
			: this(Enumerable.Empty<T>(), comparer)
		{
		}

		protected Heap(IEnumerable<T> collection)
			: this(collection, Comparer<T>.Default)
		{
		}

		protected Heap(IEnumerable<T> collection, Comparer<T> comparer)
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			Comparer = comparer ?? throw new ArgumentNullException("comparer");
			foreach (T item in collection)
			{
				if (Count == Capacity)
				{
					Grow();
				}
				_heap[_tail++] = item;
			}
			for (int num = Parent(_tail - 1); num >= 0; num--)
			{
				BubbleDown(num);
			}
		}

		public void Add(T item)
		{
			if (Count == Capacity)
			{
				Grow();
			}
			_heap[_tail++] = item;
			BubbleUp(_tail - 1);
		}

		private void BubbleUp(int i)
		{
			while (i != 0 && !Dominates(_heap[Parent(i)], _heap[i]))
			{
				Swap(i, Parent(i));
				i = Parent(i);
			}
		}

		public T GetMin()
		{
			if (Count == 0)
			{
				throw new InvalidOperationException("Heap is empty");
			}
			return _heap[0];
		}

		public T ExtractDominating()
		{
			if (Count == 0)
			{
				throw new InvalidOperationException("Heap is empty");
			}
			T result = _heap[0];
			_tail--;
			Swap(_tail, 0);
			BubbleDown(0);
			return result;
		}

		private void BubbleDown(int i)
		{
			while (true)
			{
				int num = Dominating(i);
				if (num == i)
				{
					break;
				}
				Swap(i, num);
				i = num;
			}
		}

		private int Dominating(int i)
		{
			int dominatingNode = i;
			dominatingNode = GetDominating(YoungChild(i), dominatingNode);
			return GetDominating(OldChild(i), dominatingNode);
		}

		private int GetDominating(int newNode, int dominatingNode)
		{
			if (newNode < _tail && !Dominates(_heap[dominatingNode], _heap[newNode]))
			{
				return newNode;
			}
			return dominatingNode;
		}

		private void Swap(int i, int j)
		{
			T val = _heap[i];
			_heap[i] = _heap[j];
			_heap[j] = val;
		}

		private static int Parent(int i)
		{
			return (i + 1) / 2 - 1;
		}

		private static int YoungChild(int i)
		{
			return (i + 1) * 2 - 1;
		}

		private static int OldChild(int i)
		{
			return YoungChild(i) + 1;
		}

		private void Grow()
		{
			int num = _capacity * 2 + 1;
			T[] array = new T[num];
			Array.Copy(_heap, array, _capacity);
			_heap = array;
			_capacity = num;
		}

		public IEnumerator<T> GetEnumerator()
		{
			return _heap.Take(Count).GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
	}
	public class MaxHeap<T> : Heap<T>
	{
		public MaxHeap()
			: this(Comparer<T>.Default)
		{
		}

		public MaxHeap(Comparer<T> comparer)
			: base(comparer)
		{
		}

		public MaxHeap(IEnumerable<T> collection, Comparer<T> comparer)
			: base(collection, comparer)
		{
		}

		public MaxHeap(IEnumerable<T> collection)
			: base(collection)
		{
		}

		protected override bool Dominates(T x, T y)
		{
			return base.Comparer.Compare(x, y) >= 0;
		}
	}
	public class MinHeap<T> : Heap<T>
	{
		public MinHeap()
			: this(Comparer<T>.Default)
		{
		}

		public MinHeap(Comparer<T> comparer)
			: base(comparer)
		{
		}

		public MinHeap(IEnumerable<T> collection)
			: base(collection)
		{
		}

		public MinHeap(IEnumerable<T> collection, Comparer<T> comparer)
			: base(collection, comparer)
		{
		}

		protected override bool Dominates(T x, T y)
		{
			return base.Comparer.Compare(x, y) <= 0;
		}
	}
	public class Permutor<T> where T : IComparable<T>
	{
		private readonly List<T> _set;

		public Permutor(IEnumerable<T> set)
		{
			_set = set.ToList();
		}

		public List<T> PermutationAt(long i)
		{
			List<T> list = new List<T>(_set.OrderBy((T e) => e).ToList());
			for (long num = 0L; num < i - 1; num++)
			{
				NextPermutation(list);
			}
			return list;
		}

		public List<T> NextPermutation()
		{
			NextPermutation(_set);
			return _set;
		}

		public bool NextPermutation(List<T> set)
		{
			int num = set.Count - 1;
			while (num > 0 && set[num - 1].CompareTo(set[num]) >= 0)
			{
				num--;
			}
			if (num <= 0)
			{
				return false;
			}
			int num2 = set.Count - 1;
			while (set[num2].CompareTo(set[num - 1]) <= 0)
			{
				num2--;
			}
			T value = set[num - 1];
			set[num - 1] = set[num2];
			set[num2] = value;
			num2 = set.Count - 1;
			while (num < num2)
			{
				value = set[num];
				set[num] = set[num2];
				set[num2] = value;
				num++;
				num2--;
			}
			return true;
		}
	}
	public static class Permutation
	{
		public static List<List<T>> AllPermutations<T>(this IEnumerable<T> seed)
		{
			List<T> list = new List<T>(seed);
			return Permute(list, 0, list.Count - 1).ToList();
		}

		public static List<List<T>> PermutationsOfSize<T>(this IEnumerable<T> seed, int size)
		{
			if (seed.Count() < size)
			{
				return new List<List<T>>();
			}
			return seed.PermutationsOfSize(new List<T>(), size).ToList();
		}

		private static IEnumerable<List<T>> PermutationsOfSize<T>(this IEnumerable<T> seed, List<T> set, int size)
		{
			if (size == 0)
			{
				foreach (List<T> item in set.AllPermutations())
				{
					yield return item;
				}
				yield break;
			}
			List<T> seedAsList = seed.ToList();
			for (int i = 0; i < seedAsList.Count; i++)
			{
				List<T> set2 = new List<T>(set) { seedAsList[i] };
				foreach (List<T> item2 in seedAsList.Skip(i + 1).PermutationsOfSize(set2, size - 1))
				{
					yield return item2;
				}
			}
		}

		private static IEnumerable<List<T>> Permute<T>(List<T> set, int start, int end)
		{
			if (start == end)
			{
				yield return new List<T>(set);
				yield break;
			}
			for (int i = start; i <= end; i++)
			{
				Swap(set, start, i);
				foreach (List<T> item in Permute(set, start + 1, end))
				{
					yield return item;
				}
				Swap(set, start, i);
			}
		}

		private static void Swap<T>(List<T> set, int a, int b)
		{
			T value = set[a];
			set[a] = set[b];
			set[b] = value;
		}

		public static IEnumerable<List<T>> Cycles<T>(IEnumerable<T> seed)
		{
			LinkedList<T> set = new LinkedList<T>(seed);
			for (int i = 0; i < set.Count; i++)
			{
				yield return new List<T>(set);
				T value = set.First();
				set.RemoveFirst();
				set.AddLast(value);
			}
		}

		public static bool IsPermutationOf<T>(this IEnumerable<T> set, IEnumerable<T> other)
		{
			return new HashSet<T>(set).SetEquals(other);
		}
	}
}
namespace FuzzySharp.SimilarityRatio
{
	public static class ScorerCache
	{
		private static readonly ConcurrentDictionary<Type, IRatioScorer> s_scorerCache = new ConcurrentDictionary<Type, IRatioScorer>();

		public static IRatioScorer Get<T>() where T : IRatioScorer, new()
		{
			return s_scorerCache.GetOrAdd(typeof(T), new T());
		}
	}
}
namespace FuzzySharp.SimilarityRatio.Strategy
{
	internal class DefaultRatioStrategy
	{
		public static int Calculate(string input1, string input2)
		{
			if (input1.Length == 0 || input2.Length == 0)
			{
				return 0;
			}
			return (int)Math.Round(100.0 * Levenshtein.GetRatio(input1, input2));
		}
	}
	internal class PartialRatioStrategy
	{
		public static int Calculate(string input1, string input2)
		{
			if (input1.Length == 0 || input2.Length == 0)
			{
				return 0;
			}
			string text;
			string text2;
			if (input1.Length < input2.Length)
			{
				text = input1;
				text2 = input2;
			}
			else
			{
				text = input2;
				text2 = input1;
			}
			MatchingBlock[] matchingBlocks = Levenshtein.GetMatchingBlocks(text, text2);
			List<double> list = new List<double>();
			MatchingBlock[] array = matchingBlocks;
			foreach (MatchingBlock matchingBlock in array)
			{
				int num = matchingBlock.DestPos - matchingBlock.SourcePos;
				int num2 = ((num > 0) ? num : 0);
				int num3 = num2 + text.Length;
				if (num3 > text2.Length)
				{
					num3 = text2.Length;
				}
				string s = text2.Substring(num2, num3 - num2);
				double ratio = Levenshtein.GetRatio(text, s);
				if (ratio > 0.995)
				{
					return 100;
				}
				list.Add(ratio);
			}
			return (int)Math.Round(100.0 * list.Max());
		}
	}
}
namespace FuzzySharp.SimilarityRatio.Strategy.Generic
{
	internal class DefaultRatioStrategy<T> where T : IEquatable<T>
	{
		public static int Calculate(T[] input1, T[] input2)
		{
			if (input1.Length == 0 || input2.Length == 0)
			{
				return 0;
			}
			return (int)Math.Round(100.0 * Levenshtein.GetRatio(input1, input2));
		}
	}
	internal class PartialRatioStrategy<T> where T : IEquatable<T>
	{
		public static int Calculate(T[] input1, T[] input2)
		{
			if (input1.Length == 0 || input2.Length == 0)
			{
				return 0;
			}
			T[] array;
			T[] array2;
			if (input1.Length < input2.Length)
			{
				array = input1;
				array2 = input2;
			}
			else
			{
				array = input2;
				array2 = input1;
			}
			MatchingBlock[] matchingBlocks = Levenshtein.GetMatchingBlocks(array, array2);
			List<double> list = new List<double>();
			MatchingBlock[] array3 = matchingBlocks;
			foreach (MatchingBlock matchingBlock in array3)
			{
				int num = matchingBlock.DestPos - matchingBlock.SourcePos;
				int num2 = ((num > 0) ? num : 0);
				int num3 = num2 + array.Length;
				if (num3 > array2.Length)
				{
					num3 = array2.Length;
				}
				IEnumerable<T> input3 = array2.Skip(num2).Take(num3 - num2);
				double ratio = Levenshtein.GetRatio(array, input3);
				if (ratio > 0.995)
				{
					return 100;
				}
				list.Add(ratio);
			}
			return (int)Math.Round(100.0 * list.Max());
		}
	}
}
namespace FuzzySharp.SimilarityRatio.Scorer
{
	public interface IRatioScorer
	{
		int Score(string input1, string input2);

		int Score(string input1, string input2, PreprocessMode preprocessMode);
	}
	public abstract class ScorerBase : IRatioScorer
	{
		public abstract int Score(string input1, string input2);

		public int Score(string input1, string input2, PreprocessMode preprocessMode)
		{
			Func<string, string> preprocessor = StringPreprocessorFactory.GetPreprocessor(preprocessMode);
			input1 = preprocessor(input1);
			input2 = preprocessor(input2);
			return Score(input1, input2);
		}
	}
}
namespace FuzzySharp.SimilarityRatio.Scorer.StrategySensitive
{
	public class DefaultRatioScorer : SimpleRatioScorerBase
	{
		protected override Func<string, string, int> Scorer => DefaultRatioStrategy.Calculate;
	}
	public class PartialRatioScorer : SimpleRatioScorerBase
	{
		protected override Func<string, string, int> Scorer => PartialRatioStrategy.Calculate;
	}
	public abstract class SimpleRatioScorerBase : StrategySensitiveScorerBase
	{
		public override int Score(string input1, string input2)
		{
			return Scorer(input1, input2);
		}
	}
	public abstract class StrategySensitiveScorerBase : ScorerBase
	{
		protected abstract Func<string, string, int> Scorer { get; }
	}
	public class PartialTokenAbbreviationScorer : TokenAbbreviationScorerBase
	{
		protected override Func<string, string, int> Scorer => PartialRatioStrategy.Calculate;
	}
	public class TokenAbbreviationScorer : TokenAbbreviationScorerBase
	{
		protected override Func<string, string, int> Scorer => DefaultRatioStrategy.Calculate;
	}
	public abstract class TokenAbbreviationScorerBase : StrategySensitiveScorerBase
	{
		public override int Score(string input1, string input2)
		{
			string text;
			string text2;
			if (input1.Length < input2.Length)
			{
				text = input1;
				text2 = input2;
			}
			else
			{
				text = input2;
				text2 = input1;
			}
			if ((double)text2.Length / (double)text.Length < 1.5)
			{
				return 0;
			}
			string[] array = (from Match m in Regex.Matches(text2, "[a-zA-Z]+")
				select m.Value).ToArray();
			string[] array2 = (from Match m in Regex.Matches(text, "[a-zA-Z]+")
				select m.Value).ToArray();
			if (array2.Length > 4)
			{
				return 0;
			}
			string[] seed;
			string[] array3;
			if (array.Length > array2.Length)
			{
				seed = array;
				array3 = array2;
			}
			else
			{
				seed = array2;
				array3 = array;
			}
			List<List<string>> list = seed.PermutationsOfSize(array3.Length);
			List<int> list2 = new List<int>();
			foreach (List<string> item in list)
			{
				double num = 0.0;
				for (int i = 0; i < array3.Length; i++)
				{
					string text3 = item[i];
					string text4 = array3[i];
					if (StringContainsInOrder(text3, text4))
					{
						int num2 = Scorer(text3, text4);
						num += (double)num2;
					}
				}
				list2.Add((int)(num / (double)array3.Length));
			}
			if (list2.Count != 0)
			{
				return list2.Max();
			}
			return 0;
		}

		private bool StringContainsInOrder(string s1, string s2)
		{
			if (s1.Length < s2.Length)
			{
				return false;
			}
			int num = 0;
			for (int i = 0; i < s1.Length; i++)
			{
				if (s2[num] == s1[i])
				{
					num++;
				}
				if (num == s2.Length)
				{
					return true;
				}
				if (i + s2.Length - num == s1.Length)
				{
					return false;
				}
			}
			return false;
		}
	}
	public class PartialTokenDifferenceScorer : TokenDifferenceScorerBase
	{
		protected override Func<string[], string[], int> Scorer => PartialRatioStrategy<string>.Calculate;
	}
	public class TokenDifferenceScorer : TokenDifferenceScorerBase
	{
		protected override Func<string[], string[], int> Scorer => DefaultRatioStrategy<string>.Calculate;
	}
	public abstract class TokenDifferenceScorerBase : StrategySensitiveScorerBase<string>, IRatioScorer
	{
		public override int Score(string[] input1, string[] input2)
		{
			return Scorer(input1, input2);
		}

		public int Score(string input1, string input2)
		{
			string[] input3 = (from s in Regex.Split(input1, "\\s+")
				where s.Any()
				orderby s
				select s).ToArray();
			string[] input4 = (from s in Regex.Split(input2, "\\s+")
				where s.Any()
				orderby s
				select s).ToArray();
			return Score(input3, input4);
		}

		public int Score(string input1, string input2, PreprocessMode preprocessMode)
		{
			Func<string, string> preprocessor = StringPreprocessorFactory.GetPreprocessor(preprocessMode);
			input1 = preprocessor(input1);
			input2 = preprocessor(input2);
			return Score(input1, input2);
		}
	}
	public class PartialTokenInitialismScorer : TokenInitialismScorerBase
	{
		protected override Func<string, string, int> Scorer => PartialRatioStrategy.Calculate;
	}
	public class TokenInitialismScorer : TokenInitialismScorerBase
	{
		protected override Func<string, string, int> Scorer => DefaultRatioStrategy.Calculate;
	}
	public abstract class TokenInitialismScorerBase : StrategySensitiveScorerBase
	{
		public override int Score(string input1, string input2)
		{
			string text;
			string text2;
			if (input1.Length < input2.Length)
			{
				text = input1;
				text2 = input2;
			}
			else
			{
				text = input2;
				text2 = input1;
			}
			if ((double)text2.Length / (double)text.Length < 3.0)
			{
				return 0;
			}
			IEnumerable<char> values = from s in Regex.Split(text2, "\\s+")
				where s.Any()
				select s[0];
			return Scorer(string.Join("", values), text);
		}
	}
	public class PartialTokenSetScorer : TokenSetScorerBase
	{
		protected override Func<string, string, int> Scorer => PartialRatioStrategy.Calculate;
	}
	public class TokenSetScorer : TokenSetScorerBase
	{
		protected override Func<string, string, int> Scorer => DefaultRatioStrategy.Calculate;
	}
	public abstract class TokenSetScorerBase : StrategySensitiveScorerBase
	{
		public override int Score(string input1, string input2)
		{
			HashSet<string> hashSet = new HashSet<string>(from s in Regex.Split(input1, "\\s+")
				where s.Any()
				select s);
			HashSet<string> hashSet2 = new HashSet<string>(from s in Regex.Split(input2, "\\s+")
				where s.Any()
				select s);
			string text = string.Join(" ", from s in hashSet.Intersect(hashSet2)
				orderby s
				select s).Trim();
			string text2 = (text + " " + string.Join(" ", from s in hashSet.Except(hashSet2)
				orderby s
				select s)).Trim();
			string arg = (text + " " + string.Join(" ", from s in hashSet2.Except(hashSet)
				orderby s
				select s)).Trim();
			return new int[3]
			{
				Scorer(text, text2),
				Scorer(text, arg),
				Scorer(text2, arg)
			}.Max();
		}
	}
	public class PartialTokenSortScorer : TokenSortScorerBase
	{
		protected override Func<string, string, int> Scorer => PartialRatioStrategy.Calculate;
	}
	public abstract class TokenSortScorerBase : StrategySensitiveScorerBase
	{
		public override int Score(string input1, string input2)
		{
			string arg = string.Join(" ", from s in Regex.Split(input1, "\\s+")
				where s.Any()
				orderby s
				select s).Trim();
			string arg2 = string.Join(" ", from s in Regex.Split(input2, "\\s+")
				where s.Any()
				orderby s
				select s).Trim();
			return Scorer(arg, arg2);
		}
	}
	public class TokenSortScorer : TokenSortScorerBase
	{
		protected override Func<string, string, int> Scorer => DefaultRatioStrategy.Calculate;
	}
}
namespace FuzzySharp.SimilarityRatio.Scorer.StrategySensitive.Generic
{
	public abstract class StrategySensitiveScorerBase<T> : ScorerBase<T> where T : IEquatable<T>
	{
		protected abstract Func<T[], T[], int> Scorer { get; }
	}
}
namespace FuzzySharp.SimilarityRatio.Scorer.Generic
{
	public interface IRatioScorer<in T> where T : IEquatable<T>
	{
		int Score(T[] input1, T[] input2);
	}
	public abstract class ScorerBase<T> : IRatioScorer<T> where T : IEquatable<T>
	{
		public abstract int Score(T[] input1, T[] input2);
	}
}
namespace FuzzySharp.SimilarityRatio.Scorer.Composite
{
	public class WeightedRatioScorer : ScorerBase
	{
		private static double UNBASE_SCALE = 0.95;

		private static double PARTIAL_SCALE = 0.9;

		private static bool TRY_PARTIALS = true;

		public override int Score(string input1, string input2)
		{
			int length = input1.Length;
			int length2 = input2.Length;
			if (length == 0 || length2 == 0)
			{
				return 0;
			}
			bool flag = TRY_PARTIALS;
			double uNBASE_SCALE = UNBASE_SCALE;
			double num = PARTIAL_SCALE;
			int num2 = Fuzz.Ratio(input1, input2);
			double num3 = (double)Math.Max(length, length2) / (double)Math.Min(length, length2);
			if (num3 < 1.5)
			{
				flag = false;
			}
			if (num3 > 8.0)
			{
				num = 0.6;
			}
			if (flag)
			{
				double num4 = (double)Fuzz.PartialRatio(input1, input2) * num;
				double num5 = (double)Fuzz.TokenSortRatio(input1, input2) * uNBASE_SCALE * num;
				double num6 = (double)Fuzz.TokenSetRatio(input1, input2) * uNBASE_SCALE * num;
				return (int)Math.Round(new double[4] { num2, num4, num5, num6 }.Max());
			}
			double num7 = (double)Fuzz.TokenSortRatio(input1, input2) * uNBASE_SCALE;
			double num8 = (double)Fuzz.TokenSetRatio(input1, input2) * uNBASE_SCALE;
			return (int)Math.Round(new double[3] { num2, num7, num8 }.Max());
		}
	}
}
namespace FuzzySharp.PreProcess
{
	public enum PreprocessMode
	{
		Full,
		None
	}
	internal class StringPreprocessorFactory
	{
		private static string pattern = "[^ a-zA-Z0-9]";

		private static string Default(string input)
		{
			input = Regex.Replace(input, pattern, " ");
			input = input.ToLower();
			return input.Trim();
		}

		public static Func<string, string> GetPreprocessor(PreprocessMode mode)
		{
			return mode switch
			{
				PreprocessMode.Full => Default, 
				PreprocessMode.None => (string s) => s, 
				_ => throw new InvalidOperationException($"Invalid string preprocessor mode: {mode}"), 
			};
		}
	}
}
namespace FuzzySharp.Extractor
{
	public class ExtractedResult<T> : IComparable<ExtractedResult<T>>
	{
		public readonly T Value;

		public readonly int Score;

		public readonly int Index;

		public ExtractedResult(T value, int score)
		{
			Value = value;
			Score = score;
		}

		public ExtractedResult(T value, int score, int index)
		{
			Value = value;
			Score = score;
			Index = index;
		}

		public int CompareTo(ExtractedResult<T> other)
		{
			return Comparer<int>.Default.Compare(Score, other.Score);
		}

		public override string ToString()
		{
			if (typeof(T) == typeof(string))
			{
				return $"(string: {Value}, score: {Score}, index: {Index})";
			}
			return $"(value: {Value.ToString()}, score: {Score}, index: {Index})";
		}
	}
	public static class ResultExtractor
	{
		public static IEnumerable<ExtractedResult<T>> ExtractWithoutOrder<T>(T query, IEnumerable<T> choices, Func<T, string> processor, IRatioScorer scorer, int cutoff = 0)
		{
			int index = 0;
			string processedQuery = processor(query);
			foreach (T choice in choices)
			{
				int num = scorer.Score(processedQuery, processor(choice));
				if (num >= cutoff)
				{
					yield return new ExtractedResult<T>(choice, num, index);
				}
				index++;
			}
		}

		public static ExtractedResult<T> ExtractOne<T>(T query, IEnumerable<T> choices, Func<T, string> processor, IRatioScorer calculator, int cutoff = 0)
		{
			return ExtractWithoutOrder(query, choices, processor, calculator, cutoff).Max();
		}

		public static IEnumerable<ExtractedResult<T>> ExtractSorted<T>(T query, IEnumerable<T> choices, Func<T, string> processor, IRatioScorer calculator, int cutoff = 0)
		{
			return from r in ExtractWithoutOrder(query, choices, processor, calculator, cutoff)
				orderby r.Score descending
				select r;
		}

		public static IEnumerable<ExtractedResult<T>> ExtractTop<T>(T query, IEnumerable<T> choices, Func<T, string> processor, IRatioScorer calculator, int limit, int cutoff = 0)
		{
			return ExtractWithoutOrder(query, choices, processor, calculator, cutoff).MaxN(limit).Reverse();
		}
	}
}
namespace FuzzySharp.Extensions
{
	public static class EnumerableExtensions
	{
		public static IEnumerable<T> MaxN<T>(this IEnumerable<T> source, int n) where T : IComparable<T>
		{
			MinHeap<T> queue = new MinHeap<T>(Comparer<T>.Create((T x, T y) => x.CompareTo(y)));
			foreach (T item in source)
			{
				if (queue.Count < n)
				{
					queue.Add(item);
				}
				else if (item.CompareTo(queue.GetMin()) > 0)
				{
					queue.ExtractDominating();
					queue.Add(item);
				}
			}
			for (int i = 0; i < n; i++)
			{
				if (queue.Count <= 0)
				{
					break;
				}
				yield return queue.ExtractDominating();
			}
		}

		public static IEnumerable<T> MaxNBy<T, TVal>(this IEnumerable<T> source, int n, Func<T, TVal> selector) where TVal : IComparable<TVal>
		{
			MinHeap<T> queue = new MinHeap<T>(Comparer<T>.Create((T x, T y) => selector(x).CompareTo(selector(y))));
			foreach (T item in source)
			{
				if (queue.Count < n)
				{
					queue.Add(item);
				}
				else if (selector(item).CompareTo(selector(queue.GetMin())) > 0)
				{
					queue.ExtractDominating();
					queue.Add(item);
				}
			}
			for (int i = 0; i < n; i++)
			{
				if (queue.Count <= 0)
				{
					break;
				}
				yield return queue.ExtractDominating();
			}
		}
	}
}
namespace FuzzySharp.Edits
{
	public enum EditType
	{
		DELETE,
		EQUAL,
		INSERT,
		REPLACE,
		KEEP
	}
	public class EditOp
	{
		public EditType EditType { get; set; }

		public int SourcePos { get; set; }

		public int DestPos { get; set; }

		public override string ToString()
		{
			return $"{EditType}({SourcePos}, {DestPos})";
		}
	}
	public class MatchingBlock
	{
		public int SourcePos { get; set; }

		public int DestPos { get; set; }

		public int Length { get; set; }

		public override string ToString()
		{
			return $"({SourcePos},{DestPos},{Length})";
		}
	}
	public class OpCode
	{
		public EditType EditType { get; set; }

		public int SourceBegin { get; set; }

		public int SourceEnd { get; set; }

		public int DestBegin { get; set; }

		public int DestEnd { get; set; }

		public override string ToString()
		{
			return $"{EditType}({SourceBegin},{SourceEnd},{DestBegin},{DestEnd})";
		}
	}
}