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;
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")
.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<int>("NotifyOnLevelUp");
b.Property<int>("TotalXp");
b.Property<ulong>("UserId");
b.Property<string>("Username");
@ -1362,7 +1364,7 @@ namespace NadekoBot.Migrations
b.Property<DateTime>("LastLevelUp")
.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");

View File

@ -150,6 +150,7 @@ namespace NadekoBot.Modules.Xp.Services
var oldGuildLevelData = new LevelStats(usr.Xp + usr.AwardedXp);
usr.Xp += xp;
du.TotalXp += xp;
if (du.Club != null)
du.Club.Xp += xp;
var newGuildLevelData = new LevelStats(usr.Xp + usr.AwardedXp);
@ -311,7 +312,7 @@ namespace NadekoBot.Modules.Xp.Services
{
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);
stats = uow.Xp.GetOrCreateUser(user.GuildId, user.Id);
totalXp = uow.Xp.GetTotalUserXp(user.Id);
globalRank = uow.Xp.GetUserGlobalRanking(user.Id);
totalXp = du.TotalXp;
globalRank = uow.DiscordUsers.GetUserGlobalRanking(user.Id);
guildRank = uow.Xp.GetUserGuildRanking(user.Id, user.GuildId);
}

View File

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

View File

@ -3589,7 +3589,7 @@
<value>`{0}xpex Role Excluded-Role` `{0}xpex Server`</value>
</data>
<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 name="xpnotify_cmd" xml:space="preserve">
<value>xpnotify xpn</value>

View File

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

View File

@ -6,5 +6,7 @@ namespace NadekoBot.Services.Database.Repositories
public interface IDiscordUserRepository : IRepository<DiscordUser>
{
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);
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);
UserXpStats[] GetUsersFor(ulong guildId, int page);
}
}

View File

@ -37,5 +37,24 @@ namespace NadekoBot.Services.Database.Repositories.Impl
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();
}
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)
{
return _set
@ -62,16 +53,5 @@ namespace NadekoBot.Services.Database.Repositories.Impl
.DefaultIfEmpty()
.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();
}
}
}