/* Function: VerifyCoords * Purpose : Verify that the rover coordinates falls within the zone bounds. * Notes : */ private RNResult VerifyCoords(Coords newRoverCoords) { RNResult rnRes = new RNResult(Severity.Success, ModuleId.RoverNav, (int)RoverNavResult.Success); if ((newRoverCoords.x < zoneMin.x) || (newRoverCoords.x > zoneMax.x)) { rnRes = new RNResult(Severity.Error, ModuleId.RoverNav, (int)RoverNavResult.ErrRoverBoundsX); } if ((newRoverCoords.y < zoneMin.y) || (newRoverCoords.y > zoneMax.y)) { rnRes = new RNResult(Severity.Error, ModuleId.RoverNav, (int)RoverNavResult.ErrRoverBoundsY); } return(rnRes); }
/* Function: VerifyZoneBounds * Purpose : Verify the validity of the zone bounds. * Notes : */ private RNResult VerifyZoneBounds(Coords zoneMinCoord, Coords zoneMaxCoord) { RNResult rnRes = new RNResult(Severity.Success, ModuleId.RoverNav, (int)RoverNavResult.Success); if (zoneMaxCoord.x < zoneMinCoord.x) { rnRes = new RNResult(Severity.Error, ModuleId.RoverNav, (int)RoverNavResult.ErrZoneBoundsX); } if (rnRes.severity == Severity.Success) { if (zoneMaxCoord.y < zoneMinCoord.y) { rnRes = new RNResult(Severity.Error, ModuleId.RoverNav, (int)RoverNavResult.ErrZoneBoundsY); } } return(rnRes); }
private bool PerformTest(ref TestData[] testDataList) { bool testPassed = true; RoverNav roverNav = new RoverNav(false); foreach (TestData testData in testDataList) { CmdSet cmndSet = new CmdSet(); cmndSet.zoneMin.x = 0; cmndSet.zoneMin.y = 0; cmndSet.zoneMax.x = 0; cmndSet.zoneMax.y = 0; cmndSet.startPos.coords.x = 0; cmndSet.startPos.coords.y = 0; cmndSet.startPos.cardinalPt = CardinalPoint.North; cmndSet.commands = ""; RNResult rnRes = roverNav.ParseCommandSet(testData.cmndSet, ref cmndSet); if (rnRes.severity == Severity.Success) { rnRes = roverNav.ValidateCommandSet(cmndSet); } Position curPos = roverNav.CurrentPosition; String outputData = String.Format("{0} {1}", roverNav.FormatPosition(curPos), rnRes.FormatResult()); String comparisonStr = "Success"; if (outputData != testData.navOutput) { comparisonStr = "Fail"; testPassed = false; } System.Console.WriteLine("..." + testData.cmndSet + "..." + comparisonStr); } return(testPassed); }
/* Function: ParseCommandSet * Purpose : * Notes : */ public RNResult ParseCommandSet(String cmndsetStr, ref CmdSet cmdset) { RNResult rnRes = new RNResult(Severity.Success, ModuleId.RoverNav, (int)RoverNavResult.Success); String leftDelimeter = "["; String rightDelimeter = "]"; // Initialise the member variables Initialise(); // Remove redundant characters from the string String resultStr = ""; for (int i = 0; i < cmndsetStr.Length; i++) { if ((cmndsetStr[i] != ' ') && (cmndsetStr[i] != '\r') && (cmndsetStr[i] != '\n')) { resultStr += cmndsetStr[i]; } } // Extract the parameters (enclosed with []) of the command set ArrayList cmdsetParams = new ArrayList(); rnRes = GetEnclosedParams(resultStr, leftDelimeter, rightDelimeter, cmdsetParams); if (rnRes.severity != Severity.Success) { return(rnRes); } // Validate the parameter data rnRes = VerifyCommandSetData(cmdsetParams, ref cmdset); if (rnRes.severity != Severity.Success) { return(rnRes); } return(rnRes); }
/* Function: ValidateCommandSet * Purpose : * Notes : */ public RNResult ValidateCommandSet(CmdSet cmdset) { RNResult rnRes = new RNResult(Severity.Success, ModuleId.RoverNav, (int)RoverNavResult.Success); rnRes = VerifyZoneBounds(cmdset.zoneMin, cmdset.zoneMax); if (rnRes.severity != Severity.Success) { return(rnRes); } zoneMin = cmdset.zoneMin; zoneMax = cmdset.zoneMax; rnRes = VerifyCoords(cmdset.startPos.coords); if (rnRes.severity != Severity.Success) { return(rnRes); } curPos.coords = cmdset.startPos.coords; curPos.cardinalPt = cmdset.startPos.cardinalPt; rnRes = ExecuteCommands(cmdset.commands); return(rnRes); }
/* Function: DisplayError * Purpose : * Notes : */ static void DisplayError(RNResult rnRes) { if (rnRes.module == ModuleId.RoverNav) { switch (rnRes.error) { case (Int32)RoverNavResult.ErrInvalidCmdChar: System.Console.WriteLine("One or more of the command set parameters contain invalid input data.\n"); break; case (Int32)RoverNavResult.ErrEmptyCmdsetParam: System.Console.WriteLine("One or more of the command set parameters are empty.\n"); break; case (Int32)RoverNavResult.ErrInvalidNoCmdsetParams: System.Console.WriteLine("There are no valid command set parameters.\n"); break; case (Int32)RoverNavResult.ErrZoneBoundsX: System.Console.WriteLine("The x-coordinate of the zone bounds are invalid.\n"); break; case (Int32)RoverNavResult.ErrZoneBoundsY: System.Console.WriteLine("The y-coordinate of the zone bounds are invalid.\n"); break; case (Int32)RoverNavResult.ErrRoverBoundsX: System.Console.WriteLine("The x-coordinate of the rover position is beyond the zone bound.\n"); break; case (Int32)RoverNavResult.ErrRoverBoundsY: System.Console.WriteLine("The y-coordinate of the rover position is beyond than the zone bound.\n"); break; } } }
/* Function: GetParams * Purpose : * Notes : */ private RNResult GetParams(String paramStr, String paramDelimeter, ArrayList validChars, ArrayList paramsList) { RNResult rnRes = new RNResult(Severity.Success, ModuleId.RoverNav, (int)RoverNavResult.Success); int startIndex = 0; int endIndex = 0; int paramstrLen = paramStr.Length; while ((startIndex >= 0) && (endIndex >= 0) && (startIndex < paramstrLen)) { int paramLen = 0; endIndex = paramStr.IndexOf(paramDelimeter, startIndex); if (endIndex == -1) { paramLen = paramstrLen - startIndex; } else { paramLen = endIndex - startIndex; } if (paramLen > 0) { String parameter = paramStr.Substring(startIndex, paramLen); if (parameter.Length > 0) { paramsList.Add(parameter); } startIndex = endIndex + 1; } } // Does the parameters contain only valid characters int expectedNoParams = validChars.Count; int noParams = paramsList.Count; if (expectedNoParams == noParams) { for (int i = 0; i < noParams; i++) { String param = paramsList[i].ToString(); String validCharsForParam = validChars[i].ToString(); int j = 0; for (j = 0; j < param.Length; j++) { if (!validCharsForParam.Contains(param[j])) { break; } } if (j < param.Length) { rnRes = new RNResult(Severity.Error, ModuleId.RoverNav, (int)RoverNavResult.ErrInvalidCmdChar); break; } } } else { rnRes = new RNResult(Severity.Error, ModuleId.RoverNav, (int)RoverNavResult.ErrInvalidNoCmdsetParams); } return(rnRes); }
/* Function: GetEnclosedParams * Purpose : * Notes : */ private RNResult GetEnclosedParams(String paramStr, String leftDelimeter, String rightDelimeter, ArrayList cmdsetParams) { RNResult rnRes = new RNResult(Severity.Success, ModuleId.RoverNav, (int)RoverNavResult.Success); int startIndex = 0; int endIndex = 0; int paramstrLen = paramStr.Length; while ((startIndex >= 0) && (startIndex < paramstrLen)) { try { startIndex = paramStr.IndexOf(leftDelimeter, startIndex); endIndex = paramStr.IndexOf(rightDelimeter, startIndex); if ((startIndex != -1) && (endIndex != -1) && (endIndex > startIndex) && (endIndex < paramstrLen)) { int paramLen = endIndex - startIndex - 1; if (paramLen > 0) { String parameter = paramStr.Substring(startIndex + 1, paramLen); if (parameter.Length > 0) { cmdsetParams.Add(parameter); } if (endIndex < (paramstrLen - 1)) { endIndex++; startIndex = endIndex; } else { startIndex = endIndex = -1; } } else { rnRes = new RNResult(Severity.Error, ModuleId.RoverNav, (int)RoverNavResult.ErrEmptyCmdsetParam); } } } catch { } if (rnRes.severity != Severity.Success) { startIndex = endIndex = -1; } } if (cmdsetParams.Count != noCmndsetParams) { rnRes = new RNResult(Severity.Error, ModuleId.RoverNav, (int)RoverNavResult.ErrInvalidNoCmdsetParams); } return(rnRes); }
/* Function: ExecuteCommands * Purpose : * Notes : */ private RNResult ExecuteCommands(String commands) { RNResult rnRes = new RNResult(Severity.Success, ModuleId.RoverNav, (int)RoverNavResult.Success); /* Process each command */ Display(curPos); char[] cmnds = commands.ToCharArray(); for (uint i = 0; i < commands.Length; i++) { switch (cmnds[i]) { case 'L': if (curPos.cardinalPt == CardinalPoint.North) { curPos.cardinalPt = CardinalPoint.West; } else { curPos.cardinalPt = (CardinalPoint)(curPos.cardinalPt - 1); } break; case 'R': if (curPos.cardinalPt == CardinalPoint.West) { curPos.cardinalPt = CardinalPoint.North; } else { curPos.cardinalPt = (CardinalPoint)(curPos.cardinalPt + 1); } break; case 'M': /* Before moving, first test if it is a valid move */ Coords newCoords; newCoords.x = curPos.coords.x; newCoords.y = curPos.coords.y; if (curPos.cardinalPt == CardinalPoint.North) { newCoords.y = curPos.coords.y + 1; } if (curPos.cardinalPt == CardinalPoint.South) { newCoords.y = curPos.coords.y - 1; } if (curPos.cardinalPt == CardinalPoint.East) { newCoords.x = curPos.coords.x + 1; } if (curPos.cardinalPt == CardinalPoint.West) { newCoords.x = curPos.coords.x - 1; } rnRes = VerifyCoords(newCoords); if (rnRes.severity == Severity.Success) { curPos.coords.x = newCoords.x; curPos.coords.y = newCoords.y; } break; default: // No default as input has been checked. break; } // Stop processing the commands if there is an error. Display(curPos); if (rnRes.severity != Severity.Success) { break; } } return(rnRes); }
// Private member functions /* Function: VerifyCommandSetData * Purpose : * Notes : */ private RNResult VerifyCommandSetData(ArrayList cmdsetParams, ref CmdSet cmdset) { RNResult rnRes = new RNResult(Severity.Success, ModuleId.RoverNav, (int)RoverNavResult.Success); String paramDelimeter = ","; String sign = "-"; String numericChars = "0123456789"; String orientationChars = "NESW"; String cmndChars = "RLM"; // Verify the first parameter, the minimum zone coordinate ArrayList subParams = new ArrayList(); ArrayList validChars = new ArrayList(); validChars.Add(sign + numericChars); validChars.Add(sign + numericChars); rnRes = GetParams(cmdsetParams[0].ToString(), paramDelimeter, validChars, subParams); if (rnRes.severity == Severity.Success) { cmdset.zoneMin.x = System.Convert.ToInt32(subParams[0]); cmdset.zoneMin.y = System.Convert.ToInt32(subParams[1]); } // Verify the second parameter, the maximum zone coordinate subParams.Clear(); validChars.Clear(); if (rnRes.severity == Severity.Success) { validChars.Add(sign + numericChars); validChars.Add(sign + numericChars); rnRes = GetParams(cmdsetParams[1].ToString(), paramDelimeter, validChars, subParams); if (rnRes.severity == Severity.Success) { cmdset.zoneMax.x = System.Convert.ToInt32(subParams[0]); cmdset.zoneMax.y = System.Convert.ToInt32(subParams[1]); } } // Verify the third parameter, the rover's starting position subParams.Clear(); validChars.Clear(); if (rnRes.severity == Severity.Success) { validChars.Add(sign + numericChars); validChars.Add(sign + numericChars); validChars.Add(orientationChars); rnRes = GetParams(cmdsetParams[2].ToString(), paramDelimeter, validChars, subParams); if (rnRes.severity == Severity.Success) { cmdset.startPos.coords.x = System.Convert.ToInt32(subParams[0]); cmdset.startPos.coords.y = System.Convert.ToInt32(subParams[1]); String cardinalPtChar = subParams[2].ToString(); cmdset.startPos.cardinalPt = CharToCardinalPoint(cardinalPtChar[0]); } } // Verify the fourth parameter, the list of commands subParams.Clear(); validChars.Clear(); if (rnRes.severity == Severity.Success) { validChars.Add(cmndChars); rnRes = GetParams(cmdsetParams[3].ToString(), paramDelimeter, validChars, subParams); if (rnRes.severity == Severity.Success) { cmdset.commands = subParams[0].ToString(); } } return(rnRes); }
/* Function: Main * Purpose : * Notes : */ static void Main(string[] args) { RNResult rnRes = new RNResult(Severity.Success, ModuleId.RoverNav, (int)RoverNavResult.Success); bool displayData = true; if (args.Length == 1) { if (args[0] == "Test") { TestRoverNav testRoverNav = new TestRoverNav(); testRoverNav.PerformAllTests(); return; } } if (args.Length != 2) { System.Console.WriteLine("Syntax:\n\n"); System.Console.WriteLine("RoverNavSystem [intput file] [output file]\n\n"); System.Console.WriteLine(" [input file] is the input file with the following format:\n"); System.Console.WriteLine(" [xmin, ymin] [xmax, ymax] [xstart, ystart, hstart] [commands]"); System.Console.WriteLine(" where"); System.Console.WriteLine(" [xmin, ymin] is the minimum cartesian coordinate of the zone's boundary."); System.Console.WriteLine(" [xmax, ymax] is the maximum cartesian coordinate of the zone's boundary."); System.Console.WriteLine(" [xstart, ystart, hstart] is the starting position and heading of the rover."); System.Console.WriteLine(" [commands] is a list of commands, directing the rover where to go.\n"); System.Console.WriteLine(" [output file] is the output file with the following format:\n"); System.Console.WriteLine(" [xpos, ypos, hpos] [moduleId, resultcode]"); System.Console.WriteLine(" where"); System.Console.WriteLine(" [xpos, ypos, hpos] is the resulting position and heading of the rover."); System.Console.WriteLine(" [moduleId, resultcode] is the module ID and resultcode."); System.Console.ReadKey(); return; } String inputFile = args[0]; String outputFile = args[1]; // Verify that the file exists. if (!System.IO.File.Exists(inputFile)) { System.Console.WriteLine("The file, {0}, does not exists.\n", inputFile); return; } // Read the input from a file. String inputText = ""; try { inputText = System.IO.File.ReadAllText(inputFile); } catch { System.Console.WriteLine("Unable to read the file, {0}.\n", inputFile); return; } /* Initialize the command set structure */ CmdSet cmndSet = new CmdSet(); cmndSet.zoneMin.x = 0; cmndSet.zoneMin.y = 0; cmndSet.zoneMax.x = 0; cmndSet.zoneMax.y = 0; cmndSet.startPos.coords.x = 0; cmndSet.startPos.coords.y = 0; cmndSet.startPos.cardinalPt = CardinalPoint.North; cmndSet.commands = ""; RoverNav roverNav = new RoverNav(displayData); rnRes = roverNav.ParseCommandSet(inputText, ref cmndSet); if (rnRes.severity == Severity.Success) { rnRes = roverNav.ValidateCommandSet(cmndSet); } if (rnRes.severity == Severity.Success) { System.Console.WriteLine("The command set in file, {0}, executed successfully and is ready for transmission.\n", inputFile); } else { System.Console.WriteLine("Unable to execute the command set in file, {0}.\n", inputFile); DisplayError(rnRes); } // Get the current position even if the command set resulted in an error. Position curPos = roverNav.CurrentPosition; String dataToSend = String.Format("{0} {1}", roverNav.FormatPosition(curPos), rnRes.FormatResult()); System.IO.File.WriteAllText(outputFile, dataToSend); if (displayData) { System.Console.WriteLine(dataToSend); } }