Slight tweaks to xp loop

This commit is contained in:
Kwoth
2022-07-13 01:15:28 +02:00
parent 34955f88f6
commit 0b122e8d3f

View File

@@ -1,4 +1,4 @@
#nullable disable
#nullable disable warnings
using LinqToDB;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Common.ModuleBehaviors;
@@ -14,7 +14,6 @@ using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System.Threading.Channels;
using Nadeko.Common;
using Color = SixLabors.ImageSharp.Color;
using Image = SixLabors.ImageSharp.Image;
@@ -170,53 +169,55 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand
else
ci.XpAmount += item.XpAmount;
}
await using var ctx = _db.GetDbContext();
await using var tran = await ctx.Database.BeginTransactionAsync();
// update global user xp in batches
// group by xp amount and update the same amounts at the same time
var dus = new List<DiscordUser>(globalToAdd.Count);
foreach (var group in globalToAdd.GroupBy(x => x.Value.XpAmount, x => x.Key))
{
var items = await ctx.DiscordUser
.Where(x => group.Contains(x.UserId))
.UpdateWithOutputAsync(old => new()
{
TotalXp = old.TotalXp + group.Key
},
(_, n) => n);
dus.AddRange(items);
}
// update guild user xp in batches
var gxps = new List<UserXpStats>(globalToAdd.Count);
foreach (var (guildId, toAdd) in guildToAdd)
await using (var ctx = _db.GetDbContext())
{
foreach (var group in toAdd.GroupBy(x => x.Value.XpAmount, x => x.Key))
await using var tran = await ctx.Database.BeginTransactionAsync();
// update global user xp in batches
// group by xp amount and update the same amounts at the same time
foreach (var group in globalToAdd.GroupBy(x => x.Value.XpAmount, x => x.Key))
{
var items = await ctx
.UserXpStats
.Where(x => x.GuildId == guildId)
var items = await ctx.DiscordUser
.Where(x => group.Contains(x.UserId))
.UpdateWithOutputAsync(old => new()
{
Xp = old.Xp + group.Key
TotalXp = old.TotalXp + group.Key
},
(_, n) => n);
gxps.AddRange(items);
dus.AddRange(items);
}
// update guild user xp in batches
foreach (var (guildId, toAdd) in guildToAdd)
{
foreach (var group in toAdd.GroupBy(x => x.Value.XpAmount, x => x.Key))
{
var items = await ctx
.UserXpStats
.Where(x => x.GuildId == guildId)
.Where(x => group.Contains(x.UserId))
.UpdateWithOutputAsync(old => new()
{
Xp = old.Xp + group.Key
},
(_, n) => n);
gxps.AddRange(items);
}
}
await tran.CommitAsync();
}
await tran.CommitAsync();
foreach (var du in dus)
{
var oldLevel = new LevelStats(du.TotalXp - globalToAdd[du.UserId].XpAmount);
var newLevel = new LevelStats(du.TotalXp);
if (oldLevel.Level != newLevel.Level)
{
var item = globalToAdd[du.UserId];
@@ -279,10 +280,14 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand
private async Task HandleRewardsInternalAsync(ulong guildId, ulong userId, long oldLevel, long newLevel)
{
await using var ctx = _db.GetDbContext();
var rrews = ctx.XpSettingsFor(guildId).RoleRewards.ToList();
var crews = ctx.XpSettingsFor(guildId).CurrencyRewards.ToList();
List<XpRoleReward> rrews;
List<XpCurrencyReward> crews;
await using (var ctx = _db.GetDbContext())
{
rrews = ctx.XpSettingsFor(guildId).RoleRewards.ToList();
crews = ctx.XpSettingsFor(guildId).CurrencyRewards.ToList();
}
//loop through levels since last level up, so if a high amount of xp is gained, reward are still applied.
for (var i = oldLevel + 1; i <= newLevel; i++)
{
@@ -569,8 +574,10 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand
await ScanChannelForVoiceXp(before.VoiceChannel);
if (after.VoiceChannel is not null && after.VoiceChannel != before.VoiceChannel)
{
await ScanChannelForVoiceXp(after.VoiceChannel);
else if (after.VoiceChannel is null)
}
else if (after.VoiceChannel is null && before.VoiceChannel is not null)
{
// In this case, the user left the channel and the previous for loops didn't catch
// it because it wasn't in any new channel. So we need to get rid of it.