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

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)

You may want to use this extension.

Hey is it possible to use webrtc data channels using this extension the javascript code

// Creating a RTCPeerConnection object
const configuration = {}; // Configuration details for RTCPeerConnection

const peerConnection = new RTCPeerConnection(configuration);

// Creating a data channel
const dataChannel = peerConnection.createDataChannel();

// Listening for incoming data channels
peerConnection.addEventListener('datachannel', event => {
    const receivedDataChannel = event.channel;

    // Handling received data channel
    receivedDataChannel.addEventListener('message', event => {
        const receivedMessage = event.data;
        // Code to handle received message
    });

    receivedDataChannel.addEventListener('open', event => {
        // Code to handle opened data channel
    });

    receivedDataChannel.addEventListener('close', event => {
        // Code to handle closed data channel
    });
});

// Opening and closing events for the created data channel
dataChannel.addEventListener('open', event => {
    // Enabling elements when data channel is opened
    messageBox.disabled = false;
    messageBox.focus();
    sendButton.disabled = false;
});

dataChannel.addEventListener('close', event => {
    // Disabling elements when data channel is closed
    messageBox.disabled = true;
    sendButton.disabled = true;
});

// Sending a message when the send button is clicked
sendButton.addEventListener('click', event => {
    const message = messageBox.value;
    dataChannel.send(message);
});

// Receiving incoming messages and appending them to a message box
const incomingMessages = document.querySelector('#incomingMessages');

peerConnection.addEventListener('datachannel', event => {
    const receivedDataChannel = event.channel;

    receivedDataChannel.addEventListener('message', event => {
        const receivedMessage = event.data;
        incomingMessages.textContent += receivedMessage + '\n';
    });
});