This repository has been archived on 2024-12-22. You can view files and clone it, but cannot push or open issues or pull requests.
elliebot/src/EllieBot/Modules/Gambling/BetStatsCommands.cs

244 lines
7.8 KiB
C#
Raw Normal View History

#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);
2024-11-28 01:06:01 +13:00
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
}
};
2024-11-28 01:06:01 +13:00
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();
2024-11-28 01:06:01 +13:00
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()
{
2024-11-28 01:06:01 +13:00
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();
}
}
}