/// <summary> /// Заполняет компонент похожести всех узлов из Result на текстовую строку из заданной точки. /// Если по четверке (Имя, внешний контекст, внутренний контекст, текстовая строка) /// найден ровно один совпадающий узел - устанавливает флаг Singular, удаляет несовпадающие узлы из результата. /// </summary> /// <param name="Result"></param> /// <param name="Point"></param> /// <param name="Source"></param> private static void ProcessText(TreeSearchResult Result, PointOfInterest Point, string Source, bool Full = false) { List<TreeSearchResultNode> ExactMatch = new List<TreeSearchResultNode>(); TextSearch ts = new TextSearch(Source); foreach (TreeSearchResultNode node in Result._result) { Pair<int, int> Sim = ts.Similarity(node.TreeNode.Location, Point.Text); node.TextStringMatch = Sim.Second; if (Sim.First == TreeSearchOptions.Equility && node.NameMatch == TreeSearchOptions.Equility && node.OuterContextMatch == TreeSearchOptions.Equility && node.InnerContextMatch == TreeSearchOptions.Equility) ExactMatch.Add(node); } if (ExactMatch.Count == 1 && !Full) { Result.Singular = true; Result._result = ExactMatch; } }
/// <summary> /// Заполняет поле Location в единственном узле результата /// </summary> /// <param name="Result"></param> /// <param name="Source"></param> /// <param name="Text"></param> private static void FillLocationForSingularResult(TreeSearchResult Result, string Source, string Text) { PointOfInterest Point = Result._result[0].TreeNode.ClonePoint(); Point.ApplyInnerContext(); Point.Items.Clear(); Point.Text = Text; LexLocation Loc = FindTextPosition(Point, Source); Point.Location = Loc; Result._result[0].TreeNode = Point; }
/// <summary> /// Обрабатывает внешний контект всех узлов из Result, заполняет компонент похожести внешнего контекста. /// Если по паре (Имя, Внешний контекст) найден ровно один совпадающий узел - устанавливает флаг Singular, удаляет несовпадающие узлы из результата. /// </summary> /// <param name="Result"></param> /// <param name="Point"></param> private static void ProcessOuterContext(TreeSearchResult Result, PointOfInterest Point, bool Full = false) { List<TreeSearchResultNode> ExactMatch = new List<TreeSearchResultNode>(); foreach (TreeSearchResultNode node in Result._result) { int Sim = TreeSearchComparer.OuterContextsSimilarity(node.TreeNode.Context.GetRange(1, node.TreeNode.Context.Count-1), Point.Context.GetRange(1, Point.Context.Count-1)); node.OuterContextMatch = Sim; if (Sim == TreeSearchOptions.Equility && node.NameMatch == TreeSearchOptions.Equility) ExactMatch.Add(node); } if (ExactMatch.Count == 1 && !Full) { Result.Singular = true; Result._result = ExactMatch; } }
/// <summary> /// Обрабатывает внутренний контект всех узлов из Result, заполняет компонент похожести внутреннего контекста. /// Если по паре (Имя, Внутренний контекст) или по тройке (Имя, Внешний контекст, Внутренний контекст) /// найден ровно один совпадающий узел - устанавливает флаг Singular, удаляет несовпадающие узлы из результата. /// </summary> /// <param name="Result"></param> /// <param name="Point"></param> private static void ProcessInnerContext(TreeSearchResult Result, PointOfInterest Point, bool Full = false) { //return; //For testing, TODO remove List<TreeSearchResultNode> ExactMatchPair = new List<TreeSearchResultNode>(); List<TreeSearchResultNode> ExactMatchThree = new List<TreeSearchResultNode>(); List<List<string>> PointContext = ConvertInnerContextToList(Point); foreach (TreeSearchResultNode node in Result._result) { node.TreeNode.ApplyInnerContext(); List<List<string>> ResContext = ConvertInnerContextToList(node.TreeNode); int Sim = TreeSearchComparer.TokenListListsIntersection(ResContext, PointContext); node.InnerContextMatch = Sim; if (Sim == TreeSearchOptions.Equility && node.NameMatch == TreeSearchOptions.Equility) ExactMatchPair.Add(node); if (Sim == TreeSearchOptions.Equility && node.NameMatch == TreeSearchOptions.Equility && node.OuterContextMatch == TreeSearchOptions.Equility) ExactMatchThree.Add(node); } if (ExactMatchPair.Count == 1 && !Full) { Result.Singular = true; Result._result = ExactMatchPair; } if (ExactMatchThree.Count == 1 && !Full) { Result.Singular = true; Result._result = ExactMatchThree; } }
/// <summary> /// Обрабатывает заголовки всех узлов из Result, заполняет компонент похожести заголовка. /// Если по имени найден ровно один совпадающий узел - устанавливает флаг Singular, удаляет несовпадающие узлы из результата. /// </summary> /// <param name="Result"></param> /// <param name="Point"></param> private static void ProcessHeaders(TreeSearchResult Result, PointOfInterest Point, bool Full = false) { List<TreeSearchResultNode> exactMatch = new List<TreeSearchResultNode>(); foreach (TreeSearchResultNode node in Result._result) if (node.TreeNode.Context.Count != 0) { int sim = 0; if (string.IsNullOrWhiteSpace(Point.Context[0].Type) || node.TreeNode.Context[0].Type == Point.Context[0].Type) sim = TreeSearchComparer.TokenListsSimilarity(node.TreeNode.Context[0].Name, Point.Context[0].Name); node.HeaderMatch = sim; if (sim == TreeSearchOptions.Equility) exactMatch.Add(node); } if (exactMatch.Count == 1 && !Full) { Result.Singular = true; Result._result = exactMatch; } }
/// <summary> /// Обрабатывает идентификаторы всех узлов из Result, заполняет компонент похожести идентификатора. /// Если по имени найден ровно один совпадающий узел - устанавливает флаг Singular, удаляет несовпадающие узлы из результата. /// </summary> /// <param name="Result"></param> /// <param name="Point"></param> private static void ProcessIDs(TreeSearchResult Result, PointOfInterest Point, bool Full = false) { //пустой идентификатор похож на все непустые. Для совместимости со старыми версиями, где идентификатора не было. if (string.IsNullOrWhiteSpace(Point.ID)) { foreach (TreeSearchResultNode node in Result._result) node.NameMatch = TreeSearchOptions.Equility; return; } List<TreeSearchResultNode> exactMatch = new List<TreeSearchResultNode>(); foreach (TreeSearchResultNode node in Result._result) if (!string.IsNullOrWhiteSpace(node.TreeNode.ID)) { node.NameMatch = TreeSearchComparer.StringsSimilarity(node.TreeNode.ID, Point.ID); if (node.NameMatch == TreeSearchOptions.Equility) exactMatch.Add(node); } if (exactMatch.Count == 1 && !Full) if ((exactMatch[0].TreeNode.Context[0]?.Type ?? "") == (Point.Context[0]?.Type ?? "")) { Result.Singular = true; Result._result = exactMatch; } }
/// <summary> /// Возвращает величину похожести имени для самого похожего узла в множестве /// </summary> /// <param name="Nodes"></param> /// <param name="point"></param> /// <returns></returns> private static float GetMaxSimilarityByName(TreeSearchResult Nodes, PointOfInterest point, string Text) { if (Nodes.Count == 0) return -1; int maxSim = 0; foreach (TreeSearchResultNode node in Nodes._result) { int sim = TreeSearchComparer.TokenListsSimilarity(point.Context[0].Name, node.TreeNode.Context[0].Name); if (sim > maxSim) maxSim = sim; } //ProcessSearchResult(Nodes, point, Text); return (float)maxSim / TreeSearchOptions.Equility; }
/// <summary> /// Создает первоначальный объект результата поиска, заполняя его всеми узлами заданного типа из заданного дерева /// </summary> /// <param name="TreeRoot"></param> /// <param name="Type"></param> /// <returns></returns> private static TreeSearchResult InitializeResultFromTree(PointOfInterest TreeRoot, string Type) { TreeSearchResult result = new TreeSearchResult(); if (string.IsNullOrWhiteSpace(Type) || (TreeRoot.Context != null && TreeRoot.Context.Count != 0 && TreeRoot.Context[0].Type == Type)) result._result.Add(new TreeSearchResultNode(TreeRoot)); foreach (PointOfInterest point in TreeRoot.Items) result._result.AddRange(InitializeResultFromTree(point, Type)._result); return result; }
/// <summary> /// Возвращает константы NearG и NearL для заданного узла в дереве /// </summary> /// <param name="TreeRoot"></param> /// <param name="point"></param> /// <param name="NearL"></param> /// <param name="NearG"></param> public static void SetNearLG(PointOfInterest TreeRoot, PointOfInterest point, string Text, out float NearL, out float NearG) { NearL = 0; NearG = 0; if (TreeRoot == null || point == null) return; //В TreeG записываем все потенциально искомые узлы TreeSearchResult TreeG = InitializeResultFromTree(TreeRoot, point.Context[0]?.Type); TreeSearchResult TreeL = new TreeSearchResult(); //Переписываем в TreeL соседние узлы, удаляем их из TreeG (Point тоже удаляем) HashSet<PointOfInterest> Neighbours = GetNeighbours(TreeRoot, point); for (int i = 0; i < TreeG._result.Count;) if (TreeG._result[i].TreeNode == point) TreeG._result.RemoveAt(i); else if (Neighbours.Contains(TreeG._result[i].TreeNode)) { TreeL._result.Add(TreeG._result[i]); TreeG._result.RemoveAt(i); } else ++i; //Находим метрику для наиболее похожих имен узлов в двух множествах NearL = GetMaxSimilarityByName(TreeL, point, Text); NearG = GetMaxSimilarityByName(TreeG, point, Text); }