diff --git a/NineChronicles.DataProvider.Tests/WorldBossRankingRewardQueryTest.cs b/NineChronicles.DataProvider.Tests/WorldBossRankingRewardQueryTest.cs index 54f7ec9c..26d99433 100644 --- a/NineChronicles.DataProvider.Tests/WorldBossRankingRewardQueryTest.cs +++ b/NineChronicles.DataProvider.Tests/WorldBossRankingRewardQueryTest.cs @@ -128,6 +128,11 @@ public async Task WorldBossRankingReward(int rank, long blockIndex, bool canRece [InlineData(11L, false, 100, 2, 100, 2)] public async Task WorldBossRankingRewards(long blockIndex, bool canReceive, int offset, int limit, int expectedRank, int expectedCount) { + if (canReceive) + { + Context.WorldBossSeasonMigrationModels.Add(new WorldBossSeasonMigrationModel { RaidId = 1 }); + } + for (int i = 0; i < 200; i++) { var avatarAddress = new PrivateKey().ToAddress(); @@ -203,6 +208,8 @@ public async Task WorldBossRankingRewards(long blockIndex, bool canReceive, int [InlineData(2, 198, 199, "15000")] public async Task WorldBossRankingRewards_Rate(int raidId, int offset, int expectedRank, string expectedCrystal) { + Context.WorldBossSeasonMigrationModels.Add(new WorldBossSeasonMigrationModel { RaidId = raidId }); + for (int i = 0; i < 200; i++) { var avatarAddress = new PrivateKey().ToAddress(); diff --git a/NineChronicles.DataProvider/Queries/NineChroniclesSummaryQuery.cs b/NineChronicles.DataProvider/Queries/NineChroniclesSummaryQuery.cs index e95d0d43..42af92f8 100644 --- a/NineChronicles.DataProvider/Queries/NineChroniclesSummaryQuery.cs +++ b/NineChronicles.DataProvider/Queries/NineChroniclesSummaryQuery.cs @@ -288,36 +288,18 @@ public NineChroniclesSummaryQuery(MySqlStore store, StandaloneContext standalone var avatarAddress = context.GetArgument
("avatarAddress"); // Use database block tip because sync db & store delay. + var (sheet, runeSheet, rankingRewardSheet) = GetWorldBossSheets(Store, stateContext, raidId); var blockIndex = Store.GetTip(); - var worldBossListSheetAddress = Addresses.GetSheetAddress(); - var runeSheetAddress = Addresses.GetSheetAddress(); - var rewardSheetAddress = Addresses.GetSheetAddress(); - var values = stateContext.GetStates(new[] { worldBossListSheetAddress, runeSheetAddress, rewardSheetAddress }); - if (values[0] is Text wbs && values[1] is Text rs && values[2] is Text wrs) + var bossRow = sheet.OrderedList!.First(r => r.Id == raidId); + if (bossRow.EndedBlockIndex <= blockIndex) { - var sheet = new WorldBossListSheet(); - sheet.Set(wbs); - var runeSheet = new RuneSheet(); - runeSheet.Set(rs); - var rankingRewardSheet = new WorldBossRankingRewardSheet(); - rankingRewardSheet.Set(wrs); - var bossRow = sheet.OrderedList!.First(r => r.Id == raidId); - if (bossRow.EndedBlockIndex <= blockIndex && Store.MigrationExists(raidId)) - { - // Check ranking. - var raiders = Store.GetWorldBossRanking(raidId, null, null); - var raider = raiders.First(r => r.Address == avatarAddress.ToHex()); - var ranking = raider.Ranking; - - // backward compatibility for season 1. because season 1 reward already distributed. - var rate = raidId == 1 - ? ranking / raiders.Count * 100 - : ranking * 100 / raiders.Count; + // Check ranking. + var raiders = Store.GetWorldBossRanking(raidId, null, null); + var totalCount = raiders.Count; + var raider = raiders.First(r => r.Address == avatarAddress.ToHex()); - // calculate rewards. - var row = FindRow(rankingRewardSheet, bossRow.BossId, ranking, rate); - return (raider, row.GetRewards(runeSheet)); - } + // calculate rewards. + return GetWorldBossRankingReward(raidId, totalCount, raider, rankingRewardSheet, bossRow, runeSheet); } throw new ExecutionError("can't receive"); @@ -351,40 +333,21 @@ public NineChroniclesSummaryQuery(MySqlStore store, StandaloneContext standalone // Check calculate state end. // Use database block tip because sync db & store delay. + var (sheet, runeSheet, rankingRewardSheet) = GetWorldBossSheets(Store, stateContext, raidId); var blockIndex = Store.GetTip(); - var worldBossListSheetAddress = Addresses.GetSheetAddress(); - var runeSheetAddress = Addresses.GetSheetAddress(); - var rewardSheetAddress = Addresses.GetSheetAddress(); - var values = stateContext.GetStates(new[] { worldBossListSheetAddress, runeSheetAddress, rewardSheetAddress }); - if (values[0] is Text wbs && values[1] is Text rs && values[2] is Text wrs) + var bossRow = sheet.OrderedList!.First(r => r.Id == raidId); + if (bossRow.EndedBlockIndex <= blockIndex) { - var sheet = new WorldBossListSheet(); - sheet.Set(wbs); - var runeSheet = new RuneSheet(); - runeSheet.Set(rs); - var rankingRewardSheet = new WorldBossRankingRewardSheet(); - rankingRewardSheet.Set(wrs); - var bossRow = sheet.OrderedList!.First(r => r.Id == raidId); - if (bossRow.EndedBlockIndex <= blockIndex) + // Check ranking. + var raiders = Store.GetWorldBossRanking(raidId, offset, limit); + int totalCount = Store.GetTotalRaiders(raidId); + var result = new List<(WorldBossRankingModel, List)>(); + foreach (var raider in raiders) { - // Check ranking. - var raiders = Store.GetWorldBossRanking(raidId, offset, limit); - int totalCount = Store.GetTotalRaiders(raidId); - var result = new List<(WorldBossRankingModel, List)>(); - foreach (var raider in raiders) - { - var ranking = raider.Ranking; - - // backward compatibility for season 1. because season 1 reward already distributed. - var rate = raidId == 1 - ? ranking / totalCount * 100 - : ranking * 100 / totalCount; - var row = FindRow(rankingRewardSheet, bossRow.BossId, ranking, rate); - result.Add((raider, row.GetRewards(runeSheet))); - } - - return result; + result.Add(GetWorldBossRankingReward(raidId, totalCount, raider, rankingRewardSheet, bossRow, runeSheet)); } + + return result; } throw new ExecutionError("can't receive"); @@ -410,5 +373,45 @@ private static WorldBossRankingRewardSheet.Row FindRow(WorldBossRankingRewardShe return (sheet.OrderedList?.LastOrDefault(r => r.BossId == bossId && r.RankingMin <= ranking && ranking <= r.RankingMax) ?? sheet.OrderedList?.LastOrDefault(r => r.BossId == bossId && r.RateMin <= rate && rate <= r.RateMax))!; } + + private static (WorldBossListSheet, RuneSheet, WorldBossRankingRewardSheet) GetWorldBossSheets(MySqlStore store, StateContext stateContext, int raidId) + { + if (store.MigrationExists(raidId)) + { + var worldBossListSheetAddress = Addresses.GetSheetAddress(); + var runeSheetAddress = Addresses.GetSheetAddress(); + var rewardSheetAddress = Addresses.GetSheetAddress(); + var values = stateContext.GetStates(new[] { worldBossListSheetAddress, runeSheetAddress, rewardSheetAddress }); + if (values[0] is Text wbs && values[1] is Text rs && values[2] is Text wrs) + { + var sheet = new WorldBossListSheet(); + sheet.Set(wbs); + var runeSheet = new RuneSheet(); + runeSheet.Set(rs); + var rankingRewardSheet = new WorldBossRankingRewardSheet(); + rankingRewardSheet.Set(wrs); + return (sheet, runeSheet, rankingRewardSheet); + } + } + + throw new ExecutionError("can't receive"); + } + + private static int GetRankingRate(int raidId, int ranking, int totalCount) + { + // backward compatibility for season 1. because season 1 reward already distributed. + var rate = raidId == 1 + ? ranking / totalCount * 100 + : ranking * 100 / totalCount; + return rate; + } + + private static (WorldBossRankingModel, List) GetWorldBossRankingReward(int raidId, int totalCount, WorldBossRankingModel raider, WorldBossRankingRewardSheet rankingRewardSheet, WorldBossListSheet.Row bossRow, RuneSheet runeSheet) + { + var ranking = raider.Ranking; + var rate = GetRankingRate(raidId, ranking, totalCount); + var row = FindRow(rankingRewardSheet, bossRow.BossId, ranking, rate); + return (raider, row.GetRewards(runeSheet)); + } } } diff --git a/NineChronicles.Headless b/NineChronicles.Headless index 44553c3f..e6b6891d 160000 --- a/NineChronicles.Headless +++ b/NineChronicles.Headless @@ -1 +1 @@ -Subproject commit 44553c3fc776f3595d17dab65232c4ee42f64477 +Subproject commit e6b6891d6c6bbe50d892b5813e6440e742c94219