Skip to content

Commit

Permalink
Code Optimization
Browse files Browse the repository at this point in the history
Improved command parsing
Updates to userguide export command.  No backslashes!
LR calc optimization
Additional exception processing
Grammer/spelling
Much is based on IntelliJ recommendations
  • Loading branch information
frossm committed Feb 15, 2024
1 parent 4854c9a commit 9ed1218
Show file tree
Hide file tree
Showing 11 changed files with 69 additions and 57 deletions.
2 changes: 1 addition & 1 deletion mdbook/src/Chapters/OperationalCommands.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Operational commands are commands that do not directly impact your stack numbers
|-------|-------------|
|debug|Toggle debug mode which will display additional information on what's happening internally in the program. Same as the `-D` command line switch. Probably not the useful for a normal user|
|h <br> ?|`h` or `?` will display the in-program help page|
|export `FILE`|`Export` will simply export the current stack values into the file specified. The format is very simple with one number per line. The output will be ordered as on the screen with the top of the stack item at the end of the file and the last stack item at the top. If the file exists, it will be overwritten.|
|export `FILE`|`Export` will simply export the current stack values into the file specified. The format is very simple with one number per line. The output will be ordered as on the screen with the top of the stack item at the end of the file and the last stack item at the top. If the file exists, it will be overwritten. <br> <br>NOTE: Please ensure the backslash (`/`) is used as a directory separator, even on Windows. Backslashes (`\`) are **NOT** suported and are removed when the command is entered|
|import `FILE`|With `import` RPNCalc will replace the current stack with one loaded from a file. The file format is simple, just one number per line. Do not include any comments or alphanumeric/special characters. Just one number per line with the last number being `line1` - just like the display in RPNCalc|
|list stacks|List the current saved stacks on the system, including the one currently in use|
|list mem|Display the contents of the memory slots|
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<groupId>org.fross</groupId>
<artifactId>rpncalc</artifactId>
<version>5.2.2</version>
<version>5.2.3</version>
<packaging>jar</packaging>

<name>rpncalc</name>
Expand Down
2 changes: 1 addition & 1 deletion snap/snapcraft.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: rpncalc
version: '5.2.2'
version: '5.2.3'
summary: The command line Reverse Polish Notation (RPN) calculator
description: |
RPNCalc is an easy to use command line based Reverse Polish
Expand Down
8 changes: 5 additions & 3 deletions src/main/java/org/fross/rpncalc/CommandParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ public static void Parse(StackObj calcStack, StackObj calcStack2, String cmdInpu
calcStack.push(new BigDecimal(cmdInputCmd));

// Handle NumOps - numbers with a single operand at the end (*, /, +, -, ^)
} else if (cmdInputCmd.matches("^-?\\d*\\.?\\d*[Ee]?\\d*[\\*\\+\\-\\/\\^]")) {
} else if (cmdInputCmd.matches("^-?\\d*\\.?\\d*[Ee]?\\d*[*+\\-/^]")) {
// Save current calcStack to the undoStack
calcStack.saveUndo();

Expand All @@ -507,7 +507,7 @@ public static void Parse(StackObj calcStack, StackObj calcStack2, String cmdInpu
Output.debugPrintln("NumOp Found: Num= '" + tempNum + "'");
Output.debugPrintln("NumOp Found: Op = '" + tempOp + "'");
calcStack.push(new BigDecimal(tempNum));
calcStack = Math.Parse(tempOp, calcStack);
Math.Parse(tempOp, calcStack);

} catch (NumberFormatException ex) {
// Prevents a crash if user enters "-+" (which they shouldn't do)
Expand Down Expand Up @@ -557,7 +557,9 @@ public static void Parse(StackObj calcStack, StackObj calcStack2, String cmdInpu

}
break;
}

} // End of giant switch statement

}

}
23 changes: 14 additions & 9 deletions src/main/java/org/fross/rpncalc/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ public static void DisplayStatusLine() {
* @param args
*/
public static void main(String[] args) {
String cmdInput = ""; // What the user enters in totality
String cmdInputCmd = ""; // The first field - the command
String cmdInput = ""; // What the user enters in totality
String cmdInputCmd = ""; // The first field - the command
String cmdInputParam = ""; // The remaining string - Parameters
Preferences prefConfig = Preferences.userRoot().node("/org/fross/rpn/config"); // Persistent configuration settings

Expand Down Expand Up @@ -242,6 +242,7 @@ public static void main(String[] args) {
// Input command from user
try {
cmdInput = scanner.readLine("\n" + INPUT_PROMPT);

} catch (UserInterruptException ex) {
// User entered Ctrl-C so exit the program gracefully by placing the "exit" command as the input
cmdInput = "exit";
Expand All @@ -252,6 +253,12 @@ public static void main(String[] args) {
Output.fatalError("Could not read user input\n" + ex.getMessage(), 5);
}

// If nothing was entered, stop processing and request new input
if (cmdInput.isEmpty()) {
Output.debugPrintln("Blank line entered");
continue;
}

// Break each entered line (cmdInput) into a command (cmdInputCmd) and a parameter (cmdInputParam) string
try {
// Remove any commas from the string allowing for numbers such as "12,123" to be entered
Expand All @@ -264,11 +271,9 @@ public static void main(String[] args) {
cmdInputParam = ci[1];

} catch (ArrayIndexOutOfBoundsException e) {
// Ignore this exception if there is no command or parameter entered
if (cmdInputCmd.isEmpty()) {
Output.debugPrintln("Blank line entered");
continue;
}
// TODO: Ignore this error as it will trigger if just a command is entered with no parameter. There must be a better way...
} catch (Exception e) {
Output.printColorln(Ansi.Color.RED, "ERROR: Problem parsing the command: '" + cmdInput + "' into command and arguments");
}

// While in debug mode, show the entered text along with the broken up command and parameter
Expand All @@ -282,11 +287,11 @@ public static void main(String[] args) {
// Call the parser to send the command to the correct function to execute
CommandParser.Parse(calcStack, calcStack2, cmdInput, cmdInputCmd, cmdInputParam);

// Clear input parameters before we start again
// Clear input parameters before we start again with the next command
cmdInputCmd = "";
cmdInputParam = "";

} // End While Loop
} // End While Command Loop

// If recording is on, complete the recording off process before exiting
if (UserFunctions.recordingIsEnabled()) {
Expand Down
24 changes: 11 additions & 13 deletions src/main/java/org/fross/rpncalc/StackCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public static void cmdAddAll(StackObj calcStack, String arg) {
keepFlag = true;
}
} catch (StringIndexOutOfBoundsException ex) {
keepFlag = false;
// keepFlag is already set to false, so just ignore this error
}

// Counter to hold the accumulating total
Expand Down Expand Up @@ -128,7 +128,7 @@ public static void cmdAverage(StackObj calcStack, String arg) {
keepFlag = true;
}
} catch (StringIndexOutOfBoundsException ex) {
keepFlag = false;
// keepFlag is already false so just ignore this error
}

// Calculate the mean
Expand Down Expand Up @@ -233,13 +233,13 @@ public static void cmdDelete(StackObj calcStack, String arg) {

// Determine line to delete by looking at arg
try {
// If this doesn't have an exception, user entered in a single number integer
// If this doesn't have an exception, user has entered a single number integer
// Simple delete that line
startLine = Integer.parseInt(arg);
endLine = startLine;

} catch (NumberFormatException ex) {
// If a dash is present, user entered in a range
// If a dash is present, user entered a range
if (arg.contains("-")) {
try {
startLine = Integer.parseInt(arg.split("-")[0]);
Expand Down Expand Up @@ -439,11 +439,9 @@ public static void cmdLinearRegression(StackObj calcStack, String args) {
if (a.toLowerCase().startsWith("a")) {
argAdd = true;
Output.debugPrintln("Setting LR ADD flag");
continue;
} else {
argX = new BigDecimal(a).subtract(BigDecimal.ONE);
Output.debugPrintln("Setting LR 'x' value to : " + argX);
continue;
}
}
}
Expand Down Expand Up @@ -500,8 +498,8 @@ public static void cmdLinearRegression(StackObj calcStack, String args) {
BigDecimal a = a_top.divide(a_bottom, MathContext.DECIMAL128);

BigDecimal b_top = n.multiply(sumXY).subtract(sumX.multiply(sumY));
BigDecimal b_bottom = n.multiply(sumX2).subtract(sumX.pow(2));
BigDecimal b = b_top.divide(b_bottom, MathContext.DECIMAL128);
// b_bottom is the same as a_bottom so just it that
BigDecimal b = b_top.divide(a_bottom, MathContext.DECIMAL128);

// Output details if debug is enabled
Output.debugPrintln("n: " + n.toPlainString());
Expand Down Expand Up @@ -595,7 +593,7 @@ public static boolean cmdMaximum(StackObj calcStack) {
largestValue = calcStack.get(i);
}

// Add lowest value to the stack
// Add the lowest value to the stack
calcStack.push(largestValue);

return true;
Expand Down Expand Up @@ -625,7 +623,7 @@ public static void cmdMedian(StackObj calcStack, String arg) {
keepFlag = true;
}
} catch (StringIndexOutOfBoundsException ex) {
keepFlag = false;
// keepFlag is already false so just ignore this error
}

// Calculate the median
Expand Down Expand Up @@ -664,7 +662,7 @@ public static boolean cmdMinimum(StackObj calcStack) {
lowestValue = calcStack.get(i);
}

// Add lowest value to the stack
// Add the lowest value to the stack
calcStack.push(lowestValue);

return true;
Expand Down Expand Up @@ -728,7 +726,7 @@ public static void cmdOperand(StackObj calcStack, String op) {
public static void cmdRandom(StackObj calcStack, String param) {
long low = 1L;
long high = 100L;
long randomNumber = 0L;
long randomNumber;

// Parse out the low and high numbers
try {
Expand Down Expand Up @@ -933,7 +931,7 @@ public static void cmdStdDeviation(StackObj calcStack, String arg) {
keepFlag = true;
}
} catch (StringIndexOutOfBoundsException ex) {
keepFlag = false;
// keepFlag is already false so just ignore this error
}

// Step1: Get the mean
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/org/fross/rpncalc/StackMemory.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ public static boolean SetMaxMemorySlots(String slots) {
public static int QueryInUseMemorySlots() {
int inUseCounter = 0;

for (int i = 0; i < memorySlots.length; i++) {
if (memorySlots[i] != null) inUseCounter++;
for (BigDecimal memorySlot : memorySlots) {
if (memorySlot != null) inUseCounter++;
}

return inUseCounter;
Expand Down Expand Up @@ -138,8 +138,8 @@ public static void cmdMem(StackObj calcStack, String arg) {
String[] argParse;
int memSlot;

// Parse the command string provided. If we can't create an integer from the first
// arg then no stack number was provided
// Parse the command string provided. If we can't create an integer from the first arg then no stack number was provided
// arg contains either a command or a slot number + command
try {
argParse = arg.split(" ");
memSlot = Integer.parseInt(argParse[0]);
Expand Down
3 changes: 0 additions & 3 deletions src/main/java/org/fross/rpncalc/StackObj.java
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,6 @@ public void sort(String mode) {
sortedStack.push(tmpValue);
}

// Clear the calcStack and replace the values with the sorted stack
calcStack.clear();

// Fill the calcStack back with the sorted values from sortedStack
if (mode.equalsIgnoreCase("ascending")) {
// Ascending
Expand Down
20 changes: 11 additions & 9 deletions src/main/java/org/fross/rpncalc/StackOperations.java
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,14 @@ public static void exportStackToDisk(StackObj calcStack, String arg) {
File file = new File(fileName);
if (file.exists()) {
Output.debugPrintln("'" + fileName + "' exists - deleting");
file.delete();

// Delete the file. If it returns false, then throw an error
if (!file.delete()) {
throw new Exception("File Delete Failed");
}
}
} catch (Exception ex) {
Output.printColorln(Ansi.Color.RED, "'" + fileName + "' exists and was not able to be deleted");
Output.printColorln(Ansi.Color.RED, "'" + fileName + "' exists but could not be deleted\n" + ex.getMessage());
return;
}

Expand All @@ -239,7 +243,7 @@ public static void exportStackToDisk(StackObj calcStack, String arg) {
return;
}

Output.printColorln(Ansi.Color.CYAN, "Export successful to '" + fileName + "'");
Output.printColorln(Ansi.Color.CYAN, "Export successful: '" + new File(fileName).getAbsoluteFile() + "'");
}

/**
Expand All @@ -265,9 +269,9 @@ public static void importStackFromDisk(StackObj calcStack, String arg) {
calcStack.clear();

// Convert the strings to BigDecimal values. Skip empty lines
for (int i = 0; i < linesRead.size(); i++) {
if (!linesRead.get(i).isEmpty()) {
calcStack.push(new BigDecimal(String.valueOf(linesRead.get(i))));
for (String s : linesRead) {
if (!s.isEmpty()) {
calcStack.push(new BigDecimal(s));
}
}

Expand Down Expand Up @@ -295,9 +299,8 @@ public static void importStackFromDisk(StackObj calcStack, String arg) {
* @param stk Primary Stack
* @param item1 First item to swap
* @param item2 Second item to swap
* @return StackObj
*/
public static StackObj StackSwapItems(StackObj stk, int item1, int item2) {
public static void StackSwapItems(StackObj stk, int item1, int item2) {
int stkSize = stk.size();
BigDecimal[] tempArray = new BigDecimal[stkSize];
BigDecimal value1;
Expand All @@ -324,7 +327,6 @@ public static StackObj StackSwapItems(StackObj stk, int item1, int item2) {
stk.push(tempArray[i]);
}

return (stk);
}

}
17 changes: 8 additions & 9 deletions src/main/java/org/fross/rpncalc/UserFunctions.java
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,12 @@ public static boolean recordingIsEnabled() {
*/
public static void RecordCommand(String arg) {
// Ignore the following commands from recording
String[] ignore = {"list", "debug", "ver", "version", "h", "help", "?", "record", "rec", "function", "func", "reset", "cx", "x", "exit", "quit"};
String[] commandsToIgnore = {"list", "debug", "ver", "version", "h", "help", "?", "record", "rec", "function", "func", "reset", "cx", "x", "exit", "quit"};

// If the command starts with an ignored item, just return before adding it to the recording
for (int i = 0; i < ignore.length; i++) {
if (arg.startsWith(ignore[i])) {
Output.debugPrintln("Record ignoring the command '" + ignore[i] + "'");
for (String s : commandsToIgnore) {
if (arg.startsWith(s)) {
Output.debugPrintln("Record ignoring the command '" + s + "'");
return;
}
}
Expand Down Expand Up @@ -286,12 +286,11 @@ public static void FunctionRun(StackObj calcStack, StackObj calcStack2, String f
String[] ci = fullCommand.toLowerCase().trim().split("\\s+", 2);
command = ci[0];
param = ci[1];

} catch (ArrayIndexOutOfBoundsException e) {
// Ignore if there is no command or parameter entered
if (command.isEmpty()) {
Output.debugPrintln("Blank line entered");
continue;
}
// TODO: Ignore this error as it will trigger if just a command is entered with no parameter. There must be a better way...
} catch (Exception e) {
Output.printColorln(Ansi.Color.RED, "ERROR: Problem parsing the command: '" + fullCommand + "' into command and arguments");
}

Output.debugPrintln(" Step" + i + ": " + pChild.get("Step" + i, "Error"));
Expand Down
17 changes: 13 additions & 4 deletions src/test/java/org/fross/rpncalc/StackOperationsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,10 @@ void testExport() {

// Delete the testFile if it exists
try {
testFile.delete();
} catch (Exception ex) {
if (!testFile.delete()) {
throw new IOException("Delete Failed");
}
} catch (IOException ex) {
Output.println("Testing Export: Issue deleting test file: ' " + testFileName + "'");
}

Expand Down Expand Up @@ -228,8 +230,12 @@ void testExport() {
// Delete the test import file
try {
File file = new File(testFileName);
file.delete();

if (!file.delete()) {
throw new Exception("Unable to delete file");
}
assertFalse(testFile.exists());

} catch (Exception ex) {
Output.println("Testing Export: Issue deleting test file: ' " + testFileName + "'");
}
Expand Down Expand Up @@ -272,8 +278,11 @@ void testImport() {
// Delete the test import file
try {
File file = new File(testFileName);
file.delete();
if (!file.delete()) {
throw new Exception("Unable to delete file");
}
assertFalse(file.exists());

} catch (Exception ex) {
Output.println("Testing Import: Issue deleting test file: ' " + testFileName + "'");
}
Expand Down

0 comments on commit 9ed1218

Please sign in to comment.