diff --git a/NineChronicles.DataProvider.Tests/WorldBossRankingQueryTest.cs b/NineChronicles.DataProvider.Tests/WorldBossRankingQueryTest.cs index dc587654..9e2b8e93 100644 --- a/NineChronicles.DataProvider.Tests/WorldBossRankingQueryTest.cs +++ b/NineChronicles.DataProvider.Tests/WorldBossRankingQueryTest.cs @@ -117,6 +117,18 @@ public async Task WorldBossRanking_Sort() new PrivateKey().Address, new PrivateKey().Address, new PrivateKey().Address, + new PrivateKey().Address, + new PrivateKey().Address, + new PrivateKey().Address, + }; + var totalScores = new List + { + 100, + 100, + 90, + 90, + 80, + 70, }; var targetAvatarAddress = avatarAddresses[0]; var queryAddress = targetAvatarAddress.ToString(); @@ -130,24 +142,21 @@ public async Task WorldBossRanking_Sort() }} }} }}"; - for (int idx = 0; idx < 2; idx++) + for (int i = 0; i < 6; i++) { - for (int i = 0; i < 3; i++) - { - var avatarAddress = avatarAddresses[i]; - var model = new RaiderModel( - idx + 1, - i.ToString(), - idx, - idx + 1, - i + 2, - GameConfig.DefaultAvatarArmorId, - i, - avatarAddress.ToHex(), - 0 - ); - Context.Raiders.Add(model); - } + var avatarAddress = avatarAddresses[i]; + var model = new RaiderModel( + 1, + i.ToString(), + i + 1, + totalScores[i], + i + 2, + GameConfig.DefaultAvatarArmorId, + i, + avatarAddress.ToHex(), + 0 + ); + Context.Raiders.Add(model); } var block = new BlockModel @@ -169,15 +178,26 @@ public async Task WorldBossRanking_Sort() Context.Blocks.Add(block); await Context.SaveChangesAsync(); + Assert.Equal(6, Context.Raiders.Count()); var result = await ExecuteAsync(query); var data = (Dictionary)((Dictionary)((ExecutionNode)result.Data).ToValue())["worldBossRanking"]; Assert.Equal(1L, data["blockIndex"]); var models = (object[]) data["rankingInfo"]; - Assert.Equal(3, models.Length); - for (int j = 0; j < 3; j++) + // season 1 + Assert.Equal(6, models.Length); + var expectedRanking = new Dictionary() + { + [0] = 2, + [1] = 2, + [2] = 4, + [3] = 4, + [4] = 5, + [5] = 6, + }; + for (int j = 0; j < 6; j++) { var model = (Dictionary)models[j]; - Assert.Equal(3, model["ranking"]); + Assert.Equal(expectedRanking[j], model["ranking"]); Assert.Contains(new Address((string)model["address"]), avatarAddresses); } } diff --git a/NineChronicles.DataProvider/Store/MySqlStore.cs b/NineChronicles.DataProvider/Store/MySqlStore.cs index cf097187..0bc43473 100644 --- a/NineChronicles.DataProvider/Store/MySqlStore.cs +++ b/NineChronicles.DataProvider/Store/MySqlStore.cs @@ -2254,21 +2254,86 @@ public void StoreWorldBossMigration(int raidId) public List GetWorldBossRanking(int raidId, int? queryOffset, int? queryLimit) { using NineChroniclesContext? ctx = _dbContextFactory.CreateDbContext(); + List query = ctx + .Raiders + .Where(i => i.RaidId == raidId) + .OrderByDescending(i => i.TotalScore) + .Select(i => new WorldBossRankingModel + { + Ranking = 0, + AvatarName = i.AvatarName, + HighScore = (int)i.HighScore, + TotalScore = (int)i.TotalScore, + Cp = i.Cp, + Level = i.Level, + Address = i.Address, + IconId = i.IconId, + }) + .ToList(); + int? currentScore = null; + var currentRank = 1; + var trunk = new List(); + var result = new List(); + for (int i = 0; i < query.Count; i++) + { + var model = query[i]; + if (!currentScore.HasValue) + { + currentScore = model.TotalScore; + trunk.Add(model); + continue; + } + + if (currentScore.Value == model.TotalScore) + { + trunk.Add(model); + currentRank++; + if (i < query.Count - 1) + { + continue; + } + + foreach (var modelInTrunk in trunk) + { + modelInTrunk.Ranking = currentRank; + result.Add(modelInTrunk); + } + + trunk.Clear(); + + continue; + } + + foreach (var modelInTrunk in trunk) + { + modelInTrunk.Ranking = currentRank; + result.Add(modelInTrunk); + } + + trunk.Clear(); + if (i < query.Count - 1) + { + trunk.Add(model); + currentScore = model.TotalScore; + currentRank++; + continue; + } + + model.Ranking = currentRank + 1; + result.Add(model); + } - // Call ToList for convert query result from IQueryable - IEnumerable query = ctx.Set() - .FromSqlRaw("SET @prev_score = (SELECT max(`TotalScore`) FROM `Raiders` WHERE `RaidId` = {0}); SET @rank = (SELECT count(*) FROM `Raiders` WHERE `RaidId` = {0} AND `TotalScore` = @prev_score); SELECT `AvatarName`, `HighScore`, `TotalScore`, `Cp`, `Level`, `Address`, `IconId`, @rank := IF(@prev_score = TotalScore, @rank, @rank + 1) as `Ranking` FROM `Raiders` WHERE `RaidId` = {0} ORDER BY `TotalScore` DESC", raidId).ToList(); if (queryOffset.HasValue) { - query = query.Skip(queryOffset.Value); + result = result.Skip(queryOffset.Value).ToList(); } if (queryLimit.HasValue) { - query = query.Take(queryLimit.Value); + result = result.Take(queryLimit.Value).ToList(); } - return query.OrderBy(i => i.Ranking).ToList(); + return result.OrderBy(i => i.Ranking).ToList(); } public int GetTotalRaiders(int raidId)