roll command is now object-oriented and pretty-prints output

This commit is contained in:
Valerie Wolfe 2024-03-31 00:59:15 -04:00
parent 1c6603be0a
commit 48799dc0a7
3 changed files with 75 additions and 46 deletions

View file

@ -8,54 +8,14 @@ namespace Dungeoneer {
// don't do anything with empty expressions
if(args.Count == 0)
return;
var expression = "";
var diePattern = new Regex(@"\d+d\d+");
// reassemble split args and substitute die notation
foreach(string arg in args) {
string part;
var dieCheck = diePattern.Match(arg);
if(dieCheck.Success) {
var parts = arg.Split('d');
var first = parts[0];
var second = parts[1];
int count;
int sides;
try {
count = int.Parse(first);
sides = int.Parse(second);
} catch {
Console.WriteLine("'{arg}' is not a valid dice expression");
return;
}
var rolls = "( ";
for(int i = 0; i < count; i++) {
string result;
var roll = Util.Roll(sides);
if(i < count - 1)
result = $"{roll} + ";
else
result = $"{roll} ";
rolls += result;
}
rolls += ")";
part = rolls;
} else
part = arg;
expression += $"{part} ";
}
dynamic output;
try { output = Scripting.Expr($"eval('{expression}')"); }
catch {
// create new parsed expression object and pretty-print
var roll = new RollExpression(args);
var result = roll.Result;
if(result == null)
Console.WriteLine("invalid expression");
return;
}
Console.WriteLine($"{expression}\n=> {output}");
else
Console.WriteLine($"{roll.Print}\n => {result}");
}

16
Format.cs Normal file
View file

@ -0,0 +1,16 @@
namespace Dungeoneer {
public static class Format {
public const string Reset = "\x1b[0m";
public const string Black = "\x1b[30m";
public const string Red = "\x1b[31m";
public const string Green = "\x1b[32m";
public const string Yellow = "\x1b[33m";
public const string Blue = "\x1b[34m";
}
}

53
Util.cs
View file

@ -1,4 +1,5 @@
using System.Security.Cryptography;
using System.Text.RegularExpressions;
namespace Dungeoneer {
@ -10,5 +11,57 @@ namespace Dungeoneer {
}
public class RollExpression {
private IList<string> Parts;
public string Print { get; private set; }
public string Expression { get; private set; }
public dynamic Result {
get {
try { return Scripting.Expr($"eval('{Expression}')"); }
catch { return null; }
}
}
private const string DieFormat = "\x1b[34;1m";
private static readonly Regex DiePattern = new Regex(@"(\d+)d(\d+)");
public RollExpression(IList<string> parts) {
this.Parts = parts;
this.Print = "";
this.Expression = "";
// build expression from string parts
foreach(string piece in Parts) {
// die expression substitution
var dieCheck = DiePattern.Match(piece);
if(dieCheck.Success) {
// get /(d+)/ capture group values
var count = int.Parse(dieCheck.Groups[1].Value);
var sides = int.Parse(dieCheck.Groups[2].Value);
// and build roll outcomes
this.Print += $"{DieFormat}( ";
this.Expression += "( ";
for(int i = 0; i < count; i++) {
var roll = Util.Roll(sides);
if(i < count - 1) {
this.Print += $"{roll}, ";
this.Expression += $"{roll} + ";
} else {
var part = $"{roll} ";
this.Print += $"{roll} ){Format.Reset} ";
this.Expression += $"{roll} ) ";
}
}
} else {
var part = $"{piece} ";
this.Expression += part;
this.Print += part;
}
}
}
}
}