public static PickPlayerResponse PickSetPlayer(SdlPlayer pick, Set playerMatch) { try { if (playerMatch.DraftPlayers.All(e => e.DiscordId != pick.DiscordId)) { return(new PickPlayerResponse(false, "This player is not available to be drafted.")); } SdlPlayer sdlPick = playerMatch.DraftPlayers.Find(e => e.DiscordId == pick.DiscordId); playerMatch.GetPickingTeam().AddPlayer(sdlPick); playerMatch.DraftPlayers.Remove(sdlPick); PickPlayerResponse pickPlayerResponse = new PickPlayerResponse(true); if (playerMatch.DraftPlayers.Count == 1) { playerMatch.GetPickingTeam().AddPlayer(playerMatch.DraftPlayers.First()); playerMatch.DraftPlayers.Clear(); pickPlayerResponse.LastPlayer = true; } playerMatch.ResetTimeout(); return(pickPlayerResponse); } catch (Exception e) { return(new PickPlayerResponse(false, exception: e)); } }
public static LobbySelectResponse SelectLobbyByNumber(SdlPlayer sdlPlayer, int lobbyNumber) { try { Lobby selectedLobby = Lobbies[lobbyNumber - 1]; if (selectedLobby.IsWithinThreshold(sdlPlayer.PowerLevel)) { return(new LobbySelectResponse(true, result: selectedLobby)); } if ((int)sdlPlayer.Class < (int)selectedLobby.Class) { SdlClass highestPlayerClass = GetClass(selectedLobby.Players.OrderBy(x => x.PowerLevel).First().PowerLevel); int divisor = (int)GetClass(selectedLobby.Players.OrderBy(x => x.PowerLevel).First().PowerLevel) - ((int)sdlPlayer.Class > (int)highestPlayerClass ? (int)highestPlayerClass : (int)sdlPlayer.Class) + 1; return(new LobbySelectResponse(true, $"Please note that in joining this lobby you will gain 1/{divisor} the points for winning.", result: selectedLobby)); } return(new LobbySelectResponse(false, $"You are not eligible to join lobby #{lobbyNumber} " + $"due to it either being outside your class or power level.")); } catch (Exception e) { return(new LobbySelectResponse(false, exception: e)); } }
public static LobbySelectResponse FindLobby(SdlPlayer sdlPlayer) { try { List <Lobby> matchedLobbies = Lobbies.Where(e => !e.IsFull && e.IsWithinThreshold(sdlPlayer.PowerLevel)).ToList(); if (matchedLobbies.Any()) { return(new LobbySelectResponse(true, result: matchedLobbies.OrderBy(e => Math.Abs(e.LobbyPowerLevel - sdlPlayer.PowerLevel)).First())); } if (Lobbies.All(e => e.Players.Any())) { return(new LobbySelectResponse(false, Resources.LobbiesFull)); } return(new LobbySelectResponse(true, result: Lobbies.First(e => !e.Players.Any()))); } catch (Exception e) { return(new LobbySelectResponse(false, exception: e)); } }
public async Task Pick(CommandContext ctx, [RemainingText, Description("Person you want to pick.")] DiscordMember pick) { try { Set playerMatch = Matchmaker.Sets.FirstOrDefault(e => e.GetPickingTeam().IsCaptain(ctx.Message.Author.Id)); Logger.Warn(string.Join(",", Matchmaker.Sets[0].BravoTeam.Players.Select(x => x.Nickname))); if (playerMatch == null || !CommandHelper.SetChannelIds.Contains(ctx.Channel.Id)) { return; } SdlPlayer sdlPlayer = await MySqlClient.RetrieveSdlPlayer(pick.Id); await PickPlayer(playerMatch, sdlPlayer, ctx.Channel); } catch (Exception e) { Logger.Error(e); throw; } }
public static async Task PickPlayer(Set playerMatch, SdlPlayer pick, DiscordChannel context) { PickPlayerResponse pickPlayerResponse = Matchmaker.PickSetPlayer(pick, playerMatch); if (!pickPlayerResponse.Success) { if (!string.IsNullOrWhiteSpace(pickPlayerResponse.Message)) { await context.SendMessageAsync(pickPlayerResponse.Message); } if (pickPlayerResponse.Exception != null) { Logger.Error(pickPlayerResponse.Exception); } return; } await context.SendMessageAsync($"Added {pick.DiscordId.ToUserMention()}."); if (pickPlayerResponse.LastPlayer) { await context.SendMessageAsync("There is only one player left! Drafting them automatically."); await MatchModule.MoveToMatch(context, playerMatch); } else { await context.SendMessageAsync($"{playerMatch.GetPickingTeam().Captain.DiscordId.ToUserMention()} it is your turn to pick.", embed : playerMatch.GetEmbedBuilder().Build()); } }
public static async Task SetRoleAsync(SdlPlayer player, string role, int roleNum) { MySqlCommand updateRoleCommand = new MySqlCommand($"UPDATE Players SET `Role {roleNum}`=@Role WHERE `Discord ID`=@PlayerID", mySqlConnection); updateRoleCommand.Parameters.AddWithValue("@Role", role); updateRoleCommand.Parameters.AddWithValue("@PlayerID", player.DiscordId); await updateRoleCommand.ExecuteNonQueryAsync(); }
public async Task PickFor(CommandContext ctx, int setNumber, DiscordMember pick) { Set playerMatch = Matchmaker.Sets[setNumber - 1]; SdlPlayer sdlPlayer = await MySqlClient.RetrieveSdlPlayer(pick.Id); await PickPlayer(playerMatch, sdlPlayer, ctx.Channel); }
public static async Task SetFriendCodeAsync(SdlPlayer player, string code) { MySqlCommand updateRoleCommand = new MySqlCommand($"UPDATE Players SET `Friend Code`=@Code WHERE `Discord ID`=@PlayerID", mySqlConnection); updateRoleCommand.Parameters.AddWithValue("@Code", code); updateRoleCommand.Parameters.AddWithValue("@PlayerID", player.DiscordId); await updateRoleCommand.ExecuteNonQueryAsync(); }
public static async Task <SdlPlayer[]> RetrieveAllSdlPlayers() { try { List <SdlPlayer> allPlayers = new List <SdlPlayer>(); MySqlCommand retrievePlayerCommand = new MySqlCommand("SELECT * FROM Players", mySqlConnection); using (MySqlDataReader retrievePlayerReader = (MySqlDataReader)await retrievePlayerCommand.ExecuteReaderAsync()) { while (await retrievePlayerReader.ReadAsync()) { SdlPlayer sdlPlayer = new SdlPlayer(Convert.ToUInt64(retrievePlayerReader["Discord ID"])) { Nickname = retrievePlayerReader["Name"].ToString(), PowerLevel = (decimal)retrievePlayerReader["Power"], RoleOne = retrievePlayerReader["Role 1"] == DBNull.Value ? retrievePlayerReader["Role 1"].ToString() : string.Empty, RoleTwo = retrievePlayerReader["Role 2"] == DBNull.Value ? retrievePlayerReader["Role 2"].ToString() : string.Empty }; if (retrievePlayerReader.TryGetValue("Friend Code", out object friendCode)) { sdlPlayer.SwitchFriendCode = friendCode?.ToString(); } if (retrievePlayerReader.TryGetValue("Role 1", out object roleOne)) { sdlPlayer.RoleOne = roleOne?.ToString(); } if (retrievePlayerReader.TryGetValue("Role 2", out object roleTwo)) { sdlPlayer.RoleTwo = roleTwo?.ToString(); } if (retrievePlayerReader.TryGetValue("Active Team", out object activeTeam)) { sdlPlayer.TeamId = Convert.ToUInt64(activeTeam); } // TODO Win Rates. allPlayers.Add(sdlPlayer); } } return(allPlayers.ToArray()); } catch (Exception e) { // TODO Catch the exception better. Logger.Error(e); throw; } }
public static async Task <bool> CheckHasPlayedSet(SdlPlayer player) { string offset = null; string errorMessage = null; List <AirtableRecord> records = new List <AirtableRecord>(); using (AirtableBase airtableBase = new AirtableBase(Globals.BotSettings.AppKey, Globals.BotSettings.BaseId)) { do { Logger.Info($"Retrieving data with offset {offset}."); Task <AirtableListRecordsResponse> task = airtableBase.ListRecords( "Draft Log", offset, null, null, null, null ); AirtableListRecordsResponse response = await task; if (response.Success) { Logger.Info($"Success! Continuing with offset \"{response.Offset}\""); records.AddRange(response.Records.ToList()); offset = response.Offset; } else if (response.AirtableApiError != null) { errorMessage = response.AirtableApiError.ErrorMessage; break; } else { errorMessage = "Unknown error"; break; } } while (offset != null); } if (!string.IsNullOrEmpty(errorMessage)) { SdlAirTableException airTableException = new SdlAirTableException( errorMessage, SdlAirTableException.AirtableErrorType.CommunicationError); Logger.Error(airTableException); throw airTableException; } return(records.Any(x => ((JArray)x.Fields["Alpha Players"]).Any(y => y.Value <string>() == player.AirtableId) || ((JArray)x.Fields["Bravo Players"]).Any(y => y.Value <string>() == player.AirtableId))); }
public static async Task <bool> CheckHasPlayedSet(SdlPlayer player) { MySqlCommand selectCommand = new MySqlCommand( $"SELECT COUNT(*) " + $"FROM `Draft Log` " + $"WHERE `Alpha Players` LIKE '%{player.DiscordId}%' " + $"OR `Bravo Players` LIKE '%{player.DiscordId}%'", mySqlConnection); return(Convert.ToInt32(await selectCommand.ExecuteScalarAsync()) > 0); }
private static async Task ReportPlayerScores(SdlPlayer player, decimal score) { MySqlCommand updateCommand = new MySqlCommand($"UPDATE Players SET `Power`={player.PowerLevel + score} WHERE `Discord ID`=@PlayerID", mySqlConnection); updateCommand.Parameters.AddWithValue("@PlayerID", player.DiscordId); if (await updateCommand.ExecuteNonQueryAsync() > 0) { return; } throw new SdlMySqlException(SdlMySqlException.ExceptionType.ZeroUpdates, "Failed to update player's score in the database; SQL responded with 0 updated rows."); }
public static async Task SetFriendCodeAsync(SdlPlayer player, string code) { using (AirtableBase airtableBase = new AirtableBase(Globals.BotSettings.AppKey, Globals.BotSettings.BaseId)) { Fields fields = new Fields(); fields.AddField("Friend Code", code); AirtableCreateUpdateReplaceRecordResponse response = await airtableBase.UpdateRecord("Draft Standings", fields, player.AirtableId, true); if (!response.Success) { Logger.Error(response.AirtableApiError.ErrorMessage); } } }
public static async Task AddPlayerToTeam(ulong teamId, SdlPlayer player) { if (player.TeamId != default) { throw new SdlMySqlException(SdlMySqlException.ExceptionType.DuplicateEntry, "Failed to add player to a team in the database; This player is already on a team."); } MySqlCommand updateCommand = new MySqlCommand($"UPDATE Players SET `Active Team`={teamId}", mySqlConnection); if (await updateCommand.ExecuteNonQueryAsync() > 0) { return; } throw new SdlMySqlException(SdlMySqlException.ExceptionType.ZeroUpdates, "Failed to add player to a team in the database; SQL responded with 0 updated rows."); }
public static async Task PenalizePlayer(SdlPlayer player, decimal points, string notes) { // Snowflake generator. Generator generator = new Generator(8, new DateTime(2019, 6, 22, new GregorianCalendar(GregorianCalendarTypes.USEnglish))); ulong reportId = generator.NextLong(); MySqlCommand updateCommand = new MySqlCommand($"UPDATE Players SET `Power`={player.PowerLevel - points} WHERE `Discord ID`=@PlayerID", mySqlConnection); updateCommand.Parameters.AddWithValue("@PlayerID", player.DiscordId); if (await updateCommand.ExecuteNonQueryAsync() > 0) { return; } throw new SdlMySqlException(SdlMySqlException.ExceptionType.ZeroUpdates, "Failed to apply the player's penalty to their power level in the database; SQL responded with 0 updated rows."); }
public static async Task <DateTime> GetDateOfLastSet(SdlPlayer player) { List <DateTime> setTimes = new List <DateTime>(); MySqlCommand selectCommand = new MySqlCommand( $"SELECT Date " + $"FROM `Draft Log` " + $"WHERE `Alpha Players` LIKE '%{player.DiscordId}%' " + $"OR `Bravo Players` LIKE '%{player.DiscordId}%'", mySqlConnection); using (MySqlDataReader reader = selectCommand.ExecuteReader()) { while (await reader.ReadAsync()) { setTimes.Add((DateTime)reader["Date"]); } } return(setTimes.OrderByDescending(x => x).FirstOrDefault()); }
public static async Task <SdlPlayer> RetrieveSdlPlayer(ulong discordId) { try { AirtableRecord playerRecord = await GetPlayerRecord(discordId); SdlPlayer sdlPlayer = new SdlPlayer(discordId) { AirtableName = playerRecord.Fields.ContainsKey("Name") ? playerRecord.Fields["Name"].ToString() : string.Empty, PowerLevel = Convert.ToDouble(playerRecord.Fields["Power"].ToString()), SwitchFriendCode = playerRecord.Fields.ContainsKey("Friend Code") ? playerRecord.Fields["Friend Code"].ToString() : string.Empty, AirtableId = playerRecord.Id, Role = playerRecord.Fields.ContainsKey("Role") ? playerRecord.Fields["Role"].ToString() : string.Empty }; try { if (playerRecord.Fields.ContainsKey("W%")) { sdlPlayer.OverallWinRate = Convert.ToDouble(playerRecord.Fields["W%"]); } else { sdlPlayer.OverallWinRate = -1; } } catch (Exception e) { Logger.Warn(e); } try { if (playerRecord.Fields.ContainsKey("SZ W%")) { sdlPlayer.WinRates[GameMode.SplatZones] = Convert.ToDouble(playerRecord.Fields["SZ W%"]); } } catch (Exception e) { Logger.Warn(e); } try { if (playerRecord.Fields.ContainsKey("TC W%")) { sdlPlayer.WinRates[GameMode.TowerControl] = Convert.ToDouble(playerRecord.Fields["TC W%"]); } } catch (Exception e) { Logger.Warn(e); } try { if (playerRecord.Fields.ContainsKey("RM W%")) { sdlPlayer.WinRates[GameMode.Rainmaker] = Convert.ToDouble(playerRecord.Fields["RM W%"]); } } catch (Exception e) { Logger.Warn(e); } try { if (playerRecord.Fields.ContainsKey("CB W%")) { sdlPlayer.WinRates[GameMode.ClamBlitz] = Convert.ToDouble(playerRecord.Fields["CB W%"]); } } catch (Exception e) { Logger.Warn(e); } return(sdlPlayer); } catch (Exception e) { SdlAirTableException caughtAirTableException = new SdlAirTableException( e.Message, SdlAirTableException.AirtableErrorType.Generic); Logger.Error(caughtAirTableException); throw caughtAirTableException; } }
public async Task Notif(CommandContext ctx) { if (!(ctx.User is DiscordMember user)) { return; } if (user.Roles.All(e => e.Name != "Player")) { return; } SdlPlayer player = await MySqlClient.RetrieveSdlPlayer(user.Id); DiscordRole classOneRole = ctx.Guild.GetRole(600770643075661824); DiscordRole classTwoRole = ctx.Guild.GetRole(600770814521901076); DiscordRole classThreeRole = ctx.Guild.GetRole(600770862307606542); DiscordRole classFourRole = ctx.Guild.GetRole(600770905282576406); DiscordRole selectedRole = null; switch (Matchmaker.GetClass(player.PowerLevel)) { case SdlClass.Zero: break; case SdlClass.One: selectedRole = classOneRole; break; case SdlClass.Two: selectedRole = classTwoRole; break; case SdlClass.Three: selectedRole = classThreeRole; break; case SdlClass.Four: selectedRole = classFourRole; break; default: throw new ArgumentOutOfRangeException(); } string optOutDirectory = Directory.CreateDirectory(Path.Combine(Globals.AppPath, "Opt Out")).FullName; if (user.Roles.Any(e => e.Id == selectedRole?.Id)) { await File.WriteAllTextAsync(Path.Combine(optOutDirectory, $"{ctx.User.Id}.dat"), "bruh"); await user.RevokeRoleAsync(selectedRole); await ctx.RespondAsync("Disabled lobby notifications."); } else { if (File.Exists(Path.Combine(optOutDirectory, $"{ctx.User.Id}.dat"))) { File.Delete(Path.Combine(optOutDirectory, $"{ctx.User.Id}.dat")); } await user.RevokeRoleAsync(selectedRole); await ctx.RespondAsync("Enabled lobby notifications."); } }
public async Task DebugPropagate(CommandContext ctx) { SdlPlayer sdlPlayer = await MySqlClient.RetrieveSdlPlayer(ctx.User.Id); await this.JoinLobby(ctx, sdlPlayer, true); }
private async Task JoinLobby(CommandContext ctx, SdlPlayer sdlPlayer, bool debugFill = false, int?lobbyNumber = null) { try { Lobby matchedLobby; if (lobbyNumber != null) { LobbySelectResponse lobbySelectResponse = Matchmaker.SelectLobbyByNumber(sdlPlayer, lobbyNumber.Value); if (!lobbySelectResponse.Success) { if (lobbySelectResponse.Exception != null) { Logger.Error(lobbySelectResponse.Exception); } if (!string.IsNullOrEmpty(lobbySelectResponse.Message)) { await ctx.RespondAsync(lobbySelectResponse.Message); } return; } matchedLobby = lobbySelectResponse.Result; if (!string.IsNullOrEmpty(lobbySelectResponse.Message)) { await ctx.RespondAsync(lobbySelectResponse.Message); } } else { LobbySelectResponse lobbySelectResponse = Matchmaker.FindLobby(sdlPlayer); if (!lobbySelectResponse.Success) { if (lobbySelectResponse.Exception != null) { Logger.Error(lobbySelectResponse.Exception); } if (!string.IsNullOrEmpty(lobbySelectResponse.Message)) { await ctx.RespondAsync(lobbySelectResponse.Message); } return; } if (!string.IsNullOrEmpty(lobbySelectResponse.Message)) { await ctx.RespondAsync(lobbySelectResponse.Message); } matchedLobby = lobbySelectResponse.Result; } matchedLobby.AddPlayer(sdlPlayer); if (debugFill) { foreach (SdlPlayer nextPlayer in (await MySqlClient.RetrieveAllSdlPlayers()).Where(e => e != sdlPlayer).Take(7)) { matchedLobby.AddPlayer(nextPlayer, true); } } if (matchedLobby.IsFull) { MoveToSetResponse moveToSetResponse = Matchmaker.MoveLobbyToSet(matchedLobby); if (!moveToSetResponse.Success) { if (moveToSetResponse.Exception != null) { Logger.Error(moveToSetResponse.Exception); } if (moveToSetResponse.Message != null) { await ctx.RespondAsync(moveToSetResponse.Message, embed : matchedLobby.GetEmbedBuilder().Build()); } return; } if (!string.IsNullOrEmpty(moveToSetResponse.Message)) { await ctx.RespondAsync(moveToSetResponse.Message); } Set newSet = moveToSetResponse.Result; newSet.Closed += this.NewMatch_Closed; DiscordRole setRole = ctx.Guild.Roles.First(e => e.Name == $"In Set ({newSet.SetNumber})"); foreach (SdlPlayer setPlayer in newSet.AllPlayers) { DiscordMember member = await ctx.Guild.GetMemberAsync(setPlayer.DiscordId); await member.GrantRoleAsync(setRole); } DiscordChannel setChannel = await CommandHelper.ChannelFromSet(newSet.SetNumber); await ctx.RespondAsync($"Lobby filled! Please move to {setChannel.Mention}."); await ctx.Guild.UpdateRoleAsync(setRole, mentionable : true); DiscordMessage lastMessage = await setChannel.SendMessageAsync( $"{setRole.Mention} Welcome to set #{newSet.SetNumber}! To begin, " + $"{(await ctx.Guild.GetMemberAsync(newSet.BravoTeam.Captain.DiscordId)).Mention} will have " + $"one minute to pick a player using `%pick [player]`.", embed : newSet.GetEmbedBuilder().Build()); await ctx.Guild.UpdateRoleAsync(setRole, mentionable : false); newSet.DraftTimeout += NewSet_DraftTimeout; newSet.ResetTimeout(); } else { string message = $"{sdlPlayer.DiscordId.ToUserMention()} has been added to " + $"Lobby #{matchedLobby.LobbyNumber}. {8 - matchedLobby.Players.Count} players needed to begin."; DiscordRole classOneRole = ctx.Guild.GetRole(600770643075661824); DiscordRole classTwoRole = ctx.Guild.GetRole(600770814521901076); DiscordRole classThreeRole = ctx.Guild.GetRole(600770862307606542); DiscordRole classFourRole = ctx.Guild.GetRole(600770905282576406); DiscordRole[] notifRoles = { classOneRole, classTwoRole, classThreeRole, classFourRole }; if (matchedLobby.Players.Count == 1) { matchedLobby.DeltaUpdated += MatchedLobby_DeltaUpdated; message = $"{notifRoles[(int)matchedLobby.Class - 1].Mention} " + $"{((int)matchedLobby.Class - 2 > 0 ? notifRoles[(int)matchedLobby.Class - 2].Mention + " " : "")}" + $"A new lobby has been started! {message}"; } DiscordEmbedBuilder builder = matchedLobby.GetEmbedBuilder(); await ctx.RespondAsync(message, false, builder.Build()); } } catch (Exception e) { Console.WriteLine(e); Logger.Error(e); throw; } }
public static async Task <SdlPlayer[]> RetrieveAllSdlPlayers() { AirtableRecord[] records = await GetAllPlayerRecords(); return(records.Select(playerRecord => { SdlPlayer sdlPlayer = new SdlPlayer(Convert.ToUInt64(playerRecord.Fields["DiscordID"])) { AirtableName = playerRecord.Fields.ContainsKey("Name") ? playerRecord.Fields["Name"].ToString() : string.Empty, PowerLevel = Convert.ToDouble(playerRecord.Fields["Power"].ToString()), SwitchFriendCode = playerRecord.Fields.ContainsKey("Friend Code") ? playerRecord.Fields["Friend Code"].ToString() : string.Empty, AirtableId = playerRecord.Id, Role = playerRecord.Fields.ContainsKey("Role") ? playerRecord.Fields["Role"].ToString() : string.Empty }; try { if (playerRecord.Fields.ContainsKey("SZ W%")) { sdlPlayer.WinRates[GameMode.SplatZones] = Convert.ToDouble(playerRecord.Fields["SZ W%"]); } } catch (Exception exception) { // Logger.Warn(exception); } try { if (playerRecord.Fields.ContainsKey("TC W%")) { sdlPlayer.WinRates[GameMode.TowerControl] = Convert.ToDouble(playerRecord.Fields["TC W%"]); } } catch (Exception exception) { // Logger.Warn(exception); } try { if (playerRecord.Fields.ContainsKey("RM W%")) { sdlPlayer.WinRates[GameMode.Rainmaker] = Convert.ToDouble(playerRecord.Fields["RM W%"]); } } catch (Exception exception) { // Logger.Warn(exception); } try { if (playerRecord.Fields.ContainsKey("CB W%")) { sdlPlayer.WinRates[GameMode.ClamBlitz] = Convert.ToDouble(playerRecord.Fields["CB W%"]); } } catch (Exception exception) { // Logger.Warn(exception); } return sdlPlayer; }) .ToArray()); }
public static async Task <(int Placement, string Ordinal)> GetPlayerStandings(SdlPlayer player) { AirtableRecord[] allPlayerRecords = await GetAllPlayerRecords(); List <double> orderedPlayers = allPlayerRecords .Select(e => Convert.ToDouble(e.Fields["Power"].ToString())) .OrderByDescending(e => e) .ToList(); int placement = -1; for (int i = 0; i < orderedPlayers.Count; i++) { if (Math.Abs(orderedPlayers[i] - player.PowerLevel) >= 0.1) { continue; } placement = i + 1; } return(placement, GetOrdinal(placement)); }