# EBTCalc (Android)

### Description

EBTCalc is a Reverse Polish Notation (RPN) calculator that can have custom buttons. Custom buttons are programmed in JavaScript with a convenient editor.

Figure 1: EBTCalc Main Screen

### RPN Calculators

RPN calculators require numbers to be entered before the operation is performed. Operations have no priority - they are performed in the order entered. Consequently RPN calculators do not need parentheses. Since numbers must be entered before the operation to be performed, to evaluate 1 + 2:
1. Press the 1 button
2. Press the Enter button
3. Press the 2 button
4. Press the + button
The result, 3, is left on the stack.

More Examples:

 Expression How to Evaluate 17 * (3 + 4) 17 Enter 3 Enter 4 + * 3.14 * 123.4^2 3.14 Enter 123.4 x^2 * (3^2 * (7^2 - 8)) / 5 3 x^2 7 x^2 8 - * 5 /

### The Value Entry Area and the Stack

Figure 2: Value Entry Area, Stack, Category Selector, Built-in Buttons, Custom Buttons

As values are entered they are displayed in the Value Entry Area. Press the BS (Back Space) button to correct errors in the value you're entering. Press the Clear Ent (Clear Entry) button to clear the entire value.

Every time you press the Enter key, the value you entered is placed at the bottom of a list, called the stack.

### Built-in Buttons

EBTCalc includes the usual buttons that you'd expect to find on a calculator. These buttons operate on values stored in the stack.

### Category Selector

Buttons are arranged in categories. To display the buttons belong to a particular category, click the Category Selector (Figure 2).

Custom buttons are added by programming them in JavaScript. To add a new button, click Edit. Buttons are organized into categories that correspond to JavaScript classes or constructors. For example, to add a new custom button to compute Fibonacci numbers, click Edit.

Add the following code, without the line numbers:

``` 1:  // category custom "My Custom Buttons"
2:  function custom() {}
3:
4:  // button custom.Fibonacci "Fibonacci Sequence"
5:  custom.Fibonacci = (x) => {
7:
8:    if (x === 1 || x === 2) {
9:      return 1;
10:    } else {
11:      return custom.Fibonacci(x - 1) + custom.Fibonacci(x - 2);
12:    }
13:  }
14:
15:  custom.sum = (a, b) => { return a + b; }
16:
17:  custom.array = (e) => { return [e, e, e]; }
```

Line 2 declares the custom class or constructor. By default, class names appear exactly as programmed in the Category Selector. In other words, by default the custom class would appears as "custom" in the Category Selector. However, this default can be over-ridden with the // category comment, as it is in line 1. Line 1 causes the category to display as "My Custom Buttons" in the Category Selector.

A method is declared in lines 5 to 13. By default, method names appear exactly as programmed in custom buttons. However, they can be over-ridden with a // button comment. Line 4 causes the custom button to have the "Fibonacci Sequence" text.

The argument (x) in line 5 comes from the bottom of the stack.

The logging statement on line 6 is used to write information useful for debugging in the log. More about the log later.

Remember: The "// button" comments are only necessary when the button text differs from the corresponding method name. For example, the methods in lines 15 and 17 have button texts of "sum" and "array", respectively.

After you've entered the JavaScript code, the editor should look like the illustration below. If your code matches the illustration, click OK to save your changes. If any syntax errors were discovered, you will be prompted to fix them.

To use your new custom button, click the Category Selector and you'll see the new "My Custom Buttons" category:

Figure 3: Creating a Custom Button

Select "My Custom Buttons" and the new custom button will be displayed:

Figure 4: Creating a Custom Button

Enter a value of 10 and click "Fibonacci Sequence". A result of 34 should be calculated, since 34 is the 10th number in the Fibonacci Series.

However, the custom.Fibonacci method is rather slow-running. It might time out. If it does, you'll see an error message like the following:

Figure 5: Timeout

### Timeouts

By default, EBTCalc will automatically stop custom methods after 15 seconds. If necessary, you can increase the timeout value by selecting the Settings menu. Select Method Timeout and specify a new timeout period. You can eliminate the timeout entirely, but this is not recommended as an inadvertent infinite loop in your JavaScript code will lock up the application.

### Logging

Logging statements like the one you added to the Custom.Fibonacci method, can be useful for debugging custom methods. To see your log statements, select "Log" with the Category Selector. Then long-click the stack. When you click the stack and keep holding your finger down, eventually a menu will be displayed:

