NadekoBot/NadekoBot.Core/Modules/Gambling/Services/CurrencyRaffleService.cs

97 lines
3.5 KiB
C#
Raw Normal View History

2017-10-19 12:10:22 +00:00
using System.Threading.Tasks;
using NadekoBot.Core.Services;
using NadekoBot.Core.Modules.Gambling.Common;
using System.Threading;
2017-10-20 03:55:14 +00:00
using System.Linq;
using System.Collections.Generic;
using Discord;
using System;
2017-10-19 12:10:22 +00:00
namespace NadekoBot.Core.Modules.Gambling.Services
{
public class CurrencyRaffleService : INService
{
2017-10-20 15:20:26 +00:00
public enum JoinErrorType
{
2017-10-20 03:55:14 +00:00
NotEnoughCurrency,
2017-10-20 15:20:26 +00:00
AlreadyJoinedOrInvalidAmount
2017-10-20 03:55:14 +00:00
}
2017-10-19 12:10:22 +00:00
private readonly SemaphoreSlim _locker = new SemaphoreSlim(1, 1);
private readonly DbService _db;
2017-10-20 03:55:14 +00:00
private readonly CurrencyService _cs;
2017-10-19 12:10:22 +00:00
2017-10-20 03:55:14 +00:00
public Dictionary<ulong, CurrencyRaffleGame> Games { get; } = new Dictionary<ulong, CurrencyRaffleGame>();
2017-10-19 12:10:22 +00:00
2017-10-20 03:55:14 +00:00
public CurrencyRaffleService(DbService db, CurrencyService cs)
2017-10-19 12:10:22 +00:00
{
_db = db;
2017-10-20 03:55:14 +00:00
_cs = cs;
2017-10-19 12:10:22 +00:00
}
2017-10-20 15:20:26 +00:00
public async Task<(CurrencyRaffleGame, JoinErrorType?)> JoinOrCreateGame(ulong channelId, IUser user, int amount, bool mixed, Func<IUser, int, Task> onEnded)
2017-10-19 12:10:22 +00:00
{
await _locker.WaitAsync().ConfigureAwait(false);
try
{
2017-10-20 03:55:14 +00:00
var newGame = false;
if (!Games.TryGetValue(channelId, out var crg))
{
newGame = true;
2017-10-20 15:20:26 +00:00
crg = new CurrencyRaffleGame(mixed
? CurrencyRaffleGame.Type.Mixed
: CurrencyRaffleGame.Type.Normal);
Games.Add(channelId, crg);
2017-10-20 03:55:14 +00:00
}
2017-10-19 12:10:22 +00:00
using (var uow = _db.UnitOfWork)
{
2017-10-20 03:55:14 +00:00
//remove money, and stop the game if this
// user created it and doesn't have the money
if (!await _cs.RemoveAsync(user.Id, "Currency Raffle Join", amount, uow).ConfigureAwait(false))
{
2017-10-20 15:20:26 +00:00
if (newGame)
2017-10-20 03:55:14 +00:00
Games.Remove(channelId);
return (null, JoinErrorType.NotEnoughCurrency);
}
2017-10-20 15:20:26 +00:00
if (!crg.AddUser(user, amount))
2017-10-20 03:55:14 +00:00
{
await _cs.AddAsync(user.Id, "Curency Raffle Refund", amount, uow).ConfigureAwait(false);
2017-10-20 15:20:26 +00:00
return (null, JoinErrorType.AlreadyJoinedOrInvalidAmount);
2017-10-20 03:55:14 +00:00
}
2017-10-20 15:20:26 +00:00
uow.Complete();
2017-10-19 12:10:22 +00:00
}
2017-10-20 03:55:14 +00:00
if (newGame)
{
2017-10-20 15:20:26 +00:00
var _t = Task.Run(async () =>
2017-10-20 03:55:14 +00:00
{
2017-10-21 10:13:31 +00:00
await Task.Delay(60000).ConfigureAwait(false);
2017-10-20 03:55:14 +00:00
await _locker.WaitAsync().ConfigureAwait(false);
try
{
2017-10-20 15:20:26 +00:00
var winner = crg.GetWinner();
var won = crg.Users.Sum(x => x.Amount);
2017-10-20 03:55:14 +00:00
using (var uow = _db.UnitOfWork)
{
2017-10-20 15:20:26 +00:00
await _cs.AddAsync(winner.DiscordUser.Id, "Currency Raffle Win",
won, uow);
uow.Complete();
2017-10-20 03:55:14 +00:00
}
Games.Remove(channelId, out _);
2017-10-20 15:20:26 +00:00
var oe = onEnded(winner.DiscordUser, won);
2017-10-20 03:55:14 +00:00
}
catch { }
finally { _locker.Release(); }
2017-10-20 15:20:26 +00:00
});
2017-10-20 03:55:14 +00:00
}
return (crg, null);
2017-10-19 12:10:22 +00:00
}
finally
{
_locker.Release();
}
}
}
2017-10-20 15:20:26 +00:00
}