update randomInt function

This commit is contained in:
Mario Pesch 2021-05-17 17:03:53 +02:00
parent da65e23d3f
commit 59142b4c25

View File

@ -1,5 +1,4 @@
import * as Blockly from "blockly/core";
import * as Blockly from 'blockly/core';
/** /**
* @license Licensed under the Apache License, Version 2.0 (the "License"): * @license Licensed under the Apache License, Version 2.0 (the "License"):
@ -19,13 +18,13 @@ import * as Blockly from 'blockly/core';
* @param {!Blockly.Block} block Block to generate the code from. * @param {!Blockly.Block} block Block to generate the code from.
* @return {array} Completed code with order of operation. * @return {array} Completed code with order of operation.
*/ */
Blockly.Arduino['math_number'] = function (block) { Blockly.Arduino["math_number"] = function (block) {
// Numeric value. // Numeric value.
var code = parseFloat(block.getFieldValue('NUM')); var code = parseFloat(block.getFieldValue("NUM"));
if (code === Infinity) { if (code === Infinity) {
code = 'INFINITY'; code = "INFINITY";
} else if (code === -Infinity) { } else if (code === -Infinity) {
code = '-INFINITY'; code = "-INFINITY";
} }
return [code, Blockly.Arduino.ORDER_ATOMIC]; return [code, Blockly.Arduino.ORDER_ATOMIC];
}; };
@ -37,23 +36,23 @@ Blockly.Arduino['math_number'] = function (block) {
* @param {!Blockly.Block} block Block to generate the code from. * @param {!Blockly.Block} block Block to generate the code from.
* @return {array} Completed code with order of operation. * @return {array} Completed code with order of operation.
*/ */
Blockly.Arduino['math_arithmetic'] = function (block) { Blockly.Arduino["math_arithmetic"] = function (block) {
var OPERATORS = { var OPERATORS = {
ADD: [' + ', Blockly.Arduino.ORDER_ADDITIVE], ADD: [" + ", Blockly.Arduino.ORDER_ADDITIVE],
MINUS: [' - ', Blockly.Arduino.ORDER_ADDITIVE], MINUS: [" - ", Blockly.Arduino.ORDER_ADDITIVE],
MULTIPLY: [' * ', Blockly.Arduino.ORDER_MULTIPLICATIVE], MULTIPLY: [" * ", Blockly.Arduino.ORDER_MULTIPLICATIVE],
DIVIDE: [' / ', Blockly.Arduino.ORDER_MULTIPLICATIVE], DIVIDE: [" / ", Blockly.Arduino.ORDER_MULTIPLICATIVE],
POWER: [null, Blockly.Arduino.ORDER_NONE] // Handle power separately. POWER: [null, Blockly.Arduino.ORDER_NONE], // Handle power separately.
}; };
var tuple = OPERATORS[block.getFieldValue('OP')]; var tuple = OPERATORS[block.getFieldValue("OP")];
var operator = tuple[0]; var operator = tuple[0];
var order = tuple[1]; var order = tuple[1];
var argument0 = Blockly.Arduino.valueToCode(block, 'A', order) || '0'; var argument0 = Blockly.Arduino.valueToCode(block, "A", order) || "0";
var argument1 = Blockly.Arduino.valueToCode(block, 'B', order) || '0'; var argument1 = Blockly.Arduino.valueToCode(block, "B", order) || "0";
var code; var code;
// Power in C++ requires a special case since it has no operator. // Power in C++ requires a special case since it has no operator.
if (!operator) { if (!operator) {
code = 'Math.pow(' + argument0 + ', ' + argument1 + ')'; code = "Math.pow(" + argument0 + ", " + argument1 + ")";
return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX]; return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX];
} }
code = argument0 + operator + argument1; code = argument0 + operator + argument1;
@ -66,65 +65,78 @@ Blockly.Arduino['math_arithmetic'] = function (block) {
* @param {!Blockly.Block} block Block to generate the code from. * @param {!Blockly.Block} block Block to generate the code from.
* @return {array} Completed code with order of operation. * @return {array} Completed code with order of operation.
*/ */
Blockly.Arduino['math_single'] = function (block) { Blockly.Arduino["math_single"] = function (block) {
var operator = block.getFieldValue('OP'); var operator = block.getFieldValue("OP");
var code; var code;
var arg; var arg;
if (operator === 'NEG') { if (operator === "NEG") {
// Negation is a special case given its different operator precedents. // Negation is a special case given its different operator precedents.
arg = Blockly.Arduino.valueToCode(block, 'NUM', arg =
Blockly.Arduino.ORDER_UNARY_PREFIX) || '0'; Blockly.Arduino.valueToCode(
if (arg[0] === '-') { block,
"NUM",
Blockly.Arduino.ORDER_UNARY_PREFIX
) || "0";
if (arg[0] === "-") {
// --3 is not legal in C++ in this context. // --3 is not legal in C++ in this context.
arg = ' ' + arg; arg = " " + arg;
} }
code = '-' + arg; code = "-" + arg;
return [code, Blockly.Arduino.ORDER_UNARY_PREFIX]; return [code, Blockly.Arduino.ORDER_UNARY_PREFIX];
} }
if (operator === 'ABS' || operator.substring(0, 5) === 'ROUND') { if (operator === "ABS" || operator.substring(0, 5) === "ROUND") {
arg = Blockly.Arduino.valueToCode(block, 'NUM', arg =
Blockly.Arduino.ORDER_UNARY_POSTFIX) || '0'; Blockly.Arduino.valueToCode(
} else if (operator === 'SIN' || operator === 'COS' || operator === 'TAN') { block,
arg = Blockly.Arduino.valueToCode(block, 'NUM', "NUM",
Blockly.Arduino.ORDER_MULTIPLICATIVE) || '0'; Blockly.Arduino.ORDER_UNARY_POSTFIX
) || "0";
} else if (operator === "SIN" || operator === "COS" || operator === "TAN") {
arg =
Blockly.Arduino.valueToCode(
block,
"NUM",
Blockly.Arduino.ORDER_MULTIPLICATIVE
) || "0";
} else { } else {
arg = Blockly.Arduino.valueToCode(block, 'NUM', arg =
Blockly.Arduino.ORDER_NONE) || '0'; Blockly.Arduino.valueToCode(block, "NUM", Blockly.Arduino.ORDER_NONE) ||
"0";
} }
// First, handle cases which generate values that don't need parentheses. // First, handle cases which generate values that don't need parentheses.
switch (operator) { switch (operator) {
case 'ABS': case "ABS":
code = 'abs(' + arg + ')'; code = "abs(" + arg + ")";
break; break;
case 'ROOT': case "ROOT":
code = 'sqrt(' + arg + ')'; code = "sqrt(" + arg + ")";
break; break;
case 'LN': case "LN":
code = 'log(' + arg + ')'; code = "log(" + arg + ")";
break; break;
case 'EXP': case "EXP":
code = 'exp(' + arg + ')'; code = "exp(" + arg + ")";
break; break;
case 'POW10': case "POW10":
code = 'pow(10,' + arg + ')'; code = "pow(10," + arg + ")";
break; break;
case 'ROUND': case "ROUND":
code = 'round(' + arg + ')'; code = "round(" + arg + ")";
break; break;
case 'ROUNDUP': case "ROUNDUP":
code = 'ceil(' + arg + ')'; code = "ceil(" + arg + ")";
break; break;
case 'ROUNDDOWN': case "ROUNDDOWN":
code = 'floor(' + arg + ')'; code = "floor(" + arg + ")";
break; break;
case 'SIN': case "SIN":
code = 'sin(' + arg + ' / 180 * Math.PI)'; code = "sin(" + arg + " / 180 * Math.PI)";
break; break;
case 'COS': case "COS":
code = 'cos(' + arg + ' / 180 * Math.PI)'; code = "cos(" + arg + " / 180 * Math.PI)";
break; break;
case 'TAN': case "TAN":
code = 'tan(' + arg + ' / 180 * Math.PI)'; code = "tan(" + arg + " / 180 * Math.PI)";
break; break;
default: default:
break; break;
@ -134,20 +146,20 @@ Blockly.Arduino['math_single'] = function (block) {
} }
// Second, handle cases which generate values that may need parentheses. // Second, handle cases which generate values that may need parentheses.
switch (operator) { switch (operator) {
case 'LOG10': case "LOG10":
code = 'log(' + arg + ') / log(10)'; code = "log(" + arg + ") / log(10)";
break; break;
case 'ASIN': case "ASIN":
code = 'asin(' + arg + ') / M_PI * 180'; code = "asin(" + arg + ") / M_PI * 180";
break; break;
case 'ACOS': case "ACOS":
code = 'acos(' + arg + ') / M_PI * 180'; code = "acos(" + arg + ") / M_PI * 180";
break; break;
case 'ATAN': case "ATAN":
code = 'atan(' + arg + ') / M_PI * 180'; code = "atan(" + arg + ") / M_PI * 180";
break; break;
default: default:
throw new Error('Unknown math operator: ' + operator); throw new Error("Unknown math operator: " + operator);
} }
return [code, Blockly.Arduino.ORDER_MULTIPLICATIVE]; return [code, Blockly.Arduino.ORDER_MULTIPLICATIVE];
}; };
@ -161,16 +173,16 @@ Blockly.Arduino['math_single'] = function (block) {
* @param {!Blockly.Block} block Block to generate the code from. * @param {!Blockly.Block} block Block to generate the code from.
* @return {string} Completed code. * @return {string} Completed code.
*/ */
Blockly.Arduino['math_constant'] = function (block) { Blockly.Arduino["math_constant"] = function (block) {
var CONSTANTS = { var CONSTANTS = {
'PI': ['M_PI', Blockly.Arduino.ORDER_UNARY_POSTFIX], PI: ["M_PI", Blockly.Arduino.ORDER_UNARY_POSTFIX],
'E': ['M_E', Blockly.Arduino.ORDER_UNARY_POSTFIX], E: ["M_E", Blockly.Arduino.ORDER_UNARY_POSTFIX],
'GOLDEN_RATIO': ['(1 + sqrt(5)) / 2', Blockly.Arduino.ORDER_MULTIPLICATIVE], GOLDEN_RATIO: ["(1 + sqrt(5)) / 2", Blockly.Arduino.ORDER_MULTIPLICATIVE],
'SQRT2': ['M_SQRT2', Blockly.Arduino.ORDER_UNARY_POSTFIX], SQRT2: ["M_SQRT2", Blockly.Arduino.ORDER_UNARY_POSTFIX],
'SQRT1_2': ['M_SQRT1_2', Blockly.Arduino.ORDER_UNARY_POSTFIX], SQRT1_2: ["M_SQRT1_2", Blockly.Arduino.ORDER_UNARY_POSTFIX],
'INFINITY': ['INFINITY', Blockly.Arduino.ORDER_ATOMIC] INFINITY: ["INFINITY", Blockly.Arduino.ORDER_ATOMIC],
}; };
return CONSTANTS[block.getFieldValue('CONSTANT')]; return CONSTANTS[block.getFieldValue("CONSTANT")];
}; };
/** /**
@ -180,58 +192,67 @@ Blockly.Arduino['math_constant'] = function (block) {
* @param {!Blockly.Block} block Block to generate the code from. * @param {!Blockly.Block} block Block to generate the code from.
* @return {array} Completed code with order of operation. * @return {array} Completed code with order of operation.
*/ */
Blockly.Arduino['math_number_property'] = function (block) { Blockly.Arduino["math_number_property"] = function (block) {
var number_to_check = Blockly.Arduino.valueToCode(block, 'NUMBER_TO_CHECK', var number_to_check =
Blockly.Arduino.ORDER_MULTIPLICATIVE) || '0'; Blockly.Arduino.valueToCode(
var dropdown_property = block.getFieldValue('PROPERTY'); block,
"NUMBER_TO_CHECK",
Blockly.Arduino.ORDER_MULTIPLICATIVE
) || "0";
var dropdown_property = block.getFieldValue("PROPERTY");
var code; var code;
if (dropdown_property === 'PRIME') { if (dropdown_property === "PRIME") {
var func = [ var func = [
'boolean ' + Blockly.Arduino.DEF_FUNC_NAME + '(int n) {', "boolean " + Blockly.Arduino.DEF_FUNC_NAME + "(int n) {",
' // https://en.wikipedia.org/wiki/Primality_test#Naive_methods', " // https://en.wikipedia.org/wiki/Primality_test#Naive_methods",
' if (n == 2 || n == 3) {', " if (n == 2 || n == 3) {",
' return true;', " return true;",
' }', " }",
' // False if n is NaN, negative, is 1.', " // False if n is NaN, negative, is 1.",
' // And false if n is divisible by 2 or 3.', " // And false if n is divisible by 2 or 3.",
' if (isnan(n) || (n <= 1) || (n == 1) || (n % 2 == 0) || ' + " if (isnan(n) || (n <= 1) || (n == 1) || (n % 2 == 0) || " +
'(n % 3 == 0)) {', "(n % 3 == 0)) {",
' return false;', " return false;",
' }', " }",
' // Check all the numbers of form 6k +/- 1, up to sqrt(n).', " // Check all the numbers of form 6k +/- 1, up to sqrt(n).",
' for (int x = 6; x <= sqrt(n) + 1; x += 6) {', " for (int x = 6; x <= sqrt(n) + 1; x += 6) {",
' if (n % (x - 1) == 0 || n % (x + 1) == 0) {', " if (n % (x - 1) == 0 || n % (x + 1) == 0) {",
' return false;', " return false;",
' }', " }",
' }', " }",
' return true;', " return true;",
'}']; "}",
var funcName = Blockly.Arduino.addFunction('mathIsPrime', func.join('\n')); ];
Blockly.Arduino.addInclude('math', '#include <math.h>'); var funcName = Blockly.Arduino.addFunction("mathIsPrime", func.join("\n"));
code = funcName + '(' + number_to_check + ')'; Blockly.Arduino.addInclude("math", "#include <math.h>");
code = funcName + "(" + number_to_check + ")";
return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX]; return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX];
} }
switch (dropdown_property) { switch (dropdown_property) {
case 'EVEN': case "EVEN":
code = number_to_check + ' % 2 == 0'; code = number_to_check + " % 2 == 0";
break; break;
case 'ODD': case "ODD":
code = number_to_check + ' % 2 == 1'; code = number_to_check + " % 2 == 1";
break; break;
case 'WHOLE': case "WHOLE":
Blockly.Arduino.addInclude('math', '#include <math.h>'); Blockly.Arduino.addInclude("math", "#include <math.h>");
code = '(floor(' + number_to_check + ') == ' + number_to_check + ')'; code = "(floor(" + number_to_check + ") == " + number_to_check + ")";
break; break;
case 'POSITIVE': case "POSITIVE":
code = number_to_check + ' > 0'; code = number_to_check + " > 0";
break; break;
case 'NEGATIVE': case "NEGATIVE":
code = number_to_check + ' < 0'; code = number_to_check + " < 0";
break; break;
case 'DIVISIBLE_BY': case "DIVISIBLE_BY":
var divisor = Blockly.Arduino.valueToCode(block, 'DIVISOR', var divisor =
Blockly.Arduino.ORDER_MULTIPLICATIVE) || '0'; Blockly.Arduino.valueToCode(
code = number_to_check + ' % ' + divisor + ' == 0'; block,
"DIVISOR",
Blockly.Arduino.ORDER_MULTIPLICATIVE
) || "0";
code = number_to_check + " % " + divisor + " == 0";
break; break;
default: default:
break; break;
@ -247,19 +268,25 @@ Blockly.Arduino['math_number_property'] = function (block) {
* @param {!Blockly.Block} block Block to generate the code from. * @param {!Blockly.Block} block Block to generate the code from.
* @return {array} Completed code with order of operation. * @return {array} Completed code with order of operation.
*/ */
Blockly.Arduino['math_change'] = function (block) { Blockly.Arduino["math_change"] = function (block) {
var argument0 = Blockly.Arduino.valueToCode(block, 'DELTA', var argument0 =
Blockly.Arduino.ORDER_ADDITIVE) || '0'; Blockly.Arduino.valueToCode(
block,
"DELTA",
Blockly.Arduino.ORDER_ADDITIVE
) || "0";
var varName = Blockly.Arduino.variableDB_.getName( var varName = Blockly.Arduino.variableDB_.getName(
block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); block.getFieldValue("VAR"),
return varName + ' += ' + argument0 + ';\n'; Blockly.Variables.NAME_TYPE
);
return varName + " += " + argument0 + ";\n";
}; };
/** Rounding functions have a single operand. */ /** Rounding functions have a single operand. */
Blockly.Arduino['math_round'] = Blockly.Arduino['math_single']; Blockly.Arduino["math_round"] = Blockly.Arduino["math_single"];
/** Trigonometry functions have a single operand. */ /** Trigonometry functions have a single operand. */
Blockly.Arduino['math_trig'] = Blockly.Arduino['math_single']; Blockly.Arduino["math_trig"] = Blockly.Arduino["math_single"];
/** /**
* Generator for the math function to a list. * Generator for the math function to a list.
@ -268,7 +295,7 @@ Blockly.Arduino['math_trig'] = Blockly.Arduino['math_single'];
* @param {!Blockly.Block} block Block to generate the code from. * @param {!Blockly.Block} block Block to generate the code from.
* @return {array} Completed code with order of operation. * @return {array} Completed code with order of operation.
*/ */
Blockly.Arduino['math_on_list'] = Blockly.Arduino.noGeneratorCodeInline; Blockly.Arduino["math_on_list"] = Blockly.Arduino.noGeneratorCodeInline;
/** /**
* Generator for the math modulo function (calculates remainder of X/Y). * Generator for the math modulo function (calculates remainder of X/Y).
@ -276,12 +303,20 @@ Blockly.Arduino['math_on_list'] = Blockly.Arduino.noGeneratorCodeInline;
* @param {!Blockly.Block} block Block to generate the code from. * @param {!Blockly.Block} block Block to generate the code from.
* @return {array} Completed code with order of operation. * @return {array} Completed code with order of operation.
*/ */
Blockly.Arduino['math_modulo'] = function (block) { Blockly.Arduino["math_modulo"] = function (block) {
var argument0 = Blockly.Arduino.valueToCode(block, 'DIVIDEND', var argument0 =
Blockly.Arduino.ORDER_MULTIPLICATIVE) || '0'; Blockly.Arduino.valueToCode(
var argument1 = Blockly.Arduino.valueToCode(block, 'DIVISOR', block,
Blockly.Arduino.ORDER_MULTIPLICATIVE) || '0'; "DIVIDEND",
var code = argument0 + ' % ' + argument1; Blockly.Arduino.ORDER_MULTIPLICATIVE
) || "0";
var argument1 =
Blockly.Arduino.valueToCode(
block,
"DIVISOR",
Blockly.Arduino.ORDER_MULTIPLICATIVE
) || "0";
var code = argument0 + " % " + argument1;
return [code, Blockly.Arduino.ORDER_MULTIPLICATIVE]; return [code, Blockly.Arduino.ORDER_MULTIPLICATIVE];
}; };
@ -291,17 +326,33 @@ Blockly.Arduino['math_modulo'] = function (block) {
* @param {!Blockly.Block} block Block to generate the code from. * @param {!Blockly.Block} block Block to generate the code from.
* @return {array} Completed code with order of operation. * @return {array} Completed code with order of operation.
*/ */
Blockly.Arduino['math_constrain'] = function (block) { Blockly.Arduino["math_constrain"] = function (block) {
// Constrain a number between two limits. // Constrain a number between two limits.
var argument0 = Blockly.Arduino.valueToCode(block, 'VALUE', var argument0 =
Blockly.Arduino.ORDER_NONE) || '0'; Blockly.Arduino.valueToCode(block, "VALUE", Blockly.Arduino.ORDER_NONE) ||
var argument1 = Blockly.Arduino.valueToCode(block, 'LOW', "0";
Blockly.Arduino.ORDER_NONE) || '0'; var argument1 =
var argument2 = Blockly.Arduino.valueToCode(block, 'HIGH', Blockly.Arduino.valueToCode(block, "LOW", Blockly.Arduino.ORDER_NONE) ||
Blockly.Arduino.ORDER_NONE) || '0'; "0";
var code = '(' + argument0 + ' < ' + argument1 + ' ? ' + argument1 + var argument2 =
' : ( ' + argument0 + ' > ' + argument2 + ' ? ' + argument2 + ' : ' + Blockly.Arduino.valueToCode(block, "HIGH", Blockly.Arduino.ORDER_NONE) ||
argument0 + '))'; "0";
var code =
"(" +
argument0 +
" < " +
argument1 +
" ? " +
argument1 +
" : ( " +
argument0 +
" > " +
argument2 +
" ? " +
argument2 +
" : " +
argument0 +
"))";
return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX]; return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX];
}; };
@ -312,28 +363,26 @@ Blockly.Arduino['math_constrain'] = function (block) {
* @param {!Blockly.Block} block Block to generate the code from. * @param {!Blockly.Block} block Block to generate the code from.
* @return {array} Completed code with order of operation. * @return {array} Completed code with order of operation.
*/ */
Blockly.Arduino['math_random_int'] = function (block) { Blockly.Arduino["math_random_int"] = function (block) {
var argument0 = Blockly.Arduino.valueToCode(block, 'FROM', var argument0 =
Blockly.Arduino.ORDER_NONE) || '0'; Blockly.Arduino.valueToCode(block, "FROM", Blockly.Arduino.ORDER_NONE) ||
var argument1 = Blockly.Arduino.valueToCode(block, 'TO', "0";
Blockly.Arduino.ORDER_NONE) || '0'; var argument1 =
var functionName = Blockly.Arduino.variableDB_.getDistinctName( Blockly.Arduino.valueToCode(block, "TO", Blockly.Arduino.ORDER_NONE) || "0";
'math_random_int', Blockly.Generator.NAME_TYPE); Blockly.Arduino.setupCode_["init_rand"] = "randomSeed(analogRead(0));";
Blockly.Arduino.setups_['init_rand'] = 'randomSeed(analogRead(0));'; Blockly.Arduino.functionNames_[
Blockly.Arduino.math_random_int.random_function = functionName; "math_random_int"
var func = [ ] = `int mathRandomInt (int min, int max) {\n
'int ' + Blockly.Arduino.DEF_FUNC_NAME + '(int min, int max) {', if (min > max) {
' if (min > max) {', int temp = min;
' // Swap min and max to ensure min is smaller.', min = max;
' int temp = min;', max = temp;
' min = max;', }
' max = temp;', return min + (rand() % (max - min + 1));
' }', }
' return min + (rand() % (max - min + 1));', `;
'}']; var code = `mathRandomInt(${argument0},${argument1});`;
var funcName = Blockly.Arduino.addFunction('mathRandomInt', func.join('\n')); return [code, Blockly.Arduino.ORDER_ATOMIC];
var code = funcName + '(' + argument0 + ', ' + argument1 + ')';
return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX];
}; };
/** /**
@ -342,6 +391,6 @@ Blockly.Arduino['math_random_int'] = function (block) {
* @param {!Blockly.Block} block Block to generate the code from. * @param {!Blockly.Block} block Block to generate the code from.
* @return {string} Completed code. * @return {string} Completed code.
*/ */
Blockly.Arduino['math_random_float'] = function (block) { Blockly.Arduino["math_random_float"] = function (block) {
return ['(rand() / RAND_MAX)', Blockly.Arduino.ORDER_UNARY_POSTFIX]; return ["(rand() / RAND_MAX)", Blockly.Arduino.ORDER_UNARY_POSTFIX];
}; };