[Free] Evaluate JavaScript Extension. Math expression. Source code

Hello friends,

to execute JavaScript codes we can use RunJavaScript block found in the WebViewer component.
Here are some examples: RunJavaScript examples.

We can also use the Andrés Daniel extension: EvaluatorJs

Here we have a similar extension, but with some peculiarities.

Pro:
it does not need the Math particle when writing expressions.
It can be used with event or directly.

Con:
it doesn't work with functions.

Blocks.

runjs1

com.KIO4_JS.aix (8.0 KB)

6 Likes

1.- Examples.

1.- Get ASCII of 'R'.

'R'.codePointAt(0)

2.- Get char 83.

String.fromCodePoint(83)

3.- Obtain the hypotenuse using the Pythagorean theorem.

a = 3.47;
b = 4.71;
hypotenuse = sqrt(pow(a, 2) + pow(b, 2))

4.- Get 5 random cards.

from: JavaScript Program to Shuffle Deck of Cards

suits = ['Spades', 'Diamonds', 'Club', 'Heart']; 
const values = ['Ace', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen','King', ];  
deck = []; 
for (let i = 0; i < suits.length; i++) {for (x = 0; x < values.length; x++) {card = { Value: values[x], Suit: suits[i] };         deck.push(card); } }  
for (let i = deck.length - 1; i > 0; i--) { j = floor(random() * i);
 temp = deck[i]; 
 deck[i] = deck[j];
 deck[j] = temp; } 
 out = ''; 
 for (let i = 0; i < 5; i++) {out = out + `${deck[i].Value} of ${deck[i].Suit},`; };

5.- Sieve of Eratosthenes (800).

max = 800;
sieve = [];
primes = [];
for (i = 2; i <= max; ++i) {
	if (!sieve[i]) {
	primes.push(i);
	for (j = i << 1; j <= max; j += i) {
	sieve[j] = true;} 
	} 
} 
primes.toString();

6.- Evaluate expression log(6) / cos(6) + sqrt(25)

log(6) / cos(6) + sqrt(25)

7.- Get max(3,12,1,9,6,2,10).

max(3,12,1,9,6,2,10)

8.-Sort "3,12,1,9,6,2,10".

"3,12,1,9,6,2,10".split(",").sort(function(a,b) { return b - a; }).toString()

9.- ["Banana", "Orange", "Apple", "Mango"].sort().

["Banana", "Orange", "Apple", "Mango"].sort()

10.- indexOf.

texto = 'This is text';
out = texto.indexOf('is');

11.- Date.now.

Date.now().toString()

12.- Fibonacci Series (25 terms).

https://en.wikipedia.org/wiki/Fibonacci_number

terms = 25;
n1 = 0; 
n2 = 1;
f = "";

for (i = 1; i <= terms; i++) {
    f = f + n1.toString() + "-";
    next = n1 + n2;
    n1 = n2;
    n2 = next;
}
resultado = f;

2.- App and Blocks.

p51e_runJS.aia (11.8 KB)

2 Likes

3.- Source code.

KIO4_JS.java


package com.KIO4_JS;
//  © Juan Antonio Villalpando  - kio4.com

import com.google.appinventor.components.annotations.DesignerComponent;
import com.google.appinventor.components.annotations.DesignerProperty;
import com.google.appinventor.components.annotations.SimpleEvent;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.annotations.SimpleObject;
import com.google.appinventor.components.common.ComponentCategory;
import com.google.appinventor.components.runtime.*;
import android.content.Context;

import android.webkit.WebView;
import android.webkit.ValueCallback;

@DesignerComponent(version = 1,
    description = "Evaluate JavaScript codes. Juan A. Villalpando - kio4.com. ",
    category = ComponentCategory.EXTENSION,
	licenseName = "https://opensource.org/licenses/MIT",
    nonVisible = true,
    iconName = "") 
@SimpleObject(external = true)
public class KIO4_JS extends AndroidNonvisibleComponent implements Component {

	public static final int VERSION = 1;
	private ComponentContainer container;
	private Context context;
	private WebView myWebView = null;
	private String salida = "0";

public KIO4_JS(ComponentContainer container) {
	super(container.$form());
	this.container = container;
	context = (Context) container.$context();
	myWebView = new WebView(context);
	myWebView.getSettings().setJavaScriptEnabled(true);
}

////////////////////// FUNCIONES //////////////////////////////////////////////////////////////////////
@SimpleFunction(description = "Set a JavaScript code and get result in event Result.")
 public void RunJS(String js) {
	js = addMath(js); // Add Math.
    myWebView.evaluateJavascript(js, new ValueCallback<String>() {
    public void onReceiveValue(String s) {
                  Result(s);
				  salida = s;
	}
});
 }
////////////////////////////////////////////////////////////////////
 @SimpleFunction(description = "Set a JavaScript code and get result directly.")
 public String RunJSd(String js) {
RunJS(js);
return salida;
 }
////////////// EVENTO ///////////////////
   @SimpleEvent(description = "Result.")
  public void Result(String value) {
    EventDispatcher.dispatchEvent(this, "Result", value);
  }
/////////////////////////////////////////////////
public String addMath(String js) {	
js = js.replaceAll("LN2","Math.LN2");
js = js.replaceAll("LN10","Math.LN10");
js = js.replaceAll("LOG2E","Math.LOG2E");
js = js.replaceAll("LOG10E","Math.LOG10E");
js = js.replaceAll("PI","Math.PI");
js = js.replaceAll("SQRT1_2","Math.SQRT1_2");
js = js.replaceAll("SQRT2","Math.SQRT2");
js = js.replaceAll("abs", "Math.abs");
js = js.replaceAll("acos","Math.acos");
js = js.replaceAll("acosh","Math.acosh");
js = js.replaceAll("asin","Math.asin");
js = js.replaceAll("asinh","Math.asinh");
js = js.replaceAll("atan","Math.atan");
js = js.replaceAll("atanh","Math.atanh");
js = js.replaceAll("atan2","Math.atan2");
js = js.replaceAll("cbrt","Math.cbrt");
js = js.replaceAll("ceil","Math.ceil");
js = js.replaceAll("clz32","Math.clz32");
js = js.replaceAll("cos","Math.cos");
js = js.replaceAll("cosh","Math.cosh");
js = js.replaceAll("exp","Math.exp");
js = js.replaceAll("expm1","Math.expm1");
js = js.replaceAll("floor","Math.floor");
js = js.replaceAll("fround","Math.fround");
js = js.replaceAll("hypot","Math.hypot");
js = js.replaceAll("imul","Math.imul");
js = js.replaceAll("log","Math.log");
js = js.replaceAll("log1p","Math.log1p");
js = js.replaceAll("log10","Math.log10");
js = js.replaceAll("log2","Math.log2");
js = js.replaceAll("max","Math.max");
js = js.replaceAll("min","Math.min");
js = js.replaceAll("pow","Math.pow");
js = js.replaceAll("random","Math.random");
js = js.replaceAll("round","Math.round");
js = js.replaceAll("sign","Math.sign");
js = js.replaceAll("sin","Math.sin");  
js = js.replaceAll("sinh","Math.sinh");
js = js.replaceAll("sqrt","Math.sqrt");
js = js.replaceAll("tan","Math.tan");
js = js.replaceAll("tanh","Math.tanh");
js = js.replaceAll("trunc","Math.trunc");
return js;
 }
       
}	// ==> FIN
1 Like

4.- Comments.

Look at the source code. Create a WebView, but don't set it.

Note that to display the result you don't need AppInventor.setWebViewString.

The code is offered under the MIT license, it can be optimized and improved.

Search for complicated expressions and execute them with this extension, for example: complex-mathematical-expression

(5*(3*x*x+5*x+2)/(7*w-1/z)-z)/(4*((3+x)/7))

1 Like

5.- Stress test this extension. Finding probability using the Normal Distribution.

p51f_runJs_Normal.aia (11.3 KB)

We are going to find the probability of a normal distribution using this extension. Comparison with block code.

We will follow this video:
https://www.youtube.com/watch?v=Rionve04Dvs

Scores are normally distributed.
mean = 24.2
Standard Deviation (SD) (delta) = 4.2
What is probability that a student scores greater than 31?
Use the Standard normal table.

Sol: the green area has a value of 0.0527, that is the probability.

Process:
a) To convert from a normally distributed x value to a z-score, we use the following formula:
runjs6
b) Now we consult the Standard normal table.

OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO

- With Blocks.

  • Now we are going to calculate the area of ​​the green zone by another method.
    We will create small rectangles with a base of 0.1 and a height indicated by the function.
  • We will add the area of ​​all those rectangles.


Through a "for" loop we are cumulatively adding the small rectangles (I have used a base rectangle of 0.01)

- With RunJavaScript of WebView component.

area=0;
mean=24.2;
SD=4.2;
e=2.7182818;
for(x=31;x<48.4;x=x+0.01){area = area + 0.01 * 1/(SD*Math.sqrt(2*3.1416))*Math.pow(e,Math.pow(x-mean,2)/(-2*Math.pow(SD,2)))};
AppInventor.setWebViewString(area.toString());

- With extension.

area=0;
mean=24.2;
SD=4.2;
e=2.7182818;
for(x=31;x<48.4;x=x+0.01){area = area + 0.01 * 1/(SD*sqrt(2*3.1416))*pow(e,pow(x-mean,2)/(-2*pow(SD,2)))};

- With extension. Insert block.
(It needs double click)

area=0;
mean=24.2;
SD=4.2;
e=2.7182818;
for(x=31;x<48.4;x=x+0.01){area = area + 0.01 * 1/(SD*sqrt(2*3.1416))*pow(e,pow(x-mean,2)/(-2*pow(SD,2)))};

