From 497a9eded3b785f7f96732c447943cc8bbad284b Mon Sep 17 00:00:00 2001 From: TrueDoctor Date: Tue, 17 Jul 2018 21:18:59 +0200 Subject: Added object oriented dice resolving --- .gitignore | 3 +- DiscoBot/Auxiliary/Calculator/Argument.cs | 38 +++ DiscoBot/Auxiliary/Calculator/ISolvable.cs | 10 + DiscoBot/Auxiliary/Calculator/Operator.cs | 50 ++++ DiscoBot/Auxiliary/Calculator/Ops.cs | 13 + DiscoBot/Auxiliary/Calculator/StringSolver.cs | 207 +++++++++++++++ DiscoBot/Auxiliary/Dice.cs | 38 +++ DiscoBot/Commands/MiscCommands.cs | 6 + DiscoBot/DSA_Game/Dsa.cs | 1 + DiscoBot/DiscoBot.csproj | 5 + ZooBOTanica/CritCreate.Designer.cs | 16 ++ ZooBOTanica/CritCreate.resx | 368 +++++++++++++++++++------- 12 files changed, 654 insertions(+), 101 deletions(-) create mode 100644 DiscoBot/Auxiliary/Calculator/Argument.cs create mode 100644 DiscoBot/Auxiliary/Calculator/ISolvable.cs create mode 100644 DiscoBot/Auxiliary/Calculator/Operator.cs create mode 100644 DiscoBot/Auxiliary/Calculator/Ops.cs create mode 100644 DiscoBot/Auxiliary/Calculator/StringSolver.cs diff --git a/.gitignore b/.gitignore index 3c4efe2..752305f 100644 --- a/.gitignore +++ b/.gitignore @@ -258,4 +258,5 @@ paket-files/ # Python Tools for Visual Studio (PTVS) __pycache__/ -*.pyc \ No newline at end of file +*.pyc +/ZooBOTanica/Critters diff --git a/DiscoBot/Auxiliary/Calculator/Argument.cs b/DiscoBot/Auxiliary/Calculator/Argument.cs new file mode 100644 index 0000000..2379bfe --- /dev/null +++ b/DiscoBot/Auxiliary/Calculator/Argument.cs @@ -0,0 +1,38 @@ +namespace DiscoBot.Auxiliary.Calculator +{ + using System; + + /// + /// Provides an ISolvable class to save numbers. The class handles Argument checking and conversion from string to int. + /// + public class Argument : ISolvable + { + private readonly int value; + + public Argument(string value) + { + // check whether the value given is an empty string + if (string.IsNullOrEmpty(value)) + { + throw new ArgumentException("Argument kann nicht mit einem leeren string instanziert werden. ", nameof(value)); + } + + if (!int.TryParse(value, out int result)) + { + throw new ArgumentException($"Kann {value} nicht in Integer konvertieren"); + } + + this.value = result; + } + + public int Solve() + { + return this.value; + } + + public override string ToString() + { + return this.value.ToString(); + } + } +} \ No newline at end of file diff --git a/DiscoBot/Auxiliary/Calculator/ISolvable.cs b/DiscoBot/Auxiliary/Calculator/ISolvable.cs new file mode 100644 index 0000000..a869bdb --- /dev/null +++ b/DiscoBot/Auxiliary/Calculator/ISolvable.cs @@ -0,0 +1,10 @@ +namespace DiscoBot.Auxiliary.Calculator +{ + /// + /// Object has to be able to return an integer as it's value + /// + public interface ISolvable + { + int Solve(); + } +} diff --git a/DiscoBot/Auxiliary/Calculator/Operator.cs b/DiscoBot/Auxiliary/Calculator/Operator.cs new file mode 100644 index 0000000..0928ec2 --- /dev/null +++ b/DiscoBot/Auxiliary/Calculator/Operator.cs @@ -0,0 +1,50 @@ +using System; + +namespace DiscoBot.Auxiliary.Calculator +{ + /// + /// The Operator Class represents a binary operator with tow Arguments and an Operation type + /// + public class Operator : ISolvable + { + private readonly ISolvable arg1, arg2; + + public Operator(ISolvable arg1, ISolvable arg2, Ops operatorType) + { + this.arg1 = arg1; + this.arg2 = arg2; + this.OperatorType = operatorType; + } + + public Ops OperatorType { get; set; } + + public int Solve() + { + int result; + switch (this.OperatorType) + { + case Ops.Dice: + result = Dice.Roll(this.arg1.Solve(), this.arg2.Solve()); + break; + case Ops.Multiply: + result = this.arg1.Solve() * this.arg2.Solve(); + break; + case Ops.Add: + result = this.arg1.Solve() + this.arg2.Solve(); + break; + case Ops.Subtract: + result = this.arg1.Solve() - this.arg2.Solve(); + break; + default: + throw new ArgumentOutOfRangeException(); + } + + return result; + } + + public override string ToString() + { + return $"({this.arg1} {this.OperatorType} {this.arg2})"; + } + } +} diff --git a/DiscoBot/Auxiliary/Calculator/Ops.cs b/DiscoBot/Auxiliary/Calculator/Ops.cs new file mode 100644 index 0000000..62c1309 --- /dev/null +++ b/DiscoBot/Auxiliary/Calculator/Ops.cs @@ -0,0 +1,13 @@ +namespace DiscoBot.Auxiliary.Calculator +{ + /// + /// The Different Operations, witch can be performed in execution-order + /// + public enum Ops + { + Dice, + Multiply, + Subtract, + Add + } +} diff --git a/DiscoBot/Auxiliary/Calculator/StringSolver.cs b/DiscoBot/Auxiliary/Calculator/StringSolver.cs new file mode 100644 index 0000000..30c2134 --- /dev/null +++ b/DiscoBot/Auxiliary/Calculator/StringSolver.cs @@ -0,0 +1,207 @@ +namespace DiscoBot.Auxiliary.Calculator +{ + using System; + using System.Collections.Generic; + using System.Linq; + + /// + /// The StringSolver divides the calculation string into operations and SubStringSolvers if the string contains parentheses + /// + public class StringSolver : ISolvable + { + private readonly string input; + private readonly List arguments = new List(); + + public StringSolver(string input) + { + this.input = input; + } + + public override string ToString() + { + return "(0+" + this.input.Replace(" ", string.Empty).ToLower() + ")"; + } + + public int Solve() + { + string workInput = "0+" + this.input.Replace(" ", string.Empty).ToLower(); + workInput = ExpandParentheses(workInput); + + // Create a List of the different parts of the calculation, e.g.:{"0", "+", "(5+6)", "d", "3"}. + this.AtomizeOperations(workInput); + + // traverse the List in order of Operation to Create the binary operation tree . + this.NestOperations(); + + // the List now contains only the top operation node, witch can be solved recursively, + return ((ISolvable)this.arguments.First()).Solve(); + } + + private static string GetInner(ref string input) // extract the inner bracket an remove the section from the input string + { + int depth = 0; + for (var index = 1; index < input.Length; index++) + { + char c = input[index]; + switch (c) + { + case '(': + depth++; + break; + case ')': + if (depth == 0) + { + var split = input.Substring(1, index - 1); + input = input.Substring(index + 1); + return split.Equals(string.Empty) ? "0" : split; + } + else + { + depth--; + } + + break; + } + } + + return string.Empty; + } + + private static Ops GetOps(char c) + { + switch (c) + { + case 'd': + case 'w': + return Ops.Dice; + case '+': + return Ops.Add; + case '-': + return Ops.Subtract; + case '*': + return Ops.Multiply; + default: + return Ops.Multiply; + } + } + + private static string ExpandParentheses(string input) // insert * between Parentheses and digits + { + for (int i = 0; i < input.Length - 1; i++) + { + if (input[i + 1] == '(' && char.IsNumber(input[i])) + { + input = input.Insert(i + 1, "*"); + } + } + + for (int i = 1; i < input.Length; i++) + { + if (input[i - 1] == ')' && char.IsNumber(input[i])) + { + input = input.Insert(i, "*"); + } + } + + return input; + } + + private void AtomizeOperations(string workInput) + { + for (var index = 0; index < workInput.Length; index++) + { + char c = workInput[index]; + + if (char.IsNumber(c)) + { + // if char number, check if at end of string, else continue looping + if (index == workInput.Length - 1) + { + // if at end of string; add remaining number to arguments + this.arguments.Add(new Argument(workInput.Substring(0, index + 1))); + } + + continue; + } + + switch (c) + { + case ')': + throw new ArgumentException($"Unmögliche Anordnung von Klammern"); + case '(': + this.arguments.Add(new StringSolver(GetInner(ref workInput))); + index = -1; + break; + default: + if (index > 0) + { + this.arguments.Add(new Argument(workInput.Substring(0, index))); + } + + this.arguments.Add(GetOps(c)); + workInput = workInput.Remove(0, index + 1); + index = -1; + break; + } + } + } + + private void NestOperations() + { + foreach (Ops currentOp in Enum.GetValues(typeof(Ops))) + { + // cycle through operators in operational order + for (var index = 0; index < this.arguments.Count; index++) + { + var arg = this.arguments[index]; + + if (arg.GetType() != typeof(Ops)) + { + continue; + } + + // arg is of type Ops + var op = (Ops)arg; + + if (op != currentOp) + { + continue; + } + + // arg describes the current operation + this.HandleSpecialFormatting(ref index, op); // Deal with special needs... + + // replace the previous current and next Element in the List with one Operation object + var temp = new Operator((ISolvable)this.arguments[index - 1], (ISolvable)this.arguments[index + 1], op); + this.arguments[index - 1] = temp; + this.arguments.RemoveRange(index, 2); + index--; + } + } + } + + private void HandleSpecialFormatting(ref int index, Ops op) + { + var arg1 = this.arguments[index - 1]; + if (arg1.GetType() == typeof(Ops)) + { + if (op == Ops.Dice) + { + this.arguments.Insert(index++, new Argument("1")); // w6 -> 1w6 + } + + if (op == Ops.Subtract) + { + this.arguments.Insert(index++, new Argument("0")); // +-3 -> +0-3 + } + } + + var arg2 = this.arguments[index + 1]; // 3+-5 -> 3+(0-5) + if (arg2.GetType() == typeof(Ops)) + { + this.arguments[index + 1] = new Operator(new Argument("0"), (ISolvable)this.arguments[index + 2], (Ops)arg2); + this.arguments.RemoveAt(index + 2); + } + } + } +} \ No newline at end of file diff --git a/DiscoBot/Auxiliary/Dice.cs b/DiscoBot/Auxiliary/Dice.cs index 16a8a77..0cd9656 100644 --- a/DiscoBot/Auxiliary/Dice.cs +++ b/DiscoBot/Auxiliary/Dice.cs @@ -1,5 +1,10 @@ namespace DiscoBot.Auxiliary { + using System; + using System.Linq; + + using Discord.Commands; + public static class Dice // roll it! { private static readonly System.Random Rnd = new System.Random(); @@ -8,5 +13,38 @@ { return Rnd.Next(d) + 1; } + + public static int Roll(string input) + { + var strings = input.ToLower().Split(new[] { 'w', 'd' }, 2, StringSplitOptions.RemoveEmptyEntries).ToList(); + int count = Convert.ToInt32(strings[0]); + int d = Convert.ToInt32(strings[0]); + + if (strings.Count != 2) + { + throw new ArgumentException($"{input}: erfüllt nicht die Formatvogaben( Anzahl d Augenzahl)"); + } + + return Roll(count, d); + } + + public static int Roll(int count, int d) + { + if (d <= 0) + { + return 0; + } + + int sum = 0; + for (int i = 0; i < Math.Abs(count); i++) + { + var roll = Dice.Roll(d); + sum += roll; + } + + sum *= Math.Abs(count) / count; + + return sum; + } } } diff --git a/DiscoBot/Commands/MiscCommands.cs b/DiscoBot/Commands/MiscCommands.cs index aa3ea1b..4a91081 100644 --- a/DiscoBot/Commands/MiscCommands.cs +++ b/DiscoBot/Commands/MiscCommands.cs @@ -37,6 +37,12 @@ namespace DiscoBot.Commands return this.ReplyAsync("```xl\n" + RandomMisc.Roll(roll) + "\n```"); } + [Command("rd"), Summary("Würfel Dennis ")] + public Task RollDennisAsync([Remainder, Summary("Weapon")] string roll) + { + return this.ReplyAsync("```xl\n" + new Auxiliary.Calculator.StringSolver(roll).Solve() + "\n```"); + } + [Command("general"), Summary("Set General ")] public Task SetGeneralAsync([Remainder, Summary("Set General")] int i = 0) { diff --git a/DiscoBot/DSA_Game/Dsa.cs b/DiscoBot/DSA_Game/Dsa.cs index 09e874d..139ad91 100644 --- a/DiscoBot/DSA_Game/Dsa.cs +++ b/DiscoBot/DSA_Game/Dsa.cs @@ -44,6 +44,7 @@ public static void Startup() { + //new DiscoBot.Auxiliary.Calculator.StringSolver("1d100 - (1d200 + 1) * -50000").Solve(); /*Session = new Session();*/ // relation.Add("Papo", "Pump aus der Gosse"); foreach (var filename in Directory.GetFiles("helden", "*.xml")) diff --git a/DiscoBot/DiscoBot.csproj b/DiscoBot/DiscoBot.csproj index 4560755..7049b03 100644 --- a/DiscoBot/DiscoBot.csproj +++ b/DiscoBot/DiscoBot.csproj @@ -97,6 +97,11 @@ + + + + + diff --git a/ZooBOTanica/CritCreate.Designer.cs b/ZooBOTanica/CritCreate.Designer.cs index 93e1599..d64aaa3 100644 --- a/ZooBOTanica/CritCreate.Designer.cs +++ b/ZooBOTanica/CritCreate.Designer.cs @@ -99,6 +99,11 @@ // LeEdit // resources.ApplyResources(this.LeEdit, "LeEdit"); + this.LeEdit.Maximum = new decimal(new int[] { + 999, + 0, + 0, + 0}); this.LeEdit.Name = "LeEdit"; this.LeEdit.Value = new decimal(new int[] { 30, @@ -174,6 +179,11 @@ // resources.ApplyResources(this.PaEdit, "PaEdit"); this.PaEdit.Name = "PaEdit"; + this.PaEdit.Value = new decimal(new int[] { + 6, + 0, + 0, + 0}); // // PaLabel // @@ -188,6 +198,11 @@ // MREdit // resources.ApplyResources(this.MREdit, "MREdit"); + this.MREdit.Minimum = new decimal(new int[] { + 100, + 0, + 0, + -2147483648}); this.MREdit.Name = "MREdit"; this.MREdit.Value = new decimal(new int[] { 5, @@ -322,6 +337,7 @@ // resources.ApplyResources(this.LoadButton, "LoadButton"); this.LoadButton.Name = "LoadButton"; + this.LoadButton.TabStop = false; this.LoadButton.UseVisualStyleBackColor = true; this.LoadButton.Click += new System.EventHandler(this.LoadButton_Click); // diff --git a/ZooBOTanica/CritCreate.resx b/ZooBOTanica/CritCreate.resx index ccdf4fd..aac2d43 100644 --- a/ZooBOTanica/CritCreate.resx +++ b/ZooBOTanica/CritCreate.resx @@ -204,7 +204,7 @@ 45, 20 - 2 + 3 LeEdit @@ -218,6 +218,102 @@ 6 + + KoLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + GrundwerteGroup + + + 0 + + + KoEdit + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + GrundwerteGroup + + + 1 + + + AeLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + GrundwerteGroup + + + 2 + + + AeEdit + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + GrundwerteGroup + + + 3 + + + AuLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + GrundwerteGroup + + + 4 + + + AuEdit + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + GrundwerteGroup + + + 5 + + + 325, 117 + + + 277, 53 + + + 5 + + + Grundwerte + + + GrundwerteGroup + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 9 + True @@ -228,7 +324,7 @@ 25, 13 - 10 + 4 KO: @@ -252,7 +348,7 @@ 45, 20 - 9 + 5 KoEdit @@ -276,7 +372,7 @@ 23, 13 - 8 + 2 Ae: @@ -300,7 +396,7 @@ 45, 20 - 8 + 3 AeEdit @@ -324,7 +420,7 @@ 23, 13 - 6 + 0 Au: @@ -348,7 +444,7 @@ 45, 20 - 7 + 1 AuEdit @@ -362,30 +458,6 @@ 5 - - 325, 117 - - - 277, 53 - - - 4 - - - Grundwerte - - - GrundwerteGroup - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 9 - 36, 23 @@ -393,7 +465,7 @@ 45, 20 - 3 + 1 PaEdit @@ -421,7 +493,7 @@ 24, 13 - 10 + 0 PA: @@ -448,7 +520,7 @@ 27, 13 - 8 + 4 MR: @@ -472,7 +544,7 @@ 45, 20 - 6 + 5 MREdit @@ -496,7 +568,7 @@ 25, 13 - 6 + 2 RS: @@ -520,7 +592,7 @@ 45, 20 - 4 + 3 RSEdit @@ -541,7 +613,7 @@ 277, 53 - 10 + 4 Verteidigung @@ -558,6 +630,102 @@ 8 + + INIEdit + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + SecondGroup + + + 0 + + + GWLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + SecondGroup + + + 1 + + + GWEdit + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + SecondGroup + + + 2 + + + INILabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + SecondGroup + + + 3 + + + GsLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + SecondGroup + + + 4 + + + GsEdit + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + SecondGroup + + + 5 + + + 325, 182 + + + 277, 53 + + + 6 + + + Sekundäre Werte + + + SecondGroup + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 7 + 121, 18 @@ -565,7 +733,7 @@ 55, 20 - 11 + 3 1w6 @@ -592,7 +760,7 @@ 29, 13 - 8 + 4 GW: @@ -616,7 +784,7 @@ 45, 20 - 12 + 5 GWEdit @@ -640,7 +808,7 @@ 24, 13 - 6 + 2 INI: @@ -667,7 +835,7 @@ 25, 13 - 2 + 0 GS: @@ -691,7 +859,7 @@ 45, 20 - 10 + 1 GsEdit @@ -705,60 +873,54 @@ 5 - - 325, 182 + + AttackList - - 277, 53 + + System.Windows.Forms.DataGridView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 10 + + AttackGroup - - Sekundäre Werte + + 0 - - SecondGroup + + 11, 21 - + + 296, 181 + + + 7 + + + Attacke(n) + + + AttackGroup + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + $this - - 7 + + 4 True - - Name - True - - At - - - 42 - True - - TP - - - 46 - True - - Kommentar - 11, 19 @@ -766,7 +928,7 @@ 279, 150 - 13 + 0 AttackList @@ -780,29 +942,35 @@ 0 - - 11, 21 - - - 296, 181 - - - 12 + + True + + + Name - - Attacke(n) + + True + + + At - - AttackGroup + + 42 - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + True + + + TP - - $this + + 46 - - 4 + + True + + + Kommentar 22, 227 @@ -814,7 +982,7 @@ 279, 60 - 14 + 9 MeisterkommentarEdit @@ -838,7 +1006,7 @@ 96, 13 - 16 + 8 Meisterkommentar: @@ -862,7 +1030,7 @@ 119, 36 - 15 + 10 Speichern @@ -889,7 +1057,7 @@ 119, 36 - 18 + 11 Laden @@ -916,7 +1084,7 @@ 6, 13 - 646, 304 + 606, 304 CritCreate -- cgit v1.2.3-70-g09d2