From c858cf906375eba9ecb17369b134c29839399cb1 Mon Sep 17 00:00:00 2001 From: LimeNade Date: Sat, 20 Apr 2024 15:53:15 +0200 Subject: [PATCH 01/53] feat: Dynamic inputs --- src/lib/blocks/Javascript/Loops.ts | 2 +- src/lib/blocks/Javascript/logic.ts | 11 +- src/lib/components/Workspace.svelte | 5 +- src/lib/types/DiscodesInput.ts | 9 ++ src/lib/utils/BlockGen/Blocks/Block.ts | 118 +++++++++++++++--- src/lib/utils/BlockGen/Inputs/BaseInput.ts | 13 +- src/lib/utils/BlockGen/Inputs/Dropdown.ts | 8 +- src/lib/utils/BlockGen/Inputs/Image.ts | 20 +-- src/lib/utils/BlockGen/Inputs/NumberInput.ts | 13 +- .../utils/BlockGen/Inputs/StatementInput.ts | 6 +- src/lib/utils/BlockGen/Inputs/TextInput.ts | 6 +- src/lib/utils/BlockGen/Inputs/ValueInput.ts | 8 +- 12 files changed, 164 insertions(+), 55 deletions(-) create mode 100644 src/lib/types/DiscodesInput.ts diff --git a/src/lib/blocks/Javascript/Loops.ts b/src/lib/blocks/Javascript/Loops.ts index f6982bb..1206c2b 100644 --- a/src/lib/blocks/Javascript/Loops.ts +++ b/src/lib/blocks/Javascript/Loops.ts @@ -14,7 +14,7 @@ const blocks: BlockDefinition[] = [ shape: BlockShape.Action, inline: true, colour: rgbToHex(91, 165, 91), - tooltip: "Repeat x times", + tooltip: "Repeats the code inside the given ammount of times.", helpUrl: "", code: (args) => { return `for (let i = 0; i < ${args.VALUE}; i++) {\n${args.INPUT}\n}`; diff --git a/src/lib/blocks/Javascript/logic.ts b/src/lib/blocks/Javascript/logic.ts index 0f117f7..7140b06 100644 --- a/src/lib/blocks/Javascript/logic.ts +++ b/src/lib/blocks/Javascript/logic.ts @@ -2,6 +2,8 @@ import { BlockShape, BlockType, DropdownType, WarningType } from "$lib/enums/Blo import type { BlockDefinition } from "$lib/types/BlockDefinition"; import type { CategoryDefinition } from "$lib/types/CategoryDefinition"; import Dropdown from "$lib/utils/BlockGen/Inputs/Dropdown"; +import NumberInput from "$lib/utils/BlockGen/Inputs/NumberInput"; +import TextInput from "$lib/utils/BlockGen/Inputs/TextInput"; import ValueInput from "$lib/utils/BlockGen/Inputs/ValueInput"; import Warning from "$lib/utils/BlockGen/Warnings/Warning"; import rgbToHex from "$lib/utils/helpers/rgbToHex"; @@ -33,8 +35,13 @@ const blocks: BlockDefinition[] = [ colour: rgbToHex(91, 128, 165), tooltip: "Checks if the first input and the second input validate the condition.", helpUrl: "https://www.w3schools.com/js/js_comparisons.asp", - code: (args) => { - return `${args.A} ${args.CONDITION} ${args.B}`; + code: (args, block) => { + block.addInput(new Dropdown("bob", DropdownType.Auto, {"bob": "hello", "alex":"nikola"})); + block.addInput(new ValueInput("chicken", BlockType.Any)); + block.addInput(new NumberInput("numberrr", 50, {max: 100, min: 50, precision: 10})); + block.addInput(new TextInput("textttt", "I am a text input!")); + console.log("Args (code prop parameter): ",args); + return `${args.textttt}`; } }, { diff --git a/src/lib/components/Workspace.svelte b/src/lib/components/Workspace.svelte index 9dd1a44..4d1f073 100644 --- a/src/lib/components/Workspace.svelte +++ b/src/lib/components/Workspace.svelte @@ -24,7 +24,6 @@ await loadBlocks(); workspace = Blockly.inject("blocklyDiv", { ...options, toolbox: toolbox }); - // Only console log the code and warnings when debug mode is enabled. const supportedEvents = new Set([ Blockly.Events.BLOCK_CHANGE, Blockly.Events.BLOCK_CREATE, @@ -33,9 +32,13 @@ ]); function updateCode(event: Abstract) { + workspace.getAllBlocks(true).forEach((block) => { + if (block.type === "is_equal") console.log(block) + }) if (workspace.isDragging()) return; // Don't update while changes are happening. if (!supportedEvents.has(event.type)) return; + // Needed to remove the deleted block imports from the imports list. if (event.type === Blockly.Events.BLOCK_DELETE) wipeImports(); if (LOG_CODE) { diff --git a/src/lib/types/DiscodesInput.ts b/src/lib/types/DiscodesInput.ts new file mode 100644 index 0000000..d64bad8 --- /dev/null +++ b/src/lib/types/DiscodesInput.ts @@ -0,0 +1,9 @@ +import type BaseInput from "$lib/utils/BlockGen/Inputs/BaseInput"; +import type { DropdownIDef } from "$lib/utils/BlockGen/Inputs/Dropdown"; +import type { ImageIDef } from "$lib/utils/BlockGen/Inputs/Image"; +import type { NumberIDef } from "$lib/utils/BlockGen/Inputs/NumberInput"; +import type { StatementIDef } from "$lib/utils/BlockGen/Inputs/StatementInput"; +import type { TextIDef } from "$lib/utils/BlockGen/Inputs/TextInput"; +import type { ValueIDef } from "$lib/utils/BlockGen/Inputs/ValueInput"; + +export type DiscodesInput = BaseInput; diff --git a/src/lib/utils/BlockGen/Blocks/Block.ts b/src/lib/utils/BlockGen/Blocks/Block.ts index cfa309f..c2a581d 100644 --- a/src/lib/utils/BlockGen/Blocks/Block.ts +++ b/src/lib/utils/BlockGen/Blocks/Block.ts @@ -1,13 +1,15 @@ // Blockly import Blockly from "blockly/core"; -import "@blockly/field-grid-dropdown"; +import * as gridDropdown from "@blockly/field-grid-dropdown"; import pkg from "blockly/javascript"; const { javascriptGenerator, Order } = pkg; // Types import type { Argument, BlockDefinition } from "$lib/types/BlockDefinition"; -import { BlockShape, BlockType, WarningType } from "$lib/enums/BlockTypes"; +import { BlockShape, BlockType, DropdownType, WarningType } from "$lib/enums/BlockTypes"; import type { Abstract } from "blockly/core/events/events_abstract"; +import type { DiscodesInput } from "$lib/types/DiscodesInput"; +import type Warning from "../Warnings/Warning"; // Warnings import { addWarning, removeWarning, warnings as warningsObj } from "../Warnings/WarningsList"; @@ -17,11 +19,22 @@ import { EventsToTriggerWarnings } from "$lib/constants/warnings"; import { dev } from "$app/environment"; import salt from "$lib/utils/helpers/salt"; import { addImport } from "$lib/utils/BlockGen/Blocks/importsList"; -import type Warning from "../Warnings/Warning"; + +interface BlocklyBlockDefinition { + type: string + colour: string + tooltip: string + helpUrl: string + inputsInline: boolean + args0: Record[] + message0: string + mutator:string | undefined +}; export default class Block { private _blockDefinition: BlockDefinition; private _block!: Blockly.Block; + private _blocklyDefinition!: BlocklyBlockDefinition; constructor(definition: BlockDefinition) { this._blockDefinition = definition; @@ -35,18 +48,77 @@ export default class Block { this._block.setColour(colour); } - addWarning(warning: Warning): void { + public addWarning(warning: Warning): void { if (this._blockDefinition.label) throw new Error("Cannot add a warning to a label"); if (warningsObj[this._block.id] && warningsObj[this._block.id][warning.data.fieldName]) return; this._blockDefinition.warnings = this._blockDefinition.warnings ? [...this._blockDefinition.warnings, warning] : [warning]; } - removeWarning(fieldName: string): void { + public removeWarning(fieldName: string): void { if (this._blockDefinition.label) throw new Error("Cannot remove a warning form a label"); if ((!warningsObj[this._block.id] || !warningsObj[this._block.id][fieldName]) && this._blockDefinition.warnings !== undefined) return; this._blockDefinition.warnings = this._blockDefinition.warnings?.filter(warning => warning.data.fieldName !== fieldName); } + public addText(text: string, fieldName: string): void { + this._block.appendDummyInput(fieldName).appendField(text); + } + + public removeText(fieldName: string): void { + this._block.removeInput(fieldName); + } + + public addInput(input: DiscodesInput): void { + const generated = input.generate(); + if (!this._block || this._block.getInput(generated.name) || this._block.isInFlyout) return; + let isDummy: boolean = true; + + switch(generated.type) { + + case DropdownType.Grid: + this._block.appendDummyInput(generated.name) + .appendField(new gridDropdown.FieldGridDropdown(generated.options as Blockly.MenuGenerator) as Blockly.Field); + break; + + case DropdownType.List: + this._block.appendDummyInput(generated.name) + .appendField(new Blockly.FieldDropdown(generated.options as Blockly.MenuGenerator) as Blockly.Field); + break; + + case "input_value": + this._block.appendValueInput(generated.name) + .setCheck(generated.check as string | string[] | undefined ? generated.check as string | string[]: null); + isDummy = false; + break; + + case "input_statement": + this._block.appendStatementInput(generated.name); + isDummy = false; + break; + + case "field_number": + this._block.appendDummyInput(generated.name) + .appendField(new Blockly.FieldNumber(generated.value, generated.min, generated.max, generated.precision)); + break; + + case "field_image": + this._block.appendDummyInput(generated.name) + .appendField(new Blockly.FieldImage(generated.src, generated.width, generated.height, generated.alt)); + break; + + case "field_input": + this._block.appendDummyInput(generated.name) + .appendField(new Blockly.FieldTextInput(generated.text, undefined,{spellcheck: generated.spellcheck})); + break; + } + (this._blocklyDefinition.args0 as Array).push({...generated, isDummy: isDummy}); + } + + public removeInput(inputName: string): void { + if (!this._block.getInput(inputName)) return; + this._block.removeInput(inputName); + } + generate(): void { if (this._blockDefinition.label) return; @@ -61,17 +133,19 @@ export default class Block { ? this._blockDefinition.id + salt(5) : ""; - const blockDef = { + const blockDef: BlocklyBlockDefinition = { type: this._blockDefinition.id, colour: this._blockDefinition.colour, tooltip: this._blockDefinition.tooltip, helpUrl: this._blockDefinition.helpUrl, inputsInline: this._blockDefinition.inline, - args0: [] as Record[], + args0: [], message0: "", mutator: mutatorName == "" ? undefined : mutatorName }; + blockClass._blocklyDefinition = blockDef; + if (this._blockDefinition.mutator) { this._blockDefinition.mutator.registerMutator(mutatorName); } @@ -128,6 +202,7 @@ export default class Block { !this.isInFlyout && changeEvent.type !== Blockly.Events.VIEWPORT_CHANGE ) { + // "import" is a reserved name for (const import_ of importName) { addImport(import_); } @@ -186,27 +261,36 @@ export default class Block { // Generating the export code javascriptGenerator.forBlock[blockDef.type] = function(block: Blockly.Block) { - const args: Record = {}; //? Object we will pass as argument for the custom code to run properly - - for (const arg in blockDef.args0) { - const argValue = blockDef.args0[arg]; //? The argument object, contains the name, the type etc.. - const argName: string = blockDef.args0[arg].name as string; + const args: Record = {}; //? Object we will pass as argument to be used for code generation + + for (const arg of blockClass._blocklyDefinition.args0) { + if (arg.isDummy === true) { + // Since it's a dummy input we need to get the value from the fields array inside the dummy input! + //@ts-expect-error We have to access the protected value to generate it correctly. + args[arg.name] = block.getInput(arg.name)?.fieldRow[0].value_; + continue; + } - switch (argValue.type) { + switch (arg.type) { case "input_value": - args[argName] = javascriptGenerator.valueToCode( + args[arg.name] = javascriptGenerator.valueToCode( block, - argName, + arg.name, javascriptGenerator.ORDER_ATOMIC ); break; + case "input_statement": - args[argName] = javascriptGenerator.statementToCode(block, argName); + args[arg.name] = javascriptGenerator.statementToCode(block, arg.name); break; + default: - args[argName] = block.getFieldValue(argName); + args[arg.name] = block.getFieldValue(arg.name); break; } + + + } return output ? [code(args, blockClass), Order.NONE] : code(args, blockClass); }; diff --git a/src/lib/utils/BlockGen/Inputs/BaseInput.ts b/src/lib/utils/BlockGen/Inputs/BaseInput.ts index d3208c0..949963a 100644 --- a/src/lib/utils/BlockGen/Inputs/BaseInput.ts +++ b/src/lib/utils/BlockGen/Inputs/BaseInput.ts @@ -1,16 +1,11 @@ -export default class BaseInput { - //! Replace unknown by an enum with all the types of inputs! - private _method: () => unknown; +export default class BaseInput { + private _method!: () => Definition; - constructor() { - this._method = () => {}; - } - - protected setMethod(generationMethod: () => unknown) { + protected setMethod(generationMethod: () => Definition) { this._method = generationMethod; } - public generate(): unknown { + public generate(): Definition { return this._method(); } } diff --git a/src/lib/utils/BlockGen/Inputs/Dropdown.ts b/src/lib/utils/BlockGen/Inputs/Dropdown.ts index be2b4f7..6f9795d 100644 --- a/src/lib/utils/BlockGen/Inputs/Dropdown.ts +++ b/src/lib/utils/BlockGen/Inputs/Dropdown.ts @@ -2,10 +2,10 @@ import BaseInput from "./BaseInput"; import { DropdownType } from "$lib/enums/BlockTypes"; -interface DropdownJSON { +export interface DropdownIDef { name: string; type: DropdownType; - options: Array>; + options: string[][]; } /** @@ -15,7 +15,7 @@ interface DropdownJSON { * @class Dropdown * @extends {BaseInput} */ -export default class Dropdown extends BaseInput { +export default class Dropdown extends BaseInput { private readonly _name: string; private readonly _options: Array>; private _dropdownType: DropdownType; @@ -47,7 +47,7 @@ export default class Dropdown extends BaseInput { * @return {*} {DropdownJSON} * @memberof Dropdown */ - getDefinition(): DropdownJSON { + getDefinition(): DropdownIDef { if (this._dropdownType === DropdownType.Auto) { // Automatically swaps between grid and list type depending on the length of the arguments. this._dropdownType = this._options.length > 10 ? DropdownType.Grid : DropdownType.List; diff --git a/src/lib/utils/BlockGen/Inputs/Image.ts b/src/lib/utils/BlockGen/Inputs/Image.ts index 337cf1b..3f0feb7 100644 --- a/src/lib/utils/BlockGen/Inputs/Image.ts +++ b/src/lib/utils/BlockGen/Inputs/Image.ts @@ -1,6 +1,15 @@ import BaseInput from "./BaseInput"; -export default class Image extends BaseInput { +export interface ImageIDef { + name: string; + type: "field_image"; + src: string; + alt: string; + width: number; + height: number; +} + +export default class Image extends BaseInput { private readonly _src: string; private readonly _settings: { alt: string; @@ -22,14 +31,7 @@ export default class Image extends BaseInput { this._settings = settings; } - private getDefinition(): { - name: string; - type: "field_image"; - src: string; - alt: string; - width: number; - height: number; - } { + private getDefinition(): ImageIDef { return { name: this._settings.alt, type: "field_image", diff --git a/src/lib/utils/BlockGen/Inputs/NumberInput.ts b/src/lib/utils/BlockGen/Inputs/NumberInput.ts index ed4587c..5d59a00 100644 --- a/src/lib/utils/BlockGen/Inputs/NumberInput.ts +++ b/src/lib/utils/BlockGen/Inputs/NumberInput.ts @@ -1,6 +1,15 @@ import BaseInput from "./BaseInput"; -export default class NumberInput extends BaseInput { +export interface NumberIDef { + type: "field_number"; + name: string; + value: number + min? : number + max?: number + precision?: number +} + +export default class NumberInput extends BaseInput { private readonly _name: string; private readonly _value: number; private readonly _settings: { @@ -22,7 +31,7 @@ export default class NumberInput extends BaseInput { this._settings = settings || {}; } - private getDefinition(): { type: "field_number"; name: string; value: number } { + private getDefinition(): NumberIDef { return { type: "field_number", name: this._name, diff --git a/src/lib/utils/BlockGen/Inputs/StatementInput.ts b/src/lib/utils/BlockGen/Inputs/StatementInput.ts index d59c26d..0b52617 100644 --- a/src/lib/utils/BlockGen/Inputs/StatementInput.ts +++ b/src/lib/utils/BlockGen/Inputs/StatementInput.ts @@ -1,6 +1,6 @@ import BaseInput from "./BaseInput"; -interface StatementInputJSON { +export interface StatementIDef { name: string; type: "input_statement"; } @@ -12,7 +12,7 @@ interface StatementInputJSON { * @class ValueInput * @extends {BaseInput} */ -export default class StatementInput extends BaseInput { +export default class StatementInput extends BaseInput { private readonly _name: string; constructor(name: string) { @@ -28,7 +28,7 @@ export default class StatementInput extends BaseInput { * @return {*} {ValueInputJSON} * @memberof ValueInput */ - getDefinition(): StatementInputJSON { + getDefinition(): StatementIDef { return { type: "input_statement", name: this._name diff --git a/src/lib/utils/BlockGen/Inputs/TextInput.ts b/src/lib/utils/BlockGen/Inputs/TextInput.ts index b18a2e1..8583bb8 100644 --- a/src/lib/utils/BlockGen/Inputs/TextInput.ts +++ b/src/lib/utils/BlockGen/Inputs/TextInput.ts @@ -1,6 +1,6 @@ import BaseInput from "./BaseInput"; -interface TextInputObject { +export interface TextIDef { type: "field_input"; name: string; text: string; @@ -8,7 +8,7 @@ interface TextInputObject { spellcheck: false; } -export default class TextInput extends BaseInput { +export default class TextInput extends BaseInput { private readonly _name: string; private readonly _text: string; @@ -20,7 +20,7 @@ export default class TextInput extends BaseInput { this._text = defaultValue; } - private getDefinition(): TextInputObject { + private getDefinition(): TextIDef { return { type: "field_input", name: this._name, diff --git a/src/lib/utils/BlockGen/Inputs/ValueInput.ts b/src/lib/utils/BlockGen/Inputs/ValueInput.ts index 846bfc4..33a460e 100644 --- a/src/lib/utils/BlockGen/Inputs/ValueInput.ts +++ b/src/lib/utils/BlockGen/Inputs/ValueInput.ts @@ -2,7 +2,7 @@ import { BlockType } from "$lib/enums/BlockTypes"; import BaseInput from "./BaseInput"; import argFilter from "../../helpers/argFilter"; -interface ValueInputJSON { +export interface ValueIDef { name: string; type: "input_value"; check?: BlockType | BlockType[]; @@ -14,7 +14,7 @@ interface ValueInputJSON { * @class ValueInput * @extends {BaseInput} */ -export default class ValueInput extends BaseInput { +export default class ValueInput extends BaseInput { private readonly _name: string; private readonly _type: BlockType[]; @@ -32,8 +32,8 @@ export default class ValueInput extends BaseInput { * @return {*} {ValueInputJSON} * @memberof ValueInput */ - getDefinition(): ValueInputJSON { - const result: ValueInputJSON = { + getDefinition(): ValueIDef { + const result: ValueIDef = { type: "input_value", name: this._name }; From 2d835e6fe7f50bffd2214fc430eefb04a990ebda Mon Sep 17 00:00:00 2001 From: LimeNade Date: Sat, 20 Apr 2024 16:10:15 +0200 Subject: [PATCH 02/53] Fix: math category errors --- src/lib/blocks/Javascript/math.ts | 70 +++++++++++++------------- src/lib/utils/BlockGen/Blocks/Block.ts | 8 +-- 2 files changed, 36 insertions(+), 42 deletions(-) diff --git a/src/lib/blocks/Javascript/math.ts b/src/lib/blocks/Javascript/math.ts index 98d709c..35ca01c 100644 --- a/src/lib/blocks/Javascript/math.ts +++ b/src/lib/blocks/Javascript/math.ts @@ -1,12 +1,10 @@ -import { BlockShape, BlockType, WarningType, DropdownType, PlaceholderType } from "$lib/enums/BlockTypes"; +import { BlockShape, BlockType, DropdownType, PlaceholderType } from "$lib/enums/BlockTypes"; import type { BlockDefinition } from "$lib/types/BlockDefinition"; import type { CategoryDefinition } from "$lib/types/CategoryDefinition"; -import TextInput from "$lib/utils/BlockGen/Inputs/TextInput"; +import Dropdown from "$lib/utils/BlockGen/Inputs/Dropdown"; import NumberInput from "$lib/utils/BlockGen/Inputs/NumberInput"; import ValueInput from "$lib/utils/BlockGen/Inputs/ValueInput"; import Placeholder from "$lib/utils/ToolboxGen/Placeholder"; -import { Order } from "blockly/javascript"; -import Dropdown from "$lib/utils/BlockGen/Inputs/Dropdown"; const blocks: BlockDefinition[] = [ { @@ -93,21 +91,21 @@ const blocks: BlockDefinition[] = [ code: (args) => { switch (args.OPERATION) { case "negate": - return `Math.abs(${args.NUMBER}) * -1` + return `Math.abs(${args.NUMBER}) * -1`; case "inverse": - return `${args.NUMBER}) * -1` + return `${args.NUMBER}) * -1`; case "log10": - return `Math.log(${args.NUMBER}) / Math.log(10)` + return `Math.log(${args.NUMBER}) / Math.log(10)`; case "sin": case "cos": case "tan": case "asin": case "acos": case "atan": - return `(Math.(${args.OPERATION}) / Math.PI) * 180` + return `(Math.(${args.OPERATION}) / Math.PI) * 180`; default: - return `Math.${args.OPERATION}(${args.NUMBER})` + return `Math.${args.OPERATION}(${args.NUMBER})`; } } }, @@ -132,7 +130,7 @@ const blocks: BlockDefinition[] = [ tooltip: "Allows you to use constants.", helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", code: (args) => { - return `${args.CONSTANT}` + return `${args.CONSTANT}`; } }, { @@ -164,21 +162,21 @@ const blocks: BlockDefinition[] = [ code: (args) => { switch (`${args.VALUE}`) { case "number": - return `typeof ${args.NUMBER} === "number" && ${args.NUMBER} % 1 === 0` + return `typeof ${args.NUMBER} === "number" && ${args.NUMBER} % 1 === 0`; case "even": - return `${args.NUMBER} % 2 === 0` + return `${args.NUMBER} % 2 === 0`; case "odd": - return `${args.NUMBER} % 2!== 0` + return `${args.NUMBER} % 2!== 0`; case "prime": - return `isPrime(${args.NUMBER})` /* function isPrime(number) {if (number < 2) {return false;};for (let i = 2; i <= Math.sqrt(number); i++) {if (number % i === 0) {return false;}}return true;} */ + return `isPrime(${args.NUMBER})`; /* function isPrime(number) {if (number < 2) {return false;};for (let i = 2; i <= Math.sqrt(number); i++) {if (number % i === 0) {return false;}}return true;} */ case "whole": - return `${args.NUMBER} % 1 === 0` + return `${args.NUMBER} % 1 === 0`; case "positive": - return `${args.NUMBER} > 0` + return `${args.NUMBER} > 0`; case "negative": - return `${args.NUMBER} < 0` + return `${args.NUMBER} < 0`; default: - return `${args.NUMBER} % ${args.VALUE} === 0` // fix when added mutator + return `${args.NUMBER} % ${args.VALUE} === 0`; // fix when added mutator } } }, @@ -212,25 +210,25 @@ const blocks: BlockDefinition[] = [ code: (args) => { switch (args.OPERATION) { case "sum": - return `${args.ARRAY}.reduce((a, b) => a + b)` + return `${args.ARRAY}.reduce((a, b) => a + b)`; case "min": - return `${args.ARRAY}.reduce((a, b) => Math.min(a, b))` + return `${args.ARRAY}.reduce((a, b) => Math.min(a, b))`; case "max": - return `${args.ARRAY}.reduce((a, b) => Math.max(a, b))` + return `${args.ARRAY}.reduce((a, b) => Math.max(a, b))`; case "average": - return `${args.ARRAY}.reduce((a, b) => a + b) / ${args.ARRAY}.length` + return `${args.ARRAY}.reduce((a, b) => a + b) / ${args.ARRAY}.length`; case "median": - return `${args.ARRAY}.sort((a, b) => a - b).length % 2? ${args.ARRAY}.sort((a, b) => a - b)[Math.floor(${args.ARRAY}.length / 2)] : ((${args.ARRAY}.sort((a, b) => a - b)[Math.floor(${args.ARRAY}.length / 2)] + ${args.ARRAY}.sort((a, b) => a - b - 1)[Math.floor(${args.ARRAY}.length / 2)]) / 2 ))` + return `${args.ARRAY}.sort((a, b) => a - b).length % 2? ${args.ARRAY}.sort((a, b) => a - b)[Math.floor(${args.ARRAY}.length / 2)] : ((${args.ARRAY}.sort((a, b) => a - b)[Math.floor(${args.ARRAY}.length / 2)] + ${args.ARRAY}.sort((a, b) => a - b - 1)[Math.floor(${args.ARRAY}.length / 2)]) / 2 ))`; case "mode": - return `${args.ARRAY}.sort((a, b) => a - b).length % 2` + return `${args.ARRAY}.sort((a, b) => a - b).length % 2`; case "range": - return `${args.ARRAY}.reduce((a, b) => Math.max(a, b) - Math.min(a, b))` + return `${args.ARRAY}.reduce((a, b) => Math.max(a, b) - Math.min(a, b))`; case "random": - return `Math.floor(Math.random() * ${args.ARRAY}.length)` + return `Math.floor(Math.random() * ${args.ARRAY}.length)`; case "standard deviation": - return `Math.sqrt(${args.ARRAY}.reduce((a, b) => Math.pow(a - b, 2)) / ${args.ARRAY}.length)` + return `Math.sqrt(${args.ARRAY}.reduce((a, b) => Math.pow(a - b, 2)) / ${args.ARRAY}.length)`; default: - return `Math.${args.OPERATION}(${args.ARRAY})` + return `Math.${args.OPERATION}(${args.ARRAY})`; } } }, @@ -252,7 +250,7 @@ const blocks: BlockDefinition[] = [ tooltip: "Gets a random integer between two numbers.", helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", code: (args) => { - return `Math.floor(Math.random() * (${args.MAX} - ${args.MIN}) + ${args.MIN})` + return `Math.floor(Math.random() * (${args.MAX} - ${args.MIN}) + ${args.MIN})`; } }, { @@ -265,8 +263,8 @@ const blocks: BlockDefinition[] = [ colour: "#5b67a5", tooltip: "Gets a random fraction.", helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", - code: (args) => { - return `Math.random()` + code: () => { + return "Math.random()"; } }, { @@ -285,7 +283,7 @@ const blocks: BlockDefinition[] = [ tooltip: "Converts text to a number.", helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", code: (args) => { - return `parseInt(${args.TEXT})` + return `parseInt(${args.TEXT})`; } }, { @@ -308,7 +306,7 @@ const blocks: BlockDefinition[] = [ tooltip: "Constrains a number between two numbers.", helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", code: (args) => { - return `Math.min(Math.max(${args.VALUE}, ${args.MIN}), ${args.MAX})` + return `Math.min(Math.max(${args.VALUE}, ${args.MIN}), ${args.MAX})`; } }, // { @@ -332,11 +330,11 @@ const blocks: BlockDefinition[] = [ // } -] +]; const category: CategoryDefinition = { name: "Math", colour: "#5b67a5" -} +}; -export default {blocks, category} \ No newline at end of file +export default {blocks, category}; diff --git a/src/lib/utils/BlockGen/Blocks/Block.ts b/src/lib/utils/BlockGen/Blocks/Block.ts index c2a581d..9e64bf7 100644 --- a/src/lib/utils/BlockGen/Blocks/Block.ts +++ b/src/lib/utils/BlockGen/Blocks/Block.ts @@ -74,7 +74,6 @@ export default class Block { let isDummy: boolean = true; switch(generated.type) { - case DropdownType.Grid: this._block.appendDummyInput(generated.name) .appendField(new gridDropdown.FieldGridDropdown(generated.options as Blockly.MenuGenerator) as Blockly.Field); @@ -264,6 +263,8 @@ export default class Block { const args: Record = {}; //? Object we will pass as argument to be used for code generation for (const arg of blockClass._blocklyDefinition.args0) { + //! Fix this asap... + //@ts-expect-error gergerg if (arg.isDummy === true) { // Since it's a dummy input we need to get the value from the fields array inside the dummy input! //@ts-expect-error We have to access the protected value to generate it correctly. @@ -288,13 +289,8 @@ export default class Block { args[arg.name] = block.getFieldValue(arg.name); break; } - - - } return output ? [code(args, blockClass), Order.NONE] : code(args, blockClass); }; } - - } From da86697f0ae9e3e6a9c344ad3d570ce2687974d9 Mon Sep 17 00:00:00 2001 From: LimeNade Date: Sat, 20 Apr 2024 20:13:03 +0200 Subject: [PATCH 03/53] Fix: Merge conflicts crumbs --- src/lib/blocks/Javascript/Loops.ts | 6 +++--- src/lib/utils/BlockGen/Blocks/Block.ts | 2 +- src/lib/utils/BlockGen/Inputs/BaseInput.ts | 2 +- src/lib/utils/BlockGen/Inputs/Dropdown.ts | 2 -- src/lib/utils/BlockGen/Inputs/Image.ts | 6 +----- src/lib/utils/BlockGen/Inputs/NumberInput.ts | 1 - src/lib/utils/BlockGen/Inputs/StatementInput.ts | 2 -- src/lib/utils/BlockGen/Inputs/TextInput.ts | 1 - src/lib/utils/BlockGen/Inputs/ValueInput.ts | 1 - 9 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/lib/blocks/Javascript/Loops.ts b/src/lib/blocks/Javascript/Loops.ts index 27ed0f0..2a7fddb 100644 --- a/src/lib/blocks/Javascript/Loops.ts +++ b/src/lib/blocks/Javascript/Loops.ts @@ -61,9 +61,9 @@ const blocks: BlockDefinition[] = [ helpUrl: "", code: (args) => { if(args.VARIABLE === "") return ""; - let variable = `let ${args.VARIABLE} =${args.START ===""? "0" : args.START}`; - let condition = `${args.VARIABLE} < ${args.END === ""? "0" : args.END}`; - let step = `${args.VARIABLE} += ${args.STEP ===""? "0" : args.STEP}}`; + const variable = `let ${args.VARIABLE} =${args.START ===""? "0" : args.START}`; + const condition = `${args.VARIABLE} < ${args.END === ""? "0" : args.END}`; + const step = `${args.VARIABLE} += ${args.STEP ===""? "0" : args.STEP}}`; if (args.VARIABLE === "") { const varName = salt(10); return `for(let vk${varName} = 0; false; vk${varName}+= 0) {}`; diff --git a/src/lib/utils/BlockGen/Blocks/Block.ts b/src/lib/utils/BlockGen/Blocks/Block.ts index 5f80426..8427212 100644 --- a/src/lib/utils/BlockGen/Blocks/Block.ts +++ b/src/lib/utils/BlockGen/Blocks/Block.ts @@ -11,7 +11,7 @@ import type { CheckBoxMutatorBlock, MutatorBlock } from "$lib/types/BlockDefinition"; -import { BlockShape, BlockType, DropdownType, WarningType } from "$lib/enums/BlockTypes"; +import { BlockShape, BlockType, DropdownType, MutatorType, WarningType } from "$lib/enums/BlockTypes"; import type { Abstract } from "blockly/core/events/events_abstract"; import type { DiscodesInput } from "$lib/types/DiscodesInput"; import type Warning from "../Warnings/Warning"; diff --git a/src/lib/utils/BlockGen/Inputs/BaseInput.ts b/src/lib/utils/BlockGen/Inputs/BaseInput.ts index c8375f3..0bcdadb 100644 --- a/src/lib/utils/BlockGen/Inputs/BaseInput.ts +++ b/src/lib/utils/BlockGen/Inputs/BaseInput.ts @@ -15,7 +15,7 @@ export default class BaseInput { /* this function currently is meant for Mutator use */ - public setField(text: string): BaseInput { + public setField(text: string): BaseInput { this._fieldText = text; return this; } diff --git a/src/lib/utils/BlockGen/Inputs/Dropdown.ts b/src/lib/utils/BlockGen/Inputs/Dropdown.ts index 506f255..f47b068 100644 --- a/src/lib/utils/BlockGen/Inputs/Dropdown.ts +++ b/src/lib/utils/BlockGen/Inputs/Dropdown.ts @@ -17,7 +17,6 @@ export interface DropdownIDef { */ export default class Dropdown extends BaseInput { - private readonly _name: string; private readonly _options: Array>; private _dropdownType: DropdownType; @@ -53,7 +52,6 @@ export default class Dropdown extends BaseInput { // Automatically swaps between grid and list type depending on the length of the arguments. this._dropdownType = this._options.length > 10 ? DropdownType.Grid : DropdownType.List; } - console.log(this._options) return { type: this._dropdownType, name: super.name, diff --git a/src/lib/utils/BlockGen/Inputs/Image.ts b/src/lib/utils/BlockGen/Inputs/Image.ts index 3f0feb7..cc5dedd 100644 --- a/src/lib/utils/BlockGen/Inputs/Image.ts +++ b/src/lib/utils/BlockGen/Inputs/Image.ts @@ -24,7 +24,7 @@ export default class Image extends BaseInput { * @memberof NumberInput */ constructor(src: string, settings: { alt: string; width: number; height: number }) { - super(); + super(settings.alt); this.setMethod(this.getDefinition); this._src = src; @@ -39,8 +39,4 @@ export default class Image extends BaseInput { ...this._settings }; } - - get name(): string { - return this._settings.alt; - } } diff --git a/src/lib/utils/BlockGen/Inputs/NumberInput.ts b/src/lib/utils/BlockGen/Inputs/NumberInput.ts index cbc326b..b9ed18b 100644 --- a/src/lib/utils/BlockGen/Inputs/NumberInput.ts +++ b/src/lib/utils/BlockGen/Inputs/NumberInput.ts @@ -11,7 +11,6 @@ export interface NumberIDef { } export default class NumberInput extends BaseInput { - private readonly _name: string; private readonly _value: number; private readonly _settings: { min?: number; diff --git a/src/lib/utils/BlockGen/Inputs/StatementInput.ts b/src/lib/utils/BlockGen/Inputs/StatementInput.ts index 21d15e2..dd26c8c 100644 --- a/src/lib/utils/BlockGen/Inputs/StatementInput.ts +++ b/src/lib/utils/BlockGen/Inputs/StatementInput.ts @@ -14,8 +14,6 @@ export interface StatementIDef { */ export default class StatementInput extends BaseInput { - private readonly _name: string; - constructor(name: string) { super(name); diff --git a/src/lib/utils/BlockGen/Inputs/TextInput.ts b/src/lib/utils/BlockGen/Inputs/TextInput.ts index c7d764e..7000423 100644 --- a/src/lib/utils/BlockGen/Inputs/TextInput.ts +++ b/src/lib/utils/BlockGen/Inputs/TextInput.ts @@ -10,7 +10,6 @@ export interface TextIDef { export default class TextInput extends BaseInput { - private readonly _name: string; private readonly _text: string; constructor(name: string, defaultValue: string) { diff --git a/src/lib/utils/BlockGen/Inputs/ValueInput.ts b/src/lib/utils/BlockGen/Inputs/ValueInput.ts index cd1a581..1962258 100644 --- a/src/lib/utils/BlockGen/Inputs/ValueInput.ts +++ b/src/lib/utils/BlockGen/Inputs/ValueInput.ts @@ -16,7 +16,6 @@ export interface ValueIDef { */ export default class ValueInput extends BaseInput { - private readonly _name: string; private readonly _type: BlockType[]; constructor(name: string, type: BlockType | BlockType[]) { From 4fdb7c2ad3fac05de3d648987e299ff33ede1aa3 Mon Sep 17 00:00:00 2001 From: LimeNade Date: Sat, 20 Apr 2024 20:17:05 +0200 Subject: [PATCH 04/53] Fix: import bug --- src/lib/blocks/Javascript/text.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/blocks/Javascript/text.ts b/src/lib/blocks/Javascript/text.ts index 0e2f9a4..980a019 100644 --- a/src/lib/blocks/Javascript/text.ts +++ b/src/lib/blocks/Javascript/text.ts @@ -6,7 +6,7 @@ import ValueInput from "$lib/utils/BlockGen/Inputs/ValueInput"; import Placeholder from "$lib/utils/ToolboxGen/Placeholder"; import StatementInput from "$lib/utils/BlockGen/Inputs/StatementInput"; import Dropdown from "$lib/utils/BlockGen/Inputs/Dropdown"; -import AssemblerMutator from "$lib/utils/BlockGen/Mutators/AssemblerMutator"; +import AssemblerMutatorV2 from "$lib/utils/BlockGen/Mutators/AssemblerMutatorV2"; const blocks: BlockDefinition[] = [ @@ -40,7 +40,7 @@ const blocks: BlockDefinition[] = [ code: (args) => { return `new Text("${args.CONTENT}")`; }, - mutator: new AssemblerMutator("Add Content", [ + mutator: new AssemblerMutatorV2("Add Content", [ { block: "text_content", adds: [new ValueInput("text_content", BlockType.String)], From 218930aff81b2436e6b797d28c95005de9f3b1cf Mon Sep 17 00:00:00 2001 From: LimeNade Date: Sat, 20 Apr 2024 20:22:39 +0200 Subject: [PATCH 05/53] Chore: Lint --- src/lib/blocks/Javascript/Loops.ts | 12 +- src/lib/blocks/Javascript/logic.ts | 73 +- src/lib/blocks/Javascript/math.ts | 640 +++++++++--------- src/lib/blocks/Javascript/text.ts | 569 ++++++++-------- src/lib/blocks/Test Blocks/mutators.ts | 43 +- src/lib/components/Workspace.svelte | 4 +- src/lib/enums/BlockTypes.ts | 2 +- src/lib/types/BlockDefinition.ts | 10 +- src/lib/types/DiscodesInput.ts | 4 +- src/lib/utils/BlockGen/Blocks/Block.ts | 206 +++--- src/lib/utils/BlockGen/Inputs/BaseInput.ts | 2 +- src/lib/utils/BlockGen/Inputs/Dropdown.ts | 1 - src/lib/utils/BlockGen/Inputs/NumberInput.ts | 16 +- .../utils/BlockGen/Inputs/StatementInput.ts | 4 +- src/lib/utils/BlockGen/Inputs/TextInput.ts | 2 - src/lib/utils/BlockGen/Inputs/ValueInput.ts | 1 - .../BlockGen/Mutators/AssemblerMutatorV2.ts | 474 +++++++------ .../BlockGen/Mutators/CheckboxMutator.ts | 78 ++- src/lib/utils/BlockGen/Mutators/Mutator.ts | 8 +- src/lib/utils/helpers/getInputValue.ts | 24 +- src/routes/+page.svelte | 2 +- 21 files changed, 1087 insertions(+), 1088 deletions(-) diff --git a/src/lib/blocks/Javascript/Loops.ts b/src/lib/blocks/Javascript/Loops.ts index 2a7fddb..02f8ccc 100644 --- a/src/lib/blocks/Javascript/Loops.ts +++ b/src/lib/blocks/Javascript/Loops.ts @@ -18,7 +18,7 @@ const blocks: BlockDefinition[] = [ tooltip: "Repeats the code inside the given ammount of times.", helpUrl: "", code: (args) => { - return `for (let i = 0; i < ${args.VALUE === ""? "0" : args.VALUE}; i++) {\n${args.INPUT === ""? "" : args.INPUT}\n}`; + return `for (let i = 0; i < ${args.VALUE === "" ? "0" : args.VALUE}; i++) {\n${args.INPUT === "" ? "" : args.INPUT}\n}`; } }, { @@ -38,7 +38,7 @@ const blocks: BlockDefinition[] = [ tooltip: "Repeat while", helpUrl: "", code: (args) => { - return `while (${args.WHILE === "while" ? "" : "!"}( ${args.CONDITION === ""? "false" : args.CONDITION} )) {\n${args.INPUT === ""? "" : args.INPUT}\n}`; + return `while (${args.WHILE === "while" ? "" : "!"}( ${args.CONDITION === "" ? "false" : args.CONDITION} )) {\n${args.INPUT === "" ? "" : args.INPUT}\n}`; } }, { @@ -60,10 +60,10 @@ const blocks: BlockDefinition[] = [ tooltip: "For loop", helpUrl: "", code: (args) => { - if(args.VARIABLE === "") return ""; - const variable = `let ${args.VARIABLE} =${args.START ===""? "0" : args.START}`; - const condition = `${args.VARIABLE} < ${args.END === ""? "0" : args.END}`; - const step = `${args.VARIABLE} += ${args.STEP ===""? "0" : args.STEP}}`; + if (args.VARIABLE === "") return ""; + const variable = `let ${args.VARIABLE} =${args.START === "" ? "0" : args.START}`; + const condition = `${args.VARIABLE} < ${args.END === "" ? "0" : args.END}`; + const step = `${args.VARIABLE} += ${args.STEP === "" ? "0" : args.STEP}}`; if (args.VARIABLE === "") { const varName = salt(10); return `for(let vk${varName} = 0; false; vk${varName}+= 0) {}`; diff --git a/src/lib/blocks/Javascript/logic.ts b/src/lib/blocks/Javascript/logic.ts index 0fe8bcf..335c42b 100644 --- a/src/lib/blocks/Javascript/logic.ts +++ b/src/lib/blocks/Javascript/logic.ts @@ -12,50 +12,58 @@ import AssemblerMutatorV2 from "$lib/utils/BlockGen/Mutators/AssemblerMutatorV2" const blocks: BlockDefinition[] = [ { - id: "if_block", text: "if {operand} {if}", args: [new ValueInput("operand", BlockType.Boolean), new StatementInput("if")], - warnings: [new Warning(WarningType.Input, { - fieldName: "operand", - })], + warnings: [ + new Warning(WarningType.Input, { + fieldName: "operand" + }) + ], shape: BlockShape.Action, inline: true, colour: rgbToHex(91, 128, 165), tooltip: "Returns the opposite of the input", helpUrl: - `https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_NOT`, + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_NOT", code: (args) => { - console.log(args) - let code = `if(${args.operand === ""? "false" : args.operand}) { + console.log(args); + let code = `if(${args.operand === "" ? "false" : args.operand}) { ${args.if} }`; const ifInputs = args.if_input as string[]; const ifStatementInputs = args.if_statement as string[]; - for (let i=0; i < ifInputs.length; i++) { + for (let i = 0; i < ifInputs.length; i++) { const ifInp = ifInputs[i]; - code += ` else if(${ifInp === ""? "false" : ifInp}) { + code += ` else if(${ifInp === "" ? "false" : ifInp}) { ${ifStatementInputs[i]} }`; } return code; }, - mutator: new AssemblerMutatorV2("If", [ - { - block: "if_test", - adds: [new ValueInput("if_input", BlockType.Boolean).setField("else if"), new StatementInput("if_statement").setField("do")], - once: true - }, + mutator: new AssemblerMutatorV2( + "If", + [ + { + block: "if_test", + adds: [ + new ValueInput("if_input", BlockType.Boolean).setField("else if"), + new StatementInput("if_statement").setField("do") + ], + once: true + }, + { + block: "else_test", + adds: [new StatementInput("else_input").setField("else")], + once: true + } + ], { - block: "else_test", - adds: [new StatementInput("else_input").setField("else")], - once: true + color: rgbToHex(91, 128, 165) } - ], { - color: rgbToHex(91, 128, 165) - }) + ) }, { id: "is_equal", @@ -68,7 +76,7 @@ const blocks: BlockDefinition[] = [ "<": "<", "≤": "<=", ">": ">", - "≥": ">=", + "≥": ">=" //always need to use === instead of == in js, removed this //because user is always going to select the first one and question the last one. //"==": "===" @@ -90,13 +98,12 @@ const blocks: BlockDefinition[] = [ // return `${args.A} ${args.CONDITION} ${args.B}`; code: (args, block) => { - block.addInput(new Dropdown("bob", DropdownType.Auto, {"bob": "hello", "alex":"nikola"})); + block.addInput(new Dropdown("bob", DropdownType.Auto, { bob: "hello", alex: "nikola" })); block.addInput(new ValueInput("chicken", BlockType.Any)); - block.addInput(new NumberInput("numberrr", 50, {max: 100, min: 50, precision: 10})); + block.addInput(new NumberInput("numberrr", 50, { max: 100, min: 50, precision: 10 })); block.addInput(new TextInput("textttt", "I am a text input!")); - console.log("Args (code prop parameter): ",args); + console.log("Args (code prop parameter): ", args); return `${args.textttt}`; - } }, { @@ -118,7 +125,7 @@ const blocks: BlockDefinition[] = [ tooltip: "Checks if the first input and the second input validate the condition.", helpUrl: "", code: (args) => { - if(args.A === "" || args.B === "") return "false"; + if (args.A === "" || args.B === "") return "false"; return `${args.A} ${args.CONDITION} ${args.B}`; } @@ -136,7 +143,7 @@ const blocks: BlockDefinition[] = [ helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_NOT", code: (args) => { - if(args.OPERAND === "") return "false"; + if (args.OPERAND === "") return "false"; return `!${args.OPERAND}`; } @@ -148,18 +155,18 @@ const blocks: BlockDefinition[] = [ new Dropdown("INPUT", DropdownType.Auto, { true: "true", false: "false", - null: "null", + null: "null" //undefined: "undefined" }) ], shape: BlockShape.Floating, - output: BlockType.Any , + output: BlockType.Any, inline: true, colour: rgbToHex(91, 128, 165), tooltip: "", helpUrl: "", code: (args) => { - return `${args.INPUT !== ""? args.INPUT : "null"}`; + return `${args.INPUT !== "" ? args.INPUT : "null"}`; } }, { @@ -197,7 +204,7 @@ const blocks: BlockDefinition[] = [ tooltip: "", helpUrl: "", code: (args) => { - if(args.OPERAND === "") return "null"; + if (args.OPERAND === "") return "null"; return `typeof ${args.OPERAND}`; } }, @@ -218,10 +225,8 @@ const blocks: BlockDefinition[] = [ }) ], warnings: [ - // new Warning(WarningType.Input, { fieldName: "OPERAND" }), new Warning(WarningType.Input, { fieldName: "TYPE" }) - ], shape: BlockShape.Bottom, output: BlockType.Boolean, diff --git a/src/lib/blocks/Javascript/math.ts b/src/lib/blocks/Javascript/math.ts index 35ca01c..d54ba0e 100644 --- a/src/lib/blocks/Javascript/math.ts +++ b/src/lib/blocks/Javascript/math.ts @@ -7,334 +7,326 @@ import ValueInput from "$lib/utils/BlockGen/Inputs/ValueInput"; import Placeholder from "$lib/utils/ToolboxGen/Placeholder"; const blocks: BlockDefinition[] = [ - { - id: "number", - text: "{NUMBER}", - args: [ - new NumberInput("NUMBER", 0) - ], - shape: BlockShape.Floating, - output: BlockType.Number, - inline: true, - colour: "#5b67a5", - tooltip: "Allows you to make a number input.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", - code: (args) => { - return `${args.NUMBER}`; - } - }, - { - id: "operations", - text: "{OPERAND1} {OPERATOR} {OPERAND2}", - args: [ - new ValueInput("OPERAND1", BlockType.Number), - new Dropdown("OPERATOR", DropdownType.Auto, { - "+": "+", - "-": "-", - "*": "*", - "/": "/", - "%": "%", - "^": "pow", - }), - new ValueInput("OPERAND2", BlockType.Number), - ], - placeholders: [ - new Placeholder(PlaceholderType.Block, "OPERAND1", "number", {NUMBER: 1}), - new Placeholder(PlaceholderType.Block, "OPERAND2", "number", {NUMBER: 2}) + { + id: "number", + text: "{NUMBER}", + args: [new NumberInput("NUMBER", 0)], + shape: BlockShape.Floating, + output: BlockType.Number, + inline: true, + colour: "#5b67a5", + tooltip: "Allows you to make a number input.", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", + code: (args) => { + return `${args.NUMBER}`; + } + }, + { + id: "operations", + text: "{OPERAND1} {OPERATOR} {OPERAND2}", + args: [ + new ValueInput("OPERAND1", BlockType.Number), + new Dropdown("OPERATOR", DropdownType.Auto, { + "+": "+", + "-": "-", + "*": "*", + "/": "/", + "%": "%", + "^": "pow" + }), + new ValueInput("OPERAND2", BlockType.Number) + ], + placeholders: [ + new Placeholder(PlaceholderType.Block, "OPERAND1", "number", { NUMBER: 1 }), + new Placeholder(PlaceholderType.Block, "OPERAND2", "number", { NUMBER: 2 }) + ], + shape: BlockShape.Floating, + output: BlockType.Number, + inline: true, + colour: "#5b67a5", + tooltip: "Allows you to make operations with numbers.", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", + code: (args) => { + if (args.OPERATOR === "pow") return `Math.pow(${args.OPERAND1}, ${args.OPERAND2})`; + return `${args.OPERAND1} ${args.OPERATOR} ${args.OPERAND2}`; + } + }, + { + id: "operations2", + text: "{OPERATION} {NUMBER}", + args: [ + new Dropdown("OPERATION", DropdownType.Auto, { + "square root": "sqrt", + absolute: "abs", + negate: "negative", + inverse: "inverse", + ln: "log", + log10: "log10", + exp: "exp", + sin: "sin", + cos: "cos", + tan: "tan", + asin: "asin", + acos: "acos", + atan: "atan", + round: "round", + "round up": "ceil", + "round down": "floor" + }), + new ValueInput("NUMBER", BlockType.Number) + ], + placeholders: [new Placeholder(PlaceholderType.Block, "NUMBER", "number", { NUMBER: 1 })], + shape: BlockShape.Floating, + output: BlockType.Number, + inline: true, + colour: "#5b67a5", + tooltip: "Allows you to make operations with numbers.", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", + code: (args) => { + switch (args.OPERATION) { + case "negate": + return `Math.abs(${args.NUMBER}) * -1`; - ], - shape: BlockShape.Floating, - output: BlockType.Number, - inline: true, - colour: "#5b67a5", - tooltip: "Allows you to make operations with numbers.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", - code: (args) => { - if (args.OPERATOR === "pow") return `Math.pow(${args.OPERAND1}, ${args.OPERAND2})`; - return `${args.OPERAND1} ${args.OPERATOR} ${args.OPERAND2}`; - } - }, - { - id: "operations2", - text: "{OPERATION} {NUMBER}", - args: [ - new Dropdown("OPERATION", DropdownType.Auto, { - "square root": "sqrt", - "absolute": "abs", - "negate": "negative", - "inverse": "inverse", - "ln": "log", - "log10": "log10", - "exp": "exp", - "sin": "sin", - "cos": "cos", - "tan": "tan", - "asin": "asin", - "acos": "acos", - "atan": "atan", - "round": "round", - "round up": "ceil", - "round down": "floor", - } - ), - new ValueInput("NUMBER", BlockType.Number), - ], - placeholders: [ - new Placeholder(PlaceholderType.Block, "NUMBER", "number", {NUMBER: 1}) - ], - shape: BlockShape.Floating, - output: BlockType.Number, - inline: true, - colour: "#5b67a5", - tooltip: "Allows you to make operations with numbers.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", - code: (args) => { - switch (args.OPERATION) { - case "negate": - return `Math.abs(${args.NUMBER}) * -1`; - - case "inverse": - return `${args.NUMBER}) * -1`; - case "log10": - return `Math.log(${args.NUMBER}) / Math.log(10)`; - case "sin": - case "cos": - case "tan": - case "asin": - case "acos": - case "atan": - return `(Math.(${args.OPERATION}) / Math.PI) * 180`; - default: - return `Math.${args.OPERATION}(${args.NUMBER})`; - } - } - }, - { - id: "constants", - text: "{CONSTANT}", - args: [ - new Dropdown("CONSTANT", DropdownType.Auto, { - "π": "Math.PI", - "e": "Math.E", - "ϕ": "(1 + Math.sqrt(5)) / 2", - "√(2)": "Math.SQRT2", - "√(½)": "Math.Math.SQRT1_2", - "∞": "Infinity", - "NaN": "NaN", - }) - ], - shape: BlockShape.Floating, - output: BlockType.Number, - inline: true, - colour: "#5b67a5", - tooltip: "Allows you to use constants.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", - code: (args) => { - return `${args.CONSTANT}`; - } - }, - { - id: "is", - text: "{NUMBER} is {VALUE}", - args: [ - new ValueInput("NUMBER", BlockType.Number), - new Dropdown("VALUE", DropdownType.Auto, { - "number": "number", - "even": "even", - "odd": "odd", - "prime": "prime", - "whole": "whole", - "positive": "positive", - "negative": "negative", - "divisible by": "divisible" - })], - placeholders: [ - new Placeholder(PlaceholderType.Block, "NUMBER", "number", {NUMBER: 1}), - - - ], - shape: BlockShape.Floating, - output: BlockType.Boolean, - inline: true, - colour: "#5b67a5", - tooltip: "Checks if a number is even, odd, prime, whole, positive, negative, or div", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", - code: (args) => { - switch (`${args.VALUE}`) { - case "number": - return `typeof ${args.NUMBER} === "number" && ${args.NUMBER} % 1 === 0`; - case "even": - return `${args.NUMBER} % 2 === 0`; - case "odd": - return `${args.NUMBER} % 2!== 0`; - case "prime": - return `isPrime(${args.NUMBER})`; /* function isPrime(number) {if (number < 2) {return false;};for (let i = 2; i <= Math.sqrt(number); i++) {if (number % i === 0) {return false;}}return true;} */ - case "whole": - return `${args.NUMBER} % 1 === 0`; - case "positive": - return `${args.NUMBER} > 0`; - case "negative": - return `${args.NUMBER} < 0`; - default: - return `${args.NUMBER} % ${args.VALUE} === 0`; // fix when added mutator - } - } - }, - { - id: "array_math", - text: "{OPERATION} of list {ARRAY}", - args: [ - new Dropdown("OPERATION", DropdownType.Auto, { - "sum": "sum", - "min": "min", - "max": "max", - "average": "average", - "median": "median", - "mode": "mode", - "range": "range", - "random": "random", - "standard deviation": "standard deviation", - - }), - new ValueInput("ARRAY", BlockType.Array) - ], - // placeholders: [ - // new Placeholder(PlaceholderType.Block, "ARRAY", "array", {ARRAY: [1, 2, 3]}) - // ], - shape: BlockShape.Floating, - output: BlockType.Number, - inline: true, - colour: "#5b67a5", - tooltip: "Allows you to use math with arrays.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", - code: (args) => { - switch (args.OPERATION) { - case "sum": - return `${args.ARRAY}.reduce((a, b) => a + b)`; - case "min": - return `${args.ARRAY}.reduce((a, b) => Math.min(a, b))`; - case "max": - return `${args.ARRAY}.reduce((a, b) => Math.max(a, b))`; - case "average": - return `${args.ARRAY}.reduce((a, b) => a + b) / ${args.ARRAY}.length`; - case "median": - return `${args.ARRAY}.sort((a, b) => a - b).length % 2? ${args.ARRAY}.sort((a, b) => a - b)[Math.floor(${args.ARRAY}.length / 2)] : ((${args.ARRAY}.sort((a, b) => a - b)[Math.floor(${args.ARRAY}.length / 2)] + ${args.ARRAY}.sort((a, b) => a - b - 1)[Math.floor(${args.ARRAY}.length / 2)]) / 2 ))`; - case "mode": - return `${args.ARRAY}.sort((a, b) => a - b).length % 2`; - case "range": - return `${args.ARRAY}.reduce((a, b) => Math.max(a, b) - Math.min(a, b))`; - case "random": - return `Math.floor(Math.random() * ${args.ARRAY}.length)`; - case "standard deviation": - return `Math.sqrt(${args.ARRAY}.reduce((a, b) => Math.pow(a - b, 2)) / ${args.ARRAY}.length)`; - default: - return `Math.${args.OPERATION}(${args.ARRAY})`; - } - } - }, - { - id: "random_int", - text: "random integer between {MIN} to {MAX}", - args: [ - new ValueInput("MIN", BlockType.Number), - new ValueInput("MAX", BlockType.Number) - ], - placeholders: [ - new Placeholder(PlaceholderType.Block, "MIN", "number", {NUMBER: 1}), - new Placeholder(PlaceholderType.Block, "MAX", "number", {NUMBER: 10}) - ], - shape: BlockShape.Floating, - output: BlockType.Number, - inline: true, - colour: "#5b67a5", - tooltip: "Gets a random integer between two numbers.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", - code: (args) => { - return `Math.floor(Math.random() * (${args.MAX} - ${args.MIN}) + ${args.MIN})`; - } - }, - { - id: "random_fraction", - text: "random fraction", - args: [], - shape: BlockShape.Floating, - output: BlockType.Number, - inline: true, - colour: "#5b67a5", - tooltip: "Gets a random fraction.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", - code: () => { - return "Math.random()"; - } - }, - { - id: "toNumber", - text: "convert text {TEXT} to number", - args: [ - new ValueInput("TEXT", BlockType.String) - ], - placeholders: [ - new Placeholder(PlaceholderType.Block, "TEXT", "text", {TEXT: "123"}) - ], - shape: BlockShape.Floating, - output: BlockType.Number, - inline: true, - colour: "#5b67a5", - tooltip: "Converts text to a number.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", - code: (args) => { - return `parseInt(${args.TEXT})`; - } - }, - { - id: "constrain {VALUE} between {MIN} and {MAX}", - text: "constrain {VALUE} between {MIN} and {MAX}", - args: [ - new ValueInput("VALUE", BlockType.Number), - new ValueInput("MIN", BlockType.Number), - new ValueInput("MAX", BlockType.Number) - ], - placeholders: [ - new Placeholder(PlaceholderType.Block, "VALUE", "number", {NUMBER: 50}), - new Placeholder(PlaceholderType.Block, "MIN", "number", {NUMBER: 1}), - new Placeholder(PlaceholderType.Block, "MAX", "number", {NUMBER: 100}) - ], - shape: BlockShape.Floating, - output: BlockType.Number, - inline: true, - colour: "#5b67a5", - tooltip: "Constrains a number between two numbers.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", - code: (args) => { - return `Math.min(Math.max(${args.VALUE}, ${args.MIN}), ${args.MAX})`; - } - }, - // { - // id: "chance {CHANCE} %", - // text: "{CHANCE} % chance of true", - // args: [ - // new ValueInput("CHANCE", BlockType.Number) - // ], - // placeholders: [ - // new Placeholder(PlaceholderType.Block, "CHANCE", "number", {NUMBER: 50}) - // ], - // shape: BlockShape.Floating, - // output: BlockType.Boolean, - // inline: true, - // colour: "#5b67a5", - // tooltip: "Chances a number between two numbers.", - // helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", - // code: (args) => { - // return `Math.random() * 100 < ${args.CHANCE}` - // } - - // } + case "inverse": + return `${args.NUMBER}) * -1`; + case "log10": + return `Math.log(${args.NUMBER}) / Math.log(10)`; + case "sin": + case "cos": + case "tan": + case "asin": + case "acos": + case "atan": + return `(Math.(${args.OPERATION}) / Math.PI) * 180`; + default: + return `Math.${args.OPERATION}(${args.NUMBER})`; + } + } + }, + { + id: "constants", + text: "{CONSTANT}", + args: [ + new Dropdown("CONSTANT", DropdownType.Auto, { + π: "Math.PI", + e: "Math.E", + ϕ: "(1 + Math.sqrt(5)) / 2", + "√(2)": "Math.SQRT2", + "√(½)": "Math.Math.SQRT1_2", + "∞": "Infinity", + NaN: "NaN" + }) + ], + shape: BlockShape.Floating, + output: BlockType.Number, + inline: true, + colour: "#5b67a5", + tooltip: "Allows you to use constants.", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", + code: (args) => { + return `${args.CONSTANT}`; + } + }, + { + id: "is", + text: "{NUMBER} is {VALUE}", + args: [ + new ValueInput("NUMBER", BlockType.Number), + new Dropdown("VALUE", DropdownType.Auto, { + number: "number", + even: "even", + odd: "odd", + prime: "prime", + whole: "whole", + positive: "positive", + negative: "negative", + "divisible by": "divisible" + }) + ], + placeholders: [new Placeholder(PlaceholderType.Block, "NUMBER", "number", { NUMBER: 1 })], + shape: BlockShape.Floating, + output: BlockType.Boolean, + inline: true, + colour: "#5b67a5", + tooltip: "Checks if a number is even, odd, prime, whole, positive, negative, or div", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", + code: (args) => { + switch (`${args.VALUE}`) { + case "number": + return `typeof ${args.NUMBER} === "number" && ${args.NUMBER} % 1 === 0`; + case "even": + return `${args.NUMBER} % 2 === 0`; + case "odd": + return `${args.NUMBER} % 2!== 0`; + case "prime": + return `isPrime(${args.NUMBER})`; /* function isPrime(number) {if (number < 2) {return false;};for (let i = 2; i <= Math.sqrt(number); i++) {if (number % i === 0) {return false;}}return true;} */ + case "whole": + return `${args.NUMBER} % 1 === 0`; + case "positive": + return `${args.NUMBER} > 0`; + case "negative": + return `${args.NUMBER} < 0`; + default: + return `${args.NUMBER} % ${args.VALUE} === 0`; // fix when added mutator + } + } + }, + { + id: "array_math", + text: "{OPERATION} of list {ARRAY}", + args: [ + new Dropdown("OPERATION", DropdownType.Auto, { + sum: "sum", + min: "min", + max: "max", + average: "average", + median: "median", + mode: "mode", + range: "range", + random: "random", + "standard deviation": "standard deviation" + }), + new ValueInput("ARRAY", BlockType.Array) + ], + // placeholders: [ + // new Placeholder(PlaceholderType.Block, "ARRAY", "array", {ARRAY: [1, 2, 3]}) + // ], + shape: BlockShape.Floating, + output: BlockType.Number, + inline: true, + colour: "#5b67a5", + tooltip: "Allows you to use math with arrays.", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", + code: (args) => { + switch (args.OPERATION) { + case "sum": + return `${args.ARRAY}.reduce((a, b) => a + b)`; + case "min": + return `${args.ARRAY}.reduce((a, b) => Math.min(a, b))`; + case "max": + return `${args.ARRAY}.reduce((a, b) => Math.max(a, b))`; + case "average": + return `${args.ARRAY}.reduce((a, b) => a + b) / ${args.ARRAY}.length`; + case "median": + return `${args.ARRAY}.sort((a, b) => a - b).length % 2? ${args.ARRAY}.sort((a, b) => a - b)[Math.floor(${args.ARRAY}.length / 2)] : ((${args.ARRAY}.sort((a, b) => a - b)[Math.floor(${args.ARRAY}.length / 2)] + ${args.ARRAY}.sort((a, b) => a - b - 1)[Math.floor(${args.ARRAY}.length / 2)]) / 2 ))`; + case "mode": + return `${args.ARRAY}.sort((a, b) => a - b).length % 2`; + case "range": + return `${args.ARRAY}.reduce((a, b) => Math.max(a, b) - Math.min(a, b))`; + case "random": + return `Math.floor(Math.random() * ${args.ARRAY}.length)`; + case "standard deviation": + return `Math.sqrt(${args.ARRAY}.reduce((a, b) => Math.pow(a - b, 2)) / ${args.ARRAY}.length)`; + default: + return `Math.${args.OPERATION}(${args.ARRAY})`; + } + } + }, + { + id: "random_int", + text: "random integer between {MIN} to {MAX}", + args: [new ValueInput("MIN", BlockType.Number), new ValueInput("MAX", BlockType.Number)], + placeholders: [ + new Placeholder(PlaceholderType.Block, "MIN", "number", { NUMBER: 1 }), + new Placeholder(PlaceholderType.Block, "MAX", "number", { NUMBER: 10 }) + ], + shape: BlockShape.Floating, + output: BlockType.Number, + inline: true, + colour: "#5b67a5", + tooltip: "Gets a random integer between two numbers.", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", + code: (args) => { + return `Math.floor(Math.random() * (${args.MAX} - ${args.MIN}) + ${args.MIN})`; + } + }, + { + id: "random_fraction", + text: "random fraction", + args: [], + shape: BlockShape.Floating, + output: BlockType.Number, + inline: true, + colour: "#5b67a5", + tooltip: "Gets a random fraction.", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", + code: () => { + return "Math.random()"; + } + }, + { + id: "toNumber", + text: "convert text {TEXT} to number", + args: [new ValueInput("TEXT", BlockType.String)], + placeholders: [new Placeholder(PlaceholderType.Block, "TEXT", "text", { TEXT: "123" })], + shape: BlockShape.Floating, + output: BlockType.Number, + inline: true, + colour: "#5b67a5", + tooltip: "Converts text to a number.", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", + code: (args) => { + return `parseInt(${args.TEXT})`; + } + }, + { + id: "constrain {VALUE} between {MIN} and {MAX}", + text: "constrain {VALUE} between {MIN} and {MAX}", + args: [ + new ValueInput("VALUE", BlockType.Number), + new ValueInput("MIN", BlockType.Number), + new ValueInput("MAX", BlockType.Number) + ], + placeholders: [ + new Placeholder(PlaceholderType.Block, "VALUE", "number", { NUMBER: 50 }), + new Placeholder(PlaceholderType.Block, "MIN", "number", { NUMBER: 1 }), + new Placeholder(PlaceholderType.Block, "MAX", "number", { NUMBER: 100 }) + ], + shape: BlockShape.Floating, + output: BlockType.Number, + inline: true, + colour: "#5b67a5", + tooltip: "Constrains a number between two numbers.", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", + code: (args) => { + return `Math.min(Math.max(${args.VALUE}, ${args.MIN}), ${args.MAX})`; + } + } + // { + // id: "chance {CHANCE} %", + // text: "{CHANCE} % chance of true", + // args: [ + // new ValueInput("CHANCE", BlockType.Number) + // ], + // placeholders: [ + // new Placeholder(PlaceholderType.Block, "CHANCE", "number", {NUMBER: 50}) + // ], + // shape: BlockShape.Floating, + // output: BlockType.Boolean, + // inline: true, + // colour: "#5b67a5", + // tooltip: "Chances a number between two numbers.", + // helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", + // code: (args) => { + // return `Math.random() * 100 < ${args.CHANCE}` + // } + // } ]; const category: CategoryDefinition = { - name: "Math", - colour: "#5b67a5" + name: "Math", + colour: "#5b67a5" }; -export default {blocks, category}; +export default { blocks, category }; diff --git a/src/lib/blocks/Javascript/text.ts b/src/lib/blocks/Javascript/text.ts index 980a019..18ea2fc 100644 --- a/src/lib/blocks/Javascript/text.ts +++ b/src/lib/blocks/Javascript/text.ts @@ -8,7 +8,6 @@ import StatementInput from "$lib/utils/BlockGen/Inputs/StatementInput"; import Dropdown from "$lib/utils/BlockGen/Inputs/Dropdown"; import AssemblerMutatorV2 from "$lib/utils/BlockGen/Mutators/AssemblerMutatorV2"; - const blocks: BlockDefinition[] = [ { id: "text", @@ -26,147 +25,144 @@ const blocks: BlockDefinition[] = [ } }, { - id: "create_text_with_x", - text: "create text with {CONTENT}", - args: [ - new ValueInput("CONTENT", BlockType.String), - ], - shape: BlockShape.Floating, + id: "create_text_with_x", + text: "create text with {CONTENT}", + args: [new ValueInput("CONTENT", BlockType.String)], + shape: BlockShape.Floating, output: BlockType.String, - inline: true, - colour: "%{BKY_TEXTS_HUE}", - tooltip: "Creates text with dynamic content", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", - code: (args) => { - return `new Text("${args.CONTENT}")`; - }, - mutator: new AssemblerMutatorV2("Add Content", [ - { - block: "text_content", - adds: [new ValueInput("text_content", BlockType.String)], - once: true - } - ]) - }, - { - id: "text_content", - text: "text {TEXT_CONTENT}", - args: [ - new ValueInput("TEXT_CONTENT", BlockType.String) - ], - shape: BlockShape.Action, - inline: true, - colour: "%{BKY_TEXTS_HUE}", - tooltip: "Text content for creating text with x", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", - code: (args) => { - return args.TEXT_CONTENT; - }, + inline: true, + colour: "%{BKY_TEXTS_HUE}", + tooltip: "Creates text with dynamic content", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + code: (args) => { + return `new Text("${args.CONTENT}")`; + }, + mutator: new AssemblerMutatorV2("Add Content", [ + { + block: "text_content", + adds: [new ValueInput("text_content", BlockType.String)], + once: true + } + ]) + }, + { + id: "text_content", + text: "text {TEXT_CONTENT}", + args: [new ValueInput("TEXT_CONTENT", BlockType.String)], + shape: BlockShape.Action, + inline: true, + colour: "%{BKY_TEXTS_HUE}", + tooltip: "Text content for creating text with x", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + code: (args) => { + return `${args.TEXT_CONTENT}`; + }, hidden: true - }, + }, { - id: "text_count", - text: "count {INPUT} in {TEXT}", - args: [ - new ValueInput("INPUT", BlockType.String), - new ValueInput("TEXT", BlockType.String) - ], + id: "text_count", + text: "count {INPUT} in {TEXT}", + args: [new ValueInput("INPUT", BlockType.String), new ValueInput("TEXT", BlockType.String)], placeholders: [ - new Placeholder(PlaceholderType.Block, "INPUT", "text", {TEXT: "o"}), - new Placeholder(PlaceholderType.Block, "TEXT", "text", {INPUT: "Hello World"}) + new Placeholder(PlaceholderType.Block, "INPUT", "text", { TEXT: "o" }), + new Placeholder(PlaceholderType.Block, "TEXT", "text", { INPUT: "Hello World" }) ], - shape: BlockShape.Floating, - output: BlockType.Number, - inline: true, - colour: "%{BKY_TEXTS_HUE}", - tooltip: "Counts the occurrences of a substring in a text.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", - code: (args) => { - return `String(${args.TEXT}).split(${args.INPUT}).length - 1`; - } - }, + shape: BlockShape.Floating, + output: BlockType.Number, + inline: true, + colour: "%{BKY_TEXTS_HUE}", + tooltip: "Counts the occurrences of a substring in a text.", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + code: (args) => { + return `String(${args.TEXT}).split(${args.INPUT}).length - 1`; + } + }, { - id: "text_trim", - text: "trim spaces from {SIDE} of {TEXT}", - args: [ - new Dropdown("SIDE", DropdownType.Auto, { - "both sides": "trim", - "left side": "trimLeft", - "right side": "trimRight" - }), - new ValueInput("TEXT", BlockType.String), - ], + id: "text_trim", + text: "trim spaces from {SIDE} of {TEXT}", + args: [ + new Dropdown("SIDE", DropdownType.Auto, { + "both sides": "trim", + "left side": "trimLeft", + "right side": "trimRight" + }), + new ValueInput("TEXT", BlockType.String) + ], placeholders: [ - new Placeholder(PlaceholderType.Block, "TEXT", "text", {SIDE: " Hello World "}) - ], - shape: BlockShape.Floating, - output: BlockType.String, - inline: true, - colour: "%{BKY_TEXTS_HUE}", - tooltip: "Removes leading and trailing whitespace from a string.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim", - code: (args) => { - return `String(${args.TEXT}).${args.SIDE}()`; - } - }, + new Placeholder(PlaceholderType.Block, "TEXT", "text", { SIDE: " Hello World " }) + ], + shape: BlockShape.Floating, + output: BlockType.String, + inline: true, + colour: "%{BKY_TEXTS_HUE}", + tooltip: "Removes leading and trailing whitespace from a string.", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim", + code: (args) => { + return `String(${args.TEXT}).${args.SIDE}()`; + } + }, { - id: "text_case", - text: "tp {CASE} case of {TEXT}", - args: [ - new Dropdown("CASE", DropdownType.Auto, { - "upper": "toUpperCase", - "lower": "toLowerCase", - "title": "toTitleCase" - }), - new ValueInput("TEXT", BlockType.String), - ], - placeholders: [ - new Placeholder(PlaceholderType.Block, "TEXT", "text", {CASE: "abc"}) - ], - shape: BlockShape.Floating, - output: BlockType.String, - inline: true, - colour: "%{BKY_TEXTS_HUE}", - tooltip: "Converts the case of text.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", - code: (args) => { - if(args.CASE === 'toTitleCase') { - return `String(${args.TEXT}).replace(/\\w\\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();})`; - } - return `String(${args.TEXT}).${args.CASE}()`; - } - }, + id: "text_case", + text: "tp {CASE} case of {TEXT}", + args: [ + new Dropdown("CASE", DropdownType.Auto, { + upper: "toUpperCase", + lower: "toLowerCase", + title: "toTitleCase" + }), + new ValueInput("TEXT", BlockType.String) + ], + placeholders: [new Placeholder(PlaceholderType.Block, "TEXT", "text", { CASE: "abc" })], + shape: BlockShape.Floating, + output: BlockType.String, + inline: true, + colour: "%{BKY_TEXTS_HUE}", + tooltip: "Converts the case of text.", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + code: (args) => { + if (args.CASE === "toTitleCase") { + return `String(${args.TEXT}).replace(/\\w\\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();})`; + } + return `String(${args.TEXT}).${args.CASE}()`; + } + }, { id: "text_substring", text: "in text {TEXT} get substring from {FROM} {INPUT1} to {TO} {INPUT2}", args: [ new ValueInput("TEXT", BlockType.String), new Dropdown("FROM", DropdownType.Auto, { - "letter": "charAt", + letter: "charAt", "first letter": "start", "last letter": "charEndAt", "from end": "end" }), new ValueInput("INPUT1", BlockType.Number), new Dropdown("TO", DropdownType.Auto, { - "letter": "charAt", - "last": "last", + letter: "charAt", + last: "last", "from start letter": "substring", "x from end": "slice" }), new ValueInput("INPUT2", BlockType.Number) ], placeholders: [ - new Placeholder(PlaceholderType.Block, "TEXT", "text", {TEXT: "hey"}), - new Placeholder(PlaceholderType.Block, "INPUT1", "number", {NUMBER: 1}), - new Placeholder(PlaceholderType.Block, "INPUT2", "number", {NUMBER: 2}), - ], + new Placeholder(PlaceholderType.Block, "TEXT", "text", { TEXT: "hey" }), + new Placeholder(PlaceholderType.Block, "INPUT1", "number", { NUMBER: 1 }), + new Placeholder(PlaceholderType.Block, "INPUT2", "number", { NUMBER: 2 }) + ], shape: BlockShape.Floating, output: BlockType.String, inline: true, colour: "%{BKY_TEXTS_HUE}", tooltip: "Gets a substring from a text.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", code: (args) => { return `String(${args.TEXT}).${args.FROM}(${args.INPUT1}, ${args.INPUT2})`; // No idea how to make this } @@ -177,39 +173,40 @@ const blocks: BlockDefinition[] = [ args: [ new ValueInput("TEXT", BlockType.String), new Dropdown("LETTER", DropdownType.Auto, { - "letter": "charAt", + letter: "charAt", "letter from end": "chatEndAt", - "first": "charStart", - "last": "charEnd", - "random": "random" + first: "charStart", + last: "charEnd", + random: "random" }), new ValueInput("INPUT", BlockType.Number) ], placeholders: [ - new Placeholder(PlaceholderType.Block, "TEXT", "text", {TEXT: "hey"}), - new Placeholder(PlaceholderType.Block, "INPUT", "number", {NUMBER: 1}), - ], + new Placeholder(PlaceholderType.Block, "TEXT", "text", { TEXT: "hey" }), + new Placeholder(PlaceholderType.Block, "INPUT", "number", { NUMBER: 1 }) + ], shape: BlockShape.Floating, output: BlockType.String, inline: true, colour: "%{BKY_TEXTS_HUE}", tooltip: "Gets a specific letter from a text.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", code: (args) => { const text = `String(${args.TEXT})`; switch (args.LETTER) { - case 'charAt': - return text + `.charAt(${args.INPUT})`; - case 'chatEndAt': - return text + `.slice(-${args.INPUT}).charAt(0)`; - case 'charStart': - return text + `.charAt(0)`; - case 'charEnd': - return text + `.slice(-1)`; - case 'random': - return text + `.charAt(Math.floor(Math.random() * ${args.INPUT}))`; - default: - return ''; + case "charAt": + return `${text}.charAt(${args.INPUT})`; + case "chatEndAt": + return `${text}.slice(-${args.INPUT}).charAt(0)`; + case "charStart": + return `${text}.charAt(0)`; + case "charEnd": + return `${text}.slice(-1)`; + case "random": + return `${text}.charAt(Math.floor(Math.random() * ${args.INPUT}))`; + default: + return ""; } } }, @@ -219,21 +216,22 @@ const blocks: BlockDefinition[] = [ args: [ new ValueInput("TEXT", BlockType.String), new Dropdown("FIRST_LAST", DropdownType.Auto, { - "first": "indexOf", - "last": "lastIndexOf" + first: "indexOf", + last: "lastIndexOf" }), new ValueInput("ITEM", BlockType.String) ], placeholders: [ - new Placeholder(PlaceholderType.Block, "TEXT", "text", {TEXT: "hey hey"}), - new Placeholder(PlaceholderType.Block, "ITEM", "text", {TEXT: "hey"}) - ], + new Placeholder(PlaceholderType.Block, "TEXT", "text", { TEXT: "hey hey" }), + new Placeholder(PlaceholderType.Block, "ITEM", "text", { TEXT: "hey" }) + ], shape: BlockShape.Floating, output: BlockType.Number, inline: true, colour: "%{BKY_TEXTS_HUE}", tooltip: "Finds the first or last occurrence of an item in a text.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", code: (args) => { const text = `String(${args.TEXT})`; return `${text}.${args.FIRST_LAST}(${args.ITEM})`; @@ -242,18 +240,15 @@ const blocks: BlockDefinition[] = [ { id: "text_reverse", text: "reverse text {TEXT}", - args: [ - new ValueInput("TEXT", BlockType.String) - ], - placeholders: [ - new Placeholder(PlaceholderType.Block, "TEXT", "text", {TEXT: "abc"}) - ], + args: [new ValueInput("TEXT", BlockType.String)], + placeholders: [new Placeholder(PlaceholderType.Block, "TEXT", "text", { TEXT: "abc" })], shape: BlockShape.Floating, output: BlockType.String, inline: true, colour: "%{BKY_TEXTS_HUE}", tooltip: "Reverses the given text.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", code: (args) => { return `String(${args.TEXT}).split('').reverse().join('')`; } @@ -261,18 +256,15 @@ const blocks: BlockDefinition[] = [ { id: "text_is_empty", text: "text {TEXT} is empty?", - args: [ - new ValueInput("TEXT", BlockType.String) - ], - placeholders: [ - new Placeholder(PlaceholderType.Block, "TEXT", "text", {TEXT: ""}) - ], + args: [new ValueInput("TEXT", BlockType.String)], + placeholders: [new Placeholder(PlaceholderType.Block, "TEXT", "text", { TEXT: "" })], shape: BlockShape.Floating, output: BlockType.Boolean, inline: true, colour: "%{BKY_TEXTS_HUE}", tooltip: "Checks if the given text is empty.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", code: (args) => { return `String(${args.TEXT}).length === 0`; } @@ -286,158 +278,155 @@ const blocks: BlockDefinition[] = [ new ValueInput("TEXT", BlockType.String) ], placeholders: [ - new Placeholder(PlaceholderType.Block, "INPUT", "text", {TEXT: "Hello"}), - new Placeholder(PlaceholderType.Block, "REPLACE", "text", {TEXT: "Bye"}), - new Placeholder(PlaceholderType.Block, "TEXT", "text", {TEXT: "Hello World"}) - ], - shape: BlockShape.Floating, + new Placeholder(PlaceholderType.Block, "INPUT", "text", { TEXT: "Hello" }), + new Placeholder(PlaceholderType.Block, "REPLACE", "text", { TEXT: "Bye" }), + new Placeholder(PlaceholderType.Block, "TEXT", "text", { TEXT: "Hello World" }) + ], + shape: BlockShape.Floating, output: BlockType.String, inline: true, colour: "%{BKY_TEXTS_HUE}", tooltip: "Replaces occurrences of input with replace in the given text.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", code: (args) => { return `String(${args.TEXT}).replace(new RegExp(${args.INPUT}, 'g'), ${args.REPLACE})`; } }, { - id: "text_length", - text: "length of {TEXT}", - args: [ - new ValueInput("TEXT", BlockType.String) - ], - placeholders: [ - new Placeholder(PlaceholderType.Block, "TEXT", "text", {TEXT: "Hello World"}) - ], - shape: BlockShape.Floating, - output: BlockType.Number, - inline: true, - colour: "%{BKY_TEXTS_HUE}", - tooltip: "Gets the length of a text.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length", - code: (args) => { - return `String(${args.TEXT}).length`; - } - }, - { - id: "text_starts_ends", - text: "{TEXT} {OPTION} {OTHERTEXT}", - args: [ - new ValueInput("TEXT", BlockType.String), - new Dropdown("OPTION", DropdownType.Auto, { - "starts with": "startsWith", - "ends with": "endsWith", - "includes": "includes", - }), - new ValueInput("OTHERTEXT", BlockType.String), - ], - placeholders: [ - new Placeholder(PlaceholderType.Block, "TEXT", "text", {TEXT: "abcdefg"}), - new Placeholder(PlaceholderType.Block, "OTHERTEXT", "text", {TEXT: "abc"}) + id: "text_length", + text: "length of {TEXT}", + args: [new ValueInput("TEXT", BlockType.String)], + placeholders: [new Placeholder(PlaceholderType.Block, "TEXT", "text", { TEXT: "Hello World" })], + shape: BlockShape.Floating, + output: BlockType.Number, + inline: true, + colour: "%{BKY_TEXTS_HUE}", + tooltip: "Gets the length of a text.", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length", + code: (args) => { + return `String(${args.TEXT}).length`; + } + }, + { + id: "text_starts_ends", + text: "{TEXT} {OPTION} {OTHERTEXT}", + args: [ + new ValueInput("TEXT", BlockType.String), + new Dropdown("OPTION", DropdownType.Auto, { + "starts with": "startsWith", + "ends with": "endsWith", + includes: "includes" + }), + new ValueInput("OTHERTEXT", BlockType.String) ], - shape: BlockShape.Floating, - output: BlockType.Boolean, - inline: true, - colour: "%{BKY_TEXTS_HUE}", - tooltip: "Checks if text starts, ends, or includes another text.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", - code: (args) => { - return `String(${args.TEXT}).${args.OPTION}(${args.OTHERTEXT})`; - } - }, - { - id: "text_newline", - text: "new line", - output: BlockType.String, - shape: BlockShape.Floating, - inline: true, - colour: "%{BKY_TEXTS_HUE}", - tooltip: "Represents a new line character.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", - code: () => { - return `\\n`; - } - }, - { - id: "text_contains_number", - text: "{TEXT} contains numbers ?", - args: [ - new ValueInput("TEXT", BlockType.String) - ], placeholders: [ - new Placeholder(PlaceholderType.Block, "TEXT", "text", {TEXT: "abc123"}) - ], - shape: BlockShape.Floating, - output: BlockType.Boolean, - inline: true, - colour: "%{BKY_TEXTS_HUE}", - tooltip: "Checks if text contains any numbers.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", - code: (args) => { - return `String(${args.TEXT}).match(/\\d+/g) !== null`; - } - }, - { - id: "text_for_each", - text: "for each {SELECT} in {TEXT} \n {INPUT}", - args: [ - new Dropdown("SELECT", DropdownType.Auto, { - "character": "char", - "word": "word" - }), - new ValueInput("TEXT", BlockType.String), + new Placeholder(PlaceholderType.Block, "TEXT", "text", { TEXT: "abcdefg" }), + new Placeholder(PlaceholderType.Block, "OTHERTEXT", "text", { TEXT: "abc" }) + ], + shape: BlockShape.Floating, + output: BlockType.Boolean, + inline: true, + colour: "%{BKY_TEXTS_HUE}", + tooltip: "Checks if text starts, ends, or includes another text.", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + code: (args) => { + return `String(${args.TEXT}).${args.OPTION}(${args.OTHERTEXT})`; + } + }, + { + id: "text_newline", + text: "new line", + output: BlockType.String, + shape: BlockShape.Floating, + inline: true, + colour: "%{BKY_TEXTS_HUE}", + tooltip: "Represents a new line character.", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + code: () => { + return "\\n"; + } + }, + { + id: "text_contains_number", + text: "{TEXT} contains numbers ?", + args: [new ValueInput("TEXT", BlockType.String)], + placeholders: [new Placeholder(PlaceholderType.Block, "TEXT", "text", { TEXT: "abc123" })], + shape: BlockShape.Floating, + output: BlockType.Boolean, + inline: true, + colour: "%{BKY_TEXTS_HUE}", + tooltip: "Checks if text contains any numbers.", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + code: (args) => { + return `String(${args.TEXT}).match(/\\d+/g) !== null`; + } + }, + { + id: "text_for_each", + text: "for each {SELECT} in {TEXT} \n {INPUT}", + args: [ + new Dropdown("SELECT", DropdownType.Auto, { + character: "char", + word: "word" + }), + new ValueInput("TEXT", BlockType.String), new StatementInput("INPUT") - ], - placeholders: [ - new Placeholder(PlaceholderType.Block, "TEXT", "text", {TEXT: "abc"}) - ], - shape: BlockShape.Action, - inline: true, - colour: "%{BKY_TEXTS_HUE}", - tooltip: "Iterates through each character or word in the text.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", - code: (args) => { - switch (args.SELECT) { - case 'char': - return `for (let char_i = 0; char_i < String(${args.TEXT}).length; char_i++){\nlet char_i_char = String(${args.TEXT})[char_i] ${args.INPUT}}`; - case 'word': - return `for (let word_i = 0; word_i < String(${args.TEXT}).split(' ').length; word_i++){\nlet word_i_word = String(${args.TEXT}).split(' ')[word_i] ${args.INPUT}}`; - default: - return ''; - } - } - }, - { - id: "text_character", - text: "{SELECT}", - args: [ - new Dropdown("SELECT", DropdownType.Auto, { - "character": "char", - "word": "word" - }) - ], - shape: BlockShape.Floating, - output: BlockType.String, - inline: true, - colour: "%{BKY_TEXTS_HUE}", - tooltip: "Outputs the selected character or word.", - helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", - code: (args) => { - switch (args.SELECT) { - case 'char': - return `char_i_char`; - case 'word': - return `word_i_word`; - default: - return ''; - } - } - } + ], + placeholders: [new Placeholder(PlaceholderType.Block, "TEXT", "text", { TEXT: "abc" })], + shape: BlockShape.Action, + inline: true, + colour: "%{BKY_TEXTS_HUE}", + tooltip: "Iterates through each character or word in the text.", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + code: (args) => { + switch (args.SELECT) { + case "char": + return `for (let char_i = 0; char_i < String(${args.TEXT}).length; char_i++){\nlet char_i_char = String(${args.TEXT})[char_i] ${args.INPUT}}`; + case "word": + return `for (let word_i = 0; word_i < String(${args.TEXT}).split(' ').length; word_i++){\nlet word_i_word = String(${args.TEXT}).split(' ')[word_i] ${args.INPUT}}`; + default: + return ""; + } + } + }, + { + id: "text_character", + text: "{SELECT}", + args: [ + new Dropdown("SELECT", DropdownType.Auto, { + character: "char", + word: "word" + }) + ], + shape: BlockShape.Floating, + output: BlockType.String, + inline: true, + colour: "%{BKY_TEXTS_HUE}", + tooltip: "Outputs the selected character or word.", + helpUrl: + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + code: (args) => { + switch (args.SELECT) { + case "char": + return "char_i_char"; + case "word": + return "word_i_word"; + default: + return ""; + } + } + } ]; const category: CategoryDefinition = { - name: "Text", - colour: "#5ba58c" -} + name: "Text", + colour: "#5ba58c" +}; -export default {blocks, category}; +export default { blocks, category }; diff --git a/src/lib/blocks/Test Blocks/mutators.ts b/src/lib/blocks/Test Blocks/mutators.ts index 2abb6f2..cd827ad 100644 --- a/src/lib/blocks/Test Blocks/mutators.ts +++ b/src/lib/blocks/Test Blocks/mutators.ts @@ -84,7 +84,6 @@ const blocks: BlockDefinition[] = [ // }, { - id: "checkbox_mutator", text: "checkbox mutator\n", shape: BlockShape.Action, @@ -92,28 +91,34 @@ const blocks: BlockDefinition[] = [ colour: rgbToHex(91, 128, 165), tooltip: "Returns the opposite of the input", helpUrl: - `https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_NOT`, + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_NOT", code: (args) => { - return "${args}"; + return `${args}`; }, - mutator: new CheckboxMutator("hello", [ - { - text: "input 1", - inputName: "if_test", - adds: [new ValueInput("if_input", BlockType.Boolean).setField("else if"), new StatementInput("if_statement").setField("do")], - defaultValue: true, - }, + mutator: new CheckboxMutator( + "hello", + [ + { + text: "input 1", + inputName: "if_test", + adds: [ + new ValueInput("if_input", BlockType.Boolean).setField("else if"), + new StatementInput("if_statement").setField("do") + ], + defaultValue: true + }, + { + text: "input 2", + inputName: "else_test", + adds: [new StatementInput("else_input").setField("else")], + defaultValue: false + } + ], { - text: "input 2", - inputName: "else_test", - adds: [new StatementInput("else_input").setField("else")], - defaultValue: false, - + color: rgbToHex(91, 128, 165) } - ], { - color: rgbToHex(91, 128, 165) - }) - }, + ) + } ]; const category: CategoryDefinition = { diff --git a/src/lib/components/Workspace.svelte b/src/lib/components/Workspace.svelte index 4d1f073..f9d015b 100644 --- a/src/lib/components/Workspace.svelte +++ b/src/lib/components/Workspace.svelte @@ -33,8 +33,8 @@ function updateCode(event: Abstract) { workspace.getAllBlocks(true).forEach((block) => { - if (block.type === "is_equal") console.log(block) - }) + if (block.type === "is_equal") console.log(block); + }); if (workspace.isDragging()) return; // Don't update while changes are happening. if (!supportedEvents.has(event.type)) return; diff --git a/src/lib/enums/BlockTypes.ts b/src/lib/enums/BlockTypes.ts index 9f3f2de..40e31b1 100644 --- a/src/lib/enums/BlockTypes.ts +++ b/src/lib/enums/BlockTypes.ts @@ -33,5 +33,5 @@ export enum PlaceholderType { } export enum MutatorType { Assembler = "assembler", - Checkbox = "checkbox", + Checkbox = "checkbox" } diff --git a/src/lib/types/BlockDefinition.ts b/src/lib/types/BlockDefinition.ts index 53f9eeb..3215032 100644 --- a/src/lib/types/BlockDefinition.ts +++ b/src/lib/types/BlockDefinition.ts @@ -1,7 +1,7 @@ import type { BlockShape, BlockType } from "$lib/enums/BlockTypes"; import type Block from "$lib/utils/BlockGen/Blocks/Block"; import type BaseInput from "$lib/utils/BlockGen/Inputs/BaseInput"; -import type {Mutator} from "$lib/utils/BlockGen/Mutators/Mutator"; +import type { Mutator } from "$lib/utils/BlockGen/Mutators/Mutator"; import type Warning from "$lib/utils/BlockGen/Warnings/Warning"; import type Placeholder from "$lib/utils/ToolboxGen/Placeholder"; @@ -32,7 +32,7 @@ export type BlockDefinition = text: string; }; -export interface MutatorBlock { +export interface MutatorBlock { // What inputs it adds to the block adds: Argument[]; } @@ -44,8 +44,8 @@ export interface CheckBoxMutatorBlock extends MutatorBlock { */ defaultValue?: boolean; /** - * Text that appears in containerBlock in mutator menu - */ + * Text that appears in containerBlock in mutator menu + */ text: string; /** * name for input in container block @@ -54,7 +54,7 @@ export interface CheckBoxMutatorBlock extends MutatorBlock { } export interface AssemblerMutator extends MutatorBlock { // Name of the block that appears in the block list in the UI - block: string + block: string; // Can it only be added once in the UI once: boolean; } diff --git a/src/lib/types/DiscodesInput.ts b/src/lib/types/DiscodesInput.ts index d64bad8..688d19d 100644 --- a/src/lib/types/DiscodesInput.ts +++ b/src/lib/types/DiscodesInput.ts @@ -6,4 +6,6 @@ import type { StatementIDef } from "$lib/utils/BlockGen/Inputs/StatementInput"; import type { TextIDef } from "$lib/utils/BlockGen/Inputs/TextInput"; import type { ValueIDef } from "$lib/utils/BlockGen/Inputs/ValueInput"; -export type DiscodesInput = BaseInput; +export type DiscodesInput = BaseInput< + DropdownIDef | ImageIDef | NumberIDef | StatementIDef | TextIDef | ValueIDef +>; diff --git a/src/lib/utils/BlockGen/Blocks/Block.ts b/src/lib/utils/BlockGen/Blocks/Block.ts index 8427212..5bc1b45 100644 --- a/src/lib/utils/BlockGen/Blocks/Block.ts +++ b/src/lib/utils/BlockGen/Blocks/Block.ts @@ -11,36 +11,39 @@ import type { CheckBoxMutatorBlock, MutatorBlock } from "$lib/types/BlockDefinition"; -import { BlockShape, BlockType, DropdownType, MutatorType, WarningType } from "$lib/enums/BlockTypes"; +import { + BlockShape, + BlockType, + DropdownType, + MutatorType, + WarningType +} from "$lib/enums/BlockTypes"; import type { Abstract } from "blockly/core/events/events_abstract"; import type { DiscodesInput } from "$lib/types/DiscodesInput"; import type Warning from "../Warnings/Warning"; - // Warnings -import {addWarning, removeWarning, warnings as warningsObj} from "../Warnings/WarningsList"; -import {EventsToTriggerWarnings} from "$lib/constants/warnings"; +import { addWarning, removeWarning, warnings as warningsObj } from "../Warnings/WarningsList"; +import { EventsToTriggerWarnings } from "$lib/constants/warnings"; // Helpers -import {dev} from "$app/environment"; +import { dev } from "$app/environment"; import salt from "$lib/utils/helpers/salt"; -import {getInputValue} from "$lib/utils/helpers/getInputValue"; - - +import { getInputValue } from "$lib/utils/helpers/getInputValue"; import { addImport } from "$lib/utils/BlockGen/Blocks/importsList"; interface BlocklyBlockDefinition { - type: string - colour: string - tooltip: string - helpUrl: string - inputsInline: boolean - args0: Record[] - message0: string - mutator:string | undefined -}; + type: string; + colour: string; + tooltip: string; + helpUrl: string; + inputsInline: boolean; + args0: Record[]; + message0: string; + mutator: string | undefined; +} const { javascriptGenerator, Order } = pkg; @@ -64,13 +67,22 @@ export default class Block { public addWarning(warning: Warning): void { if (this._blockDefinition.label) throw new Error("Cannot add a warning to a label"); if (warningsObj[this._block.id] && warningsObj[this._block.id][warning.data.fieldName]) return; - this._blockDefinition.warnings = this._blockDefinition.warnings ? [...this._blockDefinition.warnings, warning] : [warning]; + this._blockDefinition.warnings = this._blockDefinition.warnings + ? [...this._blockDefinition.warnings, warning] + : [warning]; } public removeWarning(fieldName: string): void { if (this._blockDefinition.label) throw new Error("Cannot remove a warning form a label"); - if ((!warningsObj[this._block.id] || !warningsObj[this._block.id][fieldName]) && this._blockDefinition.warnings !== undefined) return; - this._blockDefinition.warnings = this._blockDefinition.warnings?.filter(warning => warning.data.fieldName !== fieldName); + if ( + (!warningsObj[this._block.id] || !warningsObj[this._block.id][fieldName]) && + this._blockDefinition.warnings !== undefined + ) { + return; + } + this._blockDefinition.warnings = this._blockDefinition.warnings?.filter( + (warning) => warning.data.fieldName !== fieldName + ); } public addText(text: string, fieldName: string): void { @@ -86,44 +98,73 @@ export default class Block { if (!this._block || this._block.getInput(generated.name) || this._block.isInFlyout) return; let isDummy: boolean = true; - switch(generated.type) { + switch (generated.type) { case DropdownType.Grid: - this._block.appendDummyInput(generated.name) - .appendField(new gridDropdown.FieldGridDropdown(generated.options as Blockly.MenuGenerator) as Blockly.Field); + this._block + .appendDummyInput(generated.name) + .appendField( + new gridDropdown.FieldGridDropdown( + generated.options as Blockly.MenuGenerator + ) as Blockly.Field + ); break; case DropdownType.List: - this._block.appendDummyInput(generated.name) - .appendField(new Blockly.FieldDropdown(generated.options as Blockly.MenuGenerator) as Blockly.Field); + this._block + .appendDummyInput(generated.name) + .appendField( + new Blockly.FieldDropdown(generated.options as Blockly.MenuGenerator) as Blockly.Field< + string | undefined + > + ); break; - + case "input_value": - this._block.appendValueInput(generated.name) - .setCheck(generated.check as string | string[] | undefined ? generated.check as string | string[]: null); + this._block + .appendValueInput(generated.name) + .setCheck( + (generated.check as string | string[] | undefined) + ? (generated.check as string | string[]) + : null + ); isDummy = false; break; - + case "input_statement": this._block.appendStatementInput(generated.name); isDummy = false; break; case "field_number": - this._block.appendDummyInput(generated.name) - .appendField(new Blockly.FieldNumber(generated.value, generated.min, generated.max, generated.precision)); + this._block + .appendDummyInput(generated.name) + .appendField( + new Blockly.FieldNumber( + generated.value, + generated.min, + generated.max, + generated.precision + ) + ); break; case "field_image": - this._block.appendDummyInput(generated.name) - .appendField(new Blockly.FieldImage(generated.src, generated.width, generated.height, generated.alt)); + this._block + .appendDummyInput(generated.name) + .appendField( + new Blockly.FieldImage(generated.src, generated.width, generated.height, generated.alt) + ); break; case "field_input": - this._block.appendDummyInput(generated.name) - .appendField(new Blockly.FieldTextInput(generated.text, undefined,{spellcheck: generated.spellcheck})); + this._block.appendDummyInput(generated.name).appendField( + new Blockly.FieldTextInput(generated.text, undefined, { + spellcheck: generated.spellcheck + }) + ); break; } - (this._blocklyDefinition.args0 as Array).push({...generated, isDummy: isDummy}); + (this._blocklyDefinition.args0 as Array).push({ ...generated, isDummy: isDummy }); } public removeInput(inputName: string): void { @@ -133,7 +174,7 @@ export default class Block { generate(): void { if (this._blockDefinition.label) return; - + // eslint-disable-next-line @typescript-eslint/no-this-alias const blockClass = this; // Used because `this` is overwritten in the blockly functions. @@ -210,7 +251,6 @@ export default class Block { const block = this; // Warnings Code this.setOnChange(function(this: Blockly.Block, changeEvent: Abstract) { - if ( importName && !this.isInFlyout && @@ -227,12 +267,14 @@ export default class Block { !this.isInFlyout && block.id == this.id ) { - const warnings = blockClass._blockDefinition.label ? undefined : blockClass._blockDefinition.warnings; + const warnings = blockClass._blockDefinition.label + ? undefined + : blockClass._blockDefinition.warnings; if (!warnings) return; - + const topParent = this.getRootBlock(); let resultMessage: string = ""; - + for (const warning of warnings) { const { warningType, message, fieldName } = warning.data; switch (warningType) { @@ -275,21 +317,18 @@ export default class Block { }; const properties = this._blockDefinition.mutator?.properties; const propertyMap: Record = {}; - if(properties) { + if (properties) { for (const property of properties) { - if(this._blockDefinition.mutator?.type === MutatorType.Assembler) { + if (this._blockDefinition.mutator?.type === MutatorType.Assembler) { propertyMap[(property as AssemblerMutator).block] = property; - - } else if(this._blockDefinition.mutator?.type === MutatorType.Checkbox) { + } else if (this._blockDefinition.mutator?.type === MutatorType.Checkbox) { propertyMap[(property as CheckBoxMutatorBlock).inputName] = property; - } } } // Generating the export code javascriptGenerator.forBlock[blockDef.type] = function(block: Blockly.Block) { - const args: Record = {}; //? Object we will pass as argument for the custom code to run properly for (const arg in blockDef.args0) { @@ -299,53 +338,52 @@ export default class Block { } //parse mutator values - for(const propertyKey of Object.keys(propertyMap)) { + for (const propertyKey of Object.keys(propertyMap)) { const property = propertyMap[propertyKey]; - console.log(propertyMap) + console.log(propertyMap); for (const add of property.adds) { const valueList: string[] = []; let i = 1; let input = block.getInput(add.name + i); - while(input) { + while (input) { const definition = add.generate() as Record; - valueList.push(getInputValue(block, definition.name as string + i, definition.type as string)); + valueList.push( + getInputValue(block, (definition.name as string) + i, definition.type as string) + ); i++; input = block.getInput(add.name + i); } - args[add.name] = valueList; - - -// const args: Record = {}; //? Object we will pass as argument to be used for code generation - -// for (const arg of blockClass._blocklyDefinition.args0) { -// //! Fix this asap... -// //@ts-expect-error gergerg -// if (arg.isDummy === true) { -// // Since it's a dummy input we need to get the value from the fields array inside the dummy input! -// //@ts-expect-error We have to access the protected value to generate it correctly. -// args[arg.name] = block.getInput(arg.name)?.fieldRow[0].value_; -// continue; -// } - -// switch (arg.type) { -// case "input_value": -// args[arg.name] = javascriptGenerator.valueToCode( -// block, -// arg.name, -// javascriptGenerator.ORDER_ATOMIC -// ); -// break; - -// case "input_statement": -// args[arg.name] = javascriptGenerator.statementToCode(block, arg.name); -// break; - -// default: -// args[arg.name] = block.getFieldValue(arg.name); -// break; - + args[add.name] = valueList; + + // const args: Record = {}; //? Object we will pass as argument to be used for code generation + + // for (const arg of blockClass._blocklyDefinition.args0) { + // //! Fix this asap... + // //@ts-expect-error gergerg + // if (arg.isDummy === true) { + // // Since it's a dummy input we need to get the value from the fields array inside the dummy input! + // //@ts-expect-error We have to access the protected value to generate it correctly. + // args[arg.name] = block.getInput(arg.name)?.fieldRow[0].value_; + // continue; + // } + + // switch (arg.type) { + // case "input_value": + // args[arg.name] = javascriptGenerator.valueToCode( + // block, + // arg.name, + // javascriptGenerator.ORDER_ATOMIC + // ); + // break; + + // case "input_statement": + // args[arg.name] = javascriptGenerator.statementToCode(block, arg.name); + // break; + + // default: + // args[arg.name] = block.getFieldValue(arg.name); + // break; } - } return output ? [code(args, blockClass), Order.NONE] : code(args, blockClass); }; diff --git a/src/lib/utils/BlockGen/Inputs/BaseInput.ts b/src/lib/utils/BlockGen/Inputs/BaseInput.ts index 0bcdadb..4eac117 100644 --- a/src/lib/utils/BlockGen/Inputs/BaseInput.ts +++ b/src/lib/utils/BlockGen/Inputs/BaseInput.ts @@ -15,7 +15,7 @@ export default class BaseInput { /* this function currently is meant for Mutator use */ - public setField(text: string): BaseInput { + public setField(text: string): BaseInput { this._fieldText = text; return this; } diff --git a/src/lib/utils/BlockGen/Inputs/Dropdown.ts b/src/lib/utils/BlockGen/Inputs/Dropdown.ts index f47b068..adafe50 100644 --- a/src/lib/utils/BlockGen/Inputs/Dropdown.ts +++ b/src/lib/utils/BlockGen/Inputs/Dropdown.ts @@ -58,5 +58,4 @@ export default class Dropdown extends BaseInput { options: this._options }; } - } diff --git a/src/lib/utils/BlockGen/Inputs/NumberInput.ts b/src/lib/utils/BlockGen/Inputs/NumberInput.ts index b9ed18b..7cc0ed7 100644 --- a/src/lib/utils/BlockGen/Inputs/NumberInput.ts +++ b/src/lib/utils/BlockGen/Inputs/NumberInput.ts @@ -1,13 +1,12 @@ import BaseInput from "./BaseInput"; - -export interface NumberIDef { - type: "field_number"; - name: string; - value: number - min? : number - max?: number - precision?: number +export interface NumberIDef { + type: "field_number"; + name: string; + value: number; + min?: number; + max?: number; + precision?: number; } export default class NumberInput extends BaseInput { @@ -39,5 +38,4 @@ export default class NumberInput extends BaseInput { ...this._settings }; } - } diff --git a/src/lib/utils/BlockGen/Inputs/StatementInput.ts b/src/lib/utils/BlockGen/Inputs/StatementInput.ts index dd26c8c..0d55a12 100644 --- a/src/lib/utils/BlockGen/Inputs/StatementInput.ts +++ b/src/lib/utils/BlockGen/Inputs/StatementInput.ts @@ -1,6 +1,6 @@ import BaseInput from "./BaseInput"; -export interface StatementIDef { +export interface StatementIDef { name: string; type: "input_statement"; } @@ -19,7 +19,6 @@ export default class StatementInput extends BaseInput { this.setMethod(this.getDefinition); super.setName(name); - } /** @@ -34,5 +33,4 @@ export default class StatementInput extends BaseInput { name: super.name }; } - } diff --git a/src/lib/utils/BlockGen/Inputs/TextInput.ts b/src/lib/utils/BlockGen/Inputs/TextInput.ts index 7000423..26d5eb5 100644 --- a/src/lib/utils/BlockGen/Inputs/TextInput.ts +++ b/src/lib/utils/BlockGen/Inputs/TextInput.ts @@ -8,7 +8,6 @@ export interface TextIDef { spellcheck: false; } - export default class TextInput extends BaseInput { private readonly _text: string; @@ -28,5 +27,4 @@ export default class TextInput extends BaseInput { spellcheck: false }; } - } diff --git a/src/lib/utils/BlockGen/Inputs/ValueInput.ts b/src/lib/utils/BlockGen/Inputs/ValueInput.ts index 1962258..10364ca 100644 --- a/src/lib/utils/BlockGen/Inputs/ValueInput.ts +++ b/src/lib/utils/BlockGen/Inputs/ValueInput.ts @@ -46,5 +46,4 @@ export default class ValueInput extends BaseInput { result.check = [...filtered]; return result; } - } diff --git a/src/lib/utils/BlockGen/Mutators/AssemblerMutatorV2.ts b/src/lib/utils/BlockGen/Mutators/AssemblerMutatorV2.ts index 2493019..a52c057 100644 --- a/src/lib/utils/BlockGen/Mutators/AssemblerMutatorV2.ts +++ b/src/lib/utils/BlockGen/Mutators/AssemblerMutatorV2.ts @@ -1,259 +1,241 @@ -import type {AssemblerMutator} from "$lib/types/BlockDefinition"; +import type { AssemblerMutator } from "$lib/types/BlockDefinition"; import salt from "$lib/utils/helpers/salt"; import pkg from "blockly/javascript"; -import type {AdditionalSettings} from "./Mutator"; -import {Mutator} from "./Mutator"; -import Blockly, {Connection} from "blockly/core"; -import {MutatorType} from "$lib/enums/BlockTypes"; +import type { AdditionalSettings } from "./Mutator"; +import { Mutator } from "./Mutator"; +import Blockly, { Connection } from "blockly/core"; +import { MutatorType } from "$lib/enums/BlockTypes"; const { javascriptGenerator } = pkg; function orderListChanged(order1: string[], order2: string[]): boolean { - if(!(Array.isArray(order1) && Array.isArray(order2))) return false; - if(order1.length !== order2.length) return true; - for (let i = 0; i < order1.length; i++) { - if(order1[i] !== order2[i]) { - return true; - } - } - return false; + if (!(Array.isArray(order1) && Array.isArray(order2))) return false; + if (order1.length !== order2.length) return true; + for (let i = 0; i < order1.length; i++) { + if (order1[i] !== order2[i]) { + return true; + } + } + return false; } interface ClauseBlock extends Blockly.Block { - //input_type: Connection - connections_: {[key: string]: Connection} + //input_type: Connection + connections_: { [key: string]: Connection }; } -type ConnectionMap = {[key: string]: ConnectionMapConnection}; +type ConnectionMap = { [key: string]: ConnectionMapConnection }; interface ConnectionMapConnection { - connection: Connection, - input_name: string + connection: Connection; + input_name: string; } export default class AssemblerMutatorV2 extends Mutator { - //will store each properties name - private order: string[]; - private settings: AdditionalSettings | undefined; - constructor(containerBlockText: string, properties: AssemblerMutator[], settings?: AdditionalSettings) { - super(properties, containerBlockText, MutatorType.Assembler); - this.order = []; - this.mixin = this.getMixin(settings); - this.setBlocks = this.blocks; - this.settings = settings; - } - - get blocks(): string[] { - const arr: string[] = []; - for (const prop of super.properties as AssemblerMutator[]) { - arr.push(prop.block); - } - return arr; - } - - - getMixin(settings?: AdditionalSettings): object { - this.order = []; - const properties = super.properties as AssemblerMutator[]; - const propertieMap = Object.create(null); - const containerBlockName = salt(10); - const containerBlockText = super.containerBlockText; - let inputIndexMap: Map = new Map(); - // First we set the save and load states. - for(const prop of properties) { - propertieMap[prop.block] = prop; - } - console.log(settings) - Blockly.Blocks[containerBlockName] = { - init: function(this: Blockly.Block) { - this.jsonInit({ - type: containerBlockName, - message0: `${containerBlockText}`, - nextStatement: true, - - colour: settings?.color ?? 230, - tooltip: "Put blocks under the container block to modify the original block", - helpUrl: "" - }); - - } - }; - javascriptGenerator.forBlock[containerBlockName] = function() { - return ""; - }; - const mixin = { - //! Disable eslint cuz the state variable is of type any until they fully migrate to typescript - // eslint-disable-next-line - saveExtraState: function(this: any): object { - - const state = Object.create(null); - if(this.order) state["order"] = this.order; - return state; - }, - //! Disable eslint cuz the state variable is of type any until they fully migrate to typescript - // eslint-disable-next-line - loadExtraState: function (this: any, state: any): void { - // const oldOrder = this.order; - this.order = state["order"] ?? []; - /*if(orderListChanged(oldOrder, this.order)) */ - this.updateShape_(); - - }, - decompose: function(this: Blockly.Block, workspace: Blockly.WorkspaceSvg) { - - const containerBlock = workspace.newBlock(containerBlockName); - containerBlock.initSvg(); - // eslint-disable-next-line - const orders = (this as any).order as string[]; - // let connection = containerBlock.getInput("STACK")?.connection; - let connection = containerBlock.nextConnection; - if(orders) { - for(const order of orders) { - const block = workspace.newBlock(order); - block.initSvg(); - connection?.connect(block.previousConnection!); - connection = block.nextConnection!; - } - } - - - - return containerBlock; - - }, - // eslint-disable-next-line - compose: function(this: any, containerBlock: Blockly.Block) { - const connections: ConnectionMap= {}; - const oldOrder = this.order; - const order = []; - - // let itemBlock: ClauseBlock | null = containerBlock.getInputTargetBlock("STACK") as ClauseBlock | null; - // eslint-disable-next-line - let itemBlock = containerBlock.nextConnection!.targetBlock() as any; - - while(itemBlock) { - order.push(itemBlock.type); - if(itemBlock.connections_) { - for (const conStr of Object.keys(itemBlock.connections_)) { - connections[conStr] = { - connection: itemBlock.connections_[conStr], - input_name: itemBlock.type - }; - } - } - // connections.push(itemBlock.conne); - itemBlock = itemBlock.nextConnection && itemBlock.nextConnection.targetBlock() as ClauseBlock | null; - } - this.order = order; - if(orderListChanged(oldOrder, this.order)) this.updateShape_(); - this.reconnectChildBlocks_( - connections - ); - }, - // eslint-disable-next-line - updateShape_: function(this: any) { - - for (const inp of properties) { - for(const add of inp.adds) { - let i = 1; - let moreInputs = true; - while(moreInputs) { - const failed = !this.removeInput(add.name + i, true); - i++; - if(failed) moreInputs = false; - } - } - } - inputIndexMap = new Map(); - if(this.order) { - for (const order of this.order) { - const adds = propertieMap[order].adds; - for (const add of adds) { - inputIndexMap.set(add._name, (inputIndexMap.get(add.name)??0) + 1); - const name = add._name + inputIndexMap.get(add.name) ; - if (!this.getInput(name)) { - const input = add.generate(); - this.appendInput_(input, name, add.getField()); - } - - - } - - } - } - - - }, - reconnectChildBlocks_: function( - this: Blockly.Block, - connections: ConnectionMap, - - ) { - const count = new Map(); - for (const connectionKey in connections) { - const ConMap = connections[connectionKey]; - const property = propertieMap[ConMap.input_name]; - const connection = ConMap.connection; - if(!connection) continue; - for (const add of property.adds) { - const name = add.name; - const c = count.get(name) ?? 1; - connection.reconnect(this, name+c); - count.set(name, c+1); - - } - } - // for (let i = 1; i <= 10; i++) { - // connections[i]?.reconnect(this, 'IF' + i); - // } - }, - // eslint-disable-next-line - saveConnections: function(this: any, containerBlock: Blockly.Block) { - const count = new Map(); - //let clauseBlock = containerBlock.getInputTargetBlock("STACK") as ClauseBlock | null; - let clauseBlock = containerBlock as ClauseBlock | null; - - while(clauseBlock) { - if(clauseBlock.isInsertionMarker()) { - clauseBlock = clauseBlock.getNextBlock() as ClauseBlock | null; - continue; - } - clauseBlock.connections_ = {}; - //count - const c = count.get(clauseBlock.type) ?? 1; - const prop = propertieMap[clauseBlock.type]; - if(prop) { - for(const add of prop.adds) { - const inp = this.getInput(add._name + c); - if(inp) { - - clauseBlock.connections_[add._name + c] = inp && inp.connection!.targetConnection; - count.set(clauseBlock.type, c+1); - } - } - } - - clauseBlock = clauseBlock.getNextBlock() as ClauseBlock | null; - } - - }, - appendInput_: function(this: Blockly.Block, input, name, fieldText) { - const inputType = input.type || "input_value"; // Default to input_value if type is not specified - const inputCheck = input.check; // Check for input type if specified - - switch (inputType) { - case "input_value": - this.appendValueInput(name).setCheck(inputCheck).appendField(fieldText); - break; - case "input_statement": - this.appendStatementInput(name).setCheck(inputCheck).appendField(fieldText); - break; - case "input_dummy": - this.appendDummyInput(name).appendField(fieldText); - break; - default: - throw new Error(`Unsupported input type: ${inputType}`); - } - } - - }; - - return mixin; - } + //will store each properties name + private order: string[]; + private settings: AdditionalSettings | undefined; + constructor( + containerBlockText: string, + properties: AssemblerMutator[], + settings?: AdditionalSettings + ) { + super(properties, containerBlockText, MutatorType.Assembler); + this.order = []; + this.mixin = this.getMixin(settings); + this.setBlocks = this.blocks; + this.settings = settings; + } + + get blocks(): string[] { + const arr: string[] = []; + for (const prop of super.properties as AssemblerMutator[]) { + arr.push(prop.block); + } + return arr; + } + + getMixin(settings?: AdditionalSettings): object { + this.order = []; + const properties = super.properties as AssemblerMutator[]; + const propertieMap = Object.create(null); + const containerBlockName = salt(10); + const containerBlockText = super.containerBlockText; + let inputIndexMap: Map = new Map(); + // First we set the save and load states. + for (const prop of properties) { + propertieMap[prop.block] = prop; + } + console.log(settings); + Blockly.Blocks[containerBlockName] = { + init: function(this: Blockly.Block) { + this.jsonInit({ + type: containerBlockName, + message0: `${containerBlockText}`, + nextStatement: true, + + colour: settings?.color ?? 230, + tooltip: "Put blocks under the container block to modify the original block", + helpUrl: "" + }); + } + }; + javascriptGenerator.forBlock[containerBlockName] = function() { + return ""; + }; + const mixin = { + //! Disable eslint cuz the state variable is of type any until they fully migrate to typescript + // eslint-disable-next-line + saveExtraState: function (this: any): object { + const state = Object.create(null); + if (this.order) state["order"] = this.order; + return state; + }, + //! Disable eslint cuz the state variable is of type any until they fully migrate to typescript + // eslint-disable-next-line + loadExtraState: function (this: any, state: any): void { + // const oldOrder = this.order; + this.order = state["order"] ?? []; + /*if(orderListChanged(oldOrder, this.order)) */ + this.updateShape_(); + }, + decompose: function(this: Blockly.Block, workspace: Blockly.WorkspaceSvg) { + const containerBlock = workspace.newBlock(containerBlockName); + containerBlock.initSvg(); + // eslint-disable-next-line + const orders = (this as any).order as string[]; + // let connection = containerBlock.getInput("STACK")?.connection; + let connection = containerBlock.nextConnection; + if (orders) { + for (const order of orders) { + const block = workspace.newBlock(order); + block.initSvg(); + connection?.connect(block.previousConnection!); + connection = block.nextConnection!; + } + } + + return containerBlock; + }, + // eslint-disable-next-line + compose: function (this: any, containerBlock: Blockly.Block) { + const connections: ConnectionMap = {}; + const oldOrder = this.order; + const order = []; + + // let itemBlock: ClauseBlock | null = containerBlock.getInputTargetBlock("STACK") as ClauseBlock | null; + // eslint-disable-next-line + let itemBlock = containerBlock.nextConnection!.targetBlock() as any; + + while (itemBlock) { + order.push(itemBlock.type); + if (itemBlock.connections_) { + for (const conStr of Object.keys(itemBlock.connections_)) { + connections[conStr] = { + connection: itemBlock.connections_[conStr], + input_name: itemBlock.type + }; + } + } + // connections.push(itemBlock.conne); + itemBlock = + itemBlock.nextConnection && + (itemBlock.nextConnection.targetBlock() as ClauseBlock | null); + } + this.order = order; + if (orderListChanged(oldOrder, this.order)) this.updateShape_(); + this.reconnectChildBlocks_(connections); + }, + // eslint-disable-next-line + updateShape_: function (this: any) { + for (const inp of properties) { + for (const add of inp.adds) { + let i = 1; + let moreInputs = true; + while (moreInputs) { + const failed = !this.removeInput(add.name + i, true); + i++; + if (failed) moreInputs = false; + } + } + } + inputIndexMap = new Map(); + if (this.order) { + for (const order of this.order) { + const adds = propertieMap[order].adds; + for (const add of adds) { + inputIndexMap.set(add._name, (inputIndexMap.get(add.name) ?? 0) + 1); + const name = add._name + inputIndexMap.get(add.name); + if (!this.getInput(name)) { + const input = add.generate(); + this.appendInput_(input, name, add.getField()); + } + } + } + } + }, + reconnectChildBlocks_: function(this: Blockly.Block, connections: ConnectionMap) { + const count = new Map(); + for (const connectionKey in connections) { + const ConMap = connections[connectionKey]; + const property = propertieMap[ConMap.input_name]; + const connection = ConMap.connection; + if (!connection) continue; + for (const add of property.adds) { + const name = add.name; + const c = count.get(name) ?? 1; + connection.reconnect(this, name + c); + count.set(name, c + 1); + } + } + // for (let i = 1; i <= 10; i++) { + // connections[i]?.reconnect(this, 'IF' + i); + // } + }, + // eslint-disable-next-line + saveConnections: function (this: any, containerBlock: Blockly.Block) { + const count = new Map(); + //let clauseBlock = containerBlock.getInputTargetBlock("STACK") as ClauseBlock | null; + let clauseBlock = containerBlock as ClauseBlock | null; + + while (clauseBlock) { + if (clauseBlock.isInsertionMarker()) { + clauseBlock = clauseBlock.getNextBlock() as ClauseBlock | null; + continue; + } + clauseBlock.connections_ = {}; + //count + const c = count.get(clauseBlock.type) ?? 1; + const prop = propertieMap[clauseBlock.type]; + if (prop) { + for (const add of prop.adds) { + const inp = this.getInput(add._name + c); + if (inp) { + clauseBlock.connections_[add._name + c] = inp && inp.connection!.targetConnection; + count.set(clauseBlock.type, c + 1); + } + } + } + + clauseBlock = clauseBlock.getNextBlock() as ClauseBlock | null; + } + }, + appendInput_: function(this: Blockly.Block, input, name, fieldText) { + const inputType = input.type || "input_value"; // Default to input_value if type is not specified + const inputCheck = input.check; // Check for input type if specified + + switch (inputType) { + case "input_value": + this.appendValueInput(name).setCheck(inputCheck).appendField(fieldText); + break; + case "input_statement": + this.appendStatementInput(name).setCheck(inputCheck).appendField(fieldText); + break; + case "input_dummy": + this.appendDummyInput(name).appendField(fieldText); + break; + default: + throw new Error(`Unsupported input type: ${inputType}`); + } + } + }; + + return mixin; + } } diff --git a/src/lib/utils/BlockGen/Mutators/CheckboxMutator.ts b/src/lib/utils/BlockGen/Mutators/CheckboxMutator.ts index aae344f..695d9e2 100644 --- a/src/lib/utils/BlockGen/Mutators/CheckboxMutator.ts +++ b/src/lib/utils/BlockGen/Mutators/CheckboxMutator.ts @@ -1,23 +1,28 @@ -import {Mutator} from "./Mutator"; -import type {AdditionalSettings} from "./Mutator"; +import { Mutator } from "./Mutator"; +import type { AdditionalSettings } from "./Mutator"; -import type {CheckBoxMutatorBlock} from "$lib/types/BlockDefinition"; +import type { CheckBoxMutatorBlock } from "$lib/types/BlockDefinition"; import salt from "$lib/utils/helpers/salt"; -import Blockly, {Connection} from "blockly/core"; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import Blockly, { Connection } from "blockly/core"; import pkg from "blockly/javascript"; -import {MutatorType} from "$lib/enums/BlockTypes"; +import { MutatorType } from "$lib/enums/BlockTypes"; const { javascriptGenerator } = pkg; interface ClauseBlock extends Blockly.Block { //input_type: Connection - connections_: { [p: string]: Blockly.Connection } + connections_: { [p: string]: Blockly.Connection }; } -type ConnectionMap = {[key: string]: Blockly.Connection}; +type ConnectionMap = { [key: string]: Blockly.Connection }; export default class CheckboxMutator extends Mutator { private settings: AdditionalSettings | undefined; - constructor(containerBlockText: string, properties: CheckBoxMutatorBlock[], settings?: AdditionalSettings) { + constructor( + containerBlockText: string, + properties: CheckBoxMutatorBlock[], + settings?: AdditionalSettings + ) { super(properties, containerBlockText, MutatorType.Checkbox); this.settings = settings; @@ -36,14 +41,14 @@ export default class CheckboxMutator extends Mutator { const properties = super.properties as CheckBoxMutatorBlock[]; const propertieMap: Record = {}; - for(const prop of properties) { + for (const prop of properties) { propertieMap[prop.inputName] = prop; } const containerBlockName = salt(10); const containerBlockText = super.containerBlockText; const inputData: boolean[] = []; const fieldData: string[] = []; - for(const prop of properties) { + for (const prop of properties) { fieldData.push(prop.inputName); inputData.push(!!prop.defaultValue); } @@ -53,12 +58,10 @@ export default class CheckboxMutator extends Mutator { type: containerBlockName, message0: `${containerBlockText}`, - colour: settings?.color ?? 230, tooltip: "", helpUrl: "" }); - } }; javascriptGenerator.forBlock[containerBlockName] = function() { @@ -69,8 +72,7 @@ export default class CheckboxMutator extends Mutator { fields_: fieldData, //! Disable eslint cuz the state variable is of type any until they fully migrate to typescript // eslint-disable-next-line - saveExtraState: function(this: any): object { - + saveExtraState: function (this: any): object { if (!this.inputs_ || this.inputs_.length === 0) return {}; const state = Object.create(null); if (this.inputs_ && this.fields_) { @@ -87,24 +89,27 @@ export default class CheckboxMutator extends Mutator { this.inputs_[i] = state[this.fields_[i]] ?? false; } this.updateShape_(); - }, // eslint-disable-next-line - decompose: function(this: any, workspace: Blockly.WorkspaceSvg) { + decompose: function (this: any, workspace: Blockly.WorkspaceSvg) { const containerBlock = workspace.newBlock(containerBlockName); - for (let i= 0; iCreate - \ No newline at end of file + From 06bb44d5c88abe54b9ea74b86999caccd0f20327 Mon Sep 17 00:00:00 2001 From: LimeNade Date: Sat, 20 Apr 2024 20:28:38 +0200 Subject: [PATCH 06/53] Feat: Removed AsMu V1 -> V2 --- src/lib/blocks/Javascript/logic.ts | 2 +- src/lib/blocks/Javascript/text.ts | 2 +- .../BlockGen/Mutators/AssemblerMutator.ts | 463 +++++++++--------- .../BlockGen/Mutators/AssemblerMutatorV2.ts | 241 --------- src/lib/utils/BlockGen/Mutators/Mutator.ts | 1 + 5 files changed, 244 insertions(+), 465 deletions(-) delete mode 100644 src/lib/utils/BlockGen/Mutators/AssemblerMutatorV2.ts diff --git a/src/lib/blocks/Javascript/logic.ts b/src/lib/blocks/Javascript/logic.ts index 335c42b..1f7583d 100644 --- a/src/lib/blocks/Javascript/logic.ts +++ b/src/lib/blocks/Javascript/logic.ts @@ -8,7 +8,7 @@ import ValueInput from "$lib/utils/BlockGen/Inputs/ValueInput"; import Warning from "$lib/utils/BlockGen/Warnings/Warning"; import rgbToHex from "$lib/utils/helpers/rgbToHex"; import StatementInput from "$lib/utils/BlockGen/Inputs/StatementInput"; -import AssemblerMutatorV2 from "$lib/utils/BlockGen/Mutators/AssemblerMutatorV2"; +import AssemblerMutatorV2 from "$lib/utils/BlockGen/Mutators/AssemblerMutator"; const blocks: BlockDefinition[] = [ { diff --git a/src/lib/blocks/Javascript/text.ts b/src/lib/blocks/Javascript/text.ts index 18ea2fc..15fabf8 100644 --- a/src/lib/blocks/Javascript/text.ts +++ b/src/lib/blocks/Javascript/text.ts @@ -6,7 +6,7 @@ import ValueInput from "$lib/utils/BlockGen/Inputs/ValueInput"; import Placeholder from "$lib/utils/ToolboxGen/Placeholder"; import StatementInput from "$lib/utils/BlockGen/Inputs/StatementInput"; import Dropdown from "$lib/utils/BlockGen/Inputs/Dropdown"; -import AssemblerMutatorV2 from "$lib/utils/BlockGen/Mutators/AssemblerMutatorV2"; +import AssemblerMutatorV2 from "$lib/utils/BlockGen/Mutators/AssemblerMutator"; const blocks: BlockDefinition[] = [ { diff --git a/src/lib/utils/BlockGen/Mutators/AssemblerMutator.ts b/src/lib/utils/BlockGen/Mutators/AssemblerMutator.ts index 615939e..d43b839 100644 --- a/src/lib/utils/BlockGen/Mutators/AssemblerMutator.ts +++ b/src/lib/utils/BlockGen/Mutators/AssemblerMutator.ts @@ -1,222 +1,241 @@ -// import type { MutatorBlock } from "$lib/types/BlockDefinition"; -// import salt from "$lib/utils/helpers/salt"; -// import pkg from "blockly/javascript"; -// const { javascriptGenerator } = pkg; -// import {Mutator} from "./Mutator"; -// import Blockly from "blockly/core"; -// -// export default class AssemblerMutator extends Mutator { -// -// -// constructor(containerBlockText: string, properties: MutatorBlock[]) { -// super(properties, containerBlockText); -// this.mixin = this.getMixin(); -// this.setBlocks = this.blocks; -// } -// -// get blocks(): string[] { -// return super.properties.map((val) => val.block); -// } -// -// getMixin(): object { -// const properties = super.properties; -// const containerBlockName = salt(10); -// const containerBlockText = super.containerBlockText; -// const extraStateObj: Record = {}; -// -// // First we set the save and load states. -// const mixin = { -// -// saveExtraState: function(this: any): object { -// -// for (const mutatorProp of properties) { -// extraStateObj[mutatorProp.block] = this[`${mutatorProp.block}_count_`]; -// } -// return extraStateObj; -// }, -// //! Disable eslint cuz the state variable is of type any until they fully migrate to typescript -// // eslint-disable-next-line -// loadExtraState: function (this: any, state: any): void { -// for (const mutatorProp of properties) { -// this[`${mutatorProp.block}_count_`] = state[mutatorProp.block]; -// } -// this.updateShape_(); -// }, -// -// decompose: function(this: any, workspace: Blockly.WorkspaceSvg) { -// -// Blockly.Blocks[containerBlockName] = { -// init: function(this: Blockly.Block) { -// this.jsonInit({ -// type: containerBlockName, -// message0: `${containerBlockText}\n %1`, -// args0: [ -// { -// type: "input_statement", -// name: "STACK" -// } -// ], -// colour: 230, -// tooltip: "Put blocks inside of the container block to modify the original block", -// helpUrl: "" -// }); -// } -// }; -// javascriptGenerator.forBlock[containerBlockName] = function() { -// return ""; -// }; -// -// const containerBlock = workspace.newBlock(containerBlockName); -// containerBlock.initSvg(); -// -// let connection = containerBlock.getInput("STACK")?.connection; -// for (const key in extraStateObj) { -// for (let i = 0; i < this[`${key}_count_`]; i++) { -// const blockToAdd: string = key; -// -// const itemBlock = workspace.newBlock(blockToAdd); -// itemBlock.initSvg(); -// connection?.connect(itemBlock.previousConnection); -// connection = itemBlock.nextConnection; -// } -// } -// -// return containerBlock; -// }, -// -// -// // eslint-disable-next-line -// compose: function (this: any, containerBlock: Blockly.Block) { -// -// const workspaceBlocks = []; -// let itemBlock = containerBlock.getInputTargetBlock("STACK"); -// // Iterate over each child block in the mutator workspace and add it to the array -// while (itemBlock) { -// workspaceBlocks.push(itemBlock); -// itemBlock = itemBlock.nextConnection && itemBlock.nextConnection.targetBlock(); -// } -// // Update the shape of the original block based on the number of child blocks -// for (const mutatorProp of properties) { -// const blockCount = workspaceBlocks.filter( -// (block) => block.type === mutatorProp.block -// ).length; -// this[`${mutatorProp.block}_count_`] = blockCount; -// } -// this.updateShape_(); -// }, -// updateShape_: function(this: Blockly.Block) { -// // Iterate over each MutatorBlock defined in the properties array -// for (let i = 0; i < properties.length; i++) { -// // @ts-expect-error MutatorProp is type is "any" -// const blockCount = this[`${mutatorProp.block}_count_`]; -// if (blockCount > 0) { -// // Determine the number of items in the adds array for the current MutatorBlock -// -// // Add inputs for each block count -// for (let j = 0; j < blockCount; j++) { -// // @ts-expect-error MutatorProp is type is "any" -// const inputName = mutatorProp.block + j; -// // @ts-expect-error MutatorProp is type is "any" -// const addsLength = mutatorProp.adds.length; -// -// if (!this.getInput(inputName)) { -// // Get the input index by taking the modulo of j with the length of the adds array -// const addsIndex = j % addsLength; -// // Generate input definition from the corresponding adds item -// // @ts-expect-error MutatorProp is type is "any" -// const input = mutatorProp.adds[addsIndex].generate(); -// // Append the input to the block -// // @ts-expect-error Undefined blockly type for the private function -// this.appendInput_(input, inputName); -// } -// } -// } else { -// // If there are no child blocks, remove all inputs for this type -// let j = 0; -// // @ts-expect-error MutatorProp is type is "any" -// while (this.getInput(mutatorProp.block + j)) { -// // @ts-expect-error MutatorProp is type is "any" -// this.removeInput(mutatorProp.block + j); -// j++; -// } -// } -// -// // If 'once' is true, disable adding more blocks of this type -// // @ts-expect-error MutatorProp is type is "any" -// if (mutatorProp.once && blockCount > 0) { -// // @ts-expect-error MutatorProp is type is "any" -// this.getInput(mutatorProp.block + (blockCount - 1)).setCheck(null); -// } -// -// // Break if we have reached the end of the properties array -// if (i + 1 >= properties.length) { -// break; -// } -// -// // Continue adding inputs for the next MutatorBlock -// const nextMutatorProp = properties[i + 1]; -// // @ts-expect-error nextMutatorProp is type is "any" -// const nextBlockCount = this[`${nextMutatorProp.block}_count_`]; -// if (nextBlockCount > 0) { -// // Determine the number of items in the adds array for the next MutatorBlock -// const nextAddsLength = nextMutatorProp.adds.length; -// // Add inputs for each block count -// for (let k = 0; k < nextBlockCount; k++) { -// const nextInputName = nextMutatorProp.block + k; -// if (!this.getInput(nextInputName)) { -// // Get the input index by taking the modulo of k with the length of the adds array -// const nextAddsIndex = k % nextAddsLength; -// // Generate input definition from the corresponding adds item -// const nextInput = nextMutatorProp.adds[nextAddsIndex].generate(); -// // Append the input to the block -// // @ts-expect-error Undefined blockly type for the private function -// this.appendInput_(nextInput, nextInputName); -// } -// } -// } else { -// // If there are no child blocks, remove all inputs for this type -// let k = 0; -// while (this.getInput(nextMutatorProp.block + k)) { -// this.removeInput(nextMutatorProp.block + k); -// k++; -// } -// } -// -// // If 'once' is true, disable adding more blocks of this type -// if (nextMutatorProp.once && nextBlockCount > 0) { -// // @ts-expect-error MutatorProp is type is "any" -// this.getInput(nextMutatorProp.block + (nextBlockCount - 1)).setCheck(null); -// } -// } -// }, -// -// /** -// * Append a Blockly input to the block -// * @param {object} input - Input definition -// * @param {string} name - Name of the input -// * @private -// */ -// // eslint-disable-next-line -// appendInput_: function (this: Blockly.Block, input: any, name: any) { -// const inputType = input.type || "input_value"; // Default to input_value if type is not specified -// const inputCheck = input.check; // Check for input type if specified -// -// switch (inputType) { -// case "input_value": -// this.appendValueInput(name).setCheck(inputCheck); -// break; -// case "input_statement": -// this.appendStatementInput(name).setCheck(inputCheck); -// break; -// case "input_dummy": -// this.appendDummyInput(name); -// break; -// default: -// throw new Error(`Unsupported input type: ${inputType}`); -// } -// } -// }; -// -// return mixin; -// } -// } +import type { AssemblerMutator as AssemblerMutatorType } from "$lib/types/BlockDefinition"; +import salt from "$lib/utils/helpers/salt"; +import pkg from "blockly/javascript"; +import type { AdditionalSettings } from "./Mutator"; +import { Mutator } from "./Mutator"; +import Blockly, { Connection } from "blockly/core"; +import { MutatorType } from "$lib/enums/BlockTypes"; + +const { javascriptGenerator } = pkg; + +function orderListChanged(order1: string[], order2: string[]): boolean { + if (!(Array.isArray(order1) && Array.isArray(order2))) return false; + if (order1.length !== order2.length) return true; + for (let i = 0; i < order1.length; i++) { + if (order1[i] !== order2[i]) { + return true; + } + } + return false; +} +interface ClauseBlock extends Blockly.Block { + //input_type: Connection + connections_: { [key: string]: Connection }; +} +type ConnectionMap = { [key: string]: ConnectionMapConnection }; +interface ConnectionMapConnection { + connection: Connection; + input_name: string; +} +export default class AssemblerMutator extends Mutator { + //will store each properties name + private order: string[]; + private settings: AdditionalSettings | undefined; + constructor( + containerBlockText: string, + properties: AssemblerMutatorType[], + settings?: AdditionalSettings + ) { + super(properties, containerBlockText, MutatorType.Assembler); + this.order = []; + this.mixin = this.getMixin(settings); + this.setBlocks = this.blocks; + this.settings = settings; + } + + get blocks(): string[] { + const arr: string[] = []; + for (const prop of super.properties as AssemblerMutatorType[]) { + arr.push(prop.block); + } + return arr; + } + + getMixin(settings?: AdditionalSettings): object { + this.order = []; + const properties = super.properties as AssemblerMutatorType[]; + const propertieMap = Object.create(null); + const containerBlockName = salt(10); + const containerBlockText = super.containerBlockText; + let inputIndexMap: Map = new Map(); + // First we set the save and load states. + for (const prop of properties) { + propertieMap[prop.block] = prop; + } + console.log(settings); + Blockly.Blocks[containerBlockName] = { + init: function(this: Blockly.Block) { + this.jsonInit({ + type: containerBlockName, + message0: `${containerBlockText}`, + nextStatement: true, + + colour: settings?.color ?? 230, + tooltip: "Put blocks under the container block to modify the original block", + helpUrl: "" + }); + } + }; + javascriptGenerator.forBlock[containerBlockName] = function() { + return ""; + }; + const mixin = { + //! Disable eslint cuz the state variable is of type any until they fully migrate to typescript + // eslint-disable-next-line + saveExtraState: function (this: any): object { + const state = Object.create(null); + if (this.order) state["order"] = this.order; + return state; + }, + //! Disable eslint cuz the state variable is of type any until they fully migrate to typescript + // eslint-disable-next-line + loadExtraState: function (this: any, state: any): void { + // const oldOrder = this.order; + this.order = state["order"] ?? []; + /*if(orderListChanged(oldOrder, this.order)) */ + this.updateShape_(); + }, + decompose: function(this: Blockly.Block, workspace: Blockly.WorkspaceSvg) { + const containerBlock = workspace.newBlock(containerBlockName); + containerBlock.initSvg(); + // eslint-disable-next-line + const orders = (this as any).order as string[]; + // let connection = containerBlock.getInput("STACK")?.connection; + let connection = containerBlock.nextConnection; + if (orders) { + for (const order of orders) { + const block = workspace.newBlock(order); + block.initSvg(); + connection?.connect(block.previousConnection!); + connection = block.nextConnection!; + } + } + + return containerBlock; + }, + // eslint-disable-next-line + compose: function (this: any, containerBlock: Blockly.Block) { + const connections: ConnectionMap = {}; + const oldOrder = this.order; + const order = []; + + // let itemBlock: ClauseBlock | null = containerBlock.getInputTargetBlock("STACK") as ClauseBlock | null; + // eslint-disable-next-line + let itemBlock = containerBlock.nextConnection!.targetBlock() as any; + + while (itemBlock) { + order.push(itemBlock.type); + if (itemBlock.connections_) { + for (const conStr of Object.keys(itemBlock.connections_)) { + connections[conStr] = { + connection: itemBlock.connections_[conStr], + input_name: itemBlock.type + }; + } + } + // connections.push(itemBlock.conne); + itemBlock = + itemBlock.nextConnection && + (itemBlock.nextConnection.targetBlock() as ClauseBlock | null); + } + this.order = order; + if (orderListChanged(oldOrder, this.order)) this.updateShape_(); + this.reconnectChildBlocks_(connections); + }, + // eslint-disable-next-line + updateShape_: function (this: any) { + for (const inp of properties) { + for (const add of inp.adds) { + let i = 1; + let moreInputs = true; + while (moreInputs) { + const failed = !this.removeInput(add.name + i, true); + i++; + if (failed) moreInputs = false; + } + } + } + inputIndexMap = new Map(); + if (this.order) { + for (const order of this.order) { + const adds = propertieMap[order].adds; + for (const add of adds) { + inputIndexMap.set(add._name, (inputIndexMap.get(add.name) ?? 0) + 1); + const name = add._name + inputIndexMap.get(add.name); + if (!this.getInput(name)) { + const input = add.generate(); + this.appendInput_(input, name, add.getField()); + } + } + } + } + }, + reconnectChildBlocks_: function(this: Blockly.Block, connections: ConnectionMap) { + const count = new Map(); + for (const connectionKey in connections) { + const ConMap = connections[connectionKey]; + const property = propertieMap[ConMap.input_name]; + const connection = ConMap.connection; + if (!connection) continue; + for (const add of property.adds) { + const name = add.name; + const c = count.get(name) ?? 1; + connection.reconnect(this, name + c); + count.set(name, c + 1); + } + } + // for (let i = 1; i <= 10; i++) { + // connections[i]?.reconnect(this, 'IF' + i); + // } + }, + // eslint-disable-next-line + saveConnections: function (this: any, containerBlock: Blockly.Block) { + const count = new Map(); + //let clauseBlock = containerBlock.getInputTargetBlock("STACK") as ClauseBlock | null; + let clauseBlock = containerBlock as ClauseBlock | null; + + while (clauseBlock) { + if (clauseBlock.isInsertionMarker()) { + clauseBlock = clauseBlock.getNextBlock() as ClauseBlock | null; + continue; + } + clauseBlock.connections_ = {}; + //count + const c = count.get(clauseBlock.type) ?? 1; + const prop = propertieMap[clauseBlock.type]; + if (prop) { + for (const add of prop.adds) { + const inp = this.getInput(add._name + c); + if (inp) { + clauseBlock.connections_[add._name + c] = inp && inp.connection!.targetConnection; + count.set(clauseBlock.type, c + 1); + } + } + } + + clauseBlock = clauseBlock.getNextBlock() as ClauseBlock | null; + } + }, + appendInput_: function(this: Blockly.Block, input, name, fieldText) { + const inputType = input.type || "input_value"; // Default to input_value if type is not specified + const inputCheck = input.check; // Check for input type if specified + + switch (inputType) { + case "input_value": + this.appendValueInput(name).setCheck(inputCheck).appendField(fieldText); + break; + case "input_statement": + this.appendStatementInput(name).setCheck(inputCheck).appendField(fieldText); + break; + case "input_dummy": + this.appendDummyInput(name).appendField(fieldText); + break; + default: + throw new Error(`Unsupported input type: ${inputType}`); + } + } + }; + + return mixin; + } +} diff --git a/src/lib/utils/BlockGen/Mutators/AssemblerMutatorV2.ts b/src/lib/utils/BlockGen/Mutators/AssemblerMutatorV2.ts deleted file mode 100644 index a52c057..0000000 --- a/src/lib/utils/BlockGen/Mutators/AssemblerMutatorV2.ts +++ /dev/null @@ -1,241 +0,0 @@ -import type { AssemblerMutator } from "$lib/types/BlockDefinition"; -import salt from "$lib/utils/helpers/salt"; -import pkg from "blockly/javascript"; -import type { AdditionalSettings } from "./Mutator"; -import { Mutator } from "./Mutator"; -import Blockly, { Connection } from "blockly/core"; -import { MutatorType } from "$lib/enums/BlockTypes"; - -const { javascriptGenerator } = pkg; - -function orderListChanged(order1: string[], order2: string[]): boolean { - if (!(Array.isArray(order1) && Array.isArray(order2))) return false; - if (order1.length !== order2.length) return true; - for (let i = 0; i < order1.length; i++) { - if (order1[i] !== order2[i]) { - return true; - } - } - return false; -} -interface ClauseBlock extends Blockly.Block { - //input_type: Connection - connections_: { [key: string]: Connection }; -} -type ConnectionMap = { [key: string]: ConnectionMapConnection }; -interface ConnectionMapConnection { - connection: Connection; - input_name: string; -} -export default class AssemblerMutatorV2 extends Mutator { - //will store each properties name - private order: string[]; - private settings: AdditionalSettings | undefined; - constructor( - containerBlockText: string, - properties: AssemblerMutator[], - settings?: AdditionalSettings - ) { - super(properties, containerBlockText, MutatorType.Assembler); - this.order = []; - this.mixin = this.getMixin(settings); - this.setBlocks = this.blocks; - this.settings = settings; - } - - get blocks(): string[] { - const arr: string[] = []; - for (const prop of super.properties as AssemblerMutator[]) { - arr.push(prop.block); - } - return arr; - } - - getMixin(settings?: AdditionalSettings): object { - this.order = []; - const properties = super.properties as AssemblerMutator[]; - const propertieMap = Object.create(null); - const containerBlockName = salt(10); - const containerBlockText = super.containerBlockText; - let inputIndexMap: Map = new Map(); - // First we set the save and load states. - for (const prop of properties) { - propertieMap[prop.block] = prop; - } - console.log(settings); - Blockly.Blocks[containerBlockName] = { - init: function(this: Blockly.Block) { - this.jsonInit({ - type: containerBlockName, - message0: `${containerBlockText}`, - nextStatement: true, - - colour: settings?.color ?? 230, - tooltip: "Put blocks under the container block to modify the original block", - helpUrl: "" - }); - } - }; - javascriptGenerator.forBlock[containerBlockName] = function() { - return ""; - }; - const mixin = { - //! Disable eslint cuz the state variable is of type any until they fully migrate to typescript - // eslint-disable-next-line - saveExtraState: function (this: any): object { - const state = Object.create(null); - if (this.order) state["order"] = this.order; - return state; - }, - //! Disable eslint cuz the state variable is of type any until they fully migrate to typescript - // eslint-disable-next-line - loadExtraState: function (this: any, state: any): void { - // const oldOrder = this.order; - this.order = state["order"] ?? []; - /*if(orderListChanged(oldOrder, this.order)) */ - this.updateShape_(); - }, - decompose: function(this: Blockly.Block, workspace: Blockly.WorkspaceSvg) { - const containerBlock = workspace.newBlock(containerBlockName); - containerBlock.initSvg(); - // eslint-disable-next-line - const orders = (this as any).order as string[]; - // let connection = containerBlock.getInput("STACK")?.connection; - let connection = containerBlock.nextConnection; - if (orders) { - for (const order of orders) { - const block = workspace.newBlock(order); - block.initSvg(); - connection?.connect(block.previousConnection!); - connection = block.nextConnection!; - } - } - - return containerBlock; - }, - // eslint-disable-next-line - compose: function (this: any, containerBlock: Blockly.Block) { - const connections: ConnectionMap = {}; - const oldOrder = this.order; - const order = []; - - // let itemBlock: ClauseBlock | null = containerBlock.getInputTargetBlock("STACK") as ClauseBlock | null; - // eslint-disable-next-line - let itemBlock = containerBlock.nextConnection!.targetBlock() as any; - - while (itemBlock) { - order.push(itemBlock.type); - if (itemBlock.connections_) { - for (const conStr of Object.keys(itemBlock.connections_)) { - connections[conStr] = { - connection: itemBlock.connections_[conStr], - input_name: itemBlock.type - }; - } - } - // connections.push(itemBlock.conne); - itemBlock = - itemBlock.nextConnection && - (itemBlock.nextConnection.targetBlock() as ClauseBlock | null); - } - this.order = order; - if (orderListChanged(oldOrder, this.order)) this.updateShape_(); - this.reconnectChildBlocks_(connections); - }, - // eslint-disable-next-line - updateShape_: function (this: any) { - for (const inp of properties) { - for (const add of inp.adds) { - let i = 1; - let moreInputs = true; - while (moreInputs) { - const failed = !this.removeInput(add.name + i, true); - i++; - if (failed) moreInputs = false; - } - } - } - inputIndexMap = new Map(); - if (this.order) { - for (const order of this.order) { - const adds = propertieMap[order].adds; - for (const add of adds) { - inputIndexMap.set(add._name, (inputIndexMap.get(add.name) ?? 0) + 1); - const name = add._name + inputIndexMap.get(add.name); - if (!this.getInput(name)) { - const input = add.generate(); - this.appendInput_(input, name, add.getField()); - } - } - } - } - }, - reconnectChildBlocks_: function(this: Blockly.Block, connections: ConnectionMap) { - const count = new Map(); - for (const connectionKey in connections) { - const ConMap = connections[connectionKey]; - const property = propertieMap[ConMap.input_name]; - const connection = ConMap.connection; - if (!connection) continue; - for (const add of property.adds) { - const name = add.name; - const c = count.get(name) ?? 1; - connection.reconnect(this, name + c); - count.set(name, c + 1); - } - } - // for (let i = 1; i <= 10; i++) { - // connections[i]?.reconnect(this, 'IF' + i); - // } - }, - // eslint-disable-next-line - saveConnections: function (this: any, containerBlock: Blockly.Block) { - const count = new Map(); - //let clauseBlock = containerBlock.getInputTargetBlock("STACK") as ClauseBlock | null; - let clauseBlock = containerBlock as ClauseBlock | null; - - while (clauseBlock) { - if (clauseBlock.isInsertionMarker()) { - clauseBlock = clauseBlock.getNextBlock() as ClauseBlock | null; - continue; - } - clauseBlock.connections_ = {}; - //count - const c = count.get(clauseBlock.type) ?? 1; - const prop = propertieMap[clauseBlock.type]; - if (prop) { - for (const add of prop.adds) { - const inp = this.getInput(add._name + c); - if (inp) { - clauseBlock.connections_[add._name + c] = inp && inp.connection!.targetConnection; - count.set(clauseBlock.type, c + 1); - } - } - } - - clauseBlock = clauseBlock.getNextBlock() as ClauseBlock | null; - } - }, - appendInput_: function(this: Blockly.Block, input, name, fieldText) { - const inputType = input.type || "input_value"; // Default to input_value if type is not specified - const inputCheck = input.check; // Check for input type if specified - - switch (inputType) { - case "input_value": - this.appendValueInput(name).setCheck(inputCheck).appendField(fieldText); - break; - case "input_statement": - this.appendStatementInput(name).setCheck(inputCheck).appendField(fieldText); - break; - case "input_dummy": - this.appendDummyInput(name).appendField(fieldText); - break; - default: - throw new Error(`Unsupported input type: ${inputType}`); - } - } - }; - - return mixin; - } -} diff --git a/src/lib/utils/BlockGen/Mutators/Mutator.ts b/src/lib/utils/BlockGen/Mutators/Mutator.ts index 6ffd29c..996ed47 100644 --- a/src/lib/utils/BlockGen/Mutators/Mutator.ts +++ b/src/lib/utils/BlockGen/Mutators/Mutator.ts @@ -12,6 +12,7 @@ export class Mutator { private _blocks: string[] | undefined; private _helperFunction: (() => void) | undefined; private mutatorType: MutatorType; + constructor(properties: MutatorBlock[], containerBlockText: string, mutatorType: MutatorType) { this._properties = properties; this._containerBlockText = containerBlockText; From 5517252136de38966692137052a14a16f48bb4b6 Mon Sep 17 00:00:00 2001 From: LimeNade Date: Sun, 21 Apr 2024 13:10:30 +0200 Subject: [PATCH 07/53] Feat: Better Tooltips + Remove logs Also Fixed dynamic inputs code generation bug. Still not fixed: Dynamic inputs breaking toolbox reopen --- src/lib/blocks/Javascript/Loops.ts | 6 +-- src/lib/blocks/Javascript/logic.ts | 32 ++++++-------- src/lib/blocks/Javascript/math.ts | 24 +++++----- src/lib/components/Workspace.svelte | 3 -- src/lib/utils/BlockGen/Blocks/Block.ts | 44 +++++-------------- .../BlockGen/Mutators/AssemblerMutator.ts | 2 +- .../BlockGen/Mutators/CheckboxMutator.ts | 1 - 7 files changed, 39 insertions(+), 73 deletions(-) diff --git a/src/lib/blocks/Javascript/Loops.ts b/src/lib/blocks/Javascript/Loops.ts index 02f8ccc..a24c02d 100644 --- a/src/lib/blocks/Javascript/Loops.ts +++ b/src/lib/blocks/Javascript/Loops.ts @@ -35,7 +35,7 @@ const blocks: BlockDefinition[] = [ shape: BlockShape.Action, inline: true, colour: rgbToHex(91, 165, 91), - tooltip: "Repeat while", + tooltip: "Repeats the code inside until/while the condition is met.", helpUrl: "", code: (args) => { return `while (${args.WHILE === "while" ? "" : "!"}( ${args.CONDITION === "" ? "false" : args.CONDITION} )) {\n${args.INPUT === "" ? "" : args.INPUT}\n}`; @@ -82,7 +82,7 @@ const blocks: BlockDefinition[] = [ shape: BlockShape.Action, inline: true, colour: rgbToHex(91, 165, 91), - tooltip: "Array iteration", + tooltip: "Loops throught every item of the given array.", helpUrl: "", code: (args) => { return `for (let ${args.ITEM} of ${args.ARRAY}) {\n${args.INPUT}\n}`; @@ -100,7 +100,7 @@ const blocks: BlockDefinition[] = [ shape: BlockShape.Action, inline: true, colour: rgbToHex(91, 165, 91), - tooltip: "Break", + tooltip: "Breaks out of a loop.", helpUrl: "", code: (args) => { return `${args.ACTION};`; diff --git a/src/lib/blocks/Javascript/logic.ts b/src/lib/blocks/Javascript/logic.ts index 1f7583d..832bbfe 100644 --- a/src/lib/blocks/Javascript/logic.ts +++ b/src/lib/blocks/Javascript/logic.ts @@ -23,24 +23,18 @@ const blocks: BlockDefinition[] = [ shape: BlockShape.Action, inline: true, colour: rgbToHex(91, 128, 165), - tooltip: "Returns the opposite of the input", + tooltip: "Runs the code inside if the condition is met!", helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_NOT", code: (args) => { - console.log(args); - let code = `if(${args.operand === "" ? "false" : args.operand}) { - ${args.if} -}`; + let code = `if(${args.operand === "" ? "false" : args.operand}) {${args.if}}`; const ifInputs = args.if_input as string[]; const ifStatementInputs = args.if_statement as string[]; for (let i = 0; i < ifInputs.length; i++) { const ifInp = ifInputs[i]; - code += ` else if(${ifInp === "" ? "false" : ifInp}) { - ${ifStatementInputs[i]} -}`; + code += ` else if(${ifInp === "" ? "false" : ifInp}) {${ifStatementInputs[i]}}`; } - return code; }, mutator: new AssemblerMutatorV2( @@ -98,6 +92,8 @@ const blocks: BlockDefinition[] = [ // return `${args.A} ${args.CONDITION} ${args.B}`; code: (args, block) => { + block.colour = rgbToHex(255, 128, 165); + block.outputType = BlockType.Any; block.addInput(new Dropdown("bob", DropdownType.Auto, { bob: "hello", alex: "nikola" })); block.addInput(new ValueInput("chicken", BlockType.Any)); block.addInput(new NumberInput("numberrr", 50, { max: 100, min: 50, precision: 10 })); @@ -149,7 +145,7 @@ const blocks: BlockDefinition[] = [ } }, { - id: "values", + id: "booleans", text: "{INPUT}", args: [ new Dropdown("INPUT", DropdownType.Auto, { @@ -163,7 +159,7 @@ const blocks: BlockDefinition[] = [ output: BlockType.Any, inline: true, colour: rgbToHex(91, 128, 165), - tooltip: "", + tooltip: "Boolean values used to verify conditions.", helpUrl: "", code: (args) => { return `${args.INPUT !== "" ? args.INPUT : "null"}`; @@ -186,7 +182,7 @@ const blocks: BlockDefinition[] = [ output: BlockType.Any, inline: false, colour: rgbToHex(91, 128, 165), - tooltip: "", + tooltip: "JavaScript ternary operator.", helpUrl: "", code: (args) => { return `${args.CONDITION} ? ${args.ONTRUE} : ${args.ONFALSE}`; @@ -201,7 +197,7 @@ const blocks: BlockDefinition[] = [ output: BlockType.String, inline: true, colour: rgbToHex(91, 128, 165), - tooltip: "", + tooltip: "Gives the type of the input.", helpUrl: "", code: (args) => { if (args.OPERAND === "") return "null"; @@ -209,8 +205,8 @@ const blocks: BlockDefinition[] = [ } }, { - id: "typeof_types", - text: "typeof types {TYPE}", + id: "types", + text: "type {TYPE}", args: [ // new ValueInput("OPERAND", BlockType.Any), new Dropdown("TYPE", DropdownType.Auto, { @@ -232,7 +228,7 @@ const blocks: BlockDefinition[] = [ output: BlockType.Boolean, inline: true, colour: rgbToHex(91, 128, 165), - tooltip: "", + tooltip: "A colletion of all JavaScript base types.", helpUrl: "", code: (args) => { return `"${args.TYPE}"`; @@ -240,11 +236,11 @@ const blocks: BlockDefinition[] = [ }, { id: "stop_script", - text: "stop script", + text: "Stop script", shape: BlockShape.Bottom, inline: true, colour: rgbToHex(165, 91, 153), - tooltip: "", + tooltip: "Stops the script, cannot have any blocks under it.", helpUrl: "", code: () => { return "return;"; diff --git a/src/lib/blocks/Javascript/math.ts b/src/lib/blocks/Javascript/math.ts index d54ba0e..ed09c83 100644 --- a/src/lib/blocks/Javascript/math.ts +++ b/src/lib/blocks/Javascript/math.ts @@ -15,7 +15,7 @@ const blocks: BlockDefinition[] = [ output: BlockType.Number, inline: true, colour: "#5b67a5", - tooltip: "Allows you to make a number input.", + tooltip: "A simple number value.", helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", code: (args) => { @@ -45,7 +45,7 @@ const blocks: BlockDefinition[] = [ output: BlockType.Number, inline: true, colour: "#5b67a5", - tooltip: "Allows you to make operations with numbers.", + tooltip: "Performs a binary operation on the two given inputs.", helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", code: (args) => { @@ -82,7 +82,7 @@ const blocks: BlockDefinition[] = [ output: BlockType.Number, inline: true, colour: "#5b67a5", - tooltip: "Allows you to make operations with numbers.", + tooltip: "Perform complex math operations on a number.", helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", code: (args) => { @@ -124,7 +124,7 @@ const blocks: BlockDefinition[] = [ output: BlockType.Number, inline: true, colour: "#5b67a5", - tooltip: "Allows you to use constants.", + tooltip: "A set of math constants.", helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", code: (args) => { @@ -200,7 +200,7 @@ const blocks: BlockDefinition[] = [ output: BlockType.Number, inline: true, colour: "#5b67a5", - tooltip: "Allows you to use math with arrays.", + tooltip: "Performs math operations on lists.", helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", code: (args) => { @@ -240,14 +240,14 @@ const blocks: BlockDefinition[] = [ output: BlockType.Number, inline: true, colour: "#5b67a5", - tooltip: "Gets a random integer between two numbers.", - helpUrl: - "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", + tooltip: "Generates a random number between the two given numbers.", + helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", code: (args) => { return `Math.floor(Math.random() * (${args.MAX} - ${args.MIN}) + ${args.MIN})`; } }, { + //Todo: Delete/Remake completely this block. id: "random_fraction", text: "random fraction", args: [], @@ -255,9 +255,8 @@ const blocks: BlockDefinition[] = [ output: BlockType.Number, inline: true, colour: "#5b67a5", - tooltip: "Gets a random fraction.", - helpUrl: - "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", + tooltip: "Generates a random fraction", + helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", code: () => { return "Math.random()"; } @@ -272,8 +271,7 @@ const blocks: BlockDefinition[] = [ inline: true, colour: "#5b67a5", tooltip: "Converts text to a number.", - helpUrl: - "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", + helpUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", code: (args) => { return `parseInt(${args.TEXT})`; } diff --git a/src/lib/components/Workspace.svelte b/src/lib/components/Workspace.svelte index f9d015b..7bf7785 100644 --- a/src/lib/components/Workspace.svelte +++ b/src/lib/components/Workspace.svelte @@ -32,9 +32,6 @@ ]); function updateCode(event: Abstract) { - workspace.getAllBlocks(true).forEach((block) => { - if (block.type === "is_equal") console.log(block); - }); if (workspace.isDragging()) return; // Don't update while changes are happening. if (!supportedEvents.has(event.type)) return; diff --git a/src/lib/utils/BlockGen/Blocks/Block.ts b/src/lib/utils/BlockGen/Blocks/Block.ts index 5bc1b45..a505337 100644 --- a/src/lib/utils/BlockGen/Blocks/Block.ts +++ b/src/lib/utils/BlockGen/Blocks/Block.ts @@ -331,16 +331,21 @@ export default class Block { javascriptGenerator.forBlock[blockDef.type] = function(block: Blockly.Block) { const args: Record = {}; //? Object we will pass as argument for the custom code to run properly - for (const arg in blockDef.args0) { - const argValue = blockDef.args0[arg]; //? The argument object, contains the name, the type etc.. - const argName: string = blockDef.args0[arg].name as string; - args[argName] = getInputValue(block, argName, argValue.type); + for (const arg of blockDef.args0) { + //! Fix this asap... + //@ts-expect-error gergerg + if (arg.isDummy === true) { + // Since it's a dummy input we need to get the value from the fields array inside the dummy input! + //@ts-expect-error We have to access the protected value to generate it correctly. + args[arg.name] = block.getInput(arg.name)?.fieldRow[0].value_; + continue; + } + args[arg.name] = getInputValue(block, arg.name, arg.type); } //parse mutator values for (const propertyKey of Object.keys(propertyMap)) { const property = propertyMap[propertyKey]; - console.log(propertyMap); for (const add of property.adds) { const valueList: string[] = []; let i = 1; @@ -354,35 +359,6 @@ export default class Block { input = block.getInput(add.name + i); } args[add.name] = valueList; - - // const args: Record = {}; //? Object we will pass as argument to be used for code generation - - // for (const arg of blockClass._blocklyDefinition.args0) { - // //! Fix this asap... - // //@ts-expect-error gergerg - // if (arg.isDummy === true) { - // // Since it's a dummy input we need to get the value from the fields array inside the dummy input! - // //@ts-expect-error We have to access the protected value to generate it correctly. - // args[arg.name] = block.getInput(arg.name)?.fieldRow[0].value_; - // continue; - // } - - // switch (arg.type) { - // case "input_value": - // args[arg.name] = javascriptGenerator.valueToCode( - // block, - // arg.name, - // javascriptGenerator.ORDER_ATOMIC - // ); - // break; - - // case "input_statement": - // args[arg.name] = javascriptGenerator.statementToCode(block, arg.name); - // break; - - // default: - // args[arg.name] = block.getFieldValue(arg.name); - // break; } } return output ? [code(args, blockClass), Order.NONE] : code(args, blockClass); diff --git a/src/lib/utils/BlockGen/Mutators/AssemblerMutator.ts b/src/lib/utils/BlockGen/Mutators/AssemblerMutator.ts index d43b839..bfb2809 100644 --- a/src/lib/utils/BlockGen/Mutators/AssemblerMutator.ts +++ b/src/lib/utils/BlockGen/Mutators/AssemblerMutator.ts @@ -62,7 +62,7 @@ export default class AssemblerMutator extends Mutator { for (const prop of properties) { propertieMap[prop.block] = prop; } - console.log(settings); + Blockly.Blocks[containerBlockName] = { init: function(this: Blockly.Block) { this.jsonInit({ diff --git a/src/lib/utils/BlockGen/Mutators/CheckboxMutator.ts b/src/lib/utils/BlockGen/Mutators/CheckboxMutator.ts index 695d9e2..ad84c4f 100644 --- a/src/lib/utils/BlockGen/Mutators/CheckboxMutator.ts +++ b/src/lib/utils/BlockGen/Mutators/CheckboxMutator.ts @@ -140,7 +140,6 @@ export default class CheckboxMutator extends Mutator { if (!conn) continue; conn.reconnect(this, connectionKey); } - console.log(connections); }, // eslint-disable-next-line saveConnections: function (this: any, containerBlock: any) { From 7d48e5113f645a0793896e87c91da198b12d8adf Mon Sep 17 00:00:00 2001 From: LimeNade Date: Sun, 21 Apr 2024 20:40:47 +0200 Subject: [PATCH 08/53] Feat: update workspace creation form --- src/routes/+page.svelte | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 51c5e54..9b2ac74 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -6,8 +6,12 @@ let workspaceArray: DiscodesWorkspace[]; let loaded: boolean = false; + let workspaceName: string | undefined; let workspaceDescription: string | undefined; + let token: string; + let canCreateWorkspace: boolean = false; + let localDB = getLocalDB(); let create_workspace: HTMLDialogElement; @@ -16,11 +20,24 @@ loaded = true; }); + function canSubmit(): void { + if ((workspaceDescription && workspaceDescription?.length > 50) || (workspaceName && workspaceName?.length > 25)) { + canCreateWorkspace = false + return; + } if (token.includes(" ") || token.length === 0) { + canCreateWorkspace = false + return; + } + canCreateWorkspace = true + } + function refreshWorksapces(): void { workspaceArray = localDB.workspaces; } function createWorkspace(): void { + if (!canCreateWorkspace) return; + const workspaceID = `${localDB.workspaces.length + 1}`; //? create the userID if it does't exist. @@ -49,7 +66,7 @@ name: workspaceName || "My workspace", description: workspaceDescription || "Awesome Discord bot!", timeWasted: 0, - token: "", + token: token, lastOpened: "index" }); @@ -107,9 +124,10 @@

Create a new workspace