forked from EllieBotDevs/elliebot
added .notify with no params showing events with descriptions added .winlb updated discord.net, redid migrations
244 lines
No EOL
7.8 KiB
C#
244 lines
No EOL
7.8 KiB
C#
#nullable disable
|
||
using EllieBot.Modules.Gambling.Common;
|
||
using EllieBot.Modules.Gambling.Services;
|
||
using EllieBot.Modules.Xp.Services;
|
||
|
||
namespace EllieBot.Modules.Gambling;
|
||
|
||
public partial class Gambling
|
||
{
|
||
[Group]
|
||
public sealed class BetStatsCommands : GamblingModule<UserBetStatsService>
|
||
{
|
||
private readonly GamblingTxTracker _gamblingTxTracker;
|
||
private readonly IBotCache _cache;
|
||
private readonly IUserService _userService;
|
||
|
||
public BetStatsCommands(
|
||
GamblingTxTracker gamblingTxTracker,
|
||
GamblingConfigService gcs,
|
||
IBotCache cache,
|
||
IUserService userService)
|
||
: base(gcs)
|
||
{
|
||
_gamblingTxTracker = gamblingTxTracker;
|
||
_cache = cache;
|
||
_userService = userService;
|
||
}
|
||
|
||
[Cmd]
|
||
public async Task BetStatsReset(GamblingGame? game = null)
|
||
{
|
||
var price = await _service.GetResetStatsPriceAsync(ctx.User.Id, game);
|
||
|
||
var result = await PromptUserConfirmAsync(CreateEmbed()
|
||
.WithDescription(
|
||
$"""
|
||
Are you sure you want to reset your bet stats for **{GetGameName(game)}**?
|
||
|
||
It will cost you {N(price)}
|
||
"""));
|
||
|
||
if (!result)
|
||
return;
|
||
|
||
var success = await _service.ResetStatsAsync(ctx.User.Id, game);
|
||
|
||
if (success)
|
||
{
|
||
await ctx.OkAsync();
|
||
}
|
||
else
|
||
{
|
||
await Response()
|
||
.Error(strs.not_enough(CurrencySign))
|
||
.SendAsync();
|
||
}
|
||
}
|
||
|
||
private string GetGameName(GamblingGame? game)
|
||
{
|
||
if (game is null)
|
||
return "all games";
|
||
|
||
return game.ToString();
|
||
}
|
||
|
||
[Cmd]
|
||
[Priority(3)]
|
||
public async Task BetStats()
|
||
=> await BetStats(ctx.User, null);
|
||
|
||
[Cmd]
|
||
[Priority(2)]
|
||
public async Task BetStats(GamblingGame game)
|
||
=> await BetStats(ctx.User, game);
|
||
|
||
[Cmd]
|
||
[Priority(1)]
|
||
public async Task BetStats([Leftover] IUser user)
|
||
=> await BetStats(user, null);
|
||
|
||
[Cmd]
|
||
[Priority(0)]
|
||
public async Task BetStats(IUser user, GamblingGame? game)
|
||
{
|
||
var stats = await _gamblingTxTracker.GetUserStatsAsync(user.Id, game);
|
||
|
||
if (stats.Count == 0)
|
||
stats = new()
|
||
{
|
||
new()
|
||
{
|
||
TotalBet = 1
|
||
}
|
||
};
|
||
|
||
var eb = CreateEmbed()
|
||
.WithOkColor()
|
||
.WithAuthor(user)
|
||
.AddField("Total Won", N(stats.Sum(x => x.PaidOut)), true)
|
||
.AddField("Biggest Win", N(stats.Max(x => x.MaxWin)), true)
|
||
.AddField("Biggest Bet", N(stats.Max(x => x.MaxBet)), true)
|
||
.AddField("# Bets", stats.Sum(x => x.WinCount + x.LoseCount), true)
|
||
.AddField("Payout",
|
||
(stats.Sum(x => x.PaidOut) / stats.Sum(x => x.TotalBet)).ToString("P2", Culture),
|
||
true);
|
||
if (game == null)
|
||
{
|
||
var favGame = stats.MaxBy(x => x.WinCount + x.LoseCount);
|
||
eb.AddField("Favorite Game",
|
||
favGame.Game + "\n" + Format.Italics((favGame.WinCount + favGame.LoseCount) + " plays"),
|
||
true);
|
||
}
|
||
else
|
||
{
|
||
eb.WithDescription(game.ToString())
|
||
.AddField("# Wins", stats.Sum(x => x.WinCount), true);
|
||
}
|
||
|
||
await Response()
|
||
.Embed(eb)
|
||
.SendAsync();
|
||
}
|
||
|
||
private readonly record struct WinLbStat(
|
||
int Rank,
|
||
string User,
|
||
GamblingGame Game,
|
||
long MaxWin);
|
||
|
||
private TypedKey<List<WinLbStat>> GetWinLbKey(int page)
|
||
=> new($"winlb:{page}");
|
||
|
||
private async Task<IReadOnlyCollection<WinLbStat>> GetCachedWinLbAsync(int page)
|
||
{
|
||
return await _cache.GetOrAddAsync(GetWinLbKey(page),
|
||
async () =>
|
||
{
|
||
var items = await _service.GetWinLbAsync(page);
|
||
|
||
if (items.Count == 0)
|
||
return [];
|
||
|
||
var outputItems = new List<WinLbStat>(items.Count);
|
||
for (var i = 0; i < items.Count; i++)
|
||
{
|
||
var x = items[i];
|
||
var user = (await ctx.Client.GetUserAsync(x.UserId, CacheMode.CacheOnly))?.ToString()
|
||
?? (await _userService.GetUserAsync(x.UserId))?.Username
|
||
?? x.UserId.ToString();
|
||
|
||
outputItems.Add(new WinLbStat(i + 1 + (page * 10), user, x.Game, x.MaxWin));
|
||
}
|
||
|
||
return outputItems;
|
||
},
|
||
expiry: TimeSpan.FromMinutes(5));
|
||
}
|
||
|
||
[Cmd]
|
||
public async Task WinLb(int page = 1)
|
||
{
|
||
if (--page < 0)
|
||
return;
|
||
|
||
await Response()
|
||
.Paginated()
|
||
.PageItems(p => GetCachedWinLbAsync(p))
|
||
.PageSize(10)
|
||
.Page((items, curPage) =>
|
||
{
|
||
var eb = CreateEmbed()
|
||
.WithOkColor();
|
||
|
||
for (var i = 0; i < items.Count; i++)
|
||
{
|
||
var item = items[i];
|
||
eb.AddField($"#{item.Rank} {item.User}",
|
||
$"[{item.Game}]{N(item.MaxWin)}");
|
||
}
|
||
|
||
return eb;
|
||
})
|
||
.SendAsync();
|
||
}
|
||
|
||
[Cmd]
|
||
public async Task GambleStats()
|
||
{
|
||
var stats = await _gamblingTxTracker.GetAllAsync();
|
||
|
||
var eb = CreateEmbed()
|
||
.WithOkColor();
|
||
|
||
var str = "` Feature `|` Bet `|`Paid Out`|` RoI `\n";
|
||
str += "――――――――――――――――――――\n";
|
||
foreach (var stat in stats)
|
||
{
|
||
var perc = (stat.PaidOut / stat.Bet).ToString("P2", Culture);
|
||
str += $"`{stat.Feature.PadBoth(9)}`"
|
||
+ $"|`{stat.Bet.ToString("N0").PadLeft(8, ' ')}`"
|
||
+ $"|`{stat.PaidOut.ToString("N0").PadLeft(8, ' ')}`"
|
||
+ $"|`{perc.PadLeft(6, ' ')}`\n";
|
||
}
|
||
|
||
var bet = stats.Sum(x => x.Bet);
|
||
var paidOut = stats.Sum(x => x.PaidOut);
|
||
|
||
if (bet == 0)
|
||
bet = 1;
|
||
|
||
var tPerc = (paidOut / bet).ToString("P2", Culture);
|
||
str += "――――――――――――――――――――\n";
|
||
str += $"` {("TOTAL").PadBoth(7)}` "
|
||
+ $"|**{N(bet).PadLeft(8, ' ')}**"
|
||
+ $"|**{N(paidOut).PadLeft(8, ' ')}**"
|
||
+ $"|`{tPerc.PadLeft(6, ' ')}`";
|
||
|
||
eb.WithDescription(str);
|
||
|
||
await Response().Embed(eb).SendAsync();
|
||
}
|
||
|
||
[Cmd]
|
||
[OwnerOnly]
|
||
public async Task GambleStatsReset()
|
||
{
|
||
if (!await PromptUserConfirmAsync(CreateEmbed()
|
||
.WithDescription(
|
||
"""
|
||
Are you sure?
|
||
This will completely reset Gambling Stats.
|
||
|
||
This action is irreversible.
|
||
""")))
|
||
return;
|
||
|
||
await GambleStats();
|
||
await _service.ResetGamblingStatsAsync();
|
||
|
||
await ctx.OkAsync();
|
||
}
|
||
}
|
||
} |