public async Task UpdateTeamScoresAsync(bool win, HashSet <ulong> userIds) { var competition = Service.GetOrCreateCompetition(Context.Guild.Id); var updates = new List <(Player, int, Rank, RankChangeState, Rank)>(); var embed = new EmbedBuilder { Title = (win ? "Win" : "Lose") + $" Manual Game: #{competition.ManualGameCounter + 1}", Color = win ? Color.Green : Color.Red, }; var sb = new StringBuilder(); foreach (var userId in userIds) { var player = Service.GetPlayer(Context.Guild.Id, userId); if (player == null) { continue; } //This represents the current user's rank var maxRank = competition.MaxRank(player.Points); int updateVal; RankChangeState state = RankChangeState.None; Rank newRank = null; if (win) { updateVal = maxRank?.WinModifier ?? competition.DefaultWinModifier; player.SetPoints(competition, player.Points + updateVal); player.Wins++; newRank = competition.MaxRank(player.Points); if (newRank != null) { if (maxRank == null) { state = RankChangeState.RankUp; } else if (newRank.RoleId != maxRank.RoleId) { state = RankChangeState.RankUp; } } } else { //Loss modifier is always positive so subtract it updateVal = maxRank?.LossModifier ?? competition.DefaultLossModifier; player.SetPoints(competition, player.Points - updateVal); player.Losses++; //Set the update value to a negative value for returning purposes. updateVal = -updateVal; if (maxRank != null) { if (player.Points < maxRank.Points) { state = RankChangeState.DeRank; newRank = competition.MaxRank(player.Points); } } } updates.Add((player, updateVal, maxRank, state, newRank)); //TODO: Rank checking? //I forget what this means honestly Service.SavePlayer(player); //Ignore user updates if they aren't found in the server. var gUser = Context.Guild.GetUser(userId); if (gUser == null) { continue; } await Service.UpdateUserAsync(competition, player, gUser); var rankUpdate = ""; if (maxRank != null || newRank != null) { var oldRoleMention = maxRank == null ? "N/A" : MentionUtils.MentionRole(maxRank.RoleId); var newRoleMention = newRank == null ? "N/A" : MentionUtils.MentionRole(newRank.RoleId); rankUpdate = $" Rank: {oldRoleMention} => {newRoleMention}"; } sb.AppendLine($"{gUser.Mention} Points: {player.Points} {(win ? "Added:" : "Removed:")} {updateVal}{rankUpdate}"); } //Update counter and save new competition config competition.ManualGameCounter++; Service.SaveCompetition(competition); //Create new game info var game = new ManualGameResult(competition.ManualGameCounter, Context.Guild.Id); game.Submitter = Context.User.Id; game.GameState = win ? ManualGameResult.ManualGameState.Win : ManualGameResult.ManualGameState.Lose; game.ScoreUpdates = updates.ToDictionary(x => x.Item1.UserId, x => x.Item2); embed.Description = sb.ToString(); Service.SaveManualGame(game); await ReplyAsync(embed); }
public virtual async Task UpdateTeamScoresAsync(bool win, HashSet <ulong> userIds) { using (var db = new Database()) { var competition = db.GetOrCreateCompetition(Context.Guild.Id); var updates = new List <(Player, int, Rank, RankChangeState, Rank)>(); var ranks = db.Ranks.Where(x => x.GuildId == Context.Guild.Id).ToArray(); var embed = new EmbedBuilder { Title = (win ? "Win" : "Lose") + $" Manual Game: #{competition.ManualGameCounter + 1}", Color = win ? Color.Green : Color.Red, }; var sb = new StringBuilder(); foreach (var userId in userIds) { var player = db.Players.Find(Context.Guild.Id, userId); if (player == null) { continue; } //This represents the current user's rank var maxRank = ranks.Where(x => x.Points <= player.Points).OrderByDescending(x => x.Points).FirstOrDefault(); int updateVal; RankChangeState state = RankChangeState.None; Rank newRank = null; if (win) { updateVal = maxRank?.WinModifier ?? competition.DefaultWinModifier; player.Points += updateVal; player.Wins++; newRank = ranks.Where(x => x.Points <= player.Points).OrderByDescending(x => x.Points).FirstOrDefault(); if (newRank != null) { if (maxRank == null) { state = RankChangeState.RankUp; } else if (newRank.RoleId != maxRank.RoleId) { state = RankChangeState.RankUp; } } } else { //Loss modifier is always positive so subtract it updateVal = maxRank?.LossModifier ?? competition.DefaultLossModifier; player.Points -= updateVal; if (!competition.AllowNegativeScore && player.Points < 0) { player.Points = 0; } player.Losses++; //Set the update value to a negative value for returning purposes. updateVal = -Math.Abs(updateVal); if (maxRank != null) { if (player.Points < maxRank.Points) { state = RankChangeState.DeRank; newRank = ranks.Where(x => x.Points <= player.Points).OrderByDescending(x => x.Points).FirstOrDefault(); } } } updates.Add((player, updateVal, maxRank, state, newRank)); db.Update(player); //Ignore user updates if they aren't found in the server. var gUser = Context.Guild.GetUser(userId); if (gUser == null) { continue; } var _ = Task.Run(async() => await UserService.UpdateUserAsync(competition, player, ranks, gUser)); var rankUpdate = ""; if (maxRank != null || newRank != null) { var oldRoleMention = maxRank == null ? "N/A" : MentionUtils.MentionRole(maxRank.RoleId); var newRoleMention = newRank == null ? "N/A" : MentionUtils.MentionRole(newRank.RoleId); rankUpdate = $" Rank: {oldRoleMention} => {newRoleMention}"; } sb.AppendLine($"{gUser.Mention} Points: {player.Points} {(win ? "Added:" : "Removed:")} {updateVal}{rankUpdate}"); } //Update counter and save new competition config //Create new game info var vals = ((IQueryable <ManualGameResult>)db.ManualGameResults).Where(x => x.GuildId == Context.Guild.Id).ToArray(); var count = vals.Length == 0 ? 0 : vals.Max(x => x.GameId); var game = new ManualGameResult { GuildId = Context.Guild.Id, GameId = count + 1 }; competition.ManualGameCounter = game.GameId; db.Update(competition); game.Submitter = Context.User.Id; game.GameState = win ? ManualGameState.Win : ManualGameState.Lose; db.ManualGameResults.Add(game); db.SaveChanges(); game = db.ManualGameResults.Where(x => x.GuildId == Context.Guild.Id).OrderByDescending(x => x.GameId).First(); foreach (var upd in updates) { db.ManualGameScoreUpdates.Add(new ManualGameScoreUpdate { GuildId = Context.Guild.Id, ManualGameId = game.GameId, ModifyAmount = upd.Item2, UserId = upd.Item1.UserId }); } embed.Description = sb.ToString(); db.SaveChanges(); //save scores await ReplyAsync(embed); } }
//returns a list of userIds and the amount of points they received/lost for the win/loss, and if the user lost/gained a rank //UserId, Points added/removed, rank before, rank modify state, rank after /// <summary> /// Retrieves and updates player scores/wins /// </summary> /// <returns> /// A list containing a value tuple with the /// Player object /// Amount of points received/lost /// The player's current rank /// The player's rank change state (rank up, derank, none) /// The players new rank (if changed) /// </returns> public List <(Player, int, Rank, RankChangeState, Rank)> UpdateTeamScoresAsync(Competition competition, Lobby lobby, GameResult game, Rank[] ranks, bool win, HashSet <ulong> userIds, Database db) { var updates = new List <(Player, int, Rank, RankChangeState, Rank)>(); foreach (var userId in userIds) { var player = db.Players.Find(competition.GuildId, userId); if (player == null) { continue; } //This represents the current user's rank var maxRank = ranks.Where(x => x.Points < player.Points).OrderByDescending(x => x.Points).FirstOrDefault(); int updateVal; RankChangeState state = RankChangeState.None; Rank newRank = null; if (win) { updateVal = (int)((maxRank?.WinModifier ?? competition.DefaultWinModifier) * lobby.LobbyMultiplier); if (lobby.HighLimit != null) { if (player.Points > lobby.HighLimit) { updateVal = (int)(updateVal * lobby.ReductionPercent); } } player.Points += updateVal; player.Wins++; newRank = ranks.Where(x => x.Points <= player.Points).OrderByDescending(x => x.Points).FirstOrDefault(); if (newRank != null) { if (maxRank == null) { state = RankChangeState.RankUp; } else if (newRank.RoleId != maxRank.RoleId) { state = RankChangeState.RankUp; } } } else { //Loss modifiers are always positive values that are to be subtracted updateVal = maxRank?.LossModifier ?? competition.DefaultLossModifier; if (lobby.MultiplyLossValue) { updateVal = (int)(updateVal * lobby.LobbyMultiplier); } player.Points -= updateVal; if (!competition.AllowNegativeScore && player.Points < 0) { player.Points = 0; } player.Losses++; //Set the update value to a negative value for returning purposes. updateVal = -Math.Abs(updateVal); if (maxRank != null) { if (player.Points < maxRank.Points) { state = RankChangeState.DeRank; newRank = ranks.Where(x => x.Points <= player.Points).OrderByDescending(x => x.Points).FirstOrDefault(); } } } updates.Add((player, updateVal, maxRank, state, newRank)); var oldUpdate = db.ScoreUpdates.FirstOrDefault(x => x.ChannelId == lobby.ChannelId && x.GameNumber == game.GameId && x.UserId == userId); if (oldUpdate == null) { var update = new ScoreUpdate { GuildId = competition.GuildId, ChannelId = game.LobbyId, UserId = userId, GameNumber = game.GameId, ModifyAmount = updateVal }; db.ScoreUpdates.Add(update); } else { oldUpdate.ModifyAmount = updateVal; db.ScoreUpdates.Update(oldUpdate); } db.Update(player); } db.SaveChanges(); return(updates); }