Hello Oppst85,
After thinking in the most complex ways, I was able to design a simple solution to this. I used
this JavaScript to achieve this. Initially, I thought of making a function (in App Inventor) that'll evaluate the brackets first, then split the numbers in front of, and after the operators and store them in an array, then later see which bracket is the innermost (so as to evaluate it first) and later apply PEMDAS/BODMAS rule to calculate and then store everything in another variable....bla bla bla and everything was getting too complex to be implemented directly in App Inventor. While making this in that way for you, midway, I came across
this snippet. So I decided to follow the same trail.
Although, theoretically it could be implemented in App Inventor alone, I used a
WebViewer component and made a simple HTML file that''ll perform the calculation by getting the values from the App Inventor App using the
WebViewer.WebViewString property (
Thanks to this snippet). On the HTML part, I've used a
Math expression processing library to perform calculations. This simplifies the whole process and enables a lot of features. This is how the App works:
Whenever the Calculate button is clicked, the 'x' variable (if any) in the given expression (first text box) is replaced with the number entered in the second text box. Note that it is replaced and not substituted. Then, the value is passed to the HTML code via the WebViewer's WebViewString property. The HTML File then receives the raw expression and sends it to the JavaScript, which is a math processing library using JavaScript. Then once the calculation has been performed, the HTML file set's the result as the page's title. Now using the WebViewer.CurrentPageTitle, we can obtain the result directly. In my example, I've used a label to display the result. However, you can also use a third text box to display the result, if you want.
As I said above, this 'x' value just gets replaced instead of getting substituted. So, while giving an (5*x)+2 will produce an answer 10 (if x=2 in the 2nd Textbox), simply writing (5x)+2 will produce an answer 54 (if x=2 in the second Textbox, then 5x will become 52). Be wary of that.
Here's the layout:

The code is ridiculously simple:

Initialize a global variable "lblTxt" to *empty string*. I've used this variable to store the expression (containing x), so that when I replace the x with a value, it won't reflect in the Text box 1

I've used the downcase function just in case if the user enters the math variable x in CAPS. Upon clicking the Calculate button, these actions happen.
Note that in the above example, I've set the WebViewer to go that URL. This will only work when it is being tested in the AI Companion App. So when you are building the final APK, it must be changed to:
file:///android_asset/compute.html
The clock, fires at regular intervals (every 200ms, in my example), executing an if statement that checks if the calculation is over or not.

Every time, when the clock fires, it checks the WebViewer.CurrentPageTitle property to see if it is not equal to the one at the starting. I'm additionally checking that if it is not equal to "about:blank" because, initially, the WebViewer will have this title, before any page loads. Even Though we are visiting another URL and then only checking the Title, still the document needs time to load. (+ The Timing issue too!) Once the HTML document loads, the title changes to "Evaluating...", and once the result is computed, the title will change to the result. Setting the title to "Evaluating..." also helps to determine if the result is computed or not when another calculation is made.
The HTML file is a simple one:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Evaluating...</title>
<!-- Uses (http://redhivesoftware.github.io/math-expression-evaluator) - a JavaScript to perform math calculations -->
<script src="compute.js"></script>
</head>
<body>
<script>
document.title=mexp.eval(window.AppInventor.getWebViewString());
</script>
</body>
</html>
Using this library has many additional benefits too. It supports the following operators/operations:
+ Addition Operator eg. 2+3 results 5
- Subtraction Operator eg. 2-3 results -1
/ Division operator eg 3/2 results 1.5
* Multiplication Operator eg. 2*3 results 6
Mod Modulus Operator eg. 3 Mod 2 results 1
( Opening Parenthesis
) Closing Parenthesis
Sigma Summation eg. Sigma(1,100,n) results 5050
Pi Product eg. Pi(1,10,n) results 3628800
n Variable for Summation or Product
pi Math constant pi returns 3.14
e Math constant e returns 2.71
C Combination operator eg. 4C2 returns 6
P Permutation operator eg. 4P2 returns 12
! factorial operator eg. 4! returns 24
log logarithmic function with base 10 eg. log 1000 returns 3
ln natural log function with base e eg. ln 2 returns .3010
pow power function with two operator pow(2,3) returns 8
^ power operator eg. 2^3 returns 8
root underroot function root 4 returns 2
sin Sine function
cos Cosine function
tan Tangent function
asin Inverse Sine function
acos Inverse Cosine function
atan Inverse Tangent function
sinh Hyperbolic Sine function
cosh Hyperbolic Cosine function
tanh Hyperbolic Tangent function
asinh Inverse Hyperbolic Sine function
acosh Inverse Hyperbolic Cosine function
atanh Inverse Hyperbolic Tangent function
For full documentation, refer
here.
Additionally, If a expression is readable by human then it is readable by
this evaluator. There is no need to wrap every function inside parenthesis. For eg. sin90 will work totally fine instead of sin(90); 2pi and 2*pi are the same; and 2(45 won't produce error!
I have attached the app's AIA file here. Feel free to modify the code as per your needs.
UPDATE: Now a similar function can be achieved using an extension, without the much complexity!
Checkout the Math Extension by Taifun!
Regards,
Akshay.