Improvements to clash of clans organizer

This commit is contained in:
Master Kwoth 2016-02-17 17:14:50 +01:00
parent 070cf5d967
commit de72817847
2 changed files with 144 additions and 73 deletions

View File

@ -11,7 +11,7 @@ namespace NadekoBot
{ {
public class NadekoStats public class NadekoStats
{ {
public string BotVersion = "0.8-beta11"; public string BotVersion = "0.8-beta13";
private static readonly NadekoStats _instance = new NadekoStats(); private static readonly NadekoStats _instance = new NadekoStats();
public static NadekoStats Instance => _instance; public static NadekoStats Instance => _instance;

View File

@ -40,26 +40,46 @@ namespace NadekoBot.Commands {
return; return;
} }
var cw = new ClashWar(enemyClan, size, e); var cw = new ClashWar(enemyClan, size, e);
cw.Start(); //cw.Start();
wars.Add(cw); wars.Add(cw);
cw.OnUserTimeExpired += async (u) => { cw.OnUserTimeExpired += async (u) => {
await e.Channel.SendMessage($"❗🔰**Claim from {u.Mention} for a war against {cw.ShortPrint()} has expired.**"); await e.Channel.SendMessage($"❗🔰**Claim from @{u} for a war against {cw.ShortPrint()} has expired.**");
}; };
cw.OnWarEnded += async () => { cw.OnWarEnded += async () => {
await e.Channel.SendMessage($"❗🔰**War against {cw.ShortPrint()} ended.**"); await e.Channel.SendMessage($"❗🔰**War against {cw.ShortPrint()} ended.**");
}; };
await e.Channel.SendMessage($"❗🔰**STARTED** `{size} v {size}` **CLAN WAR AGAINST** `{enemyClan}`"); await e.Channel.SendMessage($"❗🔰**CREATED CLAN WAR AGAINST {cw.ShortPrint()}**");
//war with the index X started. //war with the index X started.
}; };
public override void Init(CommandGroupBuilder cgb) { public override void Init(CommandGroupBuilder cgb) {
cgb.CreateCommand(prefix + "startwar") cgb.CreateCommand(prefix + "createwar")
.Alias(prefix + "sw") .Alias(prefix + "cw")
.Description($"Starts a new war by specifying a size (>10 and multiple of 5) and enemy clan name. War ends in 23 hours. You need manage channels permission to use this.\n**Usage**:{prefix}sw 15 The Enemy Clan") .Description($"Creates a new war by specifying a size (>10 and multiple of 5) and enemy clan name.\n**Usage**:{prefix}cw 15 The Enemy Clan")
.Parameter("size") .Parameter("size")
.Parameter("enemy_clan", ParameterType.Unparsed) .Parameter("enemy_clan", ParameterType.Unparsed)
.Do(DoFunc()); .Do(DoFunc());
cgb.CreateCommand(prefix + "sw")
.Alias(prefix + "startwar")
.Description("Starts a war with a given number.")
.Parameter("number", ParameterType.Required)
.Do(async e => {
var warsInfo = GetInfo(e);
if (warsInfo == null) {
await e.Channel.SendMessage("💢🔰 **That war does not exist.**");
return;
}
var war = warsInfo.Item1[warsInfo.Item2];
try {
war.Start();
await e.Channel.SendMessage($"🔰**STARTED WAR AGAINST {war.ShortPrint()}**");
}
catch {
await e.Channel.SendMessage($"🔰**WAR AGAINST {war.ShortPrint()} IS ALREADY STARTED**");
}
});
cgb.CreateCommand(prefix + "listwar") cgb.CreateCommand(prefix + "listwar")
.Alias(prefix + "lw") .Alias(prefix + "lw")
.Description($"Shows the active war claims by a number. Shows all wars in a short way if no number is specified.\n**Usage**: {prefix}lw [war_number] or {prefix}lw") .Description($"Shows the active war claims by a number. Shows all wars in a short way if no number is specified.\n**Usage**: {prefix}lw [war_number] or {prefix}lw")
@ -98,9 +118,10 @@ namespace NadekoBot.Commands {
cgb.CreateCommand(prefix + "claim") cgb.CreateCommand(prefix + "claim")
.Alias(prefix + "call") .Alias(prefix + "call")
.Alias(prefix + "c") .Alias(prefix + "c")
.Description($"Claims a certain base from a certain war.\n**Usage**: {prefix}call [war_number] [base_number]") .Description($"Claims a certain base from a certain war. You can supply a name in the third optional argument to claim in someone else's place. \n**Usage**: {prefix}call [war_number] [base_number] (optional_otheruser)")
.Parameter("number") .Parameter("number")
.Parameter("baseNumber") .Parameter("baseNumber")
.Parameter("other_name", ParameterType.Unparsed)
.Do(async e => { .Do(async e => {
var warsInfo = GetInfo(e); var warsInfo = GetInfo(e);
if (warsInfo == null || warsInfo.Item1.Count == 0) { if (warsInfo == null || warsInfo.Item1.Count == 0) {
@ -112,10 +133,14 @@ namespace NadekoBot.Commands {
await e.Channel.SendMessage("💢🔰 **Invalid base number.**"); await e.Channel.SendMessage("💢🔰 **Invalid base number.**");
return; return;
} }
string usr =
string.IsNullOrWhiteSpace(e.GetArg("other_name")) ?
e.User.Name :
e.GetArg("other_name");
try { try {
var war = warsInfo.Item1[warsInfo.Item2]; var war = warsInfo.Item1[warsInfo.Item2];
await war.Call(e.User, baseNum - 1); await war.Call(usr, baseNum - 1);
await e.Channel.SendMessage($"🔰{e.User.Mention} claimed a base #{baseNum} for a war against {war.ShortPrint()}"); await e.Channel.SendMessage($"🔰**{usr}** claimed a base #{baseNum} for a war against {war.ShortPrint()}");
} }
catch (Exception ex) { catch (Exception ex) {
await e.Channel.SendMessage($"💢🔰 {ex.Message}"); await e.Channel.SendMessage($"💢🔰 {ex.Message}");
@ -124,18 +149,24 @@ namespace NadekoBot.Commands {
cgb.CreateCommand(prefix + "cf") cgb.CreateCommand(prefix + "cf")
.Alias(prefix + "claimfinish") .Alias(prefix + "claimfinish")
.Description($"Finish your claim if you destroyed a base.\n**Usage**: {prefix}cf [war_number]") .Description($"Finish your claim if you destroyed a base. Optional second argument finishes for someone else.\n**Usage**: {prefix}cf [war_number]")
.Parameter("number", ParameterType.Required) .Parameter("number", ParameterType.Required)
.Parameter("other_name", ParameterType.Unparsed)
.Do(async e => { .Do(async e => {
var warInfo = GetInfo(e); var warInfo = GetInfo(e);
if (warInfo == null || warInfo.Item1.Count == 0) { if (warInfo == null || warInfo.Item1.Count == 0) {
await e.Channel.SendMessage("💢🔰 **That war does not exist.**"); await e.Channel.SendMessage("💢🔰 **That war does not exist.**");
return; return;
} }
string usr =
string.IsNullOrWhiteSpace(e.GetArg("other_name")) ?
e.User.Name :
e.GetArg("other_name");
var war = warInfo.Item1[warInfo.Item2]; var war = warInfo.Item1[warInfo.Item2];
try { try {
var baseNum = war.FinishClaim(e.User); var baseNum = war.FinishClaim(usr);
await e.Channel.SendMessage($"❗🔰{e.User.Mention} **DESTROYED** a base #{baseNum} in a war against {war.ShortPrint()}"); await e.Channel.SendMessage($"❗🔰{e.User.Mention} **DESTROYED** a base #{baseNum + 1} in a war against {war.ShortPrint()}");
} }
catch (Exception ex) { catch (Exception ex) {
await e.Channel.SendMessage($"💢🔰 {ex.Message}"); await e.Channel.SendMessage($"💢🔰 {ex.Message}");
@ -145,18 +176,49 @@ namespace NadekoBot.Commands {
cgb.CreateCommand(prefix + "unclaim") cgb.CreateCommand(prefix + "unclaim")
.Alias(prefix + "uncall") .Alias(prefix + "uncall")
.Alias(prefix + "uc") .Alias(prefix + "uc")
.Description($"Removes your claim from a certain war.\n**Usage**: {prefix}uc [war_number] [base_number]") .Description($"Removes your claim from a certain war. Optional second argument denotes a person in whos place to unclaim\n**Usage**: {prefix}uc [war_number] (optional_other_name)")
.Parameter("number", ParameterType.Required) .Parameter("number", ParameterType.Required)
.Parameter("other_name", ParameterType.Unparsed)
.Do(async e => { .Do(async e => {
var warsInfo = GetInfo(e); var warsInfo = GetInfo(e);
if (warsInfo == null || warsInfo.Item1.Count == 0) { if (warsInfo == null || warsInfo.Item1.Count == 0) {
await e.Channel.SendMessage("💢🔰 **That war does not exist.**"); await e.Channel.SendMessage("💢🔰 **That war does not exist.**");
return; return;
} }
string usr =
string.IsNullOrWhiteSpace(e.GetArg("other_name")) ?
e.User.Name :
e.GetArg("other_name");
try { try {
var war = warsInfo.Item1[warsInfo.Item2]; var war = warsInfo.Item1[warsInfo.Item2];
int baseNumber = war.Uncall(e.User); int baseNumber = war.Uncall(usr);
await e.Channel.SendMessage($"🔰 {e.User.Mention} has **UNCLAIMED** a base #{baseNumber + 1} from a war against {war.ShortPrint()}"); await e.Channel.SendMessage($"🔰 @{usr} has **UNCLAIMED** a base #{baseNumber + 1} from a war against {war.ShortPrint()}");
}
catch (Exception ex) {
await e.Channel.SendMessage($"💢🔰 {ex.Message}");
}
});
cgb.CreateCommand(prefix + "forceunclaim")
.Alias(prefix + "forceuncall")
.Alias(prefix + "fuc")
.Description($"Force removes a base claim from a certain war from a certain base. \n**Usage**: {prefix}fuc [war_number] [base_number]")
.Parameter("number", ParameterType.Required)
.Parameter("other_name", ParameterType.Unparsed)
.Do(async e => {
var warsInfo = GetInfo(e);
if (warsInfo == null || warsInfo.Item1.Count == 0) {
await e.Channel.SendMessage("💢🔰 **That war does not exist.**");
return;
}
string usr =
string.IsNullOrWhiteSpace(e.GetArg("other_name")) ?
e.User.Name :
e.GetArg("other_name");
try {
var war = warsInfo.Item1[warsInfo.Item2];
int baseNumber = war.Uncall(usr);
await e.Channel.SendMessage($"🔰 @{usr} has **UNCLAIMED** a base #{baseNumber + 1} from a war against {war.ShortPrint()}");
} }
catch (Exception ex) { catch (Exception ex) {
await e.Channel.SendMessage($"💢🔰 {ex.Message}"); await e.Channel.SendMessage($"💢🔰 {ex.Message}");
@ -168,8 +230,6 @@ namespace NadekoBot.Commands {
.Description($"Ends the war with a given index.\n**Usage**:{prefix}ew [war_number]") .Description($"Ends the war with a given index.\n**Usage**:{prefix}ew [war_number]")
.Parameter("number") .Parameter("number")
.Do(async e => { .Do(async e => {
if (!e.User.ServerPermissions.ManageChannels)
return;
var warsInfo = GetInfo(e); var warsInfo = GetInfo(e);
if (warsInfo == null) { if (warsInfo == null) {
await e.Channel.SendMessage("💢🔰 That war does not exist."); await e.Channel.SendMessage("💢🔰 That war does not exist.");
@ -203,9 +263,9 @@ namespace NadekoBot.Commands {
} }
internal class Caller { internal class Caller {
private User _user; private string _user;
public User CallUser public string CallUser
{ {
get { return _user; } get { return _user; }
set { _user = value; } set { _user = value; }
@ -234,8 +294,9 @@ namespace NadekoBot.Commands {
private Caller[] bases; private Caller[] bases;
private CancellationTokenSource[] baseCancelTokens; private CancellationTokenSource[] baseCancelTokens;
private CancellationTokenSource endTokenSource = new CancellationTokenSource(); private CancellationTokenSource endTokenSource = new CancellationTokenSource();
public Action<User> OnUserTimeExpired { get; set; } = null; public Action<string> OnUserTimeExpired { get; set; } = null;
public Action OnWarEnded { get; set; } = null; public Action OnWarEnded { get; set; } = null;
public bool Started { get; set; } = false;
public ClashWar(string enemyClan, int size, CommandEventArgs e) { public ClashWar(string enemyClan, int size, CommandEventArgs e) {
this.enemyClan = enemyClan; this.enemyClan = enemyClan;
@ -252,21 +313,28 @@ namespace NadekoBot.Commands {
} }
} }
internal async Task Call(User u, int baseNumber) { internal async Task Call(string u, int baseNumber) {
if (baseNumber < 0 || baseNumber >= bases.Length) if (baseNumber < 0 || baseNumber >= bases.Length)
throw new ArgumentException("Invalid base number"); throw new ArgumentException("Invalid base number");
if (bases[baseNumber] != null) if (bases[baseNumber] != null)
throw new ArgumentException("That base is already claimed."); throw new ArgumentException("That base is already claimed.");
for (int i = 0; i < bases.Length; i++) { for (int i = 0; i < bases.Length; i++) {
if (bases[i]?.BaseDestroyed == false && bases[i]?.CallUser == u) if (bases[i]?.BaseDestroyed == false && bases[i]?.CallUser == u)
throw new ArgumentException($"💢 {u.Mention} You already claimed a base #{i + 1}. You can't claim a new one."); throw new ArgumentException($"@{u} You already claimed a base #{i + 1}. You can't claim a new one.");
} }
bases[baseNumber] = new Caller { CallUser = u, TimeAdded = DateTime.Now, BaseDestroyed = false }; bases[baseNumber] = new Caller { CallUser = u, TimeAdded = DateTime.Now, BaseDestroyed = false };
} }
internal async void Start() { internal async void Start() {
if (Started)
throw new InvalidOperationException();
try { try {
Started = true;
for (int i = 0; i < bases.Length; i++) {
if (bases[i] != null)
bases[i].TimeAdded = DateTime.Now;
}
Task.Run(async () => await ClearArray()); Task.Run(async () => await ClearArray());
await Task.Delay(new TimeSpan(23, 0, 0), endTokenSource.Token); await Task.Delay(new TimeSpan(23, 0, 0), endTokenSource.Token);
} }
@ -275,7 +343,7 @@ namespace NadekoBot.Commands {
End(); End();
} }
} }
internal int Uncall(User user) { internal int Uncall(string user) {
for (int i = 0; i < bases.Length; i++) { for (int i = 0; i < bases.Length; i++) {
if (bases[i]?.CallUser == user) { if (bases[i]?.CallUser == user) {
bases[i] = null; bases[i] = null;
@ -291,7 +359,7 @@ namespace NadekoBot.Commands {
for (int i = 0; i < bases.Length; i++) { for (int i = 0; i < bases.Length; i++) {
if (bases[i] == null) continue; if (bases[i] == null) continue;
if (!bases[i].BaseDestroyed && DateTime.Now - bases[i].TimeAdded >= callExpire) { if (!bases[i].BaseDestroyed && DateTime.Now - bases[i].TimeAdded >= callExpire) {
Console.WriteLine($"Removing user {bases[i].CallUser.Name}"); Console.WriteLine($"Removing user {bases[i].CallUser}");
if (OnUserTimeExpired != null) if (OnUserTimeExpired != null)
OnUserTimeExpired(bases[i].CallUser); OnUserTimeExpired(bases[i].CallUser);
bases[i] = null; bases[i] = null;
@ -306,18 +374,21 @@ namespace NadekoBot.Commands {
public override string ToString() { public override string ToString() {
var sb = new StringBuilder(); var sb = new StringBuilder();
sb.AppendLine($"🔰**WAR AGAINST `{enemyClan}` ({size} v {size}) INFO:**"); sb.AppendLine($"🔰**WAR AGAINST `{enemyClan}` ({size} v {size}) INFO:**");
if (!Started)
sb.AppendLine("`not started`");
for (int i = 0; i < bases.Length; i++) { for (int i = 0; i < bases.Length; i++) {
if (bases[i] == null) { if (bases[i] == null) {
sb.AppendLine($"`{i + 1}.` ❌*unclaimed*"); sb.AppendLine($"`{i + 1}.` ❌*unclaimed*");
} }
else { else {
if (bases[i].BaseDestroyed) { if (bases[i].BaseDestroyed) {
sb.AppendLine($"`{i + 1}.` ✅ `{bases[i].CallUser.Name}` ⭐ ⭐ ⭐"); sb.AppendLine($"`{i + 1}.` ✅ `{bases[i].CallUser}` ⭐ ⭐ ⭐");
} }
else { else {
var left = callExpire - (DateTime.Now - bases[i].TimeAdded); var left = Started ? callExpire - (DateTime.Now - bases[i].TimeAdded) : callExpire;
sb.AppendLine($"`{i + 1}.` ✅ `{bases[i].CallUser.Name}` {left.Hours}h {left.Minutes}m {left.Seconds}s left"); sb.AppendLine($"`{i + 1}.` ✅ `{bases[i].CallUser}` {left.Hours}h {left.Minutes}m {left.Seconds}s left");
} }
} }
@ -325,14 +396,14 @@ namespace NadekoBot.Commands {
return sb.ToString(); return sb.ToString();
} }
internal int FinishClaim(User user) { internal int FinishClaim(string user) {
for (int i = 0; i < bases.Length; i++) { for (int i = 0; i < bases.Length; i++) {
if (bases[i]?.BaseDestroyed == false && bases[i]?.CallUser == user) { if (bases[i]?.BaseDestroyed == false && bases[i]?.CallUser == user) {
bases[i].BaseDestroyed = true; bases[i].BaseDestroyed = true;
return i; return i;
} }
} }
throw new InvalidOperationException($"{user.Mention} You are either not participating in that war, or you already destroyed a base."); throw new InvalidOperationException($"@{user} You are either not participating in that war, or you already destroyed a base.");
} }
} }
} }