mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 17:28:27 -04:00
Work on porting over Ayu gambling command rewrites
This commit is contained in:
@@ -8,12 +8,356 @@ using SixLabors.ImageSharp.Drawing.Processing;
|
|||||||
using SixLabors.ImageSharp.PixelFormats;
|
using SixLabors.ImageSharp.PixelFormats;
|
||||||
using SixLabors.ImageSharp.Processing;
|
using SixLabors.ImageSharp.Processing;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Nadeko.Common;
|
using Grpc.Core;
|
||||||
|
using NadekoBot.Modules.Gambling.WheelOfFortune;
|
||||||
|
using NadekoBot.Services.Currency;
|
||||||
using Color = SixLabors.ImageSharp.Color;
|
using Color = SixLabors.ImageSharp.Color;
|
||||||
using Image = SixLabors.ImageSharp.Image;
|
using Image = SixLabors.ImageSharp.Image;
|
||||||
|
using OneOf;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Gambling;
|
namespace NadekoBot.Modules.Gambling;
|
||||||
|
|
||||||
|
public enum SlotError
|
||||||
|
{
|
||||||
|
InsufficientFunds,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum WofError
|
||||||
|
{
|
||||||
|
InsufficientFunds,
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ISlotService
|
||||||
|
{
|
||||||
|
ValueTask<OneOf<SlotResult, SlotError>> PullAsync(ulong userId, long amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public record struct WofRequest(ulong UserId, long Amount);
|
||||||
|
|
||||||
|
public record struct BetrollRequest(ulong UserId, long Amount);
|
||||||
|
|
||||||
|
public sealed class DefaultSlotService : INService
|
||||||
|
{
|
||||||
|
private readonly GamblingConfigService _bcs;
|
||||||
|
private readonly ICurrencyService _cs;
|
||||||
|
// public ValueTask<OneOf<SlotResult, SlotError>> PullAsync(ulong userId, long amount)
|
||||||
|
// {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
public DefaultSlotService(GamblingConfigService bcs, ICurrencyService cs)
|
||||||
|
{
|
||||||
|
_bcs = bcs;
|
||||||
|
_cs = cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<OneOf<WofResult, WofError>> Wof(WofRequest request, ServerCallContext context)
|
||||||
|
{
|
||||||
|
var isTakeSuccess = await _cs.RemoveAsync(request.UserId, request.Amount, new TxData("wof", "bet"));
|
||||||
|
|
||||||
|
if (!isTakeSuccess)
|
||||||
|
{
|
||||||
|
return WofError.InsufficientFunds;
|
||||||
|
}
|
||||||
|
|
||||||
|
var game = new WheelOfFortuneGame(_bcs.Data.WheelOfFortune.Multipliers);
|
||||||
|
var result = game.Spin(request.Amount);
|
||||||
|
|
||||||
|
if (result.Amount > 0)
|
||||||
|
{
|
||||||
|
await _cs.AddAsync(request.UserId, result.Amount, new("wof", "win"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<OneOf<>> BetRoll(BetRollRequest request, ServerCallContext context)
|
||||||
|
{
|
||||||
|
var takeRes = await _currency.TransferCurrencyAsync(new TransferCurrencyRequest
|
||||||
|
{
|
||||||
|
Amount = request.Amount,
|
||||||
|
Type = "bet-roll",
|
||||||
|
Subtype = "bet",
|
||||||
|
FromId = request.UserId,
|
||||||
|
ToId = 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!takeRes.Success)
|
||||||
|
{
|
||||||
|
return new BetRollReply
|
||||||
|
{
|
||||||
|
Error = GamblingError.NotEnough
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var game = new Betroll(_config.Data.BetRoll);
|
||||||
|
var result = game.Roll();
|
||||||
|
|
||||||
|
if (result.Multiplier > 0)
|
||||||
|
{
|
||||||
|
var won = (long)(request.Amount * result.Multiplier);
|
||||||
|
|
||||||
|
await _currency.GrantToUserAsync(new GrantToUserRequest
|
||||||
|
{
|
||||||
|
Amount = won,
|
||||||
|
Type = "bet-roll",
|
||||||
|
Subtype = "won",
|
||||||
|
UserId = request.UserId,
|
||||||
|
GranterId = 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
return new BetRollReply
|
||||||
|
{
|
||||||
|
WonAmount = won,
|
||||||
|
Multiplier = result.Multiplier,
|
||||||
|
Roll = result.Roll,
|
||||||
|
Threshold = result.Threshold,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BetRollReply
|
||||||
|
{
|
||||||
|
WonAmount = 0,
|
||||||
|
Multiplier = result.Multiplier,
|
||||||
|
Roll = result.Roll,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// public override async Task<BetFlipReply> BetFlip(BetFlipRequest request, ServerCallContext context)
|
||||||
|
// {
|
||||||
|
// var takeRes = await _currency.TransferCurrencyAsync(new TransferCurrencyRequest
|
||||||
|
// {
|
||||||
|
// Amount = request.Amount,
|
||||||
|
// Type = "bet-flip",
|
||||||
|
// Subtype = "bet",
|
||||||
|
// FromId = request.UserId,
|
||||||
|
// ToId = 0,
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// if (!takeRes.Success)
|
||||||
|
// {
|
||||||
|
// return new BetFlipReply
|
||||||
|
// {
|
||||||
|
// Error = GamblingError.NotEnough
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// var roll = _rng.Next(0, 1000) <= 499;
|
||||||
|
// long won = 0;
|
||||||
|
//
|
||||||
|
// if (roll == request.Guess)
|
||||||
|
// {
|
||||||
|
// won = (long) (_config.Data.Multipliers.BetFlip * request.Amount);
|
||||||
|
//
|
||||||
|
// await _currency.GrantToUserAsync(new GrantToUserRequest
|
||||||
|
// {
|
||||||
|
// Amount = won,
|
||||||
|
// Type = "bet-flip",
|
||||||
|
// Subtype = "won",
|
||||||
|
// UserId = request.UserId,
|
||||||
|
// GranterId = 0,
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// return new BetFlipReply
|
||||||
|
// {
|
||||||
|
// Result = roll
|
||||||
|
// ? BetFlipReply.Types.Side.Heads
|
||||||
|
// : BetFlipReply.Types.Side.Tails,
|
||||||
|
// WonAmount = won
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public override Task<FlipReply> Flip(FlipRequest request, ServerCallContext context)
|
||||||
|
// {
|
||||||
|
// if (request.Count <= 0)
|
||||||
|
// throw new RpcException(new Status(StatusCode.InvalidArgument, "Count has to be greater than 0."));
|
||||||
|
//
|
||||||
|
// var results = Enumerable.Range(0, request.Count)
|
||||||
|
// .Select(x => (FlipReply.Types.Roll) _rng.Next(0, 2));
|
||||||
|
//
|
||||||
|
// var toReturn = new FlipReply();
|
||||||
|
// toReturn.Rolls.AddRange(results);
|
||||||
|
// return Task.FromResult(toReturn);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public override async Task<SlotResponse> Slot(SlotRequest request, ServerCallContext context)
|
||||||
|
// {
|
||||||
|
// var takeRes = await _currency.TransferCurrencyAsync(new TransferCurrencyRequest
|
||||||
|
// {
|
||||||
|
// Amount = request.Amount,
|
||||||
|
// Type = "slot",
|
||||||
|
// Subtype = "bet",
|
||||||
|
// FromId = request.UserId,
|
||||||
|
// ToId = 0,
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// if (!takeRes.Success)
|
||||||
|
// {
|
||||||
|
// return new SlotResponse
|
||||||
|
// {
|
||||||
|
// Error = GamblingError.NotEnough
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// var game = new SlotGame();
|
||||||
|
// var result = game.Spin();
|
||||||
|
// long won = 0;
|
||||||
|
//
|
||||||
|
// if (result.Multiplier > 0)
|
||||||
|
// {
|
||||||
|
// won = (long) (result.Multiplier * request.Amount);
|
||||||
|
//
|
||||||
|
// await _currency.GrantToUserAsync(new GrantToUserRequest
|
||||||
|
// {
|
||||||
|
// Amount = won,
|
||||||
|
// Type = "slot",
|
||||||
|
// Subtype = "won",
|
||||||
|
// UserId = request.UserId,
|
||||||
|
// GranterId = 0,
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// var toReturn = new SlotResponse
|
||||||
|
// {
|
||||||
|
// Multiplier = result.Multiplier,
|
||||||
|
// Won = won,
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// toReturn.Rolls.AddRange(result.Rolls);
|
||||||
|
//
|
||||||
|
// return toReturn;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private readonly ConcurrentDictionary<ulong, Deck> _decks = new ConcurrentDictionary<ulong, Deck>();
|
||||||
|
//
|
||||||
|
// public override Task<DeckShuffleReply> DeckShuffle(DeckShuffleRequest request, ServerCallContext context)
|
||||||
|
// {
|
||||||
|
// _decks.AddOrUpdate(request.Id, new Deck(), (key, old) => new Deck());
|
||||||
|
// return Task.FromResult(new DeckShuffleReply { });
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public override Task<DeckDrawReply> DeckDraw(DeckDrawRequest request, ServerCallContext context)
|
||||||
|
// {
|
||||||
|
// if (request.Count < 1 || request.Count > 10)
|
||||||
|
// throw new ArgumentOutOfRangeException(nameof(request.Id));
|
||||||
|
//
|
||||||
|
// var deck = request.UseNew
|
||||||
|
// ? new Deck()
|
||||||
|
// : _decks.GetOrAdd(request.Id, new Deck());
|
||||||
|
//
|
||||||
|
// var list = new List<Deck.Card>(request.Count);
|
||||||
|
// for (int i = 0; i < request.Count; i++)
|
||||||
|
// {
|
||||||
|
// var card = deck.DrawNoRestart();
|
||||||
|
// if (card is null)
|
||||||
|
// {
|
||||||
|
// if (i == 0)
|
||||||
|
// {
|
||||||
|
// deck.Restart();
|
||||||
|
// list.Add(deck.DrawNoRestart());
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// list.Add(card);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // todo 3.2 should replace all "placeholder" words in command strings with a link to the placeholder list explanation
|
||||||
|
// var cards = list
|
||||||
|
// .Select(x => new Card
|
||||||
|
// {
|
||||||
|
// Name = x.ToString().ToLowerInvariant().Replace(' ', '_'),
|
||||||
|
// Number = x.Number,
|
||||||
|
// Suit = (CardSuit) x.Suit
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// var toReturn = new DeckDrawReply();
|
||||||
|
// toReturn.Cards.AddRange(cards);
|
||||||
|
//
|
||||||
|
// return Task.FromResult(toReturn);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public override async Task<RpsReply> Rps(RpsRequest request, ServerCallContext context)
|
||||||
|
// {
|
||||||
|
// if (request.Amount > 0)
|
||||||
|
// {
|
||||||
|
// var res = await _currency.TransferCurrencyAsync(new TransferCurrencyRequest
|
||||||
|
// {
|
||||||
|
// Amount = request.Amount,
|
||||||
|
// FromId = request.UserId,
|
||||||
|
// Type = "rps",
|
||||||
|
// Subtype = "bet",
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// if (!res.Success)
|
||||||
|
// {
|
||||||
|
// return new RpsReply
|
||||||
|
// {
|
||||||
|
// Result = RpsReply.Types.ResultType.NotEnough
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// var botPick = _rng.Next(0, 3);
|
||||||
|
// var userPick = (int) request.Pick;
|
||||||
|
//
|
||||||
|
// if (botPick == userPick)
|
||||||
|
// {
|
||||||
|
// if (request.Amount > 0)
|
||||||
|
// {
|
||||||
|
// await _currency.GrantToUserAsync(new GrantToUserRequest
|
||||||
|
// {
|
||||||
|
// Amount = request.Amount,
|
||||||
|
// GranterId = 0,
|
||||||
|
// Type = "rps",
|
||||||
|
// Subtype = "draw",
|
||||||
|
// UserId = request.UserId,
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return new RpsReply
|
||||||
|
// {
|
||||||
|
// BotPick = (RpsPick) botPick,
|
||||||
|
// WonAmount = request.Amount,
|
||||||
|
// Result = RpsReply.Types.ResultType.Draw
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if ((botPick == 1 && userPick == 2) || (botPick == 2 && userPick == 0) || (botPick == 0 && userPick == 1))
|
||||||
|
// {
|
||||||
|
// if (request.Amount > 0)
|
||||||
|
// {
|
||||||
|
// await _currency.GrantToUserAsync(new GrantToUserRequest
|
||||||
|
// {
|
||||||
|
// Amount = (long) (request.Amount * 1.95f),
|
||||||
|
// GranterId = 0,
|
||||||
|
// Type = "rps",
|
||||||
|
// Subtype = "draw",
|
||||||
|
// UserId = request.UserId,
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return new RpsReply
|
||||||
|
// {
|
||||||
|
// BotPick = (RpsPick) botPick,
|
||||||
|
// WonAmount = (long) (request.Amount * 1.95f),
|
||||||
|
// Result = RpsReply.Types.ResultType.Won
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return new RpsReply
|
||||||
|
// {
|
||||||
|
// BotPick = (RpsPick) botPick,
|
||||||
|
// WonAmount = 0,
|
||||||
|
// Result = RpsReply.Types.ResultType.Lost
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
public partial class Gambling
|
public partial class Gambling
|
||||||
{
|
{
|
||||||
[Group]
|
[Group]
|
||||||
@@ -220,50 +564,50 @@ public partial class Gambling
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class SlotMachine
|
public sealed class SlotMachine
|
||||||
|
{
|
||||||
|
public const int MAX_VALUE = 5;
|
||||||
|
|
||||||
|
private static readonly List<Func<int[], int>> _winningCombos = new()
|
||||||
|
{
|
||||||
|
//three flowers
|
||||||
|
arr => arr.All(a => a == MAX_VALUE) ? 30 : 0,
|
||||||
|
//three of the same
|
||||||
|
arr => !arr.Any(a => a != arr[0]) ? 10 : 0,
|
||||||
|
//two flowers
|
||||||
|
arr => arr.Count(a => a == MAX_VALUE) == 2 ? 4 : 0,
|
||||||
|
//one flower
|
||||||
|
arr => arr.Any(a => a == MAX_VALUE) ? 1 : 0
|
||||||
|
};
|
||||||
|
|
||||||
|
public static SlotResult Pull()
|
||||||
|
{
|
||||||
|
var numbers = new int[3];
|
||||||
|
for (var i = 0; i < numbers.Length; i++)
|
||||||
|
numbers[i] = new NadekoRandom().Next(0, MAX_VALUE + 1);
|
||||||
|
var multi = 0;
|
||||||
|
foreach (var t in _winningCombos)
|
||||||
{
|
{
|
||||||
public const int MAX_VALUE = 5;
|
multi = t(numbers);
|
||||||
|
if (multi != 0)
|
||||||
private static readonly List<Func<int[], int>> _winningCombos = new()
|
break;
|
||||||
{
|
|
||||||
//three flowers
|
|
||||||
arr => arr.All(a => a == MAX_VALUE) ? 30 : 0,
|
|
||||||
//three of the same
|
|
||||||
arr => !arr.Any(a => a != arr[0]) ? 10 : 0,
|
|
||||||
//two flowers
|
|
||||||
arr => arr.Count(a => a == MAX_VALUE) == 2 ? 4 : 0,
|
|
||||||
//one flower
|
|
||||||
arr => arr.Any(a => a == MAX_VALUE) ? 1 : 0
|
|
||||||
};
|
|
||||||
|
|
||||||
public static SlotResult Pull()
|
|
||||||
{
|
|
||||||
var numbers = new int[3];
|
|
||||||
for (var i = 0; i < numbers.Length; i++)
|
|
||||||
numbers[i] = new NadekoRandom().Next(0, MAX_VALUE + 1);
|
|
||||||
var multi = 0;
|
|
||||||
foreach (var t in _winningCombos)
|
|
||||||
{
|
|
||||||
multi = t(numbers);
|
|
||||||
if (multi != 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new(numbers, multi);
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct SlotResult
|
|
||||||
{
|
|
||||||
public int[] Numbers { get; }
|
|
||||||
public int Multiplier { get; }
|
|
||||||
|
|
||||||
public SlotResult(int[] nums, int multi)
|
|
||||||
{
|
|
||||||
Numbers = nums;
|
|
||||||
Multiplier = multi;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new(numbers, multi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct SlotResult
|
||||||
|
{
|
||||||
|
public int[] Numbers { get; }
|
||||||
|
public int Multiplier { get; }
|
||||||
|
|
||||||
|
public SlotResult(int[] nums, int multi)
|
||||||
|
{
|
||||||
|
Numbers = nums;
|
||||||
|
Multiplier = multi;
|
||||||
}
|
}
|
||||||
}
|
}
|
35
src/NadekoBot/Modules/Gambling/Wheel/WheelOfFortune.cs
Normal file
35
src/NadekoBot/Modules/Gambling/Wheel/WheelOfFortune.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#nullable disable
|
||||||
|
namespace NadekoBot.Modules.Gambling.WheelOfFortune;
|
||||||
|
|
||||||
|
public sealed class WheelOfFortuneGame
|
||||||
|
{
|
||||||
|
public static IReadOnlyList<decimal> DEFAULT_MULTIPLIERS = new[] { 1.7M, 1.5M, 0.2M, 0.1M, 0.3M, 0.5M, 1.2M, 2.4M };
|
||||||
|
|
||||||
|
private readonly IReadOnlyList<decimal> _multipliers;
|
||||||
|
private readonly NadekoRandom _rng;
|
||||||
|
|
||||||
|
public WheelOfFortuneGame(IReadOnlyList<decimal> multipliers)
|
||||||
|
{
|
||||||
|
_multipliers = multipliers;
|
||||||
|
_rng = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public WheelOfFortuneGame() : this(DEFAULT_MULTIPLIERS)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public WofResult Spin(long bet)
|
||||||
|
{
|
||||||
|
var result = _rng.Next(0, _multipliers.Count);
|
||||||
|
|
||||||
|
var multi = _multipliers[result];
|
||||||
|
var amount = (long)(bet * multi);
|
||||||
|
|
||||||
|
return new()
|
||||||
|
{
|
||||||
|
Index = result,
|
||||||
|
Multiplier = multi,
|
||||||
|
Amount = amount
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
9
src/NadekoBot/Modules/Gambling/Wheel/WofResult.cs
Normal file
9
src/NadekoBot/Modules/Gambling/Wheel/WofResult.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#nullable disable
|
||||||
|
namespace NadekoBot.Modules.Gambling.WheelOfFortune;
|
||||||
|
|
||||||
|
public readonly struct WofResult
|
||||||
|
{
|
||||||
|
public int Index { get; init; }
|
||||||
|
public decimal Multiplier { get; init; }
|
||||||
|
public long Amount { get; init; }
|
||||||
|
}
|
@@ -1,46 +0,0 @@
|
|||||||
#nullable disable
|
|
||||||
namespace NadekoBot.Modules.Gambling.Common.WheelOfFortune;
|
|
||||||
|
|
||||||
public class WheelOfFortuneGame
|
|
||||||
{
|
|
||||||
private readonly NadekoRandom _rng;
|
|
||||||
private readonly ICurrencyService _cs;
|
|
||||||
private readonly long _bet;
|
|
||||||
private readonly GamblingConfig _config;
|
|
||||||
private readonly ulong _userId;
|
|
||||||
|
|
||||||
public WheelOfFortuneGame(
|
|
||||||
ulong userId,
|
|
||||||
long bet,
|
|
||||||
GamblingConfig config,
|
|
||||||
ICurrencyService cs)
|
|
||||||
{
|
|
||||||
_rng = new();
|
|
||||||
_cs = cs;
|
|
||||||
_bet = bet;
|
|
||||||
_config = config;
|
|
||||||
_userId = userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Result> SpinAsync()
|
|
||||||
{
|
|
||||||
var result = _rng.Next(0, _config.WheelOfFortune.Multipliers.Length);
|
|
||||||
|
|
||||||
var amount = (long)(_bet * _config.WheelOfFortune.Multipliers[result]);
|
|
||||||
|
|
||||||
if (amount > 0)
|
|
||||||
await _cs.AddAsync(_userId, amount, new("wheel", "win"));
|
|
||||||
|
|
||||||
return new()
|
|
||||||
{
|
|
||||||
Index = result,
|
|
||||||
Amount = amount
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Result
|
|
||||||
{
|
|
||||||
public int Index { get; set; }
|
|
||||||
public long Amount { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -6,7 +6,7 @@ public class Betroll
|
|||||||
private readonly IOrderedEnumerable<BetRollPair> _thresholdPairs;
|
private readonly IOrderedEnumerable<BetRollPair> _thresholdPairs;
|
||||||
private readonly Random _rng;
|
private readonly Random _rng;
|
||||||
|
|
||||||
public Betroll(BetRollConfig settings)
|
public Betroll(IReadOnlyList<long> pairs)
|
||||||
{
|
{
|
||||||
_thresholdPairs = settings.Pairs.OrderByDescending(x => x.WhenAbove);
|
_thresholdPairs = settings.Pairs.OrderByDescending(x => x.WhenAbove);
|
||||||
_rng = new();
|
_rng = new();
|
||||||
|
Reference in New Issue
Block a user