/// <summary> /// Executes the commands that have been given to the Robot. /// </summary> /// <returns></returns> public InstructionExecutionResult[] Execute() { var instructions = this._commands.Select(cmd => this.ParseCommand(cmd.Trim())); var ret = instructions .Select(this.Execute) .Select(o => new InstructionExecutionResult { Executed = o.executed, LogMessage = o.log }) .ToArray(); // Perform a final Report if the user hasn't explicitly issued one himself if (!(instructions.LastOrDefault() is ReportInstruction)) { this.Execute(ReportInstruction.Create()); } return(ret); }
/// <summary> /// Parses a string command into an Instruction. /// </summary> /// <param name="command">The string command to parse</param> /// <returns>An concrete Instruction</returns> private Instruction ParseCommand(string command) { // Check which regex matches the command, and therefore derive the command's type var matchingRegex = this.Regexes .DefaultIfEmpty(KeyValuePair.Create(InstructionType.Unknown, new Regex(""))) .FirstOrDefault(kvp => kvp.Value.IsMatch(command)); var matchedType = matchingRegex.Key; var rgx = matchingRegex.Value; switch (matchedType) { default: case InstructionType.Unknown: return(NoopInstruction.Create(command)); case InstructionType.Place: { var matches = rgx.Match(command); int x = int.Parse(matches.Groups.ElementAt(1).Value); int y = int.Parse(matches.Groups.ElementAt(2).Value); var direction = Enum.Parse <MovementDirection>(matches.Groups.ElementAt(3).Value.ToTitleCase()); return(PlaceInstruction.Create(x, y, direction, command)); } case InstructionType.Move: return(MoveInstruction.Create(command)); case InstructionType.Rotate: { var matches = rgx.Match(command); var rotationDirection = matches.Groups.ElementAt(1).Value.ToLower() == "right" ? RotationDirection.Clockwise : RotationDirection.CounterClockwise; return(RotateInstruction.Create(rotationDirection, command)); } case InstructionType.Report: return(ReportInstruction.Create(command)); } }