using System.Text.RegularExpressions; using KfChatDotNetBot.Extensions; using KfChatDotNetBot.Models; using KfChatDotNetBot.Models.DbModels; using KfChatDotNetBot.Services; using KfChatDotNetBot.Settings; namespace KfChatDotNetBot.Commands.Kasino; [KasinoCommand] [WagerCommand] public class CecilCommand : ICommand { public List Patterns => [ new Regex(@"^cecil (?\d+(?:\.\d+)?) (?\d+(?:\.\d+)?) (?\d+(?:\.\d+)?)", RegexOptions.IgnoreCase), new Regex(@"^cecil (?\d+(?:\.\d+)?) (?\d+(?:\.\d+)?)", RegexOptions.IgnoreCase), new Regex(@"^cecil (?\d+(?:\.\d+)?)", RegexOptions.IgnoreCase), new Regex("^cecil") ]; public string? HelpText => "!cecil "; public UserRight RequiredRight => UserRight.Loser; public TimeSpan Timeout => TimeSpan.FromSeconds(60); public RateLimitOptionsModel? RateLimitOptions => new() { MaxInvocations = 5, Window = TimeSpan.FromSeconds(10) }; public bool WhisperCanInvoke => true; public decimal HOUSE_EDGE = 0.98m; public async Task RunCommand(ChatBot botInstance, BotCommandMessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx) { if (message is { IsWhisper: false, MessageUuid: not null }) { await botInstance.KfClient.DeleteMessageAsync(message.MessageUuid); } var cleanupDelay = TimeSpan.FromSeconds(15); var settings = await SettingsProvider.GetMultipleValuesAsync([BuiltIn.Keys.KasinoCecilEnabled]); var cecilEnabled = settings[BuiltIn.Keys.KasinoCecilEnabled].ToBoolean(); if (!cecilEnabled) { await botInstance.ReplyToUser(message, $"{user.FormatUsername()}, Cecil is currently disabled.", true, autoDeleteAfter: cleanupDelay); return; } if (!arguments.TryGetValue("bet", out var amount)) //if user just enters !keno { await botInstance.ReplyToUser(message, $"{user.FormatUsername()}, not enough arguments. !cecil <[i]optional max win > 1[/i] - Cecil Tool: https://i.ddos.lgbt/raw/CecilHelper.html>", true, autoDeleteAfter: cleanupDelay); RateLimitService.RemoveMostRecentEntry(user, this); return; } var wager = Convert.ToDecimal(amount.Value); var gambler = await Money.GetGamblerEntityAsync(user.Id, ct: ctx); if (gambler == null) throw new InvalidOperationException($"Caught a null when retrieving gambler for {user.KfUsername}"); if (gambler.Balance < wager) { await botInstance.ReplyToUser(message, $"{user.FormatUsername()}, your balance of {await gambler.Balance.FormatKasinoCurrencyAsync()} isn't enough for this wager.", true, autoDeleteAfter: cleanupDelay); RateLimitService.RemoveMostRecentEntry(user, this); return; } bool shopActive = botInstance.BotServices.KasinoShop != null; if (shopActive) { await GlobalShopFunctions.CheckProfile(botInstance, user, gambler); HOUSE_EDGE += botInstance.BotServices.KasinoShop!.Gambler_Profiles[user.KfId].HouseEdgeModifier; } var difficulty = 1.0; bool customDiff = false; double result; if (arguments.TryGetValue("difficulty", out var diff)) { difficulty = Convert.ToDouble(diff.Value); customDiff = true; } if (!customDiff && shopActive && botInstance.BotServices.KasinoShop!.Gambler_Profiles[user.KfId].Difficulty != "") { var skew = Skew.FromToken(botInstance.BotServices.KasinoShop!.Gambler_Profiles[user.KfId].Difficulty); skew.Rig((double)HOUSE_EDGE, 0); result = Cecil.Consult(skew); } else if (!arguments.TryGetValue("maxwin", out var maxWin)) { var skew = new GammaSkew(difficulty, 0); skew.Rig((double)HOUSE_EDGE, 0); result = Cecil.Consult(skew, 0); } else { var mWin = Convert.ToDouble(maxWin.Value); if (mWin < 1) { await botInstance.ReplyToUser(message, $"{user.FormatUsername()}, max win must be greater than 1.", true, autoDeleteAfter: cleanupDelay); return; } var skew = new BetaSkew(difficulty, mWin, 0); skew.Rig((double)HOUSE_EDGE, 0); result = Cecil.Consult(skew); } var payout = wager * Convert.ToDecimal(result); var net = payout - wager; var newBalance = await Money.NewWagerAsync(gambler.Id, wager, net, WagerGame.Cecil, ct: ctx); var colors = await SettingsProvider.GetMultipleValuesAsync([ BuiltIn.Keys.KiwiFarmsGreenColor, BuiltIn.Keys.KiwiFarmsRedColor ]); var red = colors[BuiltIn.Keys.KiwiFarmsRedColor].Value; var green = colors[BuiltIn.Keys.KiwiFarmsGreenColor].Value; var color = (payout > wager) ? green : red; await botInstance.ReplyToUser(message, $"{user.FormatUsername()}, Cecil has determined you are due [color={color}]{await payout.FormatKasinoCurrencyAsync()}[/color] from your wager of {await wager.FormatKasinoCurrencyAsync()}. Balance: {await newBalance.FormatKasinoCurrencyAsync()}", true, autoDeleteAfter: cleanupDelay); } }