Click Display Stack Contents and you'll see the logging messages created when the Custom.Fibonacci method was run. By default, only the most recent 100 log messages are retained. This threshold can be increased by editing the JavaScript code, but increasing the number of lines will tend to slow down the app since it permanently stores the logging statements.

### Long Clicks

To long-click an item, press it and hold your finger down. Long-click the stack to display stack contents in a wider display, or copy values from the stack. Long-click a custom button to go to that button's JavaScript code in the editor. Long-click the Value Entry Area to copy or paste that value. Only numerical values can be pasted.

Long-click the stack to display the stack in a wider format, or copy/paste stack values.

Long-click the region where new values are entered to copy/paste values.

### Defensive Programming

The Custom.Fibonacci method has some serious flaws that can be easily fixed:

1. Calling this method for non-integer values of x, or values less than 1, will cause the method to continue running until it is timed out.
2. Calling this method with very large values of x will cause it to run for an excessively long time.

To address the above issues, add the following argument validation code at the start of the Custom.Fibonacci method:

```  if (x < 1 || x > 100 || Main.FractionalPart(x) != 0) {
throw "Custom Fibonacci: Invalid Argument: " + x
}
```

Now, when invalid values of x are specified, a run time error will occur:

Figure 7: Run Time Error when Arguments are Invalid

### Hiding Methods

If you do not want a given JavaScript method to cause a custom button to be created, prefix that method with the underscore character ("_"). For example:

```function Utilities() {}

Utilities._reverseString = function(s) { ... }
```

### The Globals Object

The methods for your custom buttons can store and retrieve values in an object named "Globals". These values are retained indefinitely. In other words, a value stored in the Globals object will be available after EBTCalc is closed and re-launched.

The following values are stored in the Globals object:

• Log statements
• Values stored with the pre-programmed Store button in the Memory category

### Storing and Retrieving Named Values

Named values can be stored indefinitely and retrieved. Select the Memory category with the Category Selector. To store the bottom stack value, click the String built-in button and enter a name. Then click the Store pre-programmed button in the Memory category. To retrieve this value later, Click String and enter the name. Then click the pre-programmed Retrieve button in the Memory category.

### Prompts

If you select "Dates" with the Category Selector and click the pre-programmed EnterDateTime button, you'll see that custom buttons can prompt the user for one or more values, with validation. For instance, the EnterDateTime button's JavaScript code prompts the user for the year, month, day, and time:

Figure 8: Prompting the User for Values

In the above illustration, the label for the time value is red because a valid value has not yet been entered. The minutes value is missing.

The JavaScript code for Dates.EnterDate is a good example of prompting the user for data:

``` 1: Dates.EnterDateTime = function() {
2:   var values = Prompt.prompt(
3:     [
4:       ["Year", "v", "[0-9]{4}", ""],
5:       ["Month", "s", "1|2|3|4|5|6|7|8|9|10|11|12", ""],
6:       ["Day", "v", "[0-9]{1,2}", ""],
7:       ["Time (hh:mm)", "v", "[0-9]{1,2}:[0-9]{1,2}", "00:00"],
8:       ["am/pm", "s", "AM|PM", "1"]
9:     ], "Enter Date/Time")
10:
11:   if (values != null) {
12:     return new Date(values[1] + "/" + values[2] + "/" + values[0] + " " + values[3] + " " + values[4])
13:   }
14: }
```

The Prompt.prompt method takes two arguments. The first is an array that specifies the fields for which the user will be prompted. The second is a string that will be displayed to the user. Each row of the array specifies a single value to be supplied by the user. Each row contains the following four elements:

 Element Number Description 0 Field Label displayed to user 1 "v" if this field is a free-form value. "s" if this field is a spinner (list of selections). 2 If this field is a free-form value, this element is a regular expression used to validate the field value. You can specify an empty string if you don't need validation.If this field is a spinner, this element specifies the spinner values, separated by "|". 3 If this field is a free-form value, this element specifies the default value. If this field is a spinner, this element specifies the ordinal value of the default selection. For example, to default to the first value in the list, use "1". Use "2" to default to the second item in the list, and so on.

### JavaScript Version

EBTCalc uses the Rhino JavaScript engine to run custom code. It currently uses Rhino version 1.7.14. The various JavaScript features supported by Rhino, hence EBTCalc, can be seen in the ECMAScript 6 compatibility table, but be sure to check the "Show obsolete platforms" checkbox first.

### Free and Paid Versions

The free version of EBTCalc does not allow custom buttons to be created, and does not allow the code for pre-programmed buttons to be changed. Upgrade to the paid version to add new custom buttons and modify pre-programmed buttons, and to support continued EBTCalc development!