Conclusion.

With blocks you get the slowest result. With JavaScript it is faster.
Even using a rectangle base of 0.0001, good speed is achieved in the result.
for(x=31;x<48.4;x=x+0.0001){area = area + 0.0001 *.....

With the insert block it is necessary to press the button twice.
You can get more accurate results by changing the base of the rectangles to 0.0001

7 Likes

6.- Code proposal. Double factorial.

You know that the factorial of the number 9 is:

9! = 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 = 362880

But, do you know that the double factorial exists?
Create an application to calculate the double factorial of an integer.

9‼ = 9 * 7 * 5 * 3 * 1 = 945

3 Likes

Totally outstanding Juan.

Interesting!

  • Suggestion:: Calculate the PI value using formulas.

https://mathworld.wolfram.com/PiFormulas.html

1 Like

hello @Juan_Antonio , thanks for this wounderful extension...

BTW, how can i get result from this js?

function convertToDms(dd, isLng) {
  var dd =42.15188;
  var isLng = false;
  
  var dir = dd < 0
    ? isLng ? 'W' : 'S'
    : isLng ? 'E' : 'N';

  var absDd = Math.abs(dd);
  var deg = absDd | 0;
  var frac = absDd - deg;
  var min = (frac * 60) | 0;
  var sec = frac * 3600 - min * 60;
  // Round it to 2 decimal points.
  sec = Math.round(sec * 100) / 100;
  return deg + "°" + min + "'" + sec + '"' + dir;
}

console.log(convertToDms());

i have used the same code in both blocks but i get null.. instead of return i used out

ref link

Try this:

; dir = dd < 0 ? isLng ? ' W' : ' S' : isLng ? ' E' : ' N'; absDd = abs(dd); deg = absDd | 0; frac = absDd - deg; min = (frac * 60) | 0; sec = frac * 3600 - min * 60; sec = round(sec * 100) / 100; salida=deg + "°" + min + "" + sec + "''" + dir;

dd =42.15188;
isLng = false;
dir = dd < 0
    ? isLng ? ' W' : ' S'
    : isLng ? ' E' : ' N';
absDd = abs(dd);
deg = absDd | 0;
frac = absDd - deg;
min = (frac * 60) | 0;
sec = frac * 3600 - min * 60;
sec = round(sec * 100) / 100;
salida=deg + "°" + min + "" + sec + "''" + dir;
1 Like

Perfect.. thank you man.. you are awesome.

I don't understand why the launch of the simplest function only works for me the second time (i.e. every other time).
that is, when I run the execution again, it shows the result: (what could be the reason?

It is a feature of this block, it needs double click.

If you read the source code, you will know why.

The evaluateJavascript will return the value asynchronously. The result you get is the result of last time.
So the safe way is to use the Runjs and get the result in the Result event.

the extension is really interesting and necessary.
it's a pity that such a feature. In fact, the need for such a block disappears.
and it's sad that all this works in the WebView component (I wanted to use this extension on a wearable device running Wear, but there is no android.webkit

A workaround with a Clock.

javascriptrunjs1

borrar_runjs.aia (9.1 KB)