Currency Raffle almost done.

This commit is contained in:
Master Kwoth 2017-10-20 05:55:14 +02:00
parent fa0b9e4f80
commit cfee252ce3
5 changed files with 108 additions and 33 deletions

View File

@ -1,6 +1,9 @@
using NadekoBot.Core.Services; using Discord;
using NadekoBot.Common;
using NadekoBot.Core.Services;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -8,33 +11,24 @@ namespace NadekoBot.Core.Modules.Gambling.Common
{ {
public class CurrencyRaffleGame public class CurrencyRaffleGame
{ {
private readonly HashSet<(string, ulong)> _users = new HashSet<(string, ulong)>(); private readonly HashSet<IUser> _users = new HashSet<IUser>();
public IEnumerable<IUser> Users => _users;
private readonly int _amount; private readonly int _amount;
private readonly CurrencyService _cs;
private readonly DbService _db;
private bool running;
public CurrencyRaffleGame(int amount, CurrencyService cs, DbService db) public CurrencyRaffleGame(int amount)
{ {
if (amount < 1) if (amount < 1)
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
_amount = amount; _amount = amount;
_cs = cs;
_db = db;
} }
public async Task<bool> AddUser(string username, ulong userId) public bool AddUser(IUser usr)
{ {
if (!_users.Add(usr))
return false;
} return true;
public void ForceStop()
{
lock (_locker)
{
running = false;
}
} }
} }
} }

View File

@ -1,6 +1,10 @@
using NadekoBot.Common.Attributes; using NadekoBot.Common.Attributes;
using NadekoBot.Core.Modules.Gambling.Services; using NadekoBot.Core.Modules.Gambling.Services;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord;
using System;
using NadekoBot.Core.Services;
using NadekoBot.Extensions;
namespace NadekoBot.Modules.Gambling namespace NadekoBot.Modules.Gambling
{ {
@ -8,13 +12,34 @@ namespace NadekoBot.Modules.Gambling
{ {
public class CurrencyRaffleCommands : NadekoSubmodule<CurrencyRaffleService> public class CurrencyRaffleCommands : NadekoSubmodule<CurrencyRaffleService>
{ {
private readonly IBotConfigProvider _bc;
public CurrencyRaffleCommands(IBotConfigProvider bc)
{
_bc = bc;
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task RaffleCur(int amount) public async Task RaffleCur(int amount)
{ {
if (_service.Games.TryAdd(Context.Channel.Id, async Task OnEnded(IUser arg, int won)
))
{ {
await ReplyConfirmLocalized("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)
.ConfigureAwait(false);
if (res.Item1 != null)
{
await Context.Channel.SendConfirmAsync(GetText("rafflecur_joined", Context.User.ToString()),
string.Join("\n", res.Item1.Users)).ConfigureAwait(false);
}
else
{
if (res.Item2 == CurrencyRaffleService.JoinErrorType.AlreadyJoined)
await ReplyErrorLocalized("rafflecur_already_joined").ConfigureAwait(false);
else if (res.Item2 == CurrencyRaffleService.JoinErrorType.NotEnoughCurrency)
await ReplyErrorLocalized("not_enough").ConfigureAwait(false);
} }
} }
} }

View File

@ -1,40 +1,86 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Core.Services; using NadekoBot.Core.Services;
using System.Collections.Concurrent;
using NadekoBot.Core.Modules.Gambling.Common; using NadekoBot.Core.Modules.Gambling.Common;
using System.Threading; using System.Threading;
using System.Linq;
using NadekoBot.Common;
using System.Collections.Generic;
using Discord;
using System;
namespace NadekoBot.Core.Modules.Gambling.Services namespace NadekoBot.Core.Modules.Gambling.Services
{ {
public class CurrencyRaffleService : INService public class CurrencyRaffleService : INService
{ {
public enum JoinErrorType {
NotEnoughCurrency,
AlreadyJoined
}
private readonly SemaphoreSlim _locker = new SemaphoreSlim(1, 1); private readonly SemaphoreSlim _locker = new SemaphoreSlim(1, 1);
private readonly DbService _db; private readonly DbService _db;
private readonly CurrencyService _cs;
public ConcurrentDictionary<ulong, CurrencyRaffleGame> Games { get; } public Dictionary<ulong, CurrencyRaffleGame> Games { get; } = new Dictionary<ulong, CurrencyRaffleGame>();
public CurrencyRaffleService(DbService db) public CurrencyRaffleService(DbService db, CurrencyService cs)
{ {
_db = db; _db = db;
_cs = cs;
} }
public async Task JoinOrCreateGame(ulong channelId, string username, public async Task<(CurrencyRaffleGame, JoinErrorType?)> JoinOrCreateGame(ulong channelId, IUser user, int amount, Func<IUser, int, Task> onEnded)
ulong userId)
{ {
await _locker.WaitAsync().ConfigureAwait(false); await _locker.WaitAsync().ConfigureAwait(false);
try try
{ {
var newGame = false;
if (!Games.TryGetValue(channelId, out var crg))
{
newGame = true;
crg = new CurrencyRaffleGame(amount);
}
using (var uow = _db.UnitOfWork) using (var uow = _db.UnitOfWork)
{ {
//remove money //remove money, and stop the game if this
if (!await _cs.RemoveAsync(userId, "Currency Raffle Join", _amount).ConfigureAwait(false)) // user created it and doesn't have the money
return false; if (!await _cs.RemoveAsync(user.Id, "Currency Raffle Join", amount, uow).ConfigureAwait(false))
} {
if(newGame)
Games.Remove(channelId);
return (null, JoinErrorType.NotEnoughCurrency);
}
//add to to list if (!crg.AddUser(user))
if (_users.Add((username, userId))) {
return false; await _cs.AddAsync(user.Id, "Curency Raffle Refund", amount, uow).ConfigureAwait(false);
return true; return (null, JoinErrorType.AlreadyJoined);
}
}
if (newGame)
{
var _t = new Timer(async state =>
{
await _locker.WaitAsync().ConfigureAwait(false);
try
{
var users = crg.Users.ToArray();
var rng = new NadekoRandom();
var usr = users[rng.Next(0, users.Length)];
using (var uow = _db.UnitOfWork)
{
await _cs.AddAsync(usr.Id, "Currency Raffle Win",
amount * users.Length, uow);
}
Games.Remove(channelId, out _);
var oe = onEnded(usr, users.Length * amount);
}
catch { }
finally { _locker.Release(); }
}, null, 30000, Timeout.Infinite);
}
return (crg, null);
} }
finally finally
{ {

View File

@ -884,5 +884,8 @@
"administration_restarting": "Restarting.", "administration_restarting": "Restarting.",
"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_already_joined": "You have already joined this raffle.",
"gambling_rafflecur_ended": "{0} raffle ended. {1} won {2}!"
} }

View File

@ -3037,5 +3037,12 @@
"usage": [ "usage": [
"{0}execsql UPDATE Currency SET Amount=Amount+1234" "{0}execsql UPDATE Currency SET Amount=Amount+1234"
] ]
},
"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.",
"usage": [
"{0}rafflecur 20"
]
} }
} }