Fixed slow .xp and .xpglb

This commit is contained in:
Master Kwoth 2017-09-13 05:10:26 +02:00
parent 067297478e
commit 48adfc19af
12 changed files with 2063 additions and 53 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class totalxp : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "TotalXp",
table: "DiscordUser",
nullable: false,
defaultValue: 0);
migrationBuilder.Sql(MigrationQueries.TotalXp);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "TotalXp",
table: "DiscordUser");
}
}
}

View File

@ -34,5 +34,9 @@ INSERT INTO DiscordUser
FROM DiscordUser_tmp; FROM DiscordUser_tmp;
DROP TABLE DiscordUser_tmp;"; DROP TABLE DiscordUser_tmp;";
public static string TotalXp { get; } =
@"UPDATE DiscordUser
SET TotalXp = (SELECT SUM(Xp) FROM UserXpStats WHERE UserId = DiscordUser.UserId)";
} }
} }

View File

@ -464,12 +464,14 @@ namespace NadekoBot.Migrations
b.Property<DateTime>("LastLevelUp") b.Property<DateTime>("LastLevelUp")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasDefaultValue(new DateTime(2017, 9, 11, 22, 0, 31, 236, DateTimeKind.Local)); .HasDefaultValue(new DateTime(2017, 9, 13, 4, 26, 53, 906, DateTimeKind.Local));
b.Property<DateTime>("LastXpGain"); b.Property<DateTime>("LastXpGain");
b.Property<int>("NotifyOnLevelUp"); b.Property<int>("NotifyOnLevelUp");
b.Property<int>("TotalXp");
b.Property<ulong>("UserId"); b.Property<ulong>("UserId");
b.Property<string>("Username"); b.Property<string>("Username");
@ -1362,7 +1364,7 @@ namespace NadekoBot.Migrations
b.Property<DateTime>("LastLevelUp") b.Property<DateTime>("LastLevelUp")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasDefaultValue(new DateTime(2017, 9, 11, 22, 0, 31, 238, DateTimeKind.Local)); .HasDefaultValue(new DateTime(2017, 9, 13, 4, 26, 53, 910, DateTimeKind.Local));
b.Property<int>("NotifyOnLevelUp"); b.Property<int>("NotifyOnLevelUp");

View File

@ -150,6 +150,7 @@ namespace NadekoBot.Modules.Xp.Services
var oldGuildLevelData = new LevelStats(usr.Xp + usr.AwardedXp); var oldGuildLevelData = new LevelStats(usr.Xp + usr.AwardedXp);
usr.Xp += xp; usr.Xp += xp;
du.TotalXp += xp;
if (du.Club != null) if (du.Club != null)
du.Club.Xp += xp; du.Club.Xp += xp;
var newGuildLevelData = new LevelStats(usr.Xp + usr.AwardedXp); var newGuildLevelData = new LevelStats(usr.Xp + usr.AwardedXp);
@ -311,7 +312,7 @@ namespace NadekoBot.Modules.Xp.Services
{ {
using (var uow = _db.UnitOfWork) using (var uow = _db.UnitOfWork)
{ {
return uow.Xp.GetUsersFor(page); return uow.DiscordUsers.GetUsersXpLeaderboardFor(page);
} }
} }
@ -424,8 +425,8 @@ namespace NadekoBot.Modules.Xp.Services
{ {
du = uow.DiscordUsers.GetOrCreate(user); du = uow.DiscordUsers.GetOrCreate(user);
stats = uow.Xp.GetOrCreateUser(user.GuildId, user.Id); stats = uow.Xp.GetOrCreateUser(user.GuildId, user.Id);
totalXp = uow.Xp.GetTotalUserXp(user.Id); totalXp = du.TotalXp;
globalRank = uow.Xp.GetUserGlobalRanking(user.Id); globalRank = uow.DiscordUsers.GetUserGlobalRanking(user.Id);
guildRank = uow.Xp.GetUserGuildRanking(user.Id, user.GuildId); guildRank = uow.Xp.GetUserGuildRanking(user.Id, user.GuildId);
} }

View File

