.rafflecur added
This commit is contained in:
parent
cfee252ce3
commit
204cdbfb2b
@ -1,34 +1,85 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using NadekoBot.Common;
|
using NadekoBot.Common;
|
||||||
using NadekoBot.Core.Services;
|
using NLog;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NadekoBot.Core.Modules.Gambling.Common
|
namespace NadekoBot.Core.Modules.Gambling.Common
|
||||||
{
|
{
|
||||||
public class CurrencyRaffleGame
|
public class CurrencyRaffleGame
|
||||||
{
|
{
|
||||||
private readonly HashSet<IUser> _users = new HashSet<IUser>();
|
public enum Type {
|
||||||
public IEnumerable<IUser> Users => _users;
|
Mixed,
|
||||||
private readonly int _amount;
|
Normal
|
||||||
|
|
||||||
public CurrencyRaffleGame(int amount)
|
|
||||||
{
|
|
||||||
if (amount < 1)
|
|
||||||
throw new ArgumentOutOfRangeException();
|
|
||||||
|
|
||||||
_amount = amount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
return false;
|
||||||
|
|
||||||
|
if (!_users.Add(new User
|
||||||
|
{
|
||||||
|
DiscordUser = usr,
|
||||||
|
Amount = amount,
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
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 NadekoBot.Core.Modules.Gambling.Services;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using System;
|
|
||||||
using NadekoBot.Core.Services;
|
using NadekoBot.Core.Services;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
|
using System.Linq;
|
||||||
|
using Discord.Commands;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Gambling
|
namespace NadekoBot.Modules.Gambling
|
||||||
{
|
{
|
||||||
@ -18,28 +19,42 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
{
|
{
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum Mixed { Mixed }
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[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)
|
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,
|
var res = await _service.JoinOrCreateGame(Context.Channel.Id,
|
||||||
Context.User, amount, OnEnded)
|
Context.User, amount, mixed, OnEnded)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
if (res.Item1 != null)
|
if (res.Item1 != null)
|
||||||
{
|
{
|
||||||
await Context.Channel.SendConfirmAsync(GetText("rafflecur_joined", Context.User.ToString()),
|
await Context.Channel.SendConfirmAsync(GetText("rafflecur", res.Item1.GameType.ToString()),
|
||||||
string.Join("\n", res.Item1.Users)).ConfigureAwait(false);
|
string.Join("\n", res.Item1.Users.Select(x => $"{x.DiscordUser} ({x.Amount})")),
|
||||||
|
footer: GetText("rafflecur_joined", Context.User.ToString())).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (res.Item2 == CurrencyRaffleService.JoinErrorType.AlreadyJoined)
|
if (res.Item2 == CurrencyRaffleService.JoinErrorType.AlreadyJoinedOrInvalidAmount)
|
||||||
await ReplyErrorLocalized("rafflecur_already_joined").ConfigureAwait(false);
|
await ReplyErrorLocalized("rafflecur_already_joined").ConfigureAwait(false);
|
||||||
else if (res.Item2 == CurrencyRaffleService.JoinErrorType.NotEnoughCurrency)
|
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 NadekoBot.Core.Modules.Gambling.Common;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NadekoBot.Common;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Discord;
|
using Discord;
|
||||||
using System;
|
using System;
|
||||||
@ -12,9 +11,10 @@ namespace NadekoBot.Core.Modules.Gambling.Services
|
|||||||
{
|
{
|
||||||
public class CurrencyRaffleService : INService
|
public class CurrencyRaffleService : INService
|
||||||
{
|
{
|
||||||
public enum JoinErrorType {
|
public enum JoinErrorType
|
||||||
|
{
|
||||||
NotEnoughCurrency,
|
NotEnoughCurrency,
|
||||||
AlreadyJoined
|
AlreadyJoinedOrInvalidAmount
|
||||||
}
|
}
|
||||||
private readonly SemaphoreSlim _locker = new SemaphoreSlim(1, 1);
|
private readonly SemaphoreSlim _locker = new SemaphoreSlim(1, 1);
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
@ -28,7 +28,7 @@ namespace NadekoBot.Core.Modules.Gambling.Services
|
|||||||
_cs = cs;
|
_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);
|
await _locker.WaitAsync().ConfigureAwait(false);
|
||||||
try
|
try
|
||||||
@ -37,7 +37,10 @@ namespace NadekoBot.Core.Modules.Gambling.Services
|
|||||||
if (!Games.TryGetValue(channelId, out var crg))
|
if (!Games.TryGetValue(channelId, out var crg))
|
||||||
{
|
{
|
||||||
newGame = true;
|
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)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
@ -45,40 +48,43 @@ namespace NadekoBot.Core.Modules.Gambling.Services
|
|||||||
// user created it and doesn't have the money
|
// user created it and doesn't have the money
|
||||||
if (!await _cs.RemoveAsync(user.Id, "Currency Raffle Join", amount, uow).ConfigureAwait(false))
|
if (!await _cs.RemoveAsync(user.Id, "Currency Raffle Join", amount, uow).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
if(newGame)
|
if (newGame)
|
||||||
Games.Remove(channelId);
|
Games.Remove(channelId);
|
||||||
return (null, JoinErrorType.NotEnoughCurrency);
|
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);
|
await _cs.AddAsync(user.Id, "Curency Raffle Refund", amount, uow).ConfigureAwait(false);
|
||||||
return (null, JoinErrorType.AlreadyJoined);
|
return (null, JoinErrorType.AlreadyJoinedOrInvalidAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uow.Complete();
|
||||||
}
|
}
|
||||||
if (newGame)
|
if (newGame)
|
||||||
{
|
{
|
||||||
var _t = new Timer(async state =>
|
var _t = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
|
await Task.Delay(30000).ConfigureAwait(false);
|
||||||
await _locker.WaitAsync().ConfigureAwait(false);
|
await _locker.WaitAsync().ConfigureAwait(false);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var users = crg.Users.ToArray();
|
var winner = crg.GetWinner();
|
||||||
var rng = new NadekoRandom();
|
var won = crg.Users.Sum(x => x.Amount);
|
||||||
var usr = users[rng.Next(0, users.Length)];
|
|
||||||
|
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
await _cs.AddAsync(usr.Id, "Currency Raffle Win",
|
await _cs.AddAsync(winner.DiscordUser.Id, "Currency Raffle Win",
|
||||||
amount * users.Length, uow);
|
won, uow);
|
||||||
|
|
||||||
|
uow.Complete();
|
||||||
}
|
}
|
||||||
Games.Remove(channelId, out _);
|
Games.Remove(channelId, out _);
|
||||||
var oe = onEnded(usr, users.Length * amount);
|
var oe = onEnded(winner.DiscordUser, won);
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
finally { _locker.Release(); }
|
finally { _locker.Release(); }
|
||||||
|
});
|
||||||
}, null, 30000, Timeout.Infinite);
|
|
||||||
}
|
}
|
||||||
return (crg, null);
|
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)
|
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);
|
await ReplyErrorLocalized("poll_already_running").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,8 +53,6 @@ namespace NadekoBot.Modules.Games
|
|||||||
_service.ActivePolls.TryRemove(channel.Guild.Id, out var poll);
|
_service.ActivePolls.TryRemove(channel.Guild.Id, out var poll);
|
||||||
await poll.StopPoll().ConfigureAwait(false);
|
await poll.StopPoll().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,7 +26,7 @@ namespace NadekoBot.Modules.Games.Services
|
|||||||
_strings = strings;
|
_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(";"))
|
if (string.IsNullOrWhiteSpace(arg) || !arg.Contains(";"))
|
||||||
return null;
|
return null;
|
||||||
@ -35,7 +35,7 @@ namespace NadekoBot.Modules.Games.Services
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
var poll = new Poll(_client, _strings, msg, data[0], data.Skip(1));
|
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) =>
|
poll.OnEnded += (gid) =>
|
||||||
{
|
{
|
||||||
|
@ -24,13 +24,17 @@ namespace NadekoBot.Modules.Utility
|
|||||||
private readonly IStatsService _stats;
|
private readonly IStatsService _stats;
|
||||||
private readonly IBotCredentials _creds;
|
private readonly IBotCredentials _creds;
|
||||||
private readonly NadekoBot _bot;
|
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;
|
_client = client;
|
||||||
_stats = stats;
|
_stats = stats;
|
||||||
_creds = creds;
|
_creds = creds;
|
||||||
_bot = nadeko;
|
_bot = nadeko;
|
||||||
|
_db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
using StackExchange.Redis;
|
using StackExchange.Redis;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Core.Services
|
namespace NadekoBot.Core.Services
|
||||||
|
@ -885,7 +885,8 @@
|
|||||||
"customreactions_edit_fail": "Custom reaction with that ID does not exist.",
|
"customreactions_edit_fail": "Custom reaction with that ID does not exist.",
|
||||||
"searches_streaming": "Streaming",
|
"searches_streaming": "Streaming",
|
||||||
"searches_followers": "Followers",
|
"searches_followers": "Followers",
|
||||||
"gambling_rafflecur_joined": "User {0} joined the raffle!",
|
"gambling_rafflecur": "{0} Currency Raffle",
|
||||||
"gambling_rafflecur_already_joined": "You have already joined this raffle.",
|
"gambling_rafflecur_joined": "User {0} joined the raffle",
|
||||||
|
"gambling_rafflecur_already_joined": "You have already joined this raffle or the value you used is not valid.",
|
||||||
"gambling_rafflecur_ended": "{0} raffle ended. {1} won {2}!"
|
"gambling_rafflecur_ended": "{0} raffle ended. {1} won {2}!"
|
||||||
}
|
}
|
@ -3040,9 +3040,10 @@
|
|||||||
},
|
},
|
||||||
"rafflecur": {
|
"rafflecur": {
|
||||||
"cmd": "rafflecur",
|
"cmd": "rafflecur",
|
||||||
"desc": "Starts a currency raffle with a specified amount. Users who join the raffle will lose the amount of currency specified and add it to the pot. After 30 seconds, random winner will be selected who will receive the whole pot.",
|
"desc": "Starts or joins a currency raffle with a specified amount. Users who join the raffle will lose the amount of currency specified and add it to the pot. After 30 seconds, random winner will be selected who will receive the whole pot. There is also a `mixed` mode in which the users will be able to join the game with any amount of currency, and have their chances be proportional to the amount they've bet.",
|
||||||
"usage": [
|
"usage": [
|
||||||
"{0}rafflecur 20"
|
"{0}rafflecur 20",
|
||||||
|
"{0}rafflecur mixed 15"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user