176 lines
5.6 KiB
C#
176 lines
5.6 KiB
C#
using Discord.Commands;
|
|
using System;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace NadekoBot.Classes.ClashOfClans
|
|
{
|
|
internal class Caller
|
|
{
|
|
public string CallUser { get; }
|
|
|
|
public DateTime TimeAdded { get; private set; }
|
|
|
|
public bool BaseDestroyed { get; internal set; }
|
|
|
|
public Caller(string callUser, DateTime timeAdded, bool baseDestroyed)
|
|
{
|
|
CallUser = callUser;
|
|
TimeAdded = timeAdded;
|
|
BaseDestroyed = baseDestroyed;
|
|
}
|
|
|
|
public void ResetTime()
|
|
{
|
|
TimeAdded = DateTime.Now;
|
|
}
|
|
|
|
public void Destroy()
|
|
{
|
|
BaseDestroyed = true;
|
|
}
|
|
}
|
|
|
|
internal class ClashWar
|
|
{
|
|
private static TimeSpan callExpire => new TimeSpan(2, 0, 0);
|
|
|
|
private CommandEventArgs e;
|
|
public string EnemyClan { get; }
|
|
public int Size { get; }
|
|
|
|
private Caller[] bases { get; }
|
|
private CancellationTokenSource[] baseCancelTokens;
|
|
private CancellationTokenSource endTokenSource { get; } = new CancellationTokenSource();
|
|
public event Action<string> OnUserTimeExpired = delegate { };
|
|
public event Action OnWarEnded = delegate { };
|
|
public bool Started { get; set; } = false;
|
|
|
|
public ClashWar(string enemyClan, int size, CommandEventArgs e)
|
|
{
|
|
this.EnemyClan = enemyClan;
|
|
this.Size = size;
|
|
this.bases = new Caller[size];
|
|
this.baseCancelTokens = new CancellationTokenSource[size];
|
|
}
|
|
|
|
internal void End()
|
|
{
|
|
if (endTokenSource.Token.IsCancellationRequested) return;
|
|
endTokenSource.Cancel();
|
|
OnWarEnded();
|
|
}
|
|
|
|
internal void Call(string u, int baseNumber)
|
|
{
|
|
if (baseNumber < 0 || baseNumber >= bases.Length)
|
|
throw new ArgumentException("Invalid base number");
|
|
if (bases[baseNumber] != null)
|
|
throw new ArgumentException("That base is already claimed.");
|
|
for (var i = 0; i < bases.Length; i++)
|
|
{
|
|
if (bases[i]?.BaseDestroyed == false && bases[i]?.CallUser == u)
|
|
throw new ArgumentException($"@{u} You already claimed a base #{i + 1}. You can't claim a new one.");
|
|
}
|
|
|
|
bases[baseNumber] = new Caller(u.Trim(), DateTime.Now, false);
|
|
}
|
|
|
|
internal async Task Start()
|
|
{
|
|
if (Started)
|
|
throw new InvalidOperationException();
|
|
try
|
|
{
|
|
Started = true;
|
|
foreach (var b in bases.Where(b => b != null))
|
|
{
|
|
b.ResetTime();
|
|
}
|
|
Task.Run(async () => await ClearArray()).ConfigureAwait(false);
|
|
await Task.Delay(new TimeSpan(24, 0, 0), endTokenSource.Token);
|
|
}
|
|
catch { }
|
|
finally
|
|
{
|
|
End();
|
|
}
|
|
}
|
|
internal int Uncall(string user)
|
|
{
|
|
user = user.Trim();
|
|
for (var i = 0; i < bases.Length; i++)
|
|
{
|
|
if (bases[i]?.CallUser != user) continue;
|
|
bases[i] = null;
|
|
return i;
|
|
}
|
|
throw new InvalidOperationException("You are not participating in that war.");
|
|
}
|
|
|
|
private async Task ClearArray()
|
|
{
|
|
while (!endTokenSource.IsCancellationRequested)
|
|
{
|
|
await Task.Delay(5000);
|
|
for (var i = 0; i < bases.Length; i++)
|
|
{
|
|
if (bases[i] == null) continue;
|
|
if (!bases[i].BaseDestroyed && DateTime.Now - bases[i].TimeAdded >= callExpire)
|
|
{
|
|
OnUserTimeExpired(bases[i].CallUser);
|
|
bases[i] = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public string ShortPrint() =>
|
|
$"`{EnemyClan}` ({Size} v {Size})";
|
|
|
|
public override string ToString()
|
|
{
|
|
var sb = new StringBuilder();
|
|
|
|
sb.AppendLine($"🔰**WAR AGAINST `{EnemyClan}` ({Size} v {Size}) INFO:**");
|
|
if (!Started)
|
|
sb.AppendLine("`not started`");
|
|
for (var i = 0; i < bases.Length; i++)
|
|
{
|
|
if (bases[i] == null)
|
|
{
|
|
sb.AppendLine($"`{i + 1}.` ❌*unclaimed*");
|
|
}
|
|
else
|
|
{
|
|
if (bases[i].BaseDestroyed)
|
|
{
|
|
sb.AppendLine($"`{i + 1}.` ✅ `{bases[i].CallUser}` ⭐ ⭐ ⭐");
|
|
}
|
|
else
|
|
{
|
|
var left = Started ? callExpire - (DateTime.Now - bases[i].TimeAdded) : callExpire;
|
|
sb.AppendLine($"`{i + 1}.` ✅ `{bases[i].CallUser}` {left.Hours}h {left.Minutes}m {left.Seconds}s left");
|
|
}
|
|
}
|
|
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
|
|
internal int FinishClaim(string user)
|
|
{
|
|
user = user.Trim();
|
|
for (var i = 0; i < bases.Length; i++)
|
|
{
|
|
if (bases[i]?.BaseDestroyed != false || bases[i]?.CallUser != user) continue;
|
|
bases[i].BaseDestroyed = true;
|
|
return i;
|
|
}
|
|
throw new InvalidOperationException($"@{user} You are either not participating in that war, or you already destroyed a base.");
|
|
}
|
|
}
|
|
}
|