From 2a2c1e1c2565b0c4f7c792cd707f570a6c706a33 Mon Sep 17 00:00:00 2001 From: Mario Date: Wed, 7 Oct 2020 09:47:24 +0200 Subject: [PATCH] update loop blocks --- src/components/Blockly/blocks/loops.js | 227 +++++++++++++++++++------ src/data/tutorials.json | 14 ++ 2 files changed, 193 insertions(+), 48 deletions(-) diff --git a/src/components/Blockly/blocks/loops.js b/src/components/Blockly/blocks/loops.js index 4dcf86a..63fc9aa 100644 --- a/src/components/Blockly/blocks/loops.js +++ b/src/components/Blockly/blocks/loops.js @@ -3,54 +3,185 @@ import Blockly from 'blockly'; import { getColour } from '../helpers/colour'; import { getCompatibleTypes } from '../helpers/types' -// Blockly.defineBlocksWithJsonArray([ -// { -// type: 'controls_for', -// message0: 'count with %1 from %2 to %3 by adding %4', -// args0: [ -// { -// type: 'field_variable', -// name: 'VAR', -// variable: null, -// variableTypes: ['Number'], -// defaultType: 'Number', -// createNewVariable: true, -// showOnlyVariableAssigned: false, -// }, -// { -// type: 'input_value', -// name: 'FROM', -// check: 'Number', -// align: 'RIGHT', -// }, -// { -// type: 'input_value', -// name: 'TO', -// check: 'Number', -// align: 'RIGHT', -// }, -// { -// type: 'input_value', -// name: 'BY', -// check: 'Number', -// align: 'RIGHT', -// }, -// ], -// message1: '%{BKY_CONTROLS_REPEAT_INPUT_DO} %1', -// args1: [ -// { -// type: 'input_statement', -// name: 'DO', -// }, -// ], -// inputsInline: false, -// previousStatement: null, -// nextStatement: null, -// colour: getColour().loops, -// helpUrl: '%{BKY_CONTROLS_FOR_HELPURL}', -// extensions: ['contextMenu_newGetVariableBlock', 'controls_for_tooltip'], -// }, -// ]); + +Blockly.Blocks['controls_whileUntil'] = { + /** + * Block for 'do while/until' loop. + * @this Blockly.Block + */ + init: function () { + var OPERATORS = + [[Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE, 'WHILE'], + [Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL, 'UNTIL']]; + this.setHelpUrl(Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL); + this.setColour(getColour().loops); + this.appendValueInput('BOOL') + .setCheck(getCompatibleTypes(Boolean)) + .appendField(new Blockly.FieldDropdown(OPERATORS), 'MODE'); + this.appendStatementInput('DO') + .appendField(Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO); + this.setPreviousStatement(true); + this.setNextStatement(true); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function () { + var op = thisBlock.getFieldValue('MODE'); + var TOOLTIPS = { + 'WHILE': Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE, + 'UNTIL': Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL + }; + return TOOLTIPS[op]; + }); + } +}; + +Blockly.Blocks['controls_for'] = { + /** + * Block for 'for' loop. + * @this Blockly.Block + */ + init: function () { + this.jsonInit({ + "message0": Blockly.Msg.CONTROLS_FOR_TITLE, + "args0": [ + { + "type": "field_variable", + "name": "VAR", + "variable": null + }, + { + "type": "input_value", + "name": "FROM", + "check": getCompatibleTypes(Number), + "align": "RIGHT" + }, + { + "type": "input_value", + "name": "TO", + "check": getCompatibleTypes(Number), + "align": "RIGHT" + }, + { + "type": "input_value", + "name": "BY", + "check": getCompatibleTypes(Number), + "align": "RIGHT" + } + ], + "inputsInline": true, + "previousStatement": null, + "nextStatement": null, + "colour": getColour().loops, + "helpUrl": Blockly.Msg.CONTROLS_FOR_HELPURL + }); + this.appendStatementInput('DO') + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_DO); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function () { + return Blockly.Msg.CONTROLS_FOR_TOOLTIP.replace('%1', + thisBlock.getFieldValue('VAR')); + }); + } +}; + +Blockly.Blocks['controls_forEach'] = { + /** + * Block for 'for each' loop. + * @this Blockly.Block + */ + init: function () { + this.jsonInit({ + "message0": Blockly.Msg.CONTROLS_FOREACH_TITLE, + "args0": [ + { + "type": "field_variable", + "name": "VAR", + "variable": null + }, + { + "type": "input_value", + "name": "LIST", + "check": getCompatibleTypes(Array) + } + ], + "previousStatement": null, + "nextStatement": null, + "colour": getColour().loops, + "helpUrl": Blockly.Msg.CONTROLS_FOREACH_HELPURL + }); + this.appendStatementInput('DO') + .appendField(Blockly.Msg.CONTROLS_FOREACH_INPUT_DO); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function () { + return Blockly.Msg.CONTROLS_FOREACH_TOOLTIP.replace('%1', + thisBlock.getFieldValue('VAR')); + }); + }, + customContextMenu: Blockly.Blocks['controls_for'].customContextMenu, + /** @returns {!string} The type of the variable used in this block */ + getVarType: function (varName) { + return Blockly.Types.NUMBER; + } +}; + +Blockly.Blocks['controls_flow_statements'] = { + /** + * Block for flow statements: continue, break. + * @this Blockly.Block + */ + init: function () { + var OPERATORS = + [[Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK, 'BREAK'], + [Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE, 'CONTINUE']]; + this.setHelpUrl(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL); + this.setColour(getColour().loops); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown(OPERATORS), 'FLOW'); + this.setPreviousStatement(true); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function () { + var op = thisBlock.getFieldValue('FLOW'); + var TOOLTIPS = { + 'BREAK': Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK, + 'CONTINUE': Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE + }; + return TOOLTIPS[op]; + }); + }, + /** + * Called whenever anything on the workspace changes. + * Add warning if this flow block is not nested inside a loop. + * @param {!Blockly.Events.Abstract} e Change event. + * @this Blockly.Block + */ + onchange: function (e) { + var legal = false; + // Is the block nested in a loop? + var block = this; + do { + if (this.LOOP_TYPES.indexOf(block.type) !== -1) { + legal = true; + break; + } + block = block.getSurroundParent(); + } while (block); + if (legal) { + this.setWarningText(null); + } else { + this.setWarningText(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING); + } + }, + /** + * List of block types that are loops and thus do not need warnings. + * To add a new loop type add this to your code: + * Blockly.Blocks['controls_flow_statements'].LOOP_TYPES.push('custom_loop'); + */ + LOOP_TYPES: ['controls_repeat', 'controls_repeat_ext', 'controls_forEach', + 'controls_for', 'controls_whileUntil'] +}; Blockly.Blocks['controls_repeat_ext'] = { /** diff --git a/src/data/tutorials.json b/src/data/tutorials.json index 4ba0518..47c4b11 100644 --- a/src/data/tutorials.json +++ b/src/data/tutorials.json @@ -79,6 +79,20 @@ "headline": "Verwendung von Schleifen", "text": "Lass die LED genau 5 mal in einem Abstand von 1000 Millisekunden blinken. Anschließend soll die LED ausgeschaltet werden. ", "xml": "\n \n \n \n \n \n 5\n \n \n \n \n 1\n HIGH\n \n \n \n \n 1000\n \n \n \n \n 1\n LOW\n \n \n \n \n 1000\n \n \n \n \n \n \n \n \n \n \n \n \n \n" + }, + { + "id": 4, + "type": "instruction", + "headline": "Schleife mit Laufzeitvariable", + "text": "Mit diesem Block lässt sich die Schleife noch genauer Steuern und beeinflussen. Hierbei wird nicht nur angegeben wie oft die Anweisungen innerhalb der Schleife wiederholt werden sondern auch welche Variable zum zählen verwendet wird und in welchen Schritten gezählt werden soll. Der Vorteil bei diesem Block ist, dass die Wert der Variable auch innerhalb der Anweisungen verwendet werden kann. So kannst zum Beispiel die Variable \"i\" verwenden um die Blinkfrequenz zu beeinflussen.", + "xml": "\n \n i\n \n \n \n \n i\n \n \n 100\n \n \n \n \n 1000\n \n \n \n \n 100\n \n \n \n \n 1\n HIGH\n \n \n \n \n i\n \n \n \n \n 1\n LOW\n \n \n \n \n i\n \n \n \n \n \n \n \n \n \n \n \n \n \n" + }, + { + "id": 5, + "type": "task", + "headline": "Schleifen mit Laufzeitvariable", + "text": "Verwende die Schleife mit Laufzeitvariable und beeinflusse die Blinkfrequenz mithilfe dem Wert der Variable.", + "xml": "\n \n i\n \n \n \n \n i\n \n \n 100\n \n \n \n \n 1000\n \n \n \n \n 100\n \n \n \n \n 1\n HIGH\n \n \n \n \n i\n \n \n \n \n 1\n LOW\n \n \n \n \n i\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n 1000\n \n" } ] },