public MainWindow() { InitializeComponent(); titleLead = $"Slapp - {splatTagController.MatchPlayer(null).Length} Players and {splatTagController.MatchTeam(null).Length} Teams loaded! - "; Title = titleLead; // Initialise the delay timer if we have a UI context, otherwise don't use the timer. context = SynchronizationContext.Current; if (context != null) { smoothSearchDelayTimer = new Timer(TimerExpired); } // If we've loaded from a snapshot, then hide the setup button(s). if (sourcesImporter == null) { otherFunctionsGrid.Visibility = Visibility.Collapsed; } // Re-save if needed // SplatTagControllerFactory.SaveDatabase(splatTagController); // Now we've initialised, hook up the check changed. ignoreCaseCheckbox.Checked += CheckedChanged; ignoreCaseCheckbox.Unchecked += CheckedChanged; nearMatchCheckbox.Checked += CheckedChanged; nearMatchCheckbox.Unchecked += CheckedChanged; regexCheckbox.Checked += CheckedChanged; regexCheckbox.Unchecked += CheckedChanged; // Focus the input text box so we can start typing as soon as the program starts. searchInput.Focus(); }
public void MatchTeamByRegex_InvalidRegex() { UnitTestDatabase database = new UnitTestDatabase(); SplatTagController controller = new SplatTagController(database); controller.Initialise(); Team t1 = CreateTeam("Inkology"); t1.AddClanTag("¡g", Builtins.ManualSource, TagOption.Front); Team t2 = CreateTeam("Inkfected"); t2.AddClanTag("τイ", Builtins.ManualSource, TagOption.Front); database.expectedTeams = new List <Team> { t1, t2 }; controller.LoadDatabase(); Team[] matched = controller.MatchTeam("[", new MatchOptions { IgnoreCase = true, QueryIsRegex = true }); Assert.IsNotNull(matched); Assert.AreEqual(0, matched.Length); }
public void MatchTeamAmbiguous() { UnitTestDatabase database = new UnitTestDatabase(); SplatTagController controller = new SplatTagController(database); Team t1 = CreateTeam("Team 17"); t1.AddClanTag("x", Builtins.ManualSource, TagOption.Front); Team t2 = CreateTeam("Example 18"); t2.AddClanTag("e", Builtins.ManualSource, TagOption.Front); database.expectedTeams = new List <Team> { t1, t2 }; controller.Initialise(); // Match 'e' which will match the 'e' for a tag and 'e' in team Team[] matched = controller.MatchTeam("e"); Assert.IsNotNull(matched); Assert.IsTrue(matched.Length == 2); // Assert that the returned order is t2 then t1. Assert.IsTrue(matched[0] == t2); Assert.IsTrue(matched[1] == t1); }
public void LoadDatabaseTest() { UnitTestDatabase database = new UnitTestDatabase(); SplatTagController controller = new SplatTagController(database); controller.Initialise(); Assert.IsTrue(database.loadCalled); database.loadCalled = false; Team exampleTeam = new Team("Example Team", Builtins.ManualSource); exampleTeam.AddClanTag("e.g", Builtins.ManualSource, TagOption.Front); exampleTeam.AddDivision(new Division(1, DivType.DSB), Builtins.ManualSource); var TEAM_ID = exampleTeam.Id; database.expectedTeams = new List <Team> { exampleTeam }; var PLAYER_NAME = "Example Name"; database.expectedPlayers = new List <Player> { new Player(PLAYER_NAME, new Guid[] { TEAM_ID }, Builtins.ManualSource) }; var PLAYER_ID = database.expectedPlayers[0].Id; controller.LoadDatabase(); Assert.IsTrue(database.loadCalled); // Also check the player and team is now in the controller var players = controller.MatchPlayer(PLAYER_ID.ToString(), new MatchOptions { FilterOptions = FilterOptions.SlappId }); Assert.IsNotNull(players.FirstOrDefault()); var player = players[0]; Assert.IsTrue(player.Name.Value == PLAYER_NAME); var teams = controller.MatchTeam(TEAM_ID.ToString(), new MatchOptions { FilterOptions = FilterOptions.SlappId }); Assert.IsNotNull(teams.FirstOrDefault()); var team = teams[0]; Assert.IsTrue(team.CurrentDiv.Value == 1); Assert.IsTrue(team.CurrentDiv.DivType == DivType.DSB); // Verify getting the players for that team returns our player var playersForExampleTeam = controller.GetPlayersForTeam(exampleTeam); Assert.IsNotNull(playersForExampleTeam); Assert.IsTrue(playersForExampleTeam.Count == 1); Assert.IsTrue(playersForExampleTeam[0].player.Equals(player)); }
public void MatchTeamNoMatchTest() { UnitTestDatabase database = new UnitTestDatabase(); SplatTagController controller = new SplatTagController(database); controller.Initialise(); Team[] matched = controller.MatchTeam("WO"); Assert.IsNotNull(matched); Assert.IsTrue(matched.Length == 0); }
public void MatchTeamByNameTest() { UnitTestDatabase database = new UnitTestDatabase(); SplatTagController controller = new SplatTagController(database); controller.Initialise(); Team t = CreateTeam("Team 17"); // Purposefully mixed case t.AddClanTag("WO", Builtins.ManualSource, TagOption.Front); // Purposefully upper-case database.expectedTeams = new List <Team> { t }; controller.LoadDatabase(); Team[] matched = controller.MatchTeam("team"); // Purposefully mixed case Assert.IsNotNull(matched); Assert.IsTrue(matched.Length == 1); }
public void MatchTeamByTagTest_NearMatched() { UnitTestDatabase database = new UnitTestDatabase(); SplatTagController controller = new SplatTagController(database); controller.Initialise(); Team t = CreateTeam("Inkology"); t.AddClanTag("¡g", Builtins.ManualSource, TagOption.Front); database.expectedTeams = new List <Team> { t }; controller.LoadDatabase(); Team[] matched = controller.MatchTeam("ig"); // Note i != ¡ Assert.IsNotNull(matched); Assert.IsTrue(matched.Length == 1); }
public override IList <Response> Execute(SenderSettings senderDetail, IMessageDetail args) { // Responds asynchronously. Task.Run(async() => { var now = DateTime.UtcNow; ServerSettings serverSettings = senderDetail.ServerSettings; CommandMessageHelper command = new CommandMessageHelper(serverSettings.CommandSymbol, args.Message); string query = command.CommandDetail; Player[] matchedPlayers; Team[] matchedTeams; string title; // Call the Slapp if (string.IsNullOrWhiteSpace(query)) { matchedPlayers = new Player[0]; matchedTeams = new Team[0]; title = "Nothing to search!"; } else { Task.WaitAll(initialiseTask); matchedPlayers = splatTagController.MatchPlayer(query); matchedTeams = splatTagController.MatchTeam(query); title = $"Found {matchedPlayers.Length} player{((matchedPlayers.Length == 1) ? "" : "s")} and {matchedTeams.Length} team{((matchedTeams.Length == 1) ? "" : "s")}! "; } bool hasMatchedPlayers = matchedPlayers.Length != 0; bool hasMatchedTeams = matchedTeams.Length != 0; bool showLimitedMessage = matchedPlayers.Length > 9 || matchedTeams.Length > 9; Color color = (hasMatchedPlayers && hasMatchedTeams) ? Color.Green : (hasMatchedPlayers && !hasMatchedTeams) ? Color.Blue : (!hasMatchedPlayers && hasMatchedTeams) ? Color.Gold : (!hasMatchedPlayers && !hasMatchedTeams) ? Color.Red : Color.DarkRed; var builder = new EmbedBuilder() .WithColor(color) .WithAuthor(author => author.WithName(title)); if (hasMatchedPlayers) { for (int i = 0; i < matchedPlayers.Length && i < 9; i++) { var p = matchedPlayers[i]; var teams = p.Teams.Select(id => splatTagController.GetTeamById(id)); string oldTeams = teams.GetOldTeamsStrings(); var currentTeam = teams.FirstOrDefault(); string info = $"Plays for {currentTeam} {oldTeams}\n _{string.Join(", ", p.Sources)}_"; var playerField = new EmbedFieldBuilder() .WithIsInline(false) .WithName(p.Name.Truncate(1000, "")) .WithValue(info.Truncate(1000, "…_")); builder.AddField(playerField); } } if (hasMatchedTeams) { for (int i = 0; i < matchedTeams.Length && i < 9; i++) { var t = matchedTeams[i]; string[] players = t.GetTeamPlayersStrings(splatTagController); string divPhrase = t.GetBestTeamPlayerDivString(splatTagController); string info = $"{t.Div}. {divPhrase} Players: {string.Join(matchedTeams.Length == 1 ? ",\n" : ", ", players)}\n _{string.Join(", ", t.Sources)}_"; var teamField = new EmbedFieldBuilder() .WithIsInline(false) .WithName($"{t.Tag} {t.Name}".Truncate(1000, "")) .WithValue(info.Truncate(1000, "…_")); builder.AddField(teamField); } } builder.WithFooter($"Fetched in {Math.Floor((DateTime.UtcNow - now).TotalMilliseconds)} milliseconds. {(showLimitedMessage ? "Only the first 9 results are shown for players and teams." : "")}", "https://media.discordapp.net/attachments/471361750986522647/758104388824072253/icon.png"); Response asyncResponse = new Response { Embed = builder, ResponseType = ResponseType.Default, Message = "" }; await asyncResponder.SendResponseAsync(args, asyncResponse).ConfigureAwait(false); }); // Return out the lifecycle with no response. if (!initialiseTask.IsCompleted) { // Also react with a Sloth if the database hasn't loaded yet. return(new[] { Response.WaitForAsync, Response.CreateFromReact(Emojis.SlothUnicode) }); } else { return(new[] { Response.WaitForAsync }); } }
private void Search(string query, bool toast = false) { int playersFound = 0; int teamsFound = 0; if (query.Length > 0) { { IEnumerable <Player> players = splatTagController.MatchPlayer(query, new MatchOptions { IgnoreCase = /* ignoreCaseCheckbox.IsChecked == true, */ true, NearCharacterRecognition = /* nearMatchCheckbox.IsChecked == true, */ true, QueryIsRegex = /* regexCheckbox.IsChecked == true */ false } ); playersFound = players.Count(); if (playersFound != 0) { StringBuilder playerStrings = new StringBuilder(); foreach (var p in players) { // Use URLEncoder to unmangle any special characters string currentTeam = splatTagController.GetTeamById(p.CurrentTeam).ToString(); string oldTeams = string.Join(", ", p.OldTeams.Select(t => splatTagController.GetTeamById(t))); playerStrings .Append(p.Name.Value) .Append(" (Plays for ") .Append(currentTeam) .Append(") Old Teams: ") .Append(oldTeams) .Append("\n\n"); } playersResults.Text = playerStrings.ToString(); } } { IEnumerable <Team> teams = splatTagController.MatchTeam(query, new MatchOptions { IgnoreCase = /* ignoreCaseCheckbox.IsChecked == true, */ true, NearCharacterRecognition = /* nearMatchCheckbox.IsChecked == true, */ true, QueryIsRegex = /* regexCheckbox.IsChecked == true */ false } ); teamsFound = teams.Count(); if (teamsFound != 0) { StringBuilder teamStrings = new StringBuilder(); foreach (var t in teams) { string div = t.CurrentDiv.Name; string bestPlayer = t.GetBestTeamPlayerDivString(splatTagController); string[] teamPlayers = t.GetTeamPlayersStrings(splatTagController); teamStrings .Append(t.Tag?.Value ?? "") .Append(" ") .Append(t.Name.Value) .Append(" (") .Append(div) .Append("). ") .Append(bestPlayer) .Append("\nPlayers:\n") .Append(string.Join(", ", teamPlayers)) ; } teamsResults.Text = teamStrings.ToString(); } } } if (teamsFound == 0) { teamsResults.LayoutParameters = new LinearLayout.LayoutParams(0, Android.Views.ViewGroup.LayoutParams.MatchParent, 0.0f); } else { if (playersFound == 0) { teamsResults.LayoutParameters = new LinearLayout.LayoutParams(0, Android.Views.ViewGroup.LayoutParams.MatchParent, 2.0f); } else { teamsResults.LayoutParameters = new LinearLayout.LayoutParams(0, Android.Views.ViewGroup.LayoutParams.MatchParent, 1.0f); } } if (playersFound == 0) { if (teamsFound == 0) { playersResults.Text = query.Length > 0 ? "No results!" : "Nothing to search!"; playersResults.LayoutParameters = new LinearLayout.LayoutParams(0, Android.Views.ViewGroup.LayoutParams.MatchParent, 2.0f); } else { playersResults.LayoutParameters = new LinearLayout.LayoutParams(0, Android.Views.ViewGroup.LayoutParams.MatchParent, 0.0f); } } else { if (teamsFound == 0) { playersResults.LayoutParameters = new LinearLayout.LayoutParams(0, Android.Views.ViewGroup.LayoutParams.MatchParent, 2.0f); } else { playersResults.LayoutParameters = new LinearLayout.LayoutParams(0, Android.Views.ViewGroup.LayoutParams.MatchParent, 1.0f); } } if (toast) { Toast.MakeText(this, $"{playersFound} players found\n{teamsFound} teams found", ToastLength.Long).Show(); } }
private static void HandleCommandLineQuery( string?b64, string?query, string?slappId, bool exactCase, bool exactCharacterRecognition, string?rebuild, string?patch, bool keepOpen, int limit, bool verbose, bool queryIsRegex, bool queryIsClanTag, bool queryIsTeam, bool queryIsPlayer) { try { var options = new MatchOptions { IgnoreCase = !exactCase, NearCharacterRecognition = !exactCharacterRecognition, QueryIsRegex = queryIsRegex, Limit = limit }; if (queryIsPlayer) { options.FilterOptions = FilterOptions.Player; } else if (queryIsTeam) { options.FilterOptions = FilterOptions.Team; } else if (queryIsClanTag) { options.FilterOptions = FilterOptions.ClanTag; } else { options.FilterOptions = FilterOptions.Default; } CommandLineResult result = new CommandLineResult { Message = "OK", Options = options }; string?[] inputs = new string?[] { b64, query, slappId }; SplatTagController.Verbose = verbose; if (rebuild != null) { if (rebuild.Equals(string.Empty)) { SplatTagControllerFactory.GenerateNewDatabase(); result.Message = "Database rebuilt from default sources!"; } else if (File.Exists(rebuild)) { string?saveFolder = Directory.GetParent(rebuild)?.FullName; string sourcesFile = Path.GetFileName(rebuild); SplatTagControllerFactory.GenerateNewDatabase(saveFolder: saveFolder, sourcesFile: sourcesFile); result.Message = $"Database rebuilt from {rebuild}!"; } else { result.Message = $"Rebuild specified but the sources file specified `{rebuild}` from `{Directory.GetCurrentDirectory()}` does not exist. Aborting."; } } else if (patch != null) { if (patch.Equals(string.Empty)) { result.Message = "Patch specified but no patch sources file specified. Aborting."; } else if (File.Exists(patch)) { SplatTagControllerFactory.GenerateDatabasePatch(patchFile: patch); result.Message = $"Database patched from {patch}!"; } else { result.Message = $"Patch specified but the sources file specified `{patch}` from `{Directory.GetCurrentDirectory()}` does not exist. Aborting."; } } else if (inputs.All(s => string.IsNullOrEmpty(s))) { if (keepOpen) { // First run to open result.Message = $"Connection established. {splatTagController.MatchPlayer(null).Length} players and {splatTagController.MatchTeam(null).Length} teams loaded."; } else { result.Message = "Nothing to search!"; } } else { try { if (new[] { b64, query, slappId }.Count(s => !string.IsNullOrEmpty(s)) > 1) { result.Message = "Warning: Multiple inputs defined. YMMV."; } if (!string.IsNullOrEmpty(b64)) { result.Query = query = Encoding.UTF8.GetString(Convert.FromBase64String(b64)); } if (!string.IsNullOrEmpty(slappId)) { result.Query = slappId; options.FilterOptions = FilterOptions.SlappId; result.Players = splatTagController.MatchPlayer(slappId, options); result.Teams = splatTagController.MatchTeam(slappId, options); } else { Console.WriteLine($"Building result for query={query}"); result.Query = query ?? string.Empty; result.Players = splatTagController.MatchPlayer(query, options); result.Teams = splatTagController.MatchTeam(query, options); } if (result.Players.Length > 0 || result.Teams.Length > 0) { result.AdditionalTeams = result.Players .SelectMany(p => p.TeamInformation.GetAllTeamsUnordered().Select(id => splatTagController.GetTeamById(id))) .Distinct() .ToDictionary(t => t.Id, t => t); result.AdditionalTeams[Team.NoTeam.Id] = Team.NoTeam; result.AdditionalTeams[Team.UnlinkedTeam.Id] = Team.UnlinkedTeam; result.PlayersForTeams = result.Teams .ToDictionary(t => t.Id, t => splatTagController.GetPlayersForTeam(t).ToArray()); foreach (var pair in result.PlayersForTeams) { foreach ((Player, bool)tuple in pair.Value) { foreach (Guid t in tuple.Item1.TeamInformation.GetAllTeamsUnordered()) { result.AdditionalTeams.TryAdd(t, splatTagController.GetTeamById(t)); } } } var sources = new HashSet <string>(); foreach (var s in result.Players.SelectMany(p => p.Sources)) { sources.Add(s.Name); } foreach (var s in result.Teams.SelectMany(t => t.Sources)) { sources.Add(s.Name); } foreach (var s in result.AdditionalTeams.Values.SelectMany(t => t.Sources)) { sources.Add(s.Name); } foreach (var s in result.PlayersForTeams.Values.SelectMany(tupleArray => tupleArray.SelectMany(p => p.Item1.Sources))) { sources.Add(s.Name); } sources.Add(Builtins.BuiltinSource.Name); sources.Add(Builtins.ManualSource.Name); result.Sources = sources.ToArray(); try { result.PlacementsForPlayers = new Dictionary <Guid, Dictionary <string, Bracket[]> >(); foreach (var player in result.Players) { result.PlacementsForPlayers[player.Id] = new Dictionary <string, Bracket[]>(); foreach (var source in player.Sources) { result.PlacementsForPlayers[player.Id][source.Name] = source.Brackets; } } } catch (OutOfMemoryException oom) { const string message = "ERROR: OutOfMemoryException on PlacementsForPlayers. Will continue anyway."; Console.WriteLine(message); Console.WriteLine(oom.ToString()); result.PlacementsForPlayers = new Dictionary <Guid, Dictionary <string, Bracket[]> >(); } } } catch (Exception ex) { string message = $"ERROR: {ex.GetType().Name} while compiling data for serialization..."; Console.WriteLine(message); Console.WriteLine(ex.ToString()); string q = result.Query; result = new CommandLineResult { Query = q, Options = options, Message = message, }; } } string messageToSend; try { StringWriter sw = new StringWriter(); serializer.Serialize(sw, result); messageToSend = sw.ToString(); } catch (Exception ex) { string message = $"ERROR: {ex.GetType().Name} while serializing result..."; Console.WriteLine(message); Console.WriteLine(ex.ToString()); string q = result.Query; result = new CommandLineResult { Query = q, Options = options, Message = message }; // Attempt to send the message as a different serialized error StringWriter sw = new StringWriter(); serializer.Serialize(sw, result); messageToSend = sw.ToString(); } // Send back as a b64 string Console.WriteLine(Convert.ToBase64String(Encoding.UTF8.GetBytes(messageToSend))); } catch (Exception ex) { Console.WriteLine($"ERROR: Outer Exception handler, caught a {ex.GetType().Name}..."); Console.WriteLine(ex.ToString()); } finally { errorMessagesReported.Clear(); } }
public static SplatTagJsonSnapshotDatabase SaveDatabase(SplatTagController splatTagController, string?saveFolder = null) { if (saveFolder == null) { saveFolder = GetDefaultPath(); } return(new SplatTagJsonSnapshotDatabase(saveFolder).Save(splatTagController.MatchPlayer(null), splatTagController.MatchTeam(null), splatTagController.GetSources())); }
public static void SaveDatabase(SplatTagController splatTagController, SplatTagJsonSnapshotDatabase snapshotDatabase) { snapshotDatabase.Save(splatTagController.MatchPlayer(null), splatTagController.MatchTeam(null), splatTagController.GetSources()); }