From 7955a0909043b964875796142bcfc5d9997e4798 Mon Sep 17 00:00:00 2001 From: roridev Date: Fri, 27 Nov 2020 13:52:53 -0300 Subject: [PATCH] Creates ValidateAndGetBestMatch function This function will validate all commands from a SearchResult and return the result of said validation, along with the command matched, if a valid match was found. --- src/Discord.Net.Commands/CommandService.cs | 77 ++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/src/Discord.Net.Commands/CommandService.cs b/src/Discord.Net.Commands/CommandService.cs index 15f0c866d..be83b955f 100644 --- a/src/Discord.Net.Commands/CommandService.cs +++ b/src/Discord.Net.Commands/CommandService.cs @@ -602,6 +602,83 @@ namespace Discord.Commands return match.Command.Priority + totalArgsScore * 0.99f; } + /// + /// Validates and gets the best from a specified + /// + /// The SearchResult. + /// The context of the command. + /// The service provider to be used on the command's dependency injection. + /// The handling mode when multiple command matches are found. + /// A task that represents the asynchronous validation operation. The task result contains the result of the + /// command validation and the command matched, if a match was found. + public async Task<(IResult, Optional)> ValidateAndGetBestMatch(SearchResult matches, ICommandContext context, IServiceProvider provider, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception) + { + if (!matches.IsSuccess) + return (matches, Optional.Create()); + + var commands = matches.Commands; + var preconditionResults = new Dictionary(); + + foreach (var command in commands) + { + preconditionResults[command] = await command.CheckPreconditionsAsync(context, provider); + } + + var successfulPreconditions = preconditionResults + .Where(x => x.Value.IsSuccess) + .ToArray(); + + if (successfulPreconditions.Length == 0) + { + var bestCandidate = preconditionResults + .OrderByDescending(x => x.Key.Command.Priority) + .FirstOrDefault(x => !x.Value.IsSuccess); + + return (bestCandidate.Value, bestCandidate.Key); + } + + var parseResults = new Dictionary(); + + foreach (var pair in successfulPreconditions) + { + var parseResult = await pair.Key.ParseAsync(context, matches, pair.Value, provider).ConfigureAwait(false); + + if (parseResult.Error == CommandError.MultipleMatches) + { + IReadOnlyList argList, paramList; + switch (multiMatchHandling) + { + case MultiMatchHandling.Best: + argList = parseResult.ArgValues.Select(x => x.Values.OrderByDescending(y => y.Score).First()).ToImmutableArray(); + paramList = parseResult.ParamValues.Select(x => x.Values.OrderByDescending(y => y.Score).First()).ToImmutableArray(); + parseResult = ParseResult.FromSuccess(argList, paramList); + break; + } + } + + parseResults[pair.Key] = parseResult; + } + + var weightedParseResults = parseResults + .OrderByDescending(x => CalculateScore(x.Key, x.Value)); + + var successfulParses = weightedParseResults + .Where(x => x.Value.IsSuccess) + .ToArray(); + + if(successfulParses.Length == 0) + { + var bestMatch = parseResults + .FirstOrDefault(x => !x.Value.IsSuccess); + + return (bestMatch.Value, bestMatch.Key); + } + + var chosenOverload = successfulParses[0]; + + return (chosenOverload.Value, chosenOverload.Key); + } + protected virtual void Dispose(bool disposing) { if (!_isDisposed)