public static List <string> GetSimilarFiles(string file_name, string folder, double threshold) { List <string> similar_files = new List <string>(); string file_string; if (File.Exists(file_name)) { file_string = File.ReadAllText(file_name); } else { return(similar_files); } if (Directory.Exists(folder)) { var l = new NormalizedLevenshtein(); foreach (string file in Directory.GetFiles(folder)) { if (file != file_name && (Path.GetExtension(file) == ".html" || Path.GetExtension(file) == ".htm")) { string check_file = File.ReadAllText(file); double similarity = l.Similarity(file_string, check_file); if (similarity > threshold) { similar_files.Add(file); } } } } return(similar_files); }
public static async Task <object> SubmitGuess( [HttpTrigger(AuthorizationLevel.Anonymous, "post")] Guess guess, [Table("clues", "{clueId}", Clue.RowKeyValue)] Clue clue, [Table("guesses")] IAsyncCollector <Guess> guesses, [SignalR(HubName = "trivia")] IAsyncCollector <SignalRMessage> signalRMessages) { var l = new NormalizedLevenshtein(); var similarity = l.Similarity(NormalizeString(clue.Answer), NormalizeString(guess.Value)); await guesses.AddAsync(guess); var result = new { guess.SessionId, ClueId = clue.PartitionKey, Guess = guess.Value, IsCorrect = similarity > 0.75, Similarity = similarity }; await signalRMessages.AddAsync(new SignalRMessage { Target = "newGuess", Arguments = new object[] { new { clueId = result.ClueId, isCorrect = result.IsCorrect } } }); return(result); }
public void TestDistance() { var instance = new NormalizedLevenshtein(); NullEmptyTests.TestDistance(instance); // TODO: regular (non-null/empty) distance tests }
public void TestSimilarity() { var instance = new NormalizedLevenshtein(); NullEmptyTests.TestSimilarity(instance); // TODO: regular (non-null/empty) similarity tests }
public static bool IsCommandSimilar(Command command, string notFoundCommand, NormalizedLevenshtein normalizedLevenshtein, double goodDistance = 0.33) { return(normalizedLevenshtein.Distance(command.Name, notFoundCommand) <= goodDistance || command?.Aliases?.Any(x => normalizedLevenshtein.Distance(x, notFoundCommand) <= goodDistance) == true || normalizedLevenshtein.Distance(command.QualifiedName, notFoundCommand) <= goodDistance); }
public static async Task CommandCorrector(string input, string command, string user = null, bool shouldBeExact = false) { // def variables IDictionary <Command, double> MatchRate = new Dictionary <Command, double>(); var Match = new NormalizedLevenshtein(); // filling array with matching rate for (int i = 0; i < Commands.List.Count; i++) { MatchRate.Add(Commands.List[i], Match.Distance(command, Commands.List[i].Key)); } //is there some rate lower than 35% if (!MatchRate.Any(q => q.Value <= 0.51d)) { await Respond("@" + input.ToLower().Split("!")[0].Replace(":", "") + " , Não entendi o seu comando, tente !Exclamação para obter a lista de todos os comandos..."); return; } else { //get the minimum match rate (closest command) var minimum = MatchRate.Min(q => q.Value); var arrayMinimum = MatchRate.Where(q => q.Value == minimum); if (arrayMinimum.Count() == 1) { if (shouldBeExact) { await Respond("@" + user + " , O comando " + command + " está incorreto; " + arrayMinimum.ElementAt(0).Key.Description); } else { var Tinput = input.ToLower().Split(command)[1]; var Tuser = input.ToLower().Split("!")[0].Replace(":", ""); await Respond("@" + Tuser + " , Seu commando foi corrigido para " + arrayMinimum.ElementAt(0).Key.Key + ", tente !Exclamação para obter a lista de todos os comandos..."); arrayMinimum.ElementAt(0).Key.Action.Invoke(Tinput, Tuser); } } else { string text = "@" + input.ToLower().Split("!")[0].Replace(":", "") + " , Não entendi o seu comando, não seria "; foreach (var item in arrayMinimum) { text += item.Key.Key + " ou "; } text += "tente !Exclamação para ver todos os comandos..."; await Respond(text); } } }
public void HouseAnalysis(CallsInfo[] calls) { _logger.LogInformation("Анализ наличия номера дома"); var l = new NormalizedLevenshtein(); foreach (var call in calls) { if (call.Text == null) { continue; } var words = call.Text.Split(' '); foreach (var announcement in call.Announcements) { if (announcement.House == default) { continue; } double max_similarity = default; string best_word = default; foreach (var word in words) { var similarity = l.Similarity(word.ToLower(), announcement.House.ToLower()); if (similarity >= max_similarity) { best_word = word; max_similarity = similarity; } } //if (max_similarity == 1) { announcement.Features.Add(new FeatureInfo { Name = FeatureInfo.HOUSE, Weight = max_similarity, Data = best_word ?? "" }); } } } _logger.LogInformation("Закончили"); }
public async Task <string> Update() { var l = new NormalizedLevenshtein(); var staticVendors = _tmdb.PacingVendor.ToList().Select(i => i.Vendor).OrderBy(o => o).ToList(); var sDate = DateTime.Now.AddDays(-7); var eDate = DateTime.Now; var advVendors = (await Client.LoadMediaOrdersAsync(ServerName, DatabaseName, 0, UserName, Password, "A", sDate, sDate.Month, sDate.Year, eDate, eDate.Month, eDate.Year, true, false, false, false, false, false, "")).Select(i => i.VendorName).Distinct(); var res = advVendors.Where(s => !staticVendors.Any(e => { var ts = s.Replace(".com", "").Split("/")[0].ToLower(); var te = e.Replace(".com", "").Split("/")[0].ToLower(); return(l.Distance(ts, te) < 0.2 || ts.Contains(te) || te.Contains(ts)); })).OrderBy(o => o).ToList(); return("Span: Week\n" + string.Join('\n', res)); }
public void NormalizedLevenshteinAnalysis(CallsInfo[] calls) { _logger.LogInformation("Анализ похожих методом NormalizedLevenshtein"); var l = new NormalizedLevenshtein(); foreach (var call in calls) { if (call.Text == null) { continue; } var words = call.Text.Split(' '); foreach (var announcement in call.Announcements) { if (announcement.Street == default) { continue; } double max_similarity = default; string best_word = default; foreach (var word in words) { var similarity = l.Similarity(word.ToLower(), announcement.Street.ToLower()); if (similarity >= max_similarity) { best_word = word; max_similarity = similarity; } } announcement.Features.Add(new FeatureInfo { Name = FeatureInfo.LEVENSTAIN, Weight = max_similarity, Data = best_word ?? "" }); } } _logger.LogInformation("Закончили"); }
public async Task ExecuteGroup(CommandContext context, [RemainingText, Description("Название тега для отображения")] string name) { if (string.IsNullOrWhiteSpace(name) || ForbiddenNames.Contains(name.ToLower())) { throw new DiscordUserInputException("Название тега не может быть пустым, полностью состоять из пробелов или быть называться также как и команды.", nameof(name)); } var gId = (long)context.Guild.Id; var tag = await this.Database.Tags.SingleOrDefaultAsync(t => t.Name == name && t.GuildId == gId).ConfigureAwait(false); if (tag == null) { var nL = new NormalizedLevenshtein(); var tags = await this.Database.Tags.Where(t => t.GuildId == gId).OrderBy(t => nL.Distance(t.Name, name)).ToArrayAsync().ConfigureAwait(false); if (tags?.Any() == false) { throw new DiscordUserInputException("Тегов на этом сервере не найдено", nameof(tags)); } string suggestions = (tags.Length >= 10 ? string.Join(", ", tags.Take(10).OrderBy(x => x.Name).Select(xt => Formatter.InlineCode(xt.Name)).Distinct()) : string.Join(", ", tags.OrderBy(x => x.Name).Select(xt => Formatter.InlineCode(xt.Name)).Distinct())); await context.RespondAsync($"Нужного тега не найдено, вот некоторые {Formatter.Italic("возможные варианты того что вы искали")}:\n\u200b{suggestions}").ConfigureAwait(false); } else { string content = tag.TagContent.Replace("@here", "@\u200bhere").Replace("@everyone", "@\u200beveryone").Trim(); await context.RespondAsync($"\u200b{content}").ConfigureAwait(false); tag.TimesUsed++; this.Database.Tags.Update(tag); int rowsAffected = await this.Database.SaveChangesAsync(); if (rowsAffected <= 0) { throw new DatabaseException("Не удалось обновить количество использований в базе данных", DatabaseActionType.Save); } } }
public async Task Check() { string userText = Stopwords.RemoveStopwords(AnsweredText); string ansText = Stopwords.RemoveStopwords(Question.Answer); var l = new NormalizedLevenshtein(); var similarity = 1 - l.Distance(userText, ansText); if (similarity >= 0.8) { UpdateBuzzCorrect(); } else { UpdateBuzzIncorrect(); } await UpdateAnswered(); }
///// <summary> ///// Calcualtes the Levenshtein distance between two strings ///// </summary> ///// Source: https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C.23 ///// Explanation: https://en.wikipedia.org/wiki/Levenshtein_distance //private Int32 levenshtein(String a, String b) //{ // if (string.IsNullOrEmpty(a)) // { // if (!string.IsNullOrEmpty(b)) // { // return b.Length; // } // return 0; // } // if (string.IsNullOrEmpty(b)) // { // if (!string.IsNullOrEmpty(a)) // { // return a.Length; // } // return 0; // } // Int32 cost; // Int32[,] d = new int[a.Length + 1, b.Length + 1]; // Int32 min1; // Int32 min2; // Int32 min3; // for (Int32 i = 0; i <= d.GetUpperBound(0); i += 1) // { // d[i, 0] = i; // } // for (Int32 i = 0; i <= d.GetUpperBound(1); i += 1) // { // d[0, i] = i; // } // for (Int32 i = 1; i <= d.GetUpperBound(0); i += 1) // { // for (Int32 j = 1; j <= d.GetUpperBound(1); j += 1) // { // cost = Convert.ToInt32(!(a[i - 1] == b[j - 1])); // min1 = d[i - 1, j] + 1; // min2 = d[i, j - 1] + 1; // min3 = d[i - 1, j - 1] + cost; // d[i, j] = Math.Min(Math.Min(min1, min2), min3); // } // } // return d[d.GetUpperBound(0), d.GetUpperBound(1)]; //} ///// <summary> ///// String-similarity computed with levenshtein-distance ///// </summary> //private double similarityLevenshtein(string a, string b) //{ // if (a.Equals(b)) // { // return 1.0; // } // else // { // if (!(a.Length == 0 || b.Length == 0)) // { // double sim = 1 - (levenshtein(a, b) / Convert.ToDouble(Math.Min(a.Length, b.Length))); // return sim; // } // else // return 0.0; // } //} ///// <summary> ///// String-similarity computed with Dice Coefficient ///// </summary> ///// Source: https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Dice%27s_coefficient#C.23 ///// Explanation: https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient //private double similarityDiceCoefficient(string a, string b) //{ // //Workaround for |a| == |b| == 1 // if (a.Length <= 1 && b.Length <= 1) // { // if (a.Equals(b)) // return 1.0; // else // return 0.0; // } // HashSet<string> setA = new HashSet<string>(); // HashSet<string> setB = new HashSet<string>(); // for (int i = 0; i < a.Length - 1; ++i) // setA.Add(a.Substring(i, 2)); // for (int i = 0; i < b.Length - 1; ++i) // setB.Add(b.Substring(i, 2)); // HashSet<string> intersection = new HashSet<string>(setA); // intersection.IntersectWith(setB); // return (2.0 * intersection.Count) / (setA.Count + setB.Count); //} /// <summary> /// Combines multiple String-similarities with equal weight /// </summary> private double similarity(string a, string b) { List <double> similarities = new List <double>(); double output = 0.0; var l = new NormalizedLevenshtein(); similarities.Add(l.Similarity(a, b)); var jw = new JaroWinkler(); similarities.Add(jw.Similarity(a, b)); var jac = new Jaccard(); similarities.Add(jac.Similarity(a, b)); foreach (double sim in similarities) { output += sim; } return(output / similarities.Count); }
protected async Task <ContentStatus> StartContentBoardMission(string name) { if (!await GoToMainScreen()) { Logger.LogError("Couldn't go to main screen."); } if (!await WaitUntilVisible("MAIN_MENU_ENTER")) { Logger.LogError("Cannot find enter button.. Not on main screen?"); return(null); } await Task.Delay(500); Game.Click("CONTENT_STATUS_BOARD_BUTTON"); if (!await WaitUntilVisible("CONTENT_STATUS_BOARD_MENU_HEADER")) { Logger.LogError("Failed to navigate to content status board"); return(null); } await Task.Delay(500); for (int i = 0; i < 3; i++) { for (var row = 0; row < 5; row++) { for (var col = 0; col < 3; col++) { var nameElement = Repository["CONTENT_STATUS_BOARD_ITEM_NAME_DYN", col, row]; var missionName = Game.GetText(nameElement); missionName = missionName.Contains("\n") ? missionName.Split('\n')[0] : missionName; var nl = new NormalizedLevenshtein(); var similarity = nl.Similarity(name, missionName); if (similarity >= 0.8) // 80% should be fine. names are different enough. { var status = Game.GetText(Repository["CONTENT_STATUS_BOARD_ITEM_STATUS_DYN", col, row]); var isCompleted = missionName.Contains("\n") && nl.Similarity("RESETS IN", missionName.TrimEnd().Split('\n').Last()) > 0.8; //var isCompleted = Game.IsVisible(Repository["CONTENT_STATUS_BOARD_ITEM_NAME_COMPLETED_DYN", col, row]); var statusEntry = new ContentStatus(name, isCompleted, status); Logger.LogDebug($"Clicking on element because it matches expected: {name} actual: {missionName} similarity: {similarity}"); Game.Click(nameElement); await Task.Delay(1000); // waiting briefly for page to change. if (Game.IsVisible(UIds.GENERIC_MISSION_CUSTOM_OFFER_FOR_AGENTS)) { Game.Click(UIds.GENERIC_MISSION_CUSTOM_OFFER_FOR_AGENTS_CLOSE); await Task.Delay(1000); } return(statusEntry); } else { Logger.LogDebug($"Found mission {missionName}. But its not what we are looking for. Similarity {similarity}"); } } } Game.Drag("CONTENT_STATUS_BOARD_DRAG_START", "CONTENT_STATUS_BOARD_DRAG_END"); } return(null); }
public static double Similarity(this string expected, string actual) { var nl = new NormalizedLevenshtein(); return(nl.Similarity(expected, actual)); }
private void MergeIntoDestination() { XmlNodeList nodes; var levenshtein = new NormalizedLevenshtein(); var root = _destDoc.DocumentElement; if (_replace) { nodes = root.SelectNodes("//xliff:trans-unit", _nsmgr); } else { nodes = root.SelectNodes("//xliff:trans-unit[not(xliff:target)]", _nsmgr); } foreach (XmlNode node in nodes) { var id = node.Attributes["id"].Value; if (_translations.ContainsKey(id)) { var source = node.SelectSingleNode("xliff:source", _nsmgr); var transSource = _translations[id].SelectSingleNode($"./xliff:source", _nsmgr); var transTarget = _translations[id].SelectSingleNode($"./xliff:target", _nsmgr); if (source.InnerText != transSource.InnerText) { var percentSimilar = Math.Round((1 - levenshtein.Distance(source.InnerText, transSource.InnerText)) * 100); if (_verbose) { Console.WriteLine($"Sources mismatch in id='{id}' Similarity {percentSimilar}%."); Console.WriteLine($" Source file='{transSource.InnerText}'"); Console.WriteLine($" Target file='{source.InnerText}'"); } if (percentSimilar < _fuzzy) { if (_verbose) { Console.WriteLine($"Skipping"); } continue; } } if (_replace) { var oldTarget = node.SelectSingleNode("xliff:target", _nsmgr); if (oldTarget != null) { node.RemoveChild(oldTarget); } } if (source.NextSibling.Name != "#significant-whitespace") { XmlSignificantWhitespace sigws = _destDoc.CreateSignificantWhitespace("\n "); node.InsertAfter(sigws, source); } XmlNode target = _destDoc.ImportNode(transTarget, true); node.InsertAfter(target, source.NextSibling); if (target.NextSibling.Name != "#significant-whitespace") { XmlSignificantWhitespace sigws = _destDoc.CreateSignificantWhitespace("\n "); node.InsertAfter(sigws, target); } } } }
public async Task PlayNext(CommandContext context, [RemainingText, Description("Название песни")] string songName) { if (string.IsNullOrWhiteSpace(songName)) { throw new DiscordUserInputException("Название песни не должно быть пустым", nameof(songName)); } var songs = new List <Songs>(); lock (this.Bot.UpdateMusicLock) { songs = this.Database.Playlist.ToList(); } var playNexts = new List <PlayNextElement>(); var nL = new NormalizedLevenshtein(); foreach (var song in songs) { playNexts.Add(new PlayNextElement(song.Path, song.Name, nL.Distance(song.Name, songName))); } playNexts = playNexts.OrderBy(s => s.Coefficient).ToList(); var interactivity = context.Client.GetInteractivity(); var description = new StringBuilder(); for (int i = 0; i < 10; i++) { description.AppendLine($"\n№ {i + 1}; Name: {playNexts[i].Title}."); } var listMsg = await context.RespondAsync(embed : EmbedTemplates.ExecutedByEmbed(context.Member, context.Guild.CurrentMember) .WithTitle("Предолагаемый список песен") .WithDescription(description.ToString()) .WithFooter($"Отправьте {Formatter.InlineCode("0")} для отмены")).ConfigureAwait(false); var msg = await interactivity.WaitForMessageAsync(xm => xm.Author.Id == context.User.Id, TimeSpan.FromSeconds(45)); if (!msg.TimedOut) { if (int.TryParse(msg.Result.Content, out int res)) { if (res >= 1 && res <= playNexts.Count) { var pNData = this.GuildMusic.MusicSources[(int)MusicSourceType.PlayNextData] as PlayNextData; pNData.Enqueue(playNexts[res - 1].PathToFile); await listMsg.ModifyAsync(embed : EmbedTemplates.ExecutedByEmbed(context.Member, context.Guild.CurrentMember) .WithTitle($"Следующей песней будет {playNexts[res - 1].Title}").Build()).ConfigureAwait(false); } else if (res == 0) { await listMsg.ModifyAsync("Выбор отменен", null).ConfigureAwait(false); } else { await listMsg.ModifyAsync("Данное число выходит за границы", null).ConfigureAwait(false); } } else { await listMsg.ModifyAsync("Ответ не является числом или время вышло", null).ConfigureAwait(false); } } await Task.Delay(TimeSpan.FromSeconds(30)); await listMsg.DeleteAsync(); }
private async void ButtonValid_Click(object sender, RoutedEventArgs e) { string inputString = myInputTextBox.Text; LImagesMots selectedImage = Images[flipView.SelectedIndex]; string[] lines = inputString.Split('\r'); string voiceString = inputString; double ratingResult = 0.0; foreach (var L in lines) { var l = new NormalizedLevenshtein(); double distance = l.Similarity(L, selectedImage.ImageText); // distance est entre 0 [PERFECT] et 1 if (distance > ratingResult) { ratingResult = distance; } log.Trace("Compare " + L + ", " + selectedImage.ImageText); log.Trace("results =" + l.Similarity(L, selectedImage.ImageText)); if (L == selectedImage.ImageText) { voiceString = L; } } // transformation du result 0..1 en 0..5 (5 est 5 etoile) log.Trace("ratingResults =" + ratingResult + " ---"); log.Trace("5*ratingResult =" + 5 * (ratingResult) + " ---"); ratingResult = 5 * ratingResult; int ratingResultInt = (int)ratingResult; log.Trace(" (int)ratingResult =" + ratingResult + " ---"); string bravoText = ""; switch (ratingResultInt) { case 5: bravoText = " BRAVO !!, "; break; case 4: bravoText = " PRESQUE !!"; break; case 2: case 3: bravoText = " ESSAYE ENCORE !!"; break; case 0: case 1: bravoText = " RECOMMENCE !!"; myInputTextBox.Text = ""; break; default: bravoText = " DEFAULT !!"; break; } Flyout tmpFlyout = Resources["MyFlyout"] as Flyout; MyRating.Value = ratingResultInt; MyResultText.Text = bravoText; voiceString = string.Concat(bravoText + ",", voiceString); myInputTextBox.Focus(FocusState.Programmatic); myInputTextBox.IsTextScaleFactorEnabled = false; await letterPlayer_m.speachAsync(voiceString); tmpFlyout.ShowAt(myInputTextBox); // rend le focus a la text box myInputTextBox.Focus(FocusState.Programmatic); }
private async Task Commands_CommandErrored(CommandErrorEventArgs e) { e.Context.Client.DebugLogger.LogMessage(LogLevel.Error, this.Bot.LogName, $"{e.Context.User.Username} tried executing '{e.Command?.QualifiedName ?? "<unknown command>"}' but it errored: {e.Exception.GetType()}: {e.Exception.Message ?? "<no message>"}", DateTime.Now); var ex = e.Exception; while (ex is AggregateException || ex.InnerException != null) { ex = ex.InnerException; } // Check if exception is result of command prechecks. switch (ex) { case ChecksFailedException exep: { var failedchecks = exep.FailedChecks.First(); switch (failedchecks) { // Bot is lacking permissions. case RequireBotPermissionsAttribute reqbotperm: { string permissionsLacking = reqbotperm.Permissions.ToPermissionString(); var emoji = DiscordEmoji.FromName(e.Context.Client, ":no_entry:"); await e.Context.RespondAsync(embed : EmbedTemplates.CommandErrorEmbed(e.Context.Member, e.Command) .WithTitle($"{emoji} Боту не хватает прав") .WithDescription(permissionsLacking)).ConfigureAwait(false); break; } // User is lacking permissions. case RequireUserPermissionsAttribute requserperm: { string permissionsLacking = requserperm.Permissions.ToPermissionString(); var emoji = DiscordEmoji.FromName(e.Context.Client, ":no_entry:"); await e.Context.RespondAsync(embed : EmbedTemplates.CommandErrorEmbed(e.Context.Member, e.Command) .WithTitle($"{emoji} Вам не хватает прав") .WithDescription(permissionsLacking)).ConfigureAwait(false); break; } // User is not owner of the bot. case RequireOwnerAttribute reqowner: { var emoji = DiscordEmoji.FromName(e.Context.Client, ":no_entry:"); await e.Context.RespondAsync(embed : EmbedTemplates.CommandErrorEmbed(e.Context.Member, e.Command) .WithTitle($"{emoji} Команда доступна только владельцу")).ConfigureAwait(false); break; } // User is not owner or don't have permissions. case OwnerOrPermissionAttribute ownerOrPermission: { string permissionsLacking = ownerOrPermission.Permissions.ToPermissionString(); var emoji = DiscordEmoji.FromName(e.Context.Client, ":no_entry:"); await e.Context.RespondAsync(embed : EmbedTemplates.CommandErrorEmbed(e.Context.Member, e.Command) .WithTitle($"{emoji} Вы не являетесь владельцем или вам не хватает прав") .WithDescription(permissionsLacking)).ConfigureAwait(false); break; } // Command shouldn't be executed so fast. case CooldownAttribute cooldown: { await e.Context.RespondAsync(embed : EmbedTemplates.CommandErrorEmbed(e.Context.Member, e.Command) .WithDescription("Вы пытаетесь использовать команду слишком часто, таймер - " + $"не больше {cooldown.MaxUses} раз в {cooldown.Reset.TotalMinutes} минут")).ConfigureAwait(false); break; } // User wasn't connected to voice channel. Optionally to the same voice channel as bot case RequireVoiceConnectionAttribute requireVoice: { await e.Context.RespondAsync(embed : EmbedTemplates.CommandErrorEmbed(e.Context.Member, e.Command) .WithDescription($"Вы должны быть подключены к {(requireVoice.SameVoiceChannelAsBot ? "тому же голосовому каналу что и бот" : "голосовому каналу")}")).ConfigureAwait(false); break; } default: { await e.Context.RespondAsync(embed : EmbedTemplates.CommandErrorEmbed(e.Context.Member, e.Command) .WithDescription($"Вам не хватает прав, чтобы узнать каких используйте {Formatter.InlineCode($"{this.Bot.Config.Discord.Prefixes.RandomElement()}help {e.Command.QualifiedName}")}")); break; } } break; } case DatabaseException dbEx: { var description = new StringBuilder("Произошла ошибка в работе БД, возможно стоит попробовать чуть позже."); description.AppendLine(string.IsNullOrWhiteSpace(dbEx.Message) ? $"Тип действия: {dbEx.ActionType.ToString()}" : $"Сообщение - {Formatter.InlineCode(dbEx.Message)}. Тип действия: {dbEx.ActionType.ToString()}"); await e.Context.RespondAsync(embed : EmbedTemplates.CommandErrorEmbed(e.Context.Member, e.Command) .WithDescription(description.ToString())).ConfigureAwait(false); break; } case DiscordUserInputException inputEx: { await e.Context.RespondAsync($"{inputEx.Message}. Название параметра {inputEx.ArgumentName}").ConfigureAwait(false); break; } case CommandNotFoundException commandNotFoundException: { var cmdName = commandNotFoundException.CommandName; var suggestedCommands = new List <Command>(); var nL = new NormalizedLevenshtein(); // Let's assumme that 0.33 is good Levenshtein distance foreach (var cmd in this.Commands.RegisteredCommands.Values.Distinct()) { if (cmd is CommandGroup cmdGroup) { foreach (var children in cmdGroup.Children) { if (Helpers.IsCommandSimilar(children, cmdName, nL)) { suggestedCommands.Add(children); } } if (cmdGroup.IsExecutableWithoutSubcommands && Helpers.IsCommandSimilar(cmdGroup, cmdName, nL)) { suggestedCommands.Add(cmdGroup); } } else { if (Helpers.IsCommandSimilar(cmd, cmdName, nL)) { suggestedCommands.Add(cmd); } } } if (suggestedCommands.Any()) { suggestedCommands.OrderBy(x => x.QualifiedName); var description = new StringBuilder(); description.AppendLine($"Команды с названием {Formatter.InlineCode(cmdName)} не найдено. Вот возможные варианты того, что вы имели в виду:"); foreach (var cmd in suggestedCommands) { description.AppendLine(Formatter.InlineCode(cmd.QualifiedName)); } await e.Context.RespondAsync(embed : EmbedTemplates.ErrorEmbed() .WithDescription(description.ToString())).ConfigureAwait(false); } break; } case InvalidOperationException invOpEx when invOpEx.Message == "No matching subcommands were found, and this group is not executable.": { //Ignore. break; } default: { var embed = EmbedTemplates.CommandErrorEmbed(e.Context.Member, e.Command) .WithTitle("Произошла непредвиденная ошибка в работе команды") .WithDescription($"Message: \n{Formatter.InlineCode(ex.Message)}\n в \n{Formatter.InlineCode(ex.Source)}"); await e.Context.RespondAsync(embed : embed).ConfigureAwait(false); await this.Bot.ErrorChannel.SendMessageAsync(embed : embed).ConfigureAwait(false); break; } } }
protected override async Task RunCore(CancellationToken token) { if (!await GoToMainScreen(token)) { Logger.LogError("Could not go to main menu"); return; } if (!await OpenMenu().ConfigureAwait(false)) { Logger.LogError("Could not open main menu"); return; } Game.Click(UIds.MAIN_MENU_CHALLENGES_BUTTON); await Task.Delay(1000, token); if (!await ClickWhenVisible(UIds.CHALLENGES_DAILY_TRIVIA_TAB)) { Game.OnError(new ElementNotFoundError(Repository[UIds.CHALLENGES_DAILY_TRIVIA_TAB])); } await Task.Delay(1000, token); if (!await WaitUntil(() => Game.IsVisible(UIds.CHALLENGES_DAILY_START_BUTTON) || Game.IsVisible(UIds.CHALLENGES_DAILY_TRIVIA_BASIC_REWARD), token)) { Logger.LogInformation("Daily trivia already completed"); return; } if (Game.IsVisible(UIds.CHALLENGES_DAILY_START_BUTTON)) { Game.Click(UIds.CHALLENGES_DAILY_START_BUTTON); } await Task.Delay(2000, token); var questionStatus = Game.GetText(UIds.CHALLENGES_DAILY_TRIVIA_QUESTION_STATUS); if (questionStatus.Contains("/5")) { Logger.LogInformation("Daily Trivia already started"); } else { Logger.LogError("Start button did not appear"); return; } var nl = new NormalizedLevenshtein(); while (Game.IsVisible(UIds.CHALLENGES_DAILY_TRIVIA_BASIC_REWARD) && !token.IsCancellationRequested) { var question = Game.GetText(UIds.CHALLENGES_DAILY_TRIVIA_QUESTION); Logger.LogDebug($"Question is: {question}"); string answer = null; double highestSimilarityQuestion = 0; foreach (var item in _questionsAndAnswers) { var similarity = nl.Similarity(question, item.Question); if (similarity > highestSimilarityQuestion) { highestSimilarityQuestion = similarity; Logger.LogDebug($"Found question that matches better: {item.Question}"); answer = item.Answer; } } Logger.LogDebug($"Expected answer is: {answer}"); double highestSimilarityAnswer = 0; UiElement bestAnswerElement = null; for (int i = 0; i < 4; i++) { var answerId = Repository[UIds.CHALLENGES_DAILY_TRIVIA_ANSWER_DYN, 0, i]; var potentialAnswer = Game.GetText(answerId); var similarity = nl.Similarity(potentialAnswer, answer); Logger.LogDebug($"Found potential answer '{potentialAnswer}' that has a similarity of: {similarity * 100f}%"); if (similarity > highestSimilarityAnswer) { highestSimilarityAnswer = similarity; bestAnswerElement = answerId; } } if (bestAnswerElement == null) { Logger.LogError("Could not find answer for question."); return; } Game.Click(bestAnswerElement); if (!await WaitUntilVisible(UIds.CHALLENGES_DAILY_TRIVIA_CLOSE_BUTTON)) { Logger.LogError($"Close button did not appear. Wrong answer? Q: {question} A: {answer}"); return; } await Task.Delay(500, token); Game.Click(UIds.CHALLENGES_DAILY_TRIVIA_CLOSE_BUTTON); await Task.Delay(2000, token); } Logger.LogInformation("Daily trivia completed"); }