diff --git a/KfChatDotNetBot/Commands/KasinoUserCommands.cs b/KfChatDotNetBot/Commands/KasinoUserCommands.cs index b3ed15e..a7f4751 100644 --- a/KfChatDotNetBot/Commands/KasinoUserCommands.cs +++ b/KfChatDotNetBot/Commands/KasinoUserCommands.cs @@ -134,15 +134,15 @@ public class RakebackCommand : ICommand offset = mostRecentRakeback.TimeUnixEpochSeconds; } - var wagers = db.Wagers.Where(w => w.Gambler == gambler && w.TimeUnixEpochSeconds > offset); - if (!await wagers.AnyAsync(ctx)) + var wagers = await db.Wagers.Where(w => w.Gambler == gambler && w.TimeUnixEpochSeconds > offset).ToListAsync(ctx); + if (wagers.Count == 0) { await botInstance.SendChatMessageAsync( $"@{user.KfUsername}, you haven't wagered since your last rakeback.", true); return; } - var wagered = await wagers.SumAsync(w => w.WagerAmount, ctx); + var wagered = wagers.Sum(w => w.WagerAmount); var rakeback = wagered * (decimal)(settings[BuiltIn.Keys.MoneyRakebackPercentage].ToType() / 100.0); var minimumRakeback = settings[BuiltIn.Keys.MoneyRakebackMinimumAmount].ToType(); if (rakeback < minimumRakeback) @@ -152,5 +152,54 @@ public class RakebackCommand : ICommand } await gambler!.ModifyBalance(rakeback, TransactionSourceEventType.Rakeback, "Rakeback claimed by gambler", ct: ctx); + await botInstance.SendChatMessageAsync($"@{user.KfUsername}, the hostess has given you {await rakeback.FormatKasinoCurrencyAsync()} rakeback", true); + } +} + +[KasinoCommand] +public class LossbackCommand : ICommand +{ + public List Patterns => [ + new Regex(@"^lossback", RegexOptions.IgnoreCase) + ]; + public string? HelpText => "Collect your lossback"; + public UserRight RequiredRight => UserRight.Loser; + public TimeSpan Timeout => TimeSpan.FromSeconds(10); + + public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, + CancellationToken ctx) + { + await using var db = new ApplicationDbContext(); + var gambler = await user.GetGamblerEntity(ct: ctx); + var settings = await SettingsProvider.GetMultipleValuesAsync([ + BuiltIn.Keys.MoneyLossbackPercentage, BuiltIn.Keys.MoneyLossbackMinimumAmount + ]); + var mostRecentLossback = await db.Transactions.LastOrDefaultAsync(tx => + tx.EventSource == TransactionSourceEventType.Lossback && tx.Gambler == gambler, cancellationToken: ctx); + long offset = 0; + if (mostRecentLossback != null) + { + offset = mostRecentLossback.TimeUnixEpochSeconds; + } + + var wagers = await db.Wagers.Where(w => w.Gambler == gambler && w.TimeUnixEpochSeconds > offset && w.Multiplier < 1).ToListAsync(ctx); + if (wagers.Count == 0) + { + await botInstance.SendChatMessageAsync( + $"@{user.KfUsername}, you don't have any losses to juice back.", true); + return; + } + + var wagered = wagers.Sum(wager => Math.Abs(wager.WagerEffect)); + var lossback = wagered * (decimal)(settings[BuiltIn.Keys.MoneyLossbackPercentage].ToType() / 100.0); + var minimumLossback = settings[BuiltIn.Keys.MoneyLossbackMinimumAmount].ToType(); + if (lossback < minimumLossback) + { + await botInstance.SendChatMessageAsync($"@{user.KfUsername}, your lossback payout of {await lossback.FormatKasinoCurrencyAsync()} is below the minimum amount of {await minimumLossback.FormatKasinoCurrencyAsync()}", true); + return; + } + await gambler!.ModifyBalance(lossback, TransactionSourceEventType.Lossback, "Lossback claimed by gambler", + ct: ctx); + await botInstance.SendChatMessageAsync($"@{user.KfUsername}, the hostess has given you {await lossback.FormatKasinoCurrencyAsync()} lossback", true); } } \ No newline at end of file diff --git a/KfChatDotNetBot/Models/DbModels/MoneyDbModels.cs b/KfChatDotNetBot/Models/DbModels/MoneyDbModels.cs index 705ef5c..c09965b 100644 --- a/KfChatDotNetBot/Models/DbModels/MoneyDbModels.cs +++ b/KfChatDotNetBot/Models/DbModels/MoneyDbModels.cs @@ -264,7 +264,13 @@ public enum TransactionSourceEventType /// /// Use this only for hostess juicers as the sum of these juicers in a given day can influence the hostess' behavior /// - Hostess + Hostess, + /// + /// Specifically use for lossback as we use the delta between last lossback txn to calculate total lost + /// to figure out what the next lossback should be. (Basically return a small % of the player's losses + /// unless the player's actual position is positive during the period, then tell them to fuck off) + /// + Lossback } public enum WagerGame diff --git a/KfChatDotNetBot/Settings/BuiltIn.cs b/KfChatDotNetBot/Settings/BuiltIn.cs index dc1697f..3577af0 100644 --- a/KfChatDotNetBot/Settings/BuiltIn.cs +++ b/KfChatDotNetBot/Settings/BuiltIn.cs @@ -1008,6 +1008,21 @@ public static class BuiltIn ValueType = SettingValueType.Text, Regex = WholeNumberRegex }, + new BuiltInSettingsModel + { + Key = Keys.MoneyLossbackPercentage, + Description = "Percentage of total amount lost that should be returned for lossback.", + Default = "5", + ValueType = SettingValueType.Text + }, + new BuiltInSettingsModel + { + Key = Keys.MoneyLossbackMinimumAmount, + Description = "Minimum lossback to pay out. Anything below this will tell the user to go away.", + Default = "100", + ValueType = SettingValueType.Text, + Regex = WholeNumberRegex + }, ]; public static class Keys @@ -1122,5 +1137,7 @@ public static class BuiltIn public static string OwncastPersistedCurrentlyLive = "Owncast.PersistedCurrentlyLive"; public static string MoneyRakebackPercentage = "Money.Rakeback.Percentage"; public static string MoneyRakebackMinimumAmount = "Money.Rakeback.MinimumAmount"; + public static string MoneyLossbackPercentage = "Money.Lossback.Percentage"; + public static string MoneyLossbackMinimumAmount = "Money.Lossback.MinimumAmount"; } } \ No newline at end of file