.rafflecur added
This commit is contained in:
@ -1,34 +1,85 @@
|
||||
using Discord;
|
||||
using NadekoBot.Common;
|
||||
using NadekoBot.Core.Services;
|
||||
using System;
|
||||
using NLog;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Core.Modules.Gambling.Common
|
||||
{
|
||||
public class CurrencyRaffleGame
|
||||
{
|
||||
private readonly HashSet<IUser> _users = new HashSet<IUser>();
|
||||
public IEnumerable<IUser> Users => _users;
|
||||
private readonly int _amount;
|
||||
|
||||
public CurrencyRaffleGame(int amount)
|
||||
{
|
||||
if (amount < 1)
|
||||
throw new ArgumentOutOfRangeException();
|
||||
|
||||
_amount = amount;
|
||||
public enum Type {
|
||||
Mixed,
|
||||
Normal
|
||||
}
|
||||
|
||||
public bool AddUser(IUser usr)
|
||||
public class User
|
||||
{
|
||||
if (!_users.Add(usr))
|
||||
public IUser DiscordUser { get; set; }
|
||||
public int Amount { get; set; }
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return DiscordUser.GetHashCode();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is User u
|
||||
? u.DiscordUser == DiscordUser
|
||||
: false;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly HashSet<User> _users = new HashSet<User>();
|
||||
public IEnumerable<User> Users => _users;
|
||||
public Type GameType { get; }
|
||||
private readonly Logger _log;
|
||||
|
||||
public CurrencyRaffleGame(Type type)
|
||||
{
|
||||
GameType = type;
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
}
|
||||
|
||||
public bool AddUser(IUser usr, int amount)
|
||||
{
|
||||
// if game type is normal, and someone already joined the game
|
||||
// (that's the user who created it)
|
||||
if (GameType == Type.Normal && _users.Count > 0 &&
|
||||
_users.First().Amount != amount)
|
||||
return false;
|
||||
|
||||
if (!_users.Add(new User
|
||||
{
|
||||
DiscordUser = usr,
|
||||
Amount = amount,
|
||||
}))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public User GetWinner()
|
||||
{
|
||||
var rng = new NadekoRandom();
|
||||
if (GameType == Type.Mixed)
|
||||
{
|
||||
var num = rng.Next(0, Users.Sum(x => x.Amount));
|
||||
var sum = 0;
|
||||
foreach (var u in Users)
|
||||
{
|
||||
sum += u.Amount;
|
||||
if (sum > num)
|
||||
return u;
|
||||
}
|
||||
_log.Error("Woah. Report this.\nRoll: {0}\nAmounts: {1}", num, string.Join(",", Users.Select(x => x.Amount)));
|
||||
}
|
||||
|
||||
var usrs = _users.ToArray();
|
||||
return usrs[rng.Next(0, usrs.Length)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,10 @@
|
||||
using NadekoBot.Core.Modules.Gambling.Services;
|
||||
using System.Threading.Tasks;
|
||||
using Discord;
|
||||
using System;
|
||||
using NadekoBot.Core.Services;
|
||||
using NadekoBot.Extensions;
|
||||
using System.Linq;
|
||||
using Discord.Commands;
|
||||
|
||||
namespace NadekoBot.Modules.Gambling
|
||||
{
|
||||
@ -18,28 +19,42 @@ namespace NadekoBot.Modules.Gambling
|
||||
{
|
||||
_bc = bc;
|
||||
}
|
||||
|
||||
public enum Mixed { Mixed }
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
public async Task RaffleCur(int amount)
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[Priority(0)]
|
||||
public Task RaffleCur(Mixed _, int amount) =>
|
||||
RaffleCur(amount, true);
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[Priority(1)]
|
||||
public async Task RaffleCur(int amount, bool mixed = false)
|
||||
{
|
||||
if (amount < 1)
|
||||
return;
|
||||
async Task OnEnded(IUser arg, int won)
|
||||
{
|
||||
await ReplyConfirmLocalized("rafflecur_ended", _bc.BotConfig.CurrencyName, Format.Bold(arg.ToString()), won + _bc.BotConfig.CurrencySign);
|
||||
await Context.Channel.SendConfirmAsync(GetText("rafflecur_ended", _bc.BotConfig.CurrencyName, Format.Bold(arg.ToString()), won + _bc.BotConfig.CurrencySign));
|
||||
}
|
||||
var res = await _service.JoinOrCreateGame(Context.Channel.Id,
|
||||
Context.User, amount, OnEnded)
|
||||
Context.User, amount, mixed, OnEnded)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (res.Item1 != null)
|
||||
{
|
||||
await Context.Channel.SendConfirmAsync(GetText("rafflecur_joined", Context.User.ToString()),
|
||||
string.Join("\n", res.Item1.Users)).ConfigureAwait(false);
|
||||
await Context.Channel.SendConfirmAsync(GetText("rafflecur", res.Item1.GameType.ToString()),
|
||||
string.Join("\n", res.Item1.Users.Select(x => $"{x.DiscordUser} ({x.Amount})")),
|
||||
footer: GetText("rafflecur_joined", Context.User.ToString())).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (res.Item2 == CurrencyRaffleService.JoinErrorType.AlreadyJoined)
|
||||
if (res.Item2 == CurrencyRaffleService.JoinErrorType.AlreadyJoinedOrInvalidAmount)
|
||||
await ReplyErrorLocalized("rafflecur_already_joined").ConfigureAwait(false);
|
||||
else if (res.Item2 == CurrencyRaffleService.JoinErrorType.NotEnoughCurrency)
|
||||
await ReplyErrorLocalized("not_enough").ConfigureAwait(false);
|
||||
await ReplyErrorLocalized("not_enough", _bc.BotConfig.CurrencySign).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ using NadekoBot.Core.Services;
|
||||
using NadekoBot.Core.Modules.Gambling.Common;
|
||||
using System.Threading;
|
||||
using System.Linq;
|
||||
using NadekoBot.Common;
|
||||
using System.Collections.Generic;
|
||||
using Discord;
|
||||
using System;
|
||||
@ -12,9 +11,10 @@ namespace NadekoBot.Core.Modules.Gambling.Services
|
||||
{
|
||||
public class CurrencyRaffleService : INService
|
||||
{
|
||||
public enum JoinErrorType {
|
||||
public enum JoinErrorType
|
||||
{
|
||||
NotEnoughCurrency,
|
||||
AlreadyJoined
|
||||
AlreadyJoinedOrInvalidAmount
|
||||
}
|
||||
private readonly SemaphoreSlim _locker = new SemaphoreSlim(1, 1);
|
||||
private readonly DbService _db;
|
||||
@ -28,7 +28,7 @@ namespace NadekoBot.Core.Modules.Gambling.Services
|
||||
_cs = cs;
|
||||
}
|
||||
|
||||
public async Task<(CurrencyRaffleGame, JoinErrorType?)> JoinOrCreateGame(ulong channelId, IUser user, int amount, Func<IUser, int, Task> onEnded)
|
||||
public async Task<(CurrencyRaffleGame, JoinErrorType?)> JoinOrCreateGame(ulong channelId, IUser user, int amount, bool mixed, Func<IUser, int, Task> onEnded)
|
||||
{
|
||||
await _locker.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
@ -37,7 +37,10 @@ namespace NadekoBot.Core.Modules.Gambling.Services
|
||||
if (!Games.TryGetValue(channelId, out var crg))
|
||||
{
|
||||
newGame = true;
|
||||
crg = new CurrencyRaffleGame(amount);
|
||||
crg = new CurrencyRaffleGame(mixed
|
||||
? CurrencyRaffleGame.Type.Mixed
|
||||
: CurrencyRaffleGame.Type.Normal);
|
||||
Games.Add(channelId, crg);
|
||||
}
|
||||
using (var uow = _db.UnitOfWork)
|
||||
{
|
||||
@ -45,40 +48,43 @@ namespace NadekoBot.Core.Modules.Gambling.Services
|
||||
// user created it and doesn't have the money
|
||||
if (!await _cs.RemoveAsync(user.Id, "Currency Raffle Join", amount, uow).ConfigureAwait(false))
|
||||
{
|
||||
if(newGame)
|
||||
if (newGame)
|
||||
Games.Remove(channelId);
|
||||
return (null, JoinErrorType.NotEnoughCurrency);
|
||||
}
|
||||
|
||||
if (!crg.AddUser(user))
|
||||
if (!crg.AddUser(user, amount))
|
||||
{
|
||||
await _cs.AddAsync(user.Id, "Curency Raffle Refund", amount, uow).ConfigureAwait(false);
|
||||
return (null, JoinErrorType.AlreadyJoined);
|
||||
return (null, JoinErrorType.AlreadyJoinedOrInvalidAmount);
|
||||
}
|
||||
|
||||
uow.Complete();
|
||||
}
|
||||
if (newGame)
|
||||
{
|
||||
var _t = new Timer(async state =>
|
||||
var _t = Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(30000).ConfigureAwait(false);
|
||||
await _locker.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
var users = crg.Users.ToArray();
|
||||
var rng = new NadekoRandom();
|
||||
var usr = users[rng.Next(0, users.Length)];
|
||||
var winner = crg.GetWinner();
|
||||
var won = crg.Users.Sum(x => x.Amount);
|
||||
|
||||
using (var uow = _db.UnitOfWork)
|
||||
{
|
||||
await _cs.AddAsync(usr.Id, "Currency Raffle Win",
|
||||
amount * users.Length, uow);
|
||||
await _cs.AddAsync(winner.DiscordUser.Id, "Currency Raffle Win",
|
||||
won, uow);
|
||||
|
||||
uow.Complete();
|
||||
}
|
||||
Games.Remove(channelId, out _);
|
||||
var oe = onEnded(usr, users.Length * amount);
|
||||
var oe = onEnded(winner.DiscordUser, won);
|
||||
}
|
||||
catch { }
|
||||
finally { _locker.Release(); }
|
||||
|
||||
}, null, 30000, Timeout.Infinite);
|
||||
});
|
||||
}
|
||||
return (crg, null);
|
||||
}
|
||||
@ -88,4 +94,4 @@ namespace NadekoBot.Core.Modules.Gambling.Services
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -39,7 +39,7 @@ namespace NadekoBot.Modules.Games
|
||||
|
||||
private async Task InternalStartPoll(string arg)
|
||||
{
|
||||
if(await _service.StartPoll((ITextChannel)Context.Channel, Context.Message, arg) == false)
|
||||
if(await _service.StartPoll(Context.Channel.Id, Context.Message, arg) == false)
|
||||
await ReplyErrorLocalized("poll_already_running").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@ -53,8 +53,6 @@ namespace NadekoBot.Modules.Games
|
||||
_service.ActivePolls.TryRemove(channel.Guild.Id, out var poll);
|
||||
await poll.StopPoll().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -26,7 +26,7 @@ namespace NadekoBot.Modules.Games.Services
|
||||
_strings = strings;
|
||||
}
|
||||
|
||||
public async Task<bool?> StartPoll(ITextChannel channel, IUserMessage msg, string arg)
|
||||
public async Task<bool?> StartPoll(ulong guildId, IUserMessage msg, string arg)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(arg) || !arg.Contains(";"))
|
||||
return null;
|
||||
@ -35,7 +35,7 @@ namespace NadekoBot.Modules.Games.Services
|
||||
return null;
|
||||
|
||||
var poll = new Poll(_client, _strings, msg, data[0], data.Skip(1));
|
||||
if (ActivePolls.TryAdd(channel.Guild.Id, poll))
|
||||
if (ActivePolls.TryAdd(guildId, poll))
|
||||
{
|
||||
poll.OnEnded += (gid) =>
|
||||
{
|
||||
|
@ -24,13 +24,17 @@ namespace NadekoBot.Modules.Utility
|
||||
private readonly IStatsService _stats;
|
||||
private readonly IBotCredentials _creds;
|
||||
private readonly NadekoBot _bot;
|
||||
private readonly DbService _db;
|
||||
|
||||
public Utility(NadekoBot nadeko, DiscordSocketClient client, IStatsService stats, IBotCredentials creds)
|
||||
public Utility(NadekoBot nadeko, DiscordSocketClient client,
|
||||
IStatsService stats, IBotCredentials creds,
|
||||
DbService db)
|
||||
{
|
||||
_client = client;
|
||||
_stats = stats;
|
||||
_creds = creds;
|
||||
_bot = nadeko;
|
||||
_db = db;
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
|
Reference in New Issue
Block a user