using System.Collections.Generic;
public static void Main()
var a = new CommandInput(Console.ReadLine());
Console.WriteLine(a + "\n" + a.error);
foreach(var cmd in a.commands)
public class CommandInput
public List<Command> commands = [];
public Dictionary<string, string> variables = [];
public string error = null;
public override string ToString()
return $"{{doPersists:\"{doPersist}\", commands:[{string.Join(",", commands)}], variables:[{string.Join(",", variables.Keys)}]}}";
public CommandInput(string input)
if(string.IsNullOrWhiteSpace(input)) return;
this.doPersist = input[0] == '#';
if(doPersist) input = input.Remove(0,1);
bool hasVariablesSection = input.Contains("||");
string commandsSection = null;
string variablesSection = null;
variablesSection = input.Split(new[] { "||" }, StringSplitOptions.RemoveEmptyEntries)[0];
error = "Missing variable declarations before the || operator";
string[] variableDefinitions = variablesSection.Split('|', StringSplitOptions.RemoveEmptyEntries);
foreach (var varDefinition in variableDefinitions)
string[] varDefinitionTerms = varDefinition.Split(':', StringSplitOptions.RemoveEmptyEntries);
key = varDefinitionTerms[0];
value = varDefinitionTerms[1];
variables.Add(key, value);
commandsSection = input.Split(new[] { "||" }, StringSplitOptions.RemoveEmptyEntries)[1];
error = "Missing command(s) after variable declaration section";
string[] commands = commandsSection.Split(new[] { ";;" }, StringSplitOptions.RemoveEmptyEntries);
for(int i = 0; i < commands.Length; i++)
commands[i] = commands[i].Trim();
foreach (var _command in commands)
string command = _command;
if(string.IsNullOrWhiteSpace(command)) continue;
if (command.Length >= 2) doForce = command.Substring(0,2).Contains('!');
else doForce = command.Substring(0,1).Contains('!');
if(doForce) command = StringUtils.ReplaceFirst(command,"!","");
Command commandObject = new Command(command, variables,doForce);
if(commandObject.command == "")
Console.WriteLine($"ERROR: Cannot find command '{command}'");
this.commands.Add(commandObject);
public string command = "";
public string[] arguments = [];
public Dictionary<string, string> variables = [];
public CommandInfo commandInfo = null;
commandInfo.behaviour?.Invoke(null,new[]{this});
public Command(string input, Dictionary<string, string> variables, bool doForce = false)
this.variables = variables;
foreach (var cmdInfo in Commands.commands)
if (cmdInfo.IsValid(input))
command = cmdInfo.command;
arguments = input.Remove(0, command.Length).Trim().Split(' ');
for(int i = 0; i < arguments.Length; i++)
string arg = arguments[i];
foreach(var variable in variables)
arg = arg.Replace($"&{variable.Key};",variable.Value);
foreach(var cmdInfo in Commands.commands)
if(cmdInfo.command == command && cmdInfo.IsValid(input))
this.commandInfo = cmdInfo;
public override string ToString()
return $"{{doForce:{doForce},command:\"{command}\",arguments:[{string.Join(",", arguments)}]}}";
public bool isMultiargument;
public string[] arguments;
public MethodInfo behaviour = null;
public bool IsValid(string input)
if (input.Trim().Length < command.Length)
bool doesInputStartsWithCommandName = false;
if (arguments.Length > 0)
doesInputStartsWithCommandName = input.StartsWith(command);
doesInputStartsWithCommandName = input.StartsWith(command);
bool hasCorrectArguments = false;
string[] inputArguments = input.Remove(0, command.Length).Trim().Split(' ', StringSplitOptions.RemoveEmptyEntries);
hasCorrectArguments = inputArguments.Length >= arguments.Length;
hasCorrectArguments = arguments.Length == inputArguments.Length;
return doesInputStartsWithCommandName && hasCorrectArguments;
public CommandInfo(string command, string[] arguments, bool isMultiargument, string help, string? behaviour = null)
this.arguments = arguments;
this.isMultiargument = isMultiargument;
this.behaviour = typeof(ConsoleMethods).GetMethod(behaviour ?? "");
public static class Commands
public static CommandInfo[] commands =
new("u say", new[] { "message" }, true, "Sends a message to Monika"),
new("m say", new[] { "message" }, true, "Makes Monika say something","MSay"),
new("m resp", new[] { "message" }, true, "Sends a message to Monika"),
new("m cont", new string[] { }, false, "Continues with Monika's dialogue"),
new("m expr", new[] { "pose", "expression" }, false, "Changes Monika's pose and expression"),
new("m expr", new[] { "fullbody" }, false, "Changes Monika's pose and expression"),
new("txb show", new string[] {}, false, "Shows the textbox"),
new("txb show", new string[] {"message"}, true, "Sets the value of the textbox and shows it"),
new("txb hide", new string[] {}, false, "Hide the textbox"),
new("txb set", new string[] {"message"}, true, "Sets the value of the textbox"),
new("wnd cfg", new string[] {}, false, "Opens the config window"),
new("wnd msg", new string[] {}, false, "Opens the user message window"),
new("wnd visuals", new string[] {}, false, "Opens the visuals window"),
new("wnd controls", new string[] {}, false, "Opens the controls window"),
new("wnd login", new string[] {}, false, "Opens the login window"),
new("wnd console", new string[] {}, false, "Opens the console window"),
new("wnd starterr", new string[] {}, false, "Opens the startup error window"),
new("state get", new string[] {}, false, "Gets the application state"),
new("state set", new string[] {"state"}, false, "Sets the application state"),
new("data get", new string[] {}, false, "Gets the user data"),
new("data rm", new string[] {"key"}, false, "Removes the user data"),
new("app exit -f", new string[] {}, false, "Forces the application close","AppExitF"),
new("app exit", new string[] {"motive"}, false, "Closes the application","AppExit"),
new("yes", new string[] {}, false, "Confirms the action of a command"),
new("no", new string[] {}, false, "Denies the action of a command"),
new("key", new string[] {}, false, "Gets a random generated key"),
new("var", new string[] {"name", "value"}, true, "Create or sets a variable"),
new("help", new string[] {"command"}, true, "Displays the help menu of a specific command","HelpSpecific"),
new("help", new string[] {}, false, "Displays the help menu","Help"),
new("exit", new string[] {}, false, "Closes the console"),
public static class ConsoleMethods
public static void Help(Command cmd)
List<CommandInfo> commands = Commands.commands.ToList();
for(int i = 0; i < commands.Count; i++)
CommandInfo cmdInfo = commands[i];
List<string> messageSegments = [];
messageSegments.Add(cmdInfo.command);
if(cmdInfo.arguments.Length > 0)
foreach(var arg in cmdInfo.arguments)
if(j == cmdInfo.arguments.Length-1 && cmdInfo.isMultiargument)
argsSegment += $"<{arg}...> ";
argsSegment += $"<{arg}> ";
argsSegment = argsSegment.Trim();
messageSegments.Add(argsSegment);
messageSegments.Add($"| {cmdInfo.help}");
string message = string.Join(" ",messageSegments);
Console.WriteLine(message);
public static void HelpSpecific(Command cmd)
List<CommandInfo> commands = [];
string search = string.Join(" ",cmd.arguments);
foreach(var command in Commands.commands)
if(command.command.StartsWith(search))
for(int i = 0; i < commands.Count; i++)
CommandInfo cmdInfo = commands[i];
List<string> messageSegments = [];
messageSegments.Add(cmdInfo.command);
if(cmdInfo.arguments.Length > 0)
foreach(var arg in cmdInfo.arguments)
if(j == cmdInfo.arguments.Length-1 && cmdInfo.isMultiargument)
argsSegment += $"<{arg}...> ";
argsSegment += $"<{arg}> ";
argsSegment = argsSegment.Trim();
messageSegments.Add(argsSegment);
messageSegments.Add($"| {cmdInfo.help}");
string message = string.Join(" ",messageSegments);
Console.WriteLine(message);
public static void AppExit(Command cmd)
public static void AppExitF(Command cmd)
public static void MSay(Command cmd)
string toSay = string.Join(" ",cmd.arguments);
Console.WriteLine($"Monika: {toSay}");
public static class StringUtils
public static string ReplaceFirst(string str, string term, string replace)
int position = str.IndexOf(term);
str = str.Substring(0, position) + replace + str.Substring(position + term.Length);