Files
Learning-UnityNGO/Assets/Plugins/QFSW/Quantum Console/Source/Scripts/Suggestions/QuantumSuggestor.cs
T
2026-06-17 20:44:53 +03:00

107 lines
4.3 KiB
C#

using QFSW.QC.Comparators;
using System;
using System.Collections.Generic;
using System.Linq;
namespace QFSW.QC
{
/// <summary>
/// Provides a filtered and sorted list of suggestions for a given context using IQcSuggestors and IQcSuggestionFilter
/// </summary>
public class QuantumSuggestor
{
private readonly IQcSuggestor[] _suggestors;
private readonly IQcSuggestionFilter[] _suggestionFilters;
private readonly List<IQcSuggestion> _suggestionBuffer = new List<IQcSuggestion>();
/// <summary>
/// Creates a Quantum Suggestor with a custom set of suggestors an suggestion filters.
/// </summary>
/// <param name="suggestors">The IQcSuggestors to use in this Quantum Suggestor.</param>
/// /// <param name="suggestionFilters">The IQcSuggestionFilters to use in this Quantum Suggestor.</param>
public QuantumSuggestor(IEnumerable<IQcSuggestor> suggestors, IEnumerable<IQcSuggestionFilter> suggestionFilters)
{
_suggestors = suggestors.ToArray();
_suggestionFilters = suggestionFilters.ToArray();
}
/// <summary>
/// Creates a Quantum Suggestor with the default injected suggestors and suggestion filters.
/// </summary>
public QuantumSuggestor() : this(
new InjectionLoader<IQcSuggestor>().GetInjectedInstances(),
new InjectionLoader<IQcSuggestionFilter>().GetInjectedInstances())
{
}
/// <summary>
/// Gets suggestions for a given context.
/// </summary>
/// <param name="context">The context to get suggestions for.</param>
/// <param name="options">Options for the suggestor.</param>
/// <returns>The sorted and filtered suggestions for the provided context.</returns>
public IEnumerable<IQcSuggestion> GetSuggestions(SuggestionContext context, SuggestorOptions options)
{
PreprocessContext(ref context);
// Get and filter suggestions
IEnumerable<IQcSuggestion> suggestions =
_suggestors
.SelectMany(x => x.GetSuggestions(context, options))
.Where(x => IsSuggestionPermitted(x, context));
_suggestionBuffer.Clear();
_suggestionBuffer.AddRange(suggestions);
// Sort suggestions
AlphanumComparator comparator = new AlphanumComparator();
IOrderedEnumerable<IQcSuggestion> sortedSuggestions =
_suggestionBuffer
.OrderBy(x => x.PrimarySignature.Length)
.ThenBy(x => x.PrimarySignature, comparator)
.ThenBy(x => x.SecondarySignature.Length)
.ThenBy(x => x.SecondarySignature, comparator);
if (options.Fuzzy)
{
StringComparison comparisonType = options.CaseSensitive
? StringComparison.CurrentCulture
: StringComparison.CurrentCultureIgnoreCase;
sortedSuggestions = sortedSuggestions
.OrderBy(x => x.PrimarySignature.IndexOf(context.Prompt, comparisonType));
}
// Return suggestions to user
return sortedSuggestions;
}
private void PreprocessContext(ref SuggestionContext context)
{
// Strip the scope on the provided prompt in the context to improve suggestions
// We want to allow incomplete scope reduction on the prompt so that you get suggestions
// as if you had finished the scope properly
TextProcessing.ReduceScopeOptions options = TextProcessing.ReduceScopeOptions.Default;
options.ReduceIncompleteScope = true;
context.Prompt = context.Prompt.ReduceScope(options);
}
private bool IsSuggestionPermitted(IQcSuggestion suggestion, SuggestionContext context)
{
// LINQ alternative produces too much garbage
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (IQcSuggestionFilter filter in _suggestionFilters)
{
if (!filter.IsSuggestionPermitted(suggestion, context))
{
return false;
}
}
return true;
}
}
}