@ -1,10 +1,12 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using NadekoBot.Common;
using NadekoBot.Common.Attributes; using NadekoBot.Common.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Modules.Xp.Common; using NadekoBot.Modules.Xp.Common;
using NadekoBot.Modules.Xp.Services; using NadekoBot.Modules.Xp.Services;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
@ -15,14 +17,42 @@ namespace NadekoBot.Modules.Xp
public partial class Xp : NadekoTopLevelModule<XpService> public partial class Xp : NadekoTopLevelModule<XpService>
{ {
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
private readonly DbService _db;
public Xp(DiscordSocketClient client) public Xp(DiscordSocketClient client,DbService db)
{ {
_client = client; _client = client;
_db = db;
} }
//[NadekoCommand, Usage, Description, Aliases]
//[RequireContext(ContextType.Guild)]
//[OwnerOnly]
//public async Task Populate()
//{
// var rng = new NadekoRandom();
// using (var uow = _db.UnitOfWork)
// {
// for (var i = 0ul; i < 1000000; i++)
// {
// uow.DiscordUsers.Add(new DiscordUser()
// {
// AvatarId = i.ToString(),
// Discriminator = "1234",
// UserId = i,
// Username = i.ToString(),
// Club = null,
// });
// var xp = uow.Xp.GetOrCreateUser(Context.Guild.Id, i);
// xp.Xp = rng.Next(100, 100000);
// }
// uow.Complete();
// }
//}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
//[Ratelimit(30)]
public async Task Experience([Remainder]IUser user = null) public async Task Experience([Remainder]IUser user = null)
{ {
user = user ?? Context.User; user = user ?? Context.User;
@ -44,7 +74,7 @@ namespace NadekoBot.Modules.Xp
{ {
page--; page--;
if (page < 0) if (page < 0 || page > 100)
return Task.CompletedTask; return Task.CompletedTask;
var roles = _service.GetRoleRewards(Context.Guild.Id) var roles = _service.GetRoleRewards(Context.Guild.Id)
@ -173,7 +203,7 @@ namespace NadekoBot.Modules.Xp
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public Task XpLeaderboard(int page = 1) public Task XpLeaderboard(int page = 1)
{ {
if (--page < 0) if (--page < 0 || page > 100)
return Task.CompletedTask; return Task.CompletedTask;
return Context.Channel.SendPaginatedConfirmAsync(_client, page, async (curPage) => return Context.Channel.SendPaginatedConfirmAsync(_client, page, async (curPage) =>
@ -214,32 +244,28 @@ namespace NadekoBot.Modules.Xp
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task XpGlobalLeaderboard(int page = 1) public async Task XpGlobalLeaderboard(int page = 1)
{ {
if (--page < 0) if (--page < 0 || page > 100)
return; return;
var users = _service.GetUserXps(page);
await Context.Channel.SendPaginatedConfirmAsync(_client, page, async (curPage) => var embed = new EmbedBuilder()
.WithTitle(GetText("global_leaderboard"))
.WithOkColor();
if (!users.Any())
embed.WithDescription("-");
else
{ {
var users = _service.GetUserXps(curPage); for (int i = 0; i < users.Length; i++)
var embed = new EmbedBuilder()
.WithTitle(GetText("global_leaderboard"))
.WithOkColor();
if (!users.Any())
return embed.WithDescription("-");
else
{ {
for (int i = 0; i < users.Length; i++) var user = await Context.Guild.GetUserAsync(users[i].UserId).ConfigureAwait(false);
{ embed.AddField(
var user = await Context.Guild.GetUserAsync(users[i].UserId).ConfigureAwait(false); $"#{(i + 1 + page * 9)} {(user?.ToString() ?? users[i].UserId.ToString())}",
embed.AddField( $"{GetText("level_x", LevelStats.FromXp(users[i].TotalXp).Level)} - {users[i].TotalXp}xp");
$"#{(i + 1 + curPage * 9)} {(user?.ToString() ?? users[i].UserId.ToString())}",
$"{GetText("level_x", LevelStats.FromXp(users[i].TotalXp).Level)} - {users[i].TotalXp}xp");
}
return embed;
} }
}, addPaginatedFooter: false); }
await Context.Channel.EmbedAsync(embed);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]

View File

@ -3589,7 +3589,7 @@
<value>`{0}xpex Role Excluded-Role` `{0}xpex Server`</value> <value>`{0}xpex Role Excluded-Role` `{0}xpex Server`</value>
</data> </data>
<data name="xpexclude_desc" xml:space="preserve"> <data name="xpexclude_desc" xml:space="preserve">
<value>Exclude a user or a role from the xp system, or whole current server.</value> <value>Exclude a channel, role or current server from the xp system.</value>
</data> </data>
<data name="xpnotify_cmd" xml:space="preserve"> <data name="xpnotify_cmd" xml:space="preserve">
<value>xpnotify xpn</value> <value>xpnotify xpn</value>

View File

@ -10,6 +10,8 @@ namespace NadekoBot.Services.Database.Models
public string AvatarId { get; set; } public string AvatarId { get; set; }
public ClubInfo Club { get; set; } public ClubInfo Club { get; set; }
public int TotalXp { get; set; }
public DateTime LastLevelUp { get; set; } = DateTime.UtcNow; public DateTime LastLevelUp { get; set; } = DateTime.UtcNow;
public DateTime LastXpGain { get; set; } = DateTime.MinValue; public DateTime LastXpGain { get; set; } = DateTime.MinValue;
public XpNotificationType NotifyOnLevelUp { get; set; } public XpNotificationType NotifyOnLevelUp { get; set; }

View File

@ -6,5 +6,7 @@ namespace NadekoBot.Services.Database.Repositories
public interface IDiscordUserRepository : IRepository<DiscordUser> public interface IDiscordUserRepository : IRepository<DiscordUser>
{ {
DiscordUser GetOrCreate(IUser original); DiscordUser GetOrCreate(IUser original);
int GetUserGlobalRanking(ulong id);
(ulong UserId, int TotalXp)[] GetUsersXpLeaderboardFor(int page);
} }
} }

View File

@ -6,9 +6,7 @@ namespace NadekoBot.Services.Database.Repositories
{ {
UserXpStats GetOrCreateUser(ulong guildId, ulong userId); UserXpStats GetOrCreateUser(ulong guildId, ulong userId);
int GetTotalUserXp(ulong userId); int GetTotalUserXp(ulong userId);
UserXpStats[] GetUsersFor(ulong guildId, int page);
(ulong UserId, int TotalXp)[] GetUsersFor(int page);
int GetUserGlobalRanking(ulong userId);
int GetUserGuildRanking(ulong userId, ulong guildId); int GetUserGuildRanking(ulong userId, ulong guildId);
UserXpStats[] GetUsersFor(ulong guildId, int page);
} }
} }

View File

@ -37,5 +37,24 @@ namespace NadekoBot.Services.Database.Repositories.Impl
return toReturn; return toReturn;
} }
public int GetUserGlobalRanking(ulong id)
{
return _set.Count(x => x.TotalXp >
_set.Where(y => y.UserId == id)
.DefaultIfEmpty()
.Sum(y => y.TotalXp));
}
public (ulong UserId, int TotalXp)[] GetUsersXpLeaderboardFor(int page)
{
return _set
.OrderByDescending(x => x.TotalXp)
.Skip(page * 9)
.Take(9)
.AsEnumerable()
.Select(y => (y.UserId, y.TotalXp))
.ToArray();
}
} }
} }

View File

@ -43,15 +43,6 @@ namespace NadekoBot.Services.Database.Repositories.Impl
.ToArray(); .ToArray();
} }
public int GetUserGlobalRanking(ulong userId)
{
return _set
.GroupBy(x => x.UserId)
.Count(x => x.Sum(y => y.Xp) > _set
.Where(y => y.UserId == userId)
.Sum(y => y.Xp)) + 1;
}
public int GetUserGuildRanking(ulong userId, ulong guildId) public int GetUserGuildRanking(ulong userId, ulong guildId)
{ {
return _set return _set
@ -62,16 +53,5 @@ namespace NadekoBot.Services.Database.Repositories.Impl
.DefaultIfEmpty() .DefaultIfEmpty()
.Sum())) + 1; .Sum())) + 1;
} }
public (ulong UserId, int TotalXp)[] GetUsersFor(int page)
{
return _set.GroupBy(x => x.UserId)
.OrderByDescending(x => x.Sum(y => y.Xp))
.Skip(page * 9)
.Take(9)
.AsEnumerable()
.Select(x => (x.Key, x.Sum(y => y.Xp)))
.ToArray();
}
} }
} }