From c5aa32b5bb2ac5d07b2fb13aec0ce188ed7630ea Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Wed, 12 Jul 2017 20:38:41 +0000 Subject: [PATCH 001/272] chore(package): update promise to version 8.0.1 Closes #613 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d51b27e2e..e09db53cc 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "json": "^9.0.4", "lodash.defaultsdeep": "4.6.0", "minilog": "3.1.0", - "promise": "7.1.1", + "promise": "8.0.1", "scratch-audio": "latest", "scratch-blocks": "latest", "scratch-render": "latest", From e30e5809d17dc754e61dc0be00dcfb70f3376362 Mon Sep 17 00:00:00 2001 From: Ken Date: Fri, 25 Aug 2017 15:07:38 +0800 Subject: [PATCH 002/272] Add new blocks change pen transparency by (num) set pen transparency to (num) --- src/blocks/scratch3_pen.js | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index 13c0ed42b..7389035dd 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -214,7 +214,9 @@ class Scratch3PenBlocks { pen_changepenshadeby: this.changePenShadeBy, pen_setpenshadeto: this.setPenShadeToNumber, pen_changepensizeby: this.changePenSizeBy, - pen_setpensizeto: this.setPenSizeTo + pen_setpensizeto: this.setPenSizeTo, + pen_changepentransparencyby: this.changePenTransparencyBy, + pen_setpentransparencyto: this.setPenTransparencyTo }; } @@ -371,6 +373,32 @@ class Scratch3PenBlocks { const penAttributes = this._getPenState(util.target).penAttributes; penAttributes.diameter = this._clampPenSize(Cast.toNumber(args.SIZE)); } + + /** + * The pen "change pen transparency by {number}" block changes the "transparency" of the pen, related to the RGB value. + * @param {object} args - the block arguments. + * @property {number} TRANSPARENCY - the amount of desired transparency change. + * @param {object} util - utility object provided by the runtime. + */ + changePenTransparencyBy (args, util) { + const penState = this._getPenState(util.target); + + penState.penAttributes.color4f[3] = penState.penAttributes.color4f[3] + (args.TRANSPARENCY / 255); + this._updatePenColor(penState); + } + + /** + * The pen "set pen transparency to {number}" block sets the "transparency" of the pen, related to the RGB value. + * @param {object} args - the block arguments. + * @property {number} TRANSPARENCY - the amount of desired transparency change. + * @param {object} util - utility object provided by the runtime. + */ + setPenTransparencyTo (args, util) { + const penState = this._getPenState(util.target); + + penState.penAttributes.color4f[3] = args.TRANSPARENCY / 255; + this._updatePenColor(penState); + } } module.exports = Scratch3PenBlocks; From 8a77329c7974de78485d718c7c4e2fd48a93ba84 Mon Sep 17 00:00:00 2001 From: Ken Date: Fri, 25 Aug 2017 15:24:56 +0800 Subject: [PATCH 003/272] Fix lint issue and update maximums Inferring from the issue, the maximum seems to be 100, not 255 (default for set is 50 and change is 10). Changed that. A comment line was too long (thanks lint) so it has now been reworded. --- src/blocks/scratch3_pen.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index 7389035dd..bac25ec3e 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -375,7 +375,7 @@ class Scratch3PenBlocks { } /** - * The pen "change pen transparency by {number}" block changes the "transparency" of the pen, related to the RGB value. + * The pen "change pen transparency by {number}" block changes the RGBA "transparency" of the pen. * @param {object} args - the block arguments. * @property {number} TRANSPARENCY - the amount of desired transparency change. * @param {object} util - utility object provided by the runtime. @@ -383,12 +383,12 @@ class Scratch3PenBlocks { changePenTransparencyBy (args, util) { const penState = this._getPenState(util.target); - penState.penAttributes.color4f[3] = penState.penAttributes.color4f[3] + (args.TRANSPARENCY / 255); + penState.penAttributes.color4f[3] = penState.penAttributes.color4f[3] + (args.TRANSPARENCY / 100); this._updatePenColor(penState); } /** - * The pen "set pen transparency to {number}" block sets the "transparency" of the pen, related to the RGB value. + * The pen "set pen transparency to {number}" block sets the RGBA "transparency" of the pen. * @param {object} args - the block arguments. * @property {number} TRANSPARENCY - the amount of desired transparency change. * @param {object} util - utility object provided by the runtime. @@ -396,7 +396,7 @@ class Scratch3PenBlocks { setPenTransparencyTo (args, util) { const penState = this._getPenState(util.target); - penState.penAttributes.color4f[3] = args.TRANSPARENCY / 255; + penState.penAttributes.color4f[3] = args.TRANSPARENCY / 100; this._updatePenColor(penState); } } From 5f5f7b16844620ae6495b0664ee376baef7c58e9 Mon Sep 17 00:00:00 2001 From: DD Date: Wed, 30 Aug 2017 14:23:03 -0400 Subject: [PATCH 004/272] add get svg function --- src/virtual-machine.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 762ef8c01..07ce65e10 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -340,6 +340,20 @@ class VirtualMachine extends EventEmitter { return null; } + /** + * Get an SVG string from the renderer. + * @param {int} costumeIndex - the index of the sound to be got. + * @return {string} the costume's SVG string, or null if it's not an SVG costume. + */ + getCostumeSVG (costumeIndex) { + const id = this.editingTarget.sprite.costumes[costumeIndex].assetId; + if (id && this.runtime && this.runtime.storage && + this.runtime.storage.get(id).dataFormat === 'svg') { + return this.runtime.storage.get(id).decodeText(); + } + return null; + } + /** * Update a sound buffer. * @param {int} soundIndex - the index of the sound to be updated. From f61366643d7e36eb80ecd2d946a4a7c8bfbf9714 Mon Sep 17 00:00:00 2001 From: Ken Date: Thu, 31 Aug 2017 09:24:41 +0800 Subject: [PATCH 005/272] Clamp transparency value (at least for set) --- src/blocks/scratch3_pen.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index bac25ec3e..91eaf2909 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -382,8 +382,8 @@ class Scratch3PenBlocks { */ changePenTransparencyBy (args, util) { const penState = this._getPenState(util.target); - - penState.penAttributes.color4f[3] = penState.penAttributes.color4f[3] + (args.TRANSPARENCY / 100); + const TRANSPARENCY = args.TRANSPARENCY / 100; + penState.penAttributes.color4f[3] = penState.penAttributes.color4f[3] + TRANSPARENCY; this._updatePenColor(penState); } @@ -395,8 +395,8 @@ class Scratch3PenBlocks { */ setPenTransparencyTo (args, util) { const penState = this._getPenState(util.target); - - penState.penAttributes.color4f[3] = args.TRANSPARENCY / 100; + const TRANSPARENCY = MathUtil.clamp(args.TRANSPARENCY, 0, 100) / 100; + penState.penAttributes.color4f[3] = TRANSPARENCY; this._updatePenColor(penState); } } From e5208445ac6adf5d5dc655f4b8ea9782c88cf3d6 Mon Sep 17 00:00:00 2001 From: DD Date: Wed, 30 Aug 2017 18:42:44 -0400 Subject: [PATCH 006/272] Add updateSVG to tell the renderer about the updated drawing --- src/virtual-machine.js | 48 ++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 07ce65e10..07b0a5058 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -340,20 +340,6 @@ class VirtualMachine extends EventEmitter { return null; } - /** - * Get an SVG string from the renderer. - * @param {int} costumeIndex - the index of the sound to be got. - * @return {string} the costume's SVG string, or null if it's not an SVG costume. - */ - getCostumeSVG (costumeIndex) { - const id = this.editingTarget.sprite.costumes[costumeIndex].assetId; - if (id && this.runtime && this.runtime.storage && - this.runtime.storage.get(id).dataFormat === 'svg') { - return this.runtime.storage.get(id).decodeText(); - } - return null; - } - /** * Update a sound buffer. * @param {int} soundIndex - the index of the sound to be updated. @@ -375,6 +361,40 @@ class VirtualMachine extends EventEmitter { this.editingTarget.deleteSound(soundIndex); } + /** + * Get an SVG string from the renderer. + * @param {int} costumeIndex - the index of the sound to be got. + * @return {string} the costume's SVG string, or null if it's not an SVG costume. + */ + getCostumeSvg (costumeIndex) { + const id = this.editingTarget.sprite.costumes[costumeIndex].assetId; + if (id && this.runtime && this.runtime.storage && + this.runtime.storage.get(id).dataFormat === 'svg') { + return this.runtime.storage.get(id).decodeText(); + } + return null; + } + + /** + * Update a costume with the given SVG + * @param {int} costumeIndex - the index of the costume to be updated. + * @param {string} svg - new SVG for the renderer. + */ + updateSvg (costumeIndex, svg) { + const costume = this.editingTarget.sprite.costumes[costumeIndex]; + if (costume && this.runtime && this.runtime.renderer) { + const rotationCenter = [ + costume.rotationCenterX / costume.bitmapResolution, + costume.rotationCenterY / costume.bitmapResolution + ]; + + this.runtime.renderer.updateSVGSkin(costume.skinId, svg, rotationCenter); + } + // TODO: Also update storage in addition to renderer. Without storage, if you switch + // costumes and switch back, you will lose your changes in the paint editor. + // TODO: emitTargetsUpdate if we need to update the storage ID on the updated costume; + } + /** * Add a backdrop to the stage. * @param {string} md5ext - the MD5 and extension of the backdrop to be loaded. From 7d3b9a866c722344ae1c92c91ffb3aeee5d4a991 Mon Sep 17 00:00:00 2001 From: DD Date: Thu, 31 Aug 2017 11:47:07 -0400 Subject: [PATCH 007/272] Fix comment --- src/virtual-machine.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 07b0a5058..f6567066f 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -362,7 +362,7 @@ class VirtualMachine extends EventEmitter { } /** - * Get an SVG string from the renderer. + * Get an SVG string from storage. * @param {int} costumeIndex - the index of the sound to be got. * @return {string} the costume's SVG string, or null if it's not an SVG costume. */ @@ -392,7 +392,7 @@ class VirtualMachine extends EventEmitter { } // TODO: Also update storage in addition to renderer. Without storage, if you switch // costumes and switch back, you will lose your changes in the paint editor. - // TODO: emitTargetsUpdate if we need to update the storage ID on the updated costume; + // TODO: emitTargetsUpdate if we need to update the storage ID on the updated costume. } /** From 5606b067e590704772a4a7d7570b4d7ff28388cf Mon Sep 17 00:00:00 2001 From: DD Date: Thu, 31 Aug 2017 13:41:47 -0400 Subject: [PATCH 008/272] More comment fixes --- src/virtual-machine.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index f6567066f..61afda386 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -363,7 +363,7 @@ class VirtualMachine extends EventEmitter { /** * Get an SVG string from storage. - * @param {int} costumeIndex - the index of the sound to be got. + * @param {int} costumeIndex - the index of the costume to be got. * @return {string} the costume's SVG string, or null if it's not an SVG costume. */ getCostumeSvg (costumeIndex) { @@ -390,9 +390,9 @@ class VirtualMachine extends EventEmitter { this.runtime.renderer.updateSVGSkin(costume.skinId, svg, rotationCenter); } - // TODO: Also update storage in addition to renderer. Without storage, if you switch + // @todo: Also update storage in addition to renderer. Without storage, if you switch // costumes and switch back, you will lose your changes in the paint editor. - // TODO: emitTargetsUpdate if we need to update the storage ID on the updated costume. + // @todo: emitTargetsUpdate if we need to update the storage ID on the updated costume. } /** From 3185eb27e15fc230796b8ebcb1099ed1d3140b00 Mon Sep 17 00:00:00 2001 From: Ken Date: Fri, 1 Sep 2017 14:11:09 +0800 Subject: [PATCH 009/272] Rewrote transparency block Wrapping of the value is now handled by a new function, _wrapTransparency; _updatePenColor now handles the transparency value; DEFAULT_PEN_STATE now includes a transparency value (100). --- src/blocks/scratch3_pen.js | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index 91eaf2909..273368e7c 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -55,6 +55,7 @@ class Scratch3PenBlocks { penDown: false, hue: 120, shade: 50, + transparency: 100, penAttributes: { color4f: [0, 0, 1, 1], diameter: 1 @@ -183,11 +184,11 @@ class Scratch3PenBlocks { penState.penAttributes.color4f[0] = rgb.r / 255.0; penState.penAttributes.color4f[1] = rgb.g / 255.0; penState.penAttributes.color4f[2] = rgb.b / 255.0; - penState.penAttributes.color4f[3] = 1; + penState.penAttributes.color4f[3] = penState.transparency / 100.0; } /** - * Wrap a pen hue or shade values to the range [0,200). + * Wrap a pen hue or shade values to the range (0,200). * @param {number} value - the pen hue or shade value to the proper range. * @returns {number} the wrapped value. * @private @@ -197,6 +198,18 @@ class Scratch3PenBlocks { if (value < 0) value += 200; return value; } + + /** + * Wrap a pen transparency value to the range (0, 100). + * @param {number} value - the pen transparency value to the proper range. + * @returns {number} the wrapped value. + * @private + */ + _wrapTransparency (value) { + value = value % 100; + if (value < 0) value += 100; + return value; + } /** * Retrieve the block primitives implemented by this package. @@ -382,8 +395,7 @@ class Scratch3PenBlocks { */ changePenTransparencyBy (args, util) { const penState = this._getPenState(util.target); - const TRANSPARENCY = args.TRANSPARENCY / 100; - penState.penAttributes.color4f[3] = penState.penAttributes.color4f[3] + TRANSPARENCY; + penState.transparency = this._wrapTransparency(penState.transparency + Cast.toNumber(args.TRANSPARENCY)); this._updatePenColor(penState); } @@ -395,8 +407,7 @@ class Scratch3PenBlocks { */ setPenTransparencyTo (args, util) { const penState = this._getPenState(util.target); - const TRANSPARENCY = MathUtil.clamp(args.TRANSPARENCY, 0, 100) / 100; - penState.penAttributes.color4f[3] = TRANSPARENCY; + penState.transparency = this._wrapTransparency(Cast.toNumber(args.TRANSPARENCY)); this._updatePenColor(penState); } } From 29540e705e2a42674fd2d8a6be080e3115c820c5 Mon Sep 17 00:00:00 2001 From: DD Date: Tue, 5 Sep 2017 16:51:03 -0400 Subject: [PATCH 010/272] Add updating the rotation center to updateSvg --- src/virtual-machine.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 61afda386..04409b3b0 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -380,15 +380,12 @@ class VirtualMachine extends EventEmitter { * @param {int} costumeIndex - the index of the costume to be updated. * @param {string} svg - new SVG for the renderer. */ - updateSvg (costumeIndex, svg) { + updateSvg (costumeIndex, svg, rotationCenterX, rotationCenterY) { const costume = this.editingTarget.sprite.costumes[costumeIndex]; + costume.rotationCenterX = rotationCenterX; + costume.rotationCenterY = rotationCenterY; if (costume && this.runtime && this.runtime.renderer) { - const rotationCenter = [ - costume.rotationCenterX / costume.bitmapResolution, - costume.rotationCenterY / costume.bitmapResolution - ]; - - this.runtime.renderer.updateSVGSkin(costume.skinId, svg, rotationCenter); + this.runtime.renderer.updateSVGSkin(costume.skinId, svg, [rotationCenterX, rotationCenterY]); } // @todo: Also update storage in addition to renderer. Without storage, if you switch // costumes and switch back, you will lose your changes in the paint editor. From 48fec12391126d1e535d8a4bb8813a1652820a73 Mon Sep 17 00:00:00 2001 From: DD Date: Tue, 5 Sep 2017 17:49:30 -0400 Subject: [PATCH 011/272] add jsdoc --- src/virtual-machine.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 04409b3b0..45a2de167 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -379,6 +379,8 @@ class VirtualMachine extends EventEmitter { * Update a costume with the given SVG * @param {int} costumeIndex - the index of the costume to be updated. * @param {string} svg - new SVG for the renderer. + * @param {number} rotationCenterX x of point about which the costume rotates, relative to its upper left corner + * @param {number} rotationCenterY y of point about which the costume rotates, relative to its upper left corner */ updateSvg (costumeIndex, svg, rotationCenterX, rotationCenterY) { const costume = this.editingTarget.sprite.costumes[costumeIndex]; From caf98cb185e876737afd0cc09fd23781e7c804ef Mon Sep 17 00:00:00 2001 From: DD Date: Tue, 5 Sep 2017 17:53:27 -0400 Subject: [PATCH 012/272] change order --- src/virtual-machine.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 45a2de167..6e16ef90a 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -384,9 +384,9 @@ class VirtualMachine extends EventEmitter { */ updateSvg (costumeIndex, svg, rotationCenterX, rotationCenterY) { const costume = this.editingTarget.sprite.costumes[costumeIndex]; - costume.rotationCenterX = rotationCenterX; - costume.rotationCenterY = rotationCenterY; if (costume && this.runtime && this.runtime.renderer) { + costume.rotationCenterX = rotationCenterX; + costume.rotationCenterY = rotationCenterY; this.runtime.renderer.updateSVGSkin(costume.skinId, svg, [rotationCenterX, rotationCenterY]); } // @todo: Also update storage in addition to renderer. Without storage, if you switch From 58eaeaaf6aea86fcfb5cebdf1dc965d8cf72d2be Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 5 Sep 2017 18:00:34 -0400 Subject: [PATCH 013/272] Add pen transparency, clamped 0-100 --- src/blocks/scratch3_pen.js | 54 +++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index 5755af78b..b2f7d4b6d 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -55,7 +55,7 @@ class Scratch3PenBlocks { penDown: false, hue: 120, shade: 50, - transparency: 100, + transparency: 0, penAttributes: { color4f: [0, 0, 1, 1], diameter: 1 @@ -169,7 +169,8 @@ class Scratch3PenBlocks { } /** - * Update the cached RGB color from the hue & shade values in the provided PenState object. + * Update the cached color from the hue, shade and transparency values in the provided + * PenState object. * @param {PenState} penState - the pen state to update. * @private */ @@ -184,7 +185,7 @@ class Scratch3PenBlocks { penState.penAttributes.color4f[0] = rgb.r / 255.0; penState.penAttributes.color4f[1] = rgb.g / 255.0; penState.penAttributes.color4f[2] = rgb.b / 255.0; - penState.penAttributes.color4f[3] = penState.transparency / 100.0; + penState.penAttributes.color4f[3] = this._transparencyToAlpha(penState.transparency); } /** @@ -198,17 +199,39 @@ class Scratch3PenBlocks { if (value < 0) value += 200; return value; } - + /** - * Wrap a pen transparency value to the range (0, 100). - * @param {number} value - the pen transparency value to the proper range. - * @returns {number} the wrapped value. + * Clamp a pen transparency value to the range (0,100). + * @param {number} value - the pen transparency value to be clamped. + * @returns {number} the clamped value. * @private */ - _wrapTransparency (value) { - value = value % 100; - if (value < 0) value += 100; - return value; + _clampTransparency (value) { + return MathUtil.clamp(value, 0, 100); + } + + /** + * Convert an alpha value to a pen transparency value. + * Alpha ranges from 0 to 1, where 0 is transparent and 1 is opaque. + * Transparency ranges from 0 to 100, where 0 is opaque and 100 is transparent. + * @param {number} alpha - the input alpha value. + * @returns {number} the transparency value. + * @private + */ + _alphaToTransparency (alpha) { + return (1.0 - alpha) * 100.0; + } + + /** + * Convert a pen transparency value to an alpha value. + * Alpha ranges from 0 to 1, where 0 is transparent and 1 is opaque. + * Transparency ranges from 0 to 100, where 0 is opaque and 100 is transparent. + * @param {number} transparency - the input transparency value. + * @returns {number} the alpha value. + * @private + */ + _transparencyToAlpha (transparency) { + return 1.0 - (transparency / 100.0); } /** @@ -315,6 +338,7 @@ class Scratch3PenBlocks { } else { penState.penAttributes.color4f[3] = 1; } + penState.transparency = this._alphaToTransparency(penState.penAttributes.color4f[3]); } /** @@ -386,7 +410,7 @@ class Scratch3PenBlocks { const penAttributes = this._getPenState(util.target).penAttributes; penAttributes.diameter = this._clampPenSize(Cast.toNumber(args.SIZE)); } - + /** * The pen "change pen transparency by {number}" block changes the RGBA "transparency" of the pen. * @param {object} args - the block arguments. @@ -395,10 +419,10 @@ class Scratch3PenBlocks { */ changePenTransparencyBy (args, util) { const penState = this._getPenState(util.target); - penState.transparency = this._wrapTransparency(penState.transparency + Cast.toNumber(args.TRANSPARENCY)); + penState.transparency = this._clampTransparency(penState.transparency + Cast.toNumber(args.TRANSPARENCY)); this._updatePenColor(penState); } - + /** * The pen "set pen transparency to {number}" block sets the RGBA "transparency" of the pen. * @param {object} args - the block arguments. @@ -407,7 +431,7 @@ class Scratch3PenBlocks { */ setPenTransparencyTo (args, util) { const penState = this._getPenState(util.target); - penState.transparency = this._wrapTransparency(Cast.toNumber(args.TRANSPARENCY)); + penState.transparency = this._clampTransparency(Cast.toNumber(args.TRANSPARENCY)); this._updatePenColor(penState); } } From 7fb7f0dc7bdae472f4e627611f9f36d3bb29b0fc Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Fri, 14 Jul 2017 15:37:59 -0400 Subject: [PATCH 014/272] WIP Extension Manager When asked to load an extension, the Extension Manager starts up a new Worker. That worker runs the message dispatch system as well as an instance of the new `ExtensionWorker` class, which will load the desired extension and register it with the extension system. Extensions, placed in `./src/extensions/*.js`, are now processed by Webpack as separate entry points and packed into an `extensions` subdirectory in the output. Still to do: query an extension's information, including the blocks it provides, and register that information with the VM, GUI, etc. --- package.json | 3 +- src/extension-support/extension-manager.js | 45 +++++ src/extension-support/extension-worker.js | 38 +++++ src/extensions/.eslintrc.js | 8 + src/extensions/example-extension.js | 183 +++++++++++++++++++++ webpack.config.js | 19 ++- 6 files changed, 289 insertions(+), 7 deletions(-) create mode 100644 src/extension-support/extension-manager.js create mode 100644 src/extension-support/extension-worker.js create mode 100644 src/extensions/.eslintrc.js create mode 100644 src/extensions/example-extension.js diff --git a/package.json b/package.json index 10535ef70..2dac26a58 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "tap": "^10.2.0", "tiny-worker": "^2.1.1", "webpack": "^2.4.1", - "webpack-dev-server": "^2.4.1" + "webpack-dev-server": "^2.4.1", + "worker-loader": "0.8.1" } } diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js new file mode 100644 index 000000000..a5b28147e --- /dev/null +++ b/src/extension-support/extension-manager.js @@ -0,0 +1,45 @@ +const centralDispatch = require('../dispatch/central-dispatch'); + +class ExtensionManager { + constructor () { + /** + * The list of current active extension workers. + * @type {Array.} + */ + this.workers = []; + + /** + * The ID number to provide to the next extension worker. + * @type {int} + */ + this.nextExtensionWorker = 0; + + /** + * The list of extension URLs which have been requested but not yet loaded in a worker. + * @type {Array} + */ + this.pendingExtensionURLs = []; + + centralDispatch.setService('extensions', this); + } + + foo () { + this.loadExtensionURL('extensions/example-extension.js'); + } + + loadExtensionURL (extensionURL) { + // If we `require` this at the global level it breaks non-webpack targets, including tests + const ExtensionWorker = require('worker-loader!./extension-worker'); + + this.pendingExtensionURLs.push(extensionURL); + centralDispatch.addWorker(new ExtensionWorker()); + } + + allocateWorker () { + const id = this.nextExtensionWorker++; + const extFile = this.pendingExtensionURLs.shift(); + return [id, extFile]; + } +} + +module.exports = ExtensionManager; diff --git a/src/extension-support/extension-worker.js b/src/extension-support/extension-worker.js new file mode 100644 index 000000000..aec133baf --- /dev/null +++ b/src/extension-support/extension-worker.js @@ -0,0 +1,38 @@ +/* eslint-env worker */ + +const dispatch = require('../dispatch/worker-dispatch'); + +class ExtensionWorker { + constructor () { + this.nextExtensionId = 0; + + dispatch.waitForConnection.then(() => { + dispatch.call('extensions', 'allocateWorker').then(x => { + const [id, extension] = x; + this.workerId = id; + + // TODO: catch and report any exceptions here + importScripts(extension); + }); + }); + + this.extensions = []; + } + + register (extensionObject) { + const extensionId = this.nextExtensionId++; + this.extensions.push(extensionObject); + dispatch.setService(`extension.${this.workerId}.${extensionId}`, extensionObject); + } +} + +const extensionWorker = new ExtensionWorker(); + +global.Scratch = global.Scratch || {}; + +/** + * Expose only specific parts of the worker to extensions. + */ +global.Scratch.extensions = { + register: extensionWorker.register.bind(extensionWorker) +}; diff --git a/src/extensions/.eslintrc.js b/src/extensions/.eslintrc.js new file mode 100644 index 000000000..f84dadeb6 --- /dev/null +++ b/src/extensions/.eslintrc.js @@ -0,0 +1,8 @@ +module.exports = { + env: { + worker: true + }, + globals: { + Scratch: true + } +}; diff --git a/src/extensions/example-extension.js b/src/extensions/example-extension.js new file mode 100644 index 000000000..cc9312ab1 --- /dev/null +++ b/src/extensions/example-extension.js @@ -0,0 +1,183 @@ +class ExampleExtension { + /** + * @return {object} This extension's metadata. + */ + getInfo () { + return { + // Required: the machine-readable name of this extension. + // Will be used as the extension's namespace. + id: 'someBlocks', + + // Optional: the human-readable name of this extension as string. + // This and any other string to be displayed in the Scratch UI may either be + // a string or a call to `intlDefineMessage`; a plain string will not be + // translated whereas a call to `intlDefineMessage` will connect the string + // to the translation map (see below). The `intlDefineMessage` call is + // similar to `defineMessages` from `react-intl` in form, but will actually + // call some extension support code to do its magic. For example, we will + // internally namespace the messages such that two extensions could have + // messages with the same ID without colliding. + // See also: https://github.com/yahoo/react-intl/wiki/API#definemessages + name: 'Some Blocks', + + // Optional: URI for an icon for this extension. Data URI OK. + // If not present, use a generic icon. + // TODO: what file types are OK? All web images? Just PNG? + iconURI: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAFCAAAAACyOJm3AAAAFklEQVQYV2P4DwMMEMgAI/+DE' + + 'UIMBgAEWB7i7uidhAAAAABJRU5ErkJggg==', + + // Optional: Link to documentation content for this extension. + // If not present, offer no link. + docsURI: 'https://....', + + // Required: the list of blocks implemented by this extension, + // in the order intended for display. + blocks: [ + { + // Required: the machine-readable name of this operation. + // This will appear in project JSON. + opcode: 'myReporter', // becomes 'someBlocks.myReporter' + + // Required: the kind of block we're defining, from a predefined list: + // 'command' - a normal command block, like "move {} steps" + // 'reporter' - returns a value, like "direction" + // 'Boolean' - same as 'reporter' but returns a Boolean value + // 'hat' - starts a stack if its value is truthy + // 'conditional' - control flow, like "if {}" or "repeat {}" + // A 'conditional' block may return the one-based index of a branch + // to run, or it may return zero/falsy to run no branch. Each time a + // child branch finishes, the block is called again. This is only a + // slight change to the current model for control flow blocks, and is + // also compatible with returning true/false for an "if" or "repeat" + // block. + // TODO: Consider Blockly-like nextStatement, previousStatement, and + // output attributes as an alternative. Those are more flexible, but + // allow bad combinations. + blockType: 'reporter', + + // Required for conditional blocks, ignored for others: the number of + // child branches this block controls. An "if" or "repeat" block would + // specify a branch count of 1; an "if-else" block would specify a + // branch count of 2. + // TODO: should we support dynamic branch count for "switch"-likes? + branchCount: 0, + + // Optional, default false: whether or not this block ends a stack. + // The "forever" and "stop all" blocks would specify true here. + terminal: true, + + // Optional, default false: whether or not to block all threads while + // this block is busy. This is for things like the "touching color" + // block in compatibility mode, and is only needed if the VM runs in a + // worker. We might even consider omitting it from extension docs... + blockAllThreads: false, + + // Required: the human-readable text on this block, including argument + // placeholders. Argument placeholders should be in [MACRO_CASE] and + // must be [ENCLOSED_WITHIN_SQUARE_BRACKETS]. + text: 'letter [LETTER_NUM] of [TEXT]', + + // Required: describe each argument. + // Note that this is an array: the order of arguments will be used + arguments: { + // Required: the ID of the argument, which will be the name in the + // args object passed to the implementation function. + LETTER_NUM: { + // Required: type of the argument / shape of the block input + type: 'number', + + // Optional: the default value of the argument + default: 1 + }, + + // Required: the ID of the argument, which will be the name in the + // args object passed to the implementation function. + TEXT: { + // Required: type of the argument / shape of the block input + type: 'string', + + // Optional: the default value of the argument + default: 'text' + } + }, + + // Required: the function implementing this block. + func: this.myReporter, + + // Optional: list of target types for which this block should appear. + // If absent, assume it applies to all builtin targets -- that is: + // ['sprite', 'stage'] + filter: ['someBlocks.wedo2', 'sprite', 'stage'] + }, + { + // Another block... + } + ], + + // Optional: define extension-specific menus here. + menus: { + // Required: an identifier for this menu, unique within this extension. + menuA: [ + // Static menu: list items which should appear in the menu. + { + // Required: the value of the menu item when it is chosen. + value: 'itemId1', + + // Optional: the human-readable label for this item. + // Use `value` as the text if this is absent. + text: 'Item One' + }, + + // The simplest form of a list item is a string which will be used as + // both value and text. + 'itemId2' + ], + + // Dynamic menu: returns an array as above. + // Called each time the menu is opened. + menuB: this.getItemsForMenuB + }, + + // Optional: translations + translation_map: { + de: { + 'extensionName': 'Einige Blöcke', + 'myReporter': 'Buchstabe [LETTER_NUM] von [TEXT]', + 'myReporter.TEXT_default': 'Text', + 'menuA_item1': 'Artikel eins', + + // Dynamic menus can be translated too + 'menuB_example': 'Beispiel', + + // This message contains ICU placeholders (see `myReporter()` below) + 'myReporter.result': 'Buchstabe {LETTER_NUM} von {TEXT} ist {LETTER}.' + }, + it: { + // ... + } + }, + + // Optional: list new target type(s) provided by this extension. + targetTypes: [ + 'wedo2', // automatically transformed to 'someBlocks.wedo2' + 'speech' // automatically transformed to 'someBlocks.speech' + ] + }; + } + + /** + * Implement myReporter. + * @param {object} args - the block's arguments. + * @property {number} LETTER_NUM - the string value of the argument. + * @property {string} TEXT - the string value of the argument. + * @returns {string} a string which includes the block argument value. + */ + myReporter (args) { + // Note: this implementation is not Unicode-clean; it's just here as an example. + const result = args.TEXT.charAt(args.LETTER_NUM); + + return ['Letter ', args.LETTER_NUM, ' of ', args.TEXT, ' is ', result, '.'].join(''); + } +} + +Scratch.extensions.register(new ExampleExtension()); diff --git a/webpack.config.js b/webpack.config.js index 571256800..d741b787c 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,8 +1,15 @@ const CopyWebpackPlugin = require('copy-webpack-plugin'); const defaultsDeep = require('lodash.defaultsdeep'); +const glob = require('glob'); const path = require('path'); const webpack = require('webpack'); +const extensionEntries = glob.sync('./src/extensions/*.js').reduce((bag, extensionPath) => { + const nameWithoutExtension = path.basename(extensionPath).replace(/\.[^/.]+$/, ''); + bag[`extensions/${nameWithoutExtension}`] = extensionPath; + return bag; +}, {}); + const base = { devServer: { contentBase: false, @@ -32,10 +39,10 @@ module.exports = [ // Web-compatible defaultsDeep({}, base, { target: 'web', - entry: { + entry: defaultsDeep({}, extensionEntries, { 'scratch-vm': './src/index.js', 'scratch-vm.min': './src/index.js' - }, + }), output: { path: path.resolve(__dirname, 'dist/web'), filename: '[name].js' @@ -52,9 +59,9 @@ module.exports = [ // Node-compatible defaultsDeep({}, base, { target: 'node', - entry: { + entry: defaultsDeep({}, extensionEntries, { 'scratch-vm': './src/index.js' - }, + }), output: { library: 'VirtualMachine', libraryTarget: 'commonjs2', @@ -65,7 +72,7 @@ module.exports = [ // Playground defaultsDeep({}, base, { target: 'web', - entry: { + entry: defaultsDeep({}, extensionEntries, { 'scratch-vm': './src/index.js', 'vendor': [ // FPS counter @@ -81,7 +88,7 @@ module.exports = [ // Storage 'scratch-storage' ] - }, + }), output: { path: path.resolve(__dirname, 'playground'), filename: '[name].js' From 42255bbcfa0fe5c9aa3b52f7e969b9c798ed18cf Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Fri, 21 Jul 2017 13:46:08 -0700 Subject: [PATCH 015/272] Collect extension info, prep scratch-blocks data The Extension Manager now calls an extension's `getInfo` method, then creates `scratch-blocks`-compatible XML and JSON block data from the results. --- src/extension-support/argument-type.js | 7 + src/extension-support/block-type.js | 9 + src/extension-support/extension-manager.js | 234 +++++++++++++++++++++ src/extension-support/extension-worker.js | 11 +- src/extensions/example-extension.js | 21 +- src/index.js | 7 + 6 files changed, 276 insertions(+), 13 deletions(-) create mode 100644 src/extension-support/argument-type.js create mode 100644 src/extension-support/block-type.js diff --git a/src/extension-support/argument-type.js b/src/extension-support/argument-type.js new file mode 100644 index 000000000..3fccff5ef --- /dev/null +++ b/src/extension-support/argument-type.js @@ -0,0 +1,7 @@ +const ArgumentType = { + NUMBER: 'number', + STRING: 'string', + BOOLEAN: 'Boolean' +}; + +module.exports = ArgumentType; diff --git a/src/extension-support/block-type.js b/src/extension-support/block-type.js new file mode 100644 index 000000000..663e2e3e3 --- /dev/null +++ b/src/extension-support/block-type.js @@ -0,0 +1,9 @@ +const BlockType = { + COMMAND: 'command', + REPORTER: 'reporter', + BOOLEAN: 'Boolean', + HAT: 'hat', + CONDITIONAL: 'conditional' +}; + +module.exports = BlockType; diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index a5b28147e..1c01c69f2 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -1,4 +1,56 @@ const centralDispatch = require('../dispatch/central-dispatch'); +const log = require('../util/log'); + +const ArgumentType = require('./argument-type'); +const BlockType = require('./block-type'); +const ScratchBlocks = require('scratch-blocks'); + +/** + * @typedef {object} ArgumentInfo - Information about an extension block argument + * @property {ArgumentType} type - the type of value this argument can take + * @property {*|undefined} default - the default value of this argument (default: blank) + */ + +/** + * @typedef {object} BlockInfo - Information about an extension block + * @property {string} opcode - the block opcode + * @property {string|object} text - the human-readable text on this block + * @property {BlockType|undefined} blockType - the type of block (default: BlockType.COMMAND) + * @property {int|undefined} branchCount - the number of branches this block controls, if conditional (default: 0) + * @property {Boolean|undefined} isTerminal - true if this block ends a stack (default: false) + * @property {Boolean|undefined} blockAllThreads - true if all threads must wait for this block to run (default: false) + * @property {object.|undefined} arguments - information about this block's arguments, if any + * @property {string|undefined} func - the method implementing this block on the extension service (default: opcode) + * @property {Array.|undefined} filter - the list of targets for which this block should appear (default: all) + */ + +/** + * @typedef {object} CategoryInfo - Information about a block category + * @property {string} id - the unique ID of this category + * @property {string} color1 - the primary color for this category, in '#rrggbb' format + * @property {string} color2 - the secondary color for this category, in '#rrggbb' format + * @property {string} color3 - the tertiary color for this category, in '#rrggbb' format + */ + +/** + * Information used for converting Scratch argument types into scratch-blocks data. + * @type {object.}} + */ +const ArgumentTypeMap = (() => { + const map = {}; + map[ArgumentType.NUMBER] = { + shadowType: 'math_number', + fieldType: 'NUM' + }; + map[ArgumentType.STRING] = { + shadowType: 'text', + fieldType: 'TEXT' + }; + map[ArgumentType.BOOLEAN] = { + shadowType: '' + }; + return map; +})(); class ExtensionManager { constructor () { @@ -40,6 +92,188 @@ class ExtensionManager { const extFile = this.pendingExtensionURLs.shift(); return [id, extFile]; } + + registerExtensionService (serviceName) { + centralDispatch.call(serviceName, 'getInfo').then(info => { + this._registerExtensionInfo(serviceName, info); + }); + } + + _registerExtensionInfo (serviceName, extensionInfo) { + const categoryInfo = { + id: extensionInfo.id, + name: extensionInfo.name, + color1: '#FF6680', + color2: '#FF4D6A', + color3: '#FF3355' + }; + extensionInfo = this._sanitizeExtensionInfo(extensionInfo); + for (let blockInfo of extensionInfo.blocks) { + if (!(blockInfo.opcode && blockInfo.text)) { + log.error(`Ignoring malformed extension block: ${JSON.stringify(blockInfo)}`); + continue; + } + blockInfo = this._sanitizeBlockInfo(blockInfo); + const convertedBlock = this._convertForScratchBlocks(blockInfo, serviceName, categoryInfo); + console.dir(convertedBlock); + } + } + + /** + * Modify the provided text as necessary to ensure that it may be used as an attribute value in valid XML. + * @param {string} text - the text to be sanitized + * @returns {string} - the sanitized text + * @private + */ + _sanitizeID (text) { + return text.toString().replace(/[<"&]/, '_'); + } + + /** + * Apply minor cleanup and defaults for optional extension fields. + * TODO: make the ID unique in cases where two copies of the same extension are loaded. + * @param {ExtensionInfo} extensionInfo - the extension info to be sanitized + * @returns {ExtensionInfo} - a new extension info object with cleaned-up values + * @private + */ + _sanitizeExtensionInfo (extensionInfo) { + extensionInfo = Object.assign({}, extensionInfo); + extensionInfo.id = this._sanitizeID(extensionInfo.id); + extensionInfo.name = extensionInfo.name || extensionInfo.id; + extensionInfo.blocks = extensionInfo.blocks || []; + extensionInfo.targetTypes = extensionInfo.targetTypes || []; + return extensionInfo; + } + + /** + * Apply defaults for optional block fields. + * @param {BlockInfo} blockInfo - the block info from the extension + * @returns {BlockInfo} - a new block info object which has values for all relevant optional fields. + * @private + */ + _sanitizeBlockInfo (blockInfo) { + blockInfo = Object.assign({}, { + blockType: BlockType.COMMAND, + terminal: false, + blockAllThreads: false, + arguments: {} + }, blockInfo); + blockInfo.opcode = this._sanitizeID(blockInfo.opcode); + blockInfo.func = blockInfo.func ? this._sanitizeID(blockInfo.func) : blockInfo.opcode; + return blockInfo; + } + + /** + * Convert BlockInfo into scratch-blocks JSON & XML, and generate a proxy function. + * @param {BlockInfo} blockInfo - the block to convert + * @param {string} serviceName - the name of the service hosting this extension + * @param {CategoryInfo} categoryInfo - the category for this block + * @returns {{json: object, xml: string, blockFunction: Function}} - the converted block information + * @private + */ + _convertForScratchBlocks (blockInfo, serviceName, categoryInfo) { + const extendedOpcode = `${categoryInfo.id}.${blockInfo.opcode}`; + const blockJSON = { + id: extendedOpcode, + inputsInline: true, + previousStatement: null, // null = available connection; undefined = hat block + nextStatement: null, // null = available connection; undefined = terminal + category: categoryInfo.name, + colour: categoryInfo.color1, + colourSecondary: categoryInfo.color2, + colorTertiary: categoryInfo.color3, + args0: [] + }; + + const inputList = []; + + // TODO: store this somewhere so that we can map args appropriately after translation. + // This maps an arg name to its relative position in the original (usually English) block text. + // When displaying a block in another language we'll need to run a `replace` action similar to the one below, + // but each `[ARG]` will need to be replaced with the number in this map instead of `args0.length`. + const argsMap = {}; + + blockJSON.message0 = blockInfo.text.replace(/\[(.+?)]/g, (match, placeholder) => { + + // Sanitize the placeholder to ensure valid XML + placeholder = placeholder.replace(/[<"&]/, '_'); + + blockJSON.args0.push({ + type: 'input_value', + name: placeholder + }); + + // scratch-blocks uses 1-based argument indexing + const argNum = blockJSON.args0.length; + argsMap[placeholder] = argNum; + + const argInfo = blockInfo.arguments[placeholder] || {}; + const argTypeInfo = ArgumentTypeMap[argInfo.type] || {}; + const defaultValue = (typeof argInfo.defaultValue === 'undefined' ? '' : argInfo.defaultValue.toString()); + inputList.push( + `` + + `` + + `${defaultValue}` + + `` + + `` + ); + + return `%${argNum}`; + }); + + switch (blockInfo.blockType) { + case BlockType.COMMAND: + blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_SQUARE; + break; + case BlockType.REPORTER: + blockJSON.output = 'String'; // TODO: distinguish number & string here? + blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_ROUND; + break; + case BlockType.BOOLEAN: + blockJSON.output = 'Boolean'; + blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_HEXAGONAL; + break; + case BlockType.HAT: + blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_SQUARE; + delete blockJSON.previousStatement; + break; + case BlockType.CONDITIONAL: + // Statement inputs get names like 'SUBSTACK', 'SUBSTACK2', 'SUBSTACK3', ... + for (let branchNum = 1; branchNum <= blockInfo.branchCount; ++branchNum) { + blockJSON[`args${branchNum}`] = { + type: 'input_statement', + name: `SUBSTACK${branchNum > 1 ? branchNum : ''}` + }; + } + blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_SQUARE; + break; + } + + if (blockInfo.isTerminal) { + delete blockJSON.nextStatement; + } + + const blockXML = `${inputList.join('')}`; + + return { + json: blockJSON, + xml: blockXML, + blockFunction: this._extensionProxy.bind(this, serviceName, blockInfo.opcode) + }; + } + + /** + * Run an opcode by proxying the call to an extension service. + * @param {string} serviceName - the name of the service hosting the extension + * @param {string} opcode - the opcode to run, also the name of the method on the extension service + * @param {object} blockArgs - the arguments provided to the block + * @returns {Promise} - a promise which will resolve after the block function executes. If the block function + * returns a value, this promise will resolve to that value. + * @private + */ + _extensionProxy (serviceName, opcode, blockArgs) { + return centralDispatch.call(serviceName, opcode, blockArgs); + } } module.exports = ExtensionManager; diff --git a/src/extension-support/extension-worker.js b/src/extension-support/extension-worker.js index aec133baf..8c4a57410 100644 --- a/src/extension-support/extension-worker.js +++ b/src/extension-support/extension-worker.js @@ -1,5 +1,7 @@ /* eslint-env worker */ +const ArgumentType = require('../extension-support/argument-type'); +const BlockType = require('../extension-support/block-type'); const dispatch = require('../dispatch/worker-dispatch'); class ExtensionWorker { @@ -22,17 +24,20 @@ class ExtensionWorker { register (extensionObject) { const extensionId = this.nextExtensionId++; this.extensions.push(extensionObject); - dispatch.setService(`extension.${this.workerId}.${extensionId}`, extensionObject); + const serviceName = `extension.${this.workerId}.${extensionId}`; + return dispatch.setService(serviceName, extensionObject) + .then(() => dispatch.call('extensions', 'registerExtensionService', serviceName)); } } -const extensionWorker = new ExtensionWorker(); - global.Scratch = global.Scratch || {}; +global.Scratch.ArgumentType = ArgumentType; +global.Scratch.BlockType = BlockType; /** * Expose only specific parts of the worker to extensions. */ +const extensionWorker = new ExtensionWorker(); global.Scratch.extensions = { register: extensionWorker.register.bind(extensionWorker) }; diff --git a/src/extensions/example-extension.js b/src/extensions/example-extension.js index cc9312ab1..e983808f7 100644 --- a/src/extensions/example-extension.js +++ b/src/extensions/example-extension.js @@ -53,7 +53,7 @@ class ExampleExtension { // TODO: Consider Blockly-like nextStatement, previousStatement, and // output attributes as an alternative. Those are more flexible, but // allow bad combinations. - blockType: 'reporter', + blockType: Scratch.BlockType.REPORTER, // Required for conditional blocks, ignored for others: the number of // child branches this block controls. An "if" or "repeat" block would @@ -64,7 +64,7 @@ class ExampleExtension { // Optional, default false: whether or not this block ends a stack. // The "forever" and "stop all" blocks would specify true here. - terminal: true, + isTerminal: true, // Optional, default false: whether or not to block all threads while // this block is busy. This is for things like the "touching color" @@ -84,25 +84,26 @@ class ExampleExtension { // args object passed to the implementation function. LETTER_NUM: { // Required: type of the argument / shape of the block input - type: 'number', + type: Scratch.ArgumentType.NUMBER, // Optional: the default value of the argument - default: 1 + defaultValue: 1 }, // Required: the ID of the argument, which will be the name in the // args object passed to the implementation function. TEXT: { // Required: type of the argument / shape of the block input - type: 'string', + type: Scratch.ArgumentType.STRING, // Optional: the default value of the argument - default: 'text' + defaultValue: 'text' } }, - // Required: the function implementing this block. - func: this.myReporter, + // Optional: a string naming the function implementing this block. + // If this is omitted, use the opcode string. + func: 'myReporter', // Optional: list of target types for which this block should appear. // If absent, assume it applies to all builtin targets -- that is: @@ -133,9 +134,9 @@ class ExampleExtension { 'itemId2' ], - // Dynamic menu: returns an array as above. + // Dynamic menu: a string naming a function which returns an array as above. // Called each time the menu is opened. - menuB: this.getItemsForMenuB + menuB: 'getItemsForMenuB' }, // Optional: translations diff --git a/src/index.js b/src/index.js index dfb566329..f2d277902 100644 --- a/src/index.js +++ b/src/index.js @@ -1,3 +1,10 @@ const VirtualMachine = require('./virtual-machine'); +const CentralDispatch = require('./dispatch/central-dispatch'); +const ExtensionManager = require('./extension-support/extension-manager'); + +global.Scratch = global.Scratch || {}; +global.Scratch.dispatch = CentralDispatch; +global.Scratch.extensions = new ExtensionManager(); + module.exports = VirtualMachine; From 403adb743c83e6a848dfc8c3adc4d5dea20ebc98 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Fri, 4 Aug 2017 11:25:17 -0700 Subject: [PATCH 016/272] Track extension blocks in the Runtime --- src/engine/runtime.js | 157 +++++++++++++++++- src/extension-support/extension-manager.js | 183 +++------------------ src/extensions/example-extension.js | 4 +- src/virtual-machine.js | 12 ++ 4 files changed, 193 insertions(+), 163 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index a14f15469..773ef067e 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -1,9 +1,14 @@ const EventEmitter = require('events'); -const Sequencer = require('./sequencer'); -const Blocks = require('./blocks'); -const Thread = require('./thread'); const {OrderedMap} = require('immutable'); +const ScratchBlocks = require('scratch-blocks'); + +const ArgumentType = require('../extension-support/argument-type'); +const Blocks = require('./blocks'); +const BlockType = require('../extension-support/block-type'); +const Sequencer = require('./sequencer'); +const Thread = require('./thread'); + // Virtual I/O devices. const Clock = require('../io/clock'); const DeviceManager = require('../io/deviceManager'); @@ -24,6 +29,26 @@ const defaultBlockPackages = { scratch3_wedo2: require('../blocks/scratch3_wedo2') }; +/** + * Information used for converting Scratch argument types into scratch-blocks data. + * @type {object.}} + */ +const ArgumentTypeMap = (() => { + const map = {}; + map[ArgumentType.NUMBER] = { + shadowType: 'math_number', + fieldType: 'NUM' + }; + map[ArgumentType.STRING] = { + shadowType: 'text', + fieldType: 'TEXT' + }; + map[ArgumentType.BOOLEAN] = { + shadowType: '' + }; + return map; +})(); + /** * Manages targets, scripts, and the sequencer. * @constructor @@ -75,6 +100,13 @@ class Runtime extends EventEmitter { */ this._primitives = {}; + /** + * Map to look up all block information by extended opcode. + * @type {Object.} + * @private + */ + this._blockInfo = {}; + /** * Map to look up hat blocks' metadata. * Keys are opcode for hat, values are metadata objects. @@ -320,6 +352,125 @@ class Runtime extends EventEmitter { } } + /** + * Register the primitives provided by an extension. + * @param {ExtensionInfo} extensionInfo - information about the extension (id, blocks, etc.) + * @private + */ + _registerExtensionPrimitives (extensionInfo) { + const categoryInfo = { + id: extensionInfo.id, + name: extensionInfo.name, + color1: '#FF6680', + color2: '#FF4D6A', + color3: '#FF3355' + }; + + for (const blockInfo of extensionInfo.blocks) { + const convertedBlock = this._convertForScratchBlocks(blockInfo, categoryInfo); + const opcode = convertedBlock.json.id; + this._blockInfo[opcode] = convertedBlock; + this._primitives[opcode] = convertedBlock.info.func; + } + } + + /** + * Convert BlockInfo into scratch-blocks JSON & XML, and generate a proxy function. + * @param {BlockInfo} blockInfo - the block to convert + * @param {CategoryInfo} categoryInfo - the category for this block + * @returns {{info: BlockInfo, json: object, xml: string}} - the converted & original block information + * @private + */ + _convertForScratchBlocks (blockInfo, categoryInfo) { + const extendedOpcode = `${categoryInfo.id}.${blockInfo.opcode}`; + const blockJSON = { + id: extendedOpcode, + inputsInline: true, + previousStatement: null, // null = available connection; undefined = hat block + nextStatement: null, // null = available connection; undefined = terminal + category: categoryInfo.name, + colour: categoryInfo.color1, + colourSecondary: categoryInfo.color2, + colorTertiary: categoryInfo.color3, + args0: [] + }; + + const inputList = []; + + // TODO: store this somewhere so that we can map args appropriately after translation. + // This maps an arg name to its relative position in the original (usually English) block text. + // When displaying a block in another language we'll need to run a `replace` action similar to the one below, + // but each `[ARG]` will need to be replaced with the number in this map instead of `args0.length`. + const argsMap = {}; + + blockJSON.message0 = blockInfo.text.replace(/\[(.+?)]/g, (match, placeholder) => { + + // Sanitize the placeholder to ensure valid XML + placeholder = placeholder.replace(/[<"&]/, '_'); + + blockJSON.args0.push({ + type: 'input_value', + name: placeholder + }); + + // scratch-blocks uses 1-based argument indexing + const argNum = blockJSON.args0.length; + argsMap[placeholder] = argNum; + + const argInfo = blockInfo.arguments[placeholder] || {}; + const argTypeInfo = ArgumentTypeMap[argInfo.type] || {}; + const defaultValue = (typeof argInfo.defaultValue === 'undefined' ? '' : argInfo.defaultValue.toString()); + inputList.push(`${defaultValue + }` + ); + + return `%${argNum}`; + }); + + switch (blockInfo.blockType) { + case BlockType.COMMAND: + blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_SQUARE; + break; + case BlockType.REPORTER: + blockJSON.output = 'String'; // TODO: distinguish number & string here? + blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_ROUND; + break; + case BlockType.BOOLEAN: + blockJSON.output = 'Boolean'; + blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_HEXAGONAL; + break; + case BlockType.HAT: + blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_SQUARE; + delete blockJSON.previousStatement; + break; + case BlockType.CONDITIONAL: + // Statement inputs get names like 'SUBSTACK', 'SUBSTACK2', 'SUBSTACK3', ... + for (let branchNum = 1; branchNum <= blockInfo.branchCount; ++branchNum) { + blockJSON[`args${branchNum}`] = { + type: 'input_statement', + name: `SUBSTACK${branchNum > 1 ? branchNum : ''}` + }; + } + blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_SQUARE; + break; + } + + if (blockInfo.isTerminal) { + delete blockJSON.nextStatement; + } + + const blockXML = `${inputList.join('')}`; + + return { + info: blockInfo, + json: blockJSON, + xml: blockXML + }; + } + /** * Retrieve the function associated with the given opcode. * @param {!string} opcode The opcode to look up. diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index 1c01c69f2..a453fb3a8 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -1,9 +1,7 @@ -const centralDispatch = require('../dispatch/central-dispatch'); +const dispatch = require('../dispatch/central-dispatch'); const log = require('../util/log'); -const ArgumentType = require('./argument-type'); const BlockType = require('./block-type'); -const ScratchBlocks = require('scratch-blocks'); /** * @typedef {object} ArgumentInfo - Information about an extension block argument @@ -20,7 +18,7 @@ const ScratchBlocks = require('scratch-blocks'); * @property {Boolean|undefined} isTerminal - true if this block ends a stack (default: false) * @property {Boolean|undefined} blockAllThreads - true if all threads must wait for this block to run (default: false) * @property {object.|undefined} arguments - information about this block's arguments, if any - * @property {string|undefined} func - the method implementing this block on the extension service (default: opcode) + * @property {string|Function|undefined} func - the method for this block on the extension service (default: opcode) * @property {Array.|undefined} filter - the list of targets for which this block should appear (default: all) */ @@ -32,26 +30,6 @@ const ScratchBlocks = require('scratch-blocks'); * @property {string} color3 - the tertiary color for this category, in '#rrggbb' format */ -/** - * Information used for converting Scratch argument types into scratch-blocks data. - * @type {object.}} - */ -const ArgumentTypeMap = (() => { - const map = {}; - map[ArgumentType.NUMBER] = { - shadowType: 'math_number', - fieldType: 'NUM' - }; - map[ArgumentType.STRING] = { - shadowType: 'text', - fieldType: 'TEXT' - }; - map[ArgumentType.BOOLEAN] = { - shadowType: '' - }; - return map; -})(); - class ExtensionManager { constructor () { /** @@ -72,7 +50,9 @@ class ExtensionManager { */ this.pendingExtensionURLs = []; - centralDispatch.setService('extensions', this); + dispatch.setService('extensions', this).catch(e => { + log.error(`ExtensionManager was unable to register extension service: ${JSON.stringify(e)}`); + }); } foo () { @@ -84,7 +64,7 @@ class ExtensionManager { const ExtensionWorker = require('worker-loader!./extension-worker'); this.pendingExtensionURLs.push(extensionURL); - centralDispatch.addWorker(new ExtensionWorker()); + dispatch.addWorker(new ExtensionWorker()); } allocateWorker () { @@ -94,29 +74,16 @@ class ExtensionManager { } registerExtensionService (serviceName) { - centralDispatch.call(serviceName, 'getInfo').then(info => { + dispatch.call(serviceName, 'getInfo').then(info => { this._registerExtensionInfo(serviceName, info); }); } _registerExtensionInfo (serviceName, extensionInfo) { - const categoryInfo = { - id: extensionInfo.id, - name: extensionInfo.name, - color1: '#FF6680', - color2: '#FF4D6A', - color3: '#FF3355' - }; - extensionInfo = this._sanitizeExtensionInfo(extensionInfo); - for (let blockInfo of extensionInfo.blocks) { - if (!(blockInfo.opcode && blockInfo.text)) { - log.error(`Ignoring malformed extension block: ${JSON.stringify(blockInfo)}`); - continue; - } - blockInfo = this._sanitizeBlockInfo(blockInfo); - const convertedBlock = this._convertForScratchBlocks(blockInfo, serviceName, categoryInfo); - console.dir(convertedBlock); - } + extensionInfo = this._prepareExtensionInfo(serviceName, extensionInfo); + dispatch.call('runtime', '_registerExtensionPrimitives', extensionInfo).catch(e => { + log.error(`Failed to register primitives for extension on service ${serviceName}: ${JSON.stringify(e)}`); + }); } /** @@ -132,26 +99,37 @@ class ExtensionManager { /** * Apply minor cleanup and defaults for optional extension fields. * TODO: make the ID unique in cases where two copies of the same extension are loaded. + * @param {string} serviceName - the name of the service hosting this extension block * @param {ExtensionInfo} extensionInfo - the extension info to be sanitized * @returns {ExtensionInfo} - a new extension info object with cleaned-up values * @private */ - _sanitizeExtensionInfo (extensionInfo) { + _prepareExtensionInfo (serviceName, extensionInfo) { extensionInfo = Object.assign({}, extensionInfo); extensionInfo.id = this._sanitizeID(extensionInfo.id); extensionInfo.name = extensionInfo.name || extensionInfo.id; extensionInfo.blocks = extensionInfo.blocks || []; extensionInfo.targetTypes = extensionInfo.targetTypes || []; + extensionInfo.blocks = extensionInfo.blocks.reduce((result, blockInfo) => { + try { + result.push(this._prepareBlockInfo(serviceName, blockInfo)); + } catch (e) { + // TODO: more meaningful error reporting + log.error(`Skipping malformed block: ${e}`); + } + return result; + }, []); return extensionInfo; } /** * Apply defaults for optional block fields. + * @param {string} serviceName - the name of the service hosting this extension block * @param {BlockInfo} blockInfo - the block info from the extension * @returns {BlockInfo} - a new block info object which has values for all relevant optional fields. * @private */ - _sanitizeBlockInfo (blockInfo) { + _prepareBlockInfo (serviceName, blockInfo) { blockInfo = Object.assign({}, { blockType: BlockType.COMMAND, terminal: false, @@ -160,120 +138,9 @@ class ExtensionManager { }, blockInfo); blockInfo.opcode = this._sanitizeID(blockInfo.opcode); blockInfo.func = blockInfo.func ? this._sanitizeID(blockInfo.func) : blockInfo.opcode; + blockInfo.func = dispatch.call.bind(dispatch, serviceName, blockInfo.func); return blockInfo; } - - /** - * Convert BlockInfo into scratch-blocks JSON & XML, and generate a proxy function. - * @param {BlockInfo} blockInfo - the block to convert - * @param {string} serviceName - the name of the service hosting this extension - * @param {CategoryInfo} categoryInfo - the category for this block - * @returns {{json: object, xml: string, blockFunction: Function}} - the converted block information - * @private - */ - _convertForScratchBlocks (blockInfo, serviceName, categoryInfo) { - const extendedOpcode = `${categoryInfo.id}.${blockInfo.opcode}`; - const blockJSON = { - id: extendedOpcode, - inputsInline: true, - previousStatement: null, // null = available connection; undefined = hat block - nextStatement: null, // null = available connection; undefined = terminal - category: categoryInfo.name, - colour: categoryInfo.color1, - colourSecondary: categoryInfo.color2, - colorTertiary: categoryInfo.color3, - args0: [] - }; - - const inputList = []; - - // TODO: store this somewhere so that we can map args appropriately after translation. - // This maps an arg name to its relative position in the original (usually English) block text. - // When displaying a block in another language we'll need to run a `replace` action similar to the one below, - // but each `[ARG]` will need to be replaced with the number in this map instead of `args0.length`. - const argsMap = {}; - - blockJSON.message0 = blockInfo.text.replace(/\[(.+?)]/g, (match, placeholder) => { - - // Sanitize the placeholder to ensure valid XML - placeholder = placeholder.replace(/[<"&]/, '_'); - - blockJSON.args0.push({ - type: 'input_value', - name: placeholder - }); - - // scratch-blocks uses 1-based argument indexing - const argNum = blockJSON.args0.length; - argsMap[placeholder] = argNum; - - const argInfo = blockInfo.arguments[placeholder] || {}; - const argTypeInfo = ArgumentTypeMap[argInfo.type] || {}; - const defaultValue = (typeof argInfo.defaultValue === 'undefined' ? '' : argInfo.defaultValue.toString()); - inputList.push( - `` + - `` + - `${defaultValue}` + - `` + - `` - ); - - return `%${argNum}`; - }); - - switch (blockInfo.blockType) { - case BlockType.COMMAND: - blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_SQUARE; - break; - case BlockType.REPORTER: - blockJSON.output = 'String'; // TODO: distinguish number & string here? - blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_ROUND; - break; - case BlockType.BOOLEAN: - blockJSON.output = 'Boolean'; - blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_HEXAGONAL; - break; - case BlockType.HAT: - blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_SQUARE; - delete blockJSON.previousStatement; - break; - case BlockType.CONDITIONAL: - // Statement inputs get names like 'SUBSTACK', 'SUBSTACK2', 'SUBSTACK3', ... - for (let branchNum = 1; branchNum <= blockInfo.branchCount; ++branchNum) { - blockJSON[`args${branchNum}`] = { - type: 'input_statement', - name: `SUBSTACK${branchNum > 1 ? branchNum : ''}` - }; - } - blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_SQUARE; - break; - } - - if (blockInfo.isTerminal) { - delete blockJSON.nextStatement; - } - - const blockXML = `${inputList.join('')}`; - - return { - json: blockJSON, - xml: blockXML, - blockFunction: this._extensionProxy.bind(this, serviceName, blockInfo.opcode) - }; - } - - /** - * Run an opcode by proxying the call to an extension service. - * @param {string} serviceName - the name of the service hosting the extension - * @param {string} opcode - the opcode to run, also the name of the method on the extension service - * @param {object} blockArgs - the arguments provided to the block - * @returns {Promise} - a promise which will resolve after the block function executes. If the block function - * returns a value, this promise will resolve to that value. - * @private - */ - _extensionProxy (serviceName, opcode, blockArgs) { - return centralDispatch.call(serviceName, opcode, blockArgs); - } } module.exports = ExtensionManager; diff --git a/src/extensions/example-extension.js b/src/extensions/example-extension.js index e983808f7..fa585f5e1 100644 --- a/src/extensions/example-extension.js +++ b/src/extensions/example-extension.js @@ -5,7 +5,7 @@ class ExampleExtension { getInfo () { return { // Required: the machine-readable name of this extension. - // Will be used as the extension's namespace. + // Will be used as the extension's namespace. Must not contain a '.' character. id: 'someBlocks', // Optional: the human-readable name of this extension as string. @@ -35,7 +35,7 @@ class ExampleExtension { blocks: [ { // Required: the machine-readable name of this operation. - // This will appear in project JSON. + // This will appear in project JSON. Must not contain a '.' character. opcode: 'myReporter', // becomes 'someBlocks.myReporter' // Required: the kind of block we're defining, from a predefined list: diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 61afda386..8334b3092 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -1,5 +1,6 @@ const EventEmitter = require('events'); +const centralDispatch = require('./dispatch/central-dispatch'); const log = require('./util/log'); const Runtime = require('./engine/runtime'); const sb2 = require('./serialization/sb2'); @@ -24,6 +25,10 @@ class VirtualMachine extends EventEmitter { * @type {!Runtime} */ this.runtime = new Runtime(); + centralDispatch.setService('runtime', this.runtime).catch(e => { + log.error(`Failed to register runtime service: ${JSON.stringify(e)}`); + }); + /** * The "currently editing"/selected target ID for the VM. * Block events from any Blockly workspace are routed to this target. @@ -131,6 +136,13 @@ class VirtualMachine extends EventEmitter { }); } + /** + * Get the categorized list of all blocks currently available in the VM. + */ + getBlocks () { + + } + /** * Post I/O data to the virtual devices. * @param {?string} device Name of virtual I/O device. From 64bde25d22083e1f057974b605512792d0f8a297 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Tue, 22 Aug 2017 14:28:38 -0700 Subject: [PATCH 017/272] Offer a promise for extension worker init --- src/extension-support/extension-manager.js | 62 ++++++++++++++++------ src/extension-support/extension-worker.js | 20 +++++-- 2 files changed, 62 insertions(+), 20 deletions(-) diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index a453fb3a8..e02234031 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -28,16 +28,18 @@ const BlockType = require('./block-type'); * @property {string} color1 - the primary color for this category, in '#rrggbb' format * @property {string} color2 - the secondary color for this category, in '#rrggbb' format * @property {string} color3 - the tertiary color for this category, in '#rrggbb' format + * @property {Array. block - the blocks in this category + */ + +/** + * @typedef {object} PendingExtensionWorker - Information about an extension worker still initializing + * @property {string} extensionURL - the URL of the extension to be loaded by this worker + * @property {Function} resolve - function to call on successful worker startup + * @property {Function} reject - function to call on failed worker startup */ class ExtensionManager { constructor () { - /** - * The list of current active extension workers. - * @type {Array.} - */ - this.workers = []; - /** * The ID number to provide to the next extension worker. * @type {int} @@ -45,10 +47,18 @@ class ExtensionManager { this.nextExtensionWorker = 0; /** - * The list of extension URLs which have been requested but not yet loaded in a worker. - * @type {Array} + * FIFO queue of extensions which have been requested but not yet loaded in a worker, + * along with promise resolution functions to call once the worker is ready or failed. + * + * @type {Array.} */ - this.pendingExtensionURLs = []; + this.pendingExtensions = []; + + /** + * Map of worker ID to workers which have been allocated but have not yet finished initialization. + * @type {Array.} + */ + this.pendingWorkers = []; dispatch.setService('extensions', this).catch(e => { log.error(`ExtensionManager was unable to register extension service: ${JSON.stringify(e)}`); @@ -56,21 +66,29 @@ class ExtensionManager { } foo () { - this.loadExtensionURL('extensions/example-extension.js'); + return this.loadExtensionURL('extensions/example-extension.js'); } + /** + * Load an extension by URL + * @param {string} extensionURL - the URL for the extension to load + * @returns {Promise} resolved once the extension is loaded and initialized or rejected on failure + */ loadExtensionURL (extensionURL) { - // If we `require` this at the global level it breaks non-webpack targets, including tests - const ExtensionWorker = require('worker-loader!./extension-worker'); + return new Promise((resolve, reject) => { + // If we `require` this at the global level it breaks non-webpack targets, including tests + const ExtensionWorker = require('worker-loader!./extension-worker'); - this.pendingExtensionURLs.push(extensionURL); - dispatch.addWorker(new ExtensionWorker()); + this.pendingExtensions.push({extensionURL, resolve, reject}); + dispatch.addWorker(new ExtensionWorker()); + }); } allocateWorker () { const id = this.nextExtensionWorker++; - const extFile = this.pendingExtensionURLs.shift(); - return [id, extFile]; + const workerInfo = this.pendingExtensions.shift(); + this.pendingWorkers[id] = workerInfo; + return [id, workerInfo.extensionURL]; } registerExtensionService (serviceName) { @@ -79,6 +97,16 @@ class ExtensionManager { }); } + onWorkerInit (id, e) { + const workerInfo = this.pendingWorkers[id]; + delete this.pendingWorkers[id]; + if (e) { + workerInfo.reject(e); + } else { + workerInfo.resolve(id); + } + } + _registerExtensionInfo (serviceName, extensionInfo) { extensionInfo = this._prepareExtensionInfo(serviceName, extensionInfo); dispatch.call('runtime', '_registerExtensionPrimitives', extensionInfo).catch(e => { @@ -115,7 +143,7 @@ class ExtensionManager { result.push(this._prepareBlockInfo(serviceName, blockInfo)); } catch (e) { // TODO: more meaningful error reporting - log.error(`Skipping malformed block: ${e}`); + log.error(`Skipping malformed block: ${JSON.stringify(e)}`); } return result; }, []); diff --git a/src/extension-support/extension-worker.js b/src/extension-support/extension-worker.js index 8c4a57410..02406e08b 100644 --- a/src/extension-support/extension-worker.js +++ b/src/extension-support/extension-worker.js @@ -8,13 +8,23 @@ class ExtensionWorker { constructor () { this.nextExtensionId = 0; + this.initialRegistrations = []; + dispatch.waitForConnection.then(() => { dispatch.call('extensions', 'allocateWorker').then(x => { const [id, extension] = x; this.workerId = id; - // TODO: catch and report any exceptions here - importScripts(extension); + try { + importScripts(extension); + + const initialRegistrations = this.initialRegistrations; + this.initialRegistrations = null; + + Promise.all(initialRegistrations).then(() => dispatch.call('extensions', 'onWorkerInit', id)); + } catch (e) { + dispatch.call('extensions', 'onWorkerInit', id, e); + } }); }); @@ -25,8 +35,12 @@ class ExtensionWorker { const extensionId = this.nextExtensionId++; this.extensions.push(extensionObject); const serviceName = `extension.${this.workerId}.${extensionId}`; - return dispatch.setService(serviceName, extensionObject) + const promise = dispatch.setService(serviceName, extensionObject) .then(() => dispatch.call('extensions', 'registerExtensionService', serviceName)); + if (this.initialRegistrations) { + this.initialRegistrations.push(promise); + } + return promise; } } From aaa7784d3943ec1a5fea894b652bbd896ee8ab2b Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Fri, 25 Aug 2017 13:53:57 -0700 Subject: [PATCH 018/272] Add methods to fetch scratch-blocks XML and JSON --- src/engine/runtime.js | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 773ef067e..1b0a9ddca 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -102,10 +102,10 @@ class Runtime extends EventEmitter { /** * Map to look up all block information by extended opcode. - * @type {Object.} + * @type {Array.} * @private */ - this._blockInfo = {}; + this._blockInfo = []; /** * Map to look up hat blocks' metadata. @@ -363,13 +363,16 @@ class Runtime extends EventEmitter { name: extensionInfo.name, color1: '#FF6680', color2: '#FF4D6A', - color3: '#FF3355' + color3: '#FF3355', + blocks: [] }; + this._blockInfo.push(categoryInfo); + for (const blockInfo of extensionInfo.blocks) { const convertedBlock = this._convertForScratchBlocks(blockInfo, categoryInfo); const opcode = convertedBlock.json.id; - this._blockInfo[opcode] = convertedBlock; + categoryInfo.blocks.push(convertedBlock); this._primitives[opcode] = convertedBlock.info.func; } } @@ -471,6 +474,30 @@ class Runtime extends EventEmitter { }; } + /** + * @returns {string} scratch-blocks XML description for all dynamic blocks, wrapped in elements. + */ + getBlocksXML () { + const xmlParts = []; + for (const categoryInfo of this._blockInfo) { + const {name, color1, color2} = categoryInfo; + xmlParts.push(``); + // @todo only add this label for user-loaded extensions? + xmlParts.push(`'); + } + return xmlParts.join('\n'); + } + + /** + * @returns {Array.} - an array containing the scratch-blocks JSON information for each dynamic block. + */ + getBlocksJSON () { + return this._blockInfo.reduce( + (result, categoryInfo) => result.concat(categoryInfo.blocks.map(blockInfo => blockInfo.json)), []); + } + /** * Retrieve the function associated with the given opcode. * @param {!string} opcode The opcode to look up. From d43749d67561a9c3a351b7ebd36f4def9e112a1c Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Tue, 29 Aug 2017 11:43:09 -0700 Subject: [PATCH 019/272] WIP for demo --- src/dispatch/shared-dispatch.js | 6 +++ src/engine/runtime.js | 26 ++++++++++--- src/extension-support/extension-manager.js | 6 +-- src/extensions/example-extension.js | 45 ++++++++++++++++++++++ src/index.js | 2 - src/virtual-machine.js | 6 +++ 6 files changed, 78 insertions(+), 13 deletions(-) diff --git a/src/dispatch/shared-dispatch.js b/src/dispatch/shared-dispatch.js index d582dc170..85d38bde2 100644 --- a/src/dispatch/shared-dispatch.js +++ b/src/dispatch/shared-dispatch.js @@ -115,6 +115,12 @@ class SharedDispatch { _remoteTransferCall (provider, service, method, transfer, ...args) { return new Promise((resolve, reject) => { const responseId = this._storeCallbacks(resolve, reject); + + /** @TODO: remove this hack! this is just here so we don't try to send `util` to a worker */ + if ((args.length > 0) && (typeof args[args.length - 1].yield === 'function')) { + args.pop(); + } + if (transfer) { provider.postMessage({service, method, responseId, args}, transfer); } else { diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 1b0a9ddca..1ea4fb519 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -294,6 +294,14 @@ class Runtime extends EventEmitter { return 'MONITORS_UPDATE'; } + /** + * Event name for reporting that an extension was added. + * @const {string} + */ + static get EXTENSION_WAS_ADDED () { + return 'EXTENSION_WAS_ADDED'; + } + /** * How rapidly we try to step threads by default, in ms. */ @@ -371,10 +379,12 @@ class Runtime extends EventEmitter { for (const blockInfo of extensionInfo.blocks) { const convertedBlock = this._convertForScratchBlocks(blockInfo, categoryInfo); - const opcode = convertedBlock.json.id; + const opcode = convertedBlock.json.type; categoryInfo.blocks.push(convertedBlock); this._primitives[opcode] = convertedBlock.info.func; } + + this.emit(Runtime.EXTENSION_WAS_ADDED, categoryInfo.blocks); } /** @@ -387,10 +397,8 @@ class Runtime extends EventEmitter { _convertForScratchBlocks (blockInfo, categoryInfo) { const extendedOpcode = `${categoryInfo.id}.${blockInfo.opcode}`; const blockJSON = { - id: extendedOpcode, + type: extendedOpcode, inputsInline: true, - previousStatement: null, // null = available connection; undefined = hat block - nextStatement: null, // null = available connection; undefined = terminal category: categoryInfo.name, colour: categoryInfo.color1, colourSecondary: categoryInfo.color2, @@ -436,6 +444,10 @@ class Runtime extends EventEmitter { switch (blockInfo.blockType) { case BlockType.COMMAND: blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_SQUARE; + blockJSON.previousStatement = null; // null = available connection; undefined = hat + if (!blockInfo.isTerminal) { + blockJSON.nextStatement = null; // null = available connection; undefined = terminal + } break; case BlockType.REPORTER: blockJSON.output = 'String'; // TODO: distinguish number & string here? @@ -447,7 +459,7 @@ class Runtime extends EventEmitter { break; case BlockType.HAT: blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_SQUARE; - delete blockJSON.previousStatement; + blockJSON.nextStatement = null; // null = available connection; undefined = terminal break; case BlockType.CONDITIONAL: // Statement inputs get names like 'SUBSTACK', 'SUBSTACK2', 'SUBSTACK3', ... @@ -458,6 +470,8 @@ class Runtime extends EventEmitter { }; } blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_SQUARE; + blockJSON.previousStatement = null; // null = available connection; undefined = hat + blockJSON.nextStatement = null; // null = available connection; undefined = terminal break; } @@ -659,7 +673,7 @@ class Runtime extends EventEmitter { if (this.threads[i].topBlock === topBlockId && this.threads[i].status !== Thread.STATUS_DONE) { const blockContainer = opts.target.blocks; const opcode = blockContainer.getOpcode(blockContainer.getBlock(topBlockId)); - + if (this.getIsEdgeActivatedHat(opcode) && this.threads[i].stackClick !== opts.stackClick) { // Allow edge activated hat thread stack click to coexist with // edge activated hat thread that runs every frame diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index e02234031..c7c1487df 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -65,10 +65,6 @@ class ExtensionManager { }); } - foo () { - return this.loadExtensionURL('extensions/example-extension.js'); - } - /** * Load an extension by URL * @param {string} extensionURL - the URL for the extension to load @@ -77,7 +73,7 @@ class ExtensionManager { loadExtensionURL (extensionURL) { return new Promise((resolve, reject) => { // If we `require` this at the global level it breaks non-webpack targets, including tests - const ExtensionWorker = require('worker-loader!./extension-worker'); + const ExtensionWorker = require('worker-loader?name=extension-worker.js!./extension-worker'); this.pendingExtensions.push({extensionURL, resolve, reject}); dispatch.addWorker(new ExtensionWorker()); diff --git a/src/extensions/example-extension.js b/src/extensions/example-extension.js index fa585f5e1..e9aeba53f 100644 --- a/src/extensions/example-extension.js +++ b/src/extensions/example-extension.js @@ -33,6 +33,28 @@ class ExampleExtension { // Required: the list of blocks implemented by this extension, // in the order intended for display. blocks: [ + { + opcode: 'example-noop', + blockType: Scratch.BlockType.COMMAND, + blockAllThreads: false, + text: 'do nothing', + func: 'noop' + }, + { + opcode: 'example-conditional', + blockType: Scratch.BlockType.CONDITIONAL, + branchCount: 4, + isTerminal: true, + blockAllThreads: false, + text: 'choose [BRANCH]', + arguments: { + BRANCH: { + type: Scratch.ArgumentType.NUMBER, + defaultValue: 1 + } + }, + func: 'noop' + }, { // Required: the machine-readable name of this operation. // This will appear in project JSON. Must not contain a '.' character. @@ -110,6 +132,18 @@ class ExampleExtension { // ['sprite', 'stage'] filter: ['someBlocks.wedo2', 'sprite', 'stage'] }, + { + opcode: 'example-Boolean', + blockType: Scratch.BlockType.BOOLEAN, + text: 'return true', + func: 'returnTrue' + }, + { + opcode: 'example-hat', + blockType: Scratch.BlockType.HAT, + text: 'after forever', + func: 'returnFalse' + }, { // Another block... } @@ -179,6 +213,17 @@ class ExampleExtension { return ['Letter ', args.LETTER_NUM, ' of ', args.TEXT, ' is ', result, '.'].join(''); } + + noop () { + } + + returnTrue () { + return true; + } + + returnFalse () { + return false; + } } Scratch.extensions.register(new ExampleExtension()); diff --git a/src/index.js b/src/index.js index f2d277902..a54deefbc 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,8 @@ const VirtualMachine = require('./virtual-machine'); const CentralDispatch = require('./dispatch/central-dispatch'); -const ExtensionManager = require('./extension-support/extension-manager'); global.Scratch = global.Scratch || {}; global.Scratch.dispatch = CentralDispatch; -global.Scratch.extensions = new ExtensionManager(); module.exports = VirtualMachine; diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 8334b3092..186607c37 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -1,6 +1,7 @@ const EventEmitter = require('events'); const centralDispatch = require('./dispatch/central-dispatch'); +const ExtensionManager = require('./extension-support/extension-manager'); const log = require('./util/log'); const Runtime = require('./engine/runtime'); const sb2 = require('./serialization/sb2'); @@ -63,6 +64,11 @@ class VirtualMachine extends EventEmitter { this.runtime.on(Runtime.MONITORS_UPDATE, monitorList => { this.emit(Runtime.MONITORS_UPDATE, monitorList); }); + this.runtime.on(Runtime.EXTENSION_WAS_ADDED, blocksInfo => { + this.emit(Runtime.EXTENSION_WAS_ADDED, blocksInfo); + }); + + this.extensionManager = new ExtensionManager(); this.blockListener = this.blockListener.bind(this); this.flyoutBlockListener = this.flyoutBlockListener.bind(this); From e7c727977acc624f347647922f5c19696fd73cee Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Mon, 4 Sep 2017 11:06:31 -0700 Subject: [PATCH 020/272] Adjust for LLK/scratch-gui#655 & code review - Move extension from this repository into LLK/scratch-gui - Rename `EXTENSION_WAS_ADDED` event to `EXTENSION_ADDED` --- src/engine/runtime.js | 6 +- src/extensions/.eslintrc.js | 8 - src/extensions/example-extension.js | 229 ---------------------------- src/virtual-machine.js | 4 +- 4 files changed, 5 insertions(+), 242 deletions(-) delete mode 100644 src/extensions/.eslintrc.js delete mode 100644 src/extensions/example-extension.js diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 1ea4fb519..1c5252462 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -298,8 +298,8 @@ class Runtime extends EventEmitter { * Event name for reporting that an extension was added. * @const {string} */ - static get EXTENSION_WAS_ADDED () { - return 'EXTENSION_WAS_ADDED'; + static get EXTENSION_ADDED () { + return 'EXTENSION_ADDED'; } /** @@ -384,7 +384,7 @@ class Runtime extends EventEmitter { this._primitives[opcode] = convertedBlock.info.func; } - this.emit(Runtime.EXTENSION_WAS_ADDED, categoryInfo.blocks); + this.emit(Runtime.EXTENSION_ADDED, categoryInfo.blocks); } /** diff --git a/src/extensions/.eslintrc.js b/src/extensions/.eslintrc.js deleted file mode 100644 index f84dadeb6..000000000 --- a/src/extensions/.eslintrc.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - env: { - worker: true - }, - globals: { - Scratch: true - } -}; diff --git a/src/extensions/example-extension.js b/src/extensions/example-extension.js deleted file mode 100644 index e9aeba53f..000000000 --- a/src/extensions/example-extension.js +++ /dev/null @@ -1,229 +0,0 @@ -class ExampleExtension { - /** - * @return {object} This extension's metadata. - */ - getInfo () { - return { - // Required: the machine-readable name of this extension. - // Will be used as the extension's namespace. Must not contain a '.' character. - id: 'someBlocks', - - // Optional: the human-readable name of this extension as string. - // This and any other string to be displayed in the Scratch UI may either be - // a string or a call to `intlDefineMessage`; a plain string will not be - // translated whereas a call to `intlDefineMessage` will connect the string - // to the translation map (see below). The `intlDefineMessage` call is - // similar to `defineMessages` from `react-intl` in form, but will actually - // call some extension support code to do its magic. For example, we will - // internally namespace the messages such that two extensions could have - // messages with the same ID without colliding. - // See also: https://github.com/yahoo/react-intl/wiki/API#definemessages - name: 'Some Blocks', - - // Optional: URI for an icon for this extension. Data URI OK. - // If not present, use a generic icon. - // TODO: what file types are OK? All web images? Just PNG? - iconURI: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAFCAAAAACyOJm3AAAAFklEQVQYV2P4DwMMEMgAI/+DE' + - 'UIMBgAEWB7i7uidhAAAAABJRU5ErkJggg==', - - // Optional: Link to documentation content for this extension. - // If not present, offer no link. - docsURI: 'https://....', - - // Required: the list of blocks implemented by this extension, - // in the order intended for display. - blocks: [ - { - opcode: 'example-noop', - blockType: Scratch.BlockType.COMMAND, - blockAllThreads: false, - text: 'do nothing', - func: 'noop' - }, - { - opcode: 'example-conditional', - blockType: Scratch.BlockType.CONDITIONAL, - branchCount: 4, - isTerminal: true, - blockAllThreads: false, - text: 'choose [BRANCH]', - arguments: { - BRANCH: { - type: Scratch.ArgumentType.NUMBER, - defaultValue: 1 - } - }, - func: 'noop' - }, - { - // Required: the machine-readable name of this operation. - // This will appear in project JSON. Must not contain a '.' character. - opcode: 'myReporter', // becomes 'someBlocks.myReporter' - - // Required: the kind of block we're defining, from a predefined list: - // 'command' - a normal command block, like "move {} steps" - // 'reporter' - returns a value, like "direction" - // 'Boolean' - same as 'reporter' but returns a Boolean value - // 'hat' - starts a stack if its value is truthy - // 'conditional' - control flow, like "if {}" or "repeat {}" - // A 'conditional' block may return the one-based index of a branch - // to run, or it may return zero/falsy to run no branch. Each time a - // child branch finishes, the block is called again. This is only a - // slight change to the current model for control flow blocks, and is - // also compatible with returning true/false for an "if" or "repeat" - // block. - // TODO: Consider Blockly-like nextStatement, previousStatement, and - // output attributes as an alternative. Those are more flexible, but - // allow bad combinations. - blockType: Scratch.BlockType.REPORTER, - - // Required for conditional blocks, ignored for others: the number of - // child branches this block controls. An "if" or "repeat" block would - // specify a branch count of 1; an "if-else" block would specify a - // branch count of 2. - // TODO: should we support dynamic branch count for "switch"-likes? - branchCount: 0, - - // Optional, default false: whether or not this block ends a stack. - // The "forever" and "stop all" blocks would specify true here. - isTerminal: true, - - // Optional, default false: whether or not to block all threads while - // this block is busy. This is for things like the "touching color" - // block in compatibility mode, and is only needed if the VM runs in a - // worker. We might even consider omitting it from extension docs... - blockAllThreads: false, - - // Required: the human-readable text on this block, including argument - // placeholders. Argument placeholders should be in [MACRO_CASE] and - // must be [ENCLOSED_WITHIN_SQUARE_BRACKETS]. - text: 'letter [LETTER_NUM] of [TEXT]', - - // Required: describe each argument. - // Note that this is an array: the order of arguments will be used - arguments: { - // Required: the ID of the argument, which will be the name in the - // args object passed to the implementation function. - LETTER_NUM: { - // Required: type of the argument / shape of the block input - type: Scratch.ArgumentType.NUMBER, - - // Optional: the default value of the argument - defaultValue: 1 - }, - - // Required: the ID of the argument, which will be the name in the - // args object passed to the implementation function. - TEXT: { - // Required: type of the argument / shape of the block input - type: Scratch.ArgumentType.STRING, - - // Optional: the default value of the argument - defaultValue: 'text' - } - }, - - // Optional: a string naming the function implementing this block. - // If this is omitted, use the opcode string. - func: 'myReporter', - - // Optional: list of target types for which this block should appear. - // If absent, assume it applies to all builtin targets -- that is: - // ['sprite', 'stage'] - filter: ['someBlocks.wedo2', 'sprite', 'stage'] - }, - { - opcode: 'example-Boolean', - blockType: Scratch.BlockType.BOOLEAN, - text: 'return true', - func: 'returnTrue' - }, - { - opcode: 'example-hat', - blockType: Scratch.BlockType.HAT, - text: 'after forever', - func: 'returnFalse' - }, - { - // Another block... - } - ], - - // Optional: define extension-specific menus here. - menus: { - // Required: an identifier for this menu, unique within this extension. - menuA: [ - // Static menu: list items which should appear in the menu. - { - // Required: the value of the menu item when it is chosen. - value: 'itemId1', - - // Optional: the human-readable label for this item. - // Use `value` as the text if this is absent. - text: 'Item One' - }, - - // The simplest form of a list item is a string which will be used as - // both value and text. - 'itemId2' - ], - - // Dynamic menu: a string naming a function which returns an array as above. - // Called each time the menu is opened. - menuB: 'getItemsForMenuB' - }, - - // Optional: translations - translation_map: { - de: { - 'extensionName': 'Einige Blöcke', - 'myReporter': 'Buchstabe [LETTER_NUM] von [TEXT]', - 'myReporter.TEXT_default': 'Text', - 'menuA_item1': 'Artikel eins', - - // Dynamic menus can be translated too - 'menuB_example': 'Beispiel', - - // This message contains ICU placeholders (see `myReporter()` below) - 'myReporter.result': 'Buchstabe {LETTER_NUM} von {TEXT} ist {LETTER}.' - }, - it: { - // ... - } - }, - - // Optional: list new target type(s) provided by this extension. - targetTypes: [ - 'wedo2', // automatically transformed to 'someBlocks.wedo2' - 'speech' // automatically transformed to 'someBlocks.speech' - ] - }; - } - - /** - * Implement myReporter. - * @param {object} args - the block's arguments. - * @property {number} LETTER_NUM - the string value of the argument. - * @property {string} TEXT - the string value of the argument. - * @returns {string} a string which includes the block argument value. - */ - myReporter (args) { - // Note: this implementation is not Unicode-clean; it's just here as an example. - const result = args.TEXT.charAt(args.LETTER_NUM); - - return ['Letter ', args.LETTER_NUM, ' of ', args.TEXT, ' is ', result, '.'].join(''); - } - - noop () { - } - - returnTrue () { - return true; - } - - returnFalse () { - return false; - } -} - -Scratch.extensions.register(new ExampleExtension()); diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 186607c37..55aba32a4 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -64,8 +64,8 @@ class VirtualMachine extends EventEmitter { this.runtime.on(Runtime.MONITORS_UPDATE, monitorList => { this.emit(Runtime.MONITORS_UPDATE, monitorList); }); - this.runtime.on(Runtime.EXTENSION_WAS_ADDED, blocksInfo => { - this.emit(Runtime.EXTENSION_WAS_ADDED, blocksInfo); + this.runtime.on(Runtime.EXTENSION_ADDED, blocksInfo => { + this.emit(Runtime.EXTENSION_ADDED, blocksInfo); }); this.extensionManager = new ExtensionManager(); From d99c11ef91a110f3dc6523dafab121cfb0d233ee Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Mon, 4 Sep 2017 15:37:13 -0700 Subject: [PATCH 021/272] Fix extension conditional blocks' appearance The JSON generated for conditional blocks had slightly incorrect structure for its `argsN` items and was missing some necessary `messageN` items. --- src/engine/runtime.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 1c5252462..7c0fd1a8d 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -464,10 +464,11 @@ class Runtime extends EventEmitter { case BlockType.CONDITIONAL: // Statement inputs get names like 'SUBSTACK', 'SUBSTACK2', 'SUBSTACK3', ... for (let branchNum = 1; branchNum <= blockInfo.branchCount; ++branchNum) { - blockJSON[`args${branchNum}`] = { + blockJSON[`message${branchNum}`] = '%1'; + blockJSON[`args${branchNum}`] = [{ type: 'input_statement', name: `SUBSTACK${branchNum > 1 ? branchNum : ''}` - }; + }]; } blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_SQUARE; blockJSON.previousStatement = null; // null = available connection; undefined = hat From 799d61ac98cacbe760fcd43debee1b7624bad85f Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Mon, 4 Sep 2017 15:48:51 -0700 Subject: [PATCH 022/272] Cleanup --- src/engine/runtime.js | 12 +++++++----- src/extension-support/extension-manager.js | 2 +- src/index.js | 5 ----- src/virtual-machine.js | 7 ------- webpack.config.js | 19 ++++++------------- 5 files changed, 14 insertions(+), 31 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 7c0fd1a8d..878aeaebb 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -43,6 +43,7 @@ const ArgumentTypeMap = (() => { shadowType: 'text', fieldType: 'TEXT' }; + // @TODO: talk to Rachel & co. to figure out what goes here. Make it OK to not have a field. Add `check` support. map[ArgumentType.BOOLEAN] = { shadowType: '' }; @@ -431,11 +432,12 @@ class Runtime extends EventEmitter { const argInfo = blockInfo.arguments[placeholder] || {}; const argTypeInfo = ArgumentTypeMap[argInfo.type] || {}; const defaultValue = (typeof argInfo.defaultValue === 'undefined' ? '' : argInfo.defaultValue.toString()); - inputList.push(`${defaultValue - }` + inputList.push( + `` + + `` + + `${defaultValue}` + + '' + + '' ); return `%${argNum}`; diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index c7c1487df..62a7a0cf8 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -28,7 +28,7 @@ const BlockType = require('./block-type'); * @property {string} color1 - the primary color for this category, in '#rrggbb' format * @property {string} color2 - the secondary color for this category, in '#rrggbb' format * @property {string} color3 - the tertiary color for this category, in '#rrggbb' format - * @property {Array. block - the blocks in this category + * @property {Array.} block - the blocks in this category */ /** diff --git a/src/index.js b/src/index.js index a54deefbc..dfb566329 100644 --- a/src/index.js +++ b/src/index.js @@ -1,8 +1,3 @@ const VirtualMachine = require('./virtual-machine'); -const CentralDispatch = require('./dispatch/central-dispatch'); - -global.Scratch = global.Scratch || {}; -global.Scratch.dispatch = CentralDispatch; - module.exports = VirtualMachine; diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 55aba32a4..ffc182dbd 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -142,13 +142,6 @@ class VirtualMachine extends EventEmitter { }); } - /** - * Get the categorized list of all blocks currently available in the VM. - */ - getBlocks () { - - } - /** * Post I/O data to the virtual devices. * @param {?string} device Name of virtual I/O device. diff --git a/webpack.config.js b/webpack.config.js index d741b787c..571256800 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,15 +1,8 @@ const CopyWebpackPlugin = require('copy-webpack-plugin'); const defaultsDeep = require('lodash.defaultsdeep'); -const glob = require('glob'); const path = require('path'); const webpack = require('webpack'); -const extensionEntries = glob.sync('./src/extensions/*.js').reduce((bag, extensionPath) => { - const nameWithoutExtension = path.basename(extensionPath).replace(/\.[^/.]+$/, ''); - bag[`extensions/${nameWithoutExtension}`] = extensionPath; - return bag; -}, {}); - const base = { devServer: { contentBase: false, @@ -39,10 +32,10 @@ module.exports = [ // Web-compatible defaultsDeep({}, base, { target: 'web', - entry: defaultsDeep({}, extensionEntries, { + entry: { 'scratch-vm': './src/index.js', 'scratch-vm.min': './src/index.js' - }), + }, output: { path: path.resolve(__dirname, 'dist/web'), filename: '[name].js' @@ -59,9 +52,9 @@ module.exports = [ // Node-compatible defaultsDeep({}, base, { target: 'node', - entry: defaultsDeep({}, extensionEntries, { + entry: { 'scratch-vm': './src/index.js' - }), + }, output: { library: 'VirtualMachine', libraryTarget: 'commonjs2', @@ -72,7 +65,7 @@ module.exports = [ // Playground defaultsDeep({}, base, { target: 'web', - entry: defaultsDeep({}, extensionEntries, { + entry: { 'scratch-vm': './src/index.js', 'vendor': [ // FPS counter @@ -88,7 +81,7 @@ module.exports = [ // Storage 'scratch-storage' ] - }), + }, output: { path: path.resolve(__dirname, 'playground'), filename: '[name].js' From 635c7966eb3d1fe956d5ca77e381fe68fe3f1dae Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Wed, 6 Sep 2017 01:24:24 -0600 Subject: [PATCH 023/272] Fix tests: don't require('scratch-blocks') --- src/engine/runtime.js | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 878aeaebb..a36081d60 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -1,8 +1,6 @@ const EventEmitter = require('events'); const {OrderedMap} = require('immutable'); -const ScratchBlocks = require('scratch-blocks'); - const ArgumentType = require('../extension-support/argument-type'); const Blocks = require('./blocks'); const BlockType = require('../extension-support/block-type'); @@ -50,6 +48,32 @@ const ArgumentTypeMap = (() => { return map; })(); +/** + * These constants are copied from scratch-blocks/core/constants.js + * @TODO find a way to require() these... maybe make a scratch-blocks/dist/constants.js or something like that? + * @readonly + * @enum {int} + */ +const ScratchBlocksConstants = { + /** + * ENUM for output shape: hexagonal (booleans/predicates). + * @const + */ + OUTPUT_SHAPE_HEXAGONAL: 1, + + /** + * ENUM for output shape: rounded (numbers). + * @const + */ + OUTPUT_SHAPE_ROUND: 2, + + /** + * ENUM for output shape: squared (any/all values; strings). + * @const + */ + OUTPUT_SHAPE_SQUARE: 3 +}; + /** * Manages targets, scripts, and the sequencer. * @constructor @@ -445,7 +469,7 @@ class Runtime extends EventEmitter { switch (blockInfo.blockType) { case BlockType.COMMAND: - blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_SQUARE; + blockJSON.outputShape = ScratchBlocksConstants.OUTPUT_SHAPE_SQUARE; blockJSON.previousStatement = null; // null = available connection; undefined = hat if (!blockInfo.isTerminal) { blockJSON.nextStatement = null; // null = available connection; undefined = terminal @@ -453,14 +477,14 @@ class Runtime extends EventEmitter { break; case BlockType.REPORTER: blockJSON.output = 'String'; // TODO: distinguish number & string here? - blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_ROUND; + blockJSON.outputShape = ScratchBlocksConstants.OUTPUT_SHAPE_ROUND; break; case BlockType.BOOLEAN: blockJSON.output = 'Boolean'; - blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_HEXAGONAL; + blockJSON.outputShape = ScratchBlocksConstants.OUTPUT_SHAPE_HEXAGONAL; break; case BlockType.HAT: - blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_SQUARE; + blockJSON.outputShape = ScratchBlocksConstants.OUTPUT_SHAPE_SQUARE; blockJSON.nextStatement = null; // null = available connection; undefined = terminal break; case BlockType.CONDITIONAL: @@ -472,7 +496,7 @@ class Runtime extends EventEmitter { name: `SUBSTACK${branchNum > 1 ? branchNum : ''}` }]; } - blockJSON.outputShape = ScratchBlocks.OUTPUT_SHAPE_SQUARE; + blockJSON.outputShape = ScratchBlocksConstants.OUTPUT_SHAPE_SQUARE; blockJSON.previousStatement = null; // null = available connection; undefined = hat blockJSON.nextStatement = null; // null = available connection; undefined = terminal break; From b68b87406737f50468bd34a3880bbe26c4ac8ce9 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 7 Sep 2017 11:51:21 -0400 Subject: [PATCH 024/272] Add sprite duplication method --- src/engine/blocks.js | 7 ++++ src/import/load-costume.js | 75 +++++++++++++++++----------------- src/import/load-sound.js | 24 ++++++----- src/sprites/rendered-target.js | 27 ++++++++++++ src/sprites/sprite.js | 30 ++++++++++++++ src/virtual-machine.js | 25 ++++++++++++ 6 files changed, 140 insertions(+), 48 deletions(-) diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 85aeabfb8..53e346a5a 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -2,6 +2,7 @@ const adapter = require('./adapter'); const mutationAdapter = require('./mutation-adapter'); const xmlEscape = require('../util/xml-escape'); const MonitorRecord = require('./monitor-record'); +const Clone = require('../util/clone'); /** * @fileoverview @@ -178,6 +179,12 @@ class Blocks { return null; } + duplicate () { + const newBlocks = new Blocks(); + newBlocks._blocks = Clone.simple(this._blocks); + newBlocks._scripts = Clone.simple(this._scripts); + return newBlocks; + } // --------------------------------------------------------------------- /** diff --git a/src/import/load-costume.js b/src/import/load-costume.js index d435129b2..9e2f165b6 100644 --- a/src/import/load-costume.js +++ b/src/import/load-costume.js @@ -25,55 +25,54 @@ const loadCostume = function (md5ext, costume, runtime) { const ext = idParts[1].toLowerCase(); const assetType = (ext === 'svg') ? AssetType.ImageVector : AssetType.ImageBitmap; + return runtime.storage.load(assetType, md5, ext).then(costumeAsset => { + costume.dataFormat = ext; + return loadCostumeFromAsset(costume, costumeAsset, runtime); + }); +}; + +const loadCostumeFromAsset = function (costume, costumeAsset, runtime) { const rotationCenter = [ costume.rotationCenterX / costume.bitmapResolution, costume.rotationCenterY / costume.bitmapResolution ]; - let promise = runtime.storage.load(assetType, md5, ext).then(costumeAsset => { - costume.assetId = costumeAsset.assetId; - costume.dataFormat = ext; - return costumeAsset; - }); - if (!runtime.renderer) { log.error('No rendering module present; cannot load costume asset: ', md5ext); - return promise.then(() => costume); + return costume; + } + const AssetType = runtime.storage.AssetType; + costume.assetId = costumeAsset.assetId; + if (costumeAsset.assetType === AssetType.ImageVector) { + costume.skinId = runtime.renderer.createSVGSkin(costumeAsset.decodeText(), rotationCenter); + return costume; } - if (assetType === AssetType.ImageVector) { - promise = promise.then(costumeAsset => { - costume.skinId = runtime.renderer.createSVGSkin(costumeAsset.decodeText(), rotationCenter); - return costume; - }); - } else { - promise = promise.then(costumeAsset => ( - new Promise((resolve, reject) => { - const imageElement = new Image(); - const onError = function () { + return new Promise((resolve, reject) => { + const imageElement = new Image(); + const onError = function () { // eslint-disable-next-line no-use-before-define - removeEventListeners(); - reject(); - }; - const onLoad = function () { + removeEventListeners(); + reject(); + }; + const onLoad = function () { // eslint-disable-next-line no-use-before-define - removeEventListeners(); - resolve(imageElement); - }; - const removeEventListeners = function () { - imageElement.removeEventListener('error', onError); - imageElement.removeEventListener('load', onLoad); - }; - imageElement.addEventListener('error', onError); - imageElement.addEventListener('load', onLoad); - imageElement.src = costumeAsset.encodeDataURI(); - }) - )).then(imageElement => { - costume.skinId = runtime.renderer.createBitmapSkin(imageElement, costume.bitmapResolution, rotationCenter); - return costume; - }); - } - return promise; + removeEventListeners(); + resolve(imageElement); + }; + const removeEventListeners = function () { + imageElement.removeEventListener('error', onError); + imageElement.removeEventListener('load', onLoad); + }; + imageElement.addEventListener('error', onError); + imageElement.addEventListener('load', onLoad); + imageElement.src = costumeAsset.encodeDataURI(); + }).then(imageElement => { + costume.skinId = runtime.renderer.createBitmapSkin(imageElement, costume.bitmapResolution, rotationCenter); + return costume; + }); }; +loadCostume.loadCostumeFromAsset = loadCostumeFromAsset; + module.exports = loadCostume; diff --git a/src/import/load-sound.js b/src/import/load-sound.js index 8f4f9edff..84425c189 100644 --- a/src/import/load-sound.js +++ b/src/import/load-sound.js @@ -23,18 +23,22 @@ const loadSound = function (sound, runtime) { const ext = idParts[1].toLowerCase(); return runtime.storage.load(runtime.storage.AssetType.Sound, md5, ext) .then(soundAsset => { - sound.assetId = soundAsset.assetId; sound.dataFormat = ext; - return runtime.audioEngine.decodeSound(Object.assign( - {}, - sound, - {data: soundAsset.data} - )); - }) - .then(soundId => { - sound.soundId = soundId; - return sound; + return loadSoundFromAsset(sound, soundAsset, runtime); }); }; +const loadSoundFromAsset = function (sound, soundAsset, runtime) { + sound.assetId = soundAsset.assetId; + return runtime.audioEngine.decodeSound(Object.assign( + {}, + sound, + {data: soundAsset.data} + )).then(soundId => { + sound.soundId = soundId; + return sound; + }); +}; + +loadSound.loadSoundFromAsset = loadSoundFromAsset; module.exports = loadSound; diff --git a/src/sprites/rendered-target.js b/src/sprites/rendered-target.js index bbf85231c..653bc4efd 100644 --- a/src/sprites/rendered-target.js +++ b/src/sprites/rendered-target.js @@ -787,6 +787,33 @@ class RenderedTarget extends Target { return newClone; } + /** + * Make a duplicate using a duplicate sprite. + * @return {RenderedTarget} New clone. + */ + duplicate () { + return this.sprite.duplicate().then(newSprite => { + const newTarget = newSprite.createClone(); + // Copy all properties. + // @todo refactor with clone methods + newTarget.x = Math.random() * 400 / 2; + newTarget.y = Math.random() * 300 / 2; + newTarget.direction = this.direction; + newTarget.draggable = this.draggable; + newTarget.visible = this.visible; + newTarget.size = this.size; + newTarget.currentCostume = this.currentCostume; + newTarget.rotationStyle = this.rotationStyle; + newTarget.effects = JSON.parse(JSON.stringify(this.effects)); + newTarget.variables = JSON.parse(JSON.stringify(this.variables)); + newTarget.lists = JSON.parse(JSON.stringify(this.lists)); + newTarget.initDrawable(); + newTarget.updateAllDrawableProperties(); + newTarget.goBehindOther(this); + return newTarget; + }); + } + /** * Called when the project receives a "green flag." * For a rendered target, this clears graphic effects. diff --git a/src/sprites/sprite.js b/src/sprites/sprite.js index 9e36c8fea..ee5b9394c 100644 --- a/src/sprites/sprite.js +++ b/src/sprites/sprite.js @@ -1,5 +1,8 @@ const RenderedTarget = require('./rendered-target'); const Blocks = require('../engine/blocks'); +const {loadSoundFromAsset} = require('../import/load-sound'); +const {loadCostumeFromAsset} = require('../import/load-costume'); +const StringUtil = require('../util/string-util'); class Sprite { /** @@ -73,6 +76,33 @@ class Sprite { this.clones.splice(cloneIndex, 1); } } + + duplicate () { + const newSprite = new Sprite(null, this.runtime); + + newSprite.blocks = this.blocks.duplicate(); + + const allNames = this.runtime.targets.map(t => t.name); + newSprite.name = StringUtil.unusedName(this.name, allNames); + + const assetPromises = []; + + newSprite.costumes = this.costumes.map(costume => { + const newCostume = Object.assign({}, costume); + const costumeAsset = this.runtime.storage.get(costume.assetId); + assetPromises.push(loadCostumeFromAsset(newCostume, costumeAsset, this.runtime)); + return newCostume; + }); + + newSprite.sounds = this.sounds.map(sound => { + const newSound = Object.assign({}, sound); + const soundAsset = this.runtime.storage.get(sound.assetId); + assetPromises.push(loadSoundFromAsset(newSound, soundAsset, this.runtime)); + return newSound; + }); + + return Promise.all(assetPromises).then(() => newSprite); + } } module.exports = Sprite; diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 762ef8c01..0109f9c26 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -439,6 +439,31 @@ class VirtualMachine extends EventEmitter { } } + /** + * Duplicate a sprite. + * @param {string} targetId ID of a target whose sprite to duplicate. + */ + duplicateSprite (targetId) { + const target = this.runtime.getTargetById(targetId); + + if (target) { + if (!target.isSprite()) { + throw new Error('Cannot duplicate non-sprite targets.'); + } + const sprite = target.sprite; + if (!sprite) { + throw new Error('No sprite associated with this target.'); + } + + target.duplicate().then(newTarget => { + this.runtime.targets.push(newTarget); + this.setEditingTarget(newTarget.id); + }); + } else { + throw new Error('No target with the provided id.'); + } + } + /** * Set the audio engine for the VM/runtime * @param {!AudioEngine} audioEngine The audio engine to attach From 81370f762516851f3739defc4ba69a7cd6f7cbb7 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 11 Sep 2017 09:42:16 -0400 Subject: [PATCH 025/272] Refactor method exports to fix linting and CWF comment --- src/import/load-costume.js | 100 +++++++++++++++++------------- src/import/load-sound.js | 37 +++++++---- src/serialization/sb2.js | 4 +- src/serialization/sb3.js | 4 +- src/virtual-machine.js | 4 +- test/integration/sb3-roundtrip.js | 4 +- 6 files changed, 88 insertions(+), 65 deletions(-) diff --git a/src/import/load-costume.js b/src/import/load-costume.js index 9e2f165b6..b55f07ed6 100644 --- a/src/import/load-costume.js +++ b/src/import/load-costume.js @@ -1,6 +1,59 @@ const StringUtil = require('../util/string-util'); const log = require('../util/log'); +/** + * Initialize a costume from an asset asynchronously. + * Do not call this unless there is a renderer attached. + * @param {!object} costume - the Scratch costume object. + * @property {int} skinId - the ID of the costume's render skin, once installed. + * @property {number} rotationCenterX - the X component of the costume's origin. + * @property {number} rotationCenterY - the Y component of the costume's origin. + * @property {number} [bitmapResolution] - the resolution scale for a bitmap costume. + * @param {!Asset} costumeAsset - the asset of the costume loaded from storage. + * @param {!Runtime} runtime - Scratch runtime, used to access the storage module. + * @returns {?Promise} - a promise which will resolve after skinId is set, or null on error. + */ +const loadCostumeFromAsset = function (costume, costumeAsset, runtime) { + costume.assetId = costumeAsset.assetId; + if (!runtime.renderer) { + log.error('No rendering module present; cannot load costume: ', costume.name); + return costume; + } + const AssetType = runtime.storage.AssetType; + const rotationCenter = [ + costume.rotationCenterX / costume.bitmapResolution, + costume.rotationCenterY / costume.bitmapResolution + ]; + if (costumeAsset.assetType === AssetType.ImageVector) { + costume.skinId = runtime.renderer.createSVGSkin(costumeAsset.decodeText(), rotationCenter); + return costume; + } + + return new Promise((resolve, reject) => { + const imageElement = new Image(); + const onError = function () { + // eslint-disable-next-line no-use-before-define + removeEventListeners(); + reject(); + }; + const onLoad = function () { + // eslint-disable-next-line no-use-before-define + removeEventListeners(); + resolve(imageElement); + }; + const removeEventListeners = function () { + imageElement.removeEventListener('error', onError); + imageElement.removeEventListener('load', onLoad); + }; + imageElement.addEventListener('error', onError); + imageElement.addEventListener('load', onLoad); + imageElement.src = costumeAsset.encodeDataURI(); + }).then(imageElement => { + costume.skinId = runtime.renderer.createBitmapSkin(imageElement, costume.bitmapResolution, rotationCenter); + return costume; + }); +}; + /** * Load a costume's asset into memory asynchronously. * Do not call this unless there is a renderer attached. @@ -31,48 +84,7 @@ const loadCostume = function (md5ext, costume, runtime) { }); }; -const loadCostumeFromAsset = function (costume, costumeAsset, runtime) { - const rotationCenter = [ - costume.rotationCenterX / costume.bitmapResolution, - costume.rotationCenterY / costume.bitmapResolution - ]; - - if (!runtime.renderer) { - log.error('No rendering module present; cannot load costume asset: ', md5ext); - return costume; - } - const AssetType = runtime.storage.AssetType; - costume.assetId = costumeAsset.assetId; - if (costumeAsset.assetType === AssetType.ImageVector) { - costume.skinId = runtime.renderer.createSVGSkin(costumeAsset.decodeText(), rotationCenter); - return costume; - } - - return new Promise((resolve, reject) => { - const imageElement = new Image(); - const onError = function () { - // eslint-disable-next-line no-use-before-define - removeEventListeners(); - reject(); - }; - const onLoad = function () { - // eslint-disable-next-line no-use-before-define - removeEventListeners(); - resolve(imageElement); - }; - const removeEventListeners = function () { - imageElement.removeEventListener('error', onError); - imageElement.removeEventListener('load', onLoad); - }; - imageElement.addEventListener('error', onError); - imageElement.addEventListener('load', onLoad); - imageElement.src = costumeAsset.encodeDataURI(); - }).then(imageElement => { - costume.skinId = runtime.renderer.createBitmapSkin(imageElement, costume.bitmapResolution, rotationCenter); - return costume; - }); +module.exports = { + loadCostume, + loadCostumeFromAsset }; - -loadCostume.loadCostumeFromAsset = loadCostumeFromAsset; - -module.exports = loadCostume; diff --git a/src/import/load-sound.js b/src/import/load-sound.js index 84425c189..e4c7009b9 100644 --- a/src/import/load-sound.js +++ b/src/import/load-sound.js @@ -1,6 +1,27 @@ const StringUtil = require('../util/string-util'); const log = require('../util/log'); +/** + * Initialize a sound from an asset asynchronously. + * @param {!object} sound - the Scratch sound object. + * @property {string} md5 - the MD5 and extension of the sound to be loaded. + * @property {Buffer} data - sound data will be written here once loaded. + * @param {!Asset} soundAsset - the asset loaded from storage. + * @param {!Runtime} runtime - Scratch runtime, used to access the storage module. + * @returns {!Promise} - a promise which will resolve to the sound when ready. + */ +const loadSoundFromAsset = function (sound, soundAsset, runtime) { + sound.assetId = soundAsset.assetId; + return runtime.audioEngine.decodeSound(Object.assign( + {}, + sound, + {data: soundAsset.data} + )).then(soundId => { + sound.soundId = soundId; + return sound; + }); +}; + /** * Load a sound's asset into memory asynchronously. * @param {!object} sound - the Scratch sound object. @@ -28,17 +49,7 @@ const loadSound = function (sound, runtime) { }); }; -const loadSoundFromAsset = function (sound, soundAsset, runtime) { - sound.assetId = soundAsset.assetId; - return runtime.audioEngine.decodeSound(Object.assign( - {}, - sound, - {data: soundAsset.data} - )).then(soundId => { - sound.soundId = soundId; - return sound; - }); +module.exports = { + loadSound, + loadSoundFromAsset }; - -loadSound.loadSoundFromAsset = loadSoundFromAsset; -module.exports = loadSound; diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js index 48e89f448..84560881a 100644 --- a/src/serialization/sb2.js +++ b/src/serialization/sb2.js @@ -15,8 +15,8 @@ const specMap = require('./sb2_specmap'); const Variable = require('../engine/variable'); const List = require('../engine/list'); -const loadCostume = require('../import/load-costume.js'); -const loadSound = require('../import/load-sound.js'); +const {loadCostume} = require('../import/load-costume.js'); +const {loadSound} = require('../import/load-sound.js'); /** * Convert a Scratch 2.0 procedure string (e.g., "my_procedure %s %b %n") diff --git a/src/serialization/sb3.js b/src/serialization/sb3.js index 35267a5e2..ad91cce78 100644 --- a/src/serialization/sb3.js +++ b/src/serialization/sb3.js @@ -10,8 +10,8 @@ const Sprite = require('../sprites/sprite'); const Variable = require('../engine/variable'); const List = require('../engine/list'); -const loadCostume = require('../import/load-costume.js'); -const loadSound = require('../import/load-sound.js'); +const {loadCostume} = require('../import/load-costume.js'); +const {loadSound} = require('../import/load-sound.js'); /** * Serializes the specified VM runtime. diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 0109f9c26..17df958be 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -6,8 +6,8 @@ const sb2 = require('./serialization/sb2'); const sb3 = require('./serialization/sb3'); const StringUtil = require('./util/string-util'); -const loadCostume = require('./import/load-costume.js'); -const loadSound = require('./import/load-sound.js'); +const {loadCostume} = require('./import/load-costume.js'); +const {loadSound} = require('./import/load-sound.js'); const RESERVED_NAMES = ['_mouse_', '_stage_', '_edge_', '_myself_', '_random_']; diff --git a/test/integration/sb3-roundtrip.js b/test/integration/sb3-roundtrip.js index c401248bd..058169a8d 100644 --- a/test/integration/sb3-roundtrip.js +++ b/test/integration/sb3-roundtrip.js @@ -2,8 +2,8 @@ const test = require('tap').test; const Blocks = require('../../src/engine/blocks'); const Clone = require('../../src/util/clone'); -const loadCostume = require('../../src/import/load-costume'); -const loadSound = require('../../src/import/load-sound'); +const {loadCostume} = require('../../src/import/load-costume'); +const {loadSound} = require('../../src/import/load-sound'); const makeTestStorage = require('../fixtures/make-test-storage'); const Runtime = require('../../src/engine/runtime'); const sb3 = require('../../src/serialization/sb3'); From 4a7ba534c1a507248d72e0aab77d265e3ff51305 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 11 Sep 2017 15:15:30 -0400 Subject: [PATCH 026/272] Fix linter --- src/import/load-costume.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/import/load-costume.js b/src/import/load-costume.js index b55f07ed6..a355edddc 100644 --- a/src/import/load-costume.js +++ b/src/import/load-costume.js @@ -32,12 +32,12 @@ const loadCostumeFromAsset = function (costume, costumeAsset, runtime) { return new Promise((resolve, reject) => { const imageElement = new Image(); const onError = function () { - // eslint-disable-next-line no-use-before-define + // eslint-disable-next-line no-use-before-define removeEventListeners(); reject(); }; const onLoad = function () { - // eslint-disable-next-line no-use-before-define + // eslint-disable-next-line no-use-before-define removeEventListeners(); resolve(imageElement); }; From a885e7d61973461c7fd254d0d4e3f955b5ea124c Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Tue, 12 Sep 2017 10:16:26 -0400 Subject: [PATCH 027/272] Refactor error throwing --- src/virtual-machine.js | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 17df958be..8bbaf7851 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -445,23 +445,17 @@ class VirtualMachine extends EventEmitter { */ duplicateSprite (targetId) { const target = this.runtime.getTargetById(targetId); - - if (target) { - if (!target.isSprite()) { - throw new Error('Cannot duplicate non-sprite targets.'); - } - const sprite = target.sprite; - if (!sprite) { - throw new Error('No sprite associated with this target.'); - } - - target.duplicate().then(newTarget => { - this.runtime.targets.push(newTarget); - this.setEditingTarget(newTarget.id); - }); - } else { + if (!target) { throw new Error('No target with the provided id.'); + } else if (!target.isSprite()) { + throw new Error('Cannot duplicate non-sprite targets.'); + } else if (!target.sprite) { + throw new Error('No sprite associated with this target.'); } + target.duplicate().then(newTarget => { + this.runtime.targets.push(newTarget); + this.setEditingTarget(newTarget.id); + }); } /** From 157a527def217136f6948b005c65edf13ef9f56d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Madsen?= Date: Fri, 22 Sep 2017 11:41:08 +0200 Subject: [PATCH 028/272] Use unqualified paths in package.json scripts This allows stuff like yarn workspaces to function with node_modules hoisted. --- package.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 2dac26a58..f7cf4d627 100644 --- a/package.json +++ b/package.json @@ -11,18 +11,18 @@ }, "main": "./dist/node/scratch-vm.js", "scripts": { - "build": "./node_modules/.bin/webpack --progress --colors --bail", - "coverage": "./node_modules/.bin/tap ./test/{unit,integration}/*.js --coverage --coverage-report=lcov", - "deploy": "touch playground/.nojekyll && ./node_modules/.bin/gh-pages -t -d playground -m \"Build for $(git log --pretty=format:%H -n1)\"", - "lint": "./node_modules/.bin/eslint .", + "build": "webpack --progress --colors --bail", + "coverage": "tap ./test/{unit,integration}/*.js --coverage --coverage-report=lcov", + "deploy": "touch playground/.nojekyll && gh-pages -t -d playground -m \"Build for $(git log --pretty=format:%H -n1)\"", + "lint": "eslint .", "prepublish": "in-publish && npm run build || not-in-publish", - "start": "./node_modules/.bin/webpack-dev-server", - "tap": "./node_modules/.bin/tap ./test/{unit,integration}/*.js", - "tap:unit": "./node_modules/.bin/tap ./test/unit/*.js", - "tap:integration": "./node_modules/.bin/tap ./test/integration/*.js", + "start": "webpack-dev-server", + "tap": "tap ./test/{unit,integration}/*.js", + "tap:unit": "tap ./test/unit/*.js", + "tap:integration": "tap ./test/integration/*.js", "test": "npm run lint && npm run tap", - "watch": "./node_modules/.bin/webpack --progress --colors --watch", - "version": "./node_modules/.bin/json -f package.json -I -e \"this.repository.sha = '$(git log -n1 --pretty=format:%H)'\"" + "watch": "webpack --progress --colors --watch", + "version": "json -f package.json -I -e \"this.repository.sha = '$(git log -n1 --pretty=format:%H)'\"" }, "devDependencies": { "adm-zip": "0.4.7", From 7a21d619bf0b0400fe49bdebae8d2fda55ce49a8 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Wed, 27 Sep 2017 00:00:59 -0400 Subject: [PATCH 029/272] Add a way to load an extension without a Worker The new `_registerInternalExtension` method on the extension manager will register an extension object (an object with a `getInfo()` method) with the extension system without sandboxing the object in a Worker. --- src/extension-support/extension-manager.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index 62a7a0cf8..1fc5b60de 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -103,6 +103,17 @@ class ExtensionManager { } } + /** + * Register an internal (non-Worker) extension object + * @param {object} extensionObject - the extension object to register + */ + _registerInternalExtension (extensionObject) { + const extensionInfo = extensionObject.getInfo(); + const serviceName = `extension.internal.${extensionInfo.id}`; + dispatch.setService(serviceName, extensionObject) + .then(() => dispatch.call('extensions', 'registerExtensionService', serviceName)); + } + _registerExtensionInfo (serviceName, extensionInfo) { extensionInfo = this._prepareExtensionInfo(serviceName, extensionInfo); dispatch.call('runtime', '_registerExtensionPrimitives', extensionInfo).catch(e => { @@ -162,6 +173,7 @@ class ExtensionManager { }, blockInfo); blockInfo.opcode = this._sanitizeID(blockInfo.opcode); blockInfo.func = blockInfo.func ? this._sanitizeID(blockInfo.func) : blockInfo.opcode; + blockInfo.text = blockInfo.text || blockInfo.opcode; blockInfo.func = dispatch.call.bind(dispatch, serviceName, blockInfo.func); return blockInfo; } From 06252e020b269fe44c75807a5e48a8f5e2523c4f Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Wed, 27 Sep 2017 00:02:53 -0400 Subject: [PATCH 030/272] Extensions: add support for color-picker arguments --- src/engine/runtime.js | 15 ++++++++------- src/extension-support/argument-type.js | 3 ++- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index a36081d60..d8a4ea998 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -33,6 +33,9 @@ const defaultBlockPackages = { */ const ArgumentTypeMap = (() => { const map = {}; + map[ArgumentType.COLOR] = { + shadowType: 'colour_picker' + }; map[ArgumentType.NUMBER] = { shadowType: 'math_number', fieldType: 'NUM' @@ -456,13 +459,11 @@ class Runtime extends EventEmitter { const argInfo = blockInfo.arguments[placeholder] || {}; const argTypeInfo = ArgumentTypeMap[argInfo.type] || {}; const defaultValue = (typeof argInfo.defaultValue === 'undefined' ? '' : argInfo.defaultValue.toString()); - inputList.push( - `` + - `` + - `${defaultValue}` + - '' + - '' - ); + inputList.push(``); + if (argTypeInfo.fieldType) { + inputList.push(`${defaultValue}`); + } + inputList.push(''); return `%${argNum}`; }); diff --git a/src/extension-support/argument-type.js b/src/extension-support/argument-type.js index 3fccff5ef..3f2aa9255 100644 --- a/src/extension-support/argument-type.js +++ b/src/extension-support/argument-type.js @@ -1,7 +1,8 @@ const ArgumentType = { NUMBER: 'number', STRING: 'string', - BOOLEAN: 'Boolean' + BOOLEAN: 'Boolean', + COLOR: 'color' }; module.exports = ArgumentType; From 59650b9dfd75364cd3fec2571c84e2fa1499ae7e Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Fri, 29 Sep 2017 19:14:25 +0000 Subject: [PATCH 031/272] chore(package): update script-loader to version 0.7.2 Closes #678 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2dac26a58..66b81c2c4 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "scratch-blocks": "latest", "scratch-render": "latest", "scratch-storage": "^0.2.0", - "script-loader": "0.7.0", + "script-loader": "0.7.2", "socket.io-client": "1.7.3", "stats.js": "^0.17.0", "tap": "^10.2.0", From 772da24d9eca610f9d0de2c63252000110e5fa20 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Mon, 2 Oct 2017 12:02:44 -0700 Subject: [PATCH 032/272] Add integration test for a non-worker extension --- src/extension-support/extension-manager.js | 3 +- test/integration/internal-extension.js | 51 ++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 test/integration/internal-extension.js diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index 1fc5b60de..827bc491d 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -106,11 +106,12 @@ class ExtensionManager { /** * Register an internal (non-Worker) extension object * @param {object} extensionObject - the extension object to register + * @returns {Promise} resolved once the extension is fully registered or rejected on failure */ _registerInternalExtension (extensionObject) { const extensionInfo = extensionObject.getInfo(); const serviceName = `extension.internal.${extensionInfo.id}`; - dispatch.setService(serviceName, extensionObject) + return dispatch.setService(serviceName, extensionObject) .then(() => dispatch.call('extensions', 'registerExtensionService', serviceName)); } diff --git a/test/integration/internal-extension.js b/test/integration/internal-extension.js new file mode 100644 index 000000000..52ac10a5a --- /dev/null +++ b/test/integration/internal-extension.js @@ -0,0 +1,51 @@ +const test = require('tap').test; +const Worker = require('tiny-worker'); + +const dispatch = require('../../src/dispatch/central-dispatch'); +const VirtualMachine = require('../../src/virtual-machine'); + +// By default Central Dispatch works with the Worker class built into the browser. Tell it to use TinyWorker instead. +dispatch.workerClass = Worker; + +class TestInternalExtension { + constructor () { + this.status = {}; + this.status.constructorCalled = true; + } + + getInfo () { + this.status.getInfoCalled = true; + return { + id: 'test-internal-extension', + name: 'Test Internal Extension', + blocks: [ + { + opcode: 'go' + } + ] + }; + } + + go () { + this.status.goCalled = true; + } +} + +test('internal extension', t => { + const vm = new VirtualMachine(); + + const extension = new TestInternalExtension(); + t.ok(extension.status.constructorCalled); + + t.notOk(extension.status.getInfoCalled); + return vm.extensionManager._registerInternalExtension(extension).then(() => { + t.ok(extension.status.getInfoCalled); + + const func = vm.runtime.getOpcodeFunction('test-internal-extension.go'); + t.type(func, 'function'); + + t.notOk(extension.status.goCalled); + func(); + t.ok(extension.status.goCalled); + }); +}); From 99b868c0f0ba0bd7a0d72c42becdd72c768d115a Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Mon, 2 Oct 2017 15:29:32 -0700 Subject: [PATCH 033/272] Explain when it's OK to omit element Also, alphabetize the `ArgumentType` and `BlockType` enums. --- src/engine/runtime.js | 7 +++++++ src/extension-support/argument-type.js | 6 +++--- src/extension-support/block-type.js | 6 +++--- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index d8a4ea998..1b3641ab7 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -459,10 +459,17 @@ class Runtime extends EventEmitter { const argInfo = blockInfo.arguments[placeholder] || {}; const argTypeInfo = ArgumentTypeMap[argInfo.type] || {}; const defaultValue = (typeof argInfo.defaultValue === 'undefined' ? '' : argInfo.defaultValue.toString()); + + // is the ScratchBlocks name for a block input. + // The is a placeholder for a reporter and is visible when there's no reporter in this input. inputList.push(``); + + // is a text field that the user can type into. Some shadows, like the color picker, don't allow + // text input and therefore don't need a field element. if (argTypeInfo.fieldType) { inputList.push(`${defaultValue}`); } + inputList.push(''); return `%${argNum}`; diff --git a/src/extension-support/argument-type.js b/src/extension-support/argument-type.js index 3f2aa9255..70381c84b 100644 --- a/src/extension-support/argument-type.js +++ b/src/extension-support/argument-type.js @@ -1,8 +1,8 @@ const ArgumentType = { - NUMBER: 'number', - STRING: 'string', BOOLEAN: 'Boolean', - COLOR: 'color' + COLOR: 'color', + NUMBER: 'number', + STRING: 'string' }; module.exports = ArgumentType; diff --git a/src/extension-support/block-type.js b/src/extension-support/block-type.js index 663e2e3e3..587f7d598 100644 --- a/src/extension-support/block-type.js +++ b/src/extension-support/block-type.js @@ -1,9 +1,9 @@ const BlockType = { - COMMAND: 'command', - REPORTER: 'reporter', BOOLEAN: 'Boolean', + COMMAND: 'command', + CONDITIONAL: 'conditional', HAT: 'hat', - CONDITIONAL: 'conditional' + REPORTER: 'reporter' }; module.exports = BlockType; From 0358d6c0c39973a212120d27179708daf959395f Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 4 Oct 2017 15:02:09 -0400 Subject: [PATCH 034/272] Remove label generation for extensions --- src/engine/runtime.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index a36081d60..ece787638 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -523,8 +523,6 @@ class Runtime extends EventEmitter { for (const categoryInfo of this._blockInfo) { const {name, color1, color2} = categoryInfo; xmlParts.push(``); - // @todo only add this label for user-loaded extensions? - xmlParts.push(`'); } From 6757fb6de987a1c42058e925f208efc66f123f4f Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Tue, 26 Sep 2017 23:34:07 -0400 Subject: [PATCH 035/272] Convert pen blocks into an "internal" extension --- src/blocks/scratch3_pen.js | 126 ++++++++++++++++++++++++++++++++----- src/engine/runtime.js | 1 - 2 files changed, 110 insertions(+), 17 deletions(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index b2f7d4b6d..d2b63ad7c 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -1,3 +1,5 @@ +const ArgumentType = require('../extension-support/argument-type'); +const BlockType = require('../extension-support/block-type'); const Cast = require('../util/cast'); const Clone = require('../util/clone'); const Color = require('../util/color'); @@ -235,24 +237,116 @@ class Scratch3PenBlocks { } /** - * Retrieve the block primitives implemented by this package. - * @return {object.} Mapping of opcode to Function. + * @returns {{id: string, name: string, blocks: []}} metadata for this extension and its blocks. */ - getPrimitives () { + getInfo () { return { - pen_clear: this.clear, - pen_stamp: this.stamp, - pen_pendown: this.penDown, - pen_penup: this.penUp, - pen_setpencolortocolor: this.setPenColorToColor, - pen_changepencolorby: this.changePenHueBy, - pen_setpencolortonum: this.setPenHueToNumber, - pen_changepenshadeby: this.changePenShadeBy, - pen_setpenshadeto: this.setPenShadeToNumber, - pen_changepensizeby: this.changePenSizeBy, - pen_setpensizeto: this.setPenSizeTo, - pen_changepentransparencyby: this.changePenTransparencyBy, - pen_setpentransparencyto: this.setPenTransparencyTo + id: 'pen', + name: 'Pen', + blocks: [ + { + opcode: 'clear', + blockType: BlockType.COMMAND, + arguments: { + NUM1: { + type: ArgumentType.NUMBER + }, + NUM2: { + type: ArgumentType.NUMBER + } + } + }, + { + opcode: 'stamp', + blockType: BlockType.COMMAND + }, + { + opcode: 'penDown', + blockType: BlockType.COMMAND, + text: 'pen down' + }, + { + opcode: 'penUp', + blockType: BlockType.COMMAND, + text: 'pen up' + }, + { + opcode: 'setPenColorToColor', + blockType: BlockType.COMMAND, + text: 'set pen color to [COLOR]', + arguments: { + COLOR: { + type: ArgumentType.COLOR + } + } + }, + { + opcode: 'changePenHueBy', + blockType: BlockType.COMMAND, + text: 'change pen color by [COLOR]', + arguments: { + COLOR: { + type: ArgumentType.NUMBER, + defaultValue: 10 + } + } + }, + { + opcode: 'setPenHueToNumber', + blockType: BlockType.COMMAND, + text: 'set pen color to [COLOR]', + arguments: { + COLOR: { + type: ArgumentType.NUMBER, + defaultValue: 0 + } + } + }, + { + opcode: 'changePenShadeBy', + blockType: BlockType.COMMAND, + text: 'change pen shade by [SHADE]', + arguments: { + SHADE: { + type: ArgumentType.NUMBER, + defaultValue: 10 + } + } + }, + { + opcode: 'setPenShadeToNumber', + blockType: BlockType.COMMAND, + text: 'set pen shade to [SHADE]', + arguments: { + SHADE: { + type: ArgumentType.NUMBER, + defaultValue: 50 + } + } + }, + { + opcode: 'changePenSizeBy', + blockType: BlockType.COMMAND, + text: 'change pen size by [SIZE]', + arguments: { + SIZE: { + type: ArgumentType.NUMBER, + defaultValue: 1 + } + } + }, + { + opcode: 'setPenSizeTo', + blockType: BlockType.COMMAND, + text: 'set pen size to [SIZE]', + arguments: { + SIZE: { + type: ArgumentType.NUMBER, + defaultValue: 1 + } + } + } + ] }; } diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 6d8ce1dd1..a6272b60f 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -19,7 +19,6 @@ const defaultBlockPackages = { scratch3_looks: require('../blocks/scratch3_looks'), scratch3_motion: require('../blocks/scratch3_motion'), scratch3_operators: require('../blocks/scratch3_operators'), - scratch3_pen: require('../blocks/scratch3_pen'), scratch3_sound: require('../blocks/scratch3_sound'), scratch3_sensing: require('../blocks/scratch3_sensing'), scratch3_data: require('../blocks/scratch3_data'), From e9aed49a054fa6f1779575c5d2cc3028ed3ab7bd Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Wed, 4 Oct 2017 12:16:27 -0700 Subject: [PATCH 036/272] Make `loadExtensionURL` handle built-in extensions WeDo2 and Pen blocks have been converted to internal extensions, and can now be loaded by giving `loadExtensionURL` the string 'pen' or 'wedo2' instead of an actual URL. --- src/blocks/scratch3_pen.js | 2 +- src/blocks/scratch3_wedo2.js | 200 ++++++++++++++++++--- src/extension-support/extension-manager.js | 29 ++- src/virtual-machine.js | 2 +- 4 files changed, 207 insertions(+), 26 deletions(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index d2b63ad7c..c6866f25d 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -237,7 +237,7 @@ class Scratch3PenBlocks { } /** - * @returns {{id: string, name: string, blocks: []}} metadata for this extension and its blocks. + * @returns {object} metadata for this extension and its blocks. */ getInfo () { return { diff --git a/src/blocks/scratch3_wedo2.js b/src/blocks/scratch3_wedo2.js index d79ef9096..bc0750f56 100644 --- a/src/blocks/scratch3_wedo2.js +++ b/src/blocks/scratch3_wedo2.js @@ -1,3 +1,5 @@ +const ArgumentType = require('../extension-support/argument-type'); +const BlockType = require('../extension-support/block-type'); const color = require('../util/color'); const log = require('../util/log'); @@ -398,6 +400,183 @@ class Scratch3WeDo2Blocks { this.runtime.HACK_WeDo2Blocks = this; } + /** + * @returns {object} metadata for this extension and its blocks. + */ + getInfo () { + return { + id: 'wedo2', + name: 'WeDo 2.0', + blocks: [ + { + opcode: 'motorOnFor', + text: 'turn [MOTOR_ID] on for [DURATION] seconds', + blockType: BlockType.COMMAND, + arguments: { + MOTOR_ID: { + type: ArgumentType.STRING, + menu: 'motorID', + defaultValue: MotorID.DEFAULT + }, + DURATION: { + type: ArgumentType.NUMBER, + defaultValue: 1 + } + } + }, + { + opcode: 'motorOn', + text: 'turn [MOTOR_ID] on', + blockType: BlockType.COMMAND, + arguments: { + MOTOR_ID: { + type: ArgumentType.STRING, + menu: 'motorID', + defaultValue: MotorID.DEFAULT + } + } + }, + { + opcode: 'motorOff', + text: 'turn [MOTOR_ID] off', + blockType: BlockType.COMMAND, + arguments: { + MOTOR_ID: { + type: ArgumentType.STRING, + menu: 'motorID', + defaultValue: MotorID.DEFAULT + } + } + }, + { + opcode: 'startMotorPower', + text: 'set [MOTOR_ID] power to [POWER]', + blockType: BlockType.COMMAND, + arguments: { + MOTOR_ID: { + type: ArgumentType.STRING, + menu: 'motorID', + defaultValue: MotorID.DEFAULT + }, + POWER: { + type: ArgumentType.NUMBER, + defaultValue: 100 + } + } + }, + { + opcode: 'startMotorDirection', + text: 'set [MOTOR_ID] direction to [DIRECTION]', + blockType: BlockType.COMMAND, + arguments: { + MOTOR_ID: { + type: ArgumentType.STRING, + menu: 'motorID', + defaultValue: MotorID.DEFAULT + }, + DIRECTION: { + type: ArgumentType.STRING, + menu: 'motorDirection', + defaultValue: MotorDirection.FORWARD + } + } + }, + { + opcode: 'setLightHue', + text: 'set light color to [HUE]', + blockType: BlockType.COMMAND, + arguments: { + HUE: { + type: ArgumentType.NUMBER, + defaultValue: 50 + } + } + }, + { + opcode: 'playNoteFor', + text: 'play note [NOTE] for [DURATION] seconds', + blockType: BlockType.COMMAND, + arguments: { + NOTE: { + type: ArgumentType.NUMBER, // TODO: ArgumentType.MIDI_NOTE? + defaultValue: 60 + }, + DURATION: { + type: ArgumentType.NUMBER, + defaultValue: 0.5 + } + } + }, + { + opcode: 'whenDistance', + text: 'when distance [OP] [REFERENCE]', + blockType: BlockType.HAT, + arguments: { + OP: { + type: ArgumentType.STRING, + menu: 'lessMore', + defaultValue: '<' + }, + REFERENCE: { + type: ArgumentType.NUMBER, + defaultValue: 50 + } + } + }, + { + opcode: 'whenTilted', + text: 'when tilted [DIRECTION]', + func: 'isTilted', + blockType: BlockType.HAT, + arguments: { + DIRECTION: { + type: ArgumentType.STRING, + menu: 'tiltDirectionAny', + defaultValue: TiltDirection.ANY + } + } + }, + { + opcode: 'getDistance', + text: 'distance', + blockType: BlockType.REPORTER + }, + { + opcode: 'isTilted', + text: 'tilted [DIRECTION]?', + blockType: BlockType.REPORTER, + arguments: { + DIRECTION: { + type: ArgumentType.STRING, + menu: 'tiltDirectionAny', + defaultValue: TiltDirection.ANY + } + } + }, + { + opcode: 'getTiltAngle', + text: 'tilt angle [DIRECTION]', + blockType: BlockType.REPORTER, + arguments: { + DIRECTION: { + type: ArgumentType.STRING, + menu: 'tiltDirection', + defaultValue: TiltDirection.UP + } + } + } + ], + menus: { + motorID: [MotorID.DEFAULT, MotorID.A, MotorID.B, MotorID.ALL], + motorDirection: [MotorDirection.FORWARD, MotorDirection.BACKWARD, MotorDirection.REVERSE], + tiltDirection: [TiltDirection.UP, TiltDirection.DOWN, TiltDirection.LEFT, TiltDirection.RIGHT], + tiltDirectionAny: + [TiltDirection.UP, TiltDirection.DOWN, TiltDirection.LEFT, TiltDirection.RIGHT, TiltDirection.ANY], + lessMore: ['<', '>'] + } + }; + } + /** * Use the Device Manager client to attempt to connect to a WeDo 2.0 device. */ @@ -427,27 +606,6 @@ class Scratch3WeDo2Blocks { }); } - /** - * Retrieve the block primitives implemented by this package. - * @return {object.} Mapping of opcode to Function. - */ - getPrimitives () { - return { - wedo2_motorOnFor: this.motorOnFor, - wedo2_motorOn: this.motorOn, - wedo2_motorOff: this.motorOff, - wedo2_startMotorPower: this.startMotorPower, - wedo2_setMotorDirection: this.setMotorDirection, - wedo2_setLightHue: this.setLightHue, - wedo2_playNoteFor: this.playNoteFor, - wedo2_whenDistance: this.whenDistance, - wedo2_whenTilted: this.whenTilted, - wedo2_getDistance: this.getDistance, - wedo2_isTilted: this.isTilted, - wedo2_getTiltAngle: this.getTiltAngle - }; - } - /** * Turn specified motor(s) on for a specified duration. * @param {object} args - the block's arguments. diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index 827bc491d..d5a3e07ea 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -3,6 +3,16 @@ const log = require('../util/log'); const BlockType = require('./block-type'); +// These extensions are currently built into the VM repository but should not be loaded at startup. +// TODO: move these out into a separate repository? +// TODO: change extension spec so that library info, including extension ID, can be collected through static methods +const Scratch3PenBlocks = require('../blocks/scratch3_pen'); +const Scratch3WeDo2Blocks = require('../blocks/scratch3_wedo2'); +const builtinExtensions = { + pen: Scratch3PenBlocks, + wedo2: Scratch3WeDo2Blocks +}; + /** * @typedef {object} ArgumentInfo - Information about an extension block argument * @property {ArgumentType} type - the type of value this argument can take @@ -39,7 +49,7 @@ const BlockType = require('./block-type'); */ class ExtensionManager { - constructor () { + constructor (runtime) { /** * The ID number to provide to the next extension worker. * @type {int} @@ -60,17 +70,30 @@ class ExtensionManager { */ this.pendingWorkers = []; + /** + * Keep a reference to the runtime so we can construct internal extension objects. + * TODO: remove this in favor of extensions accessing the runtime as a service. + * @type {Runtime} + */ + this.runtime = runtime; + dispatch.setService('extensions', this).catch(e => { log.error(`ExtensionManager was unable to register extension service: ${JSON.stringify(e)}`); }); } /** - * Load an extension by URL - * @param {string} extensionURL - the URL for the extension to load + * Load an extension by URL or internal extension ID + * @param {string} extensionURL - the URL for the extension to load OR the ID of an internal extension * @returns {Promise} resolved once the extension is loaded and initialized or rejected on failure */ loadExtensionURL (extensionURL) { + if (builtinExtensions.hasOwnProperty(extensionURL)) { + const extension = builtinExtensions[extensionURL]; + const extensionInstance = new extension(this.runtime); + return this._registerInternalExtension(extensionInstance); + } + return new Promise((resolve, reject) => { // If we `require` this at the global level it breaks non-webpack targets, including tests const ExtensionWorker = require('worker-loader?name=extension-worker.js!./extension-worker'); diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 721477f09..eec4d0752 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -68,7 +68,7 @@ class VirtualMachine extends EventEmitter { this.emit(Runtime.EXTENSION_ADDED, blocksInfo); }); - this.extensionManager = new ExtensionManager(); + this.extensionManager = new ExtensionManager(this.runtime); this.blockListener = this.blockListener.bind(this); this.flyoutBlockListener = this.flyoutBlockListener.bind(this); From dd20e097742d430fea8d2526cdd0ffc1773406ad Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Wed, 4 Oct 2017 12:48:08 -0700 Subject: [PATCH 037/272] Extensions: escape HTML entities in default values This prevents generation of invalid XML due to characters like '<' or '>' in fields' default values. Unfortunately the value comes back in its escaped form, so there's still more work to be done. --- package.json | 1 + src/engine/runtime.js | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 2dac26a58..dabd01f7b 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "babel-loader": "^7.0.0", "babel-preset-es2015": "^6.24.1", "copy-webpack-plugin": "4.0.1", + "escape-html": "1.0.3", "eslint": "^4.5.0", "eslint-config-scratch": "^4.0.0", "expose-loader": "0.7.3", diff --git a/src/engine/runtime.js b/src/engine/runtime.js index a6272b60f..c2ae3b3e1 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -1,5 +1,6 @@ const EventEmitter = require('events'); const {OrderedMap} = require('immutable'); +const escapeHtml = require('escape-html'); const ArgumentType = require('../extension-support/argument-type'); const Blocks = require('./blocks'); @@ -457,7 +458,9 @@ class Runtime extends EventEmitter { const argInfo = blockInfo.arguments[placeholder] || {}; const argTypeInfo = ArgumentTypeMap[argInfo.type] || {}; - const defaultValue = (typeof argInfo.defaultValue === 'undefined' ? '' : argInfo.defaultValue.toString()); + const defaultValue = (typeof argInfo.defaultValue === 'undefined' ? + '' : + escapeHtml(argInfo.defaultValue.toString())); // is the ScratchBlocks name for a block input. // The is a placeholder for a reporter and is visible when there's no reporter in this input. From b6727a766ff376a166b385c85e8e94fb4d92f012 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Wed, 4 Oct 2017 15:40:25 -0700 Subject: [PATCH 038/272] Fix pen tests --- src/dispatch/shared-dispatch.js | 10 ++++++++++ src/extension-support/extension-manager.js | 12 ++++++++++- src/serialization/sb2_specmap.js | 22 ++++++++++----------- test/integration/pen.js | 23 ++++++++++++++-------- 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/dispatch/shared-dispatch.js b/src/dispatch/shared-dispatch.js index 85d38bde2..1e4785bce 100644 --- a/src/dispatch/shared-dispatch.js +++ b/src/dispatch/shared-dispatch.js @@ -91,6 +91,16 @@ class SharedDispatch { } } + /** + * Check if a particular service lives on another worker. + * @param {string} service - the service to check. + * @returns {boolean} - true if the service is remote (calls must cross a Worker boundary), false otherwise. + * @private + */ + _isRemoteService (service) { + return this._getServiceProvider(service).isRemote; + } + /** * Like {@link call}, but force the call to be posted through a particular communication channel. * @param {object} provider - send the call through this object's `postMessage` function. diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index d5a3e07ea..bdbc274f1 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -198,7 +198,17 @@ class ExtensionManager { blockInfo.opcode = this._sanitizeID(blockInfo.opcode); blockInfo.func = blockInfo.func ? this._sanitizeID(blockInfo.func) : blockInfo.opcode; blockInfo.text = blockInfo.text || blockInfo.opcode; - blockInfo.func = dispatch.call.bind(dispatch, serviceName, blockInfo.func); + + /** + * This is only here because the VM performs poorly when blocks return promises. + * @TODO make it possible for the VM to resolve a promise and continue during the same frame. + */ + if (dispatch._isRemoteService(serviceName)) { + blockInfo.func = dispatch.call.bind(dispatch, serviceName, blockInfo.func); + } else { + const serviceObject = dispatch.services[serviceName]; + blockInfo.func = serviceObject[blockInfo.func].bind(serviceObject); + } return blockInfo; } } diff --git a/src/serialization/sb2_specmap.js b/src/serialization/sb2_specmap.js index 8f574624b..2024b239e 100644 --- a/src/serialization/sb2_specmap.js +++ b/src/serialization/sb2_specmap.js @@ -500,27 +500,27 @@ const specMap = { ] }, 'clearPenTrails': { - opcode: 'pen_clear', + opcode: 'pen.clear', argMap: [ ] }, 'stampCostume': { - opcode: 'pen_stamp', + opcode: 'pen.stamp', argMap: [ ] }, 'putPenDown': { - opcode: 'pen_pendown', + opcode: 'pen.penDown', argMap: [ ] }, 'putPenUp': { - opcode: 'pen_penup', + opcode: 'pen.penUp', argMap: [ ] }, 'penColor:': { - opcode: 'pen_setpencolortocolor', + opcode: 'pen.setPenColorToColor', argMap: [ { type: 'input', @@ -530,7 +530,7 @@ const specMap = { ] }, 'changePenHueBy:': { - opcode: 'pen_changepencolorby', + opcode: 'pen.changePenHueBy', argMap: [ { type: 'input', @@ -540,7 +540,7 @@ const specMap = { ] }, 'setPenHueTo:': { - opcode: 'pen_setpencolortonum', + opcode: 'pen.setPenHueToNumber', argMap: [ { type: 'input', @@ -550,7 +550,7 @@ const specMap = { ] }, 'changePenShadeBy:': { - opcode: 'pen_changepenshadeby', + opcode: 'pen.changePenShadeBy', argMap: [ { type: 'input', @@ -560,7 +560,7 @@ const specMap = { ] }, 'setPenShadeTo:': { - opcode: 'pen_setpenshadeto', + opcode: 'pen.setPenShadeToNumber', argMap: [ { type: 'input', @@ -570,7 +570,7 @@ const specMap = { ] }, 'changePenSizeBy:': { - opcode: 'pen_changepensizeby', + opcode: 'pen.changePenSizeBy', argMap: [ { type: 'input', @@ -580,7 +580,7 @@ const specMap = { ] }, 'penSize:': { - opcode: 'pen_setpensizeto', + opcode: 'pen.setPenSizeTo', argMap: [ { type: 'input', diff --git a/test/integration/pen.js b/test/integration/pen.js index 25c2121d8..025735bac 100644 --- a/test/integration/pen.js +++ b/test/integration/pen.js @@ -1,8 +1,10 @@ +const Worker = require('tiny-worker'); const path = require('path'); const test = require('tap').test; const Scratch3PenBlocks = require('../../src/blocks/scratch3_pen'); const VirtualMachine = require('../../src/index'); +const dispatch = require('../../src/dispatch/central-dispatch'); const makeTestStorage = require('../fixtures/make-test-storage'); const extract = require('../fixtures/extract'); @@ -10,6 +12,9 @@ const extract = require('../fixtures/extract'); const uri = path.resolve(__dirname, '../fixtures/pen.sb2'); const project = extract(uri); +// By default Central Dispatch works with the Worker class built into the browser. Tell it to use TinyWorker instead. +dispatch.workerClass = Worker; + test('pen', t => { const vm = new VirtualMachine(); vm.attachStorage(makeTestStorage()); @@ -42,14 +47,16 @@ test('pen', t => { vm.clear(); vm.setCompatibilityMode(false); vm.setTurboMode(false); - vm.loadProject(project).then(() => { - vm.greenFlag(); + vm.loadProject(project) + .then(() => vm.extensionManager.loadExtensionURL('pen')) /** @TODO: loadProject should load extensions */ + .then(() => { + vm.greenFlag(); - // After two seconds, get playground data and stop - setTimeout(() => { - vm.getPlaygroundData(); - vm.stopAll(); - }, 2000); - }); + // After two seconds, get playground data and stop + setTimeout(() => { + vm.getPlaygroundData(); + vm.stopAll(); + }, 2000); + }); }); }); From 3614a208b6eff41e56a76c5dca188f866ec7a8cd Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Thu, 5 Oct 2017 14:04:59 +0000 Subject: [PATCH 039/272] chore(package): update eslint-config-scratch to version 5.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2dac26a58..6176810a6 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "babel-preset-es2015": "^6.24.1", "copy-webpack-plugin": "4.0.1", "eslint": "^4.5.0", - "eslint-config-scratch": "^4.0.0", + "eslint-config-scratch": "^5.0.0", "expose-loader": "0.7.3", "gh-pages": "^0.12.0", "got": "5.7.1", From 43a17bdaa816eaffd307ad24cbda125bc55e6584 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 5 Oct 2017 10:24:20 -0400 Subject: [PATCH 040/272] Add say/think functionality to looks blocks --- src/blocks/scratch3_looks.js | 164 +++++++++++++++++++++++++++++++++-- 1 file changed, 157 insertions(+), 7 deletions(-) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index ca9dac2bd..6235e2ecf 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -1,4 +1,15 @@ const Cast = require('../util/cast'); +const Clone = require('../util/clone'); + +const RenderedTarget = require('../sprites/rendered-target'); + +/** + * @typedef {object} BubbleState - the bubble state associated with a particular target. + * @property {Boolean} onSpriteRight - tracks whether the bubble is right or left of the sprite. + * @property {?int} drawableId - the ID of the associated bubble Drawable, null if none. + * @property {string} text - the text of the bubble. + * @property {string} type - the type of the bubble, "say" or "think" + */ class Scratch3LooksBlocks { constructor (runtime) { @@ -7,6 +18,144 @@ class Scratch3LooksBlocks { * @type {Runtime} */ this.runtime = runtime; + + this._onTargetMoved = this._onTargetMoved.bind(this); + } + + /** + * The default bubble state, to be used when a target has no existing bubble state. + * @type {BubbleState} + */ + static get DEFAULT_BUBBLE_STATE () { + return { + drawableId: null, + onSpriteRight: true, + skinId: null, + text: '', + type: 'say' + }; + } + + /** + * The key to load & store a target's bubble-related state. + * @type {string} + */ + static get STATE_KEY () { + return 'Scratch.looks'; + } + + /** + * @param {Target} target - collect bubble state for this target. Probably, but not necessarily, a RenderedTarget. + * @returns {BubbleState} the mutable bubble state associated with that target. This will be created if necessary. + * @private + */ + _getBubbleState (target) { + let bubbleState = target.getCustomState(Scratch3LooksBlocks.STATE_KEY); + if (!bubbleState) { + bubbleState = Clone.simple(Scratch3LooksBlocks.DEFAULT_BUBBLE_STATE); + target.setCustomState(Scratch3LooksBlocks.STATE_KEY, bubbleState); + } + return bubbleState; + } + + /** + * @param {Target} target - collect bubble state for this target. Probably, but not necessarily, a RenderedTarget. + * @private + */ + _resetBubbleState (target) { + const defaultBubbleState = Clone.simple(Scratch3LooksBlocks.DEFAULT_BUBBLE_STATE); + target.setCustomState(Scratch3LooksBlocks.STATE_KEY, defaultBubbleState); + } + + /** + * Handle a target which has moved. This only fires when the bubble is visible. + * @param {RenderedTarget} target - the target which has moved. + * @private + */ + _onTargetMoved (target) { + const bubbleState = this._getBubbleState(target); + + if (bubbleState.drawableId) { + this._checkBubbleBounds(target); + this._positionBubble(target); + } + } + + _positionBubble (target) { + const bubbleState = this._getBubbleState(target); + const [bubbleWidth, bubbleHeight] = this.runtime.renderer.getSkinSize(bubbleState.drawableId); + const targetBounds = target.getBounds(); + const stageBounds = this.runtime.getTargetForStage().getBounds(); + + this.runtime.renderer.updateDrawableProperties(bubbleState.drawableId, { + position: [ + bubbleState.onSpriteRight ? targetBounds.right : targetBounds.left - bubbleWidth, + Math.min(stageBounds.top, targetBounds.top + bubbleHeight) + ] + }); + + this.runtime.requestRedraw(); + } + + _checkBubbleBounds (target) { + const bubbleState = this._getBubbleState(target); + const [bubbleWidth, _] = this.runtime.renderer.getSkinSize(bubbleState.drawableId); + const targetBounds = target.getBounds(); + const stageBounds = this.runtime.getTargetForStage().getBounds(); + if (bubbleState.onSpriteRight && bubbleWidth + targetBounds.right > stageBounds.right) { + bubbleState.onSpriteRight = false; + this._renderBubble(target); + } else if (!bubbleState.onSpriteRight && targetBounds.left - bubbleWidth < stageBounds.left) { + bubbleState.onSpriteRight = true; + this._renderBubble(target); + } + } + + _renderBubble (target) { + const bubbleState = this._getBubbleState(target); + const {type, text, onSpriteRight} = bubbleState; + + if (bubbleState.skinId) { + this.runtime.renderer.updateTextSkin(bubbleState.skinId, type, text, onSpriteRight, [0, 0]); + } else { + target.addListener(RenderedTarget.EVENT_TARGET_MOVED, this._onTargetMoved); + + bubbleState.drawableId = this.runtime.renderer.createDrawable(); + bubbleState.skinId = this.runtime.renderer.createTextSkin(type, text, bubbleState.onSpriteRight, [0, 0]); + + const order = this.runtime.renderer.getDrawableOrder(target.drawableID); + this.runtime.renderer.setDrawableOrder(bubbleState.drawableId, order + 1); + this.runtime.renderer.updateDrawableProperties(bubbleState.drawableId, { + skinId: bubbleState.skinId + }); + + this._checkBubbleBounds(target); + } + + this._positionBubble(target); + } + _updateBubble (target, type, text) { + const bubbleState = this._getBubbleState(target); + bubbleState.type = type; + bubbleState.text = text; + + this._renderBubble(target); + } + + _clearBubble (target) { + const bubbleState = this._getBubbleState(target); + if (bubbleState.drawableId) { + this.runtime.renderer.destroyDrawable(bubbleState.drawableId); + } + if (bubbleState.drawableId) { + this.runtime.renderer.destroySkin(bubbleState.skinId); + } + this._resetBubbleState(target); + + // @TODO is this safe? It could have been already removed? + target.removeListener(RenderedTarget.EVENT_TARGET_MOVED, this._onTargetMoved); + + this.runtime.requestRedraw(); } /** @@ -18,7 +167,7 @@ class Scratch3LooksBlocks { looks_say: this.say, looks_sayforsecs: this.sayforsecs, looks_think: this.think, - looks_thinkforsecs: this.sayforsecs, + looks_thinkforsecs: this.thinkforsecs, looks_show: this.show, looks_hide: this.hide, looks_switchcostumeto: this.switchCostume, @@ -41,30 +190,31 @@ class Scratch3LooksBlocks { } say (args, util) { - util.target.setSay('say', args.MESSAGE); + // @TODO in 2.0 calling say/think resets the right/left bias of the bubble + this._updateBubble(util.target, 'say', args.MESSAGE); } sayforsecs (args, util) { - util.target.setSay('say', args.MESSAGE); + this.say(args, util); return new Promise(resolve => { setTimeout(() => { // Clear say bubble and proceed. - util.target.setSay(); + this._clearBubble(util.target); resolve(); }, 1000 * args.SECS); }); } think (args, util) { - util.target.setSay('think', args.MESSAGE); + this._updateBubble(util.target, 'think', args.MESSAGE); } thinkforsecs (args, util) { - util.target.setSay('think', args.MESSAGE); + this.think(args, util); return new Promise(resolve => { setTimeout(() => { // Clear say bubble and proceed. - util.target.setSay(); + this._clearBubble(util.target); resolve(); }, 1000 * args.SECS); }); From 43d061227c0eb63cc268cf18bccf72d34cf307b5 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 5 Oct 2017 17:03:30 -0400 Subject: [PATCH 041/272] WIP --- src/blocks/scratch3_looks.js | 63 +++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index 6235e2ecf..99ec704b6 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -1,6 +1,6 @@ const Cast = require('../util/cast'); const Clone = require('../util/clone'); - +const Runtime = require('../engine/runtime'); const RenderedTarget = require('../sprites/rendered-target'); /** @@ -20,6 +20,11 @@ class Scratch3LooksBlocks { this.runtime = runtime; this._onTargetMoved = this._onTargetMoved.bind(this); + this._onResetBubbles = this._onResetBubbles.bind(this); + + // Reset all bubbles on start/stop + this.runtime.on('PROJECT_RUN_START', this._onResetBubbles); + this.runtime.on('PROJECT_RUN_STOP', this._onResetBubbles); } /** @@ -32,7 +37,8 @@ class Scratch3LooksBlocks { onSpriteRight: true, skinId: null, text: '', - type: 'say' + type: 'say', + visible: true }; } @@ -81,6 +87,16 @@ class Scratch3LooksBlocks { } } + _onResetBubbles () { + // for (let n = 0; n < this.runtime.targets.length; n++) { + // const target = this.runtime.targets[n]; + // const bubbleState = this._getBubbleState(target); + // if (bubbleState.drawableId) { + // this._clearBubble(target); + // } + // } + } + _positionBubble (target) { const bubbleState = this._getBubbleState(target); const [bubbleWidth, bubbleHeight] = this.runtime.renderer.getSkinSize(bubbleState.drawableId); @@ -116,15 +132,27 @@ class Scratch3LooksBlocks { const {type, text, onSpriteRight} = bubbleState; if (bubbleState.skinId) { + if (!bubbleState.visible) { + bubbleState.visible = true; + this.runtime.renderer.updateDrawableProperties(bubbleState.drawableId, { + visible: bubbleState.visible + }); + } this.runtime.renderer.updateTextSkin(bubbleState.skinId, type, text, onSpriteRight, [0, 0]); } else { target.addListener(RenderedTarget.EVENT_TARGET_MOVED, this._onTargetMoved); + // TODO is there a way to figure out before rendering whether to default left or right? + const targetBounds = target.getBounds(); + const stageBounds = this.runtime.getTargetForStage().getBounds(); + if (targetBounds.right + 170 > stageBounds.right) { + bubbleState.onSpriteRight = false; + } + bubbleState.drawableId = this.runtime.renderer.createDrawable(); bubbleState.skinId = this.runtime.renderer.createTextSkin(type, text, bubbleState.onSpriteRight, [0, 0]); - const order = this.runtime.renderer.getDrawableOrder(target.drawableID); - this.runtime.renderer.setDrawableOrder(bubbleState.drawableId, order + 1); + this.runtime.renderer.setDrawableOrder(bubbleState.drawableId, Infinity); this.runtime.renderer.updateDrawableProperties(bubbleState.drawableId, { skinId: bubbleState.skinId }); @@ -134,23 +162,26 @@ class Scratch3LooksBlocks { this._positionBubble(target); } - _updateBubble (target, type, text) { - const bubbleState = this._getBubbleState(target); - bubbleState.type = type; - bubbleState.text = text; - this._renderBubble(target); + _updateBubble (target, type, text) { + // Say/think empty string should clear any bubble + if (text === '') { + this._clearBubble(target); + } else { + const bubbleState = this._getBubbleState(target); + bubbleState.type = type; + bubbleState.text = text; + + this._renderBubble(target); + } } _clearBubble (target) { const bubbleState = this._getBubbleState(target); - if (bubbleState.drawableId) { - this.runtime.renderer.destroyDrawable(bubbleState.drawableId); - } - if (bubbleState.drawableId) { - this.runtime.renderer.destroySkin(bubbleState.skinId); - } - this._resetBubbleState(target); + bubbleState.visible = false; + this.runtime.renderer.updateDrawableProperties(bubbleState.drawableId, { + visible: bubbleState.visible + }); // @TODO is this safe? It could have been already removed? target.removeListener(RenderedTarget.EVENT_TARGET_MOVED, this._onTargetMoved); From 7297341c51a6dd340c9c516df058e8e098843765 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Fri, 6 Oct 2017 09:36:27 -0700 Subject: [PATCH 042/272] Fixups from code review - Remove WeDo 2 extension from the runtime's default block packages list - The WeDo 2.0 extension now calls its own `connect` method on startup I also renamed `EXTENSION_NAME` to `EXTENSION_ID` for consistency with the rest of the extension system. --- src/blocks/scratch3_wedo2.js | 10 +++++----- src/engine/runtime.js | 3 +-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/blocks/scratch3_wedo2.js b/src/blocks/scratch3_wedo2.js index bc0750f56..5e0dc183b 100644 --- a/src/blocks/scratch3_wedo2.js +++ b/src/blocks/scratch3_wedo2.js @@ -373,9 +373,9 @@ const TiltDirection = { class Scratch3WeDo2Blocks { /** - * @return {string} - the name of this extension. + * @return {string} - the ID of this extension. */ - static get EXTENSION_NAME () { + static get EXTENSION_ID () { return 'wedo2'; } @@ -397,7 +397,7 @@ class Scratch3WeDo2Blocks { */ this.runtime = runtime; - this.runtime.HACK_WeDo2Blocks = this; + this.connect(); } /** @@ -405,7 +405,7 @@ class Scratch3WeDo2Blocks { */ getInfo () { return { - id: 'wedo2', + id: Scratch3WeDo2Blocks.EXTENSION_ID, name: 'WeDo 2.0', blocks: [ { @@ -586,7 +586,7 @@ class Scratch3WeDo2Blocks { } const deviceManager = this.runtime.ioDevices.deviceManager; const finder = this._finder = - deviceManager.searchAndConnect(Scratch3WeDo2Blocks.EXTENSION_NAME, WeDo2.DEVICE_TYPE); + deviceManager.searchAndConnect(Scratch3WeDo2Blocks.EXTENSION_ID, WeDo2.DEVICE_TYPE); this._finder.promise.then( socket => { if (this._finder === finder) { diff --git a/src/engine/runtime.js b/src/engine/runtime.js index c2ae3b3e1..dc76452b7 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -23,8 +23,7 @@ const defaultBlockPackages = { scratch3_sound: require('../blocks/scratch3_sound'), scratch3_sensing: require('../blocks/scratch3_sensing'), scratch3_data: require('../blocks/scratch3_data'), - scratch3_procedures: require('../blocks/scratch3_procedures'), - scratch3_wedo2: require('../blocks/scratch3_wedo2') + scratch3_procedures: require('../blocks/scratch3_procedures') }; /** From 14600d78935fe8762f792535a4465ab7a41da909 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 6 Oct 2017 13:43:07 -0400 Subject: [PATCH 043/272] Update looks implementation --- src/blocks/scratch3_looks.js | 90 +++++++++++++++++++++++++++--------- src/engine/runtime.js | 28 ++++++++++- src/sprites/sprite.js | 1 + 3 files changed, 96 insertions(+), 23 deletions(-) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index 99ec704b6..449bfd05a 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -21,10 +21,11 @@ class Scratch3LooksBlocks { this._onTargetMoved = this._onTargetMoved.bind(this); this._onResetBubbles = this._onResetBubbles.bind(this); + this._onTargetWillExit = this._onTargetWillExit.bind(this); // Reset all bubbles on start/stop - this.runtime.on('PROJECT_RUN_START', this._onResetBubbles); - this.runtime.on('PROJECT_RUN_STOP', this._onResetBubbles); + this.runtime.on('PROJECT_STOP_ALL', this._onResetBubbles); + this.runtime.on('targetWasRemoved', this._onTargetWillExit); } /** @@ -74,29 +75,54 @@ class Scratch3LooksBlocks { } /** - * Handle a target which has moved. This only fires when the bubble is visible. + * Handle a target which has moved. * @param {RenderedTarget} target - the target which has moved. * @private */ _onTargetMoved (target) { const bubbleState = this._getBubbleState(target); - if (bubbleState.drawableId) { + if (bubbleState.drawableId && bubbleState.visible) { this._checkBubbleBounds(target); this._positionBubble(target); } } - _onResetBubbles () { - // for (let n = 0; n < this.runtime.targets.length; n++) { - // const target = this.runtime.targets[n]; - // const bubbleState = this._getBubbleState(target); - // if (bubbleState.drawableId) { - // this._clearBubble(target); - // } - // } + /** + * Handle a target which has moved. + * @param {RenderedTarget} target - the target which has moved. + * @private + */ + _onTargetWillExit (target) { + const bubbleState = this._getBubbleState(target); + if (bubbleState.drawableId) { + this.runtime.renderer.destroyDrawable(bubbleState.drawableId); + } + if (bubbleState.skinId) { + this.runtime.renderer.destroySkin(bubbleState.skinId); + } + } + /** + * Handle project start/stop by clearing all visible bubbles. + * @private + */ + _onResetBubbles () { + for (let n = 0; n < this.runtime.targets.length; n++) { + const target = this.runtime.targets[n]; + const bubbleState = this._getBubbleState(target); + if (bubbleState.drawableId) { + this._clearBubble(target); + } + } + } + + /** + * Position the bubble of a target. + * @param {!Target} target Target whose bubble needs positioning. + * @private + */ _positionBubble (target) { const bubbleState = this._getBubbleState(target); const [bubbleWidth, bubbleHeight] = this.runtime.renderer.getSkinSize(bubbleState.drawableId); @@ -113,6 +139,12 @@ class Scratch3LooksBlocks { this.runtime.requestRedraw(); } + /** + * Check whether a bubble needs to be flipped. If so, flip the `onSpriteRight` state + * and call the bubble render again. + * @param {!Target} target Target whose bubble needs positioning. + * @private + */ _checkBubbleBounds (target) { const bubbleState = this._getBubbleState(target); const [bubbleWidth, _] = this.runtime.renderer.getSkinSize(bubbleState.drawableId); @@ -127,6 +159,13 @@ class Scratch3LooksBlocks { } } + /** + * Create a visible bubble for a target. If a bubble exists for the target, + * just set it to visible and update the type/text. Otherwise create a new + * bubble and update the relevant custom state. + * @param {!Target} target Target who needs a bubble. + * @private + */ _renderBubble (target) { const bubbleState = this._getBubbleState(target); const {type, text, onSpriteRight} = bubbleState; @@ -163,29 +202,38 @@ class Scratch3LooksBlocks { this._positionBubble(target); } + /** + * The entry point for say/think blocks. Clears existing bubble if the text is empty. + * Set the bubble custom state and then call _renderBubble. + * @param {!Target} target Target that say/think blocks are being called on. + * @param {!string} type Either "say" or "think" + * @param {!string} text The text for the bubble, empty string clears the bubble. + * @private + */ _updateBubble (target, type, text) { - // Say/think empty string should clear any bubble if (text === '') { this._clearBubble(target); } else { const bubbleState = this._getBubbleState(target); bubbleState.type = type; bubbleState.text = text; - this._renderBubble(target); } } + /** + * Hide the bubble for a given target. + * @param {!Target} target Target that say/think blocks are being called on. + * @private + */ _clearBubble (target) { const bubbleState = this._getBubbleState(target); bubbleState.visible = false; - this.runtime.renderer.updateDrawableProperties(bubbleState.drawableId, { - visible: bubbleState.visible - }); - - // @TODO is this safe? It could have been already removed? - target.removeListener(RenderedTarget.EVENT_TARGET_MOVED, this._onTargetMoved); - + if (bubbleState.drawableId) { + this.runtime.renderer.updateDrawableProperties(bubbleState.drawableId, { + visible: bubbleState.visible + }); + } this.runtime.requestRedraw(); } diff --git a/src/engine/runtime.js b/src/engine/runtime.js index a36081d60..dc3f7c128 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -280,7 +280,8 @@ class Runtime extends EventEmitter { } /** - * Event name for glowing the green flag + * Event name when threads start running. + * Used by the UI to indicate running status. * @const {string} */ static get PROJECT_RUN_START () { @@ -288,13 +289,23 @@ class Runtime extends EventEmitter { } /** - * Event name for unglowing the green flag + * Event name when threads stop running + * Used by the UI to indicate not-running status. * @const {string} */ static get PROJECT_RUN_STOP () { return 'PROJECT_RUN_STOP'; } + /** + * Event name for project being stopped or restarted by the user. + * Used by blocks that need to reset state. + * @const {string} + */ + static get PROJECT_STOP_ALL () { + return 'PROJECT_STOP_ALL'; + } + /** * Event name for visual value report. * @const {string} @@ -905,6 +916,9 @@ class Runtime extends EventEmitter { * Stop "everything." */ stopAll () { + // Emit stop event to allow blocks to clean up any state. + this.emit(Runtime.PROJECT_STOP_ALL); + // Dispose all clones. const newTargets = []; for (let i = 0; i < this.targets.length; i++) { @@ -1227,6 +1241,16 @@ class Runtime extends EventEmitter { this.emit('targetWasCreated', newTarget, sourceTarget); } + /** + * Report that a new target has been created, possibly by cloning an existing target. + * @param {Target} newTarget - the newly created target. + * @param {Target} [sourceTarget] - the target used as a source for the new clone, if any. + * @fires Runtime#targetWasCreated + */ + fireTargetWasRemoved (newTarget, sourceTarget) { + this.emit('targetWasRemoved', newTarget, sourceTarget); + } + /** * Get a target representing the Scratch stage, if one exists. * @return {?Target} The target, if found. diff --git a/src/sprites/sprite.js b/src/sprites/sprite.js index ee5b9394c..268184343 100644 --- a/src/sprites/sprite.js +++ b/src/sprites/sprite.js @@ -71,6 +71,7 @@ class Sprite { * @param {!RenderedTarget} clone - the clone to be removed. */ removeClone (clone) { + this.runtime.fireTargetWasRemoved(clone); const cloneIndex = this.clones.indexOf(clone); if (cloneIndex >= 0) { this.clones.splice(cloneIndex, 1); From ef3feca3856cb1b004cfabf3a54e3ad8f3abde48 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Fri, 6 Oct 2017 10:56:38 -0700 Subject: [PATCH 044/272] Fix typo in WeDo 2.0 blocks metadata --- src/blocks/scratch3_wedo2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blocks/scratch3_wedo2.js b/src/blocks/scratch3_wedo2.js index 5e0dc183b..103694410 100644 --- a/src/blocks/scratch3_wedo2.js +++ b/src/blocks/scratch3_wedo2.js @@ -465,7 +465,7 @@ class Scratch3WeDo2Blocks { } }, { - opcode: 'startMotorDirection', + opcode: 'setMotorDirection', text: 'set [MOTOR_ID] direction to [DIRECTION]', blockType: BlockType.COMMAND, arguments: { From b0870518a4ffe7cf991159ea1101d4d4c6a26ba8 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 6 Oct 2017 15:34:32 -0400 Subject: [PATCH 045/272] Changing parsing of custom procedures for new style --- src/engine/blocks.js | 5 ++--- src/engine/execute.js | 2 ++ src/engine/sequencer.js | 4 +++- src/serialization/sb2.js | 31 ++++++++++++++++++++++++------- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 4a7eb72e2..5b74cf55b 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -154,7 +154,7 @@ class Blocks { const block = this._blocks[id]; if ((block.opcode === 'procedures_defnoreturn' || block.opcode === 'procedures_defreturn') && - block.mutation.proccode === name) { + this._blocks[block.inputs.custom_block.block].mutation.proccode === name) { return id; } } @@ -170,8 +170,7 @@ class Blocks { for (const id in this._blocks) { if (!this._blocks.hasOwnProperty(id)) continue; const block = this._blocks[id]; - if ((block.opcode === 'procedures_defnoreturn' || - block.opcode === 'procedures_defreturn') && + if (block.opcode === 'procedures_callnoreturn_internal' && block.mutation.proccode === name) { return JSON.parse(block.mutation.argumentnames); } diff --git a/src/engine/execute.js b/src/engine/execute.js index c74823ec6..a4bf76b2a 100644 --- a/src/engine/execute.js +++ b/src/engine/execute.js @@ -148,6 +148,8 @@ const execute = function (sequencer, thread) { // Recursively evaluate input blocks. for (const inputName in inputs) { if (!inputs.hasOwnProperty(inputName)) continue; + // Do not evaluate the internal custom command block within definition + if (inputName === 'custom_block') continue; const input = inputs[inputName]; const inputBlockId = input.block; // Is there no value for this input waiting in the stack frame? diff --git a/src/engine/sequencer.js b/src/engine/sequencer.js index 2846f011a..0a126d67e 100644 --- a/src/engine/sequencer.js +++ b/src/engine/sequencer.js @@ -225,7 +225,9 @@ class Sequencer { // Look for warp-mode flag on definition, and set the thread // to warp-mode if needed. const definitionBlock = thread.target.blocks.getBlock(definition); - const doWarp = definitionBlock.mutation.warp; + const innerBlock = thread.target.blocks.getBlock( + definitionBlock.inputs.custom_block.block); + const doWarp = innerBlock.mutation.warp; if (doWarp) { thread.peekStackFrame().warpMode = true; } else if (isRecursive) { diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js index 84560881a..5225614a4 100644 --- a/src/serialization/sb2.js +++ b/src/serialization/sb2.js @@ -481,14 +481,31 @@ const parseBlock = function (sb2block, getVariableId) { // Mutation for procedure definition: // store all 2.0 proc data. const procData = sb2block.slice(1); - activeBlock.mutation = { - tagName: 'mutation', - proccode: procData[0], // e.g., "abc %n %b %s" - argumentnames: JSON.stringify(procData[1]), // e.g. ['arg1', 'arg2'] - argumentdefaults: JSON.stringify(procData[2]), // e.g., [1, 'abc'] - warp: procData[3], // Warp mode, e.g., true/false. - children: [] + // Create a new block and input metadata. + const inputUid = uid(); + const inputName = 'custom_block'; + activeBlock.inputs[inputName] = { + name: inputName, + block: inputUid, + shadow: inputUid }; + activeBlock.children = [{ + id: inputUid, + opcode: 'procedures_callnoreturn_internal', + inputs: {}, + fields: {}, + next: null, + shadow: true, + children: [], + mutation: { + tagName: 'mutation', + proccode: procData[0], // e.g., "abc %n %b %s" + argumentnames: JSON.stringify(procData[1]), // e.g. ['arg1', 'arg2'] + argumentdefaults: JSON.stringify(procData[2]), // e.g., [1, 'abc'] + warp: procData[3], // Warp mode, e.g., true/false. + children: [] + } + }]; } else if (oldOpcode === 'call') { // Mutation for procedure call: // string for proc code (e.g., "abc %n %b %s"). From c1681e54d50089677ff0856c7bde08559b76b83e Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Fri, 6 Oct 2017 13:37:59 -0700 Subject: [PATCH 046/272] Implement drop-down menus for extension blocks Also, add `ANGLE` argument type (like `NUMBER` but adds an angle picker) --- src/engine/runtime.js | 83 ++++++++++++++++++++-- src/extension-support/argument-type.js | 1 + src/extension-support/extension-manager.js | 2 +- 3 files changed, 80 insertions(+), 6 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 6d8ce1dd1..85babe5d9 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -33,6 +33,10 @@ const defaultBlockPackages = { */ const ArgumentTypeMap = (() => { const map = {}; + map[ArgumentType.ANGLE] = { + shadowType: 'math_angle', + fieldType: 'NUM' + }; map[ArgumentType.COLOR] = { shadowType: 'colour_picker' }; @@ -388,6 +392,18 @@ class Runtime extends EventEmitter { } } + /** + * Generate an extension-specific menu ID. + * @param {string} menuName - the name of the menu. + * @param {string} extensionId - the ID of the extension hosting the menu. + * @returns {string} - the constructed ID. + * @private + */ + _makeExtensionMenuId (menuName, extensionId) { + /** @TODO: protect against XML characters in menu name */ + return `${extensionId}.menu.${menuName}`; + } + /** * Register the primitives provided by an extension. * @param {ExtensionInfo} extensionInfo - information about the extension (id, blocks, etc.) @@ -400,11 +416,19 @@ class Runtime extends EventEmitter { color1: '#FF6680', color2: '#FF4D6A', color3: '#FF3355', - blocks: [] + blocks: [], + menus: [] }; this._blockInfo.push(categoryInfo); + for (const menuName in extensionInfo.menus) { + if (extensionInfo.menus.hasOwnProperty(menuName)) { + const menuItems = extensionInfo.menus[menuName]; + const convertedMenu = this._buildMenuForScratchBlocks(menuName, menuItems, extensionInfo); + categoryInfo.menus.push(convertedMenu); + } + } for (const blockInfo of extensionInfo.blocks) { const convertedBlock = this._convertForScratchBlocks(blockInfo, categoryInfo); const opcode = convertedBlock.json.type; @@ -412,7 +436,51 @@ class Runtime extends EventEmitter { this._primitives[opcode] = convertedBlock.info.func; } - this.emit(Runtime.EXTENSION_ADDED, categoryInfo.blocks); + this.emit(Runtime.EXTENSION_ADDED, categoryInfo.blocks.concat(categoryInfo.menus)); + } + + /** + * Build the scratch-blocks JSON for a menu. Note that scratch-blocks treats menus as a special kind of block. + * @param {string} menuName - the name of the menu + * @param {array|string} menuItems - the list of menu items, or the name of an extension method to collect them. + * @param {CategoryInfo} categoryInfo - the category for this block + * @returns {object} - a JSON-esque object ready for scratch-blocks' consumption + * @private + */ + _buildMenuForScratchBlocks (menuName, menuItems, categoryInfo) { + const menuId = this._makeExtensionMenuId(menuName, categoryInfo.id); + + /** @TODO: support dynamic menus when 'menuItems' is a method name string (see extension spec) */ + const options = menuItems.map(item => { + switch (typeof item) { + case 'string': + return [item, item]; + case 'object': + return [item.text, item.value]; + default: + throw new Error(`Can't interpret menu item: ${item}`); + } + }); + + return { + json: { + message0: '%1', + type: menuId, + inputsInline: true, + output: 'String', + colour: categoryInfo.color1, + colourSecondary: categoryInfo.color2, + colourTertiary: categoryInfo.color3, + outputShape: ScratchBlocksConstants.OUTPUT_SHAPE_ROUND, + args0: [ + { + type: 'field_dropdown', + name: menuName, + options: options + } + ] + } + }; } /** @@ -460,14 +528,19 @@ class Runtime extends EventEmitter { const argTypeInfo = ArgumentTypeMap[argInfo.type] || {}; const defaultValue = (typeof argInfo.defaultValue === 'undefined' ? '' : argInfo.defaultValue.toString()); + const shadowType = (argInfo.menu ? + this._makeExtensionMenuId(argInfo.menu, categoryInfo.id) : + argTypeInfo.shadowType); + const fieldType = argInfo.menu || argTypeInfo.fieldType; + // is the ScratchBlocks name for a block input. // The is a placeholder for a reporter and is visible when there's no reporter in this input. - inputList.push(``); + inputList.push(``); // is a text field that the user can type into. Some shadows, like the color picker, don't allow // text input and therefore don't need a field element. - if (argTypeInfo.fieldType) { - inputList.push(`${defaultValue}`); + if (fieldType) { + inputList.push(`${defaultValue}`); } inputList.push(''); diff --git a/src/extension-support/argument-type.js b/src/extension-support/argument-type.js index 70381c84b..0589e9fb6 100644 --- a/src/extension-support/argument-type.js +++ b/src/extension-support/argument-type.js @@ -1,4 +1,5 @@ const ArgumentType = { + ANGLE: 'angle', BOOLEAN: 'Boolean', COLOR: 'color', NUMBER: 'number', diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index 827bc491d..55ac9fdb7 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -151,7 +151,7 @@ class ExtensionManager { result.push(this._prepareBlockInfo(serviceName, blockInfo)); } catch (e) { // TODO: more meaningful error reporting - log.error(`Skipping malformed block: ${JSON.stringify(e)}`); + log.error(`Error processing block: ${e.message}, Block:\n${JSON.stringify(blockInfo)}`); } return result; }, []); From 67c788ec8de1e870982d0f9d2bdd11777a6637f0 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Fri, 6 Oct 2017 23:24:41 -0700 Subject: [PATCH 047/272] Extensions: fix Boolean inputs --- src/engine/runtime.js | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 85babe5d9..4fb2c25b2 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -48,9 +48,8 @@ const ArgumentTypeMap = (() => { shadowType: 'text', fieldType: 'TEXT' }; - // @TODO: talk to Rachel & co. to figure out what goes here. Make it OK to not have a field. Add `check` support. map[ArgumentType.BOOLEAN] = { - shadowType: '' + check: 'Boolean' }; return map; })(); @@ -400,8 +399,7 @@ class Runtime extends EventEmitter { * @private */ _makeExtensionMenuId (menuName, extensionId) { - /** @TODO: protect against XML characters in menu name */ - return `${extensionId}.menu.${menuName}`; + return `${extensionId}.menu.${escapeHtml(menuName)}`; } /** @@ -515,36 +513,47 @@ class Runtime extends EventEmitter { // Sanitize the placeholder to ensure valid XML placeholder = placeholder.replace(/[<"&]/, '_'); - blockJSON.args0.push({ + const argJSON = { type: 'input_value', name: placeholder - }); - - // scratch-blocks uses 1-based argument indexing - const argNum = blockJSON.args0.length; - argsMap[placeholder] = argNum; + }; const argInfo = blockInfo.arguments[placeholder] || {}; const argTypeInfo = ArgumentTypeMap[argInfo.type] || {}; const defaultValue = (typeof argInfo.defaultValue === 'undefined' ? '' : argInfo.defaultValue.toString()); + if (argTypeInfo.check) { + argJSON.check = argTypeInfo.check; + } + const shadowType = (argInfo.menu ? this._makeExtensionMenuId(argInfo.menu, categoryInfo.id) : argTypeInfo.shadowType); const fieldType = argInfo.menu || argTypeInfo.fieldType; // is the ScratchBlocks name for a block input. - // The is a placeholder for a reporter and is visible when there's no reporter in this input. - inputList.push(``); + inputList.push(``); - // is a text field that the user can type into. Some shadows, like the color picker, don't allow - // text input and therefore don't need a field element. - if (fieldType) { - inputList.push(`${defaultValue}`); + // The is a placeholder for a reporter and is visible when there's no reporter in this input. + // Boolean inputs don't need to specify a shadow in the XML. + if (shadowType) { + inputList.push(``); + + // is a text field that the user can type into. Some shadows, like the color picker, don't allow + // text input and therefore don't need a field element. + if (fieldType) { + inputList.push(`${defaultValue}`); + } + + inputList.push(''); } - inputList.push(''); + inputList.push(''); + // scratch-blocks uses 1-based argument indexing + blockJSON.args0.push(argJSON); + const argNum = blockJSON.args0.length; + argsMap[placeholder] = argNum; return `%${argNum}`; }); From 2f9796c163e557bad50c15fe59d24e875633dd1f Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Fri, 6 Oct 2017 23:44:27 -0700 Subject: [PATCH 048/272] Fix `escapeHtml` error caused by rebase --- package.json | 1 + src/engine/runtime.js | 1 + 2 files changed, 2 insertions(+) diff --git a/package.json b/package.json index 2dac26a58..dabd01f7b 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "babel-loader": "^7.0.0", "babel-preset-es2015": "^6.24.1", "copy-webpack-plugin": "4.0.1", + "escape-html": "1.0.3", "eslint": "^4.5.0", "eslint-config-scratch": "^4.0.0", "expose-loader": "0.7.3", diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 4fb2c25b2..17e58aab0 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -1,5 +1,6 @@ const EventEmitter = require('events'); const {OrderedMap} = require('immutable'); +const escapeHtml = require('escape-html'); const ArgumentType = require('../extension-support/argument-type'); const Blocks = require('./blocks'); From 7afb17df7f04df025a411f6f5a96cc6e167f549f Mon Sep 17 00:00:00 2001 From: Scimonster Date: Mon, 9 Oct 2017 01:19:55 +0300 Subject: [PATCH 049/272] Correctly deserialize HTML entities in block DOM E.g. in variable names --- src/engine/adapter.js | 2 +- test/fixtures/events.json | 6 ++++++ test/unit/engine_adapter.js | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/engine/adapter.js b/src/engine/adapter.js index ffb8d043e..92f2caf4a 100644 --- a/src/engine/adapter.js +++ b/src/engine/adapter.js @@ -156,7 +156,7 @@ const adapter = function (e) { if (typeof e !== 'object') return; if (typeof e.xml !== 'object') return; - return domToBlocks(html.parseDOM(e.xml.outerHTML)); + return domToBlocks(html.parseDOM(e.xml.outerHTML, {decodeEntities: true})); }; module.exports = adapter; diff --git a/test/fixtures/events.json b/test/fixtures/events.json index d91370f6e..01ebff740 100644 --- a/test/fixtures/events.json +++ b/test/fixtures/events.json @@ -60,6 +60,12 @@ "outerHTML": "" } }, + "createvariablewithentity": { + "name": "block", + "xml": { + "outerHTML": "this & that" + } + }, "createobscuredshadow": { "name": "block", "xml": { diff --git a/test/unit/engine_adapter.js b/test/unit/engine_adapter.js index 37ad1ea39..4255fb8fe 100644 --- a/test/unit/engine_adapter.js +++ b/test/unit/engine_adapter.js @@ -155,6 +155,24 @@ test('create with obscured shadow', t => { t.end(); }); +test('create variable with entity in name', t => { + const result = adapter(events.createvariablewithentity); + + t.ok(Array.isArray(result)); + t.equal(result.length, 1); + + t.type(result[0].id, 'string'); + t.type(result[0].opcode, 'string'); + t.type(result[0].fields, 'object'); + t.type(result[0].fields.VARIABLE, 'object'); + t.type(result[0].fields.VARIABLE.value, 'string'); + t.equal(result[0].fields.VARIABLE.value, 'this & that'); + t.type(result[0].inputs, 'object'); + t.type(result[0].topLevel, 'boolean'); + t.equal(result[0].topLevel, true); + t.end(); +}); + test('create with invalid block xml', t => { // Entirely invalid block XML const result = adapter(events.createinvalid); From e8c5bbbf8072df5d41dd9dfb52055159f61e5527 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Tue, 10 Oct 2017 12:19:27 -0400 Subject: [PATCH 050/272] Fix tests and make chain more resilient --- src/engine/blocks.js | 21 +++++++++++++++++---- test/unit/engine_sequencer.js | 14 ++++++++++++-- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 5b74cf55b..f25827b39 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -152,10 +152,12 @@ class Blocks { for (const id in this._blocks) { if (!this._blocks.hasOwnProperty(id)) continue; const block = this._blocks[id]; - if ((block.opcode === 'procedures_defnoreturn' || - block.opcode === 'procedures_defreturn') && - this._blocks[block.inputs.custom_block.block].mutation.proccode === name) { - return id; + if (block.opcode === 'procedures_defnoreturn' || + block.opcode === 'procedures_defreturn') { + const internal = this._getCustomBlockInternal(block); + if (internal && internal.mutation.proccode === name) { + return id; // The outer define block id + } } } return null; @@ -546,6 +548,17 @@ class Blocks { return params; } + /** + * Helper to get the corresponding internal procedure definition block + * @param {!object} defineBlock Outer define block. + * @return {!object} internal definition block which has the mutation. + */ + _getCustomBlockInternal (defineBlock) { + if (defineBlock.inputs && defineBlock.inputs.custom_block) { + return this._blocks[defineBlock.inputs.custom_block.block]; + } + } + /** * Helper to add a stack to `this._scripts`. * @param {?string} topBlockId ID of block that starts the script. diff --git a/test/unit/engine_sequencer.js b/test/unit/engine_sequencer.js index e5dcd0be7..76323e67c 100644 --- a/test/unit/engine_sequencer.js +++ b/test/unit/engine_sequencer.js @@ -153,9 +153,19 @@ test('stepToProcedure', t => { t.strictEquals(th.peekStack(), expectedBlock); s.stepToProcedure(th, 'faceCode'); t.strictEquals(th.peekStack(), expectedBlock); - s.stepToProcedure(th, 'faceCode'); - th.target.blocks.getBlock(th.stack[th.stack.length - 4]).mutation.proccode = 'othercode'; + + th.target.blocks.createBlock({ + id: 'internalId', + opcode: 'procedures_defnoreturn_internal', + mutation: { + proccode: 'othercode' + } + }); expectedBlock = th.stack[th.stack.length - 4]; + th.target.blocks.getBlock(expectedBlock).inputs.custom_block = { + type: 'custom_block', + block: 'internalId' + }; s.stepToProcedure(th, 'othercode'); t.strictEquals(th.peekStack(), expectedBlock); From 8d722b9073ff762e21e89e9932b6d9560cecc41a Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Tue, 10 Oct 2017 15:10:03 -0400 Subject: [PATCH 051/272] Fix opcode, which isn't actually used in the code... --- test/unit/engine_sequencer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/engine_sequencer.js b/test/unit/engine_sequencer.js index 76323e67c..abf7102d2 100644 --- a/test/unit/engine_sequencer.js +++ b/test/unit/engine_sequencer.js @@ -156,7 +156,7 @@ test('stepToProcedure', t => { th.target.blocks.createBlock({ id: 'internalId', - opcode: 'procedures_defnoreturn_internal', + opcode: 'procedures_callnoreturn_internal', mutation: { proccode: 'othercode' } From 9af9eb1d926b5140d6acb95ab7d6febae92e3054 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 6 Oct 2017 15:24:29 -0400 Subject: [PATCH 052/272] Fix hide/show --- src/blocks/scratch3_looks.js | 87 +++++++++++++----------------------- 1 file changed, 30 insertions(+), 57 deletions(-) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index 449bfd05a..9061a008f 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -1,6 +1,5 @@ const Cast = require('../util/cast'); const Clone = require('../util/clone'); -const Runtime = require('../engine/runtime'); const RenderedTarget = require('../sprites/rendered-target'); /** @@ -9,6 +8,7 @@ const RenderedTarget = require('../sprites/rendered-target'); * @property {?int} drawableId - the ID of the associated bubble Drawable, null if none. * @property {string} text - the text of the bubble. * @property {string} type - the type of the bubble, "say" or "think" + * @property {Boolean} visible - whether the bubble is hidden along with its sprite. */ class Scratch3LooksBlocks { @@ -65,15 +65,6 @@ class Scratch3LooksBlocks { return bubbleState; } - /** - * @param {Target} target - collect bubble state for this target. Probably, but not necessarily, a RenderedTarget. - * @private - */ - _resetBubbleState (target) { - const defaultBubbleState = Clone.simple(Scratch3LooksBlocks.DEFAULT_BUBBLE_STATE); - target.setCustomState(Scratch3LooksBlocks.STATE_KEY, defaultBubbleState); - } - /** * Handle a target which has moved. * @param {RenderedTarget} target - the target which has moved. @@ -81,27 +72,26 @@ class Scratch3LooksBlocks { */ _onTargetMoved (target) { const bubbleState = this._getBubbleState(target); - if (bubbleState.drawableId && bubbleState.visible) { - this._checkBubbleBounds(target); this._positionBubble(target); } } /** - * Handle a target which has moved. - * @param {RenderedTarget} target - the target which has moved. + * Handle a target which is exiting. + * @param {RenderedTarget} target - the target. * @private */ _onTargetWillExit (target) { const bubbleState = this._getBubbleState(target); if (bubbleState.drawableId) { this.runtime.renderer.destroyDrawable(bubbleState.drawableId); + bubbleState.drawableId = null; } if (bubbleState.skinId) { this.runtime.renderer.destroySkin(bubbleState.skinId); + bubbleState.skinId = null; } - } /** @@ -110,16 +100,12 @@ class Scratch3LooksBlocks { */ _onResetBubbles () { for (let n = 0; n < this.runtime.targets.length; n++) { - const target = this.runtime.targets[n]; - const bubbleState = this._getBubbleState(target); - if (bubbleState.drawableId) { - this._clearBubble(target); - } + this._onTargetWillExit(this.runtime.targets[n]); } } /** - * Position the bubble of a target. + * Position the bubble of a target. If it doesn't fit on the specified side, flip and rerender. * @param {!Target} target Target whose bubble needs positioning. * @private */ @@ -128,34 +114,20 @@ class Scratch3LooksBlocks { const [bubbleWidth, bubbleHeight] = this.runtime.renderer.getSkinSize(bubbleState.drawableId); const targetBounds = target.getBounds(); const stageBounds = this.runtime.getTargetForStage().getBounds(); - - this.runtime.renderer.updateDrawableProperties(bubbleState.drawableId, { - position: [ - bubbleState.onSpriteRight ? targetBounds.right : targetBounds.left - bubbleWidth, - Math.min(stageBounds.top, targetBounds.top + bubbleHeight) - ] - }); - - this.runtime.requestRedraw(); - } - - /** - * Check whether a bubble needs to be flipped. If so, flip the `onSpriteRight` state - * and call the bubble render again. - * @param {!Target} target Target whose bubble needs positioning. - * @private - */ - _checkBubbleBounds (target) { - const bubbleState = this._getBubbleState(target); - const [bubbleWidth, _] = this.runtime.renderer.getSkinSize(bubbleState.drawableId); - const targetBounds = target.getBounds(); - const stageBounds = this.runtime.getTargetForStage().getBounds(); if (bubbleState.onSpriteRight && bubbleWidth + targetBounds.right > stageBounds.right) { bubbleState.onSpriteRight = false; this._renderBubble(target); } else if (!bubbleState.onSpriteRight && targetBounds.left - bubbleWidth < stageBounds.left) { bubbleState.onSpriteRight = true; this._renderBubble(target); + } else { + this.runtime.renderer.updateDrawableProperties(bubbleState.drawableId, { + position: [ + bubbleState.onSpriteRight ? targetBounds.right : targetBounds.left - bubbleWidth, + Math.min(stageBounds.top, targetBounds.top + bubbleHeight) + ] + }); + this.runtime.requestRedraw(); } } @@ -164,11 +136,15 @@ class Scratch3LooksBlocks { * just set it to visible and update the type/text. Otherwise create a new * bubble and update the relevant custom state. * @param {!Target} target Target who needs a bubble. + * @return {undefined} Early return if text is empty string. * @private */ _renderBubble (target) { const bubbleState = this._getBubbleState(target); const {type, text, onSpriteRight} = bubbleState; + if (text === '') { + return this._setBubbleVisibility(target, false); + } if (bubbleState.skinId) { if (!bubbleState.visible) { @@ -195,8 +171,6 @@ class Scratch3LooksBlocks { this.runtime.renderer.updateDrawableProperties(bubbleState.drawableId, { skinId: bubbleState.skinId }); - - this._checkBubbleBounds(target); } this._positionBubble(target); @@ -211,24 +185,21 @@ class Scratch3LooksBlocks { * @private */ _updateBubble (target, type, text) { - if (text === '') { - this._clearBubble(target); - } else { - const bubbleState = this._getBubbleState(target); - bubbleState.type = type; - bubbleState.text = text; - this._renderBubble(target); - } + const bubbleState = this._getBubbleState(target); + bubbleState.type = type; + bubbleState.text = text; + this._renderBubble(target); } /** * Hide the bubble for a given target. * @param {!Target} target Target that say/think blocks are being called on. + * @param {!boolean} visibility Visible or not. * @private */ - _clearBubble (target) { + _setBubbleVisibility (target, visibility) { const bubbleState = this._getBubbleState(target); - bubbleState.visible = false; + bubbleState.visible = visibility; if (bubbleState.drawableId) { this.runtime.renderer.updateDrawableProperties(bubbleState.drawableId, { visible: bubbleState.visible @@ -278,7 +249,7 @@ class Scratch3LooksBlocks { return new Promise(resolve => { setTimeout(() => { // Clear say bubble and proceed. - this._clearBubble(util.target); + this._updateBubble(util.target, 'say', ''); resolve(); }, 1000 * args.SECS); }); @@ -293,7 +264,7 @@ class Scratch3LooksBlocks { return new Promise(resolve => { setTimeout(() => { // Clear say bubble and proceed. - this._clearBubble(util.target); + this._updateBubble(util.target, 'think', ''); resolve(); }, 1000 * args.SECS); }); @@ -301,10 +272,12 @@ class Scratch3LooksBlocks { show (args, util) { util.target.setVisible(true); + this._renderBubble(util.target); } hide (args, util) { util.target.setVisible(false); + this._setBubbleVisibility(util.target, false); } /** From fa2db053a77c349c20362ba712f4c17f1eb03985 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 11 Oct 2017 14:19:15 -0400 Subject: [PATCH 053/272] Fix copy paste error on targetWasRemoved --- src/engine/runtime.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index dc3f7c128..0c0645f9b 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -1242,13 +1242,12 @@ class Runtime extends EventEmitter { } /** - * Report that a new target has been created, possibly by cloning an existing target. - * @param {Target} newTarget - the newly created target. - * @param {Target} [sourceTarget] - the target used as a source for the new clone, if any. - * @fires Runtime#targetWasCreated + * Report that a clone target is being removed. + * @param {Target} target - the target being removed + * @fires Runtime#targetWasRemoved */ - fireTargetWasRemoved (newTarget, sourceTarget) { - this.emit('targetWasRemoved', newTarget, sourceTarget); + fireTargetWasRemoved (target) { + this.emit('targetWasRemoved', target); } /** From 309f02542f6ac9cb78e1d83a0abaa104437a2feb Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Wed, 11 Oct 2017 11:41:03 -0700 Subject: [PATCH 054/272] Throw if extension tries to build a dynamic menu Dynamic menus are not yet supported for extension menus, though they are part of the extension spec. This change provides more thorough feedback if an extension tries to register an unsupported dynamic menu. --- src/engine/runtime.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 17e58aab0..4cc2d3800 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -441,7 +441,7 @@ class Runtime extends EventEmitter { /** * Build the scratch-blocks JSON for a menu. Note that scratch-blocks treats menus as a special kind of block. * @param {string} menuName - the name of the menu - * @param {array|string} menuItems - the list of menu items, or the name of an extension method to collect them. + * @param {array} menuItems - the list of items for this menu * @param {CategoryInfo} categoryInfo - the category for this block * @returns {object} - a JSON-esque object ready for scratch-blocks' consumption * @private @@ -450,6 +450,9 @@ class Runtime extends EventEmitter { const menuId = this._makeExtensionMenuId(menuName, categoryInfo.id); /** @TODO: support dynamic menus when 'menuItems' is a method name string (see extension spec) */ + if (typeof menuItems === 'string') { + throw new Error(`Dynamic extension menus are not yet supported. Menu name: ${menuName}`); + } const options = menuItems.map(item => { switch (typeof item) { case 'string': From b00a619e2dcb02c129d9f1163c36559c20f76a2a Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 11 Oct 2017 15:58:06 -0400 Subject: [PATCH 055/272] Only flip bubble if it would fit the other way --- src/blocks/scratch3_looks.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index 9061a008f..cb57de7ef 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -114,10 +114,12 @@ class Scratch3LooksBlocks { const [bubbleWidth, bubbleHeight] = this.runtime.renderer.getSkinSize(bubbleState.drawableId); const targetBounds = target.getBounds(); const stageBounds = this.runtime.getTargetForStage().getBounds(); - if (bubbleState.onSpriteRight && bubbleWidth + targetBounds.right > stageBounds.right) { + if (bubbleState.onSpriteRight && bubbleWidth + targetBounds.right > stageBounds.right && + (targetBounds.left - bubbleWidth > stageBounds.left)) { // Only flip if it would fit bubbleState.onSpriteRight = false; this._renderBubble(target); - } else if (!bubbleState.onSpriteRight && targetBounds.left - bubbleWidth < stageBounds.left) { + } else if (!bubbleState.onSpriteRight && targetBounds.left - bubbleWidth < stageBounds.left && + (bubbleWidth + targetBounds.right < stageBounds.right)) { // Only flip if it would fit bubbleState.onSpriteRight = true; this._renderBubble(target); } else { From 4599a71dd7a60421b3093f99f98cd215656b4d45 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 11 Oct 2017 16:34:50 -0400 Subject: [PATCH 056/272] Try to pin the bubbles within the left/right bounds --- src/blocks/scratch3_looks.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index cb57de7ef..8b9e49cc9 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -125,7 +125,11 @@ class Scratch3LooksBlocks { } else { this.runtime.renderer.updateDrawableProperties(bubbleState.drawableId, { position: [ - bubbleState.onSpriteRight ? targetBounds.right : targetBounds.left - bubbleWidth, + bubbleState.onSpriteRight ? ( + Math.min(stageBounds.right - bubbleWidth, targetBounds.right) + ) : ( + Math.max(stageBounds.left, targetBounds.left - bubbleWidth) + ), Math.min(stageBounds.top, targetBounds.top + bubbleHeight) ] }); From 96fa7315d563c65a6c930ef9f1343fbbe939aa82 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Fri, 13 Oct 2017 01:46:35 -0700 Subject: [PATCH 057/272] Don't overwrite hat block's fields Due to a typo (I believe) we were overwriting a horizontal hat block's fields list when collecting hat block inputs. Now we collect inputs into a temporary object in this case. --- src/engine/runtime.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index dc76452b7..280f11d83 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -409,6 +409,9 @@ class Runtime extends EventEmitter { const opcode = convertedBlock.json.type; categoryInfo.blocks.push(convertedBlock); this._primitives[opcode] = convertedBlock.info.func; + if (blockInfo.blockType === BlockType.HAT) { + this._hats[opcode] = {edgeActivated: true}; /** @TODO let extension specify this */ + } } this.emit(Runtime.EXTENSION_ADDED, categoryInfo.blocks); @@ -802,13 +805,14 @@ class Runtime extends EventEmitter { // If no fields are present, check inputs (horizontal blocks) if (Object.keys(hatFields).length === 0) { + hatFields = {}; // don't overwrite the block's actual fields list const hatInputs = blocks.getInputs(block); for (const input in hatInputs) { if (!hatInputs.hasOwnProperty(input)) continue; const id = hatInputs[input].block; const inpBlock = blocks.getBlock(id); const fields = blocks.getFields(inpBlock); - hatFields = Object.assign(fields, hatFields); + Object.assign(hatFields, fields); } } From 1a9e28bfc9665ef6f87c4de480a59dd8314936a0 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Fri, 13 Oct 2017 01:48:25 -0700 Subject: [PATCH 058/272] Small WeDo 2.0 fixups --- src/blocks/scratch3_wedo2.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/blocks/scratch3_wedo2.js b/src/blocks/scratch3_wedo2.js index 103694410..abc09e5db 100644 --- a/src/blocks/scratch3_wedo2.js +++ b/src/blocks/scratch3_wedo2.js @@ -245,7 +245,7 @@ class WeDo2 { * @return {number} - the latest value received from the distance sensor. */ get distance () { - return this._sensors.distance; + return this._sensors.distance * 10; } /** @@ -732,8 +732,10 @@ class Scratch3WeDo2Blocks { whenDistance (args) { switch (args.OP) { case '<': + case '<': return this._device.distance < args.REFERENCE; case '>': + case '>': return this._device.distance > args.REFERENCE; default: log.warn(`Unknown comparison operator in whenDistance: ${args.OP}`); @@ -755,7 +757,7 @@ class Scratch3WeDo2Blocks { * @return {number} - the distance sensor's value, scaled to the [0,100] range. */ getDistance () { - return this._device.distance * 10; + return this._device.distance; } /** From 82efc42a1384a3996012f0354326d1aec61e0df1 Mon Sep 17 00:00:00 2001 From: DD Date: Fri, 13 Oct 2017 17:35:56 -0400 Subject: [PATCH 059/272] Update storage when the SVG updates --- src/virtual-machine.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index eec4d0752..6f0658414 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -400,9 +400,13 @@ class VirtualMachine extends EventEmitter { costume.rotationCenterY = rotationCenterY; this.runtime.renderer.updateSVGSkin(costume.skinId, svg, [rotationCenterX, rotationCenterY]); } - // @todo: Also update storage in addition to renderer. Without storage, if you switch - // costumes and switch back, you will lose your changes in the paint editor. - // @todo: emitTargetsUpdate if we need to update the storage ID on the updated costume. + const storage = this.runtime.storage; + costume.assetId = storage.builtinHelper.cache( + storage.AssetType.ImageVector, + storage.DataFormat.SVG, + (new TextEncoder()).encode(svg) + ); + this.emitTargetsUpdate(); } /** From 22e70ce0957cc8ba0304f12e1ebc1d921ec71639 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Thu, 12 Oct 2017 10:37:02 -0400 Subject: [PATCH 060/272] =?UTF-8?q?Remove=20unused=20arguments=20for=20?= =?UTF-8?q?=E2=80=9Cclear=E2=80=9D=20block?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/blocks/scratch3_pen.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index c6866f25d..cbf5de9e5 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -246,15 +246,7 @@ class Scratch3PenBlocks { blocks: [ { opcode: 'clear', - blockType: BlockType.COMMAND, - arguments: { - NUM1: { - type: ArgumentType.NUMBER - }, - NUM2: { - type: ArgumentType.NUMBER - } - } + blockType: BlockType.COMMAND }, { opcode: 'stamp', From 3d6644609f3dafe18fb21c84e1c7c5c4a9dda2e1 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Thu, 12 Oct 2017 10:43:20 -0400 Subject: [PATCH 061/272] Add new set/change color param blocks with menu And remove set/change color and shade blocks. All 4 params are now scaled 0-100. --- src/blocks/scratch3_pen.js | 222 ++++++++++++++++--------------------- 1 file changed, 95 insertions(+), 127 deletions(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index cbf5de9e5..d3f3c7d6b 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -6,6 +6,19 @@ const Color = require('../util/color'); const MathUtil = require('../util/math-util'); const RenderedTarget = require('../sprites/rendered-target'); + +/** + * Enum for pen color parameters. + * @readonly + * @enum {string} + */ +const ColorParam = { + HUE: 'hue', + SATURATION: 'saturation', + BRIGHTNESS: 'brightness', + TRANSPARENCY: 'transparency' +}; + /** * @typedef {object} PenState - the pen state associated with a particular target. * @property {Boolean} penDown - tracks whether the pen should draw for this target. @@ -55,7 +68,9 @@ class Scratch3PenBlocks { static get DEFAULT_PEN_STATE () { return { penDown: false, - hue: 120, + hue: 33, + saturation: 100, + brightness: 100, shade: 50, transparency: 0, penAttributes: { @@ -170,26 +185,6 @@ class Scratch3PenBlocks { } } - /** - * Update the cached color from the hue, shade and transparency values in the provided - * PenState object. - * @param {PenState} penState - the pen state to update. - * @private - */ - _updatePenColor (penState) { - let rgb = Color.hsvToRgb({h: penState.hue * 180 / 100, s: 1, v: 1}); - const shade = (penState.shade > 100) ? 200 - penState.shade : penState.shade; - if (shade < 50) { - rgb = Color.mixRgb(Color.RGB_BLACK, rgb, (10 + shade) / 60); - } else { - rgb = Color.mixRgb(rgb, Color.RGB_WHITE, (shade - 50) / 60); - } - penState.penAttributes.color4f[0] = rgb.r / 255.0; - penState.penAttributes.color4f[1] = rgb.g / 255.0; - penState.penAttributes.color4f[2] = rgb.b / 255.0; - penState.penAttributes.color4f[3] = this._transparencyToAlpha(penState.transparency); - } - /** * Wrap a pen hue or shade values to the range (0,200). * @param {number} value - the pen hue or shade value to the proper range. @@ -202,13 +197,17 @@ class Scratch3PenBlocks { return value; } + _wrapHue (value) { + return MathUtil.wrapClamp(value, 0, 100); + } + /** - * Clamp a pen transparency value to the range (0,100). - * @param {number} value - the pen transparency value to be clamped. + * Clamp a pen color parameter to the range (0,100). + * @param {number} value - the value to be clamped. * @returns {number} the clamped value. * @private */ - _clampTransparency (value) { + _clampColorParam (value) { return MathUtil.clamp(value, 0, 100); } @@ -273,44 +272,32 @@ class Scratch3PenBlocks { } }, { - opcode: 'changePenHueBy', + opcode: 'changePenColorParamBy', blockType: BlockType.COMMAND, - text: 'change pen color by [COLOR]', + text: 'change pen [COLOR_PARAM] by [VALUE]', arguments: { - COLOR: { + COLOR_PARAM: { + type: ArgumentType.STRING, + menu: 'colorParam', + defaultValue: ColorParam.HUE + }, + VALUE: { type: ArgumentType.NUMBER, defaultValue: 10 } } }, { - opcode: 'setPenHueToNumber', + opcode: 'setPenColorParamTo', blockType: BlockType.COMMAND, - text: 'set pen color to [COLOR]', + text: 'set pen [COLOR_PARAM] to [VALUE]', arguments: { - COLOR: { - type: ArgumentType.NUMBER, - defaultValue: 0 - } - } - }, - { - opcode: 'changePenShadeBy', - blockType: BlockType.COMMAND, - text: 'change pen shade by [SHADE]', - arguments: { - SHADE: { - type: ArgumentType.NUMBER, - defaultValue: 10 - } - } - }, - { - opcode: 'setPenShadeToNumber', - blockType: BlockType.COMMAND, - text: 'set pen shade to [SHADE]', - arguments: { - SHADE: { + COLOR_PARAM: { + type: ArgumentType.STRING, + menu: 'colorParam', + defaultValue: ColorParam.HUE + }, + VALUE: { type: ArgumentType.NUMBER, defaultValue: 50 } @@ -338,7 +325,12 @@ class Scratch3PenBlocks { } } } - ] + ], + menus: { + colorParam: + [ColorParam.HUE, ColorParam.SATURATION, + ColorParam.BRIGHTNESS, ColorParam.TRANSPARENCY] + } }; } @@ -413,65 +405,65 @@ class Scratch3PenBlocks { const penState = this._getPenState(util.target); const rgb = Cast.toRgbColorObject(args.COLOR); const hsv = Color.rgbToHsv(rgb); + penState.hue = (hsv.h / 360) * 100; + penState.saturation = hsv.s * 100; + penState.brightness = hsv.v * 100; + this._updatePenColor(penState); + } - penState.hue = 200 * hsv.h / 360; - penState.shade = 50 * hsv.v; + /** + * Update the cached color from the hue, saturation, brightness and transparency values + * in the provided PenState object. + * @param {PenState} penState - the pen state to update. + * @private + */ + _updatePenColor (penState) { + let rgb = Color.hsvToRgb({ + h: penState.hue * 360 / 100, + s: penState.saturation / 100, + v: penState.brightness / 100 + }); penState.penAttributes.color4f[0] = rgb.r / 255.0; penState.penAttributes.color4f[1] = rgb.g / 255.0; penState.penAttributes.color4f[2] = rgb.b / 255.0; - if (rgb.hasOwnProperty('a')) { // Will there always be an 'a'? - penState.penAttributes.color4f[3] = rgb.a / 255.0; - } else { - penState.penAttributes.color4f[3] = 1; + penState.penAttributes.color4f[3] = this._transparencyToAlpha(penState.transparency); + } + + changePenColorParamBy (args, util) { + const penState = this._getPenState(util.target); + switch (args.COLOR_PARAM) { + case ColorParam.HUE: + penState.hue = this._wrapHue(penState.hue + Cast.toNumber(args.VALUE)); + break; + case ColorParam.SATURATION: + penState.saturation = this._clampColorParam(penState.saturation + Cast.toNumber(args.VALUE)); + break; + case ColorParam.BRIGHTNESS: + penState.brightness = this._clampColorParam(penState.brightness + Cast.toNumber(args.VALUE)); + break; + case ColorParam.TRANSPARENCY: + penState.transparency = this._clampColorParam(penState.transparency + Cast.toNumber(args.VALUE)); + break; } - penState.transparency = this._alphaToTransparency(penState.penAttributes.color4f[3]); - } - - /** - * The pen "change pen color by {number}" block rotates the hue of the pen by the given amount. - * @param {object} args - the block arguments. - * @property {number} COLOR - the amount of desired hue rotation. - * @param {object} util - utility object provided by the runtime. - */ - changePenHueBy (args, util) { - const penState = this._getPenState(util.target); - penState.hue = this._wrapHueOrShade(penState.hue + Cast.toNumber(args.COLOR)); this._updatePenColor(penState); } - /** - * The pen "set pen color to {number}" block sets the hue of the pen. - * @param {object} args - the block arguments. - * @property {number} COLOR - the desired hue. - * @param {object} util - utility object provided by the runtime. - */ - setPenHueToNumber (args, util) { + setPenColorParamTo (args, util) { const penState = this._getPenState(util.target); - penState.hue = this._wrapHueOrShade(Cast.toNumber(args.COLOR)); - this._updatePenColor(penState); - } - - /** - * The pen "change pen shade by {number}" block changes the "shade" of the pen, related to the HSV value. - * @param {object} args - the block arguments. - * @property {number} SHADE - the amount of desired shade change. - * @param {object} util - utility object provided by the runtime. - */ - changePenShadeBy (args, util) { - const penState = this._getPenState(util.target); - penState.shade = this._wrapHueOrShade(penState.shade + Cast.toNumber(args.SHADE)); - this._updatePenColor(penState); - } - - /** - * The pen "set pen shade to {number}" block sets the "shade" of the pen, related to the HSV value. - * @param {object} args - the block arguments. - * @property {number} SHADE - the amount of desired shade change. - * @param {object} util - utility object provided by the runtime. - */ - setPenShadeToNumber (args, util) { - const penState = this._getPenState(util.target); - penState.shade = this._wrapHueOrShade(Cast.toNumber(args.SHADE)); + switch (args.COLOR_PARAM) { + case ColorParam.HUE: + penState.hue = this._wrapHue(Cast.toNumber(args.VALUE)); + break; + case ColorParam.SATURATION: + penState.saturation = this._clampColorParam(Cast.toNumber(args.VALUE)); + break; + case ColorParam.BRIGHTNESS: + penState.brightness = this._clampColorParam(Cast.toNumber(args.VALUE)); + break; + case ColorParam.TRANSPARENCY: + penState.transparency = this._clampColorParam(Cast.toNumber(args.VALUE)); + break; + } this._updatePenColor(penState); } @@ -496,30 +488,6 @@ class Scratch3PenBlocks { const penAttributes = this._getPenState(util.target).penAttributes; penAttributes.diameter = this._clampPenSize(Cast.toNumber(args.SIZE)); } - - /** - * The pen "change pen transparency by {number}" block changes the RGBA "transparency" of the pen. - * @param {object} args - the block arguments. - * @property {number} TRANSPARENCY - the amount of desired transparency change. - * @param {object} util - utility object provided by the runtime. - */ - changePenTransparencyBy (args, util) { - const penState = this._getPenState(util.target); - penState.transparency = this._clampTransparency(penState.transparency + Cast.toNumber(args.TRANSPARENCY)); - this._updatePenColor(penState); - } - - /** - * The pen "set pen transparency to {number}" block sets the RGBA "transparency" of the pen. - * @param {object} args - the block arguments. - * @property {number} TRANSPARENCY - the amount of desired transparency change. - * @param {object} util - utility object provided by the runtime. - */ - setPenTransparencyTo (args, util) { - const penState = this._getPenState(util.target); - penState.transparency = this._clampTransparency(Cast.toNumber(args.TRANSPARENCY)); - this._updatePenColor(penState); - } } module.exports = Scratch3PenBlocks; From 4f8782cc841abc08f9037492588cdec61d03915b Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 17 Oct 2017 11:27:46 -0400 Subject: [PATCH 062/272] Remove unused function --- src/blocks/scratch3_pen.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index d3f3c7d6b..3d2b9f78f 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -185,18 +185,6 @@ class Scratch3PenBlocks { } } - /** - * Wrap a pen hue or shade values to the range (0,200). - * @param {number} value - the pen hue or shade value to the proper range. - * @returns {number} the wrapped value. - * @private - */ - _wrapHueOrShade (value) { - value = value % 200; - if (value < 0) value += 200; - return value; - } - _wrapHue (value) { return MathUtil.wrapClamp(value, 0, 100); } From 264042b4cc089728207d9675b77fdfb85fb52a89 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 17 Oct 2017 12:22:53 -0400 Subject: [PATCH 063/272] =?UTF-8?q?Use=20the=20word=20=E2=80=9Ccolor?= =?UTF-8?q?=E2=80=9D=20instead=20of=20=E2=80=9Chue=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/blocks/scratch3_pen.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index 3d2b9f78f..d167ead6e 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -13,7 +13,7 @@ const RenderedTarget = require('../sprites/rendered-target'); * @enum {string} */ const ColorParam = { - HUE: 'hue', + COLOR: 'color', SATURATION: 'saturation', BRIGHTNESS: 'brightness', TRANSPARENCY: 'transparency' @@ -22,7 +22,7 @@ const ColorParam = { /** * @typedef {object} PenState - the pen state associated with a particular target. * @property {Boolean} penDown - tracks whether the pen should draw for this target. - * @property {number} hue - the current hue of the pen. + * @property {number} color - the current color (hue) of the pen. * @property {number} shade - the current shade of the pen. * @property {PenAttributes} penAttributes - cached pen attributes for the renderer. This is the authoritative value for * diameter but not for pen color. @@ -68,7 +68,7 @@ class Scratch3PenBlocks { static get DEFAULT_PEN_STATE () { return { penDown: false, - hue: 33, + color: 33, saturation: 100, brightness: 100, shade: 50, @@ -185,7 +185,7 @@ class Scratch3PenBlocks { } } - _wrapHue (value) { + _wrapColor (value) { return MathUtil.wrapClamp(value, 0, 100); } @@ -267,7 +267,7 @@ class Scratch3PenBlocks { COLOR_PARAM: { type: ArgumentType.STRING, menu: 'colorParam', - defaultValue: ColorParam.HUE + defaultValue: ColorParam.COLOR }, VALUE: { type: ArgumentType.NUMBER, @@ -283,7 +283,7 @@ class Scratch3PenBlocks { COLOR_PARAM: { type: ArgumentType.STRING, menu: 'colorParam', - defaultValue: ColorParam.HUE + defaultValue: ColorParam.COLOR }, VALUE: { type: ArgumentType.NUMBER, @@ -316,7 +316,7 @@ class Scratch3PenBlocks { ], menus: { colorParam: - [ColorParam.HUE, ColorParam.SATURATION, + [ColorParam.COLOR, ColorParam.SATURATION, ColorParam.BRIGHTNESS, ColorParam.TRANSPARENCY] } }; @@ -393,21 +393,21 @@ class Scratch3PenBlocks { const penState = this._getPenState(util.target); const rgb = Cast.toRgbColorObject(args.COLOR); const hsv = Color.rgbToHsv(rgb); - penState.hue = (hsv.h / 360) * 100; + penState.color = (hsv.h / 360) * 100; penState.saturation = hsv.s * 100; penState.brightness = hsv.v * 100; this._updatePenColor(penState); } /** - * Update the cached color from the hue, saturation, brightness and transparency values + * Update the cached color from the color, saturation, brightness and transparency values * in the provided PenState object. * @param {PenState} penState - the pen state to update. * @private */ _updatePenColor (penState) { let rgb = Color.hsvToRgb({ - h: penState.hue * 360 / 100, + h: penState.color * 360 / 100, s: penState.saturation / 100, v: penState.brightness / 100 }); @@ -420,8 +420,8 @@ class Scratch3PenBlocks { changePenColorParamBy (args, util) { const penState = this._getPenState(util.target); switch (args.COLOR_PARAM) { - case ColorParam.HUE: - penState.hue = this._wrapHue(penState.hue + Cast.toNumber(args.VALUE)); + case ColorParam.COLOR: + penState.color = this._wrapColor(penState.color + Cast.toNumber(args.VALUE)); break; case ColorParam.SATURATION: penState.saturation = this._clampColorParam(penState.saturation + Cast.toNumber(args.VALUE)); @@ -439,8 +439,8 @@ class Scratch3PenBlocks { setPenColorParamTo (args, util) { const penState = this._getPenState(util.target); switch (args.COLOR_PARAM) { - case ColorParam.HUE: - penState.hue = this._wrapHue(Cast.toNumber(args.VALUE)); + case ColorParam.COLOR: + penState.color = this._wrapColor(Cast.toNumber(args.VALUE)); break; case ColorParam.SATURATION: penState.saturation = this._clampColorParam(Cast.toNumber(args.VALUE)); From 086df4652ecc5708d25856f451082a234d0f5ec0 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 17 Oct 2017 12:23:38 -0400 Subject: [PATCH 064/272] Remove references to pen shade --- src/blocks/scratch3_pen.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index d167ead6e..01891815f 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -23,7 +23,6 @@ const ColorParam = { * @typedef {object} PenState - the pen state associated with a particular target. * @property {Boolean} penDown - tracks whether the pen should draw for this target. * @property {number} color - the current color (hue) of the pen. - * @property {number} shade - the current shade of the pen. * @property {PenAttributes} penAttributes - cached pen attributes for the renderer. This is the authoritative value for * diameter but not for pen color. */ @@ -71,7 +70,6 @@ class Scratch3PenBlocks { color: 33, saturation: 100, brightness: 100, - shade: 50, transparency: 0, penAttributes: { color4f: [0, 0, 1, 1], From d8a3e659d5832532038fdcc8abf7f82f9ca8cf69 Mon Sep 17 00:00:00 2001 From: Chris Willis-Ford Date: Tue, 17 Oct 2017 14:40:11 -0700 Subject: [PATCH 065/272] Playground: use UMD to load storage as global (#722) * Playground: use UMD to load storage as global It appears that `expose-loader` is not compatible with WebPack's UMD exporter, so the VM playground broke when I converted `scratch-storage` to use UMD. This change causes the playground to load `scratch-storage` as an independent script and relies on its UMD loader to expose it as a global. Bonus points: we get better source mapping this way. * Playground: tell eslint about global ScratchStorage --- src/playground/index.html | 4 +++- src/playground/playground.js | 2 +- webpack.config.js | 10 +++------- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/playground/index.html b/src/playground/index.html index d248b9847..6282014fb 100644 --- a/src/playground/index.html +++ b/src/playground/index.html @@ -66,7 +66,9 @@ - + + + diff --git a/src/playground/playground.js b/src/playground/playground.js index 2c1ef3308..321afb151 100644 --- a/src/playground/playground.js +++ b/src/playground/playground.js @@ -46,7 +46,7 @@ window.onload = function () { const vm = new window.VirtualMachine(); Scratch.vm = vm; - const storage = new Scratch.Storage(); + const storage = new ScratchStorage(); /* global ScratchStorage */ const AssetType = storage.AssetType; storage.addWebSource([AssetType.Project], getProjectUrl); storage.addWebSource([AssetType.ImageVector, AssetType.ImageBitmap, AssetType.Sound], getAssetUrl); diff --git a/webpack.config.js b/webpack.config.js index 571256800..b58666d47 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -77,9 +77,7 @@ module.exports = [ // Audio 'scratch-audio', // Renderer - 'scratch-render', - // Storage - 'scratch-storage' + 'scratch-render' ] }, output: { @@ -111,10 +109,6 @@ module.exports = [ { test: require.resolve('scratch-render'), loader: 'expose-loader?RenderWebGL' - }, - { - test: require.resolve('scratch-storage'), - loader: 'expose-loader?Scratch.Storage' } ]) }, @@ -124,6 +118,8 @@ module.exports = [ to: 'media' }, { from: 'node_modules/highlightjs/styles/zenburn.css' + }, { + from: 'node_modules/scratch-storage/dist/web' }, { from: 'src/playground' }]) From 240c48ad0c1ef4c3e6de837eb106330ca03d6152 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 17 Oct 2017 19:31:51 -0400 Subject: [PATCH 066/272] Set or change color param with a single function --- src/blocks/scratch3_pen.js | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index 01891815f..e37765dfb 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -415,42 +415,32 @@ class Scratch3PenBlocks { penState.penAttributes.color4f[3] = this._transparencyToAlpha(penState.transparency); } - changePenColorParamBy (args, util) { - const penState = this._getPenState(util.target); - switch (args.COLOR_PARAM) { + _setOrChangeColorParam (param, value, penState, change) { + switch (param) { case ColorParam.COLOR: - penState.color = this._wrapColor(penState.color + Cast.toNumber(args.VALUE)); + penState.color = this._wrapColor(value + (change ? penState.color : 0)); break; case ColorParam.SATURATION: - penState.saturation = this._clampColorParam(penState.saturation + Cast.toNumber(args.VALUE)); + penState.saturation = this._clampColorParam(value + (change ? penState.saturation : 0)); break; case ColorParam.BRIGHTNESS: - penState.brightness = this._clampColorParam(penState.brightness + Cast.toNumber(args.VALUE)); + penState.brightness = this._clampColorParam(value + (change ? penState.brightness : 0)); break; case ColorParam.TRANSPARENCY: - penState.transparency = this._clampColorParam(penState.transparency + Cast.toNumber(args.VALUE)); + penState.transparency = this._clampColorParam(value + (change ? penState.transparency : 0)); break; } this._updatePenColor(penState); } + changePenColorParamBy (args, util) { + const penState = this._getPenState(util.target); + this._setOrChangeColorParam(args.COLOR_PARAM, Cast.toNumber(args.VALUE), penState, true); + } + setPenColorParamTo (args, util) { const penState = this._getPenState(util.target); - switch (args.COLOR_PARAM) { - case ColorParam.COLOR: - penState.color = this._wrapColor(Cast.toNumber(args.VALUE)); - break; - case ColorParam.SATURATION: - penState.saturation = this._clampColorParam(Cast.toNumber(args.VALUE)); - break; - case ColorParam.BRIGHTNESS: - penState.brightness = this._clampColorParam(Cast.toNumber(args.VALUE)); - break; - case ColorParam.TRANSPARENCY: - penState.transparency = this._clampColorParam(Cast.toNumber(args.VALUE)); - break; - } - this._updatePenColor(penState); + this._setOrChangeColorParam(args.COLOR_PARAM, Cast.toNumber(args.VALUE), penState, false); } /** From a32f7a6402052a7fe22eb9d5f7d50964e6e55815 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 17 Oct 2017 23:10:58 -0400 Subject: [PATCH 067/272] Default color setting matches default RGB values For color (hue) in range 0-100, to get RGB (0, 0, 1), we need to use 100 * 2/3 = 66.66 --- src/blocks/scratch3_pen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index e37765dfb..84aad4c55 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -67,7 +67,7 @@ class Scratch3PenBlocks { static get DEFAULT_PEN_STATE () { return { penDown: false, - color: 33, + color: 66.66, saturation: 100, brightness: 100, transparency: 0, From aab1b834d6b82e4461937405f1ebb1bb909f8739 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 17 Oct 2017 23:13:05 -0400 Subject: [PATCH 068/272] On set color using picker, reset transparency to 0 --- src/blocks/scratch3_pen.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index 84aad4c55..ed120409c 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -383,6 +383,7 @@ class Scratch3PenBlocks { /** * The pen "set pen color to {color}" block sets the pen to a particular RGB color. + * The transparency is reset to 0. * @param {object} args - the block arguments. * @property {int} COLOR - the color to set, expressed as a 24-bit RGB value (0xRRGGBB). * @param {object} util - utility object provided by the runtime. @@ -394,6 +395,7 @@ class Scratch3PenBlocks { penState.color = (hsv.h / 360) * 100; penState.saturation = hsv.s * 100; penState.brightness = hsv.v * 100; + penState.transparency = 0; this._updatePenColor(penState); } From b5ad5e1f6b88575eb2ef5269c5ffc9385c32932b Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Wed, 18 Oct 2017 11:33:25 -0400 Subject: [PATCH 069/272] Warn on set or change unknown color parameter --- src/blocks/scratch3_pen.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index ed120409c..7eff46a03 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -5,7 +5,7 @@ const Clone = require('../util/clone'); const Color = require('../util/color'); const MathUtil = require('../util/math-util'); const RenderedTarget = require('../sprites/rendered-target'); - +const log = require('../util/log'); /** * Enum for pen color parameters. @@ -431,6 +431,9 @@ class Scratch3PenBlocks { case ColorParam.TRANSPARENCY: penState.transparency = this._clampColorParam(value + (change ? penState.transparency : 0)); break; + default: + log.warn(`Tried to set or change unknown color parameter: ${param}`); + } this._updatePenColor(penState); } From bddabdbac6cbe4a08ccd8b43bc52493f8ee2f7e5 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Wed, 18 Oct 2017 11:48:45 -0400 Subject: [PATCH 070/272] JSDocs --- src/blocks/scratch3_pen.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index 7eff46a03..ac2af4506 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -183,6 +183,12 @@ class Scratch3PenBlocks { } } + /** + * Wrap a color input into the range (0,100). + * @param {number} value - the value to be wrapped. + * @returns {number} the wrapped value. + * @private + */ _wrapColor (value) { return MathUtil.wrapClamp(value, 0, 100); } @@ -417,6 +423,14 @@ class Scratch3PenBlocks { penState.penAttributes.color4f[3] = this._transparencyToAlpha(penState.transparency); } + /** + * Set or change a single color parameter on the pen state, and update the pen color. + * @param {ColorParam} param - the name of the color parameter to set or change. + * @param {number} value - the value to set or change the param by. + * @param {PenState} penState - the pen state to update. + * @param {boolean} change - if true change param by value, if false set param to value. + * @private + */ _setOrChangeColorParam (param, value, penState, change) { switch (param) { case ColorParam.COLOR: @@ -438,11 +452,27 @@ class Scratch3PenBlocks { this._updatePenColor(penState); } + /** + * The "change pen {ColorParam} by {number}" block changes one of the pen's color parameters + * by a given amound. + * @param {object} args - the block arguments. + * @property {ColorParam} COLOR_PARAM - the name of the selected color parameter. + * @property {number} VALUE - the amount to change the selected parameter by. + * @param {object} util - utility object provided by the runtime. + */ changePenColorParamBy (args, util) { const penState = this._getPenState(util.target); this._setOrChangeColorParam(args.COLOR_PARAM, Cast.toNumber(args.VALUE), penState, true); } + /** + * The "set pen {ColorParam} to {number}" block sets one of the pen's color parameters + * to a given amound. + * @param {object} args - the block arguments. + * @property {ColorParam} COLOR_PARAM - the name of the selected color parameter. + * @property {number} VALUE - the amount to set the selected parameter to. + * @param {object} util - utility object provided by the runtime. + */ setPenColorParamTo (args, util) { const penState = this._getPenState(util.target); this._setOrChangeColorParam(args.COLOR_PARAM, Cast.toNumber(args.VALUE), penState, false); From 0a18ce728790edf0bdcc7fa1019bf4d0af7ebd7e Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Wed, 18 Oct 2017 13:16:24 -0400 Subject: [PATCH 071/272] Lint --- src/blocks/scratch3_pen.js | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index ac2af4506..9ac233c7b 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -321,7 +321,7 @@ class Scratch3PenBlocks { menus: { colorParam: [ColorParam.COLOR, ColorParam.SATURATION, - ColorParam.BRIGHTNESS, ColorParam.TRANSPARENCY] + ColorParam.BRIGHTNESS, ColorParam.TRANSPARENCY] } }; } @@ -412,7 +412,7 @@ class Scratch3PenBlocks { * @private */ _updatePenColor (penState) { - let rgb = Color.hsvToRgb({ + const rgb = Color.hsvToRgb({ h: penState.color * 360 / 100, s: penState.saturation / 100, v: penState.brightness / 100 @@ -433,21 +433,20 @@ class Scratch3PenBlocks { */ _setOrChangeColorParam (param, value, penState, change) { switch (param) { - case ColorParam.COLOR: - penState.color = this._wrapColor(value + (change ? penState.color : 0)); - break; - case ColorParam.SATURATION: - penState.saturation = this._clampColorParam(value + (change ? penState.saturation : 0)); - break; - case ColorParam.BRIGHTNESS: - penState.brightness = this._clampColorParam(value + (change ? penState.brightness : 0)); - break; - case ColorParam.TRANSPARENCY: - penState.transparency = this._clampColorParam(value + (change ? penState.transparency : 0)); - break; - default: - log.warn(`Tried to set or change unknown color parameter: ${param}`); - + case ColorParam.COLOR: + penState.color = this._wrapColor(value + (change ? penState.color : 0)); + break; + case ColorParam.SATURATION: + penState.saturation = this._clampColorParam(value + (change ? penState.saturation : 0)); + break; + case ColorParam.BRIGHTNESS: + penState.brightness = this._clampColorParam(value + (change ? penState.brightness : 0)); + break; + case ColorParam.TRANSPARENCY: + penState.transparency = this._clampColorParam(value + (change ? penState.transparency : 0)); + break; + default: + log.warn(`Tried to set or change unknown color parameter: ${param}`); } this._updatePenColor(penState); } From b74c82a08a03d94b1cd5768a73329a0eb49eeff0 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Sun, 22 Oct 2017 13:19:34 +0000 Subject: [PATCH 072/272] chore(package): update socket.io-client to version 2.0.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dabd01f7b..fe7208276 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "scratch-render": "latest", "scratch-storage": "^0.2.0", "script-loader": "0.7.0", - "socket.io-client": "1.7.3", + "socket.io-client": "2.0.4", "stats.js": "^0.17.0", "tap": "^10.2.0", "tiny-worker": "^2.1.1", From 44ca62fefca1eba28d52e97939e91beed42c8c68 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 23 Oct 2017 11:17:39 -0400 Subject: [PATCH 073/272] Fix event listeners not being cleaned up Eventually if you hit the green flag a million times with a "green flag => say" stack, you'd get an event emitter memory leak error. --- src/blocks/scratch3_looks.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index 8b9e49cc9..632917cb1 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -92,6 +92,7 @@ class Scratch3LooksBlocks { this.runtime.renderer.destroySkin(bubbleState.skinId); bubbleState.skinId = null; } + target.removeListener(RenderedTarget.EVENT_TARGET_MOVED, this._onTargetMoved); } /** From 87a0224790863bb40966c2430cb0cf4426fc7f44 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 23 Oct 2017 11:19:39 -0400 Subject: [PATCH 074/272] Stop hide timeouts from sticking around through green flag/stop. --- src/blocks/scratch3_looks.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index 632917cb1..7bea9e76d 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -93,6 +93,7 @@ class Scratch3LooksBlocks { bubbleState.skinId = null; } target.removeListener(RenderedTarget.EVENT_TARGET_MOVED, this._onTargetMoved); + clearTimeout(this._bubbleTimeout); } /** @@ -254,7 +255,8 @@ class Scratch3LooksBlocks { sayforsecs (args, util) { this.say(args, util); return new Promise(resolve => { - setTimeout(() => { + this._bubbleTimeout = setTimeout(() => { + this._bubbleTimeout = null; // Clear say bubble and proceed. this._updateBubble(util.target, 'say', ''); resolve(); @@ -269,7 +271,8 @@ class Scratch3LooksBlocks { thinkforsecs (args, util) { this.think(args, util); return new Promise(resolve => { - setTimeout(() => { + this._bubbleTimeout = setTimeout(() => { + this._bubbleTimeout = null; // Clear say bubble and proceed. this._updateBubble(util.target, 'think', ''); resolve(); From 5ca58c7ceb653e04eed4de282853c30a93d32454 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 23 Oct 2017 11:20:46 -0400 Subject: [PATCH 075/272] Fix new bubbles not moving with their owning sprite. This was the original issue #728 that spurred these changes. --- src/blocks/scratch3_looks.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index 7bea9e76d..6a339de33 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -174,6 +174,7 @@ class Scratch3LooksBlocks { bubbleState.drawableId = this.runtime.renderer.createDrawable(); bubbleState.skinId = this.runtime.renderer.createTextSkin(type, text, bubbleState.onSpriteRight, [0, 0]); + bubbleState.visible = true; this.runtime.renderer.setDrawableOrder(bubbleState.drawableId, Infinity); this.runtime.renderer.updateDrawableProperties(bubbleState.drawableId, { From 24d550d860c159abd6e7789eea90d1b6e5c2e863 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 23 Oct 2017 13:03:10 -0400 Subject: [PATCH 076/272] Remove "visible" state flag and use target visibility directly. This fixes several other bugs like "saying" from a hidden sprite. --- src/blocks/scratch3_looks.js | 46 ++++++++---------------------------- 1 file changed, 10 insertions(+), 36 deletions(-) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index 6a339de33..eb27d090b 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -8,7 +8,6 @@ const RenderedTarget = require('../sprites/rendered-target'); * @property {?int} drawableId - the ID of the associated bubble Drawable, null if none. * @property {string} text - the text of the bubble. * @property {string} type - the type of the bubble, "say" or "think" - * @property {Boolean} visible - whether the bubble is hidden along with its sprite. */ class Scratch3LooksBlocks { @@ -38,8 +37,7 @@ class Scratch3LooksBlocks { onSpriteRight: true, skinId: null, text: '', - type: 'say', - visible: true + type: 'say' }; } @@ -72,7 +70,7 @@ class Scratch3LooksBlocks { */ _onTargetMoved (target) { const bubbleState = this._getBubbleState(target); - if (bubbleState.drawableId && bubbleState.visible) { + if (bubbleState.drawableId) { this._positionBubble(target); } } @@ -84,16 +82,14 @@ class Scratch3LooksBlocks { */ _onTargetWillExit (target) { const bubbleState = this._getBubbleState(target); - if (bubbleState.drawableId) { + if (bubbleState.drawableId && bubbleState.skinId) { this.runtime.renderer.destroyDrawable(bubbleState.drawableId); - bubbleState.drawableId = null; - } - if (bubbleState.skinId) { this.runtime.renderer.destroySkin(bubbleState.skinId); + bubbleState.drawableId = null; bubbleState.skinId = null; + this.runtime.requestRedraw(); } target.removeListener(RenderedTarget.EVENT_TARGET_MOVED, this._onTargetMoved); - clearTimeout(this._bubbleTimeout); } /** @@ -104,6 +100,7 @@ class Scratch3LooksBlocks { for (let n = 0; n < this.runtime.targets.length; n++) { this._onTargetWillExit(this.runtime.targets[n]); } + clearTimeout(this._bubbleTimeout); } /** @@ -150,17 +147,12 @@ class Scratch3LooksBlocks { _renderBubble (target) { const bubbleState = this._getBubbleState(target); const {type, text, onSpriteRight} = bubbleState; - if (text === '') { - return this._setBubbleVisibility(target, false); + // Remove the bubble if empty text or sprite is not visible + if (text === '' || !target.visible) { + return this._onTargetWillExit(target); } if (bubbleState.skinId) { - if (!bubbleState.visible) { - bubbleState.visible = true; - this.runtime.renderer.updateDrawableProperties(bubbleState.drawableId, { - visible: bubbleState.visible - }); - } this.runtime.renderer.updateTextSkin(bubbleState.skinId, type, text, onSpriteRight, [0, 0]); } else { target.addListener(RenderedTarget.EVENT_TARGET_MOVED, this._onTargetMoved); @@ -174,7 +166,6 @@ class Scratch3LooksBlocks { bubbleState.drawableId = this.runtime.renderer.createDrawable(); bubbleState.skinId = this.runtime.renderer.createTextSkin(type, text, bubbleState.onSpriteRight, [0, 0]); - bubbleState.visible = true; this.runtime.renderer.setDrawableOrder(bubbleState.drawableId, Infinity); this.runtime.renderer.updateDrawableProperties(bubbleState.drawableId, { @@ -200,23 +191,6 @@ class Scratch3LooksBlocks { this._renderBubble(target); } - /** - * Hide the bubble for a given target. - * @param {!Target} target Target that say/think blocks are being called on. - * @param {!boolean} visibility Visible or not. - * @private - */ - _setBubbleVisibility (target, visibility) { - const bubbleState = this._getBubbleState(target); - bubbleState.visible = visibility; - if (bubbleState.drawableId) { - this.runtime.renderer.updateDrawableProperties(bubbleState.drawableId, { - visible: bubbleState.visible - }); - } - this.runtime.requestRedraw(); - } - /** * Retrieve the block primitives implemented by this package. * @return {object.} Mapping of opcode to Function. @@ -288,7 +262,7 @@ class Scratch3LooksBlocks { hide (args, util) { util.target.setVisible(false); - this._setBubbleVisibility(util.target, false); + this._renderBubble(util.target); } /** From 09bb01893c3006d96a2ce15a5569ebc827f9c373 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 23 Oct 2017 14:24:37 -0400 Subject: [PATCH 077/272] Add back the visibility optimization in a simpler way. --- src/blocks/scratch3_looks.js | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index eb27d090b..600f003dc 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -6,6 +6,8 @@ const RenderedTarget = require('../sprites/rendered-target'); * @typedef {object} BubbleState - the bubble state associated with a particular target. * @property {Boolean} onSpriteRight - tracks whether the bubble is right or left of the sprite. * @property {?int} drawableId - the ID of the associated bubble Drawable, null if none. + * @property {Boolean} drawableVisible - if drawable has been hidden by blank text. + * See _renderBubble for explanation of this optimization. * @property {string} text - the text of the bubble. * @property {string} type - the type of the bubble, "say" or "think" */ @@ -34,6 +36,7 @@ class Scratch3LooksBlocks { static get DEFAULT_BUBBLE_STATE () { return { drawableId: null, + drawableVisible: true, onSpriteRight: true, skinId: null, text: '', @@ -87,6 +90,7 @@ class Scratch3LooksBlocks { this.runtime.renderer.destroySkin(bubbleState.skinId); bubbleState.drawableId = null; bubbleState.skinId = null; + bubbleState.drawableVisible = true; // Reset back to default value this.runtime.requestRedraw(); } target.removeListener(RenderedTarget.EVENT_TARGET_MOVED, this._onTargetMoved); @@ -146,14 +150,26 @@ class Scratch3LooksBlocks { */ _renderBubble (target) { const bubbleState = this._getBubbleState(target); - const {type, text, onSpriteRight} = bubbleState; - // Remove the bubble if empty text or sprite is not visible - if (text === '' || !target.visible) { + const {drawableVisible, type, text, onSpriteRight} = bubbleState; + + // Remove the bubble if target is not visible, or text is being set to blank + // without being initialized. See comment below about blank text optimization. + if (!target.visible || (text === '' && !bubbleState.skinId)) { return this._onTargetWillExit(target); } if (bubbleState.skinId) { - this.runtime.renderer.updateTextSkin(bubbleState.skinId, type, text, onSpriteRight, [0, 0]); + // Optimization: if text is set to blank, hide the drawable instead of + // getting rid of it. This prevents flickering in "typewriter" projects + if ((text === '' && drawableVisible) || (text !== '' && !drawableVisible)) { + bubbleState.drawableVisible = text !== ''; + this.runtime.renderer.updateDrawableProperties(bubbleState.drawableId, { + visible: bubbleState.drawableVisible + }); + } + if (bubbleState.drawableVisible) { + this.runtime.renderer.updateTextSkin(bubbleState.skinId, type, text, onSpriteRight, [0, 0]); + } } else { target.addListener(RenderedTarget.EVENT_TARGET_MOVED, this._onTargetMoved); From 5e4bdb2bc3dfc805075fca548e7857261552c90e Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Tue, 24 Oct 2017 02:08:45 +0000 Subject: [PATCH 078/272] chore(package): update worker-loader to version 1.1.0 Closes #680 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dabd01f7b..f02d68f2d 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,6 @@ "tiny-worker": "^2.1.1", "webpack": "^2.4.1", "webpack-dev-server": "^2.4.1", - "worker-loader": "0.8.1" + "worker-loader": "1.1.0" } } From c14155c26de8e305909b650fb3d84cdf93635ce8 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Tue, 24 Oct 2017 08:17:31 -0400 Subject: [PATCH 079/272] Fix comment on drawableVisible property --- src/blocks/scratch3_looks.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index 600f003dc..70ffd777d 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -6,7 +6,7 @@ const RenderedTarget = require('../sprites/rendered-target'); * @typedef {object} BubbleState - the bubble state associated with a particular target. * @property {Boolean} onSpriteRight - tracks whether the bubble is right or left of the sprite. * @property {?int} drawableId - the ID of the associated bubble Drawable, null if none. - * @property {Boolean} drawableVisible - if drawable has been hidden by blank text. + * @property {Boolean} drawableVisible - false if drawable has been hidden by blank text. * See _renderBubble for explanation of this optimization. * @property {string} text - the text of the bubble. * @property {string} type - the type of the bubble, "say" or "think" From ec1d8c657eb1753756c5cf8e23999badd5e309d8 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 25 Oct 2017 10:14:03 -0400 Subject: [PATCH 080/272] Add failing test for callNoReturn on undefined proc --- test/unit/blocks_procedures.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 test/unit/blocks_procedures.js diff --git a/test/unit/blocks_procedures.js b/test/unit/blocks_procedures.js new file mode 100644 index 000000000..4ecdb41d8 --- /dev/null +++ b/test/unit/blocks_procedures.js @@ -0,0 +1,28 @@ +const test = require('tap').test; +const Procedures = require('../../src/blocks/scratch3_procedures'); + +const blocks = new Procedures(null); + +test('getPrimitives', t => { + t.type(blocks.getPrimitives(), 'object'); + t.end(); +}); + +// Originally inspired by https://github.com/LLK/scratch-gui/issues/809 +test('calling a custom block with no definition does not throw', t => { + const args = { + mutation: { + proccode: 'undefined proc' + } + }; + const util = { + getProcedureParamNames: () => null, + stackFrame: { + executed: false + } + }; + t.doesNotThrow(() => { + blocks.callNoReturn(args, util); + }); + t.end(); +}); From bbbd3dd64b8a74933a24ed3e85cfbb428a8e1c98 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 25 Oct 2017 10:14:54 -0400 Subject: [PATCH 081/272] Make test pass for undefined proc execution --- src/blocks/scratch3_procedures.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/blocks/scratch3_procedures.js b/src/blocks/scratch3_procedures.js index c648d9603..b91630f12 100644 --- a/src/blocks/scratch3_procedures.js +++ b/src/blocks/scratch3_procedures.js @@ -27,11 +27,20 @@ class Scratch3ProcedureBlocks { if (!util.stackFrame.executed) { const procedureCode = args.mutation.proccode; const paramNames = util.getProcedureParamNames(procedureCode); + + // If null, procedure could not be found, which can happen if custom + // block is dragged between sprites without the definition. + // Match Scratch 2.0 behavior and noop. + if (paramNames === null) { + return; + } + for (let i = 0; i < paramNames.length; i++) { if (args.hasOwnProperty(`input${i}`)) { util.pushParam(paramNames[i], args[`input${i}`]); } } + util.stackFrame.executed = true; util.startProcedure(procedureCode); } From d126f799d817973ef597785727b8bd2ccdcf0f31 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 25 Oct 2017 11:16:42 -0400 Subject: [PATCH 082/272] Prevent imported local variables from being duplicated on the stage. --- src/engine/blocks.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/engine/blocks.js b/src/engine/blocks.js index f25827b39..ba9077fc7 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -255,7 +255,13 @@ class Blocks { }); break; case 'var_create': - stage.createVariable(e.varId, e.varName); + // New variables being created by the user are all global. + // Check if this variable exists on the current target or stage. + // If not, create it on the stage. + // TODO create global and local variables when UI provides a way. + if (!optRuntime.getEditingTarget().lookupVariableById(e.varId)) { + stage.createVariable(e.varId, e.varName); + } break; case 'var_rename': stage.renameVariable(e.varId, e.newName); From 48d3b20d6959fad94cd68f5f0a1cfcc096bef9d9 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 30 Oct 2017 15:15:38 -0400 Subject: [PATCH 083/272] Stringify things before saying --- src/blocks/scratch3_looks.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index 70ffd777d..df1a0246e 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -240,7 +240,7 @@ class Scratch3LooksBlocks { say (args, util) { // @TODO in 2.0 calling say/think resets the right/left bias of the bubble - this._updateBubble(util.target, 'say', args.MESSAGE); + this._updateBubble(util.target, 'say', String(args.MESSAGE)); } sayforsecs (args, util) { @@ -256,7 +256,7 @@ class Scratch3LooksBlocks { } think (args, util) { - this._updateBubble(util.target, 'think', args.MESSAGE); + this._updateBubble(util.target, 'think', String(args.MESSAGE)); } thinkforsecs (args, util) { From e4381b4693dbed9746992c9a5b3be73b078a2171 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Tue, 31 Oct 2017 11:28:56 -0700 Subject: [PATCH 084/272] Add an init watchdog for extension workers If an extension worker does not complete initialization in a reasonable amount of time (currently 15 seconds) then the worker will be terminated. A complete initialization includes registering an extension. --- src/dispatch/central-dispatch.js | 21 +++++- src/dispatch/shared-dispatch.js | 31 +++++++-- src/extension-support/extension-manager.js | 75 ++++++++++++++++++++-- 3 files changed, 117 insertions(+), 10 deletions(-) diff --git a/src/dispatch/central-dispatch.js b/src/dispatch/central-dispatch.js index 6dd236255..a60f9d97c 100644 --- a/src/dispatch/central-dispatch.js +++ b/src/dispatch/central-dispatch.js @@ -38,7 +38,7 @@ class CentralDispatch extends SharedDispatch { /** * Set a local object as the global provider of the specified service. * WARNING: Any method on the provider can be called from any worker within the dispatch system. - * @param {string} service - a globally unique string identifying this service. Examples: 'vm', 'gui', 'extension9'. + * @param {string} service - a globally unique string identifying this service. Examples: 'vm', 'gui'. * @param {object} provider - a local object which provides this service. * @returns {Promise} - a promise which will resolve once the service is registered. */ @@ -72,6 +72,25 @@ class CentralDispatch extends SharedDispatch { } } + /** + * Remove a service provider from the central dispatch service, un-registering any services it provides. + * If the provider is a worker its dispatch service will be shut down. + * The worker itself will NOT be terminated by this call. + * @param {Worker|object} provider - the worker or object instance to be removed. + */ + removeProvider (provider) { + const workerIndex = this.workers.indexOf(provider); + if (workerIndex !== -1) { + /** @TODO Should we ask the worker to shut down? If so, owner must wait before terminating the worker. */ + this.workers.splice(workerIndex, 1); + } + for (const serviceName in Object.keys(this.services)) { + if (this.services[serviceName] === provider) { + delete this.services[serviceName]; + } + } + } + /** * Fetch the service provider object for a particular service name. * @override diff --git a/src/dispatch/shared-dispatch.js b/src/dispatch/shared-dispatch.js index 1e4785bce..7c907d523 100644 --- a/src/dispatch/shared-dispatch.js +++ b/src/dispatch/shared-dispatch.js @@ -39,6 +39,24 @@ class SharedDispatch { * @type {int} */ this.nextResponseId = 0; + + /** + * While processing a call in _onMessage, this will be set to the originating object. + * At all other times it will be null. + * @type {object} + * @private + */ + this._callingWorker = null; + } + + /** + * Central dispatch: while processing a call from a worker, this will be set to the worker originating that call. + * Worker dispatch: while processing a call from the main thread, this will be set to the global object. + * At all other times it will be null. + * @returns {object} - the worker originating the current call, if any. + */ + get callingWorker () { + return this._callingWorker; } /** @@ -184,10 +202,15 @@ class SharedDispatch { message.args = message.args || []; let promise; if (message.service) { - if (message.service === 'dispatch') { - promise = this._onDispatchMessage(worker, message); - } else { - promise = this.call(message.service, message.method, ...message.args); + try { + this._callingWorker = worker; + if (message.service === 'dispatch') { + promise = this._onDispatchMessage(worker, message); + } else { + promise = this.call(message.service, message.method, ...message.args); + } + } finally { + this._callingWorker = null; } } else if (typeof message.responseId === 'undefined') { log.error(`Dispatch caught malformed message from a worker: ${JSON.stringify(event)}`); diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index d7c5fab05..31e915f8a 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -70,6 +70,14 @@ class ExtensionManager { */ this.pendingWorkers = []; + /** + * Set of workers currently being monitored by `_startWorkerWatchdog`. + * @see {_startWorkerWatchdog} + * @type {Set.} + * @private + */ + this._activeWatchdogs = new Set(); + /** * Keep a reference to the runtime so we can construct internal extension objects. * TODO: remove this in favor of extensions accessing the runtime as a service. @@ -99,7 +107,10 @@ class ExtensionManager { const ExtensionWorker = require('worker-loader?name=extension-worker.js!./extension-worker'); this.pendingExtensions.push({extensionURL, resolve, reject}); - dispatch.addWorker(new ExtensionWorker()); + + const worker = new ExtensionWorker(); + dispatch.addWorker(worker); + this._startWorkerWatchdog(worker); }); } @@ -110,16 +121,28 @@ class ExtensionManager { return [id, workerInfo.extensionURL]; } + /** + * Collect extension metadata from the specified service and begin the extension registration process. + * @param {string} serviceName - the name of the service hosting the extension. + */ registerExtensionService (serviceName) { dispatch.call(serviceName, 'getInfo').then(info => { this._registerExtensionInfo(serviceName, info); }); } + /** + * Called by an extension worker to indicate that the worker has finished initialization. + * @param {int} id - the worker ID. + * @param {*?} e - the error encountered during initialization, if any. + */ onWorkerInit (id, e) { const workerInfo = this.pendingWorkers[id]; delete this.pendingWorkers[id]; if (e) { + log.warn(`Extension manager forcibly terminating worker for extension with ID ${id}, URL ${ + workerInfo.extensionURL} due to error during initialization`); + workerInfo.worker.terminate(); workerInfo.reject(e); } else { workerInfo.resolve(id); @@ -133,16 +156,29 @@ class ExtensionManager { */ _registerInternalExtension (extensionObject) { const extensionInfo = extensionObject.getInfo(); - const serviceName = `extension.internal.${extensionInfo.id}`; + const fakeWorkerId = this.nextExtensionWorker++; + const serviceName = `extension.${fakeWorkerId}.${extensionInfo.id}`; return dispatch.setService(serviceName, extensionObject) .then(() => dispatch.call('extensions', 'registerExtensionService', serviceName)); } + /** + * Sanitize extension info then register its primitives with the VM. + * @param {string} serviceName - the name of the service hosting the extension + * @param {ExtensionInfo} extensionInfo - the extension's metadata + * @private + */ _registerExtensionInfo (serviceName, extensionInfo) { extensionInfo = this._prepareExtensionInfo(serviceName, extensionInfo); - dispatch.call('runtime', '_registerExtensionPrimitives', extensionInfo).catch(e => { - log.error(`Failed to register primitives for extension on service ${serviceName}: ${JSON.stringify(e)}`); - }); + dispatch.call('runtime', '_registerExtensionPrimitives', extensionInfo).then( + () => { + if (dispatch.callingWorker) { + this._stopWorkerWatchdog(dispatch.callingWorker); + } + }, + e => { + log.error(`Failed to register primitives for extension "${extensionInfo.id}": ${e.message}`); + }); } /** @@ -211,6 +247,35 @@ class ExtensionManager { } return blockInfo; } + + /** + * Start a watchdog to terminate this worker unless it registers an extension before the timeout. + * @param {object} worker - the worker to watch. + * @private + */ + _startWorkerWatchdog (worker) { + const timeout = 5 * 1000; // 5 seconds + + this._activeWatchdogs.add(worker); + setTimeout(() => { + if (this._activeWatchdogs.has(worker)) { + this._activeWatchdogs.delete(worker); + log.warn(`Worker watchdog timed out. Terminating worker.`); + dispatch.removeProvider(worker); + worker.terminate(); + } + }, timeout); + } + + /** + * Mark this worker as "safe" from the watchdog. + * @param {object} worker - the worker to mark as safe. + * @see {_startWorkerWatchdog} + * @private + */ + _stopWorkerWatchdog (worker) { + this._activeWatchdogs.delete(worker); + } } module.exports = ExtensionManager; From 670e51d33580e8a2e852b3b038bb3afc282f81b9 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Tue, 31 Oct 2017 11:32:21 -0700 Subject: [PATCH 085/272] Refuse to register second extension with same ID If an extension attempts to register with the same ID as another extension which has already registered, the new registration is refused. If the extension is in a worker and no other extension is successfully registered by that worker, the watchdog system will terminate the "empty" worker. --- src/dispatch/central-dispatch.js | 13 +++++++ src/extension-support/extension-manager.js | 43 +++++++++++++++++----- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/dispatch/central-dispatch.js b/src/dispatch/central-dispatch.js index a60f9d97c..9b9681729 100644 --- a/src/dispatch/central-dispatch.js +++ b/src/dispatch/central-dispatch.js @@ -55,6 +55,19 @@ class CentralDispatch extends SharedDispatch { } } + /** + * Unregister a service without regard to which object or worker might provide it. + * @param {string} service - the globally unique string provided to `setService` when the service was registered. + * @see {setService} + */ + clearService (service) { + if (this.services.hasOwnProperty(service)) { + delete this.services[service]; + } else { + log.warn(`Central dispatch can't clear unknown service ${service}`); + } + } + /** * Add a worker to the message dispatch system. The worker must implement a compatible message dispatch framework. * The dispatcher will immediately attempt to "handshake" with the worker. diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index 31e915f8a..f671fa536 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -70,6 +70,13 @@ class ExtensionManager { */ this.pendingWorkers = []; + /** + * Set of loaded extension IDs. For built-in extensions the "URL" is the same as the ID; they differ in general. + * @type {Set.} + * @private + */ + this._loadedExtensions = new Set(); + /** * Set of workers currently being monitored by `_startWorkerWatchdog`. * @see {_startWorkerWatchdog} @@ -90,6 +97,17 @@ class ExtensionManager { }); } + /** + * Check whether an extension is registered or is in the process of loading. This is intended to control loading or + * adding extensions so it may return `true` before the extension is ready to be used. Use the promise returned by + * `loadExtensionURL` if you need to wait until the extension is truly ready. + * @param {string} extensionID - the ID (not URL) of the extension. + * @returns {boolean} - true if loaded, false otherwise. + */ + isExtensionLoaded (extensionID) { + return this._loadedExtensions.has(extensionID); + } + /** * Load an extension by URL or internal extension ID * @param {string} extensionURL - the URL for the extension to load OR the ID of an internal extension @@ -170,15 +188,22 @@ class ExtensionManager { */ _registerExtensionInfo (serviceName, extensionInfo) { extensionInfo = this._prepareExtensionInfo(serviceName, extensionInfo); - dispatch.call('runtime', '_registerExtensionPrimitives', extensionInfo).then( - () => { - if (dispatch.callingWorker) { - this._stopWorkerWatchdog(dispatch.callingWorker); - } - }, - e => { - log.error(`Failed to register primitives for extension "${extensionInfo.id}": ${e.message}`); - }); + if (this.isExtensionLoaded(extensionInfo.id)) { + const message = `Ignoring attempt to load a second extension with ID ${extensionInfo.id}`; + log.warn(message); + dispatch.clearService(serviceName); + } else { + dispatch.call('runtime', '_registerExtensionPrimitives', extensionInfo).then( + () => { + this._loadedExtensions.add(extensionInfo.id); + if (dispatch.callingWorker) { + this._stopWorkerWatchdog(dispatch.callingWorker); + } + }, + e => { + log.error(`Failed to register primitives for extension "${extensionInfo.id}": ${e.message}`); + }); + } } /** From ae878b2050fb3d7f4fe28604856fea626791644e Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Tue, 31 Oct 2017 12:35:18 -0700 Subject: [PATCH 086/272] Simplify extension duplication prevention station Since we will only have builtin extensions for a while, the more-complicated, watchdog-based extension duplication prevention has been replaced with one that treats the extension URL as equivalent to the extension ID. This is true only for built-in extensions, so once we start supporting third-party extensions we will likely need to bring back the watchdog (commit e4381b4693dbed9746992c9a5b3be73b078a2171) and the more-complex duplication prevention (commit 670e51d33580e8a2e852b3b038bb3afc282f81b9). The code here should be treated as a last resort: ideally the GUI should check if a particular extension is loaded (maybe by calling the Extension Manager's new `isExtensionLoaded` method) and avoid calling `loadExtensionURL` if it is. --- src/dispatch/central-dispatch.js | 34 +--------- src/dispatch/shared-dispatch.js | 31 ++------- src/extension-support/extension-manager.js | 75 ++++------------------ 3 files changed, 18 insertions(+), 122 deletions(-) diff --git a/src/dispatch/central-dispatch.js b/src/dispatch/central-dispatch.js index 9b9681729..6dd236255 100644 --- a/src/dispatch/central-dispatch.js +++ b/src/dispatch/central-dispatch.js @@ -38,7 +38,7 @@ class CentralDispatch extends SharedDispatch { /** * Set a local object as the global provider of the specified service. * WARNING: Any method on the provider can be called from any worker within the dispatch system. - * @param {string} service - a globally unique string identifying this service. Examples: 'vm', 'gui'. + * @param {string} service - a globally unique string identifying this service. Examples: 'vm', 'gui', 'extension9'. * @param {object} provider - a local object which provides this service. * @returns {Promise} - a promise which will resolve once the service is registered. */ @@ -55,19 +55,6 @@ class CentralDispatch extends SharedDispatch { } } - /** - * Unregister a service without regard to which object or worker might provide it. - * @param {string} service - the globally unique string provided to `setService` when the service was registered. - * @see {setService} - */ - clearService (service) { - if (this.services.hasOwnProperty(service)) { - delete this.services[service]; - } else { - log.warn(`Central dispatch can't clear unknown service ${service}`); - } - } - /** * Add a worker to the message dispatch system. The worker must implement a compatible message dispatch framework. * The dispatcher will immediately attempt to "handshake" with the worker. @@ -85,25 +72,6 @@ class CentralDispatch extends SharedDispatch { } } - /** - * Remove a service provider from the central dispatch service, un-registering any services it provides. - * If the provider is a worker its dispatch service will be shut down. - * The worker itself will NOT be terminated by this call. - * @param {Worker|object} provider - the worker or object instance to be removed. - */ - removeProvider (provider) { - const workerIndex = this.workers.indexOf(provider); - if (workerIndex !== -1) { - /** @TODO Should we ask the worker to shut down? If so, owner must wait before terminating the worker. */ - this.workers.splice(workerIndex, 1); - } - for (const serviceName in Object.keys(this.services)) { - if (this.services[serviceName] === provider) { - delete this.services[serviceName]; - } - } - } - /** * Fetch the service provider object for a particular service name. * @override diff --git a/src/dispatch/shared-dispatch.js b/src/dispatch/shared-dispatch.js index 7c907d523..1e4785bce 100644 --- a/src/dispatch/shared-dispatch.js +++ b/src/dispatch/shared-dispatch.js @@ -39,24 +39,6 @@ class SharedDispatch { * @type {int} */ this.nextResponseId = 0; - - /** - * While processing a call in _onMessage, this will be set to the originating object. - * At all other times it will be null. - * @type {object} - * @private - */ - this._callingWorker = null; - } - - /** - * Central dispatch: while processing a call from a worker, this will be set to the worker originating that call. - * Worker dispatch: while processing a call from the main thread, this will be set to the global object. - * At all other times it will be null. - * @returns {object} - the worker originating the current call, if any. - */ - get callingWorker () { - return this._callingWorker; } /** @@ -202,15 +184,10 @@ class SharedDispatch { message.args = message.args || []; let promise; if (message.service) { - try { - this._callingWorker = worker; - if (message.service === 'dispatch') { - promise = this._onDispatchMessage(worker, message); - } else { - promise = this.call(message.service, message.method, ...message.args); - } - } finally { - this._callingWorker = null; + if (message.service === 'dispatch') { + promise = this._onDispatchMessage(worker, message); + } else { + promise = this.call(message.service, message.method, ...message.args); } } else if (typeof message.responseId === 'undefined') { log.error(`Dispatch caught malformed message from a worker: ${JSON.stringify(event)}`); diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index f671fa536..d9dc3603e 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -71,20 +71,12 @@ class ExtensionManager { this.pendingWorkers = []; /** - * Set of loaded extension IDs. For built-in extensions the "URL" is the same as the ID; they differ in general. + * Set of loaded extension URLs/IDs (equivalent for built-in extensions). * @type {Set.} * @private */ this._loadedExtensions = new Set(); - /** - * Set of workers currently being monitored by `_startWorkerWatchdog`. - * @see {_startWorkerWatchdog} - * @type {Set.} - * @private - */ - this._activeWatchdogs = new Set(); - /** * Keep a reference to the runtime so we can construct internal extension objects. * TODO: remove this in favor of extensions accessing the runtime as a service. @@ -101,7 +93,7 @@ class ExtensionManager { * Check whether an extension is registered or is in the process of loading. This is intended to control loading or * adding extensions so it may return `true` before the extension is ready to be used. Use the promise returned by * `loadExtensionURL` if you need to wait until the extension is truly ready. - * @param {string} extensionID - the ID (not URL) of the extension. + * @param {string} extensionID - the ID of the extension. * @returns {boolean} - true if loaded, false otherwise. */ isExtensionLoaded (extensionID) { @@ -115,6 +107,13 @@ class ExtensionManager { */ loadExtensionURL (extensionURL) { if (builtinExtensions.hasOwnProperty(extensionURL)) { + /** @TODO dupe handling for non-builtin extensions. See commit 670e51d33580e8a2e852b3b038bb3afc282f81b9 */ + if (this.isExtensionLoaded(extensionURL)) { + const message = `Rejecting attempt to load a second extension with ID ${extensionURL}`; + log.warn(message); + return Promise.reject(new Error(message)); + } + const extension = builtinExtensions[extensionURL]; const extensionInstance = new extension(this.runtime); return this._registerInternalExtension(extensionInstance); @@ -125,10 +124,7 @@ class ExtensionManager { const ExtensionWorker = require('worker-loader?name=extension-worker.js!./extension-worker'); this.pendingExtensions.push({extensionURL, resolve, reject}); - - const worker = new ExtensionWorker(); - dispatch.addWorker(worker); - this._startWorkerWatchdog(worker); + dispatch.addWorker(new ExtensionWorker()); }); } @@ -158,9 +154,6 @@ class ExtensionManager { const workerInfo = this.pendingWorkers[id]; delete this.pendingWorkers[id]; if (e) { - log.warn(`Extension manager forcibly terminating worker for extension with ID ${id}, URL ${ - workerInfo.extensionURL} due to error during initialization`); - workerInfo.worker.terminate(); workerInfo.reject(e); } else { workerInfo.resolve(id); @@ -188,22 +181,9 @@ class ExtensionManager { */ _registerExtensionInfo (serviceName, extensionInfo) { extensionInfo = this._prepareExtensionInfo(serviceName, extensionInfo); - if (this.isExtensionLoaded(extensionInfo.id)) { - const message = `Ignoring attempt to load a second extension with ID ${extensionInfo.id}`; - log.warn(message); - dispatch.clearService(serviceName); - } else { - dispatch.call('runtime', '_registerExtensionPrimitives', extensionInfo).then( - () => { - this._loadedExtensions.add(extensionInfo.id); - if (dispatch.callingWorker) { - this._stopWorkerWatchdog(dispatch.callingWorker); - } - }, - e => { - log.error(`Failed to register primitives for extension "${extensionInfo.id}": ${e.message}`); - }); - } + dispatch.call('runtime', '_registerExtensionPrimitives', extensionInfo).catch(e => { + log.error(`Failed to register primitives for extension on service ${serviceName}: ${JSON.stringify(e)}`); + }); } /** @@ -272,35 +252,6 @@ class ExtensionManager { } return blockInfo; } - - /** - * Start a watchdog to terminate this worker unless it registers an extension before the timeout. - * @param {object} worker - the worker to watch. - * @private - */ - _startWorkerWatchdog (worker) { - const timeout = 5 * 1000; // 5 seconds - - this._activeWatchdogs.add(worker); - setTimeout(() => { - if (this._activeWatchdogs.has(worker)) { - this._activeWatchdogs.delete(worker); - log.warn(`Worker watchdog timed out. Terminating worker.`); - dispatch.removeProvider(worker); - worker.terminate(); - } - }, timeout); - } - - /** - * Mark this worker as "safe" from the watchdog. - * @param {object} worker - the worker to mark as safe. - * @see {_startWorkerWatchdog} - * @private - */ - _stopWorkerWatchdog (worker) { - this._activeWatchdogs.delete(worker); - } } module.exports = ExtensionManager; From 8bb48e2a53c80efd922911ae770dad09ca8de3d8 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Tue, 31 Oct 2017 13:00:19 -0700 Subject: [PATCH 087/272] Add built-in extension "URL" to _loadedExtensions Dupe prevention works better when you actually record the necessary info... --- src/extension-support/extension-manager.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index d9dc3603e..ef3d56aa8 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -116,7 +116,9 @@ class ExtensionManager { const extension = builtinExtensions[extensionURL]; const extensionInstance = new extension(this.runtime); - return this._registerInternalExtension(extensionInstance); + return this._registerInternalExtension(extensionInstance).then(() => { + this._loadedExtensions.add(extensionURL); + }); } return new Promise((resolve, reject) => { From 082e051cce2d84838aa9a5aef4c3b48b83a71845 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Tue, 31 Oct 2017 17:24:12 -0400 Subject: [PATCH 088/272] Support legacy pen block op codes --- src/blocks/scratch3_pen.js | 129 +++++++++++++++++++++++++++++++ src/serialization/sb2_specmap.js | 4 +- 2 files changed, 131 insertions(+), 2 deletions(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index 9ac233c7b..d50bbe750 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -71,6 +71,7 @@ class Scratch3PenBlocks { saturation: 100, brightness: 100, transparency: 0, + _shade: 50, // Used only for legacy `change shade by` blocks penAttributes: { color4f: [0, 0, 1, 1], diameter: 1 @@ -316,6 +317,51 @@ class Scratch3PenBlocks { defaultValue: 1 } } + }, + /* Legacy blocks, should not be shown in flyout */ + { + opcode: 'setPenShadeToNumber', + blockType: BlockType.COMMAND, + text: 'set pen shade to [SHADE]', + arguments: { + SHADE: { + type: ArgumentType.NUMBER, + defaultValue: 1 + } + } + }, + { + opcode: 'changePenShadeBy', + blockType: BlockType.COMMAND, + text: 'change pen shade by [SHADE]', + arguments: { + SHADE: { + type: ArgumentType.NUMBER, + defaultValue: 1 + } + } + }, + { + opcode: 'setPenHueToNumber', + blockType: BlockType.COMMAND, + text: 'set pen hue to [HUE]', + arguments: { + HUE: { + type: ArgumentType.NUMBER, + defaultValue: 1 + } + } + }, + { + opcode: 'changePenHueBy', + blockType: BlockType.COMMAND, + text: 'change pen hue by [HUE]', + arguments: { + HUE: { + type: ArgumentType.NUMBER, + defaultValue: 1 + } + } } ], menus: { @@ -402,6 +448,10 @@ class Scratch3PenBlocks { penState.saturation = hsv.s * 100; penState.brightness = hsv.v * 100; penState.transparency = 0; + + // Set the legacy "shade" value the same way scratch 2 did. + penState._shade = penState.brightness / 2; + this._updatePenColor(penState); } @@ -498,6 +548,85 @@ class Scratch3PenBlocks { const penAttributes = this._getPenState(util.target).penAttributes; penAttributes.diameter = this._clampPenSize(Cast.toNumber(args.SIZE)); } + + /* LEGACY OPCODES */ + /** + * Scratch 2 "hue" param is equivelant to twice the new "color" param. + * @param {object} args - the block arguments. + * @property {number} HUE - the amount to set the hue to. + * @param {object} util - utility object provided by the runtime. + */ + setPenHueToNumber (args, util) { + const penState = this._getPenState(util.target); + const hueValue = Cast.toNumber(args.HUE); + const colorValue = hueValue / 2; + this._setOrChangeColorParam(ColorParam.COLOR, colorValue, penState, false); + } + + /** + * Scratch 2 "hue" param is equivelant to twice the new "color" param. + * @param {object} args - the block arguments. + * @property {number} HUE - the amount of desired hue change. + * @param {object} util - utility object provided by the runtime. + */ + changePenHueBy (args, util) { + const penState = this._getPenState(util.target); + const hueChange = Cast.toNumber(args.HUE); + const colorChange = hueChange / 2; + this._setOrChangeColorParam(ColorParam.COLOR, colorChange, penState, true); + } + + /** + * Use legacy "set shade" code to calculate RGB value for shade, + * then convert back to HSV and store those components. + * It is important to also track the given shade in penState._shade + * because it cannot be accurately backed out of the new HSV later. + * @param {object} args - the block arguments. + * @property {number} SHADE - the amount to set the shade to. + * @param {object} util - utility object provided by the runtime. + */ + setPenShadeToNumber (args, util) { + const penState = this._getPenState(util.target); + let newShade = Cast.toNumber(args.SHADE); + + // Wrap clamp the new shade value the way scratch 2 did. + newShade = newShade % 200; + if (newShade < 0) newShade += 200; + + // Create the new color in RGB using the scratch 2 "shade" model + let rgb = Color.hsvToRgb({h: penState.color * 360 / 100, s: 1, v: 1}); + const shade = (newShade > 100) ? 200 - newShade : newShade; + if (shade < 50) { + rgb = Color.mixRgb(Color.RGB_BLACK, rgb, (10 + shade) / 60); + } else { + rgb = Color.mixRgb(rgb, Color.RGB_WHITE, (shade - 50) / 60); + } + + // Update the pen state according to new color + const hsv = Color.rgbToHsv(rgb); + penState.color = 100 * hsv.h / 360; + penState.saturation = 100 * hsv.s; + penState.brightness = 100 * hsv.v; + + // And store the shade that was used to compute this new color for later use. + penState._shade = newShade; + + this._updatePenColor(penState); + } + + /** + * Because "shade" cannot be backed out of hsv consistently, use the previously + * stored penState._shade to make the shade change. + * @param {object} args - the block arguments. + * @property {number} SHADE - the amount of desired shade change. + * @param {object} util - utility object provided by the runtime. + */ + changePenShadeBy (args, util) { + const penState = this._getPenState(util.target); + const shadeChange = Cast.toNumber(args.SHADE); + this.setPenShadeToNumber({SHADE: penState._shade + shadeChange}, util); + } + } module.exports = Scratch3PenBlocks; diff --git a/src/serialization/sb2_specmap.js b/src/serialization/sb2_specmap.js index 2024b239e..1b697934e 100644 --- a/src/serialization/sb2_specmap.js +++ b/src/serialization/sb2_specmap.js @@ -535,7 +535,7 @@ const specMap = { { type: 'input', inputOp: 'math_number', - inputName: 'COLOR' + inputName: 'HUE' } ] }, @@ -545,7 +545,7 @@ const specMap = { { type: 'input', inputOp: 'math_number', - inputName: 'COLOR' + inputName: 'HUE' } ] }, From 18398d010b3dfc8e5bc60a8463263c99016db097 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 1 Nov 2017 11:07:26 -0400 Subject: [PATCH 089/272] Add hideFromPalette flag for hiding legacy blocks --- src/blocks/scratch3_pen.js | 12 ++++++++---- src/engine/runtime.js | 3 ++- src/extension-support/extension-manager.js | 1 + 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index d50bbe750..7de5e51a6 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -328,7 +328,8 @@ class Scratch3PenBlocks { type: ArgumentType.NUMBER, defaultValue: 1 } - } + }, + hideFromPalette: true }, { opcode: 'changePenShadeBy', @@ -339,7 +340,8 @@ class Scratch3PenBlocks { type: ArgumentType.NUMBER, defaultValue: 1 } - } + }, + hideFromPalette: true }, { opcode: 'setPenHueToNumber', @@ -350,7 +352,8 @@ class Scratch3PenBlocks { type: ArgumentType.NUMBER, defaultValue: 1 } - } + }, + hideFromPalette: true }, { opcode: 'changePenHueBy', @@ -361,7 +364,8 @@ class Scratch3PenBlocks { type: ArgumentType.NUMBER, defaultValue: 1 } - } + }, + hideFromPalette: true } ], menus: { diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 1e0e90ca0..b97387135 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -630,8 +630,9 @@ class Runtime extends EventEmitter { const xmlParts = []; for (const categoryInfo of this._blockInfo) { const {name, color1, color2} = categoryInfo; + const paletteBlocks = categoryInfo.blocks.filter(block => !block.info.hideFromPalette); xmlParts.push(``); - xmlParts.push.apply(xmlParts, categoryInfo.blocks.map(blockInfo => blockInfo.xml)); + xmlParts.push.apply(xmlParts, paletteBlocks.map(block => block.xml)); xmlParts.push(''); } return xmlParts.join('\n'); diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index d7c5fab05..2179e3f23 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -30,6 +30,7 @@ const builtinExtensions = { * @property {object.|undefined} arguments - information about this block's arguments, if any * @property {string|Function|undefined} func - the method for this block on the extension service (default: opcode) * @property {Array.|undefined} filter - the list of targets for which this block should appear (default: all) + * @property {Boolean|undefined} hideFromPalette - true if should not be appear in the palette. (default false) */ /** From 2c3c9f9ac877e10dbcb1979051dd0a4f5cef0ce8 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 1 Nov 2017 14:31:52 -0400 Subject: [PATCH 090/272] Search for variables by name in "of" block --- src/blocks/scratch3_sensing.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/blocks/scratch3_sensing.js b/src/blocks/scratch3_sensing.js index 98eeac97d..559b0e9c1 100644 --- a/src/blocks/scratch3_sensing.js +++ b/src/blocks/scratch3_sensing.js @@ -167,8 +167,10 @@ class Scratch3SensingBlocks { // Variables const varName = args.PROPERTY; - if (attrTarget.variables.hasOwnProperty(varName)) { - return attrTarget.variables[varName].value; + for (const id in attrTarget.variables) { + if (attrTarget.variables[id].name === varName) { + return attrTarget.variables[id].value; + } } // Otherwise, 0 From 54e19b2bb5d8581dff218182b1353b0031cd38e3 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Thu, 2 Nov 2017 20:05:55 +0000 Subject: [PATCH 091/272] chore(package): update scratch-storage to version 0.3.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a40a0bfe7..657022b1c 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "scratch-audio": "latest", "scratch-blocks": "latest", "scratch-render": "latest", - "scratch-storage": "^0.2.0", + "scratch-storage": "^0.3.0", "script-loader": "0.7.0", "socket.io-client": "1.7.3", "stats.js": "^0.17.0", From 5b9d4ae23e6da83663d2f34dc986db2d9dd49e70 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 2 Nov 2017 17:03:12 -0400 Subject: [PATCH 092/272] Provide argument id list with callers and procdef blocks --- src/serialization/sb2.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js index 5225614a4..c56479aae 100644 --- a/src/serialization/sb2.js +++ b/src/serialization/sb2.js @@ -52,6 +52,18 @@ const parseProcedureArgMap = function (procCode) { return argMap; }; +/** + * Generate a list of "argument IDs" for procdefs and caller mutations. + * IDs just end up being `input0`, `input1`, ... which is good enough. + * @param {string} procCode Scratch 2.0 procedure string. + * @return {Array.} Array of argument id strings. + */ +const parseProcedureArgIds = function (procCode) { + return parseProcedureArgMap(procCode) + .map(arg => arg.inputName) + .filter(name => name); // Filter out unnamed inputs which are labels +} + /** * Flatten a block tree into a block list. * Children are temporarily stored on the `block.children` property. @@ -501,6 +513,7 @@ const parseBlock = function (sb2block, getVariableId) { tagName: 'mutation', proccode: procData[0], // e.g., "abc %n %b %s" argumentnames: JSON.stringify(procData[1]), // e.g. ['arg1', 'arg2'] + argumentids: JSON.stringify(parseProcedureArgIds(procData[0])), argumentdefaults: JSON.stringify(procData[2]), // e.g., [1, 'abc'] warp: procData[3], // Warp mode, e.g., true/false. children: [] @@ -512,7 +525,8 @@ const parseBlock = function (sb2block, getVariableId) { activeBlock.mutation = { tagName: 'mutation', children: [], - proccode: sb2block[1] + proccode: sb2block[1], + argumentids: JSON.stringify(parseProcedureArgIds(sb2block[1])) }; } else if (oldOpcode === 'getParam') { // Mutation for procedure parameter. From 007fe2ed53892ba4de9472ca2a8c8f465243846d Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 2 Nov 2017 17:14:00 -0400 Subject: [PATCH 093/272] Fix linting --- src/serialization/sb2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js index c56479aae..092bdfc9e 100644 --- a/src/serialization/sb2.js +++ b/src/serialization/sb2.js @@ -62,7 +62,7 @@ const parseProcedureArgIds = function (procCode) { return parseProcedureArgMap(procCode) .map(arg => arg.inputName) .filter(name => name); // Filter out unnamed inputs which are labels -} +}; /** * Flatten a block tree into a block list. From a115d47bb88880a593908c6153348994447e7291 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Fri, 3 Nov 2017 11:25:39 -0400 Subject: [PATCH 094/272] Add block icon svg as single-line data URI --- src/blocks/scratch3_pen.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index 7de5e51a6..90abf2121 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -7,6 +7,13 @@ const MathUtil = require('../util/math-util'); const RenderedTarget = require('../sprites/rendered-target'); const log = require('../util/log'); +/** + * Icon svg to be displayed at the left edge of each extension block, encoded as a data URI. + * @type {string} + */ +// eslint-disable-next-line max-len +const iconURI = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+cGVuLWljb248L3RpdGxlPjxnIHN0cm9rZT0iIzU3NUU3NSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwYXRoIGQ9Ik04Ljc1MyAzNC42MDJsLTQuMjUgMS43OCAxLjc4My00LjIzN2MxLjIxOC0yLjg5MiAyLjkwNy01LjQyMyA1LjAzLTcuNTM4TDMxLjA2NiA0LjkzYy44NDYtLjg0MiAyLjY1LS40MSA0LjAzMi45NjcgMS4zOCAxLjM3NSAxLjgxNiAzLjE3My45NyA0LjAxNUwxNi4zMTggMjkuNTljLTIuMTIzIDIuMTE2LTQuNjY0IDMuOC03LjU2NSA1LjAxMiIgZmlsbD0iI0ZGRiIvPjxwYXRoIGQ9Ik0yOS40MSA2LjExcy00LjQ1LTIuMzc4LTguMjAyIDUuNzcyYy0xLjczNCAzLjc2Ni00LjM1IDEuNTQ2LTQuMzUgMS41NDYiLz48cGF0aCBkPSJNMzYuNDIgOC44MjVjMCAuNDYzLS4xNC44NzMtLjQzMiAxLjE2NGwtOS4zMzUgOS4zYy4yODItLjI5LjQxLS42NjguNDEtMS4xMiAwLS44NzQtLjUwNy0xLjk2My0xLjQwNi0yLjg2OC0xLjM2Mi0xLjM1OC0zLjE0Ny0xLjgtNC4wMDItLjk5TDMwLjk5IDUuMDFjLjg0NC0uODQgMi42NS0uNDEgNC4wMzUuOTYuODk4LjkwNCAxLjM5NiAxLjk4MiAxLjM5NiAyLjg1NU0xMC41MTUgMzMuNzc0Yy0uNTczLjMwMi0xLjE1Ny41Ny0xLjc2NC44M0w0LjUgMzYuMzgybDEuNzg2LTQuMjM1Yy4yNTgtLjYwNC41My0xLjE4Ni44MzMtMS43NTcuNjkuMTgzIDEuNDQ4LjYyNSAyLjEwOCAxLjI4Mi42Ni42NTggMS4xMDIgMS40MTIgMS4yODcgMi4xMDIiIGZpbGw9IiM0Qzk3RkYiLz48cGF0aCBkPSJNMzYuNDk4IDguNzQ4YzAgLjQ2NC0uMTQuODc0LS40MzMgMS4xNjVsLTE5Ljc0MiAxOS42OGMtMi4xMyAyLjExLTQuNjczIDMuNzkzLTcuNTcyIDUuMDFMNC41IDM2LjM4bC45NzQtMi4zMTYgMS45MjUtLjgwOGMyLjg5OC0xLjIxOCA1LjQ0LTIuOSA3LjU3LTUuMDFsMTkuNzQzLTE5LjY4Yy4yOTItLjI5Mi40MzItLjcwMi40MzItMS4xNjUgMC0uNjQ2LS4yNy0xLjQtLjc4LTIuMTIyLjI1LjE3Mi41LjM3Ny43MzcuNjE0Ljg5OC45MDUgMS4zOTYgMS45ODMgMS4zOTYgMi44NTYiIGZpbGw9IiM1NzVFNzUiIG9wYWNpdHk9Ii4xNSIvPjxwYXRoIGQ9Ik0xOC40NSAxMi44M2MwIC41LS40MDQuOTA1LS45MDQuOTA1cy0uOTA1LS40MDUtLjkwNS0uOTA0YzAtLjUuNDA3LS45MDMuOTA2LS45MDMuNSAwIC45MDQuNDA0LjkwNC45MDR6IiBmaWxsPSIjNTc1RTc1Ii8+PC9nPjwvc3ZnPg=='; + /** * Enum for pen color parameters. * @readonly @@ -235,6 +242,7 @@ class Scratch3PenBlocks { return { id: 'pen', name: 'Pen', + iconURI: iconURI, blocks: [ { opcode: 'clear', From 2ac464c53e39af1cde31973e939b07e930cb725c Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Fri, 3 Nov 2017 11:35:42 -0400 Subject: [PATCH 095/272] Prepend icon to each extension block --- src/engine/runtime.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index b97387135..eef031ac0 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -421,6 +421,7 @@ class Runtime extends EventEmitter { const categoryInfo = { id: extensionInfo.id, name: extensionInfo.name, + iconURI: extensionInfo.iconURI, color1: '#FF6680', color2: '#FF4D6A', color3: '#FF3355', @@ -524,8 +525,21 @@ class Runtime extends EventEmitter { // but each `[ARG]` will need to be replaced with the number in this map instead of `args0.length`. const argsMap = {}; - blockJSON.message0 = blockInfo.text.replace(/\[(.+?)]/g, (match, placeholder) => { + blockJSON.message0 = ''; + // If an icon for the extension exists, prepend it to each block + if (categoryInfo.iconURI) { + blockJSON.message0 = '%1'; + const iconJSON = { + type: 'field_image', + src: categoryInfo.iconURI, + width: 40, + height: 40 + }; + blockJSON.args0.push(iconJSON); + } + + blockJSON.message0 += blockInfo.text.replace(/\[(.+?)]/g, (match, placeholder) => { // Sanitize the placeholder to ensure valid XML placeholder = placeholder.replace(/[<"&]/, '_'); From c1ba902ebb00b9160729d58755e3a64c3045b0c3 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 3 Nov 2017 13:50:50 -0400 Subject: [PATCH 096/272] Use category info that has colors when building menu blocks --- src/engine/runtime.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index b97387135..c86516bf7 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -433,7 +433,7 @@ class Runtime extends EventEmitter { for (const menuName in extensionInfo.menus) { if (extensionInfo.menus.hasOwnProperty(menuName)) { const menuItems = extensionInfo.menus[menuName]; - const convertedMenu = this._buildMenuForScratchBlocks(menuName, menuItems, extensionInfo); + const convertedMenu = this._buildMenuForScratchBlocks(menuName, menuItems, categoryInfo); categoryInfo.menus.push(convertedMenu); } } From 0af3de9bf0471a6598066ea1776f3dd6ccd5751b Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Fri, 3 Nov 2017 11:17:16 -0700 Subject: [PATCH 097/272] Load extensions when loading a project or sprite - Accumulate extension info while deserializing JSON - Install extensions (if any) before installing target(s) - Merged 'install' steps of the "add sprite" and "load project" paths --- src/serialization/sb2.js | 61 ++++++---- src/serialization/sb2_specmap.js | 193 +++++++++++++++++++++++++++++++ src/serialization/sb3.js | 49 ++++++-- src/virtual-machine.js | 58 ++++++---- 4 files changed, 306 insertions(+), 55 deletions(-) diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js index 5225614a4..b5b8030b1 100644 --- a/src/serialization/sb2.js +++ b/src/serialization/sb2.js @@ -78,15 +78,16 @@ const flatten = function (blocks) { * or a list of blocks in an argument (e.g., move [pick random...]). * @param {Array.} blockList SB2 JSON-format block list. * @param {Function} getVariableId function to retreive a variable's ID based on name + * @param {ImportedExtensionsInfo} extensions - (in/out) parsed extension information will be stored here. * @return {Array.} Scratch VM-format block list. */ -const parseBlockList = function (blockList, getVariableId) { +const parseBlockList = function (blockList, getVariableId, extensions) { const resultingList = []; let previousBlock = null; // For setting next. for (let i = 0; i < blockList.length; i++) { const block = blockList[i]; // eslint-disable-next-line no-use-before-define - const parsedBlock = parseBlock(block, getVariableId); + const parsedBlock = parseBlock(block, getVariableId, extensions); if (typeof parsedBlock === 'undefined') continue; if (previousBlock) { parsedBlock.parent = previousBlock.id; @@ -104,14 +105,15 @@ const parseBlockList = function (blockList, getVariableId) { * @param {!object} scripts Scripts object from SB2 JSON. * @param {!Blocks} blocks Blocks object to load parsed blocks into. * @param {Function} getVariableId function to retreive a variable's ID based on name + * @param {ImportedExtensionsInfo} extensions - (in/out) parsed extension information will be stored here. */ -const parseScripts = function (scripts, blocks, getVariableId) { +const parseScripts = function (scripts, blocks, getVariableId, extensions) { for (let i = 0; i < scripts.length; i++) { const script = scripts[i]; const scriptX = script[0]; const scriptY = script[1]; const blockList = script[2]; - const parsedBlockList = parseBlockList(blockList, getVariableId); + const parsedBlockList = parseBlockList(blockList, getVariableId, extensions); if (parsedBlockList[0]) { // Adjust script coordinates to account for // larger block size in scratch-blocks. @@ -155,12 +157,14 @@ const generateVariableIdGetter = (function () { /** * Parse a single "Scratch object" and create all its in-memory VM objects. - * @param {!object} object From-JSON "Scratch object:" sprite, stage, watcher. - * @param {!Runtime} runtime Runtime object to load all structures into. - * @param {boolean} topLevel Whether this is the top-level object (stage). - * @return {?Promise} Promise that resolves to the loaded targets when ready. + * TODO: parse the "info" section, especially "savedExtensions" + * @param {!object} object - From-JSON "Scratch object:" sprite, stage, watcher. + * @param {!Runtime} runtime - Runtime object to load all structures into. + * @param {ImportedExtensionsInfo} extensions - (in/out) parsed extension information will be stored here. + * @param {boolean} topLevel - Whether this is the top-level object (stage). + * @return {!Promise.>} Promise for the loaded targets when ready, or null for unsupported objects. */ -const parseScratchObject = function (object, runtime, topLevel) { +const parseScratchObject = function (object, runtime, extensions, topLevel) { if (!object.hasOwnProperty('objName')) { // Watcher/monitor - skip this object until those are implemented in VM. // @todo @@ -228,7 +232,7 @@ const parseScratchObject = function (object, runtime, topLevel) { // If included, parse any and all scripts/blocks on the object. if (object.hasOwnProperty('scripts')) { - parseScripts(object.scripts, blocks, getVariableId); + parseScripts(object.scripts, blocks, getVariableId, extensions); } if (object.hasOwnProperty('lists')) { @@ -287,7 +291,7 @@ const parseScratchObject = function (object, runtime, topLevel) { const childrenPromises = []; if (object.children) { for (let m = 0; m < object.children.length; m++) { - childrenPromises.push(parseScratchObject(object.children[m], runtime, false)); + childrenPromises.push(parseScratchObject(object.children[m], runtime, extensions, false)); } } @@ -312,31 +316,42 @@ const parseScratchObject = function (object, runtime, topLevel) { * @param {!object} json SB2-format JSON to load. * @param {!Runtime} runtime Runtime object to load all structures into. * @param {boolean=} optForceSprite If set, treat as sprite (Sprite2). - * @return {?Promise} Promise that resolves to the loaded targets when ready. + * @return {Promise.} Promise that resolves to the loaded targets when ready. */ const sb2import = function (json, runtime, optForceSprite) { - return parseScratchObject( - json, - runtime, - !optForceSprite - ); + const extensions = { + extensionIDs: new Set(), + extensionURLs: new Map() + }; + return parseScratchObject(json, runtime, extensions, !optForceSprite) + .then(targets => ({ + targets, + extensions + })); }; /** * Parse a single SB2 JSON-formatted block and its children. * @param {!object} sb2block SB2 JSON-formatted block. - * @param {Function} getVariableId function to retreive a variable's ID based on name - * @return {object} Scratch VM format block. + * @param {Function} getVariableId function to retrieve a variable's ID based on name + * @param {ImportedExtensionsInfo} extensions - (in/out) parsed extension information will be stored here. + * @return {object} Scratch VM format block, or null if unsupported object. */ -const parseBlock = function (sb2block, getVariableId) { +const parseBlock = function (sb2block, getVariableId, extensions) { // First item in block object is the old opcode (e.g., 'forward:'). const oldOpcode = sb2block[0]; // Convert the block using the specMap. See sb2specmap.js. if (!oldOpcode || !specMap[oldOpcode]) { log.warn('Couldn\'t find SB2 block: ', oldOpcode); - return; + return null; } const blockMetadata = specMap[oldOpcode]; + // If the block is from an extension, record it. + const dotIndex = blockMetadata.opcode.indexOf('.'); + if (dotIndex >= 0) { + const extension = blockMetadata.opcode.substring(0, dotIndex); + extensions.extensionIDs.add(extension); + } // Block skeleton. const activeBlock = { id: uid(), // Generate a new block unique ID. @@ -373,10 +388,10 @@ const parseBlock = function (sb2block, getVariableId) { let innerBlocks; if (typeof providedArg[0] === 'object' && providedArg[0]) { // Block list occupies the input. - innerBlocks = parseBlockList(providedArg, getVariableId); + innerBlocks = parseBlockList(providedArg, getVariableId, extensions); } else { // Single block occupies the input. - innerBlocks = [parseBlock(providedArg, getVariableId)]; + innerBlocks = [parseBlock(providedArg, getVariableId, extensions)]; } let previousBlock = null; for (let j = 0; j < innerBlocks.length; j++) { diff --git a/src/serialization/sb2_specmap.js b/src/serialization/sb2_specmap.js index 1b697934e..6257bc1d1 100644 --- a/src/serialization/sb2_specmap.js +++ b/src/serialization/sb2_specmap.js @@ -21,6 +21,24 @@ * properties. By hand, I matched the opcode name to the 3.0 opcode. * Finally, I filled in the expected arguments as below. */ + +/** + * @typedef {object} SB2SpecMap_blockInfo + * @property {string} opcode - the Scratch 3.0 block opcode. Use 'extensionID.opcode' for extension opcodes. + * @property {Array.} argMap - metadata for this block's arguments. + */ + +/** + * @typedef {object} SB2SpecMap_argInfo + * @property {string} type - the type of this arg (such as 'input' or 'field') + * @property {string} inputOp - the scratch-blocks shadow type for this arg + * @property {string} inputName - the name this argument will take when provided to the block implementation + */ + +/** + * Mapping of Scratch 2.0 opcode to Scratch 3.0 block metadata. + * @type {object.} + */ const specMap = { 'forward:': { opcode: 'motion_movesteps', @@ -1376,4 +1394,179 @@ const specMap = { argMap: [] } }; + +/** + * Add to the specMap entries for an opcode from a Scratch 2.0 extension. Two entries will be made with the same + * metadata; this is done to support projects saved by both older and newer versions of the Scratch 2.0 editor. + * @param {string} sb2Extension - the Scratch 2.0 name of the extension + * @param {string} sb2Opcode - the Scratch 2.0 opcode + * @param {SB2SpecMap_blockInfo} blockInfo - the Scratch 3.0 block info + */ +const addExtensionOp = function (sb2Extension, sb2Opcode, blockInfo) { + /** + * This string separates the name of an extension and the name of an opcode in more recent Scratch 2.0 projects. + * Earlier projects used '.' as a separator, up until we added the 'LEGO WeDo 2.0' extension... + * @type {string} + */ + const sep = '\u001F'; // Unicode Unit Separator + + // make one entry for projects saved by recent versions of the Scratch 2.0 editor + specMap[`${sb2Extension}${sep}${sb2Opcode}`] = blockInfo; + + // make a second for projects saved by older versions of the Scratch 2.0 editor + specMap[`${sb2Extension}.${sb2Opcode}`] = blockInfo; +}; + +const weDo2 = 'LEGO WeDo 2.0'; + +addExtensionOp(weDo2, 'motorOnFor', { + opcode: 'wedo2.motorOnFor', + argMap: [ + { + type: 'input', + inputOp: 'text', + inputName: 'MOTOR_ID' + }, + { + type: 'input', + inputOp: 'math_number', + inputName: 'DURATION' + } + ] +}); + +addExtensionOp(weDo2, 'motorOn', { + opcode: 'wedo2.motorOn', + argMap: [ + { + type: 'input', + inputOp: 'text', + inputName: 'MOTOR_ID' + } + ] +}); + +addExtensionOp(weDo2, 'motorOff', { + opcode: 'wedo2.motorOff', + argMap: [ + { + type: 'input', + inputOp: 'text', + inputName: 'MOTOR_ID' + } + ] +}); + +addExtensionOp(weDo2, 'startMotorPower', { + opcode: 'wedo2.startMotorPower', + argMap: [ + { + type: 'input', + inputOp: 'text', + inputName: 'MOTOR_ID' + }, + { + type: 'input', + inputOp: 'math_number', + inputName: 'POWER' + } + ] +}); + +addExtensionOp(weDo2, 'setMotorDirection', { + opcode: 'wedo2.setMotorDirection', + argMap: [ + { + type: 'input', + inputOp: 'text', + inputName: 'MOTOR_ID' + }, + { + type: 'input', + inputOp: 'text', + inputName: 'DIRECTION' + } + ] +}); + +addExtensionOp(weDo2, 'setLED', { + opcode: 'wedo2.setLightHue', + argMap: [ + { + type: 'input', + inputOp: 'math_number', + inputName: 'HUE' + } + ] +}); + +addExtensionOp(weDo2, 'playNote', { + opcode: 'wedo2.playNoteFor', + argMap: [ + { + type: 'input', + inputOp: 'math_number', + inputName: 'NOTE' + }, + { + type: 'input', + inputOp: 'math_number', + inputName: 'DURATION' + } + ] +}); + +addExtensionOp(weDo2, 'whenDistance', { + opcode: 'wedo2.whenDistance', + argMap: [ + { + type: 'input', + inputOp: 'text', + inputName: 'OP' + }, + { + type: 'input', + inputOp: 'math_number', + inputName: 'REFERENCE' + } + ] +}); + +addExtensionOp(weDo2, 'whenTilted', { + opcode: 'wedo2.whenTilted', + argMap: [ + { + type: 'input', + inputOp: 'text', + inputName: 'DIRECTION' + } + ] +}); + +addExtensionOp(weDo2, 'getDistance', { + opcode: 'wedo2.motorOn' +}); + +addExtensionOp(weDo2, 'isTilted', { + opcode: 'wedo2.motorOn', + argMap: [ + { + type: 'input', + inputOp: 'text', + inputName: 'DIRECTION' + } + ] +}); + +addExtensionOp(weDo2, 'getTilt', { + opcode: 'getTiltAngle', + argMap: [ + { + type: 'input', + inputOp: 'text', + inputName: 'DIRECTION' + } + ] +}); + module.exports = specMap; diff --git a/src/serialization/sb3.js b/src/serialization/sb3.js index d73a472f7..13bdd2e72 100644 --- a/src/serialization/sb3.js +++ b/src/serialization/sb3.js @@ -13,6 +13,18 @@ const List = require('../engine/list'); const {loadCostume} = require('../import/load-costume.js'); const {loadSound} = require('../import/load-sound.js'); +/** + * @typedef {object} ImportedProject + * @property {Array.} targets - the imported Scratch 3.0 target objects. + * @property {ImportedExtensionsInfo} extensionsInfo - the ID of each extension actually used by this project. + */ + +/** + * @typedef {object} ImportedExtensionsInfo + * @property {Set.} extensionIDs - the ID of each extension actually in use by blocks in this project. + * @property {Map.} extensionURLs - map of ID => URL from project metadata. May not match extensionIDs. + */ + /** * Serializes the specified VM runtime. * @param {!Runtime} runtime VM runtime instance to be serialized. @@ -41,13 +53,14 @@ const serialize = function (runtime) { * Parse a single "Scratch object" and create all its in-memory VM objects. * @param {!object} object From-JSON "Scratch object:" sprite, stage, watcher. * @param {!Runtime} runtime Runtime object to load all structures into. - * @return {?Target} Target created (stage or sprite). + * @param {ImportedExtensionsInfo} extensions - (in/out) parsed extension information will be stored here. + * @return {!Promise.} Promise for the target created (stage or sprite), or null for unsupported objects. */ -const parseScratchObject = function (object, runtime) { +const parseScratchObject = function (object, runtime, extensions) { if (!object.hasOwnProperty('name')) { // Watcher/monitor - skip this object until those are implemented in VM. // @todo - return; + return Promise.resolve(null); } // Blocks container for this object. const blocks = new Blocks(); @@ -61,7 +74,14 @@ const parseScratchObject = function (object, runtime) { } if (object.hasOwnProperty('blocks')) { for (const blockId in object.blocks) { - blocks.createBlock(object.blocks[blockId]); + const blockJSON = object.blockType[blockId]; + blocks.createBlock(blockJSON); + + const dotIndex = blockJSON.opcode.indexOf('.'); + if (dotIndex >= 0) { + const extensionId = blockJSON.opcode.substring(0, dotIndex); + extensions.extensionIDs.add(extensionId); + } } // console.log(blocks); } @@ -155,14 +175,23 @@ const parseScratchObject = function (object, runtime) { }; /** - * Deserializes the specified representation of a VM runtime and loads it into - * the provided runtime instance. - * @param {object} json JSON representation of a VM runtime. - * @param {Runtime} runtime Runtime instance - * @returns {Promise} Promise that resolves to the list of targets after the project is deserialized + * Deserialize the specified representation of a VM runtime and loads it into the provided runtime instance. + * TODO: parse extension info (also, design extension info storage...) + * @param {object} json - JSON representation of a VM runtime. + * @param {Runtime} runtime - Runtime instance + * @returns {Promise.} Promise that resolves to the list of targets after the project is deserialized */ const deserialize = function (json, runtime) { - return Promise.all((json.targets || []).map(target => parseScratchObject(target, runtime))); + const extensions = { + extensionIDs: new Set(), + extensionURLs: new Map() + }; + return Promise.all( + (json.targets || []).map(target => parseScratchObject(target, runtime, extensions)) + ).then(targets => ({ + targets, + extensions + })); }; module.exports = { diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 6f0658414..a1dac6089 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -33,7 +33,7 @@ class VirtualMachine extends EventEmitter { /** * The "currently editing"/selected target ID for the VM. * Block events from any Blockly workspace are routed to this target. - * @type {!string} + * @type {Target} */ this.editingTarget = null; // Runtime emits are passed along as VM emits. @@ -228,19 +228,41 @@ class VirtualMachine extends EventEmitter { deserializer = sb2; } - return deserializer.deserialize(json, this.runtime).then(targets => { - this.clear(); - for (let n = 0; n < targets.length; n++) { - if (targets[n] !== null) { - this.runtime.targets.push(targets[n]); - targets[n].updateAllDrawableProperties(); - } + return deserializer.deserialize(json, this.runtime) + .then(({targets, extensions}) => + this.installTargets(targets, extensions, true)); + } + + /** + * Install `deserialize` results: zero or more targets after the extensions (if any) used by those targets. + * @param {Array.} targets - the targets to be installed + * @param {ImportedExtensionsInfo} extensions - metadata about extensions used by these targets + * @param {boolean} wholeProject - set to true if installing a whole project, as opposed to a single sprite. + */ + installTargets (targets, extensions, wholeProject) { + const extensionPromises = []; + extensions.extensionIDs.forEach(extensionID => { + if (!this.extensionManager.isExtensionLoaded(extensionID)) { + const extensionURL = extensions.extensionURLs.get(extensionID) || extensionID; + extensionPromises.push(this.extensionManager.loadExtensionURL(extensionURL)); } + }); + + targets = targets.filter(target => !!target); + + Promise.all(extensionPromises).then(() => { + if (wholeProject) { + this.clear(); + } + targets.forEach(target => { + this.runtime.targets.push(target); + (/** @type RenderedTarget */ target).updateAllDrawableProperties(); + }); // Select the first target for editing, e.g., the first sprite. - if (this.runtime.targets.length > 1) { - this.editingTarget = this.runtime.targets[1]; + if (wholeProject && (targets.length > 1)) { + this.editingTarget = targets[1]; } else { - this.editingTarget = this.runtime.targets[0]; + this.editingTarget = targets[0]; } // Update the VM user's knowledge of targets and blocks on the workspace. @@ -267,17 +289,9 @@ class VirtualMachine extends EventEmitter { return; } - // Select new sprite. - return sb2.deserialize(json, this.runtime, true).then(targets => { - this.runtime.targets.push(targets[0]); - this.editingTarget = targets[0]; - this.editingTarget.updateAllDrawableProperties(); - - // Update the VM user's knowledge of targets and blocks on the workspace. - this.emitTargetsUpdate(); - this.emitWorkspaceUpdate(); - this.runtime.setEditingTarget(this.editingTarget); - }); + return sb2.deserialize(json, this.runtime, true) + .then(({targets, extensions}) => + this.installTargets(targets, extensions, false)); } /** From c88a8fa55a2a79fd78f9957a22c99dc6d765ef93 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Fri, 3 Nov 2017 11:42:20 -0700 Subject: [PATCH 098/272] Fix tests & a typo --- src/serialization/sb3.js | 2 +- test/integration/import_sb2.js | 2 +- test/integration/sb3-roundtrip.js | 2 +- test/unit/serialization_sb2.js | 4 ++-- test/unit/serialization_sb3.js | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/serialization/sb3.js b/src/serialization/sb3.js index 13bdd2e72..426f1004a 100644 --- a/src/serialization/sb3.js +++ b/src/serialization/sb3.js @@ -74,7 +74,7 @@ const parseScratchObject = function (object, runtime, extensions) { } if (object.hasOwnProperty('blocks')) { for (const blockId in object.blocks) { - const blockJSON = object.blockType[blockId]; + const blockJSON = object.blocks[blockId]; blocks.createBlock(blockJSON); const dotIndex = blockJSON.opcode.indexOf('.'); diff --git a/test/integration/import_sb2.js b/test/integration/import_sb2.js index f9a0d2d0d..ec553dd90 100644 --- a/test/integration/import_sb2.js +++ b/test/integration/import_sb2.js @@ -21,7 +21,7 @@ test('default', t => { // Create runtime instance & load SB2 into it const rt = new runtime(); rt.attachStorage(makeTestStorage()); - sb2.deserialize(json, rt).then(targets => { + sb2.deserialize(json, rt).then(({targets}) => { // Test t.type(file, 'string'); t.type(json, 'object'); diff --git a/test/integration/sb3-roundtrip.js b/test/integration/sb3-roundtrip.js index 058169a8d..5704e33b7 100644 --- a/test/integration/sb3-roundtrip.js +++ b/test/integration/sb3-roundtrip.js @@ -103,7 +103,7 @@ test('sb3-roundtrip', t => { return sb3.deserialize(serializedState, runtime2); }); - return serializeAndDeserialize.then(targets => { + return serializeAndDeserialize.then(({targets}) => { runtime2.targets = targets; testRuntimeState('copy', runtime2); }); diff --git a/test/unit/serialization_sb2.js b/test/unit/serialization_sb2.js index 68535b408..d5aaa0248 100644 --- a/test/unit/serialization_sb2.js +++ b/test/unit/serialization_sb2.js @@ -20,7 +20,7 @@ test('default', t => { // Create runtime instance & load SB2 into it const rt = new Runtime(); - sb2.deserialize(json, rt).then(targets => { + sb2.deserialize(json, rt).then(({targets}) => { // Test t.type(file, 'string'); t.type(json, 'object'); @@ -60,7 +60,7 @@ test('data scoping', t => { // Create runtime instance & load SB2 into it const rt = new Runtime(); - sb2.deserialize(json, rt).then(targets => { + sb2.deserialize(json, rt).then(({targets}) => { const globalVariableIds = Object.keys(targets[0].variables); const localVariableIds = Object.keys(targets[1].variables); t.equal(targets[0].variables[globalVariableIds[0]].name, 'foo'); diff --git a/test/unit/serialization_sb3.js b/test/unit/serialization_sb3.js index a43ce204f..5c2b8a1e7 100644 --- a/test/unit/serialization_sb3.js +++ b/test/unit/serialization_sb3.js @@ -14,8 +14,8 @@ test('serialize', t => { test('deserialize', t => { const vm = new VirtualMachine(); - sb3.deserialize('', vm.runtime).then(targets => { - // @todo Analyize + sb3.deserialize('', vm.runtime).then(({targets}) => { + // @todo Analyze t.type(targets, 'object'); t.end(); }); From 51dcfb954d037378c5cf5d31c2425ad0cd028ba1 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Fri, 3 Nov 2017 12:50:37 -0700 Subject: [PATCH 099/272] Pen integration test: don't pre-load pen extension --- src/virtual-machine.js | 3 ++- test/integration/pen.js | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index a1dac6089..6971e4509 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -238,6 +238,7 @@ class VirtualMachine extends EventEmitter { * @param {Array.} targets - the targets to be installed * @param {ImportedExtensionsInfo} extensions - metadata about extensions used by these targets * @param {boolean} wholeProject - set to true if installing a whole project, as opposed to a single sprite. + * @returns {Promise} resolved once targets have been installed */ installTargets (targets, extensions, wholeProject) { const extensionPromises = []; @@ -250,7 +251,7 @@ class VirtualMachine extends EventEmitter { targets = targets.filter(target => !!target); - Promise.all(extensionPromises).then(() => { + return Promise.all(extensionPromises).then(() => { if (wholeProject) { this.clear(); } diff --git a/test/integration/pen.js b/test/integration/pen.js index 025735bac..7df798e7b 100644 --- a/test/integration/pen.js +++ b/test/integration/pen.js @@ -48,7 +48,6 @@ test('pen', t => { vm.setCompatibilityMode(false); vm.setTurboMode(false); vm.loadProject(project) - .then(() => vm.extensionManager.loadExtensionURL('pen')) /** @TODO: loadProject should load extensions */ .then(() => { vm.greenFlag(); From 0ad03f8d70619ddba8b9fe779d119a2c6c803a87 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Fri, 3 Nov 2017 13:48:05 -0700 Subject: [PATCH 100/272] Actually finish SB2 specMap for WeDo 2.0 Apparently I took a break at the wrong time and forgot to come back to this... :/ --- src/serialization/sb2_specmap.js | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/serialization/sb2_specmap.js b/src/serialization/sb2_specmap.js index 6257bc1d1..cf5be1c89 100644 --- a/src/serialization/sb2_specmap.js +++ b/src/serialization/sb2_specmap.js @@ -1424,7 +1424,7 @@ addExtensionOp(weDo2, 'motorOnFor', { argMap: [ { type: 'input', - inputOp: 'text', + inputOp: 'wedo2.menu.motorID', inputName: 'MOTOR_ID' }, { @@ -1440,7 +1440,7 @@ addExtensionOp(weDo2, 'motorOn', { argMap: [ { type: 'input', - inputOp: 'text', + inputOp: 'wedo2.menu.motorID', inputName: 'MOTOR_ID' } ] @@ -1451,7 +1451,7 @@ addExtensionOp(weDo2, 'motorOff', { argMap: [ { type: 'input', - inputOp: 'text', + inputOp: 'wedo2.menu.motorID', inputName: 'MOTOR_ID' } ] @@ -1462,7 +1462,7 @@ addExtensionOp(weDo2, 'startMotorPower', { argMap: [ { type: 'input', - inputOp: 'text', + inputOp: 'wedo2.menu.motorID', inputName: 'MOTOR_ID' }, { @@ -1478,12 +1478,12 @@ addExtensionOp(weDo2, 'setMotorDirection', { argMap: [ { type: 'input', - inputOp: 'text', + inputOp: 'wedo2.menu.motorID', inputName: 'MOTOR_ID' }, { type: 'input', - inputOp: 'text', + inputOp: 'wedo2.menu.motorDirection', inputName: 'DIRECTION' } ] @@ -1521,7 +1521,7 @@ addExtensionOp(weDo2, 'whenDistance', { argMap: [ { type: 'input', - inputOp: 'text', + inputOp: 'wedo2.menu.lessMore', inputName: 'OP' }, { @@ -1537,33 +1537,34 @@ addExtensionOp(weDo2, 'whenTilted', { argMap: [ { type: 'input', - inputOp: 'text', + inputOp: 'wedo2.menu.tiltDirectionAny', inputName: 'DIRECTION' } ] }); addExtensionOp(weDo2, 'getDistance', { - opcode: 'wedo2.motorOn' + opcode: 'wedo2.getDistance', + argMap: [] }); addExtensionOp(weDo2, 'isTilted', { - opcode: 'wedo2.motorOn', + opcode: 'wedo2.isTilted', argMap: [ { type: 'input', - inputOp: 'text', + inputOp: 'wedo2.menu.tiltDirectionAny', inputName: 'DIRECTION' } ] }); addExtensionOp(weDo2, 'getTilt', { - opcode: 'getTiltAngle', + opcode: 'wedo2.getTiltAngle', argMap: [ { type: 'input', - inputOp: 'text', + inputOp: 'wedo2.menu.tiltDirection', inputName: 'DIRECTION' } ] From 4e24a3f3807bd30dca6785172408b66ba4bf2c61 Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Fri, 3 Nov 2017 11:52:42 -0400 Subject: [PATCH 101/272] Constant time check if thread is in doneThreads Remove indexOf tests for thread existence in doneThreads. Maintain a list of null and thread objects mirroring the index position of threads that are done in runtime.threads. Filter out null values after filtering out done threads from runtime.threads. This has a small side effect that threads that normally became DONE and were added to doneThreads before being removed or restarted will not be in doneThreads in this version. Restarted threads (_restartThread) do not appear in this version but new copies will be in Runtime this.threads supporting glow and monitor updates. Removed threads (_removeThread) do not appear in this version if they are removed after they were seen as DONE by the prior version. Threads removed before they are seen as DONE do not appear in doneThreads in the prior or this version. Threads that are removed before normally becoming DONE do not appear in doneThreads in either case. Threads that are restarted before the loop checks if the thread is done do not appear in doneThreads in either case. --- src/engine/sequencer.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/engine/sequencer.js b/src/engine/sequencer.js index 0a126d67e..9664290c4 100644 --- a/src/engine/sequencer.js +++ b/src/engine/sequencer.js @@ -38,7 +38,7 @@ class Sequencer { let numActiveThreads = Infinity; // Whether `stepThreads` has run through a full single tick. let ranFirstTick = false; - const doneThreads = []; + const doneThreads = this.runtime.threads.map(() => null); // Conditions for continuing to stepping threads: // 1. We must have threads in the list, and some must be active. // 2. Time elapsed must be less than WORK_TIME. @@ -54,11 +54,13 @@ class Sequencer { if (activeThread.stack.length === 0 || activeThread.status === Thread.STATUS_DONE) { // Finished with this thread. - if (doneThreads.indexOf(activeThread) < 0) { - doneThreads.push(activeThread); - } + doneThreads[i] = activeThread; continue; } + // A thread was removed, added or this thread was restarted. + if (doneThreads[i] !== null) { + doneThreads[i] = null; + } if (activeThread.status === Thread.STATUS_YIELD_TICK && !ranFirstTick) { // Clear single-tick yield from the last call of `stepThreads`. @@ -82,13 +84,13 @@ class Sequencer { ranFirstTick = true; } // Filter inactive threads from `this.runtime.threads`. - this.runtime.threads = this.runtime.threads.filter(thread => { - if (doneThreads.indexOf(thread) > -1) { + this.runtime.threads = this.runtime.threads.filter((thread, i) => { + if (doneThreads[i] === null) { return false; } return true; }); - return doneThreads; + return doneThreads.filter(Boolean); } /** From 6d82c0f115713ae729dfadc024ddf6d70e21b25f Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Fri, 3 Nov 2017 16:24:12 -0400 Subject: [PATCH 102/272] In place filter threads at end of stepThreads Skip a large array allocation by filtering done threads in place with a for loop. --- src/engine/sequencer.js | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/engine/sequencer.js b/src/engine/sequencer.js index 9664290c4..f4edc966c 100644 --- a/src/engine/sequencer.js +++ b/src/engine/sequencer.js @@ -84,13 +84,28 @@ class Sequencer { ranFirstTick = true; } // Filter inactive threads from `this.runtime.threads`. - this.runtime.threads = this.runtime.threads.filter((thread, i) => { + numActiveThreads = 0; + for (let i = 0; i < this.runtime.threads.length; i++) { + const thread = this.runtime.threads[i]; if (doneThreads[i] === null) { - return false; + this.runtime.threads[numActiveThreads] = thread; + numActiveThreads++; } - return true; - }); - return doneThreads.filter(Boolean); + } + this.runtime.threads.length = numActiveThreads; + + // Filter undefined and null values from `doneThreads`. + let numDoneThreads = 0; + for (let i = 0; i < doneThreads.length; i++) { + const maybeThread = doneThreads[i]; + if (maybeThread !== null) { + doneThreads[numDoneThreads] = maybeThread; + numDoneThreads++; + } + } + doneThreads.length = numDoneThreads; + + return doneThreads; } /** From 8616390fabcfaa686a746a1359d7083d6261b166 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 3 Nov 2017 21:24:47 -0400 Subject: [PATCH 103/272] Add back pen transparency from color number --- src/blocks/scratch3_pen.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index 7de5e51a6..2a0bd4908 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -451,7 +451,11 @@ class Scratch3PenBlocks { penState.color = (hsv.h / 360) * 100; penState.saturation = hsv.s * 100; penState.brightness = hsv.v * 100; - penState.transparency = 0; + if (rgb.hasOwnProperty('a')) { + penState.transparency = 100 * (1 - rgb.a / 255.0); + } else { + penState.transparency = 0; + } // Set the legacy "shade" value the same way scratch 2 did. penState._shade = penState.brightness / 2; From caa9b97520db78de8f06d2ff2eaa098988f8d952 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Sat, 4 Nov 2017 10:10:17 -0400 Subject: [PATCH 104/272] Fix linting --- src/blocks/scratch3_pen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index 2a0bd4908..407215120 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -452,7 +452,7 @@ class Scratch3PenBlocks { penState.saturation = hsv.s * 100; penState.brightness = hsv.v * 100; if (rgb.hasOwnProperty('a')) { - penState.transparency = 100 * (1 - rgb.a / 255.0); + penState.transparency = 100 * (1 - (rgb.a / 255.0)); } else { penState.transparency = 0; } From 14087ef24fe7ae87570272a77bde45753182687b Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Mon, 6 Nov 2017 10:00:13 -0500 Subject: [PATCH 105/272] Add wedo block icon --- src/blocks/scratch3_wedo2.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/blocks/scratch3_wedo2.js b/src/blocks/scratch3_wedo2.js index abc09e5db..37011517a 100644 --- a/src/blocks/scratch3_wedo2.js +++ b/src/blocks/scratch3_wedo2.js @@ -3,6 +3,12 @@ const BlockType = require('../extension-support/block-type'); const color = require('../util/color'); const log = require('../util/log'); +/** + * Icon svg to be displayed at the left edge of each extension block, encoded as a data URI. + * @type {string} + */ +const iconURI = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+d2VkbzItYmxvY2staWNvbjwvdGl0bGU+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48cGF0aCBkPSJNMzUuMzEzIDEwLjQ2N0gzMi4wOVY4Ljg2NWMwLS4yMjMuMTgtLjQwNC40MDUtLjQwNGgyLjQxMmMuMjI0IDAgLjQwNi4xODIuNDA2LjQwNXYxLjYwMnpNMzAuNDc3IDEwLjQ2N2gtMy4yMjRWOC44NjVjMC0uMjIzLjE4My0uNDA0LjQwNy0uNDA0aDIuNDFjLjIyNiAwIC40MDcuMTgyLjQwNy40MDV2MS42MDJ6TTI1LjY0IDEwLjQ2N0gyMi40MlY4Ljg2NWMwLS4yMjMuMTgyLS40MDQuNDA2LS40MDRoMi40MWMuMjI2IDAgLjQwNy4xODIuNDA3LjQwNXYxLjYwMnpNMjAuODA2IDEwLjQ2N2gtMy4yMjRWOC44NjVjMC0uMjIzLjE4Mi0uNDA0LjQwNi0uNDA0SDIwLjRjLjIyNCAwIC40MDYuMTgyLjQwNi40MDV2MS42MDJ6TTE1Ljk3IDEwLjQ2N2gtMy4yMjRWOC44NjVjMC0uMjIzLjE4Mi0uNDA0LjQwNy0uNDA0aDIuNDFjLjIyNiAwIC40MDcuMTgyLjQwNy40MDV2MS42MDJ6TTExLjEzNSAxMC40NjdINy45MVY4Ljg2NWMwLS4yMjMuMTgzLS40MDQuNDA3LS40MDRoMi40MTJjLjIyMyAwIC40MDUuMTgyLjQwNS40MDV2MS42MDJ6IiBzdHJva2U9IiM2Rjc4OTMiIGZpbGw9IiNGRkYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjxwYXRoIGQ9Ik0zNy43MyAxMC40NjdINi4zYy0yLjY3IDAtNC44MzYgMi4xNTMtNC44MzYgNC44MDh2My4yMDVoMzcuMDczdi03LjIxYzAtLjQ0NC0uMzYyLS44MDMtLjgwNy0uODAzeiIgc3Ryb2tlPSIjNkY3ODkzIiBmaWxsPSIjRkZGIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48cGF0aCBkPSJNMzguMTM0IDMwLjk4SDEuODY3Yy0uMjI0IDAtLjQwMy0uMTgtLjQwMy0uNFYxNi4yMzZoMzIuNzFjLjczIDAgMS40My4yODcgMS45NDUuOC41MTUuNTE0IDEuMjE1LjgwMiAxLjk0NC44MDJoLjQ3M3YxMi43NGMwIC4yMi0uMTguNC0uNDAzLjR6IiBzdHJva2U9IiM2Rjc4OTMiIGZpbGw9IiNFNkU3RTgiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjxwYXRoIHN0cm9rZT0iIzZGNzg5MyIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNMzQuODMgMTYuMjM3bC40ODMtMi41NjVoMy4yMjMiLz48cGF0aCBkPSJNMzguNTM2IDExLjI2OFYzMC41OGMwIC4yMi0uMTguNC0uNDAzLjRIMS44NjZjLS4yMiAwLS40MDMtLjE4LS40MDMtLjR2LTEuMjAzaDM0LjI4MmMuNjUgMCAxLjE4LS41MjQgMS4xOC0xLjE3M1YxMC40NjdoLjgwNWMuNDQ2IDAgLjgwNi4zNi44MDYuOHoiIHN0cm9rZT0iIzZGNzg5MyIgZmlsbD0iIzZGNzg5MyIgb3BhY2l0eT0iLjE1IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48cGF0aCBkPSJNMTEuNTM4IDE2LjI4aDIwLjE0OGMuMjIyIDAgLjQwMy4xOC40MDMuNHY2LjUyN2MwIC4yMjItLjE4Mi40LS40MDQuNEgxMS41MzhjLS4yMjMgMC0uNDA0LS4xNzgtLjQwNC0uNFYxNi42OGMwLS4yMi4xOC0uNC40MDQtLjQiIGZpbGw9IiNFNkU3RTgiLz48cGF0aCBkPSJNMTEuNTM4IDE2LjI4aDIwLjE0OGMuMjIyIDAgLjQwMy4xOC40MDMuNHY2LjUyN2MwIC4yMjItLjE4Mi40LS40MDQuNEgxMS41MzhjLS4yMjMgMC0uNDA0LS4xNzgtLjQwNC0uNFYxNi42OGMwLS4yMi4xOC0uNC40MDQtLjR6IiBzdHJva2U9IiM2Rjc4OTMiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjxwYXRoIGQ9Ik0zMi4wOSAxNi4yOHY2LjkyN2MwIC4yMjItLjE4LjQtLjQwNC40aC0yMC4xNWMtLjIyIDAtLjQtLjE4LS40LS40di0xLjJoMTguMTZjLjY1MyAwIDEuMTgtLjUyNiAxLjE4LTEuMTc0VjE2LjI4aDEuNjEzeiIgc3Ryb2tlPSIjNkY3ODkzIiBmaWxsPSIjNkU3NzkyIiBvcGFjaXR5PSIuMTUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjxwYXRoIGQ9Ik0zMC40NzcgMTYuMjhoLTMuMjI0di0xLjYwNGMwLS4yMjMuMTgzLS40MDQuNDA3LS40MDRoMi40MWMuMjI2IDAgLjQwNy4xOC40MDcuNDA0djEuNjAzek0xNS45NyAxNi4yOGgtMy4yMjR2LTEuNjA0YzAtLjIyMy4xODItLjQwNC40MDctLjQwNGgyLjQxYy4yMjYgMCAuNDA3LjE4LjQwNy40MDR2MS42MDN6TTI1LjY0IDE2LjI4SDIyLjQydi0xLjYwNGMwLS4yMjMuMTgyLS40MDQuNDA2LS40MDRoMi40MWMuMjI2IDAgLjQwNy4xOC40MDcuNDA0djEuNjAzek0yMC44MDYgMTYuMjhoLTMuMjI0di0xLjYwNGMwLS4yMjMuMTgyLS40MDQuNDA2LS40MDRIMjAuNGMuMjI0IDAgLjQwNi4xOC40MDYuNDA0djEuNjAzeiIgc3Ryb2tlPSIjNkY3ODkzIiBmaWxsPSIjRTZFN0U4IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48cGF0aCBkPSJNMTguNTU3IDE5LjkxYzAgMS4wMjUtLjgzNyAxLjg1Ny0xLjg3IDEuODU3LTEuMDMgMC0xLjg2Ny0uODMyLTEuODY3LTEuODU4IDAtMS4wMjcuODM3LTEuODU4IDEuODY4LTEuODU4IDEuMDMyIDAgMS44Ny44MyAxLjg3IDEuODU3ek0yMy40OCAxOS45MWMwIDEuMDI1LS44MzYgMS44NTctMS44NjggMS44NTdzLTEuODctLjgzMi0xLjg3LTEuODU4YzAtMS4wMjcuODM4LTEuODU4IDEuODctMS44NThzMS44NjguODMgMS44NjggMS44NTd6TTI4LjQwNCAxOS45MWMwIDEuMDI1LS44MzcgMS44NTctMS44NjggMS44NTctMS4wMzIgMC0xLjg3LS44MzItMS44Ny0xLjg1OCAwLTEuMDI3LjgzOC0xLjg1OCAxLjg3LTEuODU4IDEuMDMgMCAxLjg2OC44MyAxLjg2OCAxLjg1N3oiIHN0cm9rZT0iIzZGNzg5MyIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+PHBhdGggZD0iTTE4LjU1NyAxOS45MjJjMCAxLjAyNi0uODM3IDEuODU4LTEuODcgMS44NTgtMS4wMyAwLTEuODY3LS44MzItMS44NjctMS44NTggMC0xLjAyNS44MzctMS44NTcgMS44NjgtMS44NTcgMS4wMzIgMCAxLjg3LjgzMiAxLjg3IDEuODU3TTIzLjQ4IDE5LjkyMmMwIDEuMDI2LS44MzYgMS44NTgtMS44NjggMS44NThzLTEuODctLjgzMi0xLjg3LTEuODU4YzAtMS4wMjUuODM4LTEuODU3IDEuODctMS44NTdzMS44NjguODMyIDEuODY4IDEuODU3TTI4LjQwNCAxOS45MjJjMCAxLjAyNi0uODM3IDEuODU4LTEuODY4IDEuODU4LTEuMDMyIDAtMS44Ny0uODMyLTEuODctMS44NTggMC0xLjAyNS44MzgtMS44NTcgMS44Ny0xLjg1NyAxLjAzIDAgMS44NjguODMyIDEuODY4IDEuODU3IiBmaWxsPSIjNkY3ODkzIiBvcGFjaXR5PSIuNSIvPjwvZz48L3N2Zz4='; + /** * Manage power, direction, and timers for one WeDo 2.0 motor. */ @@ -407,6 +413,7 @@ class Scratch3WeDo2Blocks { return { id: Scratch3WeDo2Blocks.EXTENSION_ID, name: 'WeDo 2.0', + iconURI: iconURI, blocks: [ { opcode: 'motorOnFor', From 323fde3859c066f0740a23b653e32dbf15e0b077 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Mon, 6 Nov 2017 10:10:41 -0500 Subject: [PATCH 106/272] Appease the linter --- src/blocks/scratch3_wedo2.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/blocks/scratch3_wedo2.js b/src/blocks/scratch3_wedo2.js index 37011517a..b8bb02dd5 100644 --- a/src/blocks/scratch3_wedo2.js +++ b/src/blocks/scratch3_wedo2.js @@ -7,6 +7,7 @@ const log = require('../util/log'); * Icon svg to be displayed at the left edge of each extension block, encoded as a data URI. * @type {string} */ +// eslint-disable-next-line max-len const iconURI = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+d2VkbzItYmxvY2staWNvbjwvdGl0bGU+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48cGF0aCBkPSJNMzUuMzEzIDEwLjQ2N0gzMi4wOVY4Ljg2NWMwLS4yMjMuMTgtLjQwNC40MDUtLjQwNGgyLjQxMmMuMjI0IDAgLjQwNi4xODIuNDA2LjQwNXYxLjYwMnpNMzAuNDc3IDEwLjQ2N2gtMy4yMjRWOC44NjVjMC0uMjIzLjE4My0uNDA0LjQwNy0uNDA0aDIuNDFjLjIyNiAwIC40MDcuMTgyLjQwNy40MDV2MS42MDJ6TTI1LjY0IDEwLjQ2N0gyMi40MlY4Ljg2NWMwLS4yMjMuMTgyLS40MDQuNDA2LS40MDRoMi40MWMuMjI2IDAgLjQwNy4xODIuNDA3LjQwNXYxLjYwMnpNMjAuODA2IDEwLjQ2N2gtMy4yMjRWOC44NjVjMC0uMjIzLjE4Mi0uNDA0LjQwNi0uNDA0SDIwLjRjLjIyNCAwIC40MDYuMTgyLjQwNi40MDV2MS42MDJ6TTE1Ljk3IDEwLjQ2N2gtMy4yMjRWOC44NjVjMC0uMjIzLjE4Mi0uNDA0LjQwNy0uNDA0aDIuNDFjLjIyNiAwIC40MDcuMTgyLjQwNy40MDV2MS42MDJ6TTExLjEzNSAxMC40NjdINy45MVY4Ljg2NWMwLS4yMjMuMTgzLS40MDQuNDA3LS40MDRoMi40MTJjLjIyMyAwIC40MDUuMTgyLjQwNS40MDV2MS42MDJ6IiBzdHJva2U9IiM2Rjc4OTMiIGZpbGw9IiNGRkYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjxwYXRoIGQ9Ik0zNy43MyAxMC40NjdINi4zYy0yLjY3IDAtNC44MzYgMi4xNTMtNC44MzYgNC44MDh2My4yMDVoMzcuMDczdi03LjIxYzAtLjQ0NC0uMzYyLS44MDMtLjgwNy0uODAzeiIgc3Ryb2tlPSIjNkY3ODkzIiBmaWxsPSIjRkZGIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48cGF0aCBkPSJNMzguMTM0IDMwLjk4SDEuODY3Yy0uMjI0IDAtLjQwMy0uMTgtLjQwMy0uNFYxNi4yMzZoMzIuNzFjLjczIDAgMS40My4yODcgMS45NDUuOC41MTUuNTE0IDEuMjE1LjgwMiAxLjk0NC44MDJoLjQ3M3YxMi43NGMwIC4yMi0uMTguNC0uNDAzLjR6IiBzdHJva2U9IiM2Rjc4OTMiIGZpbGw9IiNFNkU3RTgiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjxwYXRoIHN0cm9rZT0iIzZGNzg5MyIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNMzQuODMgMTYuMjM3bC40ODMtMi41NjVoMy4yMjMiLz48cGF0aCBkPSJNMzguNTM2IDExLjI2OFYzMC41OGMwIC4yMi0uMTguNC0uNDAzLjRIMS44NjZjLS4yMiAwLS40MDMtLjE4LS40MDMtLjR2LTEuMjAzaDM0LjI4MmMuNjUgMCAxLjE4LS41MjQgMS4xOC0xLjE3M1YxMC40NjdoLjgwNWMuNDQ2IDAgLjgwNi4zNi44MDYuOHoiIHN0cm9rZT0iIzZGNzg5MyIgZmlsbD0iIzZGNzg5MyIgb3BhY2l0eT0iLjE1IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48cGF0aCBkPSJNMTEuNTM4IDE2LjI4aDIwLjE0OGMuMjIyIDAgLjQwMy4xOC40MDMuNHY2LjUyN2MwIC4yMjItLjE4Mi40LS40MDQuNEgxMS41MzhjLS4yMjMgMC0uNDA0LS4xNzgtLjQwNC0uNFYxNi42OGMwLS4yMi4xOC0uNC40MDQtLjQiIGZpbGw9IiNFNkU3RTgiLz48cGF0aCBkPSJNMTEuNTM4IDE2LjI4aDIwLjE0OGMuMjIyIDAgLjQwMy4xOC40MDMuNHY2LjUyN2MwIC4yMjItLjE4Mi40LS40MDQuNEgxMS41MzhjLS4yMjMgMC0uNDA0LS4xNzgtLjQwNC0uNFYxNi42OGMwLS4yMi4xOC0uNC40MDQtLjR6IiBzdHJva2U9IiM2Rjc4OTMiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjxwYXRoIGQ9Ik0zMi4wOSAxNi4yOHY2LjkyN2MwIC4yMjItLjE4LjQtLjQwNC40aC0yMC4xNWMtLjIyIDAtLjQtLjE4LS40LS40di0xLjJoMTguMTZjLjY1MyAwIDEuMTgtLjUyNiAxLjE4LTEuMTc0VjE2LjI4aDEuNjEzeiIgc3Ryb2tlPSIjNkY3ODkzIiBmaWxsPSIjNkU3NzkyIiBvcGFjaXR5PSIuMTUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjxwYXRoIGQ9Ik0zMC40NzcgMTYuMjhoLTMuMjI0di0xLjYwNGMwLS4yMjMuMTgzLS40MDQuNDA3LS40MDRoMi40MWMuMjI2IDAgLjQwNy4xOC40MDcuNDA0djEuNjAzek0xNS45NyAxNi4yOGgtMy4yMjR2LTEuNjA0YzAtLjIyMy4xODItLjQwNC40MDctLjQwNGgyLjQxYy4yMjYgMCAuNDA3LjE4LjQwNy40MDR2MS42MDN6TTI1LjY0IDE2LjI4SDIyLjQydi0xLjYwNGMwLS4yMjMuMTgyLS40MDQuNDA2LS40MDRoMi40MWMuMjI2IDAgLjQwNy4xOC40MDcuNDA0djEuNjAzek0yMC44MDYgMTYuMjhoLTMuMjI0di0xLjYwNGMwLS4yMjMuMTgyLS40MDQuNDA2LS40MDRIMjAuNGMuMjI0IDAgLjQwNi4xOC40MDYuNDA0djEuNjAzeiIgc3Ryb2tlPSIjNkY3ODkzIiBmaWxsPSIjRTZFN0U4IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48cGF0aCBkPSJNMTguNTU3IDE5LjkxYzAgMS4wMjUtLjgzNyAxLjg1Ny0xLjg3IDEuODU3LTEuMDMgMC0xLjg2Ny0uODMyLTEuODY3LTEuODU4IDAtMS4wMjcuODM3LTEuODU4IDEuODY4LTEuODU4IDEuMDMyIDAgMS44Ny44MyAxLjg3IDEuODU3ek0yMy40OCAxOS45MWMwIDEuMDI1LS44MzYgMS44NTctMS44NjggMS44NTdzLTEuODctLjgzMi0xLjg3LTEuODU4YzAtMS4wMjcuODM4LTEuODU4IDEuODctMS44NThzMS44NjguODMgMS44NjggMS44NTd6TTI4LjQwNCAxOS45MWMwIDEuMDI1LS44MzcgMS44NTctMS44NjggMS44NTctMS4wMzIgMC0xLjg3LS44MzItMS44Ny0xLjg1OCAwLTEuMDI3LjgzOC0xLjg1OCAxLjg3LTEuODU4IDEuMDMgMCAxLjg2OC44MyAxLjg2OCAxLjg1N3oiIHN0cm9rZT0iIzZGNzg5MyIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+PHBhdGggZD0iTTE4LjU1NyAxOS45MjJjMCAxLjAyNi0uODM3IDEuODU4LTEuODcgMS44NTgtMS4wMyAwLTEuODY3LS44MzItMS44NjctMS44NTggMC0xLjAyNS44MzctMS44NTcgMS44NjgtMS44NTcgMS4wMzIgMCAxLjg3LjgzMiAxLjg3IDEuODU3TTIzLjQ4IDE5LjkyMmMwIDEuMDI2LS44MzYgMS44NTgtMS44NjggMS44NThzLTEuODctLjgzMi0xLjg3LTEuODU4YzAtMS4wMjUuODM4LTEuODU3IDEuODctMS44NTdzMS44NjguODMyIDEuODY4IDEuODU3TTI4LjQwNCAxOS45MjJjMCAxLjAyNi0uODM3IDEuODU4LTEuODY4IDEuODU4LTEuMDMyIDAtMS44Ny0uODMyLTEuODctMS44NTggMC0xLjAyNS44MzgtMS44NTcgMS44Ny0xLjg1NyAxLjAzIDAgMS44NjguODMyIDEuODY4IDEuODU3IiBmaWxsPSIjNkY3ODkzIiBvcGFjaXR5PSIuNSIvPjwvZz48L3N2Zz4='; /** From 59e0c75abf4ca5e7c590103be041f20086ecf0a8 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Mon, 6 Nov 2017 10:17:53 -0500 Subject: [PATCH 107/272] Fix shape of boolean tilt reporter --- src/blocks/scratch3_wedo2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blocks/scratch3_wedo2.js b/src/blocks/scratch3_wedo2.js index abc09e5db..b2d082ac4 100644 --- a/src/blocks/scratch3_wedo2.js +++ b/src/blocks/scratch3_wedo2.js @@ -544,7 +544,7 @@ class Scratch3WeDo2Blocks { { opcode: 'isTilted', text: 'tilted [DIRECTION]?', - blockType: BlockType.REPORTER, + blockType: BlockType.BOOLEAN, arguments: { DIRECTION: { type: ArgumentType.STRING, From 73ffc6a7972bcc831ad4824c750f927da1c32eb9 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Tue, 31 Oct 2017 11:12:26 -0400 Subject: [PATCH 108/272] Ask/answer opcode implementation with runtime events. --- src/blocks/scratch3_sensing.js | 58 +++++++++++++++++++++++++++++++++- test/unit/blocks_sensing.js | 34 ++++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 test/unit/blocks_sensing.js diff --git a/src/blocks/scratch3_sensing.js b/src/blocks/scratch3_sensing.js index 559b0e9c1..d9c2ab12f 100644 --- a/src/blocks/scratch3_sensing.js +++ b/src/blocks/scratch3_sensing.js @@ -7,6 +7,21 @@ class Scratch3SensingBlocks { * @type {Runtime} */ this.runtime = runtime; + + /** + * The "answer" block value. + * @type {string} + */ + this._answer = ''; + + /** + * The list of queued questions and respective `resolve` callbacks. + * @type {!Array} + */ + this._questionList = []; + + this.runtime.on('ANSWER', this._onAnswer.bind(this)); + this.runtime.on('PROJECT_STOP_ALL', this._clearAllQuestions.bind(this)); } /** @@ -28,10 +43,51 @@ class Scratch3SensingBlocks { sensing_keypressed: this.getKeyPressed, sensing_current: this.current, sensing_dayssince2000: this.daysSince2000, - sensing_loudness: this.getLoudness + sensing_loudness: this.getLoudness, + sensing_askandwait: this.askAndWait, + sensing_answer: this.getAnswer }; } + _onAnswer (answer) { + this._answer = answer; + const questionObj = this._questionList.shift(); + if (questionObj) { + const resolve = questionObj[1]; + resolve(); + this._askNextQuestion(); + } + } + + _enqueueAsk (question, resolve) { + this._questionList.push([question, resolve]); + } + + _askNextQuestion () { + if (this._questionList.length > 0) { + this.runtime.emit('QUESTION', this._questionList[0][0]); + } + } + + _clearAllQuestions () { + this._questionList = []; + this.runtime.emit('QUESTION', null); + } + + askAndWait (args) { + return new Promise(resolve => { + const isQuestionAsked = this._questionList.length > 0; + this._enqueueAsk(args.QUESTION, resolve); + if (!isQuestionAsked) { + this._askNextQuestion(); + } + }); + } + + getAnswer () { + return this._answer; + } + touchingObject (args, util) { const requestedObject = args.TOUCHINGOBJECTMENU; if (requestedObject === '_mouse_') { diff --git a/test/unit/blocks_sensing.js b/test/unit/blocks_sensing.js new file mode 100644 index 000000000..e0c60b4ba --- /dev/null +++ b/test/unit/blocks_sensing.js @@ -0,0 +1,34 @@ +const test = require('tap').test; +const Sensing = require('../../src/blocks/scratch3_sensing'); +const Runtime = require('../../src/engine/runtime'); + +test('getPrimitives', t => { + const rt = new Runtime(); + const s = new Sensing(rt); + t.type(s.getPrimitives(), 'object'); + t.end(); +}); + +test('ask and answer', t => { + const rt = new Runtime(); + const s = new Sensing(rt); + + const expectedQuestion = 'a question'; + const expectedAnswer = 'the answer'; + + // Test is written out of order because of promises, follow the (#) comments. + rt.addListener('QUESTION', question => { + // (2) Assert the question is correct, then emit the answer + t.strictEqual(question, expectedQuestion); + rt.emit('ANSWER', expectedAnswer); + }); + + // (1) Emit the question. + const promise = s.askAndWait({QUESTION: expectedQuestion}); + + // (3) Ask block resolves after the answer is emitted. + promise.then(() => { + t.strictEqual(s.getAnswer(), expectedAnswer); + t.end(); + }); +}); From cd9004ce5badc66b6e323cffcf091bc08da73706 Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Fri, 3 Nov 2017 11:40:20 -0400 Subject: [PATCH 109/272] Write src/engine/execute so it can be optimized Testing with implicitly casted `value` and `value.then` is deoptimizing isPromise, which deoptimizes execute. In this case deoptimizing means that the JavaScript VM cannot compile the functions into a form that can be run faster. --- src/engine/execute.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/engine/execute.js b/src/engine/execute.js index a4bf76b2a..24864592f 100644 --- a/src/engine/execute.js +++ b/src/engine/execute.js @@ -8,7 +8,11 @@ const {Map} = require('immutable'); * @return {boolean} True if the value appears to be a Promise. */ const isPromise = function (value) { - return value && value.then && typeof value.then === 'function'; + return ( + value !== null && + typeof value === 'object' && + typeof value.then === 'function' + ); }; /** From fbeb1de1c1f0dd76b061054667c50dfa89b8c35f Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Mon, 6 Nov 2017 16:57:16 -0500 Subject: [PATCH 110/272] Add music extension file --- src/blocks/scratch3_music.js | 301 +++++++++++++++++++++++++++++++++++ 1 file changed, 301 insertions(+) create mode 100644 src/blocks/scratch3_music.js diff --git a/src/blocks/scratch3_music.js b/src/blocks/scratch3_music.js new file mode 100644 index 000000000..b7cde9611 --- /dev/null +++ b/src/blocks/scratch3_music.js @@ -0,0 +1,301 @@ +const ArgumentType = require('../extension-support/argument-type'); +const BlockType = require('../extension-support/block-type'); +const Clone = require('../util/clone'); +const Cast = require('../util/cast'); +const MathUtil = require('../util/math-util'); + +const drumNames = [ + 'Snare Drum', + 'Bass Drum', + 'Side Stick', + 'Crash Cymbal', + 'Open Hi-Hat', + 'Closed Hi-Hat', + 'Tambourine', + 'Hand Clap', + 'Claves', + 'Wood Block', + 'Cowbell', + 'Triangle', + 'Bongo', + 'Conga', + 'Cabasa', + 'Guiro', + 'Vibraslap', + 'Open Cuica' +]; + +const instrumentNames = [ + 'Piano', + 'Electric Piano', + 'Organ', + 'Guitar', + 'Electric Guitar', + 'Bass', + 'Pizzicato', + 'Cello', + 'Trombone', + 'Clarinet', + 'Saxophone', + 'Flute', + 'Wooden Flute', + 'Bassoon', + 'Choir', + 'Vibraphone', + 'Music Box', + 'Steel Drum', + 'Marimba', + 'Synth Lead', + 'Synth Pad' +]; + +/** + * Class for the music-related blocks in Scratch 3.0 + * @param {Runtime} runtime - the runtime instantiating this block package. + * @constructor + */ +class Scratch3MusicBlocks { + constructor (runtime) { + /** + * The runtime instantiating this block package. + * @type {Runtime} + */ + this.runtime = runtime; + + this.drumMenu = this.buildMenu(drumNames); + this.instrumentMenu = this.buildMenu(instrumentNames); + } + + buildMenu (names) { + const menu = []; + for (let i = 0; i < names.length; i++) { + const entry = {}; + const num = i + 1; // Menu numbers are one-indexed + entry.text = `(${num}) ${names[i]}`; + entry.value = String(num); + menu.push(entry); + } + return menu; + } + + /** + * The key to load & store a target's music-related state. + * @type {string} + */ + static get STATE_KEY () { + return 'Scratch.music'; + } + + /** + * The default music-related state, to be used when a target has no existing music state. + * @type {MusicState} + */ + static get DEFAULT_MUSIC_STATE () { + return { + currentInstrument: 0 + }; + } + + /** + * The minimum and maximum MIDI note numbers, for clamping the input to play note. + * @type {{min: number, max: number}} + */ + static get MIDI_NOTE_RANGE () { + return {min: 36, max: 96}; // C2 to C7 + } + + /** + * The minimum and maximum beat values, for clamping the duration of play note, play drum and rest. + * 100 beats at the default tempo of 60bpm is 100 seconds. + * @type {{min: number, max: number}} + */ + static get BEAT_RANGE () { + return {min: 0, max: 100}; + } + + /** The minimum and maximum tempo values, in bpm. + * @type {{min: number, max: number}} + */ + static get TEMPO_RANGE () { + return {min: 20, max: 500}; + } + + /** + * @param {Target} target - collect music state for this target. + * @returns {MusicState} the mutable music state associated with that target. This will be created if necessary. + * @private + */ + _getMusicState (target) { + let musicState = target.getCustomState(Scratch3MusicBlocks.STATE_KEY); + if (!musicState) { + musicState = Clone.simple(Scratch3MusicBlocks.DEFAULT_MUSIC_STATE); + target.setCustomState(Scratch3MusicBlocks.STATE_KEY, musicState); + } + return musicState; + } + + /** + * @returns {object} metadata for this extension and its blocks. + */ + getInfo () { + return { + id: 'music', + name: 'Music', + blocks: [ + { + opcode: 'playDrumForBeats', + blockType: BlockType.COMMAND, + text: 'play drum [DRUM] for [BEATS] beats', + arguments: { + DRUM: { + type: ArgumentType.NUMBER, + menu: 'drums', + defaultValue: 1 + }, + BEATS: { + type: ArgumentType.NUMBER, + defaultValue: 0.25 + } + } + }, + { + opcode: 'restForBeats', + blockType: BlockType.COMMAND, + text: 'rest for [BEATS] beats', + arguments: { + BEATS: { + type: ArgumentType.NUMBER, + defaultValue: 0.25 + } + } + }, + { + opcode: 'playNoteForBeats', + blockType: BlockType.COMMAND, + text: 'play note [NOTE] for [BEATS] beats', + arguments: { + NOTE: { + type: ArgumentType.NUMBER, + defaultValue: 60 + }, + BEATS: { + type: ArgumentType.NUMBER, + defaultValue: 0.25 + } + } + }, + { + opcode: 'setInstrument', + blockType: BlockType.COMMAND, + text: 'set instrument to [INSTRUMENT]', + arguments: { + INSTRUMENT: { + type: ArgumentType.NUMBER, + menu: 'instruments', + defaultValue: 1 + } + } + }, + { + opcode: 'setTempo', + blockType: BlockType.COMMAND, + text: 'set tempo to [TEMPO]', + arguments: { + TEMPO: { + type: ArgumentType.NUMBER, + defaultValue: 60 + } + } + }, + { + opcode: 'changeTempo', + blockType: BlockType.COMMAND, + text: 'change tempo by [TEMPO]', + arguments: { + TEMPO: { + type: ArgumentType.NUMBER, + defaultValue: 20 + } + } + }, + { + opcode: 'getTempo', + text: 'tempo', + blockType: BlockType.REPORTER + } + ], + menus: { + drums: this.drumMenu, + instruments: this.instrumentMenu + } + }; + } + + playDrumForBeats (args, util) { + let drum = Cast.toNumber(args.DRUM); + drum -= 1; // drums are one-indexed + if (typeof this.runtime.audioEngine === 'undefined') return; + drum = MathUtil.wrapClamp(drum, 0, this.runtime.audioEngine.numDrums - 1); + let beats = Cast.toNumber(args.BEATS); + beats = this._clampBeats(beats); + if (util.target.audioPlayer === null) return; + return util.target.audioPlayer.playDrumForBeats(drum, beats); + } + + restForBeats (args) { + let beats = Cast.toNumber(args.BEATS); + beats = this._clampBeats(beats); + if (typeof this.runtime.audioEngine === 'undefined') return; + return this.runtime.audioEngine.waitForBeats(beats); + } + + playNoteForBeats (args, util) { + let note = Cast.toNumber(args.NOTE); + note = MathUtil.clamp(note, Scratch3MusicBlocks.MIDI_NOTE_RANGE.min, Scratch3MusicBlocks.MIDI_NOTE_RANGE.max); + let beats = Cast.toNumber(args.BEATS); + beats = this._clampBeats(beats); + const musicState = this._getMusicState(util.target); + const inst = musicState.currentInstrument; + if (typeof this.runtime.audioEngine === 'undefined') return; + return this.runtime.audioEngine.playNoteForBeatsWithInstAndVol(note, beats, inst, 100); + } + + setInstrument (args, util) { + const musicState = this._getMusicState(util.target); + let instNum = Cast.toNumber(args.INSTRUMENT); + instNum -= 1; // instruments are one-indexed + if (typeof this.runtime.audioEngine === 'undefined') return; + instNum = MathUtil.wrapClamp(instNum, 0, this.runtime.audioEngine.numInstruments - 1); + musicState.currentInstrument = instNum; + return this.runtime.audioEngine.instrumentPlayer.loadInstrument(musicState.currentInstrument); + } + + _clampBeats (beats) { + return MathUtil.clamp(beats, Scratch3MusicBlocks.BEAT_RANGE.min, Scratch3MusicBlocks.BEAT_RANGE.max); + } + + setTempo (args) { + const tempo = Cast.toNumber(args.TEMPO); + this._updateTempo(tempo); + } + + changeTempo (args) { + const change = Cast.toNumber(args.TEMPO); + if (typeof this.runtime.audioEngine === 'undefined') return; + const tempo = change + this.runtime.audioEngine.currentTempo; + this._updateTempo(tempo); + } + + _updateTempo (tempo) { + tempo = MathUtil.clamp(tempo, Scratch3MusicBlocks.TEMPO_RANGE.min, Scratch3MusicBlocks.TEMPO_RANGE.max); + if (typeof this.runtime.audioEngine === 'undefined') return; + this.runtime.audioEngine.setTempo(tempo); + } + + getTempo () { + if (typeof this.runtime.audioEngine === 'undefined') return; + return this.runtime.audioEngine.currentTempo; + } +} + +module.exports = Scratch3MusicBlocks; From 888da915a59583064488a03c8c7ad6cb92d0355a Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Mon, 6 Nov 2017 17:28:34 -0500 Subject: [PATCH 111/272] Replace duplicate documentation on getProcedureParamNames Replace the duplicate getProcedureDefintion documentation block above getProcedureParamNames. --- src/engine/blocks.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/blocks.js b/src/engine/blocks.js index ba9077fc7..92a2d58e7 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -164,9 +164,9 @@ class Blocks { } /** - * Get the procedure definition for a given name. + * Get names of parameters for the given procedure. * @param {?string} name Name of procedure to query. - * @return {?string} ID of procedure definition. + * @return {?Array.} List of param names for a procedure. */ getProcedureParamNames (name) { for (const id in this._blocks) { From cb31f206a085d7cf1ad85537d3545a6c003e4b73 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Mon, 6 Nov 2017 17:41:57 -0500 Subject: [PATCH 112/272] Improved test coverage of deleteSprite() in src/virtual-machine. Fixed bug where null check was happening after looking up property of given target. --- src/virtual-machine.js | 5 +++- test/unit/virtual-machine.js | 44 ++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 6971e4509..fe060104e 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -474,9 +474,12 @@ class VirtualMachine extends EventEmitter { */ deleteSprite (targetId) { const target = this.runtime.getTargetById(targetId); - const targetIndexBeforeDelete = this.runtime.targets.map(t => t.id).indexOf(target.id); + // const targetIndexBeforeDelete = this.runtime.targets.map(t => t.id).indexOf(target.id); + // can't call target.id if target doesn't exist. + // moving below if (target) { + const targetIndexBeforeDelete = this.runtime.targets.map(t => t.id).indexOf(target.id); if (!target.isSprite()) { throw new Error('Cannot delete non-sprite targets.'); } diff --git a/test/unit/virtual-machine.js b/test/unit/virtual-machine.js index 624dddcd1..2aa10ec87 100644 --- a/test/unit/virtual-machine.js +++ b/test/unit/virtual-machine.js @@ -110,6 +110,50 @@ test('renameSprite does not increment when renaming to the same name', t => { t.end(); }); +test('deleteSprite throws when used on a non-sprite target', t => { + const vm = new VirtualMachine(); + vm.runtime.targets = [{ + id: 'id', + isSprite: () => false + }]; + t.throws( + (() => vm.deleteSprite('id')), + new Error ('Cannot delete non-sprite targets.') + ); + t.end(); +}); + +test('deleteSprite throws when there is no sprite for the given target', t => { + const vm = new VirtualMachine(); + vm.runtime.targets = [{ + id: 'id', + isSprite: () => true, + sprite: null + }]; + t.throws( + (() => vm.deleteSprite('id')), + new Error ('No sprite associated with this target.') + ); + t.end(); +}); + +test('deleteSprite throws when there is no target with given id', t => { + const vm = new VirtualMachine(); + vm.runtime.targets = [{ + id: 'id', + isSprite: () => true, + sprite: { + name: 'this name' + } + }]; + vm.runtime.getTargetById = () => null; + t.throws( + (() => vm.deleteSprite('id')), + new Error ('No target with the provided id.') + ); + t.end(); +}); + test('emitWorkspaceUpdate', t => { const vm = new VirtualMachine(); vm.runtime.targets = [ From 78847de660b9cdbbddeb8b4dad7a6dbda2e0a0a2 Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Fri, 3 Nov 2017 11:43:19 -0400 Subject: [PATCH 113/272] Extract handleReport and add arguments to prevent closure alloc `handleReport` inside `src/engine/execute.js`'s `execute` method needs to allocate a closure to be able to refer to the higher scoped variables. `execute` is called frequently that this has a noticable impact on memory allocation and later collection. Extract handleReport and add arguments to prevent the allocation. --- src/engine/execute.js | 111 ++++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 52 deletions(-) diff --git a/src/engine/execute.js b/src/engine/execute.js index a4bf76b2a..e0da40cc2 100644 --- a/src/engine/execute.js +++ b/src/engine/execute.js @@ -11,6 +11,62 @@ const isPromise = function (value) { return value && value.then && typeof value.then === 'function'; }; +/** + * Handle any reported value from the primitive, either directly returned + * or after a promise resolves. + * @param {*} resolvedValue Value eventually returned from the primitive. + * @param {!Sequencer} sequencer Sequencer stepping the thread for the ran + * primitive. + * @param {!Thread} thread Thread containing the primitive. + * @param {!string} currentBlockId Id of the block in its thread for value from + * the primitive. + * @param {!boolean} isHat Is the current block a hat? + */ +// @todo move this to callback attached to the thread when we have performance +// metrics (dd) +const handleReport = function ( + resolvedValue, sequencer, thread, currentBlockId, isHat) { + thread.pushReportedValue(resolvedValue); + if (isHat) { + // Hat predicate was evaluated. + if (sequencer.runtime.getIsEdgeActivatedHat(opcode)) { + // If this is an edge-activated hat, only proceed if the value is + // true and used to be false, or the stack was activated explicitly + // via stack click + if (!thread.stackClick) { + const oldEdgeValue = sequencer.runtime.updateEdgeActivatedValue( + currentBlockId, + resolvedValue + ); + const edgeWasActivated = !oldEdgeValue && resolvedValue; + if (!edgeWasActivated) { + sequencer.retireThread(thread); + } + } + } else if (!resolvedValue) { + // Not an edge-activated hat: retire the thread + // if predicate was false. + sequencer.retireThread(thread); + } + } else { + // In a non-hat, report the value visually if necessary if + // at the top of the thread stack. + if (typeof resolvedValue !== 'undefined' && thread.atStackTop()) { + if (thread.stackClick) { + sequencer.runtime.visualReport(currentBlockId, resolvedValue); + } + if (thread.updateMonitor) { + sequencer.runtime.requestUpdateMonitor(Map({ + id: currentBlockId, + value: String(resolvedValue) + })); + } + } + // Finished any yields. + thread.status = Thread.STATUS_RUNNING; + } +}; + /** * Execute a block. * @param {!Sequencer} sequencer Which sequencer is executing. @@ -61,55 +117,6 @@ const execute = function (sequencer, thread) { return; } - /** - * Handle any reported value from the primitive, either directly returned - * or after a promise resolves. - * @param {*} resolvedValue Value eventually returned from the primitive. - */ - // @todo move this to callback attached to the thread when we have performance - // metrics (dd) - const handleReport = function (resolvedValue) { - thread.pushReportedValue(resolvedValue); - if (isHat) { - // Hat predicate was evaluated. - if (runtime.getIsEdgeActivatedHat(opcode)) { - // If this is an edge-activated hat, only proceed if - // the value is true and used to be false, or the stack was activated - // explicitly via stack click - if (!thread.stackClick) { - const oldEdgeValue = runtime.updateEdgeActivatedValue( - currentBlockId, - resolvedValue - ); - const edgeWasActivated = !oldEdgeValue && resolvedValue; - if (!edgeWasActivated) { - sequencer.retireThread(thread); - } - } - } else if (!resolvedValue) { - // Not an edge-activated hat: retire the thread - // if predicate was false. - sequencer.retireThread(thread); - } - } else { - // In a non-hat, report the value visually if necessary if - // at the top of the thread stack. - if (typeof resolvedValue !== 'undefined' && thread.atStackTop()) { - if (thread.stackClick) { - runtime.visualReport(currentBlockId, resolvedValue); - } - if (thread.updateMonitor) { - runtime.requestUpdateMonitor(Map({ - id: currentBlockId, - value: String(resolvedValue) - })); - } - } - // Finished any yields. - thread.status = Thread.STATUS_RUNNING; - } - }; - // Hats and single-field shadows are implemented slightly differently // from regular blocks. // For hats: if they have an associated block function, @@ -124,7 +131,7 @@ const execute = function (sequencer, thread) { const keys = Object.keys(fields); if (keys.length === 1 && Object.keys(inputs).length === 0) { // One field and no inputs - treat as arg. - handleReport(fields[keys[0]].value); + handleReport(fields[keys[0]].value, sequencer, thread, currentBlockId, isHat); } else { log.warn(`Could not get implementation for opcode: ${opcode}`); } @@ -244,7 +251,7 @@ const execute = function (sequencer, thread) { } // Promise handlers primitiveReportedValue.then(resolvedValue => { - handleReport(resolvedValue); + handleReport(resolvedValue, sequencer, thread, currentBlockId, isHat); if (typeof resolvedValue === 'undefined') { let stackFrame; let nextBlockId; @@ -277,7 +284,7 @@ const execute = function (sequencer, thread) { thread.popStack(); }); } else if (thread.status === Thread.STATUS_RUNNING) { - handleReport(primitiveReportedValue); + handleReport(primitiveReportedValue, sequencer, thread, currentBlockId, isHat); } }; From bbe79817034250a733f131062adac2562411e870 Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Fri, 3 Nov 2017 11:46:57 -0400 Subject: [PATCH 114/272] Extract blockUtility from execute to reduce allocations blockUtility as an object literal inside execute creates 11 objects, one for the object, and 10 for the function closures. As a separate object and allocated once, setting its sequencer and thread members, block functions can share the same util object. Extract blockUtility to cut down on allocations. --- src/engine/block-utility.js | 153 ++++++++++++++++++++++++++++++++++++ src/engine/execute.js | 62 ++++----------- 2 files changed, 168 insertions(+), 47 deletions(-) create mode 100644 src/engine/block-utility.js diff --git a/src/engine/block-utility.js b/src/engine/block-utility.js new file mode 100644 index 000000000..9fee1f7b6 --- /dev/null +++ b/src/engine/block-utility.js @@ -0,0 +1,153 @@ +const Thread = require('./thread'); + +/** + * @fileoverview + * Interface provided to block primitive functions for interacting with the + * runtime, thread, target, and convenient methods. + */ + +class BlockUtility { + constructor (sequencer = null, thread = null) { + /** + * A sequencer block primitives use to branch or start procedures with + * @type {?Sequencer} + */ + this.sequencer = sequencer; + + /** + * The block primitives thread with the block's target, stackFrame and + * modifiable status. + * @type {?Thread} + */ + this.thread = thread; + } + + /** + * The target the primitive is working on. + * @type {Target} + */ + get target () { + return this.thread.target; + } + + /** + * The runtime the block primitive is running in. + * @type {Runtime} + */ + get runtime () { + return this.sequencer.runtime; + } + + /** + * The stack frame used by loop and other blocks to track internal state. + * @type {object} + */ + get stackFrame () { + return this.thread.peekStackFrame().executionContext; + } + + /** + * Set the thread to yield. + */ + yield () { + this.thread.status = Thread.STATUS_YIELD; + } + + /** + * Start a branch in the current block. + * @param {number} branchNum Which branch to step to (i.e., 1, 2). + * @param {boolean} isLoop Whether this block is a loop. + */ + startBranch (branchNum, isLoop) { + this.sequencer.stepToBranch(this.thread, branchNum, isLoop); + } + + /** + * Stop all threads. + */ + stopAll () { + this.sequencer.runtime.stopAll(); + } + + /** + * Stop threads other on this target other than the thread holding the + * executed block. + */ + stopOtherTargetThreads () { + this.sequencer.runtime.stopForTarget(this.thread.target, this.thread); + } + + /** + * Stop this thread. + */ + stopThisScript () { + this.thread.stopThisScript(); + } + + /** + * Start a specified procedure on this thread. + * @param {string} procedureCode Procedure code for procedure to start. + */ + startProcedure (procedureCode) { + this.sequencer.stepToProcedure(this.thread, procedureCode); + } + + /** + * Get names for parameters for the given procedure. + * @param {string} procedureCode Procedure code for procedure to query. + * @return {Array.} List of param names for a procedure. + */ + getProcedureParamNames (procedureCode) { + return this.thread.target.blocks.getProcedureParamNames(procedureCode); + } + + /** + * Store a procedure parameter value by its name. + * @param {string} paramName The procedure's parameter name. + * @param {*} paramValue The procedure's parameter value. + */ + pushParam (paramName, paramValue) { + this.thread.pushParam(paramName, paramValue); + } + + /** + * Retrieve the stored parameter value for a given parameter name. + * @param {string} paramName The procedure's parameter name. + * @return {*} The parameter's current stored value. + */ + getParam (paramName) { + return this.thread.getParam(paramName); + } + + /** + * Start all relevant hats. + * @param {!string} requestedHat Opcode of hats to start. + * @param {object=} optMatchFields Optionally, fields to match on the hat. + * @param {Target=} optTarget Optionally, a target to restrict to. + * @return {Array.} List of threads started by this function. + */ + startHats (requestedHat, optMatchFields, optTarget) { + return ( + this.sequencer.runtime.startHats(requestedHat, optMatchFields, optTarget) + ); + } + + /** + * Query a named IO device. + * @param {string} device The name of like the device, like keyboard. + * @param {string} func The name of the device's function to query. + * @param {Array.<*>} args Arguments to pass to the device's function. + * @return {*} The expected output for the device's function. + */ + ioQuery (device, func, args) { + // Find the I/O device and execute the query/function call. + if ( + this.sequencer.runtime.ioDevices[device] && + this.sequencer.runtime.ioDevices[device][func]) { + const devObject = this.sequencer.runtime.ioDevices[device]; + return devObject[func].apply(devObject, args); + } + } +} + +module.exports = BlockUtility; diff --git a/src/engine/execute.js b/src/engine/execute.js index e0da40cc2..fda8054ad 100644 --- a/src/engine/execute.js +++ b/src/engine/execute.js @@ -1,7 +1,14 @@ +const BlockUtility = require('./block-utility'); const log = require('../util/log'); const Thread = require('./thread'); const {Map} = require('immutable'); +/** + * Single BlockUtility instance reused by execute for every pritimive ran. + * @const + */ +const blockUtility = new BlockUtility(); + /** * Utility function to determine if a value is a Promise. * @param {*} value Value to check for a Promise. @@ -20,12 +27,13 @@ const isPromise = function (value) { * @param {!Thread} thread Thread containing the primitive. * @param {!string} currentBlockId Id of the block in its thread for value from * the primitive. + * @param {!string} opcode opcode used to identify a block function primitive. * @param {!boolean} isHat Is the current block a hat? */ // @todo move this to callback attached to the thread when we have performance // metrics (dd) const handleReport = function ( - resolvedValue, sequencer, thread, currentBlockId, isHat) { + resolvedValue, sequencer, thread, currentBlockId, opcode, isHat) { thread.pushReportedValue(resolvedValue); if (isHat) { // Hat predicate was evaluated. @@ -131,7 +139,7 @@ const execute = function (sequencer, thread) { const keys = Object.keys(fields); if (keys.length === 1 && Object.keys(inputs).length === 0) { // One field and no inputs - treat as arg. - handleReport(fields[keys[0]].value, sequencer, thread, currentBlockId, isHat); + handleReport(fields[keys[0]].value, sequencer, thread, currentBlockId, opcode, isHat); } else { log.warn(`Could not get implementation for opcode: ${opcode}`); } @@ -193,49 +201,9 @@ const execute = function (sequencer, thread) { currentStackFrame.reported = {}; let primitiveReportedValue = null; - primitiveReportedValue = blockFunction(argValues, { - stackFrame: currentStackFrame.executionContext, - target: target, - yield: function () { - thread.status = Thread.STATUS_YIELD; - }, - startBranch: function (branchNum, isLoop) { - sequencer.stepToBranch(thread, branchNum, isLoop); - }, - stopAll: function () { - runtime.stopAll(); - }, - stopOtherTargetThreads: function () { - runtime.stopForTarget(target, thread); - }, - stopThisScript: function () { - thread.stopThisScript(); - }, - startProcedure: function (procedureCode) { - sequencer.stepToProcedure(thread, procedureCode); - }, - getProcedureParamNames: function (procedureCode) { - return blockContainer.getProcedureParamNames(procedureCode); - }, - pushParam: function (paramName, paramValue) { - thread.pushParam(paramName, paramValue); - }, - getParam: function (paramName) { - return thread.getParam(paramName); - }, - startHats: function (requestedHat, optMatchFields, optTarget) { - return ( - runtime.startHats(requestedHat, optMatchFields, optTarget) - ); - }, - ioQuery: function (device, func, args) { - // Find the I/O device and execute the query/function call. - if (runtime.ioDevices[device] && runtime.ioDevices[device][func]) { - const devObject = runtime.ioDevices[device]; - return devObject[func].apply(devObject, args); - } - } - }); + blockUtility.sequencer = sequencer; + blockUtility.thread = thread; + primitiveReportedValue = blockFunction(argValues, blockUtility); if (typeof primitiveReportedValue === 'undefined') { // No value reported - potentially a command block. @@ -251,7 +219,7 @@ const execute = function (sequencer, thread) { } // Promise handlers primitiveReportedValue.then(resolvedValue => { - handleReport(resolvedValue, sequencer, thread, currentBlockId, isHat); + handleReport(resolvedValue, sequencer, thread, currentBlockId, opcode, isHat); if (typeof resolvedValue === 'undefined') { let stackFrame; let nextBlockId; @@ -284,7 +252,7 @@ const execute = function (sequencer, thread) { thread.popStack(); }); } else if (thread.status === Thread.STATUS_RUNNING) { - handleReport(primitiveReportedValue, sequencer, thread, currentBlockId, isHat); + handleReport(primitiveReportedValue, sequencer, thread, currentBlockId, opcode, isHat); } }; From e3dfe24d7f8f2fae994fca87e6ca06911f7d55bd Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Fri, 3 Nov 2017 11:50:16 -0400 Subject: [PATCH 115/272] Store references to target in say blocks As part of reusing the block utility object, asynchronous say block functions cannot use the utility in a promise or timeout asynchronous handle. Store the needed target reference so utility is not needed later. --- src/blocks/scratch3_looks.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index df1a0246e..399c6efa5 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -245,11 +245,12 @@ class Scratch3LooksBlocks { sayforsecs (args, util) { this.say(args, util); + const _target = util.target; return new Promise(resolve => { this._bubbleTimeout = setTimeout(() => { this._bubbleTimeout = null; // Clear say bubble and proceed. - this._updateBubble(util.target, 'say', ''); + this._updateBubble(_target, 'say', ''); resolve(); }, 1000 * args.SECS); }); @@ -261,11 +262,12 @@ class Scratch3LooksBlocks { thinkforsecs (args, util) { this.think(args, util); + const _target = util.target; return new Promise(resolve => { this._bubbleTimeout = setTimeout(() => { this._bubbleTimeout = null; // Clear say bubble and proceed. - this._updateBubble(util.target, 'think', ''); + this._updateBubble(_target, 'think', ''); resolve(); }, 1000 * args.SECS); }); From b2941f8c5a420321d7a0b926a65220089f8fc61c Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 7 Nov 2017 11:27:33 -0500 Subject: [PATCH 116/272] Load music as internal extension --- src/extension-support/extension-manager.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index 5cfa2b4a3..938e791dc 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -8,9 +8,11 @@ const BlockType = require('./block-type'); // TODO: change extension spec so that library info, including extension ID, can be collected through static methods const Scratch3PenBlocks = require('../blocks/scratch3_pen'); const Scratch3WeDo2Blocks = require('../blocks/scratch3_wedo2'); +const Scratch3MusicBlocks = require('../blocks/scratch3_music'); const builtinExtensions = { pen: Scratch3PenBlocks, - wedo2: Scratch3WeDo2Blocks + wedo2: Scratch3WeDo2Blocks, + music: Scratch3MusicBlocks }; /** From 533ed60d98915770e20faee5191c87364e85f2a8 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 7 Nov 2017 11:27:50 -0500 Subject: [PATCH 117/272] Update sb2 specmap with music extension blocks --- src/serialization/sb2_specmap.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/serialization/sb2_specmap.js b/src/serialization/sb2_specmap.js index cf5be1c89..b511d59c8 100644 --- a/src/serialization/sb2_specmap.js +++ b/src/serialization/sb2_specmap.js @@ -418,7 +418,7 @@ const specMap = { ] }, 'playDrum': { - opcode: 'sound_playdrumforbeats', + opcode: 'music.playDrumForBeats', argMap: [ { type: 'input', @@ -433,7 +433,7 @@ const specMap = { ] }, 'rest:elapsed:from:': { - opcode: 'sound_restforbeats', + opcode: 'music.restForBeats', argMap: [ { type: 'input', @@ -443,7 +443,7 @@ const specMap = { ] }, 'noteOn:duration:elapsed:from:': { - opcode: 'sound_playnoteforbeats', + opcode: 'music.playNoteForBeats', argMap: [ { type: 'input', @@ -458,7 +458,7 @@ const specMap = { ] }, 'instrument:': { - opcode: 'sound_setinstrumentto', + opcode: 'music.setInstrument', argMap: [ { type: 'input', @@ -493,7 +493,7 @@ const specMap = { ] }, 'changeTempoBy:': { - opcode: 'sound_changetempoby', + opcode: 'music.changeTempo', argMap: [ { type: 'input', @@ -503,7 +503,7 @@ const specMap = { ] }, 'setTempoTo:': { - opcode: 'sound_settempotobpm', + opcode: 'music.setTempo', argMap: [ { type: 'input', @@ -513,7 +513,7 @@ const specMap = { ] }, 'tempo': { - opcode: 'sound_tempo', + opcode: 'music.getTempo', argMap: [ ] }, From 87cf546b038bc32f6c82bd36df7bf41f1271e382 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 7 Nov 2017 11:28:04 -0500 Subject: [PATCH 118/272] Remove music opcodes from sound bocks --- src/blocks/scratch3_sound.js | 76 +----------------------------------- 1 file changed, 1 insertion(+), 75 deletions(-) diff --git a/src/blocks/scratch3_sound.js b/src/blocks/scratch3_sound.js index 1f7745742..6f5fed972 100644 --- a/src/blocks/scratch3_sound.js +++ b/src/blocks/scratch3_sound.js @@ -91,10 +91,6 @@ class Scratch3SoundBlocks { sound_play: this.playSound, sound_playuntildone: this.playSoundAndWait, sound_stopallsounds: this.stopAllSounds, - sound_playnoteforbeats: this.playNoteForBeats, - sound_playdrumforbeats: this.playDrumForBeats, - sound_restforbeats: this.restForBeats, - sound_setinstrumentto: this.setInstrument, sound_seteffectto: this.setEffect, sound_changeeffectby: this.changeEffect, sound_cleareffects: this.clearEffects, @@ -103,10 +99,7 @@ class Scratch3SoundBlocks { sound_effects_menu: this.effectsMenu, sound_setvolumeto: this.setVolume, sound_changevolumeby: this.changeVolume, - sound_volume: this.getVolume, - sound_settempotobpm: this.setTempo, - sound_changetempoby: this.changeTempo, - sound_tempo: this.getTempo + sound_volume: this.getVolume }; } @@ -167,50 +160,6 @@ class Scratch3SoundBlocks { util.target.audioPlayer.stopAllSounds(); } - playNoteForBeats (args, util) { - let note = Cast.toNumber(args.NOTE); - note = MathUtil.clamp(note, Scratch3SoundBlocks.MIDI_NOTE_RANGE.min, Scratch3SoundBlocks.MIDI_NOTE_RANGE.max); - let beats = Cast.toNumber(args.BEATS); - beats = this._clampBeats(beats); - const soundState = this._getSoundState(util.target); - const inst = soundState.currentInstrument; - const vol = soundState.volume; - if (typeof this.runtime.audioEngine === 'undefined') return; - return this.runtime.audioEngine.playNoteForBeatsWithInstAndVol(note, beats, inst, vol); - } - - playDrumForBeats (args, util) { - let drum = Cast.toNumber(args.DRUM); - drum -= 1; // drums are one-indexed - if (typeof this.runtime.audioEngine === 'undefined') return; - drum = MathUtil.wrapClamp(drum, 0, this.runtime.audioEngine.numDrums - 1); - let beats = Cast.toNumber(args.BEATS); - beats = this._clampBeats(beats); - if (util.target.audioPlayer === null) return; - return util.target.audioPlayer.playDrumForBeats(drum, beats); - } - - restForBeats (args) { - let beats = Cast.toNumber(args.BEATS); - beats = this._clampBeats(beats); - if (typeof this.runtime.audioEngine === 'undefined') return; - return this.runtime.audioEngine.waitForBeats(beats); - } - - _clampBeats (beats) { - return MathUtil.clamp(beats, Scratch3SoundBlocks.BEAT_RANGE.min, Scratch3SoundBlocks.BEAT_RANGE.max); - } - - setInstrument (args, util) { - const soundState = this._getSoundState(util.target); - let instNum = Cast.toNumber(args.INSTRUMENT); - instNum -= 1; // instruments are one-indexed - if (typeof this.runtime.audioEngine === 'undefined') return; - instNum = MathUtil.wrapClamp(instNum, 0, this.runtime.audioEngine.numInstruments - 1); - soundState.currentInstrument = instNum; - return this.runtime.audioEngine.instrumentPlayer.loadInstrument(soundState.currentInstrument); - } - setEffect (args, util) { this._updateEffect(args, util, false); } @@ -273,29 +222,6 @@ class Scratch3SoundBlocks { return soundState.volume; } - setTempo (args) { - const tempo = Cast.toNumber(args.TEMPO); - this._updateTempo(tempo); - } - - changeTempo (args) { - const change = Cast.toNumber(args.TEMPO); - if (typeof this.runtime.audioEngine === 'undefined') return; - const tempo = change + this.runtime.audioEngine.currentTempo; - this._updateTempo(tempo); - } - - _updateTempo (tempo) { - tempo = MathUtil.clamp(tempo, Scratch3SoundBlocks.TEMPO_RANGE.min, Scratch3SoundBlocks.TEMPO_RANGE.max); - if (typeof this.runtime.audioEngine === 'undefined') return; - this.runtime.audioEngine.setTempo(tempo); - } - - getTempo () { - if (typeof this.runtime.audioEngine === 'undefined') return; - return this.runtime.audioEngine.currentTempo; - } - soundsMenu (args) { return args.SOUND_MENU; } From 9bd48e8761384e62223de7850034062cb58e7cb7 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 7 Nov 2017 15:21:20 -0500 Subject: [PATCH 119/272] Mark the buildMenu function private --- src/blocks/scratch3_music.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/blocks/scratch3_music.js b/src/blocks/scratch3_music.js index b7cde9611..cdd9fc33c 100644 --- a/src/blocks/scratch3_music.js +++ b/src/blocks/scratch3_music.js @@ -62,11 +62,12 @@ class Scratch3MusicBlocks { */ this.runtime = runtime; - this.drumMenu = this.buildMenu(drumNames); - this.instrumentMenu = this.buildMenu(instrumentNames); + this.drumMenu = this._buildMenu(drumNames); + this.instrumentMenu = this._buildMenu(instrumentNames); } buildMenu (names) { + _buildMenu (names) { const menu = []; for (let i = 0; i < names.length; i++) { const entry = {}; From 112bb55b9b02494fbf78cddea60d706ef3cff086 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 7 Nov 2017 15:21:47 -0500 Subject: [PATCH 120/272] JSDoc --- src/blocks/scratch3_music.js | 71 +++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/src/blocks/scratch3_music.js b/src/blocks/scratch3_music.js index cdd9fc33c..f70fd48ae 100644 --- a/src/blocks/scratch3_music.js +++ b/src/blocks/scratch3_music.js @@ -4,6 +4,10 @@ const Clone = require('../util/clone'); const Cast = require('../util/cast'); const MathUtil = require('../util/math-util'); +/** + * An array of drum names, used in the play drum block. + * @type {string[]} + */ const drumNames = [ 'Snare Drum', 'Bass Drum', @@ -25,6 +29,10 @@ const drumNames = [ 'Open Cuica' ]; +/** + * An array of instrument names, used in the set instrument block. + * @type {string[]} + */ const instrumentNames = [ 'Piano', 'Electric Piano', @@ -66,7 +74,13 @@ class Scratch3MusicBlocks { this.instrumentMenu = this._buildMenu(instrumentNames); } - buildMenu (names) { + /** + * Build a menu using an array of strings. + * Used for creating the drum and instrument menus. + * @param {string[]} names - An array of names. + * @return {array} - An array of objects with text and value properties, for constructing a block menu. + * @private + */ _buildMenu (names) { const menu = []; for (let i = 0; i < names.length; i++) { @@ -232,6 +246,14 @@ class Scratch3MusicBlocks { }; } + /** + * Play a drum sound for some number of beats. + * @param {object} args - the block arguments. + * @param {object} util - utility object provided by the runtime. + * @property {int} DRUM - the number of the drum to play. + * @property {number} BEATS - the duration in beats of the drum sound. + * @return {Promise} - a promise which will resolve at the end of the duration. + */ playDrumForBeats (args, util) { let drum = Cast.toNumber(args.DRUM); drum -= 1; // drums are one-indexed @@ -243,6 +265,13 @@ class Scratch3MusicBlocks { return util.target.audioPlayer.playDrumForBeats(drum, beats); } + /** + * Rest for some number of beats. + * @param {object} args - the block arguments. + * @param {object} util - utility object provided by the runtime. + * @property {number} BEATS - the duration in beats of the rest. + * @return {Promise} - a promise which will resolve at the end of the duration. + */ restForBeats (args) { let beats = Cast.toNumber(args.BEATS); beats = this._clampBeats(beats); @@ -250,6 +279,14 @@ class Scratch3MusicBlocks { return this.runtime.audioEngine.waitForBeats(beats); } + /** + * Play a note using the current musical instrument for some number of beats. + * @param {object} args - the block arguments. + * @param {object} util - utility object provided by the runtime. + * @property {number} NOTE - the pitch of the note to play, interpreted as a MIDI note number. + * @property {number} BEATS - the duration in beats of the note. + * @return {Promise} - a promise which will resolve at the end of the duration. + */ playNoteForBeats (args, util) { let note = Cast.toNumber(args.NOTE); note = MathUtil.clamp(note, Scratch3MusicBlocks.MIDI_NOTE_RANGE.min, Scratch3MusicBlocks.MIDI_NOTE_RANGE.max); @@ -261,6 +298,13 @@ class Scratch3MusicBlocks { return this.runtime.audioEngine.playNoteForBeatsWithInstAndVol(note, beats, inst, 100); } + /** + * Select an instrument for playing notes. + * @param {object} args - the block arguments. + * @param {object} util - utility object provided by the runtime. + * @property {int} INSTRUMENT - the number of the instrument to select. + * @return {Promise} - a promise which will resolve once the instrument has loaded. + */ setInstrument (args, util) { const musicState = this._getMusicState(util.target); let instNum = Cast.toNumber(args.INSTRUMENT); @@ -271,15 +315,31 @@ class Scratch3MusicBlocks { return this.runtime.audioEngine.instrumentPlayer.loadInstrument(musicState.currentInstrument); } + /** + * Clamp a duration in beats to the allowed min and max duration. + * @param {number} beats - a duration in beats. + * @return {number} - the clamped duration. + * @private + */ _clampBeats (beats) { return MathUtil.clamp(beats, Scratch3MusicBlocks.BEAT_RANGE.min, Scratch3MusicBlocks.BEAT_RANGE.max); } + /** + * Set the current tempo to a new value. + * @param {object} args - the block arguments. + * @property {number} TEMPO - the tempo, in beats per minute. + */ setTempo (args) { const tempo = Cast.toNumber(args.TEMPO); this._updateTempo(tempo); } + /** + * Change the current tempo by some amount. + * @param {object} args - the block arguments. + * @property {number} TEMPO - the amount to change the tempo, in beats per minute. + */ changeTempo (args) { const change = Cast.toNumber(args.TEMPO); if (typeof this.runtime.audioEngine === 'undefined') return; @@ -287,12 +347,21 @@ class Scratch3MusicBlocks { this._updateTempo(tempo); } + /** + * Update the current tempo, clamping it to the min and max allowable range. + * @param {number} tempo - the tempo to set, in beats per minute. + * @private + */ _updateTempo (tempo) { tempo = MathUtil.clamp(tempo, Scratch3MusicBlocks.TEMPO_RANGE.min, Scratch3MusicBlocks.TEMPO_RANGE.max); if (typeof this.runtime.audioEngine === 'undefined') return; this.runtime.audioEngine.setTempo(tempo); } + /** + * Get the current tempo. + * @return {number} - the current tempo, in beats per minute. + */ getTempo () { if (typeof this.runtime.audioEngine === 'undefined') return; return this.runtime.audioEngine.currentTempo; From dc4767646fce8cda2f22c33aed4464f45c3589f8 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 7 Nov 2017 16:26:20 -0500 Subject: [PATCH 121/272] Move music-related unit tests into a separate file --- test/unit/blocks_music.js | 48 ++++++++++++++++++++++++++++++++++++++ test/unit/blocks_sounds.js | 44 +++------------------------------- 2 files changed, 51 insertions(+), 41 deletions(-) create mode 100644 test/unit/blocks_music.js diff --git a/test/unit/blocks_music.js b/test/unit/blocks_music.js new file mode 100644 index 000000000..3b8f8d949 --- /dev/null +++ b/test/unit/blocks_music.js @@ -0,0 +1,48 @@ +const test = require('tap').test; +const Music = require('../../src/blocks/scratch3_music'); +let playedDrum; +let playedInstrument; +const runtime = { + audioEngine: { + numDrums: 3, + numInstruments: 3, + instrumentPlayer: { + loadInstrument: instrument => (playedInstrument = instrument) + } + } +}; +const blocks = new Music(runtime); +const util = { + target: { + audioPlayer: { + playDrumForBeats: drum => (playedDrum = drum) + } + } +}; + +test('playDrum uses 1-indexing and wrap clamps', t => { + let args = {DRUM: 1}; + blocks.playDrumForBeats(args, util); + t.strictEqual(playedDrum, 0); + + args = {DRUM: runtime.audioEngine.numDrums + 1}; + blocks.playDrumForBeats(args, util); + t.strictEqual(playedDrum, 0); + + t.end(); +}); + +test('setInstrument uses 1-indexing and wrap clamps', t => { + // Stub getMusicState + blocks._getMusicState = () => ({}); + + let args = {INSTRUMENT: 1}; + blocks.setInstrument(args, util); + t.strictEqual(playedInstrument, 0); + + args = {INSTRUMENT: runtime.audioEngine.numInstruments + 1}; + blocks.setInstrument(args, util); + t.strictEqual(playedInstrument, 0); + + t.end(); +}); diff --git a/test/unit/blocks_sounds.js b/test/unit/blocks_sounds.js index 753f46f0c..9a44e7f9f 100644 --- a/test/unit/blocks_sounds.js +++ b/test/unit/blocks_sounds.js @@ -1,18 +1,8 @@ const test = require('tap').test; const Sound = require('../../src/blocks/scratch3_sound'); let playedSound; -let playedDrum; -let playedInstrument; -const runtime = { - audioEngine: { - numDrums: 3, - numInstruments: 3, - instrumentPlayer: { - loadInstrument: instrument => (playedInstrument = instrument) - } - } -}; -const blocks = new Sound(runtime); + +const blocks = new Sound(); const util = { target: { sprite: { @@ -24,8 +14,7 @@ const util = { ] }, audioPlayer: { - playSound: soundId => (playedSound = soundId), - playDrumForBeats: drum => (playedDrum = drum) + playSound: soundId => (playedSound = soundId) } } }; @@ -82,30 +71,3 @@ test('playSound prioritizes sound name if given a string', t => { t.strictEqual(playedSound, 'fourth soundId'); t.end(); }); - -test('playDrum uses 1-indexing and wrap clamps', t => { - let args = {DRUM: 1}; - blocks.playDrumForBeats(args, util); - t.strictEqual(playedDrum, 0); - - args = {DRUM: runtime.audioEngine.numDrums + 1}; - blocks.playDrumForBeats(args, util); - t.strictEqual(playedDrum, 0); - - t.end(); -}); - -test('setInstrument uses 1-indexing and wrap clamps', t => { - // Stub getSoundState - blocks._getSoundState = () => ({}); - - let args = {INSTRUMENT: 1}; - blocks.setInstrument(args, util); - t.strictEqual(playedInstrument, 0); - - args = {INSTRUMENT: runtime.audioEngine.numInstruments + 1}; - blocks.setInstrument(args, util); - t.strictEqual(playedInstrument, 0); - - t.end(); -}); From c0fdbc2f4d2f3ddc78c1b39f0476624ac1cf32b2 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 7 Nov 2017 16:26:35 -0500 Subject: [PATCH 122/272] Fix sound integration test --- test/integration/sound.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/integration/sound.js b/test/integration/sound.js index 50100d70f..1c5f20dcd 100644 --- a/test/integration/sound.js +++ b/test/integration/sound.js @@ -1,12 +1,17 @@ +const Worker = require('tiny-worker'); const path = require('path'); const test = require('tap').test; const makeTestStorage = require('../fixtures/make-test-storage'); const extract = require('../fixtures/extract'); const VirtualMachine = require('../../src/index'); +const dispatch = require('../../src/dispatch/central-dispatch'); const uri = path.resolve(__dirname, '../fixtures/sound.sb2'); const project = extract(uri); +// By default Central Dispatch works with the Worker class built into the browser. Tell it to use TinyWorker instead. +dispatch.workerClass = Worker; + test('sound', t => { const vm = new VirtualMachine(); vm.attachStorage(makeTestStorage()); From 16ca994818f74892dd636d6cbb0e0e3ed97886ca Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 8 Nov 2017 10:37:38 -0500 Subject: [PATCH 123/272] Allow ask to use say bubble via events --- src/blocks/scratch3_looks.js | 4 ++++ src/blocks/scratch3_sensing.js | 25 +++++++++++++++++------ test/unit/blocks_sensing.js | 37 ++++++++++++++++++++++++++++++++-- 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index 399c6efa5..70238a786 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -23,10 +23,14 @@ class Scratch3LooksBlocks { this._onTargetMoved = this._onTargetMoved.bind(this); this._onResetBubbles = this._onResetBubbles.bind(this); this._onTargetWillExit = this._onTargetWillExit.bind(this); + this._updateBubble = this._updateBubble.bind(this); // Reset all bubbles on start/stop this.runtime.on('PROJECT_STOP_ALL', this._onResetBubbles); this.runtime.on('targetWasRemoved', this._onTargetWillExit); + + // Enable other blocks to use bubbles like ask/answer + this.runtime.on('SAY', this._updateBubble); } /** diff --git a/src/blocks/scratch3_sensing.js b/src/blocks/scratch3_sensing.js index d9c2ab12f..17dc87e9d 100644 --- a/src/blocks/scratch3_sensing.js +++ b/src/blocks/scratch3_sensing.js @@ -53,19 +53,31 @@ class Scratch3SensingBlocks { this._answer = answer; const questionObj = this._questionList.shift(); if (questionObj) { - const resolve = questionObj[1]; + const [_question, resolve, target, wasVisible] = questionObj; + // If the target was visible when asked, hide the say bubble. + if (wasVisible) { + this.runtime.emit('SAY', target, 'say', ''); + } resolve(); this._askNextQuestion(); } } - _enqueueAsk (question, resolve) { - this._questionList.push([question, resolve]); + _enqueueAsk (question, resolve, target, wasVisible) { + this._questionList.push([question, resolve, target, wasVisible]); } _askNextQuestion () { if (this._questionList.length > 0) { - this.runtime.emit('QUESTION', this._questionList[0][0]); + const [question, _resolve, target, wasVisible] = this._questionList[0]; + // If the target is visible, emit a blank question and use the + // say event to trigger a bubble. + if (wasVisible) { + this.runtime.emit('SAY', target, 'say', question); + this.runtime.emit('QUESTION', ''); + } else { + this.runtime.emit('QUESTION', question); + } } } @@ -74,10 +86,11 @@ class Scratch3SensingBlocks { this.runtime.emit('QUESTION', null); } - askAndWait (args) { + askAndWait (args, util) { + const _target = util.target; return new Promise(resolve => { const isQuestionAsked = this._questionList.length > 0; - this._enqueueAsk(args.QUESTION, resolve); + this._enqueueAsk(args.QUESTION, resolve, _target, _target.visible); if (!isQuestionAsked) { this._askNextQuestion(); } diff --git a/test/unit/blocks_sensing.js b/test/unit/blocks_sensing.js index e0c60b4ba..5c2b927a8 100644 --- a/test/unit/blocks_sensing.js +++ b/test/unit/blocks_sensing.js @@ -9,9 +9,10 @@ test('getPrimitives', t => { t.end(); }); -test('ask and answer', t => { +test('ask and answer with a hidden target', t => { const rt = new Runtime(); const s = new Sensing(rt); + const util = {target: {visible: false}}; const expectedQuestion = 'a question'; const expectedAnswer = 'the answer'; @@ -24,7 +25,7 @@ test('ask and answer', t => { }); // (1) Emit the question. - const promise = s.askAndWait({QUESTION: expectedQuestion}); + const promise = s.askAndWait({QUESTION: expectedQuestion}, util); // (3) Ask block resolves after the answer is emitted. promise.then(() => { @@ -32,3 +33,35 @@ test('ask and answer', t => { t.end(); }); }); + +test('ask and answer with a visible target', t => { + const rt = new Runtime(); + const s = new Sensing(rt); + const util = {target: {visible: true}}; + + const expectedQuestion = 'a question'; + const expectedAnswer = 'the answer'; + + rt.removeAllListeners('SAY'); // Prevent say blocks from executing + + rt.addListener('SAY', (target, type, question) => { + // Should emit SAY with the question + t.strictEqual(question, expectedQuestion); + }); + + rt.addListener('QUESTION', question => { + // Question should be blank for a visible target + t.strictEqual(question, ''); + + // Remove the say listener and add a new one to assert bubble is cleared + // by setting say to empty string after answer is received. + rt.removeAllListeners('SAY'); + rt.addListener('SAY', (target, type, text) => { + t.strictEqual(text, ''); + t.end(); + }); + rt.emit('ANSWER', expectedAnswer); + }); + + s.askAndWait({QUESTION: expectedQuestion}, util); +}); From bf6b78137a819867b89843f047fbcea7d7a9ee48 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Wed, 8 Nov 2017 15:48:24 -0500 Subject: [PATCH 124/272] Test coverage for virtual-machine's deleteSprite and duplicateSprite functions. --- test/unit/virtual-machine.js | 130 ++++++++++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 2 deletions(-) diff --git a/test/unit/virtual-machine.js b/test/unit/virtual-machine.js index 2aa10ec87..199640d74 100644 --- a/test/unit/virtual-machine.js +++ b/test/unit/virtual-machine.js @@ -1,5 +1,8 @@ const test = require('tap').test; const VirtualMachine = require('../../src/virtual-machine.js'); +const Target = require('../../src/engine/target.js'); +const Sprite = require('../../src/sprites/sprite.js'); +const RenderedTarget = require('../../src/sprites/rendered-target'); test('renameSprite throws when there is no sprite with that id', t => { const vm = new VirtualMachine(); @@ -146,14 +149,137 @@ test('deleteSprite throws when there is no target with given id', t => { name: 'this name' } }]; - vm.runtime.getTargetById = () => null; t.throws( - (() => vm.deleteSprite('id')), + (() => vm.deleteSprite('id1')), new Error ('No target with the provided id.') ); t.end(); }); +test('deleteSprite deletes a sprite when given id is associated with a known sprite', t => { + const vm = new VirtualMachine(); + const spr = new Sprite(null, vm.runtime); + const currTarget = spr.createClone(); + + vm.runtime.targets = [currTarget]; + + t.equal(currTarget.sprite.clones.length, 1); + vm.deleteSprite(currTarget.id); + t.equal(currTarget.sprite.clones.length, 0); + t.end(); +}); + +test('deleteSprite sets editing target as null when sprite being deleted is current editing target, and the only target in the runtime', t => { + const vm = new VirtualMachine(); + const spr = new Sprite(null, vm.runtime); + const currTarget = spr.createClone(); + + vm.editingTarget = currTarget; + vm.runtime.targets = [currTarget]; + + vm.deleteSprite(currTarget.id); + + t.equal(vm.runtime.targets.length, 0); + t.equal(vm.editingTarget, null); + t.end(); +}); + +test('deleteSprite updates editingTarget when sprite being deleted is current editing target, and there is another target in the runtime', t => { + const vm = new VirtualMachine(); + const spr1 = new Sprite(null, vm.runtime); + const spr2 = new Sprite(null, vm.runtime); + const currTarget = spr1.createClone(); + const otherTarget = spr2.createClone(); + + vm.emitWorkspaceUpdate = () => null; + + vm.runtime.targets = [currTarget, otherTarget]; + vm.editingTarget = currTarget; + + t.equal(vm.runtime.targets.length, 2); + vm.deleteSprite(currTarget.id); + t.equal(vm.runtime.targets.length, 1); + t.equal(vm.editingTarget.id, otherTarget.id); + + // now let's try them in the other order in the runtime.targets list + + // can't reuse deleted targets + const currTarget2 = spr1.createClone(); + const otherTarget2 = spr2.createClone(); + + vm.runtime.targets = [otherTarget2, currTarget2]; + vm.editingTarget = currTarget2; + + t.equal(vm.runtime.targets.length, 2); + vm.deleteSprite(currTarget2.id); + t.equal(vm.editingTarget.id, otherTarget2.id); + t.equal(vm.runtime.targets.length, 1); + + t.end(); +}); + + + +test('duplicateSprite throws when there is no target with given id', t => { + const vm = new VirtualMachine(); + vm.runtime.targets = [{ + id: 'id', + isSprite: () => true, + sprite: { + name: 'this name' + } + }]; + t.throws( + (() => vm.duplicateSprite('id1')), + new Error('No target with the provided id') + ); + t.end(); +}); + +test('duplicateSprite throws when used on a non-sprite target', t => { + const vm = new VirtualMachine(); + vm.runtime.targets = [{ + id: 'id', + isSprite: () => false + }]; + t.throws( + (() => vm.duplicateSprite('id')), + new Error('Cannot duplicate non-sprite targets.') + ); + t.end(); +}); + +test('duplicateSprite throws when there is no sprite for the given target', t => { + const vm = new VirtualMachine(); + vm.runtime.targets = [{ + id: 'id', + isSprite: () => true, + sprite: null + }]; + t.throws( + (() => vm.duplicateSprite('id')), + new Error ('No sprite associated with this target.') + ); + t.end(); +}); + +test('duplicateSprite duplicates a sprite when given id is associated with known sprite', t => { + const vm = new VirtualMachine(); + const spr = new Sprite(null, vm.runtime); + const currTarget = spr.createClone(); + vm.editingTarget = currTarget; + + vm.emitWorkspaceUpdate = () => null; + + vm.runtime.targets = [currTarget]; + t.equal(vm.runtime.targets.length, 1); + vm.duplicateSprite(currTarget.id).then(() => { + t.equal(vm.runtime.targets.length, 2); + t.end(); + }); + +}); + test('emitWorkspaceUpdate', t => { const vm = new VirtualMachine(); vm.runtime.targets = [ From 70081132cb4adf7a4effd40b17ae2ee2e4f480a8 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Wed, 8 Nov 2017 15:49:51 -0500 Subject: [PATCH 125/272] Changes to src/virtual-machine based on minor bugs found during testing. This was supposed to be included with the previous commit. --- src/virtual-machine.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index fe060104e..d45cca8d2 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -495,7 +495,11 @@ class VirtualMachine extends EventEmitter { // Ensure editing target is switched if we are deleting it. if (clone === currentEditingTarget) { const nextTargetIndex = Math.min(this.runtime.targets.length - 1, targetIndexBeforeDelete); - this.setEditingTarget(this.runtime.targets[nextTargetIndex].id); + if (this.runtime.targets.length > 0){ + this.setEditingTarget(this.runtime.targets[nextTargetIndex].id); + } else { + this.editingTarget = null; + } } } // Sprite object should be deleted by GC. @@ -518,7 +522,7 @@ class VirtualMachine extends EventEmitter { } else if (!target.sprite) { throw new Error('No sprite associated with this target.'); } - target.duplicate().then(newTarget => { + return target.duplicate().then(newTarget => { this.runtime.targets.push(newTarget); this.setEditingTarget(newTarget.id); }); From 7fae93f6e6af93a0f690625788c49fabbb4f1bac Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Wed, 8 Nov 2017 15:59:35 -0500 Subject: [PATCH 126/272] Removing unnecessary comments from edits. --- src/virtual-machine.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index d45cca8d2..5056e4ae0 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -474,9 +474,6 @@ class VirtualMachine extends EventEmitter { */ deleteSprite (targetId) { const target = this.runtime.getTargetById(targetId); - // const targetIndexBeforeDelete = this.runtime.targets.map(t => t.id).indexOf(target.id); - // can't call target.id if target doesn't exist. - // moving below if (target) { const targetIndexBeforeDelete = this.runtime.targets.map(t => t.id).indexOf(target.id); From c31fff8c4cc9f63e06e3fce5f939eaeba629193e Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Thu, 9 Nov 2017 09:18:44 -0500 Subject: [PATCH 127/272] Fixing linter errors. --- src/virtual-machine.js | 2 ++ test/unit/virtual-machine.js | 16 +++++++--------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 5056e4ae0..6dfc7acad 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -509,6 +509,8 @@ class VirtualMachine extends EventEmitter { /** * Duplicate a sprite. * @param {string} targetId ID of a target whose sprite to duplicate. + * @returns {Promise} Promise that resolves when duplicated target has + * been added to the runtime. */ duplicateSprite (targetId) { const target = this.runtime.getTargetById(targetId); diff --git a/test/unit/virtual-machine.js b/test/unit/virtual-machine.js index 199640d74..f0887039e 100644 --- a/test/unit/virtual-machine.js +++ b/test/unit/virtual-machine.js @@ -1,8 +1,6 @@ const test = require('tap').test; const VirtualMachine = require('../../src/virtual-machine.js'); -const Target = require('../../src/engine/target.js'); const Sprite = require('../../src/sprites/sprite.js'); -const RenderedTarget = require('../../src/sprites/rendered-target'); test('renameSprite throws when there is no sprite with that id', t => { const vm = new VirtualMachine(); @@ -121,7 +119,7 @@ test('deleteSprite throws when used on a non-sprite target', t => { }]; t.throws( (() => vm.deleteSprite('id')), - new Error ('Cannot delete non-sprite targets.') + new Error('Cannot delete non-sprite targets.') ); t.end(); }); @@ -135,7 +133,7 @@ test('deleteSprite throws when there is no sprite for the given target', t => { }]; t.throws( (() => vm.deleteSprite('id')), - new Error ('No sprite associated with this target.') + new Error('No sprite associated with this target.') ); t.end(); }); @@ -151,7 +149,7 @@ test('deleteSprite throws when there is no target with given id', t => { }]; t.throws( (() => vm.deleteSprite('id1')), - new Error ('No target with the provided id.') + new Error('No target with the provided id.') ); t.end(); }); @@ -169,7 +167,8 @@ test('deleteSprite deletes a sprite when given id is associated with a known spr t.end(); }); -test('deleteSprite sets editing target as null when sprite being deleted is current editing target, and the only target in the runtime', t => { +// eslint-disable-next-line max-len +test('deleteSprite sets editing target as null when given sprite is current editing target, and the only target in the runtime', t => { const vm = new VirtualMachine(); const spr = new Sprite(null, vm.runtime); const currTarget = spr.createClone(); @@ -184,6 +183,7 @@ test('deleteSprite sets editing target as null when sprite being deleted is curr t.end(); }); +// eslint-disable-next-line max-len test('deleteSprite updates editingTarget when sprite being deleted is current editing target, and there is another target in the runtime', t => { const vm = new VirtualMachine(); const spr1 = new Sprite(null, vm.runtime); @@ -218,8 +218,6 @@ test('deleteSprite updates editingTarget when sprite being deleted is current ed t.end(); }); - - test('duplicateSprite throws when there is no target with given id', t => { const vm = new VirtualMachine(); vm.runtime.targets = [{ @@ -258,7 +256,7 @@ test('duplicateSprite throws when there is no sprite for the given target', t => }]; t.throws( (() => vm.duplicateSprite('id')), - new Error ('No sprite associated with this target.') + new Error('No sprite associated with this target.') ); t.end(); }); From 70959cc7f52f45ef3f3281aa748d22e463bae475 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Thu, 9 Nov 2017 17:19:34 -0500 Subject: [PATCH 128/272] First cut at turning lists into typed variables --- src/blocks/scratch3_data.js | 36 ++++++++++++++++---------------- src/engine/blocks.js | 4 ++-- src/engine/execute.js | 2 +- src/engine/list.js | 18 ---------------- src/engine/target.js | 31 ++++++++++----------------- src/engine/variable.js | 16 ++++++++++---- src/serialization/sb2.js | 12 +++++++---- src/serialization/sb2_specmap.js | 2 +- src/serialization/sb3.js | 14 ++----------- 9 files changed, 55 insertions(+), 80 deletions(-) delete mode 100644 src/engine/list.js diff --git a/src/blocks/scratch3_data.js b/src/blocks/scratch3_data.js index 551f717f7..8ec4f124e 100644 --- a/src/blocks/scratch3_data.js +++ b/src/blocks/scratch3_data.js @@ -52,8 +52,8 @@ class Scratch3DataBlocks { // If it is, report contents joined together with no separator. // If it's not, report contents joined together with a space. let allSingleLetters = true; - for (let i = 0; i < list.contents.length; i++) { - const listItem = list.contents[i]; + for (let i = 0; i < list.value.length; i++) { + const listItem = list.value[i]; if (!((typeof listItem === 'string') && (listItem.length === 1))) { allSingleLetters = false; @@ -61,73 +61,73 @@ class Scratch3DataBlocks { } } if (allSingleLetters) { - return list.contents.join(''); + return list.value.join(''); } - return list.contents.join(' '); + return list.value.join(' '); } addToList (args, util) { const list = util.target.lookupOrCreateList(args.LIST); - list.contents.push(args.ITEM); + list.value.push(args.ITEM); } deleteOfList (args, util) { const list = util.target.lookupOrCreateList(args.LIST); - const index = Cast.toListIndex(args.INDEX, list.contents.length); + const index = Cast.toListIndex(args.INDEX, list.value.length); if (index === Cast.LIST_INVALID) { return; } else if (index === Cast.LIST_ALL) { - list.contents = []; + list.value = []; return; } - list.contents.splice(index - 1, 1); + list.value.splice(index - 1, 1); } insertAtList (args, util) { const item = args.ITEM; const list = util.target.lookupOrCreateList(args.LIST); - const index = Cast.toListIndex(args.INDEX, list.contents.length + 1); + const index = Cast.toListIndex(args.INDEX, list.value.length + 1); if (index === Cast.LIST_INVALID) { return; } - list.contents.splice(index - 1, 0, item); + list.value.splice(index - 1, 0, item); } replaceItemOfList (args, util) { const item = args.ITEM; const list = util.target.lookupOrCreateList(args.LIST); - const index = Cast.toListIndex(args.INDEX, list.contents.length); + const index = Cast.toListIndex(args.INDEX, list.value.length); if (index === Cast.LIST_INVALID) { return; } - list.contents.splice(index - 1, 1, item); + list.value.splice(index - 1, 1, item); } getItemOfList (args, util) { const list = util.target.lookupOrCreateList(args.LIST); - const index = Cast.toListIndex(args.INDEX, list.contents.length); + const index = Cast.toListIndex(args.INDEX, list.value.length); if (index === Cast.LIST_INVALID) { return ''; } - return list.contents[index - 1]; + return list.value[index - 1]; } lengthOfList (args, util) { const list = util.target.lookupOrCreateList(args.LIST); - return list.contents.length; + return list.value.length; } listContainsItem (args, util) { const item = args.ITEM; const list = util.target.lookupOrCreateList(args.LIST); - if (list.contents.indexOf(item) >= 0) { + if (list.value.indexOf(item) >= 0) { return true; } // Try using Scratch comparison operator on each item. // (Scratch considers the string '123' equal to the number 123). - for (let i = 0; i < list.contents.length; i++) { - if (Cast.compare(list.contents[i], item) === 0) { + for (let i = 0; i < list.value.length; i++) { + if (Cast.compare(list.value[i], item) === 0) { return true; } } diff --git a/src/engine/blocks.js b/src/engine/blocks.js index ba9077fc7..7a9ecbb88 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -260,7 +260,7 @@ class Blocks { // If not, create it on the stage. // TODO create global and local variables when UI provides a way. if (!optRuntime.getEditingTarget().lookupVariableById(e.varId)) { - stage.createVariable(e.varId, e.varName); + stage.createVariable(e.varId, e.varName, e.varType); } break; case 'var_rename': @@ -310,7 +310,7 @@ class Blocks { case 'field': // Update block value if (!block.fields[args.name]) return; - if (args.name === 'VARIABLE') { + if (args.name === 'VARIABLE' || args.name === 'LIST') { // Get variable name using the id in args.value. const variable = optRuntime.getEditingTarget().lookupVariableById(args.value); if (variable) { diff --git a/src/engine/execute.js b/src/engine/execute.js index a4bf76b2a..8093a346d 100644 --- a/src/engine/execute.js +++ b/src/engine/execute.js @@ -138,7 +138,7 @@ const execute = function (sequencer, thread) { // Add all fields on this block to the argValues. for (const fieldName in fields) { if (!fields.hasOwnProperty(fieldName)) continue; - if (fieldName === 'VARIABLE') { + if (fieldName === 'VARIABLE' || fieldName === 'LIST') { argValues[fieldName] = fields[fieldName].id; } else { argValues[fieldName] = fields[fieldName].value; diff --git a/src/engine/list.js b/src/engine/list.js deleted file mode 100644 index 0f3ec0f2b..000000000 --- a/src/engine/list.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @fileoverview - * Object representing a Scratch list. - */ - -/** - * @param {!string} name Name of the list. - * @param {Array} contents Contents of the list, as an array. - * @constructor - */ -class List { - constructor (name, contents) { - this.name = name; - this.contents = contents; - } -} - -module.exports = List; diff --git a/src/engine/target.js b/src/engine/target.js index 2a6be81a6..764094daa 100644 --- a/src/engine/target.js +++ b/src/engine/target.js @@ -2,7 +2,6 @@ const EventEmitter = require('events'); const Blocks = require('./blocks'); const Variable = require('../engine/variable'); -const List = require('../engine/list'); const uid = require('../util/uid'); const {Map} = require('immutable'); @@ -88,7 +87,7 @@ class Target extends EventEmitter { const variable = this.lookupVariableById(id); if (variable) return variable; // No variable with this name exists - create it locally. - const newVariable = new Variable(id, name, 0, false); + const newVariable = new Variable(id, name, "", false); this.variables[id] = newVariable; return newVariable; } @@ -117,24 +116,16 @@ class Target extends EventEmitter { /** * Look up a list object for this target, and create it if one doesn't exist. * Search begins for local lists; then look for globals. + * @param {!string} id Id of the list. * @param {!string} name Name of the list. * @return {!List} List object. */ - lookupOrCreateList (name) { - // If we have a local copy, return it. - if (this.lists.hasOwnProperty(name)) { - return this.lists[name]; - } - // If the stage has a global copy, return it. - if (this.runtime && !this.isStage) { - const stage = this.runtime.getTargetForStage(); - if (stage.lists.hasOwnProperty(name)) { - return stage.lists[name]; - } - } - // No list with this name exists - create it locally. - const newList = new List(name, []); - this.lists[name] = newList; + lookupOrCreateList (id, name) { + const list = this.lookupVariableById(id); + if (list) return list; + // No variable with this name exists - create it locally. + const newList = new Variable(id, name, "list", false); + this.variables[id] = newList; return newList; } @@ -143,11 +134,11 @@ class Target extends EventEmitter { * dictionary of variables. * @param {string} id Id of variable * @param {string} name Name of variable. + * @param {string} type Type of variable, one of string, number, list */ - createVariable (id, name) { + createVariable (id, name, type) { if (!this.variables.hasOwnProperty(id)) { - const newVariable = new Variable(id, name, 0, - false); + const newVariable = new Variable(id, name, type, false); this.variables[id] = newVariable; } } diff --git a/src/engine/variable.js b/src/engine/variable.js index b79ab2975..9f047a73b 100644 --- a/src/engine/variable.js +++ b/src/engine/variable.js @@ -9,19 +9,27 @@ class Variable { /** * @param {string} id Id of the variable. * @param {string} name Name of the variable. - * @param {(string|number)} value Value of the variable. + * @param {(string|number)} type Type of the variable, one of "" or "list" * @param {boolean} isCloud Whether the variable is stored in the cloud. * @constructor */ - constructor (id, name, value, isCloud) { + constructor (id, name, type, isCloud) { this.id = id || uid(); this.name = name; - this.value = value; + this.type = type; this.isCloud = isCloud; + switch (this.type) { + case "": + this.value = 0; + break; + case "list": + this.value = []; + break; + } } toXML () { - return `${this.name}`; + return `${this.name}`; } } diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js index 2a54d40a7..e76d6ee2b 100644 --- a/src/serialization/sb2.js +++ b/src/serialization/sb2.js @@ -13,7 +13,6 @@ const log = require('../util/log'); const uid = require('../util/uid'); const specMap = require('./sb2_specmap'); const Variable = require('../engine/variable'); -const List = require('../engine/list'); const {loadCostume} = require('../import/load-costume.js'); const {loadSound} = require('../import/load-sound.js'); @@ -235,9 +234,10 @@ const parseScratchObject = function (object, runtime, extensions, topLevel) { const newVariable = new Variable( getVariableId(variable.name), variable.name, - variable.value, + "", variable.isPersistent ); + newVariable.value = variable.value; target.variables[newVariable.id] = newVariable; } } @@ -251,10 +251,14 @@ const parseScratchObject = function (object, runtime, extensions, topLevel) { for (let k = 0; k < object.lists.length; k++) { const list = object.lists[k]; // @todo: monitor properties. - target.lists[list.listName] = new List( + const newVariable = new Variable( + getVariableId(list.listName), list.listName, - list.contents + "list", + list.isPersistent ); + newVariable.value = list.contents; + target.variables[newVariable.id] = newVariable; } } if (object.hasOwnProperty('scratchX')) { diff --git a/src/serialization/sb2_specmap.js b/src/serialization/sb2_specmap.js index cf5be1c89..59200a06f 100644 --- a/src/serialization/sb2_specmap.js +++ b/src/serialization/sb2_specmap.js @@ -1252,7 +1252,7 @@ const specMap = { ] }, 'contentsOfList:': { - opcode: 'data_list', + opcode: 'data_listcontents', argMap: [ { type: 'field', diff --git a/src/serialization/sb3.js b/src/serialization/sb3.js index 426f1004a..9e8bcbf4e 100644 --- a/src/serialization/sb3.js +++ b/src/serialization/sb3.js @@ -8,7 +8,6 @@ const vmPackage = require('../../package.json'); const Blocks = require('../engine/blocks'); const Sprite = require('../sprites/sprite'); const Variable = require('../engine/variable'); -const List = require('../engine/list'); const {loadCostume} = require('../import/load-costume.js'); const {loadSound} = require('../import/load-sound.js'); @@ -125,22 +124,13 @@ const parseScratchObject = function (object, runtime, extensions) { const newVariable = new Variable( variable.id, variable.name, - variable.value, + variable.type, variable.isPersistent ); + newVariable.value = variable.value; target.variables[newVariable.id] = newVariable; } } - if (object.hasOwnProperty('lists')) { - for (let k = 0; k < object.lists.length; k++) { - const list = object.lists[k]; - // @todo: monitor properties. - target.lists[list.listName] = new List( - list.listName, - list.contents - ); - } - } if (object.hasOwnProperty('x')) { target.x = object.x; } From db3b0ca204f0410dc2c751d98d20a9eba49ace95 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Thu, 9 Nov 2017 17:41:37 -0500 Subject: [PATCH 129/272] Move musical timing into music extension and use the stackframe timer, which improves timing accuracy. --- src/blocks/scratch3_music.js | 55 ++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/src/blocks/scratch3_music.js b/src/blocks/scratch3_music.js index f70fd48ae..80232f001 100644 --- a/src/blocks/scratch3_music.js +++ b/src/blocks/scratch3_music.js @@ -3,6 +3,7 @@ const BlockType = require('../extension-support/block-type'); const Clone = require('../util/clone'); const Cast = require('../util/cast'); const MathUtil = require('../util/math-util'); +const Timer = require('../util/timer'); /** * An array of drum names, used in the play drum block. @@ -70,6 +71,13 @@ class Scratch3MusicBlocks { */ this.runtime = runtime; + /** + * The current tempo in beats per minute. The tempo is a global property of the project, + * not a property of each sprite, so it is not stored in the MusicState object. + * @type {number} + */ + this.tempo = 60; + this.drumMenu = this._buildMenu(drumNames); this.instrumentMenu = this._buildMenu(instrumentNames); } @@ -272,11 +280,10 @@ class Scratch3MusicBlocks { * @property {number} BEATS - the duration in beats of the rest. * @return {Promise} - a promise which will resolve at the end of the duration. */ - restForBeats (args) { + restForBeats (args, util) { let beats = Cast.toNumber(args.BEATS); beats = this._clampBeats(beats); - if (typeof this.runtime.audioEngine === 'undefined') return; - return this.runtime.audioEngine.waitForBeats(beats); + this._waitForBeats(beats, util); } /** @@ -315,6 +322,39 @@ class Scratch3MusicBlocks { return this.runtime.audioEngine.instrumentPlayer.loadInstrument(musicState.currentInstrument); } + /** + * Convert a number of beats to a number of seconds, using the current tempo. + * @param {number} beats - number of beats to convert to secs. + * @return {number} seconds - number of seconds `beats` will last. + * @private + */ + _beatsToSec (beats) { + return (60 / this.tempo) * beats; + } + + /** + * Wait for some number of beats. + * @param {number} beats - number of beats to wait for. + * @param {object} util - utility object provided by the runtime. + * @private + */ + _waitForBeats (beats, util) { + if (util.stackFrame.timer) { + const timeElapsed = util.stackFrame.timer.timeElapsed(); + if (timeElapsed < util.stackFrame.duration * 1000) { + util.yield(); + } + } else { + util.stackFrame.timer = new Timer(); + util.stackFrame.timer.start(); + util.stackFrame.duration = this._beatsToSec(beats); + if (util.stackFrame.duration <= 0) { + return; + } + util.yield(); + } + } + /** * Clamp a duration in beats to the allowed min and max duration. * @param {number} beats - a duration in beats. @@ -342,8 +382,7 @@ class Scratch3MusicBlocks { */ changeTempo (args) { const change = Cast.toNumber(args.TEMPO); - if (typeof this.runtime.audioEngine === 'undefined') return; - const tempo = change + this.runtime.audioEngine.currentTempo; + const tempo = change + this.tempo; this._updateTempo(tempo); } @@ -354,8 +393,7 @@ class Scratch3MusicBlocks { */ _updateTempo (tempo) { tempo = MathUtil.clamp(tempo, Scratch3MusicBlocks.TEMPO_RANGE.min, Scratch3MusicBlocks.TEMPO_RANGE.max); - if (typeof this.runtime.audioEngine === 'undefined') return; - this.runtime.audioEngine.setTempo(tempo); + this.tempo = tempo; } /** @@ -363,8 +401,7 @@ class Scratch3MusicBlocks { * @return {number} - the current tempo, in beats per minute. */ getTempo () { - if (typeof this.runtime.audioEngine === 'undefined') return; - return this.runtime.audioEngine.currentTempo; + return this.tempo; } } From be25cd93bdfaae3b80e6151d7d59a1fdab460cf4 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Mon, 13 Nov 2017 10:43:09 -0500 Subject: [PATCH 130/272] Use stack timer for timing of drum, note and rest blocks. --- src/blocks/scratch3_music.js | 158 +++++++++++++++++++++-------------- 1 file changed, 93 insertions(+), 65 deletions(-) diff --git a/src/blocks/scratch3_music.js b/src/blocks/scratch3_music.js index 80232f001..5cccaf278 100644 --- a/src/blocks/scratch3_music.js +++ b/src/blocks/scratch3_music.js @@ -260,17 +260,22 @@ class Scratch3MusicBlocks { * @param {object} util - utility object provided by the runtime. * @property {int} DRUM - the number of the drum to play. * @property {number} BEATS - the duration in beats of the drum sound. - * @return {Promise} - a promise which will resolve at the end of the duration. */ playDrumForBeats (args, util) { - let drum = Cast.toNumber(args.DRUM); - drum -= 1; // drums are one-indexed - if (typeof this.runtime.audioEngine === 'undefined') return; - drum = MathUtil.wrapClamp(drum, 0, this.runtime.audioEngine.numDrums - 1); - let beats = Cast.toNumber(args.BEATS); - beats = this._clampBeats(beats); - if (util.target.audioPlayer === null) return; - return util.target.audioPlayer.playDrumForBeats(drum, beats); + if (this._stackTimerNeedsInit(util)) { + let drum = Cast.toNumber(args.DRUM); + drum -= 1; // drums are one-indexed + if (typeof this.runtime.audioEngine === 'undefined') return; + drum = MathUtil.wrapClamp(drum, 0, this.runtime.audioEngine.numDrums - 1); + let beats = Cast.toNumber(args.BEATS); + beats = this._clampBeats(beats); + if (util.target.audioPlayer !== null) { + util.target.audioPlayer.playDrumForBeats(drum, beats); + } + this._startStackTimer(util, this._beatsToSec(beats)); + } else { + this._checkStackTimer(util); + } } /** @@ -278,12 +283,15 @@ class Scratch3MusicBlocks { * @param {object} args - the block arguments. * @param {object} util - utility object provided by the runtime. * @property {number} BEATS - the duration in beats of the rest. - * @return {Promise} - a promise which will resolve at the end of the duration. */ restForBeats (args, util) { - let beats = Cast.toNumber(args.BEATS); - beats = this._clampBeats(beats); - this._waitForBeats(beats, util); + if (this._stackTimerNeedsInit(util)) { + let beats = Cast.toNumber(args.BEATS); + beats = this._clampBeats(beats); + this._startStackTimer(util, this._beatsToSec(beats)); + } else { + this._checkStackTimer(util); + } } /** @@ -292,17 +300,80 @@ class Scratch3MusicBlocks { * @param {object} util - utility object provided by the runtime. * @property {number} NOTE - the pitch of the note to play, interpreted as a MIDI note number. * @property {number} BEATS - the duration in beats of the note. - * @return {Promise} - a promise which will resolve at the end of the duration. */ playNoteForBeats (args, util) { - let note = Cast.toNumber(args.NOTE); - note = MathUtil.clamp(note, Scratch3MusicBlocks.MIDI_NOTE_RANGE.min, Scratch3MusicBlocks.MIDI_NOTE_RANGE.max); - let beats = Cast.toNumber(args.BEATS); - beats = this._clampBeats(beats); - const musicState = this._getMusicState(util.target); - const inst = musicState.currentInstrument; - if (typeof this.runtime.audioEngine === 'undefined') return; - return this.runtime.audioEngine.playNoteForBeatsWithInstAndVol(note, beats, inst, 100); + if (this._stackTimerNeedsInit(util)) { + let note = Cast.toNumber(args.NOTE); + note = MathUtil.clamp(note, + Scratch3MusicBlocks.MIDI_NOTE_RANGE.min, Scratch3MusicBlocks.MIDI_NOTE_RANGE.max); + let beats = Cast.toNumber(args.BEATS); + beats = this._clampBeats(beats); + const musicState = this._getMusicState(util.target); + const inst = musicState.currentInstrument; + if (typeof this.runtime.audioEngine !== 'undefined') { + this.runtime.audioEngine.playNoteForBeatsWithInstAndVol(note, beats, inst, 100); + } + this._startStackTimer(util, this._beatsToSec(beats)); + } else { + this._checkStackTimer(util); + } + } + + /** + * Clamp a duration in beats to the allowed min and max duration. + * @param {number} beats - a duration in beats. + * @return {number} - the clamped duration. + * @private + */ + _clampBeats (beats) { + return MathUtil.clamp(beats, Scratch3MusicBlocks.BEAT_RANGE.min, Scratch3MusicBlocks.BEAT_RANGE.max); + } + + /** + * Convert a number of beats to a number of seconds, using the current tempo. + * @param {number} beats - number of beats to convert to secs. + * @return {number} seconds - number of seconds `beats` will last. + * @private + */ + _beatsToSec (beats) { + return (60 / this.tempo) * beats; + } + + /** + * Check if the stack timer needs initialization. + * @param {object} util - utility object provided by the runtime. + * @return {boolean} - true if the stack timer needs to be initialized. + * @private + */ + _stackTimerNeedsInit (util) { + return !util.stackFrame.timer; + } + + /** + * Start the stack timer and the yield the thread if necessary. + * @param {object} util - utility object provided by the runtime. + * @param {number} duration - a duration in seconds to set the timer for. + * @private + */ + _startStackTimer (util, duration) { + util.stackFrame.timer = new Timer(); + util.stackFrame.timer.start(); + util.stackFrame.duration = duration; + if (util.stackFrame.duration > 0) { + util.yield(); + } + } + + /** + * Check the stack timer, and if its time is not up yet, yield the thread. + * @param {object} util - utility object provided by the runtime. + * @private + */ + _checkStackTimer (util) { + const timeElapsed = util.stackFrame.timer.timeElapsed(); + if (timeElapsed < util.stackFrame.duration * 1000) { + util.yield(); + } } /** @@ -322,49 +393,6 @@ class Scratch3MusicBlocks { return this.runtime.audioEngine.instrumentPlayer.loadInstrument(musicState.currentInstrument); } - /** - * Convert a number of beats to a number of seconds, using the current tempo. - * @param {number} beats - number of beats to convert to secs. - * @return {number} seconds - number of seconds `beats` will last. - * @private - */ - _beatsToSec (beats) { - return (60 / this.tempo) * beats; - } - - /** - * Wait for some number of beats. - * @param {number} beats - number of beats to wait for. - * @param {object} util - utility object provided by the runtime. - * @private - */ - _waitForBeats (beats, util) { - if (util.stackFrame.timer) { - const timeElapsed = util.stackFrame.timer.timeElapsed(); - if (timeElapsed < util.stackFrame.duration * 1000) { - util.yield(); - } - } else { - util.stackFrame.timer = new Timer(); - util.stackFrame.timer.start(); - util.stackFrame.duration = this._beatsToSec(beats); - if (util.stackFrame.duration <= 0) { - return; - } - util.yield(); - } - } - - /** - * Clamp a duration in beats to the allowed min and max duration. - * @param {number} beats - a duration in beats. - * @return {number} - the clamped duration. - * @private - */ - _clampBeats (beats) { - return MathUtil.clamp(beats, Scratch3MusicBlocks.BEAT_RANGE.min, Scratch3MusicBlocks.BEAT_RANGE.max); - } - /** * Set the current tempo to a new value. * @param {object} args - the block arguments. From 37d627bc8955c9fa7d9323e042fceeb3fb81a874 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Mon, 13 Nov 2017 10:57:36 -0500 Subject: [PATCH 131/272] Fix unit test --- test/unit/blocks_music.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/unit/blocks_music.js b/test/unit/blocks_music.js index 3b8f8d949..ae097beb1 100644 --- a/test/unit/blocks_music.js +++ b/test/unit/blocks_music.js @@ -17,7 +17,8 @@ const util = { audioPlayer: { playDrumForBeats: drum => (playedDrum = drum) } - } + }, + stackFrame: Object.create(null) }; test('playDrum uses 1-indexing and wrap clamps', t => { From b18938963fab4b6ec4c74c861b14b35d0a97da2a Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Mon, 13 Nov 2017 14:22:36 -0500 Subject: [PATCH 132/272] Fixing linting errors --- src/engine/target.js | 4 ++-- src/engine/variable.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/engine/target.js b/src/engine/target.js index 764094daa..ebe7d495f 100644 --- a/src/engine/target.js +++ b/src/engine/target.js @@ -87,7 +87,7 @@ class Target extends EventEmitter { const variable = this.lookupVariableById(id); if (variable) return variable; // No variable with this name exists - create it locally. - const newVariable = new Variable(id, name, "", false); + const newVariable = new Variable(id, name, '', false); this.variables[id] = newVariable; return newVariable; } @@ -124,7 +124,7 @@ class Target extends EventEmitter { const list = this.lookupVariableById(id); if (list) return list; // No variable with this name exists - create it locally. - const newList = new Variable(id, name, "list", false); + const newList = new Variable(id, name, 'list', false); this.variables[id] = newList; return newList; } diff --git a/src/engine/variable.js b/src/engine/variable.js index 9f047a73b..55617894c 100644 --- a/src/engine/variable.js +++ b/src/engine/variable.js @@ -19,10 +19,10 @@ class Variable { this.type = type; this.isCloud = isCloud; switch (this.type) { - case "": + case '': this.value = 0; break; - case "list": + case 'list': this.value = []; break; } From 038a65b460cfa7772b05867c907c24062060fda3 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Mon, 13 Nov 2017 14:24:30 -0500 Subject: [PATCH 133/272] Finishing up lists. --- src/engine/adapter.js | 4 +++ src/engine/blocks.js | 11 +++++++- src/serialization/sb2.js | 10 ++++--- src/serialization/sb2_specmap.js | 45 +++++++++++++++++++++----------- 4 files changed, 51 insertions(+), 19 deletions(-) diff --git a/src/engine/adapter.js b/src/engine/adapter.js index ffb8d043e..a8534e249 100644 --- a/src/engine/adapter.js +++ b/src/engine/adapter.js @@ -75,6 +75,10 @@ const domToBlock = function (blockDOM, blocks, isTopBlock, parent) { id: fieldId, value: fieldData }; + const fieldVarType = xmlChild.attribs.variabletype; + if (typeof fieldVarType === 'string') { + block.fields[fieldName].variableType = fieldVarType; + } break; } case 'value': diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 7a9ecbb88..bace2f1b5 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -499,11 +499,20 @@ class Blocks { for (const field in block.fields) { if (!block.fields.hasOwnProperty(field)) continue; const blockField = block.fields[field]; + xmlString += `${value}`; + xmlString += `>${value}`; } // Add blocks connected to the next connection. if (block.next) { diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js index e76d6ee2b..0c6c37813 100644 --- a/src/serialization/sb2.js +++ b/src/serialization/sb2.js @@ -234,7 +234,7 @@ const parseScratchObject = function (object, runtime, extensions, topLevel) { const newVariable = new Variable( getVariableId(variable.name), variable.name, - "", + '', variable.isPersistent ); newVariable.value = variable.value; @@ -254,7 +254,7 @@ const parseScratchObject = function (object, runtime, extensions, topLevel) { const newVariable = new Variable( getVariableId(list.listName), list.listName, - "list", + 'list', list.isPersistent ); newVariable.value = list.contents; @@ -490,10 +490,14 @@ const parseBlock = function (sb2block, getVariableId, extensions) { value: providedArg }; - if (expectedArg.fieldName === 'VARIABLE') { + if (expectedArg.fieldName === 'VARIABLE' || expectedArg.fieldName === 'LIST') { // Add `id` property to variable fields activeBlock.fields[expectedArg.fieldName].id = getVariableId(providedArg); } + const varType = expectedArg.variableType; + if (typeof varType === 'string') { + activeBlock.fields[expectedArg.fieldName].variableType = varType; + } } } // Special cases to generate mutations. diff --git a/src/serialization/sb2_specmap.js b/src/serialization/sb2_specmap.js index 59200a06f..c7de538e9 100644 --- a/src/serialization/sb2_specmap.js +++ b/src/serialization/sb2_specmap.js @@ -1201,7 +1201,8 @@ const specMap = { argMap: [ { type: 'field', - fieldName: 'VARIABLE' + fieldName: 'VARIABLE', + variableType: '' } ] }, @@ -1210,7 +1211,8 @@ const specMap = { argMap: [ { type: 'field', - fieldName: 'VARIABLE' + fieldName: 'VARIABLE', + variableType: '' }, { type: 'input', @@ -1224,7 +1226,8 @@ const specMap = { argMap: [ { type: 'field', - fieldName: 'VARIABLE' + fieldName: 'VARIABLE', + variableType: '' }, { type: 'input', @@ -1238,7 +1241,8 @@ const specMap = { argMap: [ { type: 'field', - fieldName: 'VARIABLE' + fieldName: 'VARIABLE', + variableType: '' } ] }, @@ -1247,7 +1251,8 @@ const specMap = { argMap: [ { type: 'field', - fieldName: 'VARIABLE' + fieldName: 'VARIABLE', + variableType: '' } ] }, @@ -1256,7 +1261,8 @@ const specMap = { argMap: [ { type: 'field', - fieldName: 'LIST' + fieldName: 'LIST', + variableType: 'list' } ] }, @@ -1270,7 +1276,8 @@ const specMap = { }, { type: 'field', - fieldName: 'LIST' + fieldName: 'LIST', + variableType: 'list' } ] }, @@ -1284,7 +1291,8 @@ const specMap = { }, { type: 'field', - fieldName: 'LIST' + fieldName: 'LIST', + variableType: 'list' } ] }, @@ -1303,7 +1311,8 @@ const specMap = { }, { type: 'field', - fieldName: 'LIST' + fieldName: 'LIST', + variableType: 'list' } ] }, @@ -1317,7 +1326,8 @@ const specMap = { }, { type: 'field', - fieldName: 'LIST' + fieldName: 'LIST', + variableType: 'list' }, { type: 'input', @@ -1336,7 +1346,8 @@ const specMap = { }, { type: 'field', - fieldName: 'LIST' + fieldName: 'LIST', + variableType: 'list' } ] }, @@ -1345,7 +1356,8 @@ const specMap = { argMap: [ { type: 'field', - fieldName: 'LIST' + fieldName: 'LIST', + variableType: 'list' } ] }, @@ -1354,7 +1366,8 @@ const specMap = { argMap: [ { type: 'field', - fieldName: 'LIST' + fieldName: 'LIST', + variableType: 'list' }, { type: 'input', @@ -1368,7 +1381,8 @@ const specMap = { argMap: [ { type: 'field', - fieldName: 'LIST' + fieldName: 'LIST', + variableType: 'list' } ] }, @@ -1377,7 +1391,8 @@ const specMap = { argMap: [ { type: 'field', - fieldName: 'LIST' + fieldName: 'LIST', + variableType: 'list' } ] }, From 1d4acde7dcc1114117ad717714c31952b935c7ef Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Mon, 13 Nov 2017 14:25:12 -0500 Subject: [PATCH 134/272] Fixing unit/integration tests. --- test/integration/hat-execution-order.js | 3 ++- test/unit/engine_target.js | 31 ++++++++++++++++++++----- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/test/integration/hat-execution-order.js b/test/integration/hat-execution-order.js index c8d2dcabf..3e5e92a2c 100644 --- a/test/integration/hat-execution-order.js +++ b/test/integration/hat-execution-order.js @@ -16,7 +16,8 @@ test('complex', t => { const threads = JSON.parse(e.threads); t.ok(threads.length === 0); - const results = vm.runtime.targets[0].lists.results.contents; + const resultKey = Object.keys(vm.runtime.targets[0].variables)[0]; + const results = vm.runtime.targets[0].variables[resultKey].value; t.deepEqual(results, ['3', '2', '1', 'stage']); t.end(); diff --git a/test/unit/engine_target.js b/test/unit/engine_target.js index cec5cf16d..db5b5e762 100644 --- a/test/unit/engine_target.js +++ b/test/unit/engine_target.js @@ -23,13 +23,14 @@ test('spec', t => { // Create Variable tests. test('createVariable', t => { const target = new Target(); - target.createVariable('foo', 'bar'); + target.createVariable('foo', 'bar', ''); const variables = target.variables; t.equal(Object.keys(variables).length, 1); const variable = variables[Object.keys(variables)[0]]; t.equal(variable.id, 'foo'); t.equal(variable.name, 'bar'); + t.equal(variable.type, ''); t.equal(variable.value, 0); t.equal(variable.isCloud, false); @@ -39,8 +40,8 @@ test('createVariable', t => { // Create Same Variable twice. test('createVariable2', t => { const target = new Target(); - target.createVariable('foo', 'bar'); - target.createVariable('foo', 'bar'); + target.createVariable('foo', 'bar', ''); + target.createVariable('foo', 'bar', ''); const variables = target.variables; t.equal(Object.keys(variables).length, 1); @@ -48,10 +49,28 @@ test('createVariable2', t => { t.end(); }); +// Create a list +test('createVariable creates a list', t => { + const target = new Target(); + target.createVariable('foo', 'bar', 'list'); + + const variables = target.variables; + t.equal(Object.keys(variables).length, 1); + const variable = variables[Object.keys(variables)[0]]; + t.equal(variable.id, 'foo'); + t.equal(variable.name, 'bar'); + t.equal(variable.type, 'list'); + t.assert(variable.value instanceof Array, true); + t.equal(variable.value.length, 0); + t.equal(variable.isCloud, false); + + t.end(); +}); + // Rename Variable tests. test('renameVariable', t => { const target = new Target(); - target.createVariable('foo', 'bar'); + target.createVariable('foo', 'bar', ''); target.renameVariable('foo', 'bar2'); const variables = target.variables; @@ -80,7 +99,7 @@ test('renameVariable2', t => { // Expect no change. test('renameVariable3', t => { const target = new Target(); - target.createVariable('foo1', 'foo'); + target.createVariable('foo1', 'foo', ''); target.renameVariable('foo', 'bar2'); const variables = target.variables; @@ -95,7 +114,7 @@ test('renameVariable3', t => { // Delete Variable tests. test('deleteVariable', t => { const target = new Target(); - target.createVariable('foo', 'bar'); + target.createVariable('foo', 'bar', ''); target.deleteVariable('foo'); const variables = target.variables; From 961b3476b20852c58d8c1f131cc1081a73ef4347 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Mon, 13 Nov 2017 16:22:37 -0500 Subject: [PATCH 135/272] Move the music extension into a new extensions directory --- src/extension-support/extension-manager.js | 2 +- .../scratch3_music/index.js} | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) rename src/{blocks/scratch3_music.js => extensions/scratch3_music/index.js} (97%) diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index 938e791dc..c3346a22d 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -8,7 +8,7 @@ const BlockType = require('./block-type'); // TODO: change extension spec so that library info, including extension ID, can be collected through static methods const Scratch3PenBlocks = require('../blocks/scratch3_pen'); const Scratch3WeDo2Blocks = require('../blocks/scratch3_wedo2'); -const Scratch3MusicBlocks = require('../blocks/scratch3_music'); +const Scratch3MusicBlocks = require('../extensions/scratch3_music'); const builtinExtensions = { pen: Scratch3PenBlocks, wedo2: Scratch3WeDo2Blocks, diff --git a/src/blocks/scratch3_music.js b/src/extensions/scratch3_music/index.js similarity index 97% rename from src/blocks/scratch3_music.js rename to src/extensions/scratch3_music/index.js index 5cccaf278..ba1360034 100644 --- a/src/blocks/scratch3_music.js +++ b/src/extensions/scratch3_music/index.js @@ -1,9 +1,9 @@ -const ArgumentType = require('../extension-support/argument-type'); -const BlockType = require('../extension-support/block-type'); -const Clone = require('../util/clone'); -const Cast = require('../util/cast'); -const MathUtil = require('../util/math-util'); -const Timer = require('../util/timer'); +const ArgumentType = require('../../extension-support/argument-type'); +const BlockType = require('../../extension-support/block-type'); +const Clone = require('../../util/clone'); +const Cast = require('../../util/cast'); +const MathUtil = require('../../util/math-util'); +const Timer = require('../../util/timer'); /** * An array of drum names, used in the play drum block. From f5b25a190e3c41185941fbc36251dea7fbe5d84f Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Mon, 13 Nov 2017 16:22:58 -0500 Subject: [PATCH 136/272] Add assets (drum sounds) for music extension --- .../scratch3_music/assets/1-snare.mp3 | Bin 0 -> 5557 bytes .../scratch3_music/assets/10-wood-block.mp3 | Bin 0 -> 3676 bytes .../scratch3_music/assets/11-cowbell.mp3 | Bin 0 -> 2688 bytes .../scratch3_music/assets/12-triangle.mp3 | Bin 0 -> 10455 bytes .../scratch3_music/assets/13-bongo.mp3 | Bin 0 -> 5269 bytes .../scratch3_music/assets/14-conga.mp3 | Bin 0 -> 3808 bytes .../scratch3_music/assets/15-cabasa.mp3 | Bin 0 -> 2041 bytes .../scratch3_music/assets/16-guiro.mp3 | Bin 0 -> 4905 bytes .../scratch3_music/assets/17-vibraslap.mp3 | Bin 0 -> 17089 bytes .../scratch3_music/assets/18-cuica.mp3 | Bin 0 -> 3257 bytes .../scratch3_music/assets/2-bass-drum.mp3 | Bin 0 -> 4513 bytes .../scratch3_music/assets/3-side-stick.mp3 | Bin 0 -> 3408 bytes .../scratch3_music/assets/4-crash-cymbal.mp3 | Bin 0 -> 17392 bytes .../scratch3_music/assets/5-open-hi-hat.mp3 | Bin 0 -> 6414 bytes .../scratch3_music/assets/6-closed-hi-hat.mp3 | Bin 0 -> 3338 bytes .../scratch3_music/assets/7-tambourine.mp3 | Bin 0 -> 4434 bytes .../scratch3_music/assets/8-hand-clap.mp3 | Bin 0 -> 2582 bytes .../scratch3_music/assets/9-claves.mp3 | Bin 0 -> 2973 bytes webpack.config.js | 8 +++++++- 19 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 src/extensions/scratch3_music/assets/1-snare.mp3 create mode 100644 src/extensions/scratch3_music/assets/10-wood-block.mp3 create mode 100644 src/extensions/scratch3_music/assets/11-cowbell.mp3 create mode 100644 src/extensions/scratch3_music/assets/12-triangle.mp3 create mode 100644 src/extensions/scratch3_music/assets/13-bongo.mp3 create mode 100644 src/extensions/scratch3_music/assets/14-conga.mp3 create mode 100644 src/extensions/scratch3_music/assets/15-cabasa.mp3 create mode 100644 src/extensions/scratch3_music/assets/16-guiro.mp3 create mode 100644 src/extensions/scratch3_music/assets/17-vibraslap.mp3 create mode 100644 src/extensions/scratch3_music/assets/18-cuica.mp3 create mode 100644 src/extensions/scratch3_music/assets/2-bass-drum.mp3 create mode 100644 src/extensions/scratch3_music/assets/3-side-stick.mp3 create mode 100644 src/extensions/scratch3_music/assets/4-crash-cymbal.mp3 create mode 100644 src/extensions/scratch3_music/assets/5-open-hi-hat.mp3 create mode 100644 src/extensions/scratch3_music/assets/6-closed-hi-hat.mp3 create mode 100644 src/extensions/scratch3_music/assets/7-tambourine.mp3 create mode 100644 src/extensions/scratch3_music/assets/8-hand-clap.mp3 create mode 100644 src/extensions/scratch3_music/assets/9-claves.mp3 diff --git a/src/extensions/scratch3_music/assets/1-snare.mp3 b/src/extensions/scratch3_music/assets/1-snare.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..38970d352e35a6524e09e0832bb265772eba3542 GIT binary patch literal 5557 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 literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/10-wood-block.mp3 b/src/extensions/scratch3_music/assets/10-wood-block.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..9c551b3661873ca96cc76af6df131f648c0e8e4b GIT binary patch literal 3676 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 kJN}<d0LlPxBn|)s@&7yj28DZ=+W-In literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/12-triangle.mp3 b/src/extensions/scratch3_music/assets/12-triangle.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..0987759cae7299681033cb17d65b48169c5029eb GIT binary patch literal 10455 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

i9^;kLV^qMP4j8A{*eqoPiaywSLtaWt2b zi+!5L8Fy2DQ)5N{kg~#cFEr!aW}zG}J1>Bna-t@%T29iBl1g^*0vX@^WwPvS(Wn7K zv_Q&8&q?EG&}_<3TSCR~qHeX{%{D&ebY27`I^0{NQq)R!1Y|hA6Y&(Rl-#U3ZNYhc z7ZNN*kJg%;g&4oRl2O`|(HuzgEn4+KXf!LN5OdyJ1Ia0y;-31r8ku`Wd_$<@V(t1< z)>rnTq**qN>UQ$CIBO#E_s-&rYV9Z7;|FEqCQ4haJ@JXEb>%%&*OQG)*dA!IdIC^U zJ~UvRbJe5Qn^0rkT%lPr|3z zZ+K1yzgW|`K4RY-MrhIWRT$m2z5!OHmHXbJg|EEQ#?$V?>HL@BUkrhBnL+M4csExO z-zEC9CyhG`u!Tlh6DpbN)L=ihpYcYV;R{J*&&ulVYE!P)aVgQ=aa~sDcRTZ)Ln~DU z;dHtGy|qyBK!m}saTH`nLNg zv!k#qP*1;9mN8qLK}Z22#H4Jf&{-xU9U=9BM4b1TJ=iwyXx)MAS31x_!vU&#!By8h zPszLfASGPNF3;_i0#*~3AGUKZ(=A8e-gJ?p*OR>H1D#ZLtLuD!Xqq}eNnm)D`b zbMD3E{)B_WU>xIjg}AnD{k`bbcRyxZh|cMfSt|OrihxPm{M6f0y2>%*@tat&8E|oW zwZF9dN#mFSRRgGJy)+8=uSAHmXb6+la zMI$3?7p$4n+hlD&C>B}QFx&A_>iP492YEbZHZA6cODv?}djrwKX<_57m8GK}8j_e= zzFve4U4bCx=ltjLaUa8$G_D0?H10V;<(Nkwr@wx!mP=j=DxS;txqY{~K4_G3@zONU6EzRF zB1A*kJObW7-_#V0>#&+LNfBWZ#Aee_d$(Z^ykW18ptg;E&PckH!XvC_x6KS=A4n+xDmIm9})r5IZ9gZ z$Oq44XuLSRvqa6^eJ_3b$A6yK@uO&4!>n!e;3eaY`y_U2A!^V$8^S!*| z&(N3#s+{lDEbEz;C5ZK}?DW3Wz6y#91Xo}|@OePZV$UCm|ouBT0JzK59 zZ_(kC^soV}%3S7TiJ&_E$H(arlZ;#pd9=YFi)h!A(UqyCm-M(mts)Z|beAD(@eaEi z$Y3f{gbJ$Do03m{?E#7wPqUHr8%@thHFnRiQWLGpe}RkfyoG)es42DW9AlL*(RZ*( zHZa>=Izv|sXd2e9%V9L(CVVCr_k)~Yf|)wBELp`xK_V~^`y(xv+j8&REH<i zOl@wIg_|UQ$&r%$h(ZiWNx0UblzZD3n4qt!Uk@W;oDOqiK(* zG?u9^a|^;x&)RShP^Dw7+=xb4DHt0S>3eY>Ia$-s$HyAl(^yUy0%zm0IvZw$GdM{P z3&0vvZc642T%;k?Y85caJCdwvyBwV0ui_ISqHoui)|Ap@EoCQlz=iH$F?nmgRy8Aj z9}l(bo_Tj@?$vS=9~f&a%dIC$p)uJrh}dBp8{K6>4O45bv&#=y?j@aB&R)44sDg^ zIdoG8XYpOEo?B%ipHj=8R8AMAN?p@$XEv^RHt8z!40}2FY^ezC}jtNw-es2Hc*Pp*ta!bB%o3Ep!TPZgC zg@mo09-=^#gY9-|G2JbAqT^feb&YPK06b2by?)Ve?!$jycnT+VXp*`Bs*2-Vya)g& Mp^xjp>i*CD2b*N8kpKVy literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/15-cabasa.mp3 b/src/extensions/scratch3_music/assets/15-cabasa.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..4fce061764374f78508d50cbc6e8e34c33a864b2 GIT binary patch literal 2041 zcmai#do&Y%AIEpiUBlE!$uE-$V_Thc`8~zvvbk)Fni(Ru`H4~}PvlZENV0B_>hCPFt;youJ$eBH#_W+a=C&LZ0$wbB0Km!WLU-r@fMdV*aJP5P|GV*jqC^b)bsz8=@E8CvpFO+5t4udLw+I6$NyLpp zr89Y<#TprJAj}`+#(6nOM5UqdOX$^(4VMotZWKt8f@2` zc#LRf`DEvRcSj+(+u}h=KvyO#c`KXQI#QY4)$5vQ3Jw^4T@6yj`q~zzg2{bQz&;Gx zJQn1l(bGyEOt3`ElFu@IDDj@bhU4}mzl}q4&lcAt9$6U&dBw@=&*VqqUk;2E+XSe4 z7LB683H))U-a#w(o;7QHd5q!b*-rli&Bg>RVmmbN?LfA>2)x2b)#+ADd7b*kGw@9E)%LU z81!7Zfkprs+5!Zpl@AoV6RePIhob?L1-Nupcf`XWL6(VV+N*vZGsHlDsH5fQHiu_V z`o*bZ=drZm*{aGQ!esd=mgv&xP*!@SpK@~%l%#8lntTXs5FuZK8{n5*KV8@!k%{uX zKji^5Ago8d6~p=UCx8Xe_-Ay?1hHbQ1x0zN+$j`ry8b8<&gn0!0|>Z(&FMDm_5@L5 zptFW1)oO%eZaAt9T<`Z8I$dDsOX#)_xs@oFwzhp;D{!m62~_hqwrh+2=UbgKFu0;F zgcF71SfA@?rwZnYvPyDZLi8O+Qv2659eK-BoNY(g?V%pBaGS3+^ydVVRuEf*PaWE4 z_;DY;zvA(j2ttEIT0m#5aSTknC1s-Uf`ev^Qkk&9yQl=AcSkE!vl-Tsql3h{Eq~`! zNNhqOc}#l1k(v`Je4Epudx6!TOERq)LiOI0=cY7pV60*3j^`roug3=1UZdu~{<-VD z!u!#ZI6JT;=(FF0qHv%TnCooaBec;`v(^#6pWBbF zybTGt{MJ=~CSD0#(@%G?@@!=!q6A;~5^3#xS(^x@ zbTD%A?ZzieZta`A&WcbZJ*_2FU{SB+m!l$7KiZLXgn5nd!X#9)?q{^8r*>1ljYGK{ z`V(n5oA?`pNVr&~co%4?NKRFt7$NfoZbXNcaO=01eAre$48t>Tym$okvm%}Qf#_`M z!&$@35;I!kz4!k{DxX5=n0xwad5?WEJ`RGG-)8wGU&nPN?$w2lY=LFMJdzgSE$8L% zxjXFObDRo(kN?e8ucZ*ZQch*9qx|CdX*pH?NxD`Wm4)Y?(llrdFvThNE8kUk!?C`eDnmC_6j5xr~TJcf(--DuRe2pNso2MKbsfIUnli#`#zt=PP1&MYVi zR697ah0S~a$_clus2ajejjp!)!yU8HTvxue?STOTAH7<*-s;BsR1uRf3VD|FFv`#y z;!5mQEIU-`++{rziS@-j;<{fxY{kRx>&CtQ(33;ZSEDi8c0H*2Dd z6<@Qu=5YT-iA20x2v;}_I-=bO0DQiq9!pgI?j7@h+(V2L@>#)13r}*NCS~St*E7a& Uxzhg#6Dmo4%lenUNzeb~PawRp;s5{u literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/16-guiro.mp3 b/src/extensions/scratch3_music/assets/16-guiro.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..882feaaafc039b527572a7d627076e5357dea5d8 GIT binary patch literal 4905 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 af?xlIrr$&EUmvM^g684+-HR9H$o~V00<`M@ literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/17-vibraslap.mp3 b/src/extensions/scratch3_music/assets/17-vibraslap.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..faf7315ae3db40ed431b40120a9feaff4ff3b6bd GIT binary patch literal 17089 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�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 H{tx*df?EMk literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/3-side-stick.mp3 b/src/extensions/scratch3_music/assets/3-side-stick.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..c7757c932b951d636278aac249344ac5d4b609d8 GIT binary patch literal 3408 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 literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/5-open-hi-hat.mp3 b/src/extensions/scratch3_music/assets/5-open-hi-hat.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..2dc63fa30366ffeac6a86ef54c6cc95325258444 GIT binary patch literal 6414 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 X74ieXNkx+n0{~iOCAggB|CWCP{dmH7 literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/7-tambourine.mp3 b/src/extensions/scratch3_music/assets/7-tambourine.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..f0ea66a585ec62f281219a156336a9fb193fd8e0 GIT binary patch literal 4434 zcmd^@S5Om7*T;jPhF+Db0!j%@dIwRk0Mcs+HS`Xl^UwrAR1ic6y$2zLBE5vrLAnA7 zy(ql~5D@}GUYu_pFTU&d?)}Z|?9ADVJv-<8ch4T;Szp{L8>!7XCu`3-K?Pd+9!ZsP$MvL{1h)*7UDSlAQOh;vND>zWwn- zk~rG`@52AeOgxLY3=oMTNi-G!xQFQ$IupwSULO8WZ~#P5wp@DfkvkRtL+c0t;2N|@ zg~EE2T-Y*pDgiM1R+P~z-&h>4&Koj?*Wh%xPTHm`!+BkSVl20lhci)QQS%=}cJEHt zt{ES4yUN@~thqjuQ6jK}pd&{6wOhPKDtUL>R?FXt)pi%EAeYru`u+yKm%sos+^jG1 zvIF)xs%P=`^Im*Z;41bO9Q#Vo=sRtw5DaDxTOm^+eG%JFa!uK#y^Lp1vsqR;a!$j* z*yx{KE-@|a`N>g+<#(8+y=o@wqsN)-Nf?GEbk%3SR-{?Xn%`;~WImx%2UZ^*hOIcK z{hm^8`L2pD2pg7F-27x@#+E)iAbWMKe>Ef4KjYEy*5cm`TIc@`TI)eAw)%KU29&anL}SI@IERWzI~Pr$3=4aq zIKE-SHrk%8o&tY?>0LKLY*n;V49Ci_3@p;q2M8L?PCmK_0mtcO_2s<0X<$TsgT!eC zs8WoSA7HKQ;nJ6_)h;KPH#-yNq{4m|rxAJGbuM=2nh_D>JUmr$uf<24fmfKs5g0QK z-NW8&a$kLU-6XYxy0vXXwH9SJ#<&W@+3NN3dNp=Y?3AOwQT34$*hVw@EmpJ1Qt$lz z)55Ju=GP|i{T#dwLm%Qr`rBjgV!d-4$={cj&D1sOcDZ~vP}I>}r2)rlTKgR^z|mTL zbt8;#Ze(1)My0%_icsV_4_bxE86t~m`qos*-8Q!j$l#5o9>_)TpZwJWe??T4nK!}?j`p~s<6Z_Qa;}i5qRUn;r zDhXLf$)ay>%u-VEXm6OkMe@LH-eR-1b=FSe`pg`Lh@Tw@&*RjMbgF2;85*2B7r_v4 z{#jv*it^{yrq}Mm*zN^MtY=j}_~&;xoN!2I6gVt!bx=y`cf%~st21D076FHSX^?f$uqa+~6q=MDjc=kP zm2xo>$x7bR-TqNeQ1|FjLN{k(AjBp#40jKZ7eo{3nFjFJyb!qOV8v`cd1bku`PKT) zm?KS7Z|ej)U;FpPMT?@w8&fm2!fkgCZDpLyz+KBFYD?3}M#%kQUx)*hyUDW;2zX-T zd6LG6uUO&QB=kv7fDvrUbTZ3l*J@SwYT z0R2G3oSGEJU#NviB^q zooZuKD`Bp%YplN$A z>jhOWUbqfAhdV}^)tD})JR3o6A?SrsRD;5O!-KHtm?BMh;3Rwy zSu!(lpJyCmIIIj3_RpU&9r_4|!41???Zwm6-Ii16ENN%0W2{vCl7X1At9)rbmAAiu zVt;B64K=V?jG3i8b~jG3dATSfRlYm}k*SXB&QG^9g9orR+QLf%GEps3@bLL%|L)@- z7vOVA3C6dBAXqP}cfKhoj<^M{Ab2z!x1F5h-vkfM4R3{0{*e%A1XylVeSI|tORax$ z5c49+t^hFq^`~xzFu(3~&?5Y+4f6AZOw6ZOP#eQayL0{V_XjaS=DH0Kl|vGiVCz=w zqwF>}Ndn=#HeBR<%AH2jH^l6uo#CMX%iOn|2s>?8Ldh?tlC$+TPH;gf{?H>BNOEK7 zG@cucG3Ki2utsf{ax8a1z=)f*iOqCOhEPrn@y+K88tSH8zlGxkgELPR?AXuu)jaHa zeB$;L&ctxz2kbe%V{&GYLP1SlfnrLdZG*J14CM{!;QA^rYdH=j&eVSU-S%{~2o(yM zys1|`#ij*%)-LtW_n&}V2Fp}%dma^f7Goa41`7JY9#+tn;MTLp=rPS&;KjIGy}++! zY(rCk(8Zo0u1mq+W!Ya?BJ2o^G%poo3#WW^Ak91`EcIkEr{7#b(+6*SzJQtwNL^sY zIipcSGnKb4_4M{#Np##?Q%CIfRAQu>VQg2PiUi48F6_7lz#mYl!9 z{BDRb;oFgaPL4WYCubD{Ix%*orRM1!%otUIiUd&F$_?q;#^2g}5Q$^EpX!{#5@}LV61ORJcU&ZT9#)3Osbb}~&T_Scp(gOuF$3w2pET6V`H7god6RfE&lQJSUAPb z{Y~K`roN_)>aOp{W6KWp8u&UUa;XlSBqMk^ctrO<=uUEVTLM+}?Y zhn-6ChqXst6WP2~VXNqV)$3Kv2OK0hPCbCR)a`iotp#S$-hXFW`wlsi_jS@Vb=Bl# zde0F72UEdj$2ylAf`Xd`b*g0?le!MW#35k+%8v>WnLs(5^-_4{F=l3=b!wyzWo86Q zDi`VLHRcescrer_!bfLiLzO~L$NF%Ji?k!{3LOwY60nm^l_VH;A^t0-z2OMN z<}-c)VdgA93vA?;zgUdPt`w~A{+?qpm-ZMWZd1imh#N`D&dn2Bh2t= z0gdeQ9In2^y-~sI6$OfFDzR6bnRLZ$-fdxTz5gHpd?sG-+dNuSloRN*_MrwrmcjQ* z@Zy^3H*z(0SYPLD12JChBwG$1?hsh4m|cdn7+8Whm8PuA(J41X^+8r;IPN;3^610LRr+sQ>@~ literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/8-hand-clap.mp3 b/src/extensions/scratch3_music/assets/8-hand-clap.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..a5b55f522f628c09360473ca0429a1a41b3331c4 GIT binary patch literal 2582 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 literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/9-claves.mp3 b/src/extensions/scratch3_music/assets/9-claves.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..75b76533dec423cece275edae9d2887073ed78ae GIT binary patch literal 2973 zcmd^>`#aP9AICq~$e}qO(up~ytmKrYl2cS$b7q9wF~V3zP8rEzrCTFxQ%+&lB+Vft zVIeKYsAR<$S?Dfz6l34Iuj{^C*Z2D;d>_~KzFyb$e*f@(U60of&zE35hY9>Q?jaGu zzwV@e9dQ7VyaT9iaeNE^Ei$&K+M;8N_gj45La@cJzffmSB5Vv{W=F7~=6_o%RXCNN7_505tp!!vqF7Kqj>)*g@_e1z-d`f*;xGzDx2L zv^fl=J1QbxXupM!G*4&orX}akx z2lsA0rI>flHKmzV+`Q3!VH(9UjEU8ysMbYf>?;&~uHW|rkG^5J*5fuAOej9$$F0KV zk7C9+vQJj&%l*ZY9-9gM3ln9Ho^#xD-s1SOOM_l~Waujz!=-wb$BgRv`M90kEckP} z=0iTqdZsbd+8E9ZAuEsLT} zIrFhYX`aL&Ms1z~t*5mWsRxzrzbp++eNZF)MT?pDv~S!y8^ z1*@K6!nBeutt@Tj7O!Z0KR5=L&Gyz5;n_;J4leZ6{7 z)CYASZdOvsTqv^aq-`dHSXW<8v{`N!G>n%MKzCy|L*4?Co-g-kZxGAMwyBn6nmCEH zgxzI@M|afsuN-SIOs@{u!SwC*Q}rMZ=ZEc0wI(y1=g z(_jBBTLQ0;U5r>TP@&-t%qOKo+1DYDP7&bSqCb+TO2!Cb_xpLHe654~m;MHz0Ew%{ z2{w770NEZ{evs}sNSz^;&S=b+A8L$wROdmcYu;IvSC^QS_N;LiMF>2TDI$JvqY=I) zYfH!|T`PK$1Pk^4Y@Mm5i4)D(ttD;5fnM`07W}-se5KVTJYS@07Uxvm5XtM?`$Fc< zYS$^I);+nYTv9`1r3Ikgv({0ckFMCCJ(1#4(GajC|4h*R4usZ#oWCFOO21{aiW~pj zHZ#p<*o^L`^?fXC_B0|-8Fm;PHkN*nlHbepou^Jdx_HJ33B`gLl22C~l&9_O=Gyy-Qz3mr{~ zag~^d{9W&D+;)Qh&G2z$3b|IVBFFMfOO%D>)opW1kxhFz@dRD_>a}u0mZL%V0}Tb8 zFU1jx{uG`HTx0(A?jt^#%zWthAI)G?IMNK(JwYUfLty%-sEe<1-abAJvK6ze(qkMb z4e9zAC1+t_LJXSc)UF3B_-8B2+?2RCTy%UK(jDHt+82>+P6F*i9%hh;wx~-6f^8n` zNpD-}m6K*IFP>$oR&g-L#0=cMvmWAc0wN|as3O0jglECx0me0=F1QWeP&fAKqn zl<~5q1vU$XaiMbBpW0Fiwr3D+0{`A?sPe=6HIFw$pAxQ=$``ti#ikhRW75$Fw%9yn437sewG~b8` zY1WuGVc$eNW4xaDa9Jj(%5|jblX;ri4h)N6>O}W1% zh~lL^q;2L3W9DbdsENxE_T*4{rJ>lqmI}uQFZ)z3>#H7EtjjE%rRES{KSl94 zBHpN>~T#w2G)PFn+648CMlDzYC zla>>AW`*-o81ps$P)+I|Vu=)@V4$a`D7#xbYy~`^zd}n0R2Yu{A6$0V{e&HhOr`7_ zCUCU+U}aSk0!ifZ*aO@2$@EU0VY_KmBPW)=$arA3nw#Aped14PT+@?6g}SJ%tR8KP1GL6zRlSN$vU zVYUfjRioONN{<&O7sE}pE^nIW(3*CZQ!|46rk*tLI;9kSr&wZsC^8$pZ12s7-Sj5DHz-Oat&PUks(Y%1uk2cAE>3L_AZpHfNKAV anW%&>Md>FCHrkgQV7z~KUf5yU|L`BPd^IZo literal 0 HcmV?d00001 diff --git a/webpack.config.js b/webpack.config.js index b58666d47..a9586f153 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -60,7 +60,13 @@ module.exports = [ libraryTarget: 'commonjs2', path: path.resolve(__dirname, 'dist/node'), filename: '[name].js' - } + }, + plugins: base.plugins.concat([ + new CopyWebpackPlugin([{ + from: './src/extensions/scratch3_music/assets', + to: 'assets/scratch3_music' + }]) + ]) }), // Playground defaultsDeep({}, base, { From 26d4a3a069253dbadaedf6bc82961255242814c2 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Mon, 13 Nov 2017 16:29:38 -0500 Subject: [PATCH 137/272] Refactoring representation of variable type. --- src/engine/target.js | 4 ++-- src/engine/variable.js | 22 ++++++++++++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/engine/target.js b/src/engine/target.js index ebe7d495f..b67b42a5a 100644 --- a/src/engine/target.js +++ b/src/engine/target.js @@ -124,7 +124,7 @@ class Target extends EventEmitter { const list = this.lookupVariableById(id); if (list) return list; // No variable with this name exists - create it locally. - const newList = new Variable(id, name, 'list', false); + const newList = new Variable(id, name, Variable.LIST_TYPE, false); this.variables[id] = newList; return newList; } @@ -134,7 +134,7 @@ class Target extends EventEmitter { * dictionary of variables. * @param {string} id Id of variable * @param {string} name Name of variable. - * @param {string} type Type of variable, one of string, number, list + * @param {string} type Type of variable, '' or 'list' */ createVariable (id, name, type) { if (!this.variables.hasOwnProperty(id)) { diff --git a/src/engine/variable.js b/src/engine/variable.js index 55617894c..a44324f6e 100644 --- a/src/engine/variable.js +++ b/src/engine/variable.js @@ -19,18 +19,36 @@ class Variable { this.type = type; this.isCloud = isCloud; switch (this.type) { - case '': + case Variable.SCALAR_TYPE: this.value = 0; break; - case 'list': + case Variable.LIST_TYPE: this.value = []; break; + default: + throw new Error(`Invalid variable type: ${this.type}`); } } toXML () { return `${this.name}`; } + + /** + * Type representation for scalar variables. + * @const {string} + */ + static get SCALAR_TYPE () { + return ''; + } + + /** + * Type representation for list variables. + * @const {string} + */ + static get LIST_TYPE () { + return 'list'; + } } module.exports = Variable; From 3f444138db9e8c4ed32804d5ca4ceb6c1a57877b Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Mon, 13 Nov 2017 16:30:47 -0500 Subject: [PATCH 138/272] Updating tests for refactoring lists. Updating demo fixture -- now we have IDs and variable types for variables. --- test/fixtures/demo.json | 2 +- test/unit/engine_target.js | 60 +++++++++++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/test/fixtures/demo.json b/test/fixtures/demo.json index d54626da6..1467a463d 100644 --- a/test/fixtures/demo.json +++ b/test/fixtures/demo.json @@ -1 +1 @@ -{"targets":[{"id":"poXv!.~0@*~j*F(Om/X5","name":"Stage","isStage":true,"x":0,"y":0,"size":100,"direction":90,"draggable":false,"currentCostume":10,"costume":{"name":"backdrop2","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"skinId":7,"assetId":"7da4181ee167de7b3f5d1a91880277ff","assetType":{"contentType":"image/svg+xml","name":"ImageVector","runtimeFormat":"svg"}},"costumeCount":11,"visible":true,"rotationStyle":"all around","blocks":{"O7D.%E~TH^ULpAuHM8)@":{"id":"O7D.%E~TH^ULpAuHM8)@","opcode":"event_whenflagclicked","inputs":{},"fields":{},"next":"78+=E[P7b8!mBXMwQF`@","shadow":false,"x":138,"y":356.40000000000003,"topLevel":true,"parent":null},"78+=E[P7b8!mBXMwQF`@":{"id":"78+=E[P7b8!mBXMwQF`@","opcode":"control_forever","inputs":{"SUBSTACK":{"name":"SUBSTACK","block":"nlnk{2XqtVI*Qg,admbW","shadow":null}},"fields":{},"next":null,"shadow":false,"parent":"O7D.%E~TH^ULpAuHM8)@"},"nlnk{2XqtVI*Qg,admbW":{"id":"nlnk{2XqtVI*Qg,admbW","opcode":"looks_changeeffectby","inputs":{"EFFECT":{"name":"EFFECT","block":"*vh;qV87Q}5IP@sW=)wD","shadow":"*vh;qV87Q}5IP@sW=)wD"},"CHANGE":{"name":"CHANGE","block":"woYo[[v=PD(`R;qW{PZ%","shadow":"woYo[[v=PD(`R;qW{PZ%"}},"fields":{},"next":null,"shadow":false,"parent":"78+=E[P7b8!mBXMwQF`@"},"*vh;qV87Q}5IP@sW=)wD":{"id":"*vh;qV87Q}5IP@sW=)wD","opcode":"looks_effectmenu","inputs":{},"fields":{"EFFECT":{"name":"EFFECT","value":"color"}},"next":null,"topLevel":false,"parent":"nlnk{2XqtVI*Qg,admbW","shadow":true},"woYo[[v=PD(`R;qW{PZ%":{"id":"woYo[[v=PD(`R;qW{PZ%","opcode":"math_number","inputs":{},"fields":{"NUM":{"name":"NUM","value":1}},"next":null,"topLevel":false,"parent":"nlnk{2XqtVI*Qg,admbW","shadow":true}},"variables":{"vy":{"name":"vy","value":-3.5165000000000006,"isCloud":false},"g":{"name":"g","value":"-.5","isCloud":false},"vx":{"name":"vx","value":1.4580000000000002,"isCloud":false},"i":{"name":"i","value":3,"isCloud":false},"d1":{"name":"d1","value":0,"isCloud":false},"x":{"name":"x","value":233.9173278872492,"isCloud":false},"acceleration":{"name":"acceleration","value":"-3","isCloud":false}},"lists":{},"costumes":[{"name":"blue sky2","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"skinId":0,"assetId":"7623e679b2baa2e7d48808614820844f","assetType":{"contentType":"image/svg+xml","name":"ImageVector","runtimeFormat":"svg"}},{"name":"woods","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"skinId":3,"assetId":"1e0f7a4c932423b13250b5cb44928109","assetType":{"contentType":"image/svg+xml","name":"ImageVector","runtimeFormat":"svg"}},{"name":"party","bitmapResolution":1,"rotationCenterX":251,"rotationCenterY":189,"skinId":2,"assetId":"108160d0e44d1c340182e31c9dc0758a","assetType":{"contentType":"image/svg+xml","name":"ImageVector","runtimeFormat":"svg"}},{"name":"boardwalk","bitmapResolution":2,"rotationCenterX":480,"rotationCenterY":360,"skinId":6,"assetId":"de0e54cd11551566f044e7e6bc588b2c","assetType":{"contentType":"image/png","name":"ImageBitmap","runtimeFormat":"png"}},{"name":"blue sky3","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":179,"skinId":1,"assetId":"2024d59c1980e667e8f656134796e2c1","assetType":{"contentType":"image/svg+xml","name":"ImageVector","runtimeFormat":"svg"}},{"name":"underwater1","bitmapResolution":2,"rotationCenterX":480,"rotationCenterY":360,"skinId":5,"assetId":"f339c6f31b11ea71d0fb8d607cec392e","assetType":{"contentType":"image/png","name":"ImageBitmap","runtimeFormat":"png"}},{"name":"underwater2","bitmapResolution":2,"rotationCenterX":480,"rotationCenterY":360,"skinId":11,"assetId":"1517c21786d2d0edc2f3037408d850bd","assetType":{"contentType":"image/png","name":"ImageBitmap","runtimeFormat":"png"}},{"name":"stars","bitmapResolution":2,"rotationCenterX":480,"rotationCenterY":360,"skinId":4,"assetId":"e87fed9c2a968dbeae8c94617e600e8c","assetType":{"contentType":"image/png","name":"ImageBitmap","runtimeFormat":"png"}},{"name":"parking-ramp","bitmapResolution":2,"rotationCenterX":480,"rotationCenterY":360,"skinId":9,"assetId":"a7832479977c166ca0057f2a99a73305","assetType":{"contentType":"image/png","name":"ImageBitmap","runtimeFormat":"png"}},{"name":"backdrop1","bitmapResolution":2,"rotationCenterX":480,"rotationCenterY":360,"skinId":10,"assetId":"f67dc7de38bac6fbb0ab68e46352521d","assetType":{"contentType":"image/png","name":"ImageBitmap","runtimeFormat":"png"}},{"name":"backdrop2","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"skinId":7,"assetId":"7da4181ee167de7b3f5d1a91880277ff","assetType":{"contentType":"image/svg+xml","name":"ImageVector","runtimeFormat":"svg"}}],"sounds":[{"name":"pop","format":"","rate":11025,"sampleCount":258,"soundID":-1,"md5":"83a9787d4cb6f3b7632b4ddfebf74367.wav","data":null,"assetId":"83a9787d4cb6f3b7632b4ddfebf74367","assetType":{"contentType":"audio/x-wav","name":"Sound","runtimeFormat":"wav"}}]},{"id":"9!d8G^[6i]k*:l[W%4;l","name":"Earth","isStage":false,"x":-10,"y":10,"size":100,"direction":90,"draggable":false,"currentCostume":0,"costume":{"name":"earth","bitmapResolution":1,"rotationCenterX":72,"rotationCenterY":72,"skinId":8,"assetId":"814197522984a302972998b1a7f92d91","assetType":{"contentType":"image/svg+xml","name":"ImageVector","runtimeFormat":"svg"}},"costumeCount":1,"visible":true,"rotationStyle":"all around","blocks":{},"variables":{},"lists":{},"costumes":[{"name":"earth","bitmapResolution":1,"rotationCenterX":72,"rotationCenterY":72,"skinId":8,"assetId":"814197522984a302972998b1a7f92d91","assetType":{"contentType":"image/svg+xml","name":"ImageVector","runtimeFormat":"svg"}}],"sounds":[{"name":"pop","format":"","rate":11025,"sampleCount":258,"soundID":-1,"md5":"83a9787d4cb6f3b7632b4ddfebf74367.wav","data":null,"assetId":"83a9787d4cb6f3b7632b4ddfebf74367","assetType":{"contentType":"audio/x-wav","name":"Sound","runtimeFormat":"wav"}}]}],"meta":{"semver":"3.0.0","vm":"0.1.0","agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36"}} +{"targets":[{"id":"m#69^p_G_]:NI,ZR#?iy","name":"Stage","isStage":true,"x":0,"y":0,"size":100,"direction":90,"draggable":false,"currentCostume":10,"costume":{"skinId":10,"name":"backdrop2","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"dataFormat":"svg","assetId":"7da4181ee167de7b3f5d1a91880277ff"},"costumeCount":11,"visible":true,"rotationStyle":"all around","blocks":{"O7D.%E~TH^ULpAuHM8)@":{"id":"O7D.%E~TH^ULpAuHM8)@","opcode":"event_whenflagclicked","inputs":{},"fields":{},"next":"78+=E[P7b8!mBXMwQF`@","shadow":false,"x":138,"y":356.40000000000003,"topLevel":true,"parent":null},"78+=E[P7b8!mBXMwQF`@":{"id":"78+=E[P7b8!mBXMwQF`@","opcode":"control_forever","inputs":{"SUBSTACK":{"name":"SUBSTACK","block":"nlnk{2XqtVI*Qg,admbW","shadow":null}},"fields":{},"next":null,"shadow":false,"parent":"O7D.%E~TH^ULpAuHM8)@"},"nlnk{2XqtVI*Qg,admbW":{"id":"nlnk{2XqtVI*Qg,admbW","opcode":"looks_changeeffectby","inputs":{"EFFECT":{"name":"EFFECT","block":"*vh;qV87Q}5IP@sW=)wD","shadow":"*vh;qV87Q}5IP@sW=)wD"},"CHANGE":{"name":"CHANGE","block":"woYo[[v=PD(`R;qW{PZ%","shadow":"woYo[[v=PD(`R;qW{PZ%"}},"fields":{},"next":null,"shadow":false,"parent":"78+=E[P7b8!mBXMwQF`@"},"*vh;qV87Q}5IP@sW=)wD":{"id":"*vh;qV87Q}5IP@sW=)wD","opcode":"looks_effectmenu","inputs":{},"fields":{"EFFECT":{"name":"EFFECT","value":"color"}},"next":null,"topLevel":false,"parent":"nlnk{2XqtVI*Qg,admbW","shadow":true},"woYo[[v=PD(`R;qW{PZ%":{"id":"woYo[[v=PD(`R;qW{PZ%","opcode":"math_number","inputs":{},"fields":{"NUM":{"name":"NUM","value":1}},"next":null,"topLevel":false,"parent":"nlnk{2XqtVI*Qg,admbW","shadow":true}},"variables":{"6C~ysz%{q=IY/@VyR,}u":{"id":"6C~ysz%{q=IY/@VyR,}u","name":"vy","value":-3.5165000000000006,"type":""},"@M%UU5XBzcjofm,PEY-3":{"id":"@M%UU5XBzcjofm,PEY-3","name":"g","value":"-.5","type":""},"rNxv=Ia#{]Jvhmo{G6cf":{"id":"rNxv=Ia#{]Jvhmo{G6cf","name":"vx","value":1.4580000000000002,"type":""},"fc2rL3s1GcD4UyOOCaN(":{"id":"fc2rL3s1GcD4UyOOCaN(","name":"i","value":3, "type":""},"0A~.tga@}|%UW31FAhz5":{"id":"0A~.tga@}|%UW31FAhz5","name":"d1","value":0, "type":""},"^T|b;%@AzqwgHp},y98=":{"id":"^T|b;%@AzqwgHp},y98=","name":"x","value":233.9173278872492,"type":""},"6m`MGC(+0!,Mwj8xE2OB":{"id":"6m`MGC(+0!,Mwj8xE2OB","name":"acceleration","value":"-3","type":""}},"lists":{},"costumes":[{"skinId":9,"name":"blue sky2","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"dataFormat":"svg","assetId":"7623e679b2baa2e7d48808614820844f"},{"skinId":13,"name":"woods","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"dataFormat":"svg","assetId":"1e0f7a4c932423b13250b5cb44928109"},{"skinId":5,"name":"party","bitmapResolution":1,"rotationCenterX":251,"rotationCenterY":189,"dataFormat":"svg","assetId":"108160d0e44d1c340182e31c9dc0758a"},{"skinId":3,"name":"boardwalk","bitmapResolution":2,"rotationCenterX":480,"rotationCenterY":360,"dataFormat":"png","assetId":"de0e54cd11551566f044e7e6bc588b2c"},{"skinId":6,"name":"blue sky3","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":179,"dataFormat":"svg","assetId":"2024d59c1980e667e8f656134796e2c1"},{"skinId":14,"name":"underwater1","bitmapResolution":2,"rotationCenterX":480,"rotationCenterY":360,"dataFormat":"png","assetId":"f339c6f31b11ea71d0fb8d607cec392e"},{"skinId":7,"name":"underwater2","bitmapResolution":2,"rotationCenterX":480,"rotationCenterY":360,"dataFormat":"png","assetId":"1517c21786d2d0edc2f3037408d850bd"},{"skinId":8,"name":"stars","bitmapResolution":2,"rotationCenterX":480,"rotationCenterY":360,"dataFormat":"png","assetId":"e87fed9c2a968dbeae8c94617e600e8c"},{"skinId":11,"name":"parking-ramp","bitmapResolution":2,"rotationCenterX":480,"rotationCenterY":360,"dataFormat":"png","assetId":"a7832479977c166ca0057f2a99a73305"},{"skinId":12,"name":"backdrop1","bitmapResolution":2,"rotationCenterX":480,"rotationCenterY":360,"dataFormat":"png","assetId":"f67dc7de38bac6fbb0ab68e46352521d"},{"skinId":10,"name":"backdrop2","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"dataFormat":"svg","assetId":"7da4181ee167de7b3f5d1a91880277ff"}],"sounds":[{"format":"","rate":11025,"sampleCount":258,"soundID":-1,"name":"pop","md5":"83a9787d4cb6f3b7632b4ddfebf74367.wav","data":null,"dataFormat":"wav","assetId":"83a9787d4cb6f3b7632b4ddfebf74367","soundId":"yGa~fKV|[-9r)^[i+xMU"}]},{"id":"./Q-Mm#v_Ifl9@[}Ye^8","name":"Earth","isStage":false,"x":-10,"y":10,"size":100,"direction":90,"draggable":false,"currentCostume":0,"costume":{"skinId":4,"name":"earth","bitmapResolution":1,"rotationCenterX":72,"rotationCenterY":72,"dataFormat":"svg","assetId":"814197522984a302972998b1a7f92d91"},"costumeCount":1,"visible":true,"rotationStyle":"all around","blocks":{},"variables":{},"lists":{},"costumes":[{"skinId":4,"name":"earth","bitmapResolution":1,"rotationCenterX":72,"rotationCenterY":72,"dataFormat":"svg","assetId":"814197522984a302972998b1a7f92d91"}],"sounds":[{"format":"","rate":11025,"sampleCount":258,"soundID":-1,"name":"pop","md5":"83a9787d4cb6f3b7632b4ddfebf74367.wav","data":null,"dataFormat":"wav","assetId":"83a9787d4cb6f3b7632b4ddfebf74367","soundId":"MRZ+h9~E:8O(Fk,.zDVC"}]}],"meta":{"semver":"3.0.0","vm":"0.1.0-prerelease.1510327661-prerelease.1510327675","agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36"}} diff --git a/test/unit/engine_target.js b/test/unit/engine_target.js index db5b5e762..70bf46e99 100644 --- a/test/unit/engine_target.js +++ b/test/unit/engine_target.js @@ -1,5 +1,6 @@ const test = require('tap').test; const Target = require('../../src/engine/target'); +const Variable = require('../../src/engine/variable'); test('spec', t => { const target = new Target(); @@ -23,14 +24,14 @@ test('spec', t => { // Create Variable tests. test('createVariable', t => { const target = new Target(); - target.createVariable('foo', 'bar', ''); + target.createVariable('foo', 'bar', Variable.SCALAR_TYPE); const variables = target.variables; t.equal(Object.keys(variables).length, 1); const variable = variables[Object.keys(variables)[0]]; t.equal(variable.id, 'foo'); t.equal(variable.name, 'bar'); - t.equal(variable.type, ''); + t.equal(variable.type, Variable.SCALAR_TYPE); t.equal(variable.value, 0); t.equal(variable.isCloud, false); @@ -40,8 +41,8 @@ test('createVariable', t => { // Create Same Variable twice. test('createVariable2', t => { const target = new Target(); - target.createVariable('foo', 'bar', ''); - target.createVariable('foo', 'bar', ''); + target.createVariable('foo', 'bar', Variable.SCALAR_TYPE); + target.createVariable('foo', 'bar', Variable.SCALAR_TYPE); const variables = target.variables; t.equal(Object.keys(variables).length, 1); @@ -50,16 +51,16 @@ test('createVariable2', t => { }); // Create a list -test('createVariable creates a list', t => { +test('createListVariable creates a list', t => { const target = new Target(); - target.createVariable('foo', 'bar', 'list'); + target.createVariable('foo', 'bar', Variable.LIST_TYPE); const variables = target.variables; t.equal(Object.keys(variables).length, 1); const variable = variables[Object.keys(variables)[0]]; t.equal(variable.id, 'foo'); t.equal(variable.name, 'bar'); - t.equal(variable.type, 'list'); + t.equal(variable.type, Variable.LIST_TYPE); t.assert(variable.value instanceof Array, true); t.equal(variable.value.length, 0); t.equal(variable.isCloud, false); @@ -67,10 +68,20 @@ test('createVariable creates a list', t => { t.end(); }); +test('createVariable throws when given invalid type', t => { + const target = new Target(); + t.throws( + (() => target.createVariable('foo', 'bar', 'baz')), + new Error('Invalid variable type: baz') + ); + + t.end(); +}); + // Rename Variable tests. test('renameVariable', t => { const target = new Target(); - target.createVariable('foo', 'bar', ''); + target.createVariable('foo', 'bar', Variable.SCALAR_TYPE); target.renameVariable('foo', 'bar2'); const variables = target.variables; @@ -99,7 +110,7 @@ test('renameVariable2', t => { // Expect no change. test('renameVariable3', t => { const target = new Target(); - target.createVariable('foo1', 'foo', ''); + target.createVariable('foo1', 'foo', Variable.SCALAR_TYPE); target.renameVariable('foo', 'bar2'); const variables = target.variables; @@ -114,7 +125,7 @@ test('renameVariable3', t => { // Delete Variable tests. test('deleteVariable', t => { const target = new Target(); - target.createVariable('foo', 'bar', ''); + target.createVariable('foo', 'bar', Variable.SCALAR_TYPE); target.deleteVariable('foo'); const variables = target.variables; @@ -133,3 +144,32 @@ test('deleteVariable2', t => { t.end(); }); + +test('lookupOrCreateList creates a list if var with given id does not exist', t => { + const target = new Target(); + const variables = target.variables; + + t.equal(Object.keys(variables).length, 0); + const listVar = target.lookupOrCreateList('foo', 'bar'); + t.equal(Object.keys(variables).length, 1); + t.equal(listVar.id, 'foo'); + t.equal(listVar.name, 'bar'); + + t.end(); +}); + +test('lookupOrCreateList returns list if one with given id exists', t => { + const target = new Target(); + const variables = target.variables; + + t.equal(Object.keys(variables).length, 0); + target.createVariable('foo', 'bar', Variable.LIST_TYPE); + t.equal(Object.keys(variables).length, 1); + + const listVar = target.lookupOrCreateList('foo', 'bar'); + t.equal(Object.keys(variables).length, 1); + t.equal(listVar.id, 'foo'); + t.equal(listVar.name, 'bar'); + + t.end(); +}); From 386045f033d074f5e61cfd95c75e827f9ad7eac1 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Mon, 13 Nov 2017 16:55:57 -0500 Subject: [PATCH 139/272] Some code cleanup. --- src/engine/target.js | 2 +- src/engine/variable.js | 2 +- src/serialization/sb2.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/engine/target.js b/src/engine/target.js index b67b42a5a..7b2f1d66f 100644 --- a/src/engine/target.js +++ b/src/engine/target.js @@ -87,7 +87,7 @@ class Target extends EventEmitter { const variable = this.lookupVariableById(id); if (variable) return variable; // No variable with this name exists - create it locally. - const newVariable = new Variable(id, name, '', false); + const newVariable = new Variable(id, name, Variable.SCALAR_TYPE, false); this.variables[id] = newVariable; return newVariable; } diff --git a/src/engine/variable.js b/src/engine/variable.js index a44324f6e..5896e593b 100644 --- a/src/engine/variable.js +++ b/src/engine/variable.js @@ -9,7 +9,7 @@ class Variable { /** * @param {string} id Id of the variable. * @param {string} name Name of the variable. - * @param {(string|number)} type Type of the variable, one of "" or "list" + * @param {string} type Type of the variable, one of '' or 'list' * @param {boolean} isCloud Whether the variable is stored in the cloud. * @constructor */ diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js index 0c6c37813..f7b7b30da 100644 --- a/src/serialization/sb2.js +++ b/src/serialization/sb2.js @@ -234,7 +234,7 @@ const parseScratchObject = function (object, runtime, extensions, topLevel) { const newVariable = new Variable( getVariableId(variable.name), variable.name, - '', + Variable.SCALAR_TYPE, variable.isPersistent ); newVariable.value = variable.value; @@ -254,7 +254,7 @@ const parseScratchObject = function (object, runtime, extensions, topLevel) { const newVariable = new Variable( getVariableId(list.listName), list.listName, - 'list', + Variable.LIST_TYPE, list.isPersistent ); newVariable.value = list.contents; From 9048a9b9e78f25fef129fc1663912a244729cb1d Mon Sep 17 00:00:00 2001 From: DD Date: Mon, 13 Nov 2017 16:28:50 -0500 Subject: [PATCH 140/272] Pipe through whether a monitor is sprite-specific --- src/engine/blocks.js | 14 +++++++++++--- src/engine/execute.js | 2 ++ src/engine/monitor-record.js | 2 ++ src/engine/runtime.js | 9 +++++---- src/util/uid.js | 3 ++- 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 92a2d58e7..7564d3ca9 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -226,7 +226,8 @@ class Blocks { id: e.blockId, element: e.element, name: e.name, - value: e.newValue + value: e.newValue, + isSpriteSpecific: e.isSpriteSpecific }, optRuntime); break; case 'move': @@ -326,12 +327,14 @@ class Blocks { break; case 'checkbox': block.isMonitored = args.value; + block.targetId = args.isSpriteSpecific ? this._getTargetIdFromBlockId(block.id) : null; if (optRuntime && wasMonitored && !block.isMonitored) { optRuntime.requestRemoveMonitor(block.id); } else if (optRuntime && !wasMonitored && block.isMonitored) { optRuntime.requestAddMonitor(MonitorRecord({ // @todo(vm#564) this will collide if multiple sprites use same block id: block.id, + spriteName: block.targetId ? optRuntime.getTargetById(block.targetId).getName() : null, opcode: block.opcode, params: this._getBlockParams(block), // @todo(vm#565) for numerical values with decimals, some countries use comma @@ -406,12 +409,17 @@ class Blocks { runAllMonitored (runtime) { Object.keys(this._blocks).forEach(blockId => { if (this.getBlock(blockId).isMonitored) { - // @todo handle specific targets (e.g. apple x position) - runtime.addMonitorScript(blockId); + const targetId = this.getBlock(blockId).targetId; + runtime.addMonitorScript(blockId, targetId ? runtime.getTargetById(targetId) : null); } }); } + _getTargetIdFromBlockId (blockId) { + // First word of block ID. See makeToolboxXML in scratch-gui + return blockId.split('_')[0]; + } + /** * Block management: delete blocks and their associated scripts. * @param {!object} e Blockly delete event to be processed. diff --git a/src/engine/execute.js b/src/engine/execute.js index df9b5964b..fe1688e6a 100644 --- a/src/engine/execute.js +++ b/src/engine/execute.js @@ -68,8 +68,10 @@ const handleReport = function ( sequencer.runtime.visualReport(currentBlockId, resolvedValue); } if (thread.updateMonitor) { + const targetId = sequencer.runtime.monitorBlocks.getBlock(currentBlockId).targetId; sequencer.runtime.requestUpdateMonitor(Map({ id: currentBlockId, + spriteName: targetId ? sequencer.runtime.getTargetById(targetId).getName() : null, value: String(resolvedValue) })); } diff --git a/src/engine/monitor-record.js b/src/engine/monitor-record.js index 76ed08489..40e67c5e7 100644 --- a/src/engine/monitor-record.js +++ b/src/engine/monitor-record.js @@ -2,6 +2,8 @@ const {Record} = require('immutable'); const MonitorRecord = Record({ id: null, + /** Present only if the monitor is sprite-specific, such as x position */ + spriteName: null, opcode: null, value: null, params: null diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 56fceadfc..06d068bcd 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -838,7 +838,7 @@ class Runtime extends EventEmitter { /** * Enqueue a script that when finished will update the monitor for the block. * @param {!string} topBlockId ID of block that starts the script. - * @param {?string} optTarget target ID for target to run script on. If not supplied, uses editing target. + * @param {?string} optTarget target Target to run script on. If not supplied, uses editing target. */ addMonitorScript (topBlockId, optTarget) { if (!optTarget) optTarget = this._editingTarget; @@ -1260,7 +1260,7 @@ class Runtime extends EventEmitter { * @param {!MonitorRecord} monitor Monitor to add. */ requestAddMonitor (monitor) { - this._monitorState = this._monitorState.set(monitor.id, monitor); + this._monitorState = this._monitorState.set(monitor.get('id'), monitor); } /** @@ -1271,9 +1271,10 @@ class Runtime extends EventEmitter { * the old monitor will keep its old value. */ requestUpdateMonitor (monitor) { - if (this._monitorState.has(monitor.get('id'))) { + const id = monitor.get('id'); + if (this._monitorState.has(id)) { this._monitorState = - this._monitorState.set(monitor.get('id'), this._monitorState.get(monitor.get('id')).merge(monitor)); + this._monitorState.set(id, this._monitorState.get(id).merge(monitor)); } } diff --git a/src/util/uid.js b/src/util/uid.js index fd4c41e87..34e8eaf58 100644 --- a/src/util/uid.js +++ b/src/util/uid.js @@ -6,9 +6,10 @@ * Legal characters for the unique ID. * Should be all on a US keyboard. No XML special characters or control codes. * Removed $ due to issue 251. + * Removed _ which denotes word separation in XML. * @private */ -const soup_ = '!#%()*+,-./:;=?@[]^_`{|}~' + +const soup_ = '!#%()*+,-./:;=?@[]^`{|}~' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; /** From 9f1bcd25946e562faa1bf9559ed93288c08d808b Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 14 Nov 2017 14:30:44 -0500 Subject: [PATCH 141/272] Arrays with drum and instrument name and filename --- src/extensions/scratch3_music/index.js | 225 +++++++++++++++++++------ 1 file changed, 172 insertions(+), 53 deletions(-) diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index ba1360034..94d22e296 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -5,59 +5,6 @@ const Cast = require('../../util/cast'); const MathUtil = require('../../util/math-util'); const Timer = require('../../util/timer'); -/** - * An array of drum names, used in the play drum block. - * @type {string[]} - */ -const drumNames = [ - 'Snare Drum', - 'Bass Drum', - 'Side Stick', - 'Crash Cymbal', - 'Open Hi-Hat', - 'Closed Hi-Hat', - 'Tambourine', - 'Hand Clap', - 'Claves', - 'Wood Block', - 'Cowbell', - 'Triangle', - 'Bongo', - 'Conga', - 'Cabasa', - 'Guiro', - 'Vibraslap', - 'Open Cuica' -]; - -/** - * An array of instrument names, used in the set instrument block. - * @type {string[]} - */ -const instrumentNames = [ - 'Piano', - 'Electric Piano', - 'Organ', - 'Guitar', - 'Electric Guitar', - 'Bass', - 'Pizzicato', - 'Cello', - 'Trombone', - 'Clarinet', - 'Saxophone', - 'Flute', - 'Wooden Flute', - 'Bassoon', - 'Choir', - 'Vibraphone', - 'Music Box', - 'Steel Drum', - 'Marimba', - 'Synth Lead', - 'Synth Pad' -]; - /** * Class for the music-related blocks in Scratch 3.0 * @param {Runtime} runtime - the runtime instantiating this block package. @@ -99,6 +46,178 @@ class Scratch3MusicBlocks { menu.push(entry); } return menu; + /** + * An array of translatable drum names and corresponding audio file names. + * @type {array} + */ + get DRUM_INFO () { + return [ + { + name: '(1) Snare Drum', + fileName: '1-snare' + }, + { + name: '(2) Bass Drum', + fileName: '2-bass-drum' + }, + { + name: '(3) Side Stick', + fileName: '3-side-stick' + }, + { + name: '(4) Crash Cymbal', + fileName: '4-crash-cymbal' + }, + { + name: '(5) Open Hi-Hat', + fileName: '5-open-hi-hat' + }, + { + name: '(6) Closed Hi-Hat', + fileName: '6-closed-hi-hat' + }, + { + name: '(7) Tambourine', + fileName: '7-tambourine' + }, + { + name: '(8) Hand Clap', + fileName: '8-hand-clap' + }, + { + name: '(9) Claves', + fileName: '9-claves' + }, + { + name: '(10) Wood Block', + fileName: '10-wood-block' + }, + { + name: '(11) Cowbell', + fileName: '11-cowbell' + }, + { + name: '(12) Triangle', + fileName: '12-triangle' + }, + { + name: '(13) Bongo', + fileName: '13-bongo' + }, + { + name: '(14) Conga', + fileName: '14-conga' + }, + { + name: '(15) Cabasa', + fileName: '15-cabasa' + }, + { + name: '(16) Guiro', + fileName: '16-guiro' + }, + { + name: '(17) Vibraslap', + fileName: '17-vibraslap' + }, + { + name: '(18) Cuica', + fileName: '18-cuica' + } + ]; + } + + /** + * An array of translatable instrument names and corresponding audio file names. + * @type {array} + */ + get INSTRUMENT_INFO () { + return [ + { + name: '(1) Piano', + fileName: '1-piano' + }, + { + name: '(2) Electric Piano', + fileName: '2-electric-piano' + }, + { + name: '(3) Organ', + fileName: '3-organ' + }, + { + name: '(4) Guitar', + fileName: '4-guitar' + }, + { + name: '(5) Electric Guitar', + fileName: '5-electric-guitar' + }, + { + name: '(6) Bass', + fileName: '6-bass' + }, + { + name: '(7) Pizzicato', + fileName: '7-pizzicato' + }, + { + name: '(8) Cello', + fileName: '8-cello' + }, + { + name: '(9) Trombone', + fileName: '9-trombone' + }, + { + name: '(10) Clarinet', + fileName: '10-clarinet' + }, + { + name: '(11) Saxophone', + fileName: '11-saxophone' + }, + { + name: '(12) Flute', + fileName: '12-flute' + }, + { + name: '(13) Wooden Flute', + fileName: '13-wooden-flute' + }, + { + name: '(14) Bassoon', + fileName: '14-bassoon' + }, + { + name: '(15) Choir', + fileName: '15-choir' + }, + { + name: '(16) Vibraphone', + fileName: '16-vibraphone' + }, + { + name: '(17) Music Box', + fileName: '17-music-box' + }, + { + name: '(18) Steel Drum', + fileName: '18-steel-drum' + }, + { + name: '(19) Marimba', + fileName: '19-marimba' + }, + { + name: '(20) Synth Lead', + fileName: '20-synth-lead' + }, + { + name: '(21) Synth Pad', + fileName: '21-synth-pad' + } + ]; } /** From 91878adfe1b963579d54595c13fb73557e6c91a7 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 14 Nov 2017 14:32:14 -0500 Subject: [PATCH 142/272] Build menus using drum and instrument info arrays --- src/extensions/scratch3_music/index.js | 33 ++++++++++++-------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index 94d22e296..c5d44a9ca 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -25,27 +25,24 @@ class Scratch3MusicBlocks { */ this.tempo = 60; - this.drumMenu = this._buildMenu(drumNames); - this.instrumentMenu = this._buildMenu(instrumentNames); } /** - * Build a menu using an array of strings. - * Used for creating the drum and instrument menus. - * @param {string[]} names - An array of names. - * @return {array} - An array of objects with text and value properties, for constructing a block menu. + * Create data for a menu in scratch-blocks format, consisting of an array of objects with text and + * value properties. The text is a translated string, and the value is one-indexed. + * @param {object[]} info - An array of info objects each having a name property. + * @return {array} - An array of objects with text and value properties. * @private */ - _buildMenu (names) { - const menu = []; - for (let i = 0; i < names.length; i++) { - const entry = {}; - const num = i + 1; // Menu numbers are one-indexed - entry.text = `(${num}) ${names[i]}`; - entry.value = String(num); - menu.push(entry); - } - return menu; + _buildMenu (info) { + return info.map((entry, index) => { + const obj = {}; + obj.text = entry.name; + obj.value = index + 1; + return obj; + }); + } + /** * An array of translatable drum names and corresponding audio file names. * @type {array} @@ -367,8 +364,8 @@ class Scratch3MusicBlocks { } ], menus: { - drums: this.drumMenu, - instruments: this.instrumentMenu + drums: this._buildMenu(this.DRUM_INFO), + instruments: this._buildMenu(this.INSTRUMENT_INFO) } }; } From c26198d050b7b24580af3bfa36ef7d797b3f8337 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 14 Nov 2017 14:33:14 -0500 Subject: [PATCH 143/272] Load drum sounds into an array of buffers --- src/extensions/scratch3_music/index.js | 43 ++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index c5d44a9ca..ba42c1676 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -25,6 +25,49 @@ class Scratch3MusicBlocks { */ this.tempo = 60; + /** + * An array of audio buffers, one for each drum sound. + * @type {Array} + * @private + */ + this._drumBuffers = []; + + this._loadAllDrumSounds(); + } + + /** + * Download and decode the full set of drum sounds, and store the audio buffers + * in the drum buffers array. + * @TODO: Also load the instrument sounds here (rename this fn), and use Promise.all + * to detect that all the assets have loaded in order to update the extension status + * indicator. + */ + _loadAllDrumSounds () { + const loadingPromises = []; + this.DRUM_INFO.forEach((drumInfo, index) => { + const promise = this._loadSound(drumInfo.fileName, index, this._drumBuffers); + loadingPromises.push(promise); + }); + Promise.all(loadingPromises).then(() => { + // done! + }); + } + + /** + * Download and decode a sound, and store the buffer in an array. + * @param {string} fileName - the audio file name. + * @param {number} index - the index at which to store the audio buffer. + * @param {array} bufferArray - the array of buffers in which to store it. + * @return {Promise} - a promise which will resolve once the sound has loaded. + */ + _loadSound (fileName, index, bufferArray) { + return this.runtime.storage.load(this.runtime.storage.AssetType.Sound, fileName, 'mp3') + .then(soundAsset => + this.runtime.audioEngine.audioContext.decodeAudioData(soundAsset.data.buffer) + ) + .then(buffer => { + bufferArray[index] = buffer; + }); } /** From 14e2ca8d9921c5095d1768ee6e123c04ba5201a8 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 14 Nov 2017 14:35:26 -0500 Subject: [PATCH 144/272] Round the drum num arg --- src/extensions/scratch3_music/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index ba42c1676..e0b2ca262 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -423,6 +423,7 @@ class Scratch3MusicBlocks { playDrumForBeats (args, util) { if (this._stackTimerNeedsInit(util)) { let drum = Cast.toNumber(args.DRUM); + drum = Math.round(drum); drum -= 1; // drums are one-indexed if (typeof this.runtime.audioEngine === 'undefined') return; drum = MathUtil.wrapClamp(drum, 0, this.runtime.audioEngine.numDrums - 1); From 73dbc824110da1436f471bb54f8da29710bf06e3 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 14 Nov 2017 14:36:34 -0500 Subject: [PATCH 145/272] Get number of drums from drum info array --- src/extensions/scratch3_music/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index e0b2ca262..84bd46798 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -425,8 +425,7 @@ class Scratch3MusicBlocks { let drum = Cast.toNumber(args.DRUM); drum = Math.round(drum); drum -= 1; // drums are one-indexed - if (typeof this.runtime.audioEngine === 'undefined') return; - drum = MathUtil.wrapClamp(drum, 0, this.runtime.audioEngine.numDrums - 1); + drum = MathUtil.wrapClamp(drum, 0, this.DRUM_INFO.length - 1); let beats = Cast.toNumber(args.BEATS); beats = this._clampBeats(beats); if (util.target.audioPlayer !== null) { From b64152637e8918b20270636e7ec9198844d3f1de Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 14 Nov 2017 14:39:11 -0500 Subject: [PATCH 146/272] Play drums! --- src/extensions/scratch3_music/index.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index 84bd46798..874dbe4fc 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -428,15 +428,22 @@ class Scratch3MusicBlocks { drum = MathUtil.wrapClamp(drum, 0, this.DRUM_INFO.length - 1); let beats = Cast.toNumber(args.BEATS); beats = this._clampBeats(beats); - if (util.target.audioPlayer !== null) { - util.target.audioPlayer.playDrumForBeats(drum, beats); - } + this._playDrumNum(util, drum); this._startStackTimer(util, this._beatsToSec(beats)); } else { this._checkStackTimer(util); } } + _playDrumNum (util, drumNum) { + if (util.target.audioPlayer === null) return; + const outputNode = util.target.audioPlayer.getInputNode(); + const bufferSource = this.runtime.audioEngine.audioContext.createBufferSource(); + bufferSource.buffer = this._drumBuffers[drumNum]; + bufferSource.connect(outputNode); + bufferSource.start(); + } + /** * Rest for some number of beats. * @param {object} args - the block arguments. From 7a65fe7d07f6bdbf8e075689fc411542222b0d9c Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 14 Nov 2017 14:39:50 -0500 Subject: [PATCH 147/272] Limit number of concurrent drum sounds --- src/extensions/scratch3_music/index.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index 874dbe4fc..1ccc340fa 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -25,6 +25,13 @@ class Scratch3MusicBlocks { */ this.tempo = 60; + /** + * The number of drum sounds currently being played simultaneously. + * @type {number} + * @private + */ + this._drumConcurrencyCounter = 0; + /** * An array of audio buffers, one for each drum sound. * @type {Array} @@ -302,6 +309,14 @@ class Scratch3MusicBlocks { return {min: 20, max: 500}; } + /** + * The maximum number of sounds to allow to play simultaneously. + * @type {number} + */ + static get CONCURRENCY_LIMIT () { + return 30; + } + /** * @param {Target} target - collect music state for this target. * @returns {MusicState} the mutable music state associated with that target. This will be created if necessary. @@ -437,11 +452,18 @@ class Scratch3MusicBlocks { _playDrumNum (util, drumNum) { if (util.target.audioPlayer === null) return; + if (this._drumConcurrencyCounter > Scratch3MusicBlocks.CONCURRENCY_LIMIT) { + return; + } const outputNode = util.target.audioPlayer.getInputNode(); const bufferSource = this.runtime.audioEngine.audioContext.createBufferSource(); bufferSource.buffer = this._drumBuffers[drumNum]; bufferSource.connect(outputNode); bufferSource.start(); + this._drumConcurrencyCounter++; + bufferSource.onended = () => { + this._drumConcurrencyCounter--; + }; } /** From 9665b3ed25379a6a86fae569f3344d24f8a60c3b Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 14 Nov 2017 14:40:27 -0500 Subject: [PATCH 148/272] Always yield on first run of a timed block --- src/extensions/scratch3_music/index.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index 1ccc340fa..484820054 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -547,9 +547,7 @@ class Scratch3MusicBlocks { util.stackFrame.timer = new Timer(); util.stackFrame.timer.start(); util.stackFrame.duration = duration; - if (util.stackFrame.duration > 0) { - util.yield(); - } + util.yield(); } /** From a5b55a51287d345fc1aeaa635f398540182c57d3 Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Thu, 9 Nov 2017 17:10:09 -0500 Subject: [PATCH 149/272] Add runtime Profiler Profile internal virtual machine performance down to which blocks take how long. --- src/engine/profiler.js | 311 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 311 insertions(+) create mode 100644 src/engine/profiler.js diff --git a/src/engine/profiler.js b/src/engine/profiler.js new file mode 100644 index 000000000..1433f36fd --- /dev/null +++ b/src/engine/profiler.js @@ -0,0 +1,311 @@ +/** + * @fileoverview + * A way to profile Scratch internal performance. Like what blocks run during a + * step? How much time do they take? How much time is spent inbetween blocks? + * + * Profiler aims for to spend as little time inside its functions while + * recording. For this it has a simple internal record structure that records a + * series of values for each START and STOP event in a single array. This lets + * all the values be pushed in one call for the array. This simplicity allows + * the contents of the start() and stop() calls to be inlined in areas that are + * called frequently enough to want even greater performance from Profiler so + * what is recorded better reflects on the profiled code and not Profiler + * itself. + */ + +/** + * The next id returned for a new profile'd function. + * @type {number} + */ +let nextId = 0; + +/** + * The mapping of names to ids. + * @const {Object.} + */ +const profilerNames = {}; + +/** + * The START event identifier in Profiler records. + * @const {number} + */ +const START = 0; + +/** + * The STOP event identifier in Profiler records. + * @const {number} + */ +const STOP = 1; + +/** + * The number of cells used in the records array by a START event. + * @const {number} + */ +const START_SIZE = 4; + +/** + * The number of cells used in the records array by a STOP event. + * @const {number} + */ +const STOP_SIZE = 2; + +/** + * Stored reference to Performance instance provided by the Browser. + * @const {Performance} + */ +const performance = typeof window === 'object' && window.performance; + + +/** + * Callback handle called by Profiler for each frame it decodes from its + * records. + * @callback FrameCallback + * @param {ProfilerFrame} frame + */ + +/** + * A set of information about a frame of execution that was recorded. + */ +class ProfilerFrame { + /** + * @param {number} depth Depth of the frame in the recorded stack. + */ + constructor (depth) { + /** + * The numeric id of a record symbol like Runtime._step or + * blockFunction. + * @type {number} + */ + this.id = -1; + + /** + * The amount of time spent inside the recorded frame and any deeper + * frames. + * @type {number} + */ + this.totalTime = 0; + + /** + * The amount of time spent only inside this record frame. Not + * including time in any deeper frames. + * @type {number} + */ + this.selfTime = 0; + + /** + * An arbitrary argument for the recorded frame. For example a block + * function might record its opcode as an argument. + * @type {*} + */ + this.arg = null; + + /** + * The depth of the recorded frame. This can help compare recursive + * funtions that are recorded. Each level of recursion with have a + * different depth value. + * @type {number} + */ + this.depth = depth; + } +} + +class Profiler { + /** + * @param {FrameCallback} onFrame a handle called for each recorded frame. + * The passed frame value may not be stored as it'll be updated with later + * frame information. Any information that is further stored by the handler + * should make copies or reduce the information. + */ + constructor (onFrame = function () {}) { + /** + * A series of START and STOP values followed by arguments. After + * recording is complete the full set of records is reported back by + * stepping through the series to connect the relative START and STOP + * information. + * @type {Array.<*>} + */ + this.records = []; + + /** + * A cache of ProfilerFrames to reuse when reporting the recorded + * frames in records. + * @type {Array.} + */ + this._stack = [new ProfilerFrame(0)]; + + /** + * A callback handle called with each decoded frame when reporting back + * all the recorded times. + * @type {FrameCallback} + */ + this.onFrame = onFrame; + + /** + * A reference to the START record id constant. + * @const {number} + */ + this.START = START; + + /** + * A reference to the STOP record id constant. + * @const {number} + */ + this.STOP = STOP; + } + + /** + * Start recording a frame of time for an id and optional argument. + * @param {number} id The id returned by idByName for a name symbol like + * Runtime._step. + * @param {?*} arg An arbitrary argument value to store with the frame. + */ + start (id, arg) { + this.records.push(START, id, arg, performance.now()); + } + + /** + * Stop the current frame. + */ + stop () { + this.records.push(STOP, performance.now()); + } + + /** + * Decode records and report all frames to `this.onFrame`. + */ + reportFrames () { + const stack = this._stack; + let depth = 1; + + // Step through the records and initialize Frame instances from the + // START and STOP events. START and STOP events are separated by events + // for deeper frames run by higher frames. Frames are stored on a stack + // and reinitialized for each START event. When a stop event is reach + // the Frame for the current depth has its final values stored and its + // passed to the current onFrame callback. This way Frames are "pushed" + // for each START event and "popped" for each STOP and handed to an + // outside handle to any desired reduction of the collected data. + for (let i = 0; i < this.records.length;) { + if (this.records[i] === START) { + if (depth >= stack.length) { + stack.push(new ProfilerFrame(depth)); + } + + // Store id, arg, totalTime, and initialize selfTime. + const frame = stack[depth++]; + frame.id = this.records[i + 1]; + frame.arg = this.records[i + 2]; + // totalTime is first set as the time recorded by this START + // event. Once the STOP event is reached the stored start time + // is subtracted from the recorded stop time. The resulting + // difference is the actual totalTime, and replaces the start + // time in frame.totalTime. + // + // totalTime is used this way as a convenient member to store a + // value between the two events without needing additional + // members on the Frame or in a shadow map. + frame.totalTime = this.records[i + 3]; + // selfTime is decremented until we reach the STOP event for + // this frame. totalTime will be added to it then to get the + // time difference. + frame.selfTime = 0; + + i += START_SIZE; + } else if (this.records[i] === STOP) { + const now = this.records[i + 1]; + + const frame = stack[--depth]; + // totalTime is the difference between the start event time + // stored in totalTime and the stop event time pulled from this + // record. + frame.totalTime = now - frame.totalTime; + // selfTime is the difference of this frame's totalTime and the + // sum of totalTime of deeper frames. + frame.selfTime += frame.totalTime; + + // Remove this frames totalTime from the parent's selfTime. + stack[depth - 1].selfTime -= frame.totalTime; + + this.onFrame(frame); + + i += STOP_SIZE; + } else { + this.records.length = 0; + throw new Error('Unable to decode Profiler records.'); + } + } + + this.records.length = 0; + } + + /** + * Lookup or create an id for a frame name. + * @param {string} name The name to return an id for. + * @return {number} The id for the passed name. + */ + idByName (name) { + return Profiler.idByName(name); + } + + /** + * Reverse lookup the name from a given frame id. + * @param {number} id The id to search for. + * @return {string} The name for the given id. + */ + nameById (id) { + return Profiler.nameById(id); + } + + /** + * Lookup or create an id for a frame name. + * @static + * @param {string} name The name to return an id for. + * @return {number} The id for the passed name. + */ + static idByName (name) { + if (typeof profilerNames[name] !== 'number') { + profilerNames[name] = nextId++; + } + return profilerNames[name]; + } + + /** + * Reverse lookup the name from a given frame id. + * @static + * @param {number} id The id to search for. + * @return {string} The name for the given id. + */ + static nameById (id) { + for (const name in profilerNames) { + if (profilerNames[name] === id) { + return name; + } + } + return null; + } + + /** + * Profiler is only available on platforms with the Performance API. + * @return {boolean} Can the Profiler run in this browser? + */ + static available () { + return ( + typeof window === 'object' && + typeof window.performance !== 'undefined'); + } +} + + +/** + * A reference to the START record id constant. + * @const {number} + */ +Profiler.START = START; + +/** + * A reference to the STOP record id constant. + * @const {number} + */ +Profiler.STOP = STOP; + +module.exports = Profiler; From 516d4f6f30daeb4aabfc378ecb225d2610f914f6 Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Thu, 9 Nov 2017 17:27:49 -0500 Subject: [PATCH 150/272] Add Profiler events to Runtime, Sequencer and execute --- src/engine/execute.js | 28 ++++++++++++++++ src/engine/runtime.js | 54 +++++++++++++++++++++++++++++++ src/engine/sequencer.js | 72 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+) diff --git a/src/engine/execute.js b/src/engine/execute.js index df9b5964b..07541c122 100644 --- a/src/engine/execute.js +++ b/src/engine/execute.js @@ -9,6 +9,18 @@ const {Map} = require('immutable'); */ const blockUtility = new BlockUtility(); +/** + * Profiler frame name for block functions. + * @const {string} + */ +const blockFunctionProfilerFrame = 'blockFunction'; + +/** + * Profiler frame ID for 'blockFunction'. + * @type {number} + */ +let blockFunctionProfilerId = -1; + /** * Utility function to determine if a value is a Promise. * @param {*} value Value to check for a Promise. @@ -207,7 +219,23 @@ const execute = function (sequencer, thread) { let primitiveReportedValue = null; blockUtility.sequencer = sequencer; blockUtility.thread = thread; + if (runtime.profiler !== null) { + if (blockFunctionProfilerId === -1) { + blockFunctionProfilerId = runtime.profiler.idByName(blockFunctionProfilerFrame); + } + // The method commented below has its code inlined underneath to reduce + // the bias recorded for the profiler's calls in this time sensitive + // execute function. + // + // runtime.profiler.start(blockFunctionProfilerId, opcode); + runtime.profiler.records.push( + runtime.profiler.START, blockFunctionProfilerId, opcode, performance.now()); + } primitiveReportedValue = blockFunction(argValues, blockUtility); + if (runtime.profiler !== null) { + // runtime.profiler.stop(blockFunctionProfilerId); + runtime.profiler.records.push(runtime.profiler.STOP, performance.now()); + } if (typeof primitiveReportedValue === 'undefined') { // No value reported - potentially a command block. diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 56fceadfc..3ba173718 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -79,6 +79,24 @@ const ScratchBlocksConstants = { OUTPUT_SHAPE_SQUARE: 3 }; +/** + * Numeric ID for Runtime._step in Profiler instances. + * @type {number} + */ +let stepProfilerId = -1; + +/** + * Numeric ID for Sequencer.stepThreads in Profiler instances. + * @type {number} + */ +let stepThreadsProfilerId = -1; + +/** + * Numeric ID for RenderWebGL.draw in Profiler instances. + * @type {number} + */ +let rendererDrawProfilerId = -1; + /** * Manages targets, scripts, and the sequencer. * @constructor @@ -234,6 +252,13 @@ class Runtime extends EventEmitter { keyboard: new Keyboard(this), mouse: new Mouse(this) }; + + /** + * A runtime profiler that records timed events for later playback to + * diagnose Scratch performance. + * @type {Profiler} + */ + this.profiler = null; } /** @@ -1055,6 +1080,12 @@ class Runtime extends EventEmitter { * inactive threads after each iteration. */ _step () { + if (this.profiler !== null) { + if (stepProfilerId === -1) { + stepProfilerId = this.profiler.idByName('Runtime._step'); + } + this.profiler.start(stepProfilerId); + } // Find all edge-activated hats, and add them to threads to be evaluated. for (const hatType in this._hats) { if (!this._hats.hasOwnProperty(hatType)) continue; @@ -1065,7 +1096,16 @@ class Runtime extends EventEmitter { } this.redrawRequested = false; this._pushMonitors(); + if (this.profiler !== null) { + if (stepThreadsProfilerId === -1) { + stepThreadsProfilerId = this.profiler.idByName('Sequencer.stepThreads'); + } + this.profiler.start(stepThreadsProfilerId); + } const doneThreads = this.sequencer.stepThreads(); + if (this.profiler !== null) { + this.profiler.stop(); + } this._updateGlows(doneThreads); // Add done threads so that even if a thread finishes within 1 frame, the green // flag will still indicate that a script ran. @@ -1074,7 +1114,16 @@ class Runtime extends EventEmitter { this._getMonitorThreadCount([...this.threads, ...doneThreads])); if (this.renderer) { // @todo: Only render when this.redrawRequested or clones rendered. + if (this.profiler !== null) { + if (rendererDrawProfilerId === -1) { + rendererDrawProfilerId = this.profiler.idByName('RenderWebGL.draw'); + } + this.profiler.start(rendererDrawProfilerId); + } this.renderer.draw(); + if (this.profiler !== null) { + this.profiler.stop(); + } } if (this._refreshTargets) { @@ -1086,6 +1135,11 @@ class Runtime extends EventEmitter { this.emit(Runtime.MONITORS_UPDATE, this._monitorState); this._prevMonitorState = this._monitorState; } + + if (this.profiler !== null) { + this.profiler.stop(); + this.profiler.reportFrames(); + } } /** diff --git a/src/engine/sequencer.js b/src/engine/sequencer.js index f4edc966c..0c796a6ea 100644 --- a/src/engine/sequencer.js +++ b/src/engine/sequencer.js @@ -2,6 +2,42 @@ const Timer = require('../util/timer'); const Thread = require('./thread'); const execute = require('./execute.js'); +/** + * Profiler frame name for stepping a single thread. + * @const {string} + */ +const stepThreadProfilerFrame = 'Sequencer.stepThread'; + +/** + * Profiler frame name for the inner loop of stepThreads. + * @const {string} + */ +const stepThreadsInnerProfilerFrame = 'Sequencer.stepThreads#inner'; + +/** + * Profiler frame name for execute. + * @const {string} + */ +const executeProfilerFrame = 'execute'; + +/** + * Profiler frame ID for stepThreadProfilerFrame. + * @type {number} + */ +let stepThreadProfilerId = -1; + +/** + * Profiler frame ID for stepThreadsInnerProfilerFrame. + * @type {number} + */ +let stepThreadsInnerProfilerId = -1; + +/** + * Profiler frame ID for executeProfilerFrame. + * @type {number} + */ +let executeProfilerId = -1; + class Sequencer { constructor (runtime) { /** @@ -47,6 +83,13 @@ class Sequencer { numActiveThreads > 0 && this.timer.timeElapsed() < WORK_TIME && (this.runtime.turboMode || !this.runtime.redrawRequested)) { + if (this.runtime.profiler !== null) { + if (stepThreadsInnerProfilerId === -1) { + stepThreadsInnerProfilerId = this.runtime.profiler.idByName(stepThreadsInnerProfilerFrame); + } + this.runtime.profiler.start(stepThreadsInnerProfilerId); + } + numActiveThreads = 0; // Attempt to run each thread one time. for (let i = 0; i < this.runtime.threads.length; i++) { @@ -69,7 +112,16 @@ class Sequencer { if (activeThread.status === Thread.STATUS_RUNNING || activeThread.status === Thread.STATUS_YIELD) { // Normal-mode thread: step. + if (this.runtime.profiler !== null) { + if (stepThreadProfilerId === -1) { + stepThreadProfilerId = this.runtime.profiler.idByName(stepThreadProfilerFrame); + } + this.runtime.profiler.start(stepThreadProfilerId); + } this.stepThread(activeThread); + if (this.runtime.profiler !== null) { + this.runtime.profiler.stop(); + } activeThread.warpTimer = null; if (activeThread.isKilled) { i--; // if the thread is removed from the list (killed), do not increase index @@ -82,6 +134,10 @@ class Sequencer { // We successfully ticked once. Prevents running STATUS_YIELD_TICK // threads on the next tick. ranFirstTick = true; + + if (this.runtime.profiler !== null) { + this.runtime.profiler.stop(); + } } // Filter inactive threads from `this.runtime.threads`. numActiveThreads = 0; @@ -129,7 +185,23 @@ class Sequencer { // Execute the current block. // Save the current block ID to notice if we did control flow. currentBlockId = thread.peekStack(); + if (this.runtime.profiler !== null) { + if (executeProfilerId === -1) { + executeProfilerId = this.runtime.profiler.idByName(executeProfilerFrame); + } + // The method commented below has its code inlined underneath to + // reduce the bias recorded for the profiler's calls in this + // time sensitive stepThread method. + // + // this.runtime.profiler.start(executeProfilerId, null); + this.runtime.profiler.records.push( + this.runtime.profiler.START, executeProfilerId, null, performance.now()); + } execute(this, thread); + if (this.runtime.profiler !== null) { + // this.runtime.profiler.stop(); + this.runtime.profiler.records.push(this.runtime.profiler.STOP, performance.now()); + } thread.blockGlowInFrame = currentBlockId; // If the thread has yielded or is waiting, yield to other threads. if (thread.status === Thread.STATUS_YIELD) { From f73dae828e4720cf237043d3af9565099d75481d Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Thu, 9 Nov 2017 17:28:40 -0500 Subject: [PATCH 151/272] Add enableProfiling and disableProfiling to Runtime --- src/engine/runtime.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 3ba173718..39be44db8 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -7,6 +7,7 @@ const Blocks = require('./blocks'); const BlockType = require('../extension-support/block-type'); const Sequencer = require('./sequencer'); const Thread = require('./thread'); +const Profiler = require('./profiler'); // Virtual I/O devices. const Clock = require('../io/clock'); @@ -1467,6 +1468,24 @@ class Runtime extends EventEmitter { this._step(); }, interval); } + + /** + * Turn on profiling. + * @param {Profiler/FrameCallback} onFrame A callback handle passed a + * profiling frame when the profiler reports its collected data. + */ + enableProfiling (onFrame) { + if (Profiler.available()) { + this.profiler = new Profiler(onFrame); + } + } + + /** + * Turn off profiling. + */ + disableProfiling () { + this.profiler = null; + } } /** From ff82699440226d09fcab109e3ac4a5d439a6400b Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Thu, 9 Nov 2017 18:33:15 -0500 Subject: [PATCH 152/272] Add Block % stats panel Enable profiler when Block % is visible and display percent of time block functions get to execute versus drawing and any overhead. --- src/playground/playground.js | 67 ++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/src/playground/playground.js b/src/playground/playground.js index 321afb151..995502d7a 100644 --- a/src/playground/playground.js +++ b/src/playground/playground.js @@ -40,6 +40,72 @@ const getAssetUrl = function (asset) { return assetUrlParts.join(''); }; +const addProfilerPanels = function ( + stats, vm, panelName = 'BLK%', panelFg = '#fff', panelBg = '#111') { + + vm.runtime.enableProfiling(); + if (vm.runtime.profiler === null) { + // Profiler isn't available on the local system. + return; + } + + const blockPercentPanel = stats.addPanel(new window.Stats.Panel(panelName, panelFg, panelBg)); + + // Store the profiler reference for later. + const profiler = vm.runtime.profiler; + // Set profiler to null to disable profiling until later. + vm.runtime.profiler = null; + + const stepThreadsProfilerId = profiler.idByName('Sequencer.stepThreads'); + const blockFunctionProfilerId = profiler.idByName('blockFunction'); + + let blockFunctionTime = 0; + const stepValues = []; + let lastUpdate = Date.now(); + + // Collect time used by `blockFunction` calls in `execute` and add a column + // to the stats graph of the average for the last second of recordings. + profiler.onFrame = function ({id, totalTime}) { + if (id === stepThreadsProfilerId && totalTime > 0) { + // This frame wraps Sequencer.stepThreads. + + // Push the most recently summed blockFunctionTime. + stepValues.push(blockFunctionTime / totalTime * 100); + // Every second, average the pushed values and render that as a new + // column in the stats graph. + if (Date.now() - lastUpdate > 1000) { + lastUpdate = Date.now(); + const average = stepValues.reduce( + (a, b) => a + b, + 0) / stepValues.length; + blockPercentPanel.update(average, 100); + stepValues.length = 0; + } + blockFunctionTime = 0; + } else if (id === blockFunctionProfilerId) { + // This frame wraps around each blockFunction call. + blockFunctionTime += totalTime; + } + }; + + // Set the stats panel to not display by default. + blockPercentPanel.dom.style.display = 'none'; + + // When the parent of the stats graphs is clicked, check if the + // blockPercentPanel is visible. If it is visible, enable profiling by + // setting the runtime's profiler to the stored Profiler instance. If it is + // not visible, disable profiling by setting the profiler to null. + stats.dom.addEventListener('click', () => { + if (blockPercentPanel.dom.style.display === 'block') { + vm.runtime.profiler = profiler; + } else { + vm.runtime.profiler = null; + } + }); + + return blockPercentPanel; +}; + window.onload = function () { // Lots of global variables to make debugging easier // Instantiate the VM. @@ -99,6 +165,7 @@ window.onload = function () { const stats = new window.Stats(); document.getElementById('tab-renderexplorer').appendChild(stats.dom); stats.dom.style.position = 'relative'; + addProfilerPanels(stats, vm, 'BLK%', '#fff', '#111'); stats.begin(); // Playground data tabs. From 75ec76cd57f7c14fbbf0782f69fa08e04a4e3fb9 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 14 Nov 2017 14:58:16 -0500 Subject: [PATCH 153/272] Fix unit test --- src/extensions/scratch3_music/index.js | 2 ++ test/unit/blocks_music.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index 484820054..8e80dcaaf 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -68,6 +68,8 @@ class Scratch3MusicBlocks { * @return {Promise} - a promise which will resolve once the sound has loaded. */ _loadSound (fileName, index, bufferArray) { + if (!this.runtime.storage) return; + if (!this.runtime.audioEngine) return; return this.runtime.storage.load(this.runtime.storage.AssetType.Sound, fileName, 'mp3') .then(soundAsset => this.runtime.audioEngine.audioContext.decodeAudioData(soundAsset.data.buffer) diff --git a/test/unit/blocks_music.js b/test/unit/blocks_music.js index ae097beb1..66c950836 100644 --- a/test/unit/blocks_music.js +++ b/test/unit/blocks_music.js @@ -1,5 +1,5 @@ const test = require('tap').test; -const Music = require('../../src/blocks/scratch3_music'); +const Music = require('../../src/extensions/scratch3_music/index.js'); let playedDrum; let playedInstrument; const runtime = { From 01e9000c04b41db9fd0b5d8f87e5d670e1ef90bc Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 14 Nov 2017 15:00:20 -0500 Subject: [PATCH 154/272] JSDoc for _playDrumNum --- src/extensions/scratch3_music/index.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index 8e80dcaaf..ab461441f 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -452,6 +452,12 @@ class Scratch3MusicBlocks { } } + /** + * Play a drum sound using its 0-indexed number. + * @param {object} util - utility object provided by the runtime. + * @param {number} drumNum - the number of the drum to play. + * @private + */ _playDrumNum (util, drumNum) { if (util.target.audioPlayer === null) return; if (this._drumConcurrencyCounter > Scratch3MusicBlocks.CONCURRENCY_LIMIT) { From 757dccd565ecc3367e5f637910b4e48e91aae24b Mon Sep 17 00:00:00 2001 From: DD Date: Tue, 14 Nov 2017 18:25:54 -0500 Subject: [PATCH 155/272] Move is sprite specific verification into VM in a temporary way. Remove monitors when their sprites are deleted. --- src/engine/blocks.js | 1 + src/engine/execute.js | 4 ++++ src/engine/monitor-record.js | 2 ++ src/engine/runtime.js | 9 +++++++++ src/virtual-machine.js | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 52 insertions(+) diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 7564d3ca9..155a2e5e8 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -334,6 +334,7 @@ class Blocks { optRuntime.requestAddMonitor(MonitorRecord({ // @todo(vm#564) this will collide if multiple sprites use same block id: block.id, + targetId: block.targetId, spriteName: block.targetId ? optRuntime.getTargetById(block.targetId).getName() : null, opcode: block.opcode, params: this._getBlockParams(block), diff --git a/src/engine/execute.js b/src/engine/execute.js index fe1688e6a..bbacca951 100644 --- a/src/engine/execute.js +++ b/src/engine/execute.js @@ -69,6 +69,10 @@ const handleReport = function ( } if (thread.updateMonitor) { const targetId = sequencer.runtime.monitorBlocks.getBlock(currentBlockId).targetId; + if (targetId && !sequencer.runtime.getTargetById(targetId)) { + // Target no longer exists + return; + } sequencer.runtime.requestUpdateMonitor(Map({ id: currentBlockId, spriteName: targetId ? sequencer.runtime.getTargetById(targetId).getName() : null, diff --git a/src/engine/monitor-record.js b/src/engine/monitor-record.js index 40e67c5e7..d42b878f5 100644 --- a/src/engine/monitor-record.js +++ b/src/engine/monitor-record.js @@ -4,6 +4,8 @@ const MonitorRecord = Record({ id: null, /** Present only if the monitor is sprite-specific, such as x position */ spriteName: null, + /** Present only if the monitor is sprite-specific, such as x position */ + targetId: null, opcode: null, value: null, params: null diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 06d068bcd..6d650668e 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -1287,6 +1287,15 @@ class Runtime extends EventEmitter { this._monitorState = this._monitorState.delete(monitorId); } + /** + * Removes all monitors with the given target ID from the state. Does nothing if + * the monitor already does not exist in the state. + * @param {!string} targetId Remove all monitors with given target ID. + */ + requestRemoveMonitorByTargetId (targetId) { + this._monitorState = this._monitorState.filterNot(value => value.targetId === targetId); + } + /** * Get a target by its id. * @param {string} targetId Id of target to find. diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 6dfc7acad..175b5fd20 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -484,6 +484,7 @@ class VirtualMachine extends EventEmitter { if (!sprite) { throw new Error('No sprite associated with this target.'); } + this.runtime.requestRemoveMonitorByTargetId(targetId); const currentEditingTarget = this.editingTarget; for (let i = 0; i < sprite.clones.length; i++) { const clone = sprite.clones[i]; @@ -574,9 +575,44 @@ class VirtualMachine extends EventEmitter { * @param {!Blockly.Event} e Any Blockly event. */ monitorBlockListener (e) { + const tempMonitoredBlocks = [ + 'volume', + 'tempo', + 'answer', + 'loudness', + 'videoon', + 'timer', + 'of', + 'current', + 'username', + 'xposition', + 'yposition', + 'direction', + 'size', + 'backdropname', + 'costumeorder', + 'backdroporder' + ]; + const tempMonitoredPerSpriteBlocks = [ + 'xposition', + 'yposition', + 'direction', + 'size', + 'costumeorder' + ]; // Filter events by type, since monitor blocks only need to listen to these events. // Monitor blocks shouldn't be destroyed when flyout blocks are deleted. if (['create', 'change'].indexOf(e.type) !== -1) { + // TEMPORARY ---- + let blockType = e.blockId.split('_'); + blockType = blockType[blockType.length - 1]; + if (tempMonitoredBlocks.indexOf(blockType) === -1) { + return; + } + if (tempMonitoredPerSpriteBlocks.indexOf(blockType) !== -1) { + e.isSpriteSpecific = true; + } + // ----- this.runtime.monitorBlocks.blocklyListen(e, this.runtime); } } From fe86e38210e7487e2d51c5a41416fc4d8dee59ea Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Wed, 15 Nov 2017 09:17:20 -0500 Subject: [PATCH 156/272] Addressing PR review comments. --- src/engine/variable.js | 2 ++ src/serialization/sb2.js | 2 +- src/serialization/sb2_specmap.js | 32 +++++++++++++++++--------------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/engine/variable.js b/src/engine/variable.js index 5896e593b..d75c0b826 100644 --- a/src/engine/variable.js +++ b/src/engine/variable.js @@ -36,6 +36,8 @@ class Variable { /** * Type representation for scalar variables. + * This is currently represented as '' + * for compatibility with blockly. * @const {string} */ static get SCALAR_TYPE () { diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js index f7b7b30da..c6590fc82 100644 --- a/src/serialization/sb2.js +++ b/src/serialization/sb2.js @@ -255,7 +255,7 @@ const parseScratchObject = function (object, runtime, extensions, topLevel) { getVariableId(list.listName), list.listName, Variable.LIST_TYPE, - list.isPersistent + false ); newVariable.value = list.contents; target.variables[newVariable.id] = newVariable; diff --git a/src/serialization/sb2_specmap.js b/src/serialization/sb2_specmap.js index c7de538e9..7e9901e00 100644 --- a/src/serialization/sb2_specmap.js +++ b/src/serialization/sb2_specmap.js @@ -22,6 +22,8 @@ * Finally, I filled in the expected arguments as below. */ +const Variable = require('../engine/variable'); + /** * @typedef {object} SB2SpecMap_blockInfo * @property {string} opcode - the Scratch 3.0 block opcode. Use 'extensionID.opcode' for extension opcodes. @@ -1202,7 +1204,7 @@ const specMap = { { type: 'field', fieldName: 'VARIABLE', - variableType: '' + variableType: Variable.SCALAR_TYPE } ] }, @@ -1212,7 +1214,7 @@ const specMap = { { type: 'field', fieldName: 'VARIABLE', - variableType: '' + variableType: Variable.SCALAR_TYPE }, { type: 'input', @@ -1227,7 +1229,7 @@ const specMap = { { type: 'field', fieldName: 'VARIABLE', - variableType: '' + variableType: Variable.SCALAR_TYPE }, { type: 'input', @@ -1242,7 +1244,7 @@ const specMap = { { type: 'field', fieldName: 'VARIABLE', - variableType: '' + variableType: Variable.SCALAR_TYPE } ] }, @@ -1252,7 +1254,7 @@ const specMap = { { type: 'field', fieldName: 'VARIABLE', - variableType: '' + variableType: Variable.SCALAR_TYPE } ] }, @@ -1262,7 +1264,7 @@ const specMap = { { type: 'field', fieldName: 'LIST', - variableType: 'list' + variableType: Variable.LIST_TYPE } ] }, @@ -1277,7 +1279,7 @@ const specMap = { { type: 'field', fieldName: 'LIST', - variableType: 'list' + variableType: Variable.LIST_TYPE } ] }, @@ -1292,7 +1294,7 @@ const specMap = { { type: 'field', fieldName: 'LIST', - variableType: 'list' + variableType: Variable.LIST_TYPE } ] }, @@ -1312,7 +1314,7 @@ const specMap = { { type: 'field', fieldName: 'LIST', - variableType: 'list' + variableType: Variable.LIST_TYPE } ] }, @@ -1327,7 +1329,7 @@ const specMap = { { type: 'field', fieldName: 'LIST', - variableType: 'list' + variableType: Variable.LIST_TYPE }, { type: 'input', @@ -1347,7 +1349,7 @@ const specMap = { { type: 'field', fieldName: 'LIST', - variableType: 'list' + variableType: Variable.LIST_TYPE } ] }, @@ -1357,7 +1359,7 @@ const specMap = { { type: 'field', fieldName: 'LIST', - variableType: 'list' + variableType: Variable.LIST_TYPE } ] }, @@ -1367,7 +1369,7 @@ const specMap = { { type: 'field', fieldName: 'LIST', - variableType: 'list' + variableType: Variable.LIST_TYPE }, { type: 'input', @@ -1382,7 +1384,7 @@ const specMap = { { type: 'field', fieldName: 'LIST', - variableType: 'list' + variableType: Variable.LIST_TYPE } ] }, @@ -1392,7 +1394,7 @@ const specMap = { { type: 'field', fieldName: 'LIST', - variableType: 'list' + variableType: Variable.LIST_TYPE } ] }, From aa0064948a0a9435fb38281daa64efa6a94cd230 Mon Sep 17 00:00:00 2001 From: DD Date: Wed, 15 Nov 2017 11:34:20 -0500 Subject: [PATCH 157/272] Delete monitor block when variable is deleted --- src/engine/blocks.js | 20 +++++++++----------- src/engine/target.js | 1 + test/unit/engine_blocks.js | 12 +++--------- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 92a2d58e7..11208bea9 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -250,9 +250,7 @@ class Blocks { if (optRuntime && this._blocks[e.blockId].topLevel) { optRuntime.quietGlow(e.blockId); } - this.deleteBlock({ - id: e.blockId - }); + this.deleteBlock(e.blockId); break; case 'var_create': // New variables being created by the user are all global. @@ -414,37 +412,37 @@ class Blocks { /** * Block management: delete blocks and their associated scripts. - * @param {!object} e Blockly delete event to be processed. + * @param {!string} blockId Id of block to delete */ - deleteBlock (e) { + deleteBlock (blockId) { // @todo In runtime, stop threads running on this script. // Get block - const block = this._blocks[e.id]; + const block = this._blocks[blockId]; // Delete children if (block.next !== null) { - this.deleteBlock({id: block.next}); + this.deleteBlock(block.next); } // Delete inputs (including branches) for (const input in block.inputs) { // If it's null, the block in this input moved away. if (block.inputs[input].block !== null) { - this.deleteBlock({id: block.inputs[input].block}); + this.deleteBlock(block.inputs[input].block); } // Delete obscured shadow blocks. if (block.inputs[input].shadow !== null && block.inputs[input].shadow !== block.inputs[input].block) { - this.deleteBlock({id: block.inputs[input].shadow}); + this.deleteBlock(block.inputs[input].shadow); } } // Delete any script starting with this block. - this._deleteScript(e.id); + this._deleteScript(blockId); // Delete block itself. - delete this._blocks[e.id]; + delete this._blocks[blockId]; } // --------------------------------------------------------------------- diff --git a/src/engine/target.js b/src/engine/target.js index 2a6be81a6..b94c221bc 100644 --- a/src/engine/target.js +++ b/src/engine/target.js @@ -189,6 +189,7 @@ class Target extends EventEmitter { if (this.variables.hasOwnProperty(id)) { delete this.variables[id]; if (this.runtime) { + this.runtime.monitorBlocks.deleteBlock(id); this.runtime.requestRemoveMonitor(id); } } diff --git a/test/unit/engine_blocks.js b/test/unit/engine_blocks.js index 1055cda68..4353fe476 100644 --- a/test/unit/engine_blocks.js +++ b/test/unit/engine_blocks.js @@ -421,9 +421,7 @@ test('delete', t => { inputs: {}, topLevel: true }); - b.deleteBlock({ - id: 'foo' - }); + b.deleteBlock('foo'); t.type(b._blocks.foo, 'undefined'); t.equal(b._scripts.indexOf('foo'), -1); @@ -458,9 +456,7 @@ test('delete chain', t => { inputs: {}, topLevel: false }); - b.deleteBlock({ - id: 'foo' - }); + b.deleteBlock('foo'); t.type(b._blocks.foo, 'undefined'); t.type(b._blocks.foo2, 'undefined'); t.type(b._blocks.foo3, 'undefined'); @@ -531,9 +527,7 @@ test('delete inputs', t => { inputs: {}, topLevel: false }); - b.deleteBlock({ - id: 'foo' - }); + b.deleteBlock('foo'); t.type(b._blocks.foo, 'undefined'); t.type(b._blocks.foo2, 'undefined'); t.type(b._blocks.foo3, 'undefined'); From c8d5ba1d5e19271f6eff498c20f95973df34de6a Mon Sep 17 00:00:00 2001 From: DD Date: Wed, 15 Nov 2017 11:55:22 -0500 Subject: [PATCH 158/272] Delete block does nothing if the block doesnt exist --- src/engine/blocks.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 11208bea9..fe6b11602 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -411,7 +411,8 @@ class Blocks { } /** - * Block management: delete blocks and their associated scripts. + * Block management: delete blocks and their associated scripts. Does nothing if a block + * with the given ID does not exist. * @param {!string} blockId Id of block to delete */ deleteBlock (blockId) { @@ -419,6 +420,10 @@ class Blocks { // Get block const block = this._blocks[blockId]; + if (!block) { + // No block with the given ID exists + return; + } // Delete children if (block.next !== null) { From ba529ad50b19b178431f6bd2379160957eeaca0d Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Wed, 15 Nov 2017 14:10:50 -0500 Subject: [PATCH 159/272] Update unit test --- test/unit/blocks_music.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/unit/blocks_music.js b/test/unit/blocks_music.js index 66c950836..b9e3c8afc 100644 --- a/test/unit/blocks_music.js +++ b/test/unit/blocks_music.js @@ -4,7 +4,6 @@ let playedDrum; let playedInstrument; const runtime = { audioEngine: { - numDrums: 3, numInstruments: 3, instrumentPlayer: { loadInstrument: instrument => (playedInstrument = instrument) @@ -12,13 +11,14 @@ const runtime = { } }; const blocks = new Music(runtime); +blocks._playDrumNum = (util, drum) => (playedDrum = drum); + const util = { + stackFrame: Object.create(null), target: { - audioPlayer: { - playDrumForBeats: drum => (playedDrum = drum) - } + audioPlayer: null }, - stackFrame: Object.create(null) + yield: () => null }; test('playDrum uses 1-indexing and wrap clamps', t => { @@ -26,7 +26,7 @@ test('playDrum uses 1-indexing and wrap clamps', t => { blocks.playDrumForBeats(args, util); t.strictEqual(playedDrum, 0); - args = {DRUM: runtime.audioEngine.numDrums + 1}; + args = {DRUM: blocks.DRUM_INFO.length + 1}; blocks.playDrumForBeats(args, util); t.strictEqual(playedDrum, 0); From 0958db2618705512dfe9172fc206a5fee6e6edd2 Mon Sep 17 00:00:00 2001 From: DD Date: Wed, 15 Nov 2017 17:53:43 -0500 Subject: [PATCH 160/272] Move data to blocks files --- src/blocks/scratch3_looks.js | 9 +++++++++ src/blocks/scratch3_motion.js | 8 ++++++++ src/blocks/scratch3_sensing.js | 10 ++++++++++ src/blocks/scratch3_sound.js | 6 ++++++ src/engine/runtime.js | 26 ++++++++++++++++++++++++++ src/virtual-machine.js | 32 +++----------------------------- 6 files changed, 62 insertions(+), 29 deletions(-) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index 70238a786..a64f095b0 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -242,6 +242,15 @@ class Scratch3LooksBlocks { }; } + getMonitored () { + return { + size: {isSpriteSpecific: true}, + costumeorder: {isSpriteSpecific: true}, + backdroporder: {}, + backdropname: {} + }; + } + say (args, util) { // @TODO in 2.0 calling say/think resets the right/left bias of the bubble this._updateBubble(util.target, 'say', String(args.MESSAGE)); diff --git a/src/blocks/scratch3_motion.js b/src/blocks/scratch3_motion.js index d040337c8..b30138d3e 100644 --- a/src/blocks/scratch3_motion.js +++ b/src/blocks/scratch3_motion.js @@ -38,6 +38,14 @@ class Scratch3MotionBlocks { }; } + getMonitored () { + return { + xposition: {isSpriteSpecific: true}, + yposition: {isSpriteSpecific: true}, + direction: {isSpriteSpecific: true} + }; + } + moveSteps (args, util) { const steps = Cast.toNumber(args.STEPS); const radians = MathUtil.degToRad(90 - util.target.direction); diff --git a/src/blocks/scratch3_sensing.js b/src/blocks/scratch3_sensing.js index 17dc87e9d..d51dd5d3b 100644 --- a/src/blocks/scratch3_sensing.js +++ b/src/blocks/scratch3_sensing.js @@ -49,6 +49,16 @@ class Scratch3SensingBlocks { }; } + getMonitored () { + return { + answer: {}, + loudness: {}, + timer: {}, + of: {}, + current: {} + }; + } + _onAnswer (answer) { this._answer = answer; const questionObj = this._questionList.shift(); diff --git a/src/blocks/scratch3_sound.js b/src/blocks/scratch3_sound.js index 6f5fed972..d3f3f92ac 100644 --- a/src/blocks/scratch3_sound.js +++ b/src/blocks/scratch3_sound.js @@ -103,6 +103,12 @@ class Scratch3SoundBlocks { }; } + getMonitored () { + return { + volume: {} + }; + } + playSound (args, util) { const index = this._getSoundIndex(args.SOUND_MENU, util); if (index >= 0) { diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 6d650668e..d8fa88358 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -176,6 +176,13 @@ class Runtime extends EventEmitter { */ this._refreshTargets = false; + /** + * Map to look up all monitor block information by opcode. + * @type {object} + * @private + */ + this.monitorBlockInfo = {}; + /** * Ordered map of all monitors, which are MonitorReporter objects. */ @@ -225,6 +232,9 @@ class Runtime extends EventEmitter { // Register all given block packages. this._registerBlockPackages(); + // Populate monitorBlockInfo + this._registerMonitorInfo(); + // Register and initialize "IO devices", containers for processing // I/O related data. /** @type {Object.} */ @@ -451,6 +461,22 @@ class Runtime extends EventEmitter { this.emit(Runtime.EXTENSION_ADDED, categoryInfo.blocks.concat(categoryInfo.menus)); } + /** + * Populate this.monitorBlockInfo + */ + _registerMonitorInfo () { + for (const packageName in defaultBlockPackages) { + if (defaultBlockPackages.hasOwnProperty(packageName)) { + // @todo pass a different runtime depending on package privilege? + const packageObject = new (defaultBlockPackages[packageName])(this); + // Collect monitored from package. + if (packageObject.getMonitored) { + this.monitorBlockInfo = Object.assign({}, this.monitorBlockInfo, packageObject.getMonitored()); + } + } + } + } + /** * Build the scratch-blocks JSON for a menu. Note that scratch-blocks treats menus as a special kind of block. * @param {string} menuName - the name of the menu diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 175b5fd20..5c5361bae 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -575,44 +575,18 @@ class VirtualMachine extends EventEmitter { * @param {!Blockly.Event} e Any Blockly event. */ monitorBlockListener (e) { - const tempMonitoredBlocks = [ - 'volume', - 'tempo', - 'answer', - 'loudness', - 'videoon', - 'timer', - 'of', - 'current', - 'username', - 'xposition', - 'yposition', - 'direction', - 'size', - 'backdropname', - 'costumeorder', - 'backdroporder' - ]; - const tempMonitoredPerSpriteBlocks = [ - 'xposition', - 'yposition', - 'direction', - 'size', - 'costumeorder' - ]; // Filter events by type, since monitor blocks only need to listen to these events. // Monitor blocks shouldn't be destroyed when flyout blocks are deleted. if (['create', 'change'].indexOf(e.type) !== -1) { - // TEMPORARY ---- let blockType = e.blockId.split('_'); blockType = blockType[blockType.length - 1]; - if (tempMonitoredBlocks.indexOf(blockType) === -1) { + if (!this.runtime.monitorBlockInfo.hasOwnProperty(blockType)) { return; } - if (tempMonitoredPerSpriteBlocks.indexOf(blockType) !== -1) { + if (!this.runtime.monitorBlockInfo.hasOwnProperty(blockType) || + this.runtime.monitorBlockInfo[blockType].isSpriteSpecific) { e.isSpriteSpecific = true; } - // ----- this.runtime.monitorBlocks.blocklyListen(e, this.runtime); } } From 9864403bc977ae212b227ae55d1b384fa07949b6 Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Tue, 7 Nov 2017 14:15:53 -0500 Subject: [PATCH 161/272] A thread in the runtime but with the DONE status is not active return false from isActiveThread if thread's status is done even when its contained in the runtime threads list. As it is done, the thread will not be run until either its replaced by a new copy of the thread or the thread is removed from the list and another is added at a later time. --- src/engine/runtime.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 39be44db8..bd1e4a90b 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -825,7 +825,11 @@ class Runtime extends EventEmitter { * @return {boolean} True if the thread is active/running. */ isActiveThread (thread) { - return this.threads.indexOf(thread) > -1; + return ( + ( + thread.stack.length > 0 && + thread.status !== Thread.STATUS_DONE) && + this.threads.indexOf(thread) > -1); } /** From 3d9255345986209c8b885b55b983bbb39224d9ea Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Tue, 7 Nov 2017 14:22:20 -0500 Subject: [PATCH 162/272] Return restarted threads in list from startHats Add restarted threads to the list of newThreads returned by startHats. --- src/engine/runtime.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index bd1e4a90b..2f34cd8d0 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -804,6 +804,7 @@ class Runtime extends EventEmitter { * This is used by `startHats` to and is necessary to ensure 2.0-like execution order. * Test project: https://scratch.mit.edu/projects/130183108/ * @param {!Thread} thread Thread object to restart. + * @return {Thread} The restarted thread. */ _restartThread (thread) { const newThread = new Thread(thread.topBlock); @@ -814,9 +815,10 @@ class Runtime extends EventEmitter { const i = this.threads.indexOf(thread); if (i > -1) { this.threads[i] = newThread; - } else { - this.threads.push(thread); + return newThread; } + this.threads.push(thread); + return thread; } /** @@ -976,7 +978,7 @@ class Runtime extends EventEmitter { if (instance.threads[i].topBlock === topBlockId && !instance.threads[i].stackClick && // stack click threads and hat threads can coexist instance.threads[i].target === target) { - instance._restartThread(instance.threads[i]); + newThreads.push(instance._restartThread(instance.threads[i])); return; } } From d173326290e592c79f006a97f36db5a62c441a26 Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Thu, 16 Nov 2017 11:21:51 -0500 Subject: [PATCH 163/272] Add broadcastAndWait regression test --- test/unit/blocks_event.js | 94 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 test/unit/blocks_event.js diff --git a/test/unit/blocks_event.js b/test/unit/blocks_event.js new file mode 100644 index 000000000..2e62125b6 --- /dev/null +++ b/test/unit/blocks_event.js @@ -0,0 +1,94 @@ +const test = require('tap').test; + +const Blocks = require('../../src/engine/blocks'); +const BlockUtility = require('../../src/engine/block-utility'); +const Event = require('../../src/blocks/scratch3_event'); +const Runtime = require('../../src/engine/runtime'); +const Target = require('../../src/engine/target'); +const Thread = require('../../src/engine/thread'); + +test('#760 - broadcastAndWait', t => { + const broadcastAndWaitBlock = { + id: 'broadcastAndWaitBlock', + fields: { + BROADCAST_OPTION: { + id: 'BROADCAST_OPTION', + value: 'message' + } + }, + inputs: Object, + block: 'fakeBlock', + opcode: 'event_broadcastandwait', + next: null, + parent: null, + shadow: false, + topLevel: true, + x: 0, + y: 0 + }; + const receiveMessageBlock = { + id: 'receiveMessageBlock', + fields: { + BROADCAST_OPTION: { + id: 'BROADCAST_OPTION', + value: 'message' + } + }, + inputs: Object, + block: 'fakeBlock', + opcode: 'event_whenbroadcastreceived', + next: null, + parent: null, + shadow: false, + topLevel: true, + x: 0, + y: 0 + }; + + const rt = new Runtime(); + const e = new Event(rt); + const b = new Blocks(); + b.createBlock(broadcastAndWaitBlock); + b.createBlock(receiveMessageBlock); + const tgt = new Target(rt, b); + rt.targets.push(tgt); + + let th = rt._pushThread('broadcastAndWaitBlock', t); + const util = new BlockUtility(); + util.sequencer = rt.sequencer; + util.thread = th; + + // creates threads + e.broadcastAndWait({BROADCAST_OPTION: 'message'}, util); + t.strictEqual(rt.threads.length, 2); + t.strictEqual(rt.threads[1].topBlock, 'receiveMessageBlock'); + // yields when some thread is active + t.strictEqual(th.status, Thread.STATUS_YIELD); + th.status = Thread.STATUS_RUNNING; + e.broadcastAndWait({BROADCAST_OPTION: 'message'}, util); + t.strictEqual(th.status, Thread.STATUS_YIELD); + // does not yield once all threads are done + th.status = Thread.STATUS_RUNNING; + rt.threads[1].status = Thread.STATUS_DONE; + e.broadcastAndWait({BROADCAST_OPTION: 'message'}, util); + t.strictEqual(th.status, Thread.STATUS_RUNNING); + + // restarts done threads that are in runtime threads + th = rt._pushThread('broadcastAndWaitBlock', tgt); + util.thread = th; + e.broadcastAndWait({BROADCAST_OPTION: 'message'}, util); + t.strictEqual(rt.threads.length, 3); + t.strictEqual(rt.threads[1].status, Thread.STATUS_RUNNING); + t.strictEqual(th.status, Thread.STATUS_YIELD); + // yields when some restarted thread is active + th.status = Thread.STATUS_RUNNING; + e.broadcastAndWait({BROADCAST_OPTION: 'message'}, util); + t.strictEqual(th.status, Thread.STATUS_YIELD); + // does not yield once all threads are done + th.status = Thread.STATUS_RUNNING; + rt.threads[1].status = Thread.STATUS_DONE; + e.broadcastAndWait({BROADCAST_OPTION: 'message'}, util); + t.strictEqual(th.status, Thread.STATUS_RUNNING); + + t.end(); +}); From 34dfbb50baf0dcc6eea58860f25e84139765d4d3 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 16 Nov 2017 14:17:08 -0500 Subject: [PATCH 164/272] Update naming and implementation for custom procedure blocks --- src/blocks/scratch3_procedures.js | 13 +++++++------ src/engine/blocks.js | 5 ++--- src/engine/thread.js | 4 ++-- src/serialization/sb2.js | 18 ++++++++++-------- src/serialization/sb2_specmap.js | 14 ++++++++++---- test/unit/engine_sequencer.js | 6 +++--- test/unit/engine_thread.js | 4 ++-- 7 files changed, 36 insertions(+), 28 deletions(-) diff --git a/src/blocks/scratch3_procedures.js b/src/blocks/scratch3_procedures.js index b91630f12..22e2f788f 100644 --- a/src/blocks/scratch3_procedures.js +++ b/src/blocks/scratch3_procedures.js @@ -13,17 +13,18 @@ class Scratch3ProcedureBlocks { */ getPrimitives () { return { - procedures_defnoreturn: this.defNoReturn, - procedures_callnoreturn: this.callNoReturn, - procedures_param: this.param + procedures_definition: this.definition, + procedures_call: this.call, + argument_reporter_string_number: this.param, + argument_reporter_boolean: this.param }; } - defNoReturn () { + definition () { // No-op: execute the blocks. } - callNoReturn (args, util) { + call (args, util) { if (!util.stackFrame.executed) { const procedureCode = args.mutation.proccode; const paramNames = util.getProcedureParamNames(procedureCode); @@ -47,7 +48,7 @@ class Scratch3ProcedureBlocks { } param (args, util) { - const value = util.getParam(args.mutation.paramname); + const value = util.getParam(args.VALUE); return value; } } diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 92a2d58e7..1aa97d28d 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -152,8 +152,7 @@ class Blocks { for (const id in this._blocks) { if (!this._blocks.hasOwnProperty(id)) continue; const block = this._blocks[id]; - if (block.opcode === 'procedures_defnoreturn' || - block.opcode === 'procedures_defreturn') { + if (block.opcode === 'procedures_definition') { const internal = this._getCustomBlockInternal(block); if (internal && internal.mutation.proccode === name) { return id; // The outer define block id @@ -172,7 +171,7 @@ class Blocks { for (const id in this._blocks) { if (!this._blocks.hasOwnProperty(id)) continue; const block = this._blocks[id]; - if (block.opcode === 'procedures_callnoreturn_internal' && + if (block.opcode === 'procedures_prototype' && block.mutation.proccode === name) { return JSON.parse(block.mutation.argumentnames); } diff --git a/src/engine/thread.js b/src/engine/thread.js index 3b8ce32bd..def1fc1ef 100644 --- a/src/engine/thread.js +++ b/src/engine/thread.js @@ -164,7 +164,7 @@ class Thread { let blockID = this.peekStack(); while (blockID !== null) { const block = this.target.blocks.getBlock(blockID); - if (typeof block !== 'undefined' && block.opcode === 'procedures_callnoreturn') { + if (typeof block !== 'undefined' && block.opcode === 'procedures_call') { break; } this.popStack(); @@ -271,7 +271,7 @@ class Thread { const sp = this.stack.length - 1; for (let i = sp - 1; i >= 0; i--) { const block = this.target.blocks.getBlock(this.stack[i]); - if (block.opcode === 'procedures_callnoreturn' && + if (block.opcode === 'procedures_call' && block.mutation.proccode === procedureCode) { return true; } diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js index 2a54d40a7..16b63da88 100644 --- a/src/serialization/sb2.js +++ b/src/serialization/sb2.js @@ -518,7 +518,7 @@ const parseBlock = function (sb2block, getVariableId, extensions) { }; activeBlock.children = [{ id: inputUid, - opcode: 'procedures_callnoreturn_internal', + opcode: 'procedures_prototype', inputs: {}, fields: {}, next: null, @@ -544,13 +544,15 @@ const parseBlock = function (sb2block, getVariableId, extensions) { argumentids: JSON.stringify(parseProcedureArgIds(sb2block[1])) }; } else if (oldOpcode === 'getParam') { - // Mutation for procedure parameter. - activeBlock.mutation = { - tagName: 'mutation', - children: [], - paramname: sb2block[1], // Name of parameter. - shape: sb2block[2] // Shape - in 2.0, 'r' or 'b'. - }; + // Assign correct opcode based on the block shape. + switch (sb2block[2]) { + case 'r': + activeBlock.opcode = 'argument_reporter_string_number'; + break; + case 'b': + activeBlock.opcode = 'argument_reporter_boolean'; + break; + } } return activeBlock; }; diff --git a/src/serialization/sb2_specmap.js b/src/serialization/sb2_specmap.js index b511d59c8..70bb0345c 100644 --- a/src/serialization/sb2_specmap.js +++ b/src/serialization/sb2_specmap.js @@ -1382,15 +1382,21 @@ const specMap = { ] }, 'procDef': { - opcode: 'procedures_defnoreturn', + opcode: 'procedures_definition', argMap: [] }, 'getParam': { - opcode: 'procedures_param', - argMap: [] + // Doesn't map to single opcode. Import step assigns final correct opcode. + opcode: 'argument_reporter_string_number', + argMap: [ + { + type: 'field', + fieldName: 'VALUE' + } + ] }, 'call': { - opcode: 'procedures_callnoreturn', + opcode: 'procedures_call', argMap: [] } }; diff --git a/test/unit/engine_sequencer.js b/test/unit/engine_sequencer.js index abf7102d2..751e9bb64 100644 --- a/test/unit/engine_sequencer.js +++ b/test/unit/engine_sequencer.js @@ -36,7 +36,7 @@ const generateBlock = function (id) { block: 'fakeBlock', name: 'fakeName', next: null, - opcode: 'procedures_defnoreturn', + opcode: 'procedures_definition', mutation: {proccode: 'fakeCode'}, parent: null, shadow: false, @@ -55,7 +55,7 @@ const generateBlockInput = function (id, next, inp) { block: 'fakeBlock', name: 'fakeName', next: next, - opcode: 'procedures_defnoreturn', + opcode: 'procedures_definition', mutation: {proccode: 'fakeCode'}, parent: null, shadow: false, @@ -156,7 +156,7 @@ test('stepToProcedure', t => { th.target.blocks.createBlock({ id: 'internalId', - opcode: 'procedures_callnoreturn_internal', + opcode: 'procedures_prototype', mutation: { proccode: 'othercode' } diff --git a/test/unit/engine_thread.js b/test/unit/engine_thread.js index 60419d360..6c9a9e4f2 100644 --- a/test/unit/engine_thread.js +++ b/test/unit/engine_thread.js @@ -194,7 +194,7 @@ test('stopThisScript', t => { block: 'fakeBlock', name: 'STEPS', next: null, - opcode: 'procedures_callnoreturn', + opcode: 'procedures_call', mutation: {proccode: 'fakeCode'}, parent: null, shadow: false, @@ -246,7 +246,7 @@ test('isRecursiveCall', t => { block: 'fakeBlock', name: 'STEPS', next: null, - opcode: 'procedures_callnoreturn', + opcode: 'procedures_call', mutation: {proccode: 'fakeCode'}, parent: null, shadow: false, From 91c93830a8bdc6c1272f08ad1ff935915fabea5d Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 16 Nov 2017 14:23:56 -0500 Subject: [PATCH 165/272] Fix tests --- test/unit/blocks_procedures.js | 2 +- test/unit/engine_thread.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/blocks_procedures.js b/test/unit/blocks_procedures.js index 4ecdb41d8..cab5e04eb 100644 --- a/test/unit/blocks_procedures.js +++ b/test/unit/blocks_procedures.js @@ -22,7 +22,7 @@ test('calling a custom block with no definition does not throw', t => { } }; t.doesNotThrow(() => { - blocks.callNoReturn(args, util); + blocks.call(args, util); }); t.end(); }); diff --git a/test/unit/engine_thread.js b/test/unit/engine_thread.js index 6c9a9e4f2..533f72523 100644 --- a/test/unit/engine_thread.js +++ b/test/unit/engine_thread.js @@ -139,7 +139,7 @@ test('goToNextBlock', t => { block: 'fakeBlock', name: 'STEPS', next: null, - opcode: 'procedures_callnoreturn', + opcode: 'procedures_call', mutation: {proccode: 'fakeCode'}, parent: null, shadow: false, From 255e160ebb00c123e373a5199b66e18b1e0ca629 Mon Sep 17 00:00:00 2001 From: DD Date: Thu, 16 Nov 2017 17:19:51 -0500 Subject: [PATCH 166/272] Change it so we dont have to do string manipulation on IDs to get data out of events --- src/blocks/scratch3_looks.js | 8 ++++---- src/blocks/scratch3_motion.js | 6 +++--- src/blocks/scratch3_sensing.js | 10 +++++----- src/blocks/scratch3_sound.js | 2 +- src/engine/blocks.js | 11 +++++------ src/virtual-machine.js | 9 --------- 6 files changed, 18 insertions(+), 28 deletions(-) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index a64f095b0..6c8f4fe3b 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -244,10 +244,10 @@ class Scratch3LooksBlocks { getMonitored () { return { - size: {isSpriteSpecific: true}, - costumeorder: {isSpriteSpecific: true}, - backdroporder: {}, - backdropname: {} + looks_size: {isSpriteSpecific: true}, + looks_costumeorder: {isSpriteSpecific: true}, + looks_backdroporder: {}, + looks_backdropname: {} }; } diff --git a/src/blocks/scratch3_motion.js b/src/blocks/scratch3_motion.js index b30138d3e..0b206975b 100644 --- a/src/blocks/scratch3_motion.js +++ b/src/blocks/scratch3_motion.js @@ -40,9 +40,9 @@ class Scratch3MotionBlocks { getMonitored () { return { - xposition: {isSpriteSpecific: true}, - yposition: {isSpriteSpecific: true}, - direction: {isSpriteSpecific: true} + motion_xposition: {isSpriteSpecific: true}, + motion_yposition: {isSpriteSpecific: true}, + motion_direction: {isSpriteSpecific: true} }; } diff --git a/src/blocks/scratch3_sensing.js b/src/blocks/scratch3_sensing.js index d51dd5d3b..fa129f6c0 100644 --- a/src/blocks/scratch3_sensing.js +++ b/src/blocks/scratch3_sensing.js @@ -51,11 +51,11 @@ class Scratch3SensingBlocks { getMonitored () { return { - answer: {}, - loudness: {}, - timer: {}, - of: {}, - current: {} + sensing_answer: {}, + sensing_loudness: {}, + sensing_timer: {}, + sensing_of: {}, + sensing_current: {} }; } diff --git a/src/blocks/scratch3_sound.js b/src/blocks/scratch3_sound.js index d3f3f92ac..be78ec7e2 100644 --- a/src/blocks/scratch3_sound.js +++ b/src/blocks/scratch3_sound.js @@ -105,7 +105,7 @@ class Scratch3SoundBlocks { getMonitored () { return { - volume: {} + sound_volume: {} }; } diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 155a2e5e8..a5b6ad45c 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -327,7 +327,11 @@ class Blocks { break; case 'checkbox': block.isMonitored = args.value; - block.targetId = args.isSpriteSpecific ? this._getTargetIdFromBlockId(block.id) : null; + if (optRuntime) { + const isSpriteSpecific = optRuntime.monitorBlockInfo.hasOwnProperty(block.opcode) && + optRuntime.monitorBlockInfo[block.opcode].isSpriteSpecific; + block.targetId = isSpriteSpecific ? optRuntime.getEditingTarget().id : null; + } if (optRuntime && wasMonitored && !block.isMonitored) { optRuntime.requestRemoveMonitor(block.id); } else if (optRuntime && !wasMonitored && block.isMonitored) { @@ -416,11 +420,6 @@ class Blocks { }); } - _getTargetIdFromBlockId (blockId) { - // First word of block ID. See makeToolboxXML in scratch-gui - return blockId.split('_')[0]; - } - /** * Block management: delete blocks and their associated scripts. * @param {!object} e Blockly delete event to be processed. diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 5c5361bae..994de9860 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -578,15 +578,6 @@ class VirtualMachine extends EventEmitter { // Filter events by type, since monitor blocks only need to listen to these events. // Monitor blocks shouldn't be destroyed when flyout blocks are deleted. if (['create', 'change'].indexOf(e.type) !== -1) { - let blockType = e.blockId.split('_'); - blockType = blockType[blockType.length - 1]; - if (!this.runtime.monitorBlockInfo.hasOwnProperty(blockType)) { - return; - } - if (!this.runtime.monitorBlockInfo.hasOwnProperty(blockType) || - this.runtime.monitorBlockInfo[blockType].isSpriteSpecific) { - e.isSpriteSpecific = true; - } this.runtime.monitorBlocks.blocklyListen(e, this.runtime); } } From 8963d0222f8f07e9b3e552036d8969133b4636d3 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Fri, 17 Nov 2017 14:24:32 +0000 Subject: [PATCH 167/272] chore(package): update copy-webpack-plugin to version 4.2.1 Closes #682 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 657022b1c..5e67750ca 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "babel-eslint": "^7.1.1", "babel-loader": "^7.0.0", "babel-preset-es2015": "^6.24.1", - "copy-webpack-plugin": "4.0.1", + "copy-webpack-plugin": "4.2.1", "escape-html": "1.0.3", "eslint": "^4.5.0", "eslint-config-scratch": "^4.0.0", From 26771e9e0c9ccc7bc984686a6a6895a44543a95d Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 17 Nov 2017 09:59:09 -0500 Subject: [PATCH 168/272] Only uglify if building for production. Uglify was trying to run always, including the dev-server output, which included es6 that broke uglifier. --- webpack.config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webpack.config.js b/webpack.config.js index b58666d47..7166587fc 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -20,12 +20,12 @@ const base = { } }] }, - plugins: [ + plugins: process.env.NODE_ENV === 'production' ? [ new webpack.optimize.UglifyJsPlugin({ include: /\.min\.js$/, minimize: true }) - ] + ] : [] }; module.exports = [ From a036564a600c63cb9dd4282487a331a0ffb67275 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 17 Nov 2017 10:06:38 -0500 Subject: [PATCH 169/272] Add node env to travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 955aa5bae..e1a2e3b8e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ node_js: env: - NPM_SCRIPT="tap:unit -- --jobs=4" - NPM_SCRIPT="tap:integration -- --jobs=4" + - NODE_ENV=production sudo: false cache: directories: From d83f32c578b2c9168d750af5e1cd48394d4214d0 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 17 Nov 2017 11:48:22 -0500 Subject: [PATCH 170/272] Use production=false in install step --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e1a2e3b8e..4f98c1364 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,8 +11,8 @@ cache: directories: - node_modules install: -- npm install -- npm update +- npm --production=false install +- npm --production=false update script: npm run $NPM_SCRIPT jobs: include: From b19af399fad3868f590858aa0dd17062ae3ee421 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Fri, 17 Nov 2017 12:12:07 -0800 Subject: [PATCH 171/272] Make _removeThread safe during thread iteration Before: `_removeThread` stops a thread and immediately removes it from the runtime's thread array. If this happens while iterating over the thread array, such as in the case of clone deletion, some elements of the array can be missed. After: `_removeThread` has been renamed to `_stopThread`. It still stops the thread immediately but it no longer removes the thread from the runtime's thread array. Instead, `_stopThread` marks the thread for later removal. Such threads are removed at the top of the next `_step`. --- src/engine/runtime.js | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 2f34cd8d0..4a2233259 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -786,17 +786,14 @@ class Runtime extends EventEmitter { } /** - * Remove a thread from the list of threads. - * @param {?Thread} thread Thread object to remove from actives + * Stop a thread: stop running it immediately, and remove it from the thread list later. + * @param {!Thread} thread Thread object to remove from actives */ - _removeThread (thread) { + _stopThread (thread) { + // Mark the thread for later removal + thread.isKilled = true; // Inform sequencer to stop executing that thread. this.sequencer.retireThread(thread); - // Remove from the list. - const i = this.threads.indexOf(thread); - if (i > -1) { - this.threads.splice(i, 1); - } } /** @@ -859,7 +856,7 @@ class Runtime extends EventEmitter { // edge activated hat thread that runs every frame continue; } - this._removeThread(this.threads[i]); + this._stopThread(this.threads[i]); return; } } @@ -1035,8 +1032,7 @@ class Runtime extends EventEmitter { continue; } if (this.threads[i].target === target) { - this.threads[i].isKilled = true; - this._removeThread(this.threads[i]); + this._stopThread(this.threads[i]); } } } @@ -1075,11 +1071,7 @@ class Runtime extends EventEmitter { } this.targets = newTargets; // Dispose all threads. - const threadsCopy = this.threads.slice(); - while (threadsCopy.length > 0) { - const poppedThread = threadsCopy.pop(); - this._removeThread(poppedThread); - } + this.threads.forEach(thread => this._stopThread(thread)); } /** @@ -1093,6 +1085,10 @@ class Runtime extends EventEmitter { } this.profiler.start(stepProfilerId); } + + // Clean up threads that were told to stop during or since the last step + this.threads = this.threads.filter(thread => !thread.isKilled); + // Find all edge-activated hats, and add them to threads to be evaluated. for (const hatType in this._hats) { if (!this._hats.hasOwnProperty(hatType)) continue; From 0959c4dbd5116ee38990c9cdd5efedb742f6945e Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Fri, 17 Nov 2017 21:59:41 +0000 Subject: [PATCH 172/272] chore(package): update gh-pages to version 1.1.0 Closes #559 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 657022b1c..efc818f7a 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "eslint": "^4.5.0", "eslint-config-scratch": "^4.0.0", "expose-loader": "0.7.3", - "gh-pages": "^0.12.0", + "gh-pages": "^1.1.0", "got": "5.7.1", "highlightjs": "^9.8.0", "htmlparser2": "3.9.2", From e052f1d53bc38c326678bb230de9650f39cc93c7 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Sat, 18 Nov 2017 07:41:49 +0000 Subject: [PATCH 173/272] chore(package): update expose-loader to version 0.7.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 657022b1c..825ff3032 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "escape-html": "1.0.3", "eslint": "^4.5.0", "eslint-config-scratch": "^4.0.0", - "expose-loader": "0.7.3", + "expose-loader": "0.7.4", "gh-pages": "^0.12.0", "got": "5.7.1", "highlightjs": "^9.8.0", From 6ed2ca6caaf2fe5d2082215c8b43508a74f061c5 Mon Sep 17 00:00:00 2001 From: griffpatch Date: Mon, 20 Nov 2017 15:22:51 +0000 Subject: [PATCH 174/272] Cache Block Inputs & Procedure Definitions * Cache Block Inputs & Procedure Definitions * @mzgoddard requested changes on this pull request * Move all caching into a single reusable field _cache. * Invalidate 'all' caches on any change. * Use 'typeof' instead of hasOwnProperty. * Take caching out of Block and use lookup instead. --- src/engine/blocks.js | 73 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 5 deletions(-) diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 2f2de7b40..8776c6f6c 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -25,6 +25,30 @@ class Blocks { * @type {Array.} */ this._scripts = []; + + /** + * Runtime Cache + * @type {{inputs: {}, procedureParamNames: {}, procedureDefinitions: {}}} + * @private + */ + this._cache = { + /** + * Cache block inputs by block id + * @type {object.>} + */ + inputs: {}, + /** + * Cache procedure Param Names by block id + * @type {object.>} + */ + procedureParamNames: {}, + /** + * Cache procedure definitions by block id + * @type {object.} + */ + procedureDefinitions: {} + }; + } /** @@ -105,11 +129,16 @@ class Blocks { /** * Get all non-branch inputs for a block. * @param {?object} block the block to query. - * @return {!object} All non-branch inputs and their associated blocks. + * @return {?Array.} All non-branch inputs and their associated blocks. */ getInputs (block) { if (typeof block === 'undefined') return null; - const inputs = {}; + let inputs = this._cache.inputs[block.id]; + if (typeof inputs !== 'undefined') { + return inputs; + } + + inputs = {}; for (const input in block.inputs) { // Ignore blocks prefixed with branch prefix. if (input.substring(0, Blocks.BRANCH_INPUT_PREFIX.length) !== @@ -117,6 +146,8 @@ class Blocks { inputs[input] = block.inputs[input]; } } + + this._cache.inputs[block.id] = inputs; return inputs; } @@ -149,16 +180,24 @@ class Blocks { * @return {?string} ID of procedure definition. */ getProcedureDefinition (name) { + const blockID = this._cache.procedureDefinitions[name]; + if (typeof blockID !== 'undefined') { + return blockID; + } + for (const id in this._blocks) { if (!this._blocks.hasOwnProperty(id)) continue; const block = this._blocks[id]; if (block.opcode === 'procedures_definition') { const internal = this._getCustomBlockInternal(block); if (internal && internal.mutation.proccode === name) { - return id; // The outer define block id + this._cache.procedureDefinitions[name] = id; // The outer define block id + return id; } } } + + this._cache.procedureDefinitions[name] = null; return null; } @@ -168,14 +207,23 @@ class Blocks { * @return {?Array.} List of param names for a procedure. */ getProcedureParamNames (name) { + const cachedNames = this._cache.procedureParamNames[name]; + if (typeof cachedNames !== 'undefined') { + return cachedNames; + } + for (const id in this._blocks) { if (!this._blocks.hasOwnProperty(id)) continue; const block = this._blocks[id]; if (block.opcode === 'procedures_prototype' && block.mutation.proccode === name) { - return JSON.parse(block.mutation.argumentnames); + const paramNames = JSON.parse(block.mutation.argumentnames); + this._cache.procedureParamNames[name] = paramNames; + return paramNames; } } + + this._cache.procedureParamNames[name] = null; return null; } @@ -271,6 +319,15 @@ class Blocks { // --------------------------------------------------------------------- + /** + * Reset all runtime caches. + */ + resetCache () { + this._cache.inputs = {}; + this._cache.procedureParamNames = {}; + this._cache.procedureDefinitions = {}; + } + /** * Block management: create blocks and scripts from a `create` event * @param {!object} block Blockly create event to be processed @@ -289,6 +346,8 @@ class Blocks { if (block.topLevel) { this._addScript(block.id); } + + this.resetCache(); } /** @@ -301,7 +360,6 @@ class Blocks { if (['field', 'mutation', 'checkbox'].indexOf(args.element) === -1) return; const block = this._blocks[args.id]; if (typeof block === 'undefined') return; - const wasMonitored = block.isMonitored; switch (args.element) { case 'field': @@ -337,6 +395,8 @@ class Blocks { } break; } + + this.resetCache(); } /** @@ -393,6 +453,7 @@ class Blocks { } this._blocks[e.id].parent = e.newParent; } + this.resetCache(); } @@ -447,6 +508,8 @@ class Blocks { // Delete block itself. delete this._blocks[blockId]; + + this.resetCache(); } // --------------------------------------------------------------------- From 6d260231049040d38c40181275a8f20e4c7ff1ee Mon Sep 17 00:00:00 2001 From: DD Date: Mon, 20 Nov 2017 13:00:37 -0500 Subject: [PATCH 175/272] revert unnecessary changes' : --- src/engine/blocks.js | 3 +-- src/util/uid.js | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/engine/blocks.js b/src/engine/blocks.js index a5b6ad45c..89d7a63ce 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -226,8 +226,7 @@ class Blocks { id: e.blockId, element: e.element, name: e.name, - value: e.newValue, - isSpriteSpecific: e.isSpriteSpecific + value: e.newValue }, optRuntime); break; case 'move': diff --git a/src/util/uid.js b/src/util/uid.js index 34e8eaf58..fd4c41e87 100644 --- a/src/util/uid.js +++ b/src/util/uid.js @@ -6,10 +6,9 @@ * Legal characters for the unique ID. * Should be all on a US keyboard. No XML special characters or control codes. * Removed $ due to issue 251. - * Removed _ which denotes word separation in XML. * @private */ -const soup_ = '!#%()*+,-./:;=?@[]^`{|}~' + +const soup_ = '!#%()*+,-./:;=?@[]^_`{|}~' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; /** From c3a72560f9d8902a77557a4977e44de7f64671fa Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Mon, 20 Nov 2017 13:42:35 -0500 Subject: [PATCH 176/272] Clarify @TODO comment about extension status indicator --- src/extensions/scratch3_music/index.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index ab461441f..b209e3cde 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -45,9 +45,7 @@ class Scratch3MusicBlocks { /** * Download and decode the full set of drum sounds, and store the audio buffers * in the drum buffers array. - * @TODO: Also load the instrument sounds here (rename this fn), and use Promise.all - * to detect that all the assets have loaded in order to update the extension status - * indicator. + * @TODO: Also load the instrument sounds here (rename this fn) */ _loadAllDrumSounds () { const loadingPromises = []; @@ -56,7 +54,7 @@ class Scratch3MusicBlocks { loadingPromises.push(promise); }); Promise.all(loadingPromises).then(() => { - // done! + // @TODO: Update the extension status indicator. }); } From 1e00a0c2526cd4db75a3fc0496076354b97e6f59 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Mon, 20 Nov 2017 13:44:44 -0500 Subject: [PATCH 177/272] Comment for no-op above concurrency limit --- src/extensions/scratch3_music/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index b209e3cde..fc07b6479 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -458,6 +458,7 @@ class Scratch3MusicBlocks { */ _playDrumNum (util, drumNum) { if (util.target.audioPlayer === null) return; + // If we're playing too many sounds, do not play the drum sound. if (this._drumConcurrencyCounter > Scratch3MusicBlocks.CONCURRENCY_LIMIT) { return; } From b6cf12202c39d454b8ea7773a4f9995a53680bb2 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Mon, 20 Nov 2017 13:50:46 -0500 Subject: [PATCH 178/272] Rename unit test file --- test/unit/{blocks_music.js => extension_music.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/unit/{blocks_music.js => extension_music.js} (100%) diff --git a/test/unit/blocks_music.js b/test/unit/extension_music.js similarity index 100% rename from test/unit/blocks_music.js rename to test/unit/extension_music.js From a8c629dc9bf8534ec19317787af5624002436afc Mon Sep 17 00:00:00 2001 From: Andrew Sliwinski Date: Mon, 20 Nov 2017 17:04:17 -0500 Subject: [PATCH 179/272] Replace 'got' module with 'nets'. Resolves GH-802 --- .gitignore | 1 + package.json | 2 +- src/io/deviceManager.js | 14 ++++++++++++-- test/unit/io_deviceManager.js | 13 +++++++++++++ 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 2f3825877..a733474c9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .DS_Store # NPM +package-lock.json /node_modules npm-* diff --git a/package.json b/package.json index efc818f7a..4bb733f86 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,6 @@ "eslint-config-scratch": "^4.0.0", "expose-loader": "0.7.3", "gh-pages": "^1.1.0", - "got": "5.7.1", "highlightjs": "^9.8.0", "htmlparser2": "3.9.2", "immutable": "3.8.1", @@ -44,6 +43,7 @@ "json": "^9.0.4", "lodash.defaultsdeep": "4.6.0", "minilog": "3.1.0", + "nets": "3.2.0", "promise": "7.1.1", "scratch-audio": "latest", "scratch-blocks": "latest", diff --git a/src/io/deviceManager.js b/src/io/deviceManager.js index d2d0046fb..2ba018ce3 100644 --- a/src/io/deviceManager.js +++ b/src/io/deviceManager.js @@ -1,4 +1,4 @@ -const got = require('got'); +const nets = require('nets'); const io = require('socket.io-client/dist/socket.io'); const querystring = require('querystring'); @@ -312,7 +312,17 @@ class DeviceManager { }; if (deviceSpec) queryObject.spec = deviceSpec; const url = `${this._serverURL}/${encodeURIComponent(deviceType)}/list?${querystring.stringify(queryObject)}`; - return got(url).then(response => JSON.parse(response.body)); + return new Promise((resolve, reject) => { + nets({ + method: 'GET', + url: url, + json: {} + }, (err, res, body) => { + if (err) return reject(err); + if (res.statusCode !== 200) reject(body); + resolve(body); + }); + }); } /** diff --git a/test/unit/io_deviceManager.js b/test/unit/io_deviceManager.js index f013ef5dd..f4d32d06f 100644 --- a/test/unit/io_deviceManager.js +++ b/test/unit/io_deviceManager.js @@ -19,3 +19,16 @@ test('default connected', t => { t.strictEqual(deviceManager.isConnected, true); t.end(); }); + +test('list', t => { + const deviceManager = new DeviceManager(); + deviceManager + .list('test', 'test', null) + .catch(err => { + t.true((typeof err === 'undefined') || (typeof err === 'object')); + }) + .then(body => { + t.true((typeof body === 'undefined') || (typeof body === 'object')); + t.end(); + }); +}); From ec9d8094bd9e41a87856c45defbe37ec5287aa03 Mon Sep 17 00:00:00 2001 From: DD Date: Mon, 20 Nov 2017 17:23:59 -0500 Subject: [PATCH 180/272] fix review comments --- src/engine/runtime.js | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index d8fa88358..63aec3bb6 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -232,9 +232,6 @@ class Runtime extends EventEmitter { // Register all given block packages. this._registerBlockPackages(); - // Populate monitorBlockInfo - this._registerMonitorInfo(); - // Register and initialize "IO devices", containers for processing // I/O related data. /** @type {Object.} */ @@ -407,6 +404,10 @@ class Runtime extends EventEmitter { } } } + // Collect monitored from package. + if (packageObject.getMonitored) { + this.monitorBlockInfo = Object.assign({}, this.monitorBlockInfo, packageObject.getMonitored()); + } } } } @@ -461,22 +462,6 @@ class Runtime extends EventEmitter { this.emit(Runtime.EXTENSION_ADDED, categoryInfo.blocks.concat(categoryInfo.menus)); } - /** - * Populate this.monitorBlockInfo - */ - _registerMonitorInfo () { - for (const packageName in defaultBlockPackages) { - if (defaultBlockPackages.hasOwnProperty(packageName)) { - // @todo pass a different runtime depending on package privilege? - const packageObject = new (defaultBlockPackages[packageName])(this); - // Collect monitored from package. - if (packageObject.getMonitored) { - this.monitorBlockInfo = Object.assign({}, this.monitorBlockInfo, packageObject.getMonitored()); - } - } - } - } - /** * Build the scratch-blocks JSON for a menu. Note that scratch-blocks treats menus as a special kind of block. * @param {string} menuName - the name of the menu @@ -864,7 +849,7 @@ class Runtime extends EventEmitter { /** * Enqueue a script that when finished will update the monitor for the block. * @param {!string} topBlockId ID of block that starts the script. - * @param {?string} optTarget target Target to run script on. If not supplied, uses editing target. + * @param {?Target} optTarget target Target to run script on. If not supplied, uses editing target. */ addMonitorScript (topBlockId, optTarget) { if (!optTarget) optTarget = this._editingTarget; From 73565460729138f6ec30f74eef4fbf361d370886 Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Thu, 9 Nov 2017 18:35:12 -0500 Subject: [PATCH 181/272] Add benchmark prototype Build a page with webpack that loads a project and automatically runs it, collecting performance information for a set amount of time, stopping and displaying the results. --- src/benchmark/benchmark.css | 7 + src/benchmark/benchmark.js | 460 ++++++++++++++++++++++++++++++++++++ src/benchmark/index.html | 69 ++++++ webpack.config.js | 63 +++++ 4 files changed, 599 insertions(+) create mode 100644 src/benchmark/benchmark.css create mode 100644 src/benchmark/benchmark.js create mode 100644 src/benchmark/index.html diff --git a/src/benchmark/benchmark.css b/src/benchmark/benchmark.css new file mode 100644 index 000000000..e843b5e94 --- /dev/null +++ b/src/benchmark/benchmark.css @@ -0,0 +1,7 @@ +@media (min-width: 960px) { + .profile-tables { + position: absolute; + top: 0; + left: 520px; + } +} diff --git a/src/benchmark/benchmark.js b/src/benchmark/benchmark.js new file mode 100644 index 000000000..d8540404a --- /dev/null +++ b/src/benchmark/benchmark.js @@ -0,0 +1,460 @@ +const Scratch = window.Scratch = window.Scratch || {}; + +const ASSET_SERVER = 'https://cdn.assets.scratch.mit.edu/'; +const PROJECT_SERVER = 'https://cdn.projects.scratch.mit.edu/'; + +const SLOW = .1; + +const loadProject = function () { + let id = location.hash.substring(1); + if (id.length < 1 || !isFinite(id)) { + id = '119615668'; + } + Scratch.vm.downloadProjectId(id); +}; + +/** + * @param {Asset} asset - calculate a URL for this asset. + * @returns {string} a URL to download a project file. + */ +const getProjectUrl = function (asset) { + const assetIdParts = asset.assetId.split('.'); + const assetUrlParts = [PROJECT_SERVER, 'internalapi/project/', assetIdParts[0], '/get/']; + if (assetIdParts[1]) { + assetUrlParts.push(assetIdParts[1]); + } + return assetUrlParts.join(''); +}; + +/** + * @param {Asset} asset - calculate a URL for this asset. + * @returns {string} a URL to download a project asset (PNG, WAV, etc.) + */ +const getAssetUrl = function (asset) { + const assetUrlParts = [ + ASSET_SERVER, + 'internalapi/asset/', + asset.assetId, + '.', + asset.dataFormat, + '/get/' + ]; + return assetUrlParts.join(''); +}; + +class LoadingProgress { + constructor (callback) { + this.total = 0; + this.complete = 0; + this.callback = callback; + } + + on (storage) { + const _this = this; + const _load = storage.webHelper.load; + storage.webHelper.load = function (...args) { + const result = _load.call(this, ...args); + _this.total += 1; + _this.callback(_this); + result.then(() => { + _this.complete += 1; + _this.callback(_this); + }); + return result; + }; + } +} + +class StatTable { + constructor ({table, keys, viewOf, isSlow}) { + this.table = table; + if (keys) { + this.keys = keys; + } + if (viewOf) { + this.viewOf = viewOf; + } + if (isSlow) { + this.isSlow = isSlow; + } + } + + render () { + const table = this.table; + Array.from(table.children) + .forEach(node => table.removeChild(node)); + const keys = this.keys(); + for (const key of keys) { + this.viewOf(key).render({ + table, + isSlow: frame => this.isSlow(key, frame) + }); + } + } +} + +class StatView { + constructor (name) { + this.name = name; + this.executions = 0; + this.selfTime = 0; + this.totalTime = 0; + } + + update (selfTime, totalTime) { + this.executions++; + this.selfTime += selfTime; + this.totalTime += totalTime; + } + + render ({table, isSlow}) { + const row = document.createElement('tr'); + let cell = document.createElement('td'); + cell.innerText = this.name; + row.appendChild(cell); + + if (isSlow(this)) { + row.setAttribute('class', 'slow'); + } + + cell = document.createElement('td'); + cell.innerText = (this.selfTime / 1000).toPrecision(3); + row.appendChild(cell); + + cell = document.createElement('td'); + cell.innerText = (this.totalTime / 1000).toPrecision(3); + row.appendChild(cell); + + cell = document.createElement('td'); + cell.innerText = this.executions; + row.appendChild(cell); + + table.appendChild(row); + } +} + +class RunningStats { + constructor (profiler) { + this.stepThreadsInnerId = profiler.idByName('Sequencer.stepThreads#inner'); + this.blockFunctionId = profiler.idByName('blockFunction'); + this.stpeThreadsId = profiler.idByName('Sequencer.stepThreads'); + + this.recordedTime = 0; + this.executed = { + steps: 0, + blocks: 0 + }; + } + + update (id, selfTime, totalTime) { + if (id === this.stpeThreadsId) { + this.recordedTime += totalTime; + } else if (id === this.stepThreadsInnerId) { + this.executed.steps++; + } else if (id === this.blockFunctionId) { + this.executed.blocks++; + } + } +} + +const WORK_TIME = 0.75; + +class RunningStatsView { + constructor ({runningStats, maxRecordedTime, dom}) { + this.recordedTimeDom = + dom.getElementsByClassName('profile-count-amount-recorded')[0]; + this.stepsLoopedDom = + dom.getElementsByClassName('profile-count-steps-looped')[0]; + this.blocksExecutedDom = + dom.getElementsByClassName('profile-count-blocks-executed')[0]; + + this.maxRecordedTime = maxRecordedTime; + this.maxWorkedTime = maxRecordedTime * WORK_TIME; + this.runningStats = runningStats; + } + + render () { + const { + runningStats, + recordedTimeDom, + stepsLoopedDom, + blocksExecutedDom + } = this; + const {executed} = runningStats; + const fractionWorked = runningStats.recordedTime / this.maxWorkedTime; + recordedTimeDom.innerText = `${(fractionWorked * 100).toFixed(1)} %`; + stepsLoopedDom.innerText = executed.steps; + blocksExecutedDom.innerText = executed.blocks; + } +} + +class Frames { + constructor (profiler) { + this.profiler = profiler; + + this.frames = []; + } + + update (id, selfTime, totalTime) { + if (!this.frames[id]) { + this.frames[id] = new StatView(this.profiler.nameById(id)); + } + this.frames[id].update(selfTime, totalTime); + } +} + +const frameOrder = [ + 'blockFunction', + 'execute', + 'Sequencer.stepThread', + 'Sequencer.stepThreads#inner', + 'Sequencer.stepThreads', + 'RenderWebGL.draw', + 'Runtime._step' +]; + +class FramesTable extends StatTable { + constructor (options) { + super(options); + + this.profiler = options.profiler; + this.frames = options.frames; + } + + keys () { + const keys = Object.keys(this.frames.frames) + .map(id => this.profiler.nameById(Number(id))); + keys.sort((a, b) => frameOrder.indexOf(a) - frameOrder.indexOf(b)); + return keys; + } + + viewOf (key) { + return this.frames.frames[this.profiler.idByName(key)]; + } + + isSlow (key, frame) { + return ([ + 'Sequencer.stepThreads', + 'Sequencer.stepThreads#inner', + 'Sequencer.stepThread', + 'execute' + ].indexOf(key) > 0 && + frame.selfTime / frame.totalTime > SLOW); + } +} + +class Opcodes { + constructor (profiler) { + this.blockFunctionId = profiler.idByName('blockFunction'); + + this.opcodes = {}; + } + + update (id, selfTime, totalTime, arg) { + if (id === this.blockFunctionId) { + if (!this.opcodes[arg]) { + this.opcodes[arg] = new StatView(arg); + } + this.opcodes[arg].update(selfTime, totalTime); + } + } +} + +class OpcodeTable extends StatTable { + constructor (options) { + super(options); + + this.profiler = options.profiler; + this.opcodes = options.opcodes; + this.frames = options.frames; + } + + keys () { + const keys = Object.keys(this.opcodes.opcodes); + keys.sort(); + return keys; + } + + viewOf (key) { + return this.opcodes.opcodes[key]; + } + + isSlow (key) { + const blockFunctionTotalTime = this.frames.frames[this.profiler.idByName('blockFunction')].totalTime; + const rowTotalTime = this.opcodes.opcodes[key].totalTime; + const percentOfRun = rowTotalTime / blockFunctionTotalTime; + return percentOfRun > SLOW; + } +} + +class ProfilerRun { + constructor ({vm, maxRecordedTime, warmUpTime}) { + this.vm = vm; + this.maxRecordedTime = maxRecordedTime; + this.warmUpTime = warmUpTime; + + vm.runtime.enableProfiling(); + const profiler = this.profiler = vm.runtime.profiler; + vm.runtime.profiler = null; + + const runningStats = this.runningStats = new RunningStats(profiler); + const runningStatsView = this.runningStatsView = new RunningStatsView({ + dom: document.getElementsByClassName('profile-count-group')[0], + + runningStats, + maxRecordedTime: 6000 + }); + + const frames = this.frames = new Frames(profiler); + this.frameTable = new FramesTable({ + table: document + .getElementsByClassName('profile-count-frame-table')[0] + .getElementsByTagName('tbody')[0], + + profiler, + frames + }); + + const opcodes = this.opcodes = new Opcodes(profiler); + this.opcodeTable = new OpcodeTable({ + table: document + .getElementsByClassName('profile-count-opcode-table')[0] + .getElementsByTagName('tbody')[0], + + profiler, + opcodes, + frames + }); + + const stepId = profiler.idByName('Runtime._step'); + profiler.onFrame = ({id, selfTime, totalTime, arg}) => { + if (id === stepId) { + runningStatsView.render(); + } + runningStats.update(id, selfTime, totalTime, arg); + opcodes.update(id, selfTime, totalTime, arg); + frames.update(id, selfTime, totalTime, arg); + }; + } + + run () { + loadProject(); + + this.vm.on('workspaceUpdate', () => { + setTimeout(() => { + this.vm.greenFlag(); + }, 100); + setTimeout(() => { + this.vm.runtime.profiler = this.profiler; + }, 100 + this.warmUpTime); + setTimeout(() => { + this.vm.stopAll(); + clearTimeout(this.vm.runtime._steppingInterval); + this.vm.runtime.profiler = null; + + this.frameTable.render(); + this.opcodeTable.render(); + }, 100 + this.warmUpTime + this.maxRecordedTime); + }); + } +} + +window.onload = function () { + // Lots of global variables to make debugging easier + // Instantiate the VM. + const vm = new window.VirtualMachine(); + Scratch.vm = vm; + + vm.setTurboMode(true); + + const storage = new ScratchStorage(); /* global ScratchStorage */ + const AssetType = storage.AssetType; + storage.addWebSource([AssetType.Project], getProjectUrl); + storage.addWebSource([AssetType.ImageVector, AssetType.ImageBitmap, AssetType.Sound], getAssetUrl); + vm.attachStorage(storage); + + new LoadingProgress(progress => { + document.getElementsByClassName('loading-total')[0] + .innerText = progress.total; + document.getElementsByClassName('loading-complete')[0] + .innerText = progress.complete; + }).on(storage); + + new ProfilerRun({ + vm, + warmUpTime: 4000, + maxRecordedTime: 6000 + }).run(); + + // Instantiate the renderer and connect it to the VM. + const canvas = document.getElementById('scratch-stage'); + const renderer = new window.RenderWebGL(canvas); + Scratch.renderer = renderer; + vm.attachRenderer(renderer); + const audioEngine = new window.AudioEngine(); + vm.attachAudioEngine(audioEngine); + + // Feed mouse events as VM I/O events. + document.addEventListener('mousemove', e => { + const rect = canvas.getBoundingClientRect(); + const coordinates = { + x: e.clientX - rect.left, + y: e.clientY - rect.top, + canvasWidth: rect.width, + canvasHeight: rect.height + }; + Scratch.vm.postIOData('mouse', coordinates); + }); + canvas.addEventListener('mousedown', e => { + const rect = canvas.getBoundingClientRect(); + const data = { + isDown: true, + x: e.clientX - rect.left, + y: e.clientY - rect.top, + canvasWidth: rect.width, + canvasHeight: rect.height + }; + Scratch.vm.postIOData('mouse', data); + e.preventDefault(); + }); + canvas.addEventListener('mouseup', e => { + const rect = canvas.getBoundingClientRect(); + const data = { + isDown: false, + x: e.clientX - rect.left, + y: e.clientY - rect.top, + canvasWidth: rect.width, + canvasHeight: rect.height + }; + Scratch.vm.postIOData('mouse', data); + e.preventDefault(); + }); + + // Feed keyboard events as VM I/O events. + document.addEventListener('keydown', e => { + // Don't capture keys intended for Blockly inputs. + if (e.target !== document && e.target !== document.body) { + return; + } + Scratch.vm.postIOData('keyboard', { + keyCode: e.keyCode, + isDown: true + }); + e.preventDefault(); + }); + document.addEventListener('keyup', e => { + // Always capture up events, + // even those that have switched to other targets. + Scratch.vm.postIOData('keyboard', { + keyCode: e.keyCode, + isDown: false + }); + // E.g., prevent scroll. + if (e.target !== document && e.target !== document.body) { + e.preventDefault(); + } + }); + + // Run threads + vm.start(); +}; diff --git a/src/benchmark/index.html b/src/benchmark/index.html new file mode 100644 index 000000000..7ddc98dc3 --- /dev/null +++ b/src/benchmark/index.html @@ -0,0 +1,69 @@ + + + + + + Scratch VM Benchmark + + + + +

Scratch VM Benchmark

+
+
+ + 0 / 0 +
+
+
+ + ... +
+
+ + ... +
+
+ + ... +
+
+ +
+ + + + + + + +
FrameSelf TimeTotal TimeExecutions
+ + + + + + + + + + +
opcodeSelf TimeTotal TimeExecutions
+
+ +
+ + + + + + + + + + + diff --git a/webpack.config.js b/webpack.config.js index f2d4c880c..6b32c6d83 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -130,5 +130,68 @@ module.exports = [ from: 'src/playground' }]) ]) + }), + // Benchmark + defaultsDeep({}, base, { + target: 'web', + entry: { + 'scratch-vm': './src/index.js', + 'vendor': [ + // FPS counter + 'stats.js/build/stats.min.js', + // Syntax highlighter + 'highlightjs/highlight.pack.min.js', + // Scratch Blocks + 'scratch-blocks/dist/vertical.js', + // Audio + 'scratch-audio', + // Renderer + 'scratch-render' + ] + }, + output: { + path: path.resolve(__dirname, 'benchmark'), + filename: '[name].js' + }, + module: { + rules: base.module.rules.concat([ + { + test: require.resolve('./src/index.js'), + loader: 'expose-loader?VirtualMachine' + }, + { + test: require.resolve('stats.js/build/stats.min.js'), + loader: 'script-loader' + }, + { + test: require.resolve('highlightjs/highlight.pack.min.js'), + loader: 'script-loader' + }, + { + test: require.resolve('scratch-blocks/dist/vertical.js'), + loader: 'expose-loader?Blockly' + }, + { + test: require.resolve('scratch-audio'), + loader: 'expose-loader?AudioEngine' + }, + { + test: require.resolve('scratch-render'), + loader: 'expose-loader?RenderWebGL' + } + ]) + }, + plugins: base.plugins.concat([ + new CopyWebpackPlugin([{ + from: 'node_modules/scratch-blocks/media', + to: 'media' + }, { + from: 'node_modules/highlightjs/styles/zenburn.css' + }, { + from: 'node_modules/scratch-storage/dist/web' + }, { + from: 'src/benchmark' + }]) + ]) }) ]; From a7314d6f0d6e9078a26051ccefe58ff814bb67de Mon Sep 17 00:00:00 2001 From: Boaz Sender Date: Thu, 16 Nov 2017 15:43:51 -0500 Subject: [PATCH 182/272] adds ui styling and context to benchmark prototype --- src/benchmark/benchmark.css | 54 +++++++++++++++++++++++++++++++++++-- src/benchmark/benchmark.js | 10 ++++++- src/benchmark/index.html | 26 +++++++++++++----- 3 files changed, 80 insertions(+), 10 deletions(-) diff --git a/src/benchmark/benchmark.css b/src/benchmark/benchmark.css index e843b5e94..07068f59b 100644 --- a/src/benchmark/benchmark.css +++ b/src/benchmark/benchmark.css @@ -1,7 +1,57 @@ +body { + font-family: monospace; +} +p { + max-width: 400px; +} @media (min-width: 960px) { .profile-tables { + top: 0px; position: absolute; - top: 0; - left: 520px; + left: 450px; } } +#scratch-stage { + border: 5px solid black; + display: block; + width: 400px; + height: 300px; +} +.loading label, .profile-count label{ + width: 15em; + display: inline-block; +} +.profile-tables table { + margin: 30px 0 30px 0px; +} +.profile-tables th { + border-bottom: 1px solid #333; + text-align: center; +} +.profile-tables th:first-child { + width: 215px; +} +.profile-tables th, .profile-tables td { + min-width: 85px; + border-bottom: 1px solid #ccc; + border-spacing: 0; + border-collapse: collapse; + padding: 5px; +} +.profile-tables td:not(:first-child) { + text-align: center; +} +.profile-tables img{ + margin: 0 auto; + display: block; + clear: both; + width: 20%; +} + +.slow { + background-color: #ffa1a1; +} +.profiler-count-running { + height: 4em; + background-color: #dddddd; +} diff --git a/src/benchmark/benchmark.js b/src/benchmark/benchmark.js index d8540404a..3fd1bc2a2 100644 --- a/src/benchmark/benchmark.js +++ b/src/benchmark/benchmark.js @@ -5,10 +5,18 @@ const PROJECT_SERVER = 'https://cdn.projects.scratch.mit.edu/'; const SLOW = .1; +const projectInput = document.querySelector('input'); + +document.querySelector('.run') + .addEventListener('click', () => { + window.location.hash = projectInput.value; + location.reload(); + }, false); + const loadProject = function () { let id = location.hash.substring(1); if (id.length < 1 || !isFinite(id)) { - id = '119615668'; + id = projectInput.value; } Scratch.vm.downloadProjectId(id); }; diff --git a/src/benchmark/index.html b/src/benchmark/index.html index 7ddc98dc3..9e6b885a4 100644 --- a/src/benchmark/index.html +++ b/src/benchmark/index.html @@ -4,16 +4,28 @@ Scratch VM Benchmark - -

Scratch VM Benchmark

-
+

Scratch VM Benchmark

+

+ Welcome to the scratch-vm benchmark. This tool helps you profile a scratch + project. When you load the page, it: +

    +
  1. loads the default project +
  2. runs the project for 4 seconds to warm up +
  3. profiles for 6 seconds +
  4. stops and reports +
+

+ + +

+ Try a different project, like `130041250` +

+ +
+
0 / 0 From aa0acc62e4ba9c379af496f6ae7abadbf6bebe85 Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Mon, 20 Nov 2017 17:45:55 -0500 Subject: [PATCH 183/272] Add benchmark to ignore files --- .eslintignore | 1 + .gitignore | 1 + 2 files changed, 2 insertions(+) diff --git a/.eslintignore b/.eslintignore index 8af9aff65..f571fb2a3 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,3 +2,4 @@ coverage/* dist/* node_modules/* playground/* +benchmark/* diff --git a/.gitignore b/.gitignore index 2f3825877..97bbbfa69 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ npm-* # Build /dist /playground +/benchmark From 5fbfecb1a9ec641834a149a47161d8a62659de53 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 21 Nov 2017 10:36:28 -0500 Subject: [PATCH 184/272] Note player (#806) * Move drums into their own folder * Load instrument samples * Play notes * Concurrency limit is shared across drums and instruments * Increase MIDI note range * Set instrument directly on musicState object * JSDoc * Clean up the play note functions and add comments * Cleanup * Check for audioEngine in playDrumNum * JSDoc and comments * Round the instrument number * Fix unit test for set instrument * Comment fixes * Nit (condense onto single line) --- .../assets/{ => drums}/1-snare.mp3 | Bin .../assets/{ => drums}/10-wood-block.mp3 | Bin .../assets/{ => drums}/11-cowbell.mp3 | Bin .../assets/{ => drums}/12-triangle.mp3 | Bin .../assets/{ => drums}/13-bongo.mp3 | Bin .../assets/{ => drums}/14-conga.mp3 | Bin .../assets/{ => drums}/15-cabasa.mp3 | Bin .../assets/{ => drums}/16-guiro.mp3 | Bin .../assets/{ => drums}/17-vibraslap.mp3 | Bin .../assets/{ => drums}/18-cuica.mp3 | Bin .../assets/{ => drums}/2-bass-drum.mp3 | Bin .../assets/{ => drums}/3-side-stick.mp3 | Bin .../assets/{ => drums}/4-crash-cymbal.mp3 | Bin .../assets/{ => drums}/5-open-hi-hat.mp3 | Bin .../assets/{ => drums}/6-closed-hi-hat.mp3 | Bin .../assets/{ => drums}/7-tambourine.mp3 | Bin .../assets/{ => drums}/8-hand-clap.mp3 | Bin .../assets/{ => drums}/9-claves.mp3 | Bin .../assets/instruments/1-piano/108.mp3 | Bin 0 -> 9852 bytes .../assets/instruments/1-piano/24.mp3 | Bin 0 -> 75617 bytes .../assets/instruments/1-piano/36.mp3 | Bin 0 -> 80416 bytes .../assets/instruments/1-piano/48.mp3 | Bin 0 -> 58811 bytes .../assets/instruments/1-piano/60.mp3 | Bin 0 -> 57227 bytes .../assets/instruments/1-piano/72.mp3 | Bin 0 -> 46418 bytes .../assets/instruments/1-piano/84.mp3 | Bin 0 -> 30729 bytes .../assets/instruments/1-piano/96.mp3 | Bin 0 -> 25596 bytes .../assets/instruments/10-clarinet/48.mp3 | Bin 0 -> 29950 bytes .../assets/instruments/10-clarinet/60.mp3 | Bin 0 -> 33369 bytes .../assets/instruments/11-saxophone/36.mp3 | Bin 0 -> 24649 bytes .../assets/instruments/11-saxophone/60.mp3 | Bin 0 -> 24649 bytes .../assets/instruments/11-saxophone/84.mp3 | Bin 0 -> 24649 bytes .../assets/instruments/12-flute/60.mp3 | Bin 0 -> 45669 bytes .../assets/instruments/12-flute/72.mp3 | Bin 0 -> 33812 bytes .../assets/instruments/13-wooden-flute/60.mp3 | Bin 0 -> 34383 bytes .../assets/instruments/13-wooden-flute/72.mp3 | Bin 0 -> 36776 bytes .../assets/instruments/14-bassoon/36.mp3 | Bin 0 -> 28433 bytes .../assets/instruments/14-bassoon/48.mp3 | Bin 0 -> 27567 bytes .../assets/instruments/14-bassoon/60.mp3 | Bin 0 -> 28049 bytes .../assets/instruments/15-choir/48.mp3 | Bin 0 -> 32402 bytes .../assets/instruments/15-choir/60.mp3 | Bin 0 -> 31410 bytes .../assets/instruments/15-choir/72.mp3 | Bin 0 -> 29022 bytes .../assets/instruments/16-vibraphone/60.mp3 | Bin 0 -> 22265 bytes .../assets/instruments/16-vibraphone/72.mp3 | Bin 0 -> 23547 bytes .../assets/instruments/17-music-box/60.mp3 | Bin 0 -> 30465 bytes .../assets/instruments/18-steel-drum/60.mp3 | Bin 0 -> 28015 bytes .../assets/instruments/19-marimba/60.mp3 | Bin 0 -> 5229 bytes .../instruments/2-electric-piano/60.mp3 | Bin 0 -> 23858 bytes .../assets/instruments/20-synth-lead/60.mp3 | Bin 0 -> 60288 bytes .../assets/instruments/21-synth-pad/60.mp3 | Bin 0 -> 33916 bytes .../assets/instruments/3-organ/60.mp3 | Bin 0 -> 26939 bytes .../assets/instruments/4-guitar/60.mp3 | Bin 0 -> 26857 bytes .../instruments/5-electric-guitar/60.mp3 | Bin 0 -> 24649 bytes .../assets/instruments/6-bass/36.mp3 | Bin 0 -> 19738 bytes .../assets/instruments/6-bass/48.mp3 | Bin 0 -> 23175 bytes .../assets/instruments/7-pizzicato/60.mp3 | Bin 0 -> 15102 bytes .../assets/instruments/8-cello/36.mp3 | Bin 0 -> 25512 bytes .../assets/instruments/8-cello/48.mp3 | Bin 0 -> 36240 bytes .../assets/instruments/8-cello/60.mp3 | Bin 0 -> 28848 bytes .../assets/instruments/9-trombone/36.mp3 | Bin 0 -> 28495 bytes .../assets/instruments/9-trombone/48.mp3 | Bin 0 -> 28545 bytes .../assets/instruments/9-trombone/60.mp3 | Bin 0 -> 27147 bytes src/extensions/scratch3_music/index.js | 247 ++++++++++++++---- test/unit/extension_music.js | 26 +- 63 files changed, 210 insertions(+), 63 deletions(-) rename src/extensions/scratch3_music/assets/{ => drums}/1-snare.mp3 (100%) rename src/extensions/scratch3_music/assets/{ => drums}/10-wood-block.mp3 (100%) rename src/extensions/scratch3_music/assets/{ => drums}/11-cowbell.mp3 (100%) rename src/extensions/scratch3_music/assets/{ => drums}/12-triangle.mp3 (100%) rename src/extensions/scratch3_music/assets/{ => drums}/13-bongo.mp3 (100%) rename src/extensions/scratch3_music/assets/{ => drums}/14-conga.mp3 (100%) rename src/extensions/scratch3_music/assets/{ => drums}/15-cabasa.mp3 (100%) rename src/extensions/scratch3_music/assets/{ => drums}/16-guiro.mp3 (100%) rename src/extensions/scratch3_music/assets/{ => drums}/17-vibraslap.mp3 (100%) rename src/extensions/scratch3_music/assets/{ => drums}/18-cuica.mp3 (100%) rename src/extensions/scratch3_music/assets/{ => drums}/2-bass-drum.mp3 (100%) rename src/extensions/scratch3_music/assets/{ => drums}/3-side-stick.mp3 (100%) rename src/extensions/scratch3_music/assets/{ => drums}/4-crash-cymbal.mp3 (100%) rename src/extensions/scratch3_music/assets/{ => drums}/5-open-hi-hat.mp3 (100%) rename src/extensions/scratch3_music/assets/{ => drums}/6-closed-hi-hat.mp3 (100%) rename src/extensions/scratch3_music/assets/{ => drums}/7-tambourine.mp3 (100%) rename src/extensions/scratch3_music/assets/{ => drums}/8-hand-clap.mp3 (100%) rename src/extensions/scratch3_music/assets/{ => drums}/9-claves.mp3 (100%) create mode 100644 src/extensions/scratch3_music/assets/instruments/1-piano/108.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/1-piano/24.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/1-piano/36.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/1-piano/48.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/1-piano/60.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/1-piano/72.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/1-piano/84.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/1-piano/96.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/10-clarinet/48.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/10-clarinet/60.mp3 create mode 100755 src/extensions/scratch3_music/assets/instruments/11-saxophone/36.mp3 create mode 100755 src/extensions/scratch3_music/assets/instruments/11-saxophone/60.mp3 create mode 100755 src/extensions/scratch3_music/assets/instruments/11-saxophone/84.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/12-flute/60.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/12-flute/72.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/13-wooden-flute/60.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/13-wooden-flute/72.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/14-bassoon/36.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/14-bassoon/48.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/14-bassoon/60.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/15-choir/48.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/15-choir/60.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/15-choir/72.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/16-vibraphone/60.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/16-vibraphone/72.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/17-music-box/60.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/18-steel-drum/60.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/19-marimba/60.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/2-electric-piano/60.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/20-synth-lead/60.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/21-synth-pad/60.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/3-organ/60.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/4-guitar/60.mp3 create mode 100755 src/extensions/scratch3_music/assets/instruments/5-electric-guitar/60.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/6-bass/36.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/6-bass/48.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/7-pizzicato/60.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/8-cello/36.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/8-cello/48.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/8-cello/60.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/9-trombone/36.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/9-trombone/48.mp3 create mode 100644 src/extensions/scratch3_music/assets/instruments/9-trombone/60.mp3 diff --git a/src/extensions/scratch3_music/assets/1-snare.mp3 b/src/extensions/scratch3_music/assets/drums/1-snare.mp3 similarity index 100% rename from src/extensions/scratch3_music/assets/1-snare.mp3 rename to src/extensions/scratch3_music/assets/drums/1-snare.mp3 diff --git a/src/extensions/scratch3_music/assets/10-wood-block.mp3 b/src/extensions/scratch3_music/assets/drums/10-wood-block.mp3 similarity index 100% rename from src/extensions/scratch3_music/assets/10-wood-block.mp3 rename to src/extensions/scratch3_music/assets/drums/10-wood-block.mp3 diff --git a/src/extensions/scratch3_music/assets/11-cowbell.mp3 b/src/extensions/scratch3_music/assets/drums/11-cowbell.mp3 similarity index 100% rename from src/extensions/scratch3_music/assets/11-cowbell.mp3 rename to src/extensions/scratch3_music/assets/drums/11-cowbell.mp3 diff --git a/src/extensions/scratch3_music/assets/12-triangle.mp3 b/src/extensions/scratch3_music/assets/drums/12-triangle.mp3 similarity index 100% rename from src/extensions/scratch3_music/assets/12-triangle.mp3 rename to src/extensions/scratch3_music/assets/drums/12-triangle.mp3 diff --git a/src/extensions/scratch3_music/assets/13-bongo.mp3 b/src/extensions/scratch3_music/assets/drums/13-bongo.mp3 similarity index 100% rename from src/extensions/scratch3_music/assets/13-bongo.mp3 rename to src/extensions/scratch3_music/assets/drums/13-bongo.mp3 diff --git a/src/extensions/scratch3_music/assets/14-conga.mp3 b/src/extensions/scratch3_music/assets/drums/14-conga.mp3 similarity index 100% rename from src/extensions/scratch3_music/assets/14-conga.mp3 rename to src/extensions/scratch3_music/assets/drums/14-conga.mp3 diff --git a/src/extensions/scratch3_music/assets/15-cabasa.mp3 b/src/extensions/scratch3_music/assets/drums/15-cabasa.mp3 similarity index 100% rename from src/extensions/scratch3_music/assets/15-cabasa.mp3 rename to src/extensions/scratch3_music/assets/drums/15-cabasa.mp3 diff --git a/src/extensions/scratch3_music/assets/16-guiro.mp3 b/src/extensions/scratch3_music/assets/drums/16-guiro.mp3 similarity index 100% rename from src/extensions/scratch3_music/assets/16-guiro.mp3 rename to src/extensions/scratch3_music/assets/drums/16-guiro.mp3 diff --git a/src/extensions/scratch3_music/assets/17-vibraslap.mp3 b/src/extensions/scratch3_music/assets/drums/17-vibraslap.mp3 similarity index 100% rename from src/extensions/scratch3_music/assets/17-vibraslap.mp3 rename to src/extensions/scratch3_music/assets/drums/17-vibraslap.mp3 diff --git a/src/extensions/scratch3_music/assets/18-cuica.mp3 b/src/extensions/scratch3_music/assets/drums/18-cuica.mp3 similarity index 100% rename from src/extensions/scratch3_music/assets/18-cuica.mp3 rename to src/extensions/scratch3_music/assets/drums/18-cuica.mp3 diff --git a/src/extensions/scratch3_music/assets/2-bass-drum.mp3 b/src/extensions/scratch3_music/assets/drums/2-bass-drum.mp3 similarity index 100% rename from src/extensions/scratch3_music/assets/2-bass-drum.mp3 rename to src/extensions/scratch3_music/assets/drums/2-bass-drum.mp3 diff --git a/src/extensions/scratch3_music/assets/3-side-stick.mp3 b/src/extensions/scratch3_music/assets/drums/3-side-stick.mp3 similarity index 100% rename from src/extensions/scratch3_music/assets/3-side-stick.mp3 rename to src/extensions/scratch3_music/assets/drums/3-side-stick.mp3 diff --git a/src/extensions/scratch3_music/assets/4-crash-cymbal.mp3 b/src/extensions/scratch3_music/assets/drums/4-crash-cymbal.mp3 similarity index 100% rename from src/extensions/scratch3_music/assets/4-crash-cymbal.mp3 rename to src/extensions/scratch3_music/assets/drums/4-crash-cymbal.mp3 diff --git a/src/extensions/scratch3_music/assets/5-open-hi-hat.mp3 b/src/extensions/scratch3_music/assets/drums/5-open-hi-hat.mp3 similarity index 100% rename from src/extensions/scratch3_music/assets/5-open-hi-hat.mp3 rename to src/extensions/scratch3_music/assets/drums/5-open-hi-hat.mp3 diff --git a/src/extensions/scratch3_music/assets/6-closed-hi-hat.mp3 b/src/extensions/scratch3_music/assets/drums/6-closed-hi-hat.mp3 similarity index 100% rename from src/extensions/scratch3_music/assets/6-closed-hi-hat.mp3 rename to src/extensions/scratch3_music/assets/drums/6-closed-hi-hat.mp3 diff --git a/src/extensions/scratch3_music/assets/7-tambourine.mp3 b/src/extensions/scratch3_music/assets/drums/7-tambourine.mp3 similarity index 100% rename from src/extensions/scratch3_music/assets/7-tambourine.mp3 rename to src/extensions/scratch3_music/assets/drums/7-tambourine.mp3 diff --git a/src/extensions/scratch3_music/assets/8-hand-clap.mp3 b/src/extensions/scratch3_music/assets/drums/8-hand-clap.mp3 similarity index 100% rename from src/extensions/scratch3_music/assets/8-hand-clap.mp3 rename to src/extensions/scratch3_music/assets/drums/8-hand-clap.mp3 diff --git a/src/extensions/scratch3_music/assets/9-claves.mp3 b/src/extensions/scratch3_music/assets/drums/9-claves.mp3 similarity index 100% rename from src/extensions/scratch3_music/assets/9-claves.mp3 rename to src/extensions/scratch3_music/assets/drums/9-claves.mp3 diff --git a/src/extensions/scratch3_music/assets/instruments/1-piano/108.mp3 b/src/extensions/scratch3_music/assets/instruments/1-piano/108.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..a7c0507397443cc7ac9f94457f83917042def883 GIT binary patch literal 9852 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

xrN3k`sEPW|ast~*lA zp^P@EO4P?%>4~pQ_6RLXnaP?eGW-J@1hS%?G@|j`{;`$nUh((^a0!Uw$n~U>Rb)TT zw5b|XCdHf^8D<7KDi_UF!NbL+A5NBfeLmd1I$OJPJfjI7H8q&@&y9na(^pG3RkQKN&r0zaB_@r7dZjh zPo{fMAv()+Z|udX$%rt};;#Sp!x|H2`ieR0!r@}y>Qv=eZ{DilIj{y$Yf)S3LTo~& zpT5EGXz-91EF)O-Uv-kHK_KSy9BgdhB|89cY^J1sgHo`Iiv6oSm)w_KD`K?@xd%_# zHtoHAuPN~e&ekWJiecq^Oi%OmRi3XLm#k*x3%dBAA3(qtbdGfea4r6mzy(_u$=gWs z6;=g=&SosaffC&DVt!wteMdX`Zdv*+>ARyc9H!ey11jz+zz;t9<1>Il_J^-V(#m+zk7f8-uH#LPZ|XLzaJwfcL(I(2#`Mq0Kjf100j*L8;^j9gp87! zmVt?tor{NGNaUr&D``0eWi?H0JwszN3u`+^XLk=T-+-X^q2bXnu?fj(898|$ib~3= zYU-L=+B&+v^bHJ;O-#+qFRiS9{kHXU_u%N{{P*Sc?ce){N91>DsY$EL3-Y`a^+av| zzmFtD&y40G4FLXldXAyVg!%vbkN;nOBkt)30YD%%ig7Ohz~Gm@m!E+r^j~O@1ZMfL z&3ZtvG;beEfZV1~r&E1ot09V8m_siVmnY%2aJ{KeAb}>8x|CATd~+`}Hs((RfTv55 zoap17;Y&%JTfT@40D$m!+6YEJJ}Ow``MRrT7(RC>IajKt&$>@3fC7@ui$L6a459#t z%+Q22tT?w{2->Sp=1YPKejL;O@M1oU?(L%tMHw8lVhD|urUxH}MMU9{S+IWaaiKsy!dizzjt2;x-sl3$zjz6yy-3MmUfJ7!5wM)GK(gJH zSXECO?MK+GJH~26)oGfX{Y*|y^XzzN?nTS@j@y?k?3#Do@#pIG)XTQiY~=&toyXV9 zK=B#_IkY_?L8O>sWfu^B$pJY`=b!=h+yi0!#q`P|@Dp>w+Q?_m+dG zP>tS=ml{8Iw+3<@@FvqG1X0cw$Yd`$;1E6lHI$MuULlM57oY7%R`odIV7c`acVYSl zH?jJHUy3{fD{h}_t!Cq>2yrl0)mYKg7+c6md@5(iL=&BLKMpP)jU;7T%Vg`-E5uH+ z*;Hk-MeJ3UPMZ(uTRhg^9h_LZlLB8`c@(bk4=c);E>42fs%=#?-%(wzU8OC_{=U6ka}yO`^=AqcZWKc!Gch z(9)X_INL4V+NCPX-=zLWrAZ-&3Vp2^j<;RO`gfqC!|NQvVYpLMIF~X=#d)*@W?-k+ zo>uUm42$r>q;SAx-ANhYHxdUk)xr{N1K4i@6qMJix|0$Q{hCs2M(v!knAGv$x&g67 zuBohFc@rTW`0L4*QV7H;x3&nE5o04g6!6W;W80nw-wt5zR4|Upfa`{;3|Y+P8(zhv zwhT1}iwj4mf3k-1m8>dbc_wSKyy76N;2o17_$=$=e5K=m7f}cS3fUQ{4H?z={%(e4 z=9)8(q+!NUd~L?%{80B?66g4XXHxpB6TQ$_BH_(R{$L9P0+Fej1em!d>D_vQfC407 z9uac4E8prQvp@V=(}mKDKmJOQog}Nq5!9MtZesVDBQz@;m1%CAkyQ(ap&$WXo`l9_ zaXLo!y{({XiD4pzJibx{M=wFwBf&mwb!+>RgLFVm>e1hbqZkxJi6iaG>=1Yy^`Q&h zTyUAq41csDF;9t>RqQeHNybF}!1y=@fdKsThBBN;1^y{?0@Pt=q5%L*rbJYQAI#Gd zaZe)$Z~y!w!rb&U$Ss=B?@Y*PV+rgc>7h#O#_gM9j?Z9p3Wn~z*ngll$(n7b*gtN{SA#qC73(sLsc;h7KpO2|h+ z>95B=YBTDf(wxf$=OaShjaFgDk+E*)8;e14(p2DNQTjT;e=vXP60ihwIdkHW`!gxERqgJ2e9HswDhfo5@hH%|3 z#@1l2{oybfwTz{uCrAnirJog}cdU}Gp`s`GNIV*NL-qhhz2uZLa~7c}#`ap7F?Y2B zyBL-hmlwFRpfvv3;+`Tb-`PL@be-zBmm~6Wwb*csF6tztL-En z@~w(ICoL$0kuOjvYIpSbkPW>2a;tc_J^K_(o@TdZF^BX)y#d;UGE}+o497=~LzIKq zUqxQuqGn7AfoKB+E~wi?>w^Kji2f{k1&5h{7=^Mwf)rp!eEUe~69k-44b)AMGt2$0 z&aAz|$(ojnUuakgL4-OH_V4KXw11T26O(d8i*TFc`(K8hNCjy2y~!gDbV6kTNIYb9 zeE#r;lUGC~^$jO2PfzkJWR$i{{WdKjvtDP|2s5@LU4D})2!Xh{fARS!1_&j%1i=YMuDOIVE+>As?M11g zUM)#z4q5A9;4}Y?PYG>y?zxCo#M@D(zIDHcqmjzNnQW1HX&0yOChrjlce^*;TLS7x z(W5>7(JH|F+F%0#PGS#IG61rzD};VXD~p15tRtGDT+lhbvg;u3wFXI0;zu`LXxPaY z7H93nf30cxP-Qr$=&W1_J+LEE$)b&xT~L$OoBc_qz_v?aX0E8=!zmu8%6Xfy7@y=r z`{e=!&X8u3sey|@sqVfygFsxnDNUgD%GLE#;F4tdVP$EdWP4jA0A$AfJtjS-sP!zx zZC>h%s905QmPO^(;!#_lT?L$IAETV2I#B_C9Wr;_XlT8G#|?C7WRq7`-}|2I=cClM zU$6HZ{c`wD_q)t^!=g5Kc}=)X6{&I33-2mqfZNuygjk!$rF8U&C0lZW%A^34lH?H6U?(ejD~T|TV~N3H=%!(jDTTbko1i*Iis&rK`HQpNA%#^aI414mF7vYD9t%dLuY`SWJ z0U;St0Q9(xa$HCB_;Ea3TDD1T3{*%UOO^;a4B8wa>dChdS@bnZwXyXzA7NrrdV$p` z+*f46Kwm-11jE$b%eLR9LD;}4{{F+ysL#^F-*f?QQ!3U-4@Iv+%H2s0o;e3;QVk`i z)AD{;9`ANXARa#n!u5vAe5DZXo zwKv*nu8958;52D2P;ZhaILM```Hh$oF#gJTN#duE*_xW=E$g5m;_*nh(VmJK9@glA zelyxzBp7F^ZlEoE&DJN^><0|%9d6mvr&qWF&c|P_73c-BGBu~Ou6YuqAZhM zXM!YuQwnh%L_9xQ`CpL(AvQ4CsQC@DhDvM%Apb!C;{R$CtV1ecJ!^MritAr5imWa` zr4CC)8(TGWj}(v}HK4}wPFaJ>loY~s^}?)r5Lmc4hpp5fLmm1mEisZ|J0q6=6PJ@) zhTD`>t;W_pJv6KS_{|tuK_YLWKr&%boft0kZ2XxqLqg#pGSyw}of#Qt3GR9)aWQBg za*|kmKlSQkI?%_k(bz|D(9=4hJLbt+rerhV^>wolU=k*Dor(xMYnMwF9o8&nv;>f{ z&`1)`;u#N(AI|A3zHBA>le^$$*Kkr9Skc|mv(DK^=gR$WiB8W5hlF*f@l@V4N5T*3 zD}Gq(RZ++~NAnPd8>=?9!AGI@2Td1~IqrXz;5dR*g2UDt#hwqc#-)&B19jA<(6j)? zLzMw$JCsGvCiv0fOSLH1@wyaF6plgq;&%k1SRXD6-QJ3tjP3;kz9U?4d2ofo zDJHj=aAJ6FWgTUHH&$T9&+zvHUMHRmgmyyOoZ4h*#r*LI#Kvrt zv6OTq3exZ2H}GSME;bGDplAsHmkyZW_=DehHJt1U$0_#kCQDktsC{2;&@1t9ll2Yp zNXR|qeVSB&8W#G5#(0=D)Z%Co9J9qg0m>fvLZG}_+iNz)jaXg2aQvG+F^lDy*~M97 z`gyf_c@11>}IF+U*?w=Xff*~q!^P;c*GmIcc2{XH%W3U@|4 zt{hx2xFJ1C47E5*mNba5jN8NXg$7qzJ`dhA7o}S6MGXui213jC=nmK%9>81OdC%#f z)azj}x{vP=7h}J!7Ot_=-+b)aMhr=;-*1@l6P9;5xhVPsA|)V(+rLOiZJUEE{G{(& z1RiomUpepxe704E=SEtOqOSSbbq%GyJ5Y;h@6}sZI{Y1{odY>kJ81?3% z-oxju=T?CAxT5Hny2H1~F8sr>zDx9H2-%j_TKJ{irHxit!V33M2o!=EJ-Rt#lQ zwjVKrvFW)*ipFxye$FvL6N3+;%dJH3lgCcN$qmb5I8XKAZa81~e%rW>yt}Nd*v6-P ztG{{aJT3ed&*weHp8xi_sY?83<8!5tV!Fr_Fg;vvZR$WCUif{3P_p27o-$)#0|g0@ za1E=B)@!zS1nrd|m;aO7fl=@&{s#i=8FGlMXfbU?&C&)FeK38K{PuY z6MS??Z{!&a`ZD~YJz+wny6gS$+1=Wmx9fa*=Ni}Y)XT2Kyo!(Qv$ambIe}7TKttq+ zir$D$%_Twle!2fK8|#%7c&(ps7@q=EzzT}@50$B4gGxIIp2tJ>EO9ubmRJHcg%)?^ z!v3^WFeR8O;&)c3d!~H)nQX9fPpc23x;yvDr{P<_=RdD@mpLO*{$7^&cy576TJlmX z0s|)=ia>I>PeDaR!R!6RciM2V)kU^DHJR6vNQ9W(<;2L+-^er_ql6igZ(7neJ4=2mjX=?q>St?0hh7Z_#p zAs?IOMxz_>S=AVB7^+l6+D>{cj_Yd(DNyr-(42D8-)2iWdk2!5oGo22t6w4yJ{Sre ze#X>256hO;*FFC!!iDE4@aNNlqjE$GSy(}T9b6euEzm(uJh;G#(GdM;ATi*15YRPX z<5&^8wV&eQjcxU7I6d#9werw=XEVfOk5bZnb%_oDYvQ_r0v~q>1fsiPgMKFaAi#}@ zX1H3~g7f?-sCc335})|ocI~W+$o7Ph5aNHQ;KqvFa>Iqt))*ok2~BiU>HkEDR$nYa zH>z90+5P$X!6Cd5G#$A+sjj>qGMB3#eK~+wNgH>zz!l%vWhX}W}w%|Gu z02H)ugRVe>MLnIO#CH(E7-3hGJ}iKyJxDJV$uG~)zy_un78Wf{^QF&hN_)+kI4nos zpBM`dKea}QruMCBs9`{SY%h&_qstT>R$l2%ldIfnu+1J@%ldeuyMaLL)TLDj08|Fj zk;UsNsK8LXxK@4*C!4}LvNHCrnwsbrZNmWTG_Xg@0h%mY+&P?@Ena~-=t7cDjy~rq zP>b5$6f<2CZYG*5Gb-^dj`>#&SE+)roOAmmnM%?_HZgq<;^xt61Tp5=E(j*(gN|ona{HAUgmR|Bte_L z%MiUTvi7ONpSfjdwr=bkfl%1z9#SpFNf!fXAt#fvo0#VU)`FzZ1!m~2jR!$Qtdv`2 z*iR7fLh+1R`D=IOtv->nY$74d(@|#>ah0?7$*3@M)1jWsE=uS`Di!Zg!M286jkIxV zTDkO>GhncIgmFscJw?Rtw~U!Wj(YyhiNhv^#tHo`QR;1F$Xa>G1ljM3oqr9X{x(4< zTJ=vr&-eQtH73;snfw~iU+E+&}(1;V&IW z8B92Z*mz^POV@r+F9N-kHa0Nk!MfJ zrUb@UJSjo8FfVJ5eTvOnp3%r-@BLEKi48Dd5-7mloaCOOfySu0kjVZcd;(uV^B{^&Q~+A>a*+}lpiPJf@Z6^Aae~oKW*fk6qVuoY_!LI$qT!W!HFxu_0IVp4?>n- z9(Sa&`!e=ukU^E188#yXL#y%VVrGQYYw%rQwu3vVwtu<6{lnlgxis+{y~)}h@n4jU zKjXg-m#UfWAMxhO;8Itw+f9A-!I=69o=}n03}Ai@H*Ap#Sx>eolw5kNqfB7}p+lIW zg-z!D=#QM1ed$Izl@UV*m@hhDD_p}WiP~kUNt>3`R`_VYI?W^Fi>weQL@8+SKcHd2;9p*A*g&k+pZUf| zI2kQfA>9X~XHh;*CWVYb;It7-NrGZLB_bEHDm!Y__lkvo$M28WKbEJU5(Dv|?fmLn zc7+3tcAKr~*Y&IQ+SS(W-4qqSaYge5S)~8g!3pSlrg}j2LJ!}Yt96db;b#dx)AeY7 zFC4w^exeY-G=*xkij7uY_acWNmGJbwQU)Sa6kJ`{|o~F#Fpn`ySv+evEjz6~w zN%z>13V&a*fw*Kha-kX z8B{RLV?eAxSi|bToi9e7`~7FLgXF2xxEo0wKP$kgL6nsikGnJNr-jBlN8NbCQ6yE zl4Xd;)ZMsG0)M{&2K@Ib0vmg>#V>#}fqnP`rXxe)S)_g|#X6 z!YvtkCG~ShrN4#=8X2R+)!k%{DTF-wLX(6jIJkcOnVKt&R?T)$BCxU$uL=Gj=9Fe) zmSLdJJRwtna$+=_J5H}Aa%1WHwSAUI{n>n(6O%wi6C@`dTpnko zt^`QLOvIB_ffGa8lSi!UWQ$tIkrQQLZRk0xtH=_33dDi@E&!nZW>sh%2&ShLedtyB z9Ul?-R)?vMn|^S_i8jODwP)^M?sF!|j|P4w2L0%Yah^}grUK$aKJnJ>+7;Gk+Fc`u z4Nhvzz$^q>^AM*3spJCx6cNJjvUE7L__5Y)wsgWPiAI7JI2>lEeamf;4c&ih@#O^VluV!!H;;a`{koOD`0DZZvQU88Tx z@q3Ph`wv>6_wKh=5(AVE3;1+qF*S{X@qc zDeVW-BMrYPCI(YECu8O-EAR91udLsQ$Ro0_)TtkNuh&ql!izJ{MbV2!Uvg}DpQ6Y< zJkr})5i#hrIxu3Tk0>@VWIk^f6DYqY4*YkVJcjfnWb+tE9CE5)U|M*>vrUhQr2qUn zxu5|O*9*8TU;&_|N{28(mBLjQyquAGsRLU>#>x0`=@-xK3a}W<1*8_mh z-IjES*#dgxcb4CqD4{a(lM;#M{Hih<1xH{#LBI*ck16J_%`+&R60#TWqW*^o0BWSX z%)nHJ?h>nF2*>^mQSOXmkg&OCgo0WeWj+0 zG+kg#jLv?(Ny~@Mqq|R=X7l%MNPTa3|7$h%P9`OjDSA!FhYFxZn5y{~j4j84_BbQ> z;LZRvsJ^4%hdjrj*i;M7Dm#-9ai;Vw{PG=f=G|9(`(xkQh2B#o>q&01fFV|i+2Fy% zKbO^X_nc-Jv@stx^L9;hypCe3IzBjaOFoW|l_Po(w}{8spu$rxT=P0>=1PWR&Uzw^<+ht-3!Kwt6+PEzaI1}+m_duDK&|~N zUt*KqpNm$$K{4RVs$nROW<#`^g*k-MHwTB6fZG%sO(t6m|IHZpxJ8W;fvYl(i< z*hf5NMpB>&nW6!MZ?fP>^7p?l$n_1DoGVRW^je^^E!n8Tg115?qg7Mvs>l?VLe$Lm zZoz>76shI@umyBZFpPE+E3At0GuvxzchZ=-cr@;?@WY((dS7Xd2%&`Tu~%|vXkUtl z)j9FB@Y8rx9d&K@YZ8)M!~5QEi;LH#3pUGXs2Jp^Ed?*R8!SiamK`42yGZ(Wa{3`2 z9}y41ft-fU*bL4N1rX%1>+g<`=Rponp$U>7`D+`RDyxa?4%^7|I&7e}MfSnA0u;h! z6838T%pCm&3;;rDVHRJs&vF_v5A!`R!Wip|GctWt7r75?-K3Z;f3M>{C@OK`At*m@ zzL9)kDA(1=M3H77U!65MGoDw4KzvufTe(7}xWr^hVA_brkbGyX4U~2RmjoU_eg+k1LxCR|Usr&%@&h0zMFb?IU-c?f&6o3rp)Td{HJhgOSzQp<;+A-<2;g z`t28c=6MKtVcaIJ6`lcn^24iw9~Bt1nH^1ru*Odh72A=D-t#MLBd(|FdvEM*4+A@{ z58aP?4n}*BXTCjeO&Jqi`QS-0jL%P!0)+s-pEUIK4xnT&0cS(^@OiS7z=`3#HfUkY za*!fz0T!cmB{ijU$;0pZf80^~vly?gmC$#Nt?~kS=S6R=q{-SxIQ?vSY35JgJK7pC z%zn`m>jOtCW~VJ{Zgh6%#oDUVT^`Q8Z!X_B=$U)p9n(==s#`Y9Z48#yMBM(qhSJjm z0Jk?VE7^YfUN*wVhAMJP<$<oCpg0Prq4SvGq|3#a%xBVir zi_mUN9ldbYzcU|p{cSw>xG1bfmk*}JB(uUUJU-Kc2ipvoZ{fR4z0{|;B;1{HA_My# zYBw5`pjMWzGa@I2hX+#tF}NTe)bp5!v{%0eS3amN0W}U*-cTq+*|c{jDhW+5fJ_DX zR$p7)C?MHr%>!<>)SX5b!DhLFrg4>%_Q*F#OK!Yi>oVPQC z=_Q6O*Qe0Tlr6RwPY}RBe5YdG+AaC5@f22M3-h{kK~NG+dZKM3OCRuSr)~FNz$G6g z7i~qq00U?^XoAG1l+qes;4$s%Fh5nanyo>ak4WJ2dPR4H>brFpx0GR)`>UYG?{5%@ zZ{1E_Yfi#yd@+t(faeG|>47~i00WljYA**AN|Kh2pv259C&bj|V|in};LG9>8CFT> zKG^RwQ`j&ff!}Ue+)onL6H<5T`6rPRnk?DvqSR;WPC$!ZzG@ealjF_U2YMc9op|P1 zr&H(rrY)i=W}CDmS>TOU?~mS9&M;)_hFG5c(U=T6qHFq0{{u~AKp}Jl#lqmT3a%Ev zCj6>2Lh!Hin@ztb2&6y)ykcJUuBIZ?mXgiMN{QTTzH5}$WkP>=cJ^EGjp{l>i~Y!k zWe37{C~@BdwG$L;b%NI89CQVUMr#gyTsY{eSYfAMu4g*T6Yn{Lr4Uz-Q;K=F;+rQE zf%)V8vjEB3wq=u0Vx`(|oS?QA; zdWV}%CLbM}g^!%<3+Lqvr#oe+W_iuk^NqZ_)!RH?+7u34 zB9K>b>G||;W~o~efjEHQKhGI2*Sdc>ddj?jP>$>a1JF+0ih-dKF@;v_8?+EmcC9o- zn^B1ZRi$_oL*;*z0LJ|E9QlfL8-^LK9#E9i_yVmz6|ZQhsC>hKVp)sS)SqvoNN{V6OF7wn zKO|%EqTDo5`~i?Z_z`iiD3;=#;2b&zeolAih<&CN=63b^ZsvKt%ilxO4U6Mr-{Du6 z%=G1OwpWb6*oae#pKeyZSQ$Tl*uE;1!NP+N;+sh!&gypgHN=GNF!S$){Enf>wee|u zA%rj*!pM+a_H^F_BNSY7{9HrGcN@RC?5f2o4aZ0-xnr$fW%5K#7wxViPKq=`^mEYEi`Tn8 z|5CCSO4g4m;}lAA-6Uv0Y&tu9pCRNN4LV8^)U|c(mBAc6ZyuL|CzWoZsD5?!JRo1Q z%_~%u5d$f}*q%QbBCyb30bqq>XgWBo{5;wYeum*cDXiW&^DB`bGSO#;QOH6^%uHCw zXbY4WLy6bK(l#7u4$=zecG83tAeL?}o!6)~~LZC}d`~4B@hFDPk$R@XLLrPimqs4#))6|0L0eXGiQpr+J3FOqJc4 z;bT=7)n+==cGZ5(2MX5Z8|!296UCC++7Dm8zd5|Vw)?ieV<$|gG7^N{4h)3=kZHhQ z%Le}=+qwV$x-lTS-SAv*gQkJM|Lowwrhe796%ZYpleM|MuDKtX|WG$ zq7%?%>j5AbtY}!MmQ6OK_G$jMrKfO_DnjdZ`OLqVBc;Hx;#@zz?wW#Fz4k9l`WU?D z;YKdZnlYbAiA>!WHkQmB-`#eTOx2b6h&OX|E$R`QFT0tobp&rLTqEjx5D%1Y!gFhR zQI&G)h~mkm0p!BtG({l?8^79V6{LXA3zJqrr9ejy?R#EpO@yif^5dzDp!l?;f=Y`b zUent^@T4A!P_TSDy9QU&)=3JBQx~a(M=q_VWj98eQHTJ20e&(tWDnLB-y`k^6GbD; z7Rr^oJ<194I{Bh6Ytv&JfFh_7fwW0EY%~ zRS3X2bq)1^w$n%OA#9{s3#!5@8M{zGbHvP07N_dB5!WW=xwDoI+3XC8uwOIdUcp~9 zh1UZ)9?uPp*Dl{tNhBDh7yiLfApPq^#H9;@U_q2N6h)omOi*8uqd{5YTAZf}<}On{ zuH3A)gwBC_ov^c_vgFXuH*Rc5p)$zE0&%xaA!ED!qjy0khZ}Y++b;nDfh^P{6;*nF zP1Qd^APh}l$>*)DX{sD;wmWQw+sS>iAHie*R4lF?LhQoCjP9SO1(3PWX`_&u7Z$S{ z2+5$RoO>%%UtYNM)LrXzIKqRqRb_(;cWc))A1n@$W$OF=yOz2K{J&b+j@v0eqBpcW z9T`v~*e2Oz2A~Hi06!lrVQuG#8UhnXUUeq@s<4-8{1j}2Fmk$3J2I?1@9bG6HIQ~w z?!E@-Cl6PRw~BISnfFWi$)L-CaWHZ@*=%F zz&|R(;73{V$wP&U>xzQP-=lMVL8{J2v+m?n*5#D%Zjui^ci-Ap7-mNT*L{LV;~Yd= zlK{NeZKX-ze2m1JtNsD>>OpH=B}Vt@oDdQe=bws!&zAX_cxuJf zff9&sm&RO7n<5SZ#oPx4-y?3jTUb~3EsCte+*!9(4dKq6ha%>nSj_- zxR8#6mb7uE?$+}DPU{i|KvuBvZ$61&vXtjK9Ip%}61>AV+W0&TPA+Bk9u;kB9YW;h zjJjLQ&r)bcRZjJa)7M9Bh)vbIHTIa0a(k#o+}(I`)3!UNDRm%sfoO=f`3B3UprVE% z&4F7zPnY39&@R6PhX(TpOlk0VSVe{?><7DbYP|jjQb2k&4X24k9qr!U8Qj|}Upi846&)?4sp?hc}0mQ|oVCL2W;&yOF^|0Cma6}DIm2eju zj%L2pYQAOw5ZxeOl|T#~Z!f4)C|PJ!|K20CbG8s;^$DWm4N?iMxx-TnZdh-5ruaoN z@AW1a56aG~+NR@{z1g!CBqwB-R`aim?|Bgx^F2LP=Dy+``8D+1G`;lyV-6qy{$?@K z9CR5mg-V?!*;YQR=EuvCRMMTESiH}#tz2BMK0T>kGn$Yo zv{)C1ECI-mdsS*FjR{O3} zNM$1CqxahO;Ip=jPJzG(v9Nt7;f3mZb#?aR)$Fv^;A$Lx+f>y5EeVpvoa!xlTdT=- zPRQ0mOT)#`Q3W2Wy#GOv&rbft=d9Y?SBP!MgbLom{wz>kL9J?m^+NAFpK_yFB#Ns{ zu9QIiV5ys~?xRKdcZB9mhgcP$<9!v`0_Kw%IMH6;+M_GKbT zP|~*b!zQgMJ%bZOG|1)EC6J)tCwm>eLE&(VU1ck_?N3F) zPSSN!r^7lg05}PC>nG(K?U`oMQX;{zkS;e>`MdVE7|&YLjx8P zgY=SZANCZ5`gH*eA5$jUTn^fjs*p~A?gtb?~n`UiZ)q66yX5~E(W5lw*Xu@2Vj`!fGG|TqIxhg zkvPNm1sYvc^_%MVjx`wYGK!6A1XSkUxtXJu{s#eyzZ=V~j@&?;HQG6~!WV~5-chBI zQ2kX9Ue2gd$T=2NP%YBdskvN=pYi^XdE?A*??Iei5p;jrll=5gIzcp-ToG7|&Y8IR$UZ`cZljB^D{C5-RN-l3L zwyyW($j19|??uPqo#D!Q`U6#!d^j$EF<2`Iaa@Zm3CQ+ndDWJ_ObAYnFXHS0NwOX7 z<*M~))$>%oXi)pDG8|Y<#e6}kV8-HL@!u|r0!R><%UN4vP=qgJCyazJrzo6nAD#bT zu`J-PvV69zl0W_R5uzHjHcVFG%~{17le=H!dpvoy=ChYih_(qUaZvCq3#re^&qr)} z-@m+ilWZV6#p5~3UW2$w;s8jsrm$|Y|6oSF`vzr&lq`_Z5Lw8uYzxurVR51^f%M0* zLiKYhw8-vil~=Y^17F0Clex);gx@luN(*G1>Zevd3dRxMdLTknmSZ}Y%!6b|$~>JT z4H&ZZpB3rP&CE`BiwIn)uUFT8ynFwbd&N&){6nm-oof5qD0h@dZcmR2l;{b{&AJ5& zH@hbIT?IIa{+$+~hT*Y<%6uR0@dc;p2}pJWlVd!Rgaf#EaX zs!z;S!oDO>E8Xbqg4YF-8v5{uH`w~!Jn3GpP0VN2_WbZMmng=znZ*eCiB68@#jo!BRFtsMtbLelB-0AOBW4jb^)tpuC}u(teVHKW5yN{0TTe@np;Hi1e* zal$TWZb?rBq50(23M#s5D3>c7wO9D<8Cay%D{}m;7H=?8DDmqVBBc^0+R#Tit5B*D zJ&TW7U}G~AN$zC!oJ#A#&Wv{5{EI%7tba5scQ5k!FkIYKS3wgNCg ze9gWYvK1|J;Mut!Y^dHOJ#zmQMgk~7dm-l&g!5z;pRN|~lML-wg>GXKtKY%%ug5G= z3)65zMd;~?W4>w{iE}WrzpE}j9-c%MTZ!V-f1UEFnPIf)Lz2h)Pat?^Cm(a0tI07 zEcdU%G?JpFfs?nPt_m9-fNouBC~AuStwQ1$Nk7H_4N5dNPHdVOa>COmV8y5u z`7rkQCPcWAg^Lq)& zaoG}&3n9sHX1-Z#H}AJS^PYM{y(U7L=-%$2xlk{P%n-4TAf;z}N{D+SIa(RWX2Ons zVwwaTQwjo*_Qjy5>wAJg0K|9oq z%fu$H{{}WXRKCB`ZjUzw0eh7&lioi*U_%@M01)DC+1v*F3_F}sjpC4qNR3*Jftd}I z7Xjg|G}07dNBi$u6fqEAzYqzb)@p~wj=eP@?{~s1jT+49B0#lyWn|4cHOK5RX5wV# z1AlVM4<+KOpqpkB#j$r$`n8+($qo*j>vFBe4{KlVn|&C^olUbl5Uria7E&|UP2NEY zAwvy(wXCp+i+R99)x}r;(+A0-UL>nM@Tk<6_2{4K_E; z)z{e8xjt8LKPdsZT$_yHtlcWzx)NmZL8e2?NMwPUMY4Il9y?l$mF~7l$+DB}1g_JH zlLExhFq^$FyKy_Ll|-7-Fqs`@V!7&e;N&^2D?bS5aio0V6|BB_I&1M-MZ&aHn(D}5IS+|k~@3d{rjAQ_ep`0s3ZLS4Wz~lm+6kt_336+14I^X&i zAwB9pV!Jh*6z#1gD$#8#wSGmM=|mmwM=b`$^{w9$#pf#n=QIq8t4_v8tG-1dx;E}6 z?i>$lJ{bszSB@v`NutK)OClbehkF6!k8Q)A)|gmlewYvx55n1l@IQP++r*ej=p-ms zImW!L^8ej>BnE1}%;i+iGpHOB+;u90=P9Lb2N!DbZyLL2t2)y74abUq2jmpC5jW}9 z$ZJiUhD^8GVq%G@xEn`y2MdcUS?f>6;{fj3XM z;CLx;nBW247h*+=@=@GA5a!}TlI8k{*Yt9XwNfJ8s|+}~tQw3oDwpRmL*FMo9G(pD zH8YX^-mN?_IO-Yk&N!&l%!+mC;cQ;=KJwEMJa;2aR+U#}#~fW|Pp+OCzj6pZ_r1D% z|A<(#-4RH;t4x7deSe4vjR0UF+D0vj@;pQnXMenPLDS-Oem^l5PL$-#a~jl z@;GUfI{rT;0ODJGkcIJA;kF=4YcYKB9rk43JTzd}&nj1SRm03UgdyhD=bQo%y==DE zn1{Ed%~w4hIov`mCQO{~E?91rH?8x^4>Cted2eMDBc}=c4G}AHz=mFw_GXh$g@K4rTqDD9n_AM7)tK-qK{`ImIgy(iTUUQtF((Xp7yzqAde zLf+%ohYlil%u+W;%%~)K?)w6-@n~_Cb@~~EG9%JJq$pXXf$-fAysP;fUTXo8m;XM# zbJjw6ft3?m}>rECg_cWwN8+B5a;XIoy)W8h2wORVdu?kvJ6jbOC@E*wI!6`!7YjvZ2jEH z(+}Dkx`UAfdO5*REI?ENWfX4sL|jUFabiN5dV2V##r3pySWLZW!Twn+OC!IxU9sgh zlh9B7595h;cKMZ?j{E-(Pwul?8&l`%->4d0byAIXN}jdyxB9psOr0Jxr>alos>`Nd zaa-abx{*7T*2XqLY!*H+Q>6!lS7qgw_85A)KmbA9w;Hoz|)ZyoLM=(oYxvF1piNo4#%9&=XD*bZc*WZFT zS0_!YN(UI{qrUTr&mXP$HlgBMFL1UJ?^_@&5E`*F*%~{}Rh*0s)&NETo$K2|2(&?l z$CXl*D+qH~Za57WlPy9Rb)ZmgjHm;2J77DgGin5-%{QT^AaYT~u=mAsiI2h$bK5<8 z{NcQO-RH&qifZ`vpnm&?-+En~kHK|mI_o{PGf0u7W_Lwy_N>;+$yZ@dz3TS;#$WTR zCI(}B~*?VLW|x znSr#rHn76SC7z1NEI>6~8f$<|-`Z0N99GcFKSJMC056^28nb|M#N@3g7>Go_O#j-w zM9EfHH{>??J+D(Rm@?gHRAFgTttdzC^@pXUjmOq2_28EIx^k203>5x~T{bC%M)LL3 zmL34q<}QBzG&_(8?&J@_7oXA!@Yp104MKlCNByd=87zqQiozq5(1XH^J2Gk*GEU%j zQa~A(j4oHmo~$t{k1x;IfR&B|D+o^Q9q4o&nX+@L52WBIQ0Movmg91X!lY5`QVTUHQ zmp)goFeoBuVZKHVT{4ytsloD*IH=46trg%Yb|SRn^nxfupaTZtwae0;afz=w`q_>G z8+jQ~iK0)nzuII~PL%LmowtLF;OjefS@1!tEqnIf-->*A$@HWjBiYdSgGwT|ZFO+Z zeaL2|k1o5>iMNlj9(bbRai4do!z>iCEXRl{$ly`o!CKPr8l8}m2?MtT#Ty^UL7WV@ ziIhyq9tpFw>cxp$jv~!3BhGh@^%ZALn_HLzZRKdjmA-#N7e+n#BB*;apL7oHWSlUQ z)?w5HCRDY~$5k!vC}7nyj?ex!oS!q;8jMx@aPKlleE1O1qM8qH-^8z=7DSvNyOsa& zh+;xq_0e9mqu?kB&IfxMyowA2Q>6+c%m z(cAh*!(92Pa>tge(l*qqXn?>$P8s$Ru^rMKga{?{bsOHonT`qZULvc~xj2dRHC3xj zKXCBNkfoe7F`Dr8VW>2$4tm~Me}VX>=ccUTZ9vbVqQJkFWPbPQ!PC+bbTc~lR*g#z z7c)4H9@^*ZBg~3Jg=J&iKUjAB7%pJB@0tbs=ZQD$wI&ef+}L)Q)8E=%a8vB3)5|OT z@dWA@{OfDq-C@w?ba(ET4bvNWepm0po%WfIu_OQkCQc1sWw8MuFY(i+MUT;2nSu^T z$&kzsul3!=Q=_z~rlYX`xCoq4G#(mJ@SODZDtwHV{DxJEdEYMoL1uq`St*!RQc>QeuRpw16O;N-79@ z$M5|Qp3iyiJ-5!iU-2T1%NG+>-H;;Fj$U65;f^jzXpiNnlj}<1!&(^fa(}9)Yf+yD z98E6VSaRdN&WWm*dYTp12nB#qgqKAT(WT`Oy=ZP8w|y4G5R2(@zO1-46&_=t62_5y zy7;H&X2Fs?^W4b+e;0aH@+dX_6#SP*fO4|^s#gi)M@A)IYcJ;)Y^MT*f8R~LS7)?9 zm{7hA$JZhBI&zJv{N@XD4-5JM;1=A}+oa6H3@zqVJIcPbo<>m%5+xF4nF@cj1Z*_o z87LQ=yNL;1n3bdD0|hCjXwZmu456+47gE(ujzAq%f!iG83>(Fy{Y-s9S>W;Xk;xXi zSy_P}<1lvv6VGpCc;gty{c)BSqTI#DAwVljO`1gFW~R+tnpEW7X-s<1M14CewWjN2 z{vz_&jrDaNZgZY4IS~0!=ZPH(hl}GGsK`xZ15c-nY?#Df>>|YzCqV55mod^lom#e?X1rRj;oeg#LGE3g@CN2c2C(0L%%4IYmVQR%@Q*x#9zlHd z2!gK7pVr6bjeXel61s;6n7Qd!nb|-?sjQpSr>~T8@~i}PR|*CPj?+_ZZt|u&llGk7 z-l{H>%Z+DXx>#GEG>5_0IL_}Hb^6PWrOv6 zKQTR>Y^IZ^JWaSd?_5Y&$+}SO_Pf=6@{o|ylU0{gZocbXtk0bEW_cMlf|A=@x3`tr zIy<9DL^1=|m7Dr^UvmPcasvUfve~Cx!TxMGxh1+5kY%p5`u_HVCZGRun1~O*p&Xip z{*b$t@~gIN7EXVUD^u?Xx?i1d-jNQL%;a`{hw%K&%ar4up=PSI!tXh&ycs(%{^eB1 zW3pPmCYE3!Wb)25EwuPu81iq3-D&L35Oa*CB)0bA-TFri^kv$(`240n6u?c(eyHr| z4`4JN2&-O!+klRZx8-^9R40FHS(%v`akLAK4wdz-j)VqD+#CLh45H$WxB&W#VE~AB z{j6o@S?4^1VdApnqFlG4#w_fsd+v~-lW(>k{C?a6{zm?twvyHUMnEvn_hh;8F8Zy( zlIxk1CXxSI!VgV@U04Ko7#e1fJGN{ApjR0>Alk_k6KhbxkeB+u{wEn4FspoIkO}|16eK$91pG~Q-IOwJWj9^n z2O~RDS}VS9F-%J<5J-iuXBsFOF|mrK_KElfI9lFWAy?ANxMua54e?cfAVOc4^}rO+ z!>N$wCe?PfzFo2C2O!eD0eyE?VqZl7E)mbkm04!!w|OwZ2#37;)}T|qk|v#Yz&9{4 z|La@bPeKKEs#xLUZdZb>lkTQPGd<6p+P|IGkGGr_#a*s*xtih^z}c1;@4GjU$RpUA z#VUBdEH(^T6V49;puLz?vMqPCe!xPL$O3TCagjyBz%oi9-ybc3I2>4%@tDIvt{Hbk z+8OE9vA)t?h3i0aGq8<66)qMZ#7G8EyAFE9(C221G-x`llX*Xc?|KCOD;#Kl;XD6$K_N-x zC%2iP5a8A6l}6T}9UmX$MH$H{6lQj}eA5N4%TZ|VlAh12No7ToD5yqw|XW64Y|k^Ra^foZK=iO0=JC{y*k6O+a-ZT z^j3d4N10-0jGIzxRl=z*Jb&wdE`zk#>Oz=hfii!(=v-$9s+uBCH_AkjUS3f2y@4i~ zQu`aE`*^qxppT}N?WtJ5Pdo%O%0Lwzq|)g<3yRi@Lhyc5o40rQ<%o7fB**_%am0|k zP@IW$%vid4*uTU2_he6Blnv*}eQxK|htxB~26q^UH6oOJj^JQ&lJ<>0}QtgeXX+Zs>x?pQl0^7Zqo@Wp1U|0&RC^4hU& z>xk$1GZR1U&_7SANQwJ+n6*%S;!%%C^yP43TGvZ8@BDsCddy&O)6`~fF7BizK9Qnk zesHUQ`|$4!s)jhrx=iF}A&7f^?Qd9z0YDG7kJpYKO+EDH!zPxg8+020<8^?c(+b9Z z3>-m>&1{Y3nw%=fD_i*{{8FHKASS?9Zj2`mEnEAeXWej7ATJ@Whudlx^~n8ipDqt* zkIGNj-&lQ~-+EX5xF(*a8lJyNv$1CxWczO!qeUK4xA&w7w|{i{pfX#a;t?vDu84r*>GJ|27nXIRfMyeNh* zPhKf%u6)Q$WX_w+vs1y_36LtF)jk&j{|a?)UHZj$`=rZ@oe(8ub$9t@i*exVUFJ-} zsD~XdXbTe03};1S7wPnKVK30=R_K>_fj=!^64=~^w~LY9mewpwftA5qXk<=*`0f{V zaLK_1i($nL;%>HB*<(4)Jbku^VT6cAAVLH`W}uQpjDa+2us;cuTwLK#l?X|l&=O9y z-rK+22U$Nh4HgzGK(-as()!VOv7DTYA-Lfqk02065X)R}zy-9nNQ7A0+7c|tw=)9; z3;uApmFZv{5`Nc`rD2`Lsm!oP37vnWebIj#R5P_xwR>g81)U56UpdXMR@_#c1#jf< zdu2E%hGS<=<73E?A*^RjzYM|O9(GA+3&%gFa^|g~mGwk>x6Gv0sP|Tfebin>PXh!{ z0&#oNbAL*_me5nM3lIzsD2+2}?a_4l;Yul%XW>`Kz*#MWwLh^|O^MNM=A6)HW&E=` zYVY~D()xLa-oM?M;2P&dDnr9I-pL)i4YPSei@)jdiYtc&MOiP_Ufyi%RJPFUSsw!! z$9UyT_Fn47$;mvDSMRKnu<(F9Fjg!SS3Bwv1iT0!Wx+Ezzup$QFiTBaip5(3R(4Jx zYcs?PKOHQ}Ssq!EEZ4D}+0d5;x*l4^mD;sD`{g{1^j7 zd(o@_G;zQ~O!y|U(@5P?pyh-|lxBY9q;GjO&1$C47ph(PP`QCiC2m{i38|5>h%~9y zgXUN#dujCMJn!ArcQJvNUPzrcP(-vzRQ#p46duS^mr8h(w*yz_6T0=Y zN8ULhivz=Mwm0`8iYZP1G#=PZblBZRLJ{rlii!H(AXiRxz)<&-R#6Xj`>rVQpBDpw zg^)st`ejLJ&INmo6kk(nrm?lZ4lc>Jq%#_mhkDR76U8;tXzrg>MS>lu{_=h8Vly*W znKVB0bS~`>ZCCkcfZ=SMFRx5RwNh92(>ZLPWuq>@MYH zqJ&fs`M;N0$FLC1U!TR-|5K2vxa%X7Bl%V?>@n4Ix9fJUz;^bl?A<$uhA*9LMz2Ue zNje}wfcL>9aBY)ZGq{WXxs8z8m%xwc;Me=T@>vw}@{0SKfs5{oeS zp&)=-Tm|wS`RrINnimhoVywFi>CalJjEiBc0Rg|t8V@%4|iHI z9YI{yc|sM3{XnU-n6q{nxKbX#)^aDn|mlRR+8|8_q2@j=les$eg7~Q0c8d_flj$^Olgeak_2+R|1O7-paBgZLD1X07An7LO<*C@eU$iSJr|P@FA58`d=ePfs)@MyI?prAf_;BFUN9RwLAWjTpdD zTC>%u+(vvSiwe#$?80Tkf`|I+lNQwldY~?d#M&R&2uusS>P=Lq^~GlBCV}RGy2_OM5TDJ~1Vn-|~HIqJI8_sQ|g?(H*wF{=o<`KQ^MowWQv62ImrM zn}1ALQLd|mOai{#dvqb}2$GX5R+I~E{$;XnYfWLXr^jR1p1G<+M13LYR-22x1w9oeMJgNiqNHY}_A`H>@0t`dxnx^pqGyyX>i( zmze3IvwR`QZHqpw8}7>&kk5MvwiV(a{uiCJ@+$f+ukqqBwpehNDh2pbyx$|?mMu&_ z3gt{_Zj4%9`{_i@%Ag>@d5QdEJsii9jg>!z4^Vc7YL*J4mOF5mn2ro}2e#N>!0jJC zK54R@Ms!LFG>P_Zqdu~iaLjj0h*fALt$Z((7#lF|0RW6j}kFYi% zSpJ@msD`G>l*$0m-R+a)sL%woF)HzZSOk1YSr8grS*>qNFlX3@xyE$PvK|qIwmLKy zMv||ug&Z-qj&_E=NgvYz8DZw5uB#O!X6yccJ12YtR7F{jl}ulo5lZ3`FRW2S>F3{N zF8EjEC#>`tcf(A>w98h`l(G`4z^SHjVuDl8V~k%N;9EaBP1xOAQ#%D7Tx>~lZ;*E@ z#R3=V-rU$D2t*M;$Rabmym54{m8GUUn?fm)04GW&{Z%GL4=XxljlNQ$0xCt{3+xgU z41HOY!gKQ*V4cAuIn^_t9;~ltTEAQ&6JnuDoje2@zLr-d)jcYDuSj zUVoauEL67aw98f2&7fkFXrO(i&`_VLM88P<1>n>!mgEg7jvEVTBBmxxl28rCp~%%v zH&jsJ9};0e2lb4;6edhkRQ_V3O7r5KBzuT8NeD=KGbL01AYo;!&k5mp_Glv!&zlvTu<|l& zWaM6;LiFQCElFMlE1X_$^B6^@n6^6|A}%BR&Ov zPaA>my_eNZPiY#W=ED~&YTI>MRi04Ra$Sb|R&eG~OtpNk0cTdw&Q|G*y{m3>^!5m_ z{dN`>FuVV7Fn9N`@>-)o;#>U}qbG)0Oy5*^-U9#t>^oHx4vv^?vz8A!_WKSpAIWT@ z8E$y1a&1AH3Gu&X>8H{dLju^d&~2;M!%6iJl0#aYmr!#zLZA zSB3(Irq-=)akoygZB`I%hiwH($Tv0M9{f(DrL#0%fLEc~Av zM;r6Si8fe(7Dk8RanOv7BVZYW9>rjJ#>QN6ILB6%W4Rt62%%*#olW?ZZS2pQmNz|d zoaP_Y0y>nPZzk34y0qjm3wv|$?^CP`zI*Ozg@c6ehUk2jIKp1pSef`37w`m$tfV4y zWYzR!^atZo8KUk|fIU5vn&`~)Ocg~d3Mv(_CJc@K@xIv8%$C@}jk9z!nJTsB9uSCyfy4*He8qJIKD#jQf~5LMpUg%^1bgCHQo11nuDk&gCx6aNi(0s zJOO2tH1vLS!A4>7usSl)sKk!$jW>)f1Cp7E1?QFOp&*EKSK1J(0Q-_5+pq&XkS&4J)Y?$q(m3 z%6uW@oxD5OP-dI3Bp=C#F3JzF4_puH<|hwq+OI~^;lm14B1#fkt7mt+$k{`y#W7Ui zLnpc&1)`x%0CD zyq>=lh(!IqU$58Pv@IqlOJPZW?Txl3cPa``jL8GsB)CeCebtNaH6}Np|GKJb-O9qW zbBb%<6=(qaJ7uj}-g#Gwr~yIR56iKn*f1cP@Vit5v`d<0;626fIyu8_4F`RWuYgS4 z@kbEI(1??Zm`+%l05N|LrtJHMfl92L%3r1Gj0l_l&NK^Iv@t* z{f}nyXWaCF2Xh57-p{2*&cLMbI8~dEzm_c(6g@Cyg6B0Ibsgl`uoW%{vC-=?lhxv8 z$AO*Ev&D;5&x9lbsg!SbAb2k(62&{SD21|pk3^g1=NisOQ{FJdb!I8OpeC867JB)D z50xMPt6Pj{xJr59(I1O<>G=BD6PovL0GPN0NaW{;79a_q>1+}}`Ad8v;LetqCS}SD!uo61+0nJ%^fGk14rU0^J(a@)rN*OMYhl+;#1h z1rJa#a@T2B;BKGSwM=t|&uDowBu&we1m`p-2Rv~U`_c^s#xhA#OY&SA&ye-qYSn1L z{aNG^qIeHMcG0&&vCt@I;G|4AI@P~;LZ#I0LYZlu*S+}owL=(xG_Vc%tS$@w7vlJTlj^X@Wib7*_MGHUzjGQgPQd_T}|p@vQ0HN}lfm(WjSa#0=%;cyd&-)G!D z2{wo2@zhe(RcE9z)Ng|#-C@b|WELqvEYt}l7Wy$`N_^`knP?guJYlr7OGRrOk_@gM zOCKqhp$WQV;fh1^i?>xlju@v8$E68JxY%*)u$$uOjXcSvcmZj@%NkWpZ6UP}cIo@- z)B@bqO-iW!JLa~wHvgG!ePq?jnpR9e1+0rdyfh{y$4YHmWIhrA5J#>GuI8dF!4uUf z17gmDHMzY9&IRpVP-Hrwi(|fT3RE<*Frs01=@w3VU%vP=3n=o^@??@lWH0}(%*XrA zT99zU!iOn#)%?QGcP0O_q>fERrHuv8=EiS?zbA8lvTe~_appFm$zaJ&KwBVVVW;Gv zbdKvjnbRD%K(?GSgS*fa~{A?yIb_cxIMD4&Kw6`3y{zv6G*c^DSy zd%Oq)U^MIWie_nL;?`iT>)&(XvSsh4^Y>nO_B)w$JK6YPCF2`qgPP?cB4tg|(_-Zg zD8ksaWrlE;!^pNeyC`R6f%RUM)0BH;G&JYduomfW@G8Y^p$-)BgFWXhqpa}CnJquM zW&3gzX7u>{fx0uWnuv{`sdfUSsyqiH<`OTek4YUhdFHL8Hk*lbTnWmrB7Xm9J*dSb z(gM&)x!&kOt9@JPhu3?(uUe~ZNqdFQ;)9X!+K$?wIqfv=Za0|0sGNo(hanCRFyH;TIs3LC4O?b(rNIDjouu>UfI;fz zA;y(WB9~$mWdw_Fkb29u$XX~h!P38S+`uy7|X+V=pzW^Xut{x zSQDf-dJQgjDbLn1ZC_U+Q$QDsLWGotQ%MA_ph-TRdrzL+erC+mt#;iV)Kb*lp0usF z=44=MorOkrF_u9~rEDN51>27b2=2PJ7=tlP0=&>!8IgsMOK3(}~4_Xzu(Kn#*k23_8dZVcf{NN`v%nEbG?o>hmZl zFY=Uu&a$>Ymsi=;B`~3Ssy9Ea>s8xX;PQN(fglg12yc#F(S*N*#}18+j=|V~F0ku; zl#-7j-b=kT7eUe?8W#1=X9hL)AB5`iQJX80$W?&|M_YDGjtc~5CjGBR7eY0Ono1r) z82H=5;?jz5!pTw!l8b)Ir>i^t`yeSkVmJZAEMLkYry zZ+gG8)W$|TdC#i6b-(R=+PAJtfGy6m&e@U1wRyYyKnC{VegS1;E0jmB`c;b$#hPc9 zYLhU3P6>X0PS<%u(p1Q4bY!>*fF$hUSHEnO>er>8IO?uC2$?5bbWieB(dAh~U%`B( zT@&C;FbAAxKWqJSC_EeOeSPY1{+xz)bn!wj#FG-kb^|IWUUiqX^f26br+nZ@8}SMJ zR;~nXN}t@$(#`z3c0ATs(%$l_=-t$54)cm!VL2y_2|&$fUnTl4hL&h4Dl^1sO>Wk3 zd~K~!dZ;*P{aL&EJkfrrDZ-iza-os=m7DIvVEtrG56kn+@%0!NZ&X$MSlj_?vcQjZ z4Vh3m2Qih+%#8_;91LPumjJ@@hYxNbpXoNd5BDz|C3Fp&?hwU4FWs=iyEfMinVX_|FKR zo=nf0mWY$kpgC8Hk@T&o3tnB;5N;fT8oOrg4^Nx4x@t&k!;HJ@Hi4YJcq~(tKWX=_3h@HJa`W3Jop~9eVGOHDh1= z3vDx?@(~IX{;@5#^jihRA|?9P!UfQQsVwIzBZpYj>8rKY)DPPKbR>Ty&*wSyF1K#j z>oHbwtvwM%oH4HzW(;_6A}Af=KJQa;yX%Jp7N;X}X=fT+nT8x^6wto?ws&<}Qmw=O7=nm=_X(!}4u$mS(~ zqkH@tBs_RJ^TdF`-$lY!=E2Cxk890>actSX$2o_U+K$Y}AQW0j)q`ow%<{o&iI@2h%9;kiD2N(}=g?@4<M-?hLS_YLY8XU>$m+T;cLN0X~X?>1QsSQBLOFN?$`ifo@o`oH>nwf)gXnz zh>9l#;SvUANej3Me;N)7@Yj-HAf4w8g~Wvhr&V*iJXmjrB01#v?sBQD`qW^@F?$U3;f;CdNl19tG&8rLO?ZM=`Uk8!Dq+Dd&_N}4S}-f)(jzV6=E z&)45qvV*zo@~YM+?XIM)N4$h3?8ewpY`gpNlZQAJuYK*tOXS676LRYB&7E4y5g(&s zm4t@f2l4~smTI^P%07^*{9nEh0DQHCbJ25c`*&pDV%op@k4M6_e`A3)3w_YeAuJp% zDbC?>Qc-JU&g@jgWvvUV+AS(|qa(tWHaqed6|+rUnMNulh6nT=oyAUFdkrKr0JZ(gU^t<{w` zg~zU zgrN(Ut>HFWzE=4~u35p4)xNULy)-n4j`7?w0V@B6_|q|sx+p6a{kNb$L+92%SVsa} zU;2YejwF^pAjJH9ZklEZvfTZK9{7$<`bxSw?)ome|JqhtSuK*T4E9M1VoiU$`xD6V z6TK}&@=N^8!<)-VLez9*Zv*}&MBsGkT-FHLw?YtB@OpZAne{WO)H!iaP21I`wI{+B zto)*ZMk-0f^)@a=^;~)ZRzz(~X(^ag0eeQQsw{|`{Qot30LdsSk+X(w;Wd_vRAoVk zh?HsZMwGXS=<0Gzb|^lsxAkbM@uZ%UGT`q2MeIqZu(rGko{TXt&TKa=ZZlBsZlhn% z;)IL#RcRw;~e&t`@ zwHgo-H)^Y(i(jKsL}Kg_DH{g8xqo?Wco-1STq{1PX=6(%!H?2cJZ!zZ-PyCw z3Xgbmy&MsaN0d3e6)}Luq8Xn=}SnU1`az9HEnKdoNX1luet z>~3#uzGKUrFQRMr)ug3606$}$fOl{Ei|b?sbwfn8N{%k;=Q~;`w(oQ*f(@nuP2&2a z*;jqyCg^3MfM1N7jS=pspArsM`dO-#1(1CN0Vf<74F#Rhdq>O*veZ<>Z~r(h!yGN- zP7VbHg34UH z!G|Z@eqJP}Ld_xMd9SK(8Z=$jZ;r#7jiTII1T3kUu6;XeQBUR|<{jF2(*ds@PRR^8yeY4U%;as{)y2Z3qsxg1-U3IE$8~kFhbp-G zp1nC+eKvaiYuR8vx8~oZ1A?A{1_8{IkIppLSEPa_C7l9ltjvI=Q~)%>*ocg;OX6;D zhb)2*92n#aOsqOgwq0CWO&K zSpy9^Ewyx5C&t%|Su2v6?VNSbzx-}`v>uvpZ3|R8q0mQmztrw4DhkOtC>f=G&1#bJ zn%mCPXkA`8UgNmCa6RD?umBP{uOCzFDN4= z_Lek*xU5QNF=ng;M7*RTrDTx%3=l%afrW(?i5Hn9!`k=(2Ux)7;Lh|N$847;=eo*= zboMw>EjEkR^mqO$WhpF}lRH_|1*v|f)%t0aa67@{y1WZlM40V@n=@qp`WNU$N3@L` zdPM81UDlHXs)un#_T5=x8XVb7sXBu@CS@7}6HO}Y`?gV=B#zmoC!flz;MBw!8Xf13{7ovs5nV{lA(^BXvD;BAv$sK?Jg|NK$YG>8|TpKy6geyFHF7G8~&w&?U{oitx9M<~uGPjb@QCilLMN#PL0>%0zA|B98sa zqQeOsXoEZ>tS9o8juN~y{cNgP#2+nzG#toNgo-E?p8>*l2cI(EZmlmgU%wJ=GsWLhD3v0g!acj#deaW>008D+d^kjGusO92|Ieyj6Tep z7F`^`&BpIwzFG--wWr2HsYy~~1h#Qn7p#7b)>t0_xESrLj>5urAh_?(!6-hACYof+ zXzB`fRqOtwR=5O&eg+1~dZucxs(Q0_&DwlL zOzC%&%q66&eL1yao%A~K_jl&PJY0E7coVyt-_>egtx2514Y=~F4;sB*bJjpuSYSXV z0uj#Eh>h#zY8}(yn9x`(N{qz+6p6Uu+R~^d5x+J*4(R6rG{t7rWVVLw^gF#^>yuHb zgVM`}4-!8L`Tlf(zj=X+^=EiE6}oM@sLaURPA_xv1%D|C z;j}7R-OsozQjR<{0X?1aIR``C^V+p>T_VG}k2?;r%tJa_RwhdCjd665eeSy7m?qsA*t4AE zO}_m`%^UbkiAvvsM&~E_0I-qTTE#Zi8FJkTr`kA>fiz^`=s*xA%9q zUdK;DiZkyK7qzs%7rSBF8;kjYpIy73kJySgmJ?*y; ze|cWEJB zzC$OgOy8RSedNJN+UtjAurmOAsh^bK8EJ$VCHeqfV+wm@(%a|9!t}86IEx{N8xaD? z8~d;K;rrN(DmGXZ$xNH_j@sW=)R1hBe8Gl9j za6sFI{)O$9&fEtAhjKHCzc|sPp~gtW6}Yvn`%0>X*EnX#VFhw!zH%R$oSHQ0Jy1x` zxI{{f^q6!>plQ;JxG42(^c8sx;Bf)*H*OPjj=6bOO z>t6(Hp_GU@b_|zl)Z~ilcY=s_?`@xNy9@7f`*ykFuhYBG%3X2NFM7{uH*NWf5&?c` zbXhmG!9DXgeaMHeVGp~Tf8OQx$C-Qvfz{qw%#=WlS`DqXw9)_okZ8M-JQ2U8p}gp< z{v5!N^(~D-s5&ktdr*3}S^jYB7G2f*SL!jsGLewinJK#Jb~w2CTg2JkrVK&qcR{_d zgRIKq%o)2bM@RjMUulRmGOB>K5}FAN%oobPi#OilV$aa9yf%qHD_Iq!K0vW1+GAvA zu->HPS*~b&v;VYlXMUH;o0+=8A}BZ{XMv z30_D0aHmZPZnB;4ASM6)bsg+sc^fw~RD>BRE@Fej`W6c^+_VqCLwg`2RI4#3F1zv+ zv5&e-u>LH{`p!TMw_1|Ir^L&$!sEbGVR_E+=_~)vmVXLiUJ)V#MYSHQ4M(+MYHwI) z3$&&TT^VNuS<}*rRL0`sl!cne6?ndKd1OBzwQrEu@^g;L{-sUb#oXfKj6X1cJm*a4 z2gE%^b%0bK!zw0#WM>hqNobrvDQtIDma-=0eFi=mQa<~-rmL1 zSiMte7%gcX;rx1Ir=Sbc)A!GkwB$YQ@MVjTgyK@r;BDhvfgo90o_@?PS2w2?Hl+%& zn|u70b;?Q2mmDQs)7hS8H%>N_^grOxQP20>trkZjDvYsWDL?*g&zf;de)Ix#3^%T$ zrg1~}F9ZKJ&wXh6^SfOms52$z9FY)GEX;-&MTeExC)!+R$nznY`RtJCVN<68Y_^hV zS?i4}#gZR==V3RWj5mUAy|mTlWdMXkr~_*|j{Gw&DfCUWHf-Bmtg^OVa-fPRS#fRw z4>uW64UhliROI0#ifd0brE2l6y6q0?D4OiAX@4y&!hS4qQi+QdiVivmnq^p7-5ihJ zr|lXfSR^Hln7gT!;Wnk_bT6OP;4d`kEGiXc%vsGhFqJjjyEiP<2Q25vOY3IG`+LBA z%g((7X?_6EiC5k8^YhxGPgv_V$sJL=7)dK!MIRgWZ2|8>Wx1s&>@RgY^ab5Bu>sGf zg+U5gb5h@sjKzCtzV^G0mqMi7Q0NSuF=S?}Z1~eKq-ZVfD+Ld?QvjzSTb@or?U{?u z?cRM6rC}FW@wFn?hpN!8h5zV6s9pzr^U;OyuAf5>sZq5C9vTx7(0|fIbFXgv zY&fqTaJ$x(Fb}$M)+p$)f0`%d;kWef+#d1*f#m+Q zz_8h=FZEhXyUS5|?;m@!Ub&)6TnkD%{JwW(`>p^DLuSehP?Kh(sOa%0?!B@nt_%f# zgMkJa;n79mH?{0H5PmgXGOUzW0%&ukH>l01Rk*ZpdyVoPn0Tj)mXwr_UQS4;tef^U ztA{T$y?#vDm2qAjwZsL7-h|x-Ynt6IW75e9@LroE*h=;(lc=c%^S>cV!J+NTA8^6W zaM1lD2q-cwB6=iK)#G9o4rq#RIOZlULArv4(hGV<0yGNY`Jo%(z4?;Y(rN8R7igbd z9SI2-LKNj1;z-DSlVESOrW)Gw`(nJ@L^HWI<3Wc+MV0)iMmrY<^|A}G~Q(*RqChn}WuJGp3L$4qq4F}*d z{Fj~sNG!3QYSQS*p0_|z?hx3%3YM#6Kg6B5-1XG-^kYipXWCH&#L8vxG(`49+Rkc; z`?EGjyX2+oR3Vde|Rc4iQDXK7!ZDC&o_{u?ZM9cSyLL5i6$8!|tw^Yt>scgB;V7%A7cB zVTHS}Z|V67h7{)FgkzC)_2Y8LT2-a)AR$<&I<$VZyRfdSiSmp(In3rVO!`miQhQQX zP#o&5^oLa;B@@gwy+S`(Bdl&(i8h&m1G4@`4N`uX94NoQ*T*n*DeSwv9?B?99&a(y z0EjzL6|NL)U|!g64T`UFme3hcoDpEC4U@dm_IX~nJzLI0Y|tX0o458=C{63Dkzjs8 zb%K$o+_)Y2UFZ$6+3(Ksh;11D-P3n3OM*A%30}|cG(RA^ePuVnHg-q3pS`qyf78xx zpnnJyBWLoW#qGPJ*DzEx(dL`Oq3x}iPY6F<@1JrEEhwk^_1O*FXU4QvQ%{bRE+DUP z^pnCI1Dc0=XlDN3qQGn?qt1*otM!tjUc^GHo-qARd6csC*~bW?^55H|bW)^`h5$gl zbXIOCiOqq=X}&G1OWh>F_wCqh0ngk$eJc3 zJhf%U_eaeYjP55Wk4Z5mX1f0jgW7paqj9VG$g{On<*CQ6;jZh+p;rzoeS2Sf$^7Qn zqN)lcM^frlE7fl}hgESx4@`XGKZ^w(ZXhQ~pQ83q&sypZoNu2-CcS^!=BbGcD5Yh$ zbT3rxk^$gK+Ph=`S@4VG(OT5nbU?Lnxw>`Jjgi~qBe32)?Ioz6cV_SZOB4Xf*Mg_0 z=K1C&%VQ+2dqaWI6!RYQ3wNq+#5>{LZG$$dqRY$UbHQ%rOD@KC)#{;;i4lK4eT~06 zib4#v#^-RY$~T0cOuJx5m+vZ?X6}N42v} z=7X{nzfP~bUg23awhu{o40bs-#xeuYoD>~(XX!K2mecIhk}@81fu8uQzg#yfO~+nI zyjjUlHq-D#CXS+FJmYQ(vn)mQxyO+fi&7iNapYv?sn;Yetv&ceC(_4m^agn_Pfji$ zEBGCRh0-0UaF0WcBD#MG@AF2d{amv zWXVN>sp7k=GB2_nc>l_(h@ag8JOh!gXR-6X-VXj z+Do;dl?Cn!^)Jd|qgh;x8e80XlvW*aMuk(TZ5ZUghMTJ{(n0PzVD>CKZkom@uINWr z-FPL8AF7#5;nZ#LX1gR@8^YxEK@U7)&hvkmI4XU5I*>Yvq3sms@BMixXmfD$vC;RZ zb=7Tvt^q+m`>NTq+R)P>x!!Rl!3w$#CN9K^hJzm~HaIy5e&A4+Zpk6I;+9=>c^`He z*mY~5c%X!r<>DT%?+g*O$SyoDt^BZ?}^IS-zvWv;ssD3xXSTUAW>q%qcuvQ|a)G(0o z&Ml1$9pi*%TO??>Cr+;lVd{w=O39+}+D-H=N8jgU=&8s;gE?@%arQUz+fvxDWU)$N z{{lXbq&_jPR@#XPg>{teP_!zc*N-x?8>#2V%fsMnK3VmyPiA#8 zs$}!ws95z3HFnehZoDwxGXM$4&4J|(h9&6KR>*+1|A`Ap!nLuWU^u_l=8cfuK_%Xr z<3iW`tQ5$kG)A!4t!!vVtm7O2f!CT}ExtJuVvuGGXogDgJoBx}d!KeUgYWR_@O9FW zTNi9?vCA}R6w-cBWByQd^Hu7GlVu-FyLlG;on1oOD+mlRF2@ECP4lb1m+8_5eF3Zy z5B0Ni%ka`@r$b_TxXNEOx`pU@TFJdFzCNd4*U`UzH}zxz7T@rqu0)VSs4H-pO3v6x z(WoXZQ&LRA;F1~aJT@rTwLhrO@hqTurnv6lE=V}%CP#Wt{i}+EfY!D38@b}kp3gV4 zs@DEkoaqU1n1I^X?&(aCBJicH7D_q%eHlmt5I^+)@70BqG?hHnWYO9@5&U^jkw6*9 z;gDy{#(VY61c9c+M3V9>PDEYd>EI_Y(5i0gA@9s>9=E2z((F38I9oy4m#kV*cQ4Q4 zj9CoESCfFiWqN)H5Ae^v4&uA?EA9(^F8*g6LOdRjl=|Ve<365X_uTNgwm5!tOOlJ`( zzbDi|;RB3p*CA`G?zfcgNJTs`bP%{rf;CmbP(-o@{U}+7RPl6~g@?Z$Qi6x?bz~Mr zXUhB3WGYfks+wH2B%2-P$LKE;_zuB_Laf4O_d=LOn#SdemYIu~1t&@c3kovm-iY-z zfB3tn9;MH#kG{TVyNU8WLv5a2|1net79ChBk^`~U9{q7~Df@Mtsc zGi{4hB8ej`v@_O+4TFp~~vco|XtBb3o?;J{b>=PZIB~B!gYcZ`YTKKdy(_U2z z??GQ-P3M1FXto-vpg(xEKVfohNt5;hw(xx64AxnJ*s!Z(I`o%Pch0uwBw3v*4)$$< z(aJM@og4&)Y5(kWBLB>_UP(qc2%C~de1b<^e05r63wf`8#;Q2q4+2>N7$28{okfp>CpR|XF0uCpNIH1+!(fPC} z#ll&VB%%{k&0oZ6y>hx>)vnjR@Ghb5G-ifwzm=7hMPh|`?B#B05e(du)v$KlcGnSj zTy%H)KFjU5lTu(H-NlHtrFqY=k)r$hfq1(W2+PvbiygBjCYXwIo9mNaYz(uY5YweUtz3KZmUo&W(QSaIN_E4EC8N*C&+k2y>1n#z3qdyrY zaoYvoDm(W#ciRf5Z=!v@M$I0SkBq2DZT#rwW<33Je}9rER`^=Xv>ouApalPv7SW4k zHaWk*5r@P#_~pjs@*GSKWuxIc{-k8uPZi0f#mMFr#zVa@QW_tWKow4uQBDu%Z`e8) zE(dZ8&u=29*%>nD60GI{Zrpm=N12CRWR5hZc`(v1y~GPfJ;hS>FlDHkYF%q{5e-6b zW0cFNxFZ1$OLFSEl%#P7>wF*No{v|T&(_`QfdcMgI8RU!e|_j>U`#H$gE`vc;kXRy z@T_ELB7B3Op|VEh7_n$i_RP^3FNuSHb(S{s?iv*&B-zz#-e`%hkYhVP|GEX|-TT{^v!f{ZcmnRz2prJ3 zy&9vZPbr2DvcPG)uPyZhqWol#aAZGq=gucp$vpjTtx)7T&5 zhmV!uo-lhPhVy@aONC1R&?Uc5hGVvxky%>T_xjbhk=_SOAc`O=EvGw%`js9ql(#pK zw?Ra6l5sKh*P|=sO8xESppK2O<#C}dx|YipSK!ulV|$>n9*d6EjXdKzukf1#_~*K+ zaE-l$hI$A>QE*Q3X8?CoJ7$)Z}kCIAkcltir9d z-7eyI1b@^NtEz=-$otCsm&DbKZF>dH0LsCgY`gtxX@6vV!4NvE1c6)Lc^zNWX0Vm! zH+buFKVMs+Z^XV)R>7cO>kv@et2eIzg<#f6}v6CREy>RhBH=kFhB`W1}^>^LvceUbb~TP^*Xj& zf~!A#j-B!K`a)3Q zzxPblRh|f-EU$HNjlv-x&$MKJ`I9jo{L(yX?D2yoJPs!&nWF{z%LkJP7S3$k3O0r* zXUL|#sL4ft#`Q3XFWcYonz!oRW?0mt+)1Cnmp69^0fLo+Lu9-WhU9@jYfkdTy|&!t*>ss$c~rhiByB zApH+UD|E5}V)2_5j!k|TaN$7`_51=G4sJ8wqWe8=`^Hu(k)s=TX*H0j>jke4(AQMgiCZMH2)|rYB-caE zc36k~naNtu6Mx(FQO}pmxh%Tyd)LbMc4TUINau3-kRUJ3m$RN>MqQ;Bnqne-iEf< zzmM>`Nar}!$HBofRwNRPIp{yY#G+W`A}4)}p6{@un{pZ2NA0$YkDks-$yWBIb~?bY zY)?Vx)E|Ci`q(E7+Jtj}#DIFx zRCfhTvaug6&pDRzLiI7?jzZa(yqO8%lg-3F-C+gZ%*!A9U>8-3UGij>u5taS&n=`8 zF}I-Q%a}2xOxX_CtIK-oiU)CK*_O(*f8>}~cNIKl`D6udxnJCkdjG7*k2{~%jAcJF?(<-4?RREE7l=Ep>TkaTvA6$P*ijOI zt2o>Iy$X5jYU8GjJJw?2i%p3#Zo3J7St%5k`;L)lARq>WRaBvw?r)Q9ngP$VAvp=> z$dI&n^}~rPxfJ~E-xphwdvOyb2RP*P!Fnh_gm+~08o7F|6KxJ6*|^Z^ME}S5)}khT z0vKw4!XWJLO=YYPSGozW8d?^*vV-z?8cxkABi5(zrqIs&Wa#7C!zy-PpmMZt?`CV6 zYSNYYixPK&(_VeC7QV2K+W`jLL0U&oqowVsS?y(vh+Ez#5sc0J)Y z)ohH_yh*w{o0!PgH4F-|L=HX)W@k)`nm$iTjlcwfTK!X+Tu8vnMEzaUXc-O>vJL|S z1nX`d93{#o{aHlMIM(rh5NWicZ>hyUDB(#s5iK`8oW{>~>8U-?4S?0rq`q11L>8lr z*3b6m@IUUY^^89sJ=6{9Ez%^U^&~BmujK^>#@}?SSmLepW%ZIgd}6O=KYPSDj;(wXZN|{KC{SRE9xJM974O*@mlYqH$5J0a=lJp13e- z3hIAKDWk%+^#kp+-O&JrdT)A1eca&>+?xNx49z3tkg7?c=j)kTb$jRV_LjNmZ1wfY z&7C%CGPKi|Mx0RMw|DuYu=cCDUmYepF85;({<8MLUxvTLYn$Sx{v;gDFFc6*B_E&C zi2X!kJ<4ijPSP9GKbh8#6Dj}(cus&U6GY@#MBmWUPS6^yPK~p-G>NQ&&Zk97M z3x#;yj-$LAlN?)eYXSqtbYCCVg>Gj|fAJ44a`r1i>wSpeoE`}bChK3?HMA`-T^T;4 z3P%v)&EB)(=hEDrru8rEncf2+FmR(QoCpr1Z79^M-4kL4ZkQWVj`FS%tZdt3c@lCw zzFcQF(7P4;Ey!#xr3W+38*`AdJbc|%bLOO=X2-=OeX2Dm1-(M#P3#KQJE>nCHCo>h zRqB52j8~+|6sZYgW9*Bb>nlU@6YB7TKw^9uRmQcs#j3to@%U(;6Tx~e1o2ap=#8|e zoU9d@8-Y@IuS-HY)Wy_3@)q>0+AQwQ$H4Yr3x-ml@|yHwM2z z9w`Q82Kd9buTB#>kOfQEUAW5nBqMw77|fqhL5${avNI+tyKRK(0LTv11ymq7sx~FU z-%JC&bn@izu$bEBSh*g#h>1KX0oWW65k(JhmegJgJBVbZdT^J9aJ;2(;*_1gI)`5$ zCs$5nQM0_S2sl_XmvP^0e`aQF*fZ6*sG?|J%6!RD+H!qE6&opC+jsu-J$aD;dTy_Mp$fgWz%(4Zo}9LbPm?LnGayF9jY4nm1ctu6n&6QJY~gi z*mFC@*D?#0< zFP>hL=4_UxsqRIFq~o4C3G&?D2dIwuK!=5MIw%u_xSSU8ytgQEQ7eTZvBIPugl6iX zM#exs{K4!I$zu^FJ=u2{KywVpG6A0eqXnjqTsIiY4=V8tuzYGV(Uf2Ot;E=rvt5UC zM_NqsH_qe^d?Y6asWqgg+?1_k^ zh5Gml6sjxe`ii2e`;7e=)Cp%^C^erl@9cA~YgabER%Tg0`p&Fqe^Ue%g2Y$NgQpFL zCw}?c)fQS4)c(uC?~raK414Ojg$|Ppq@H+c3su01p!sZ)8zk&w5p|=I*6d=;h;r7{ zkFh{jp%Tjko$cmnPGXmzP3cS~K0!=ca|E0RT1&dYO#`0??5p|dO-p5^WpU8Zrtc=? zaE>ZGGb+%OTU!72v&gH)6Fw*bH=MAcn_i|FLdax?OFzb~2ZF^m0G1l%yJMYfEon>#_;cuR{dK&dJHhu2&%RB3S~O*LTs<=%w3@lR_zY^A^Z&NuRU3vvcJNuP!2@dZJU;4k zbERhmVe2C)7n+4dNZXJ;4bDzx@0MKWfA?)(`FA8XzF(NGkbBf|I+1i!*!-ANqKh5w zBr1zL2_#PFE`)sPWul);9}WFa2{QnoE3LM*FU@>ena~iCK%$68n3g4%PTRf)t*y1M zKCBXg1*eYo#q>yiy~`imSXzvjeXZ|(bNhbhPu^{p#(gmRP8XrU>xGV$MXwR3Gx$N^zHNdbNHN=ZD>H`Iw?tuu>cx5QubMb&ZVyEwb?!wc^WBG68VF z>zrTXwSP;^&Ihrf_=6bHxZzVgt36k3_nMqUvwM!!DAYma3?2$T-6-E$pFL7@sR!e# zP)?U3j}w~K7%&9S2X-er6lEe`w1>X9u>_m$H|Op-velG6HaB*#G?+rHX7eqb}PQp^~l)+PoWxgKE9+gQ=Rr%>A6wfXCv=d>XsJOyYeSnUKj^YC^Gdf5XWIc z1F&x>59=9qO*0PfBwwIrlT^Fg<;sF2ahp_ZK1pt!UR%Z$e?2-femxcmQpDU@6dpxV zI;3#ac% zyIn|xhi1UIa9~0*8a0sK4gWH5#`Dzut6q-$nSwK?fWpnY%;78@JprotYA4@B+WGVR z$g-?*)tX()2PJ?&gzI~N5;SdBAD3T3;f3*$=xF9Z*6F89MI|4eqNLl8{zZLC1B;Ej zb4Z6k;jIosf1JMgJ3-OLitD)(CBlpM;qPBOfA_KY<0eYcp&?$mW3Rj!sk6&VhpQ_7 zhJ;^H)PxV?2_Y5cc!iwPVF9I__ledJ9vJhplg^Mci^Xm!A=x8*T82R$5N4+Nqju@xY_5qnZ^NBa)Nx6jg*cHr86NNSB0Si5T2QIc9pYb)Gr+734xE1uiUJ444zr^_6 zfa3^_LVr*Ku)R=GpT42e%XXvX$0amjN6kM)u&P{%;b1gF=jBSQlVeQj;byUBO31&z z%2O}b@hZp~!s^ox{ckROYDqP(+P$0{tQvp5k@p}Zp^;GThh~$pFqJAiW2UT#hmI=p z2jg@5(ONYs4Pz=sGj93r5P!;Tjv*D@i>#B)aPx@;77>D~0P(TWIn|>%Ir*H$@jNup zTuM7#yKA(pDKaGvY_grIXx9~_+sVdJ@re=1f83UgJAqYJ-PaVn*1dT}hle%05QVP7 zJd49oF#+PlbH*7DeJ@x?8ZbLkeAVmEtDZZuAnV9wYJ~XMGY5}VO|Xh*cN>YoS^-); zl+piP`M?4Z^8cpSV9~T4WMT=(O7*vMzQZ5l!*Xg>*T+XB2EwI&|Hd^3i4xL^{M`E| zUVM8)fg#elbYIVxa6if1r+%0(>SR>d9>RC*kWo~)B{!B>$VG>rPieE|*Nid$hkYc# zR$k7=pDmU+_z51Ci)BTE1*2$GqS|W)Sy``Ta~6iv3DM$klM*?VAu8HV<$XcHYA>&k zG?CxjKa9TZC46f0c0`;|@f?O287o5?h`JpGZ{*^%755C)F z0|s%2wJ0}py_0d%d74{031eP{lC6ryaoX8eHsA+s^k@V&5St)k}(sfuhJHJH7(RD5_CLjQ3!2FKvinY$Du6)a+ z-zI?i?RB+XKmT~_88j5yZ59w*DIHTNoYHboAk&AlHNd?TwuidDOYb|M3Vz#AB+~3l ztTQ%TYNE|8niKfiHlSXKsP$@4QJyG8uDb@WF4ale?G_pZw8TojQx6u0&86#7JR*>qhekIltu8Ut^AOl6vjWloWy zp`>j7paeV+!TN8;hC-jx9$^-dXjoy4?zbmfFHB|F^j6b6)z3~9eE6My9FLLWSi18> zqU_YdQ1`t#?%KOC;~knB;~n#rZ^{B97}0q!$tyTCl+#P?j;nNK9P95sQ%B?Kv15P; zapn$jCxx^@jRi7+v^s>ar*q zadhD%^GKh{6hni3wV^urN+S`tH7u^tv)D{Gw8|}Ljbrs+bP4f;7htt#6EvcJX#WH= z5IY|qMx)3;1mc_Y8WkE_i^AoXfF%t z9mmw4)tTl9KEG~;N$d?Di3Z!edYQd-MgJ~5&lobigBhlbLS0IsjIQ6jdo!gcKfPqH?2{>9Xq#E04~ z*gd>dP&ko9AALgwoO51iTLcP&V#}e80s{cg)dVIKk2!F~sTqk!x1SK|?Fub`m!KA} zj^fHP?Ki2G+1RA|I6o&69CV^8FAkm~GR_>v)ew{VXmAW?a_!?gRMl+5$Hq(E@|Cz^D39M5!iX8t>b?6e15og8*Qa0i-W-x>jP39hKZkYcS&Fy3vz!X6 z-$|{+Sr+z6g?> znkgiTGXP#fbQc;j&ABl+#@pb-SQo``fX#Qz1PoLyQE>UDFUeuFM*M;YEW}Ucf1D~u zSJQYxr76z_b&Qwpv)>;f`Fc(AT^GkWDZG7o)^~#n6XU%K*jh~4ttOR)^5K>g&nNp( zjbDpMR<=pXhC;>GuhHM>Ebto6Eh-t}gcuhy5U zmvL*@cjZqc1{pfH6eSzdH@9_$>R(%;E)`Es?)**Hhpe*u8tf>tyM7p|D5dm&#v)%> zUHs0|ghBFqAN{~>8xF13__10o7pvwe75}zuCo*^3MBb5r>@U~jO_ji`yG!pDA(ysV zq(+t$*9x@WR5vXUKC9w6p@-M4?HcLN4tD@;MQ$PeOY*Fke6z8c%*EKW2ZzE zsB)X_w4nsK(|6KF8F$sKdK)s8H4bD4td+YZx9l58)nh1Q5J!Z|yUk$6khF4%56POm zj*Q^iWlw1iqcf>|d1_OhAY)&zF3iSaXhuEc;T;i!pWw|6M0QpF{FumL9%Q%gpdMa28` z42dpu{y0?fRCHE4#uneRFOj@VRO&~-OnVt(@mgfjb&Ts@+jugzlmU`V&&t;O> z=w7uC4?&%@=%d^=yH(ZeCX9LHzJ2wC%NpDa={CXAs3IW}G4KJ>`GJB5%f@~vYXGRD z+I6|jzC8zeqDYoG(qD%i0j6%1qvpu{>N|JwhGktM+v_^mNi|tcE~mm$NyhXA>c0MC zZ)U1}MF9dqp?X0VZ#73EM6;O39YAAI&%385JqeLXJaE!qtZ75_%@n=YFQsTW9uXkc z4|=05+_)v|=w=sD#t=@dQKFnFx654+As9o9QN^DmhT-l*shc4>7HQCGmD|>m`w`4l zBG>y3{gHPVfGo5*7#OVoLy|g$Fh6M}A*nG|KQ)64xNPq0U(}d6>3?Fu6imFWcEsi8si51z~A@bnhle-A&75%YqZXW8;EV zP#y3w=+5aC%c$W_Y$78>qAjI`iGiE@IR!Le{v((qk@0(yUhP`_e?AUG==hYrq0q1N zSla$FE7emj`f+l;-9PKBHokxb8hK~zrG|#I)}_0r+6Obe!Dp+B&gV|YczMhgZ2R zrV{cBJFzwif1x>o%6eRD1wMQXd)&oXa@^S*_=OU&H^QL-Z!06aMP231bs*~&P%;G4 z=T3fJ+XQVgkgWM=y;ce>S7Bk1%tDqu!gnuQQ7=%t)|@NZK~rn01GM~Y75FEJu**Qy z*nuEZm$Vb5I+raD37#s@5~=8~l#Ju|AWzUM^M#^wbN?&1mCX2`qgN}Y1)`m6*VFRL zY+A=@odu414vMt={Z*Irtbg(~-hdT`zR+F?bl7iOXz?^MY^L60gz3U4Zs6y-jh$v; zmN%}bz~_h;L3v(dicQU%qtCUnQw)CQ*UBmCRDm*6ZJ9L^@ENrp(eqG)o|AxFIzI0- zx+`()5>LbaDQt2=`0c+f^9vo(C0nbYP&Z-4?Kz4@B8J8*x~H8!H&?v$>Xj2`@mHR* zeQlwrNfr1-NGj^~<5J)fQOV>#gG!!Fb19y#%|K)~(ku=qQVrP-c(_C-9K=+4a(qIw z9QuYap8sc~k)ZU8tQ`6S6KHml1@r%_H2vcZp<4T7LH;Edn z8Ale(Dx_=;IuR{o)tH*3ORAs~s8ps%8NePX4I}2tA@SWU zktN`7wOJiO-Gaujt<+KfiXFWiy6QIEp!*JfVp8w+?ZGKeM{dEIvN61vcsZZt{ucTs zX?vrN4unuBR2cYQXYycH#N=N|cc;9Ako|pRIwXxw{ z;&Ec7F>`CJ9tT?y8Rzkk5OnsE(Ys)^LTjfptZHOq^@bLIPoQ4HCEkyrP_eD(-HBf@ ziaM~>Bg2_unC10yV%9`n(Ox@-gCQyxZ%a7pgpzn|z*5#4ni z$S*HukbpDWb=y!@`7!H*!gcoHs(F%Sc#;3*ap<5FWHAu9)NQBQ>@Q&nj%v{t*0!h!#W%8kjm2tq!ak885Qf51 zT7uH4x>+S7L6WdZPy?k!**LNVvrG>5UR-cBD{ z)-5{hNN6^5?U^tUTM~{d$v0;!^28e|hs=;w->EL#k9RYQA|x|3Zkr;B`QI1cSJ8Fj zs*E=N=ub?-%ka~{Y#t!_ThW-&vY*2LVA(j~1o5N5@T!l{V`Vb7 zlQ5I=wuYyM1WtDhDRDoF!e;bMc!tK3m4XSH;K4Dpi)Z9pdzA=rIx}R_4c3u1jKFb?y5cPQtZ&3OF(DQ!I;?Q{cUcCD_3jc z^rP?zlh}MNHwZ>b3pys5v<7xl3`noiV28U)sVH!8SAPQiC=Gw#i}&T;=vs}T*r#bj zz^G7vZh5;Ym94H?h!=y57PzVRNG5WG;<*b?Ls~^nJhH^9Hx{gKjEjW6GBejVr~l4V zf$ND`Sh#;-C}A<>auNmmJiJtNP-=TQZ9`AB>jdkM_NY|P5uOAFTAP=IA3`JKqodFT zWvHKS~8$ej*PNI8T^rmZmB@i%I(&SeHf}=F2u3>(?`Fy5J zqLP(3VxJ!Q)j252%c%a9qnX&T7VZ2rzPS=u1+0s?4KAEp?G-t1E+NX>_`7%4>aI1_ zRF-{`N`*s+z)aw`pNf1?0&p9J;0pjx*K;D<%G+ZIMe?$tBO120lkw^=(#@xbZ2H@N z6pm_qQH@s^I~b@ddn1A63_Qk3RmTxKEPwyN^+ce<&>@uK0{Ezrq;Fi^j+_MR&D{9j zUcB|cyKl2}R@wJg(Zvkx6;*Z>;c1TM?}UkqE9j^&@UFP{R1v+z^g`!XVjXNiBawKz z1GR3CeADMWq_$E|{6)DEO~Th$^}FP+8-kN+YaqhhiAUdYP5rBs^vxrvpx|kfns!2rs!uJv@0+f4RO^=~oVB(Jj_ohV1WAXq6a zto9{;80-`sCgK>sHrFxXdK+n@4&Fia?|*UYjNscU)Xwbdi1*X1~q5u zHI>zKkskgHe6?rcRsQQPJk1wffP$2K2a5aDh7@d4@9#a0#-f`32xImc4D*eG_skfk zqh#&|n)E83LSGc}GT|Y(piqK+l6+lHCA?}f`4UJ4*gh;^5fuqOb(qcnB_BaH>{+@x zgim|-q``tG0%!gak+jWvh!rEQoNi#-OUuX+RiiN=l5sFpG}{;)StLbl;jKiK#uU&J zY7ilIMdh3ylt2PX=`9BW7v$h$8*@7hR;1+c1z(+`A`COG@8JQg;bI{oI`!(juO)O& zW0_{_ELrpr(ac@7{^f!j2?u2}bl%pp*-A6JA!Dh-N+ua;`)@BeocD~CO!Sf<>wNq> z2@LPBZB%yy-ZVcdp;0SPThe;wnvLk4;Yi#8 zSZV#pWAvOA5REsI<;2m6wrr+!Yt=&NG<9n1b078n&CPs^}AE5lMKLgw-WpWvt_tz^)J>UjKhiF_vAL#y?uw}&lI+PKA zOy1rHh+W;0dZD4s*Ju#DplM&LNSlX@chqO5YGC?IZptD9>|EP1SVK8=-Jhsm6#Ws7 z9ORN>)wF+n7X0gPXHeL0yd5!E;)ktN1Xe-|1H-~1=gmM2{!iUOh>vUhyN8#GA5Osf z-{-wm%1{B|aTXmT$A35Qs{Q>=GE-HP+x@?(S_4K<`!=EDkJS;vZ1nex_3Y=`7*7Sx z0H)s62IK1@z23)=YSD!`vz5#=p)|#Ha1_SF)Cv19LX}o{u(cM1R((MK5z)K2{elD!#9bdSo#x zm)(#KY#$YwG1wp@OYEV4q$$mvCV7~-0es1(=PFxUsPSZ4mvZh0CE$VZEA$x~DvnEs zTUZ_d738Pz__)SuF)lQ&gHiMXNF3kYSkBLDAq~{gbO$duE>-_4NmK>KQG10ZST|}A zWRtPQtq>?Qb56g^tgh%mj2ZhBOK)38#6>@W4kX&TwX5dQBo&ChxJsy;pJ?Qh&M4rP zg~{QtPF?rZv(|B6YQ!RJy??c_*5EOnVET|+7?A6tcy%+7u+s}>$RMOEc?BAy2vFu! zh!mK8)dN_|9PLBcZ#HT+TV{~Ynq5xqO{TaEXo$djP$ivlgKblqTmv zkSd#QK_nMrS~8v0_|7F02?xQ}^mz@O`1TK3lJtQ{1OiB5bO81zg3A@4!wxxUX0>n6 z#GnQ@WK3-dt(t z5c}0^9&9|cX;Z<3e7!L}I!@6V)hh0yCb+ovuRmH6Ma)8g)__jST)MHL_`nN|AH?1Ym<}}{d zmrAEwG82yEmDN2PwT5WB!h|1z=&bKFiyFpS z&?;SJYvQVx`>CzmlolAycX%HtSd3cw4h%X47^=FssJKV}re7PY!FVLB!MNO!w?|3#oK| zDx;QV+AR(778IxQO>|?iw^rZY+yB0vp27u&78Ab*t^z_6|B`!rFK6o!M+I?< z$I#h!f7L7;?!T&zX{Er3GoxDZq|1$^rUL_P`i zlMyrS%1gH6xyYz+5|R`m&gxp=QRl9oNRtS$?wPoGQSG)m0f5TRmAW0Aw3PH82^&6j zkaEQ_tmJ!r$j@E{axM~3wDJF0HlZ9~*+2!^4vdRt<9ZBU6C*|lD3rtv*96S62+bmS zb*-3GhSLS=>x5sK*Y`ZwHmdW)Td^JAKvAjE%!$XMO>&4t$CYYA0=b_oKkwE&lC5;B ze|5i@-FHx@YvkzL8(>6|S+)8*rOhSZ?~@#bgHnYz1V0 z=8A}O$fWUCJW2R(dYTZ8AT$doqaj<9Kn0nZ>ZmUlML2NHeyA5FY4WuCF>wCkjc?Cn zNOL1pYD$l3VPfo{IH;&GbcRJhC;s)b0Dl!dN8f$x?0RNFcGPNqN9wwv>^FSNPAYOQ z|JYY*ye#6zF)3{h$(^(F1FH~e0S03JSuVa!N4BvaaU$M<@80(b|JkXvkK9=4`!CJR z3UvE7o*n$PmToH7sB+ey9jj0^VTBu8eDL7FF(9Sh^(*%Q>OKHZs=CGx9xi5W`iF<`pjaYq8$fhChwu$|y)v%VOlC`O}Q#>;%qg zf4p(f2g`4){LivUR)8|P?qGoF2cU$2FhFe7(Zy1)!IXg8X|S-OAZb!UO%$Icc*@FO zua>s)i$k{SHxd!`Kos}5Vt zupTTM1C)}$3*2I_W~?q^zO16KfDaJje;7k2=u$E~G$DeZMSLT&Z8a10+-G9{KRL0aPfk-S(kW$_>n_uJUpXAEh_?NFcnwalTuMmKe>nhsqp~`A})CjiRHEB zKNq5ch4AqV16;>~@X?4v<5df@5R)O*yr2xZ0Ua)gih|=4*}4F)hfc_76ulXJZ>D?0 zV`9QoK@8Az8!xq@Y!DGm!1thqKy#XoRjibzrEdn>BI&FN{5U+o2866jTQ-;G(KzJ8 zOC<^?NWP?pb9iqxv}^|eDP{=HI7Vu)&i9Y6DX9>?)_}Y{8z*K{%g*?TKNA9C^7aI& ztZPO5ZC;vj5J_8>&x)h7q$AwTz_%n8k!eqxJ}l6JyIg&?1~+PwH8OpNobpfl5vqE% zbTCztBxyf&kb&yTK%^^#Se|PjT8#L}LpH}yQQZ17AS>$XXtG(i$m(2Trp6t?T~;wi zAUG0V6J5+ntvMO!tQb@&v-iT#XeR7padD!$dQqe#J zpDKYERLeL3zyeST%hmjKKm&x-9K5_!+-z9>h`|B$Z&@5th=OS)TV%?US_TrEBRa~% z5A47bT+aG;Zd*eP!MKJ(A{@#hD|BB9le%#2MTje;xY{49=u4Wdxu~m~9<7$Dxd-Ge7jo-on5Nit@tVkR*0;dKQ^su?Q&AbD5FD(Ad>Ws@S#qF>ryON1}2 z=g4pQst*wN^8VskcJicBIk!ZPg6YJ5s)3zQt(JN(cw^9bvbE?&&;_+3b!=_TMV_X> z)e{euEKH80Vc;J?-5b=&e7*Nj&hF2LNSS9!0tX7C8F0L!lk$+3_-|?rH=H0e2l!I8 zZ1aIU8_2F2Ka}DiQYR_>Oj^~`KS;Z-v55_@_TQsz0y0;Zd%M+79XBK^3eXpUPsb7y zf~WUYMD#NZrA(8~%K2_l3k3-8BV*W%%X&4QjhEw4E}GIayoML?d=On$k9G$rE~zZY zETWXM)a?xdQ?MI4L+v zc*0fGU--tO2j@iDnen^#EY}hk3~KMMiN>{m`uFe-0Vp-#!Lq491Zt%~;DQ|VwflZ!q*L?HUUw>KTbmV_8NNmurql~qT7Y-m@*?Q_=->Lq zhF<1DLSxrjs&+cUnKW`#p<1I~qZlEd=tx0$#;#P~L!lV87BRDv%bdLg&WVq#=m5Td z;MXU}EM+=Ss-?o1SGNe$OAF#)7Tgr@H5U>+5b+AuUT?UuF8i}q<(bz->k+`9*Q87= zg$nI*&#igm_f6nC!$QKO`yvp8n?kq>2ha}U07j+3nm0q#0i#%*0A_N zdA%Id^1fi4QsLMVfG5(=B0e$vXuuqJhC83^rIkqWU470 z>m{Y|iIKoqm?33+HFe}OZ2V%HLGql(kY*ePc7=rK^1Aq{)CkpT2IbsPu~)A$YkX&S z`WhYee>K^mZ`g!AuaPG@?t2sl9I}C!O|VQTp7D9DAb}_?Celz=#*;dWiXNA8%V$vOVO>!#tVAuclx`6$ z4zu__p&HD9nSh{Mpr%1k_9fll((y#NRr+MHhG{)CKf0qw!=HP+VmoQi%q!c}yRQ^! z229rUo=YERIU$0inOgh{med(!VXNHaQbGC83b?yP>n-abt_0GN1Vv9o|3}Sly_BWHt@>JQH!Afc~;#NB|g{YM* zHq85Gz46W`spD_4Y7qs@?D;-4GF^&vRQfhcUSG7<`k_<5Wd4J?kY-|hdTNdx)DYZ? z%xEsZ9j4B(7NTI_Fto1Ju0Is_b8|Ar`T>9x$&_Rcfa3 zgF3*Q?~sOLc4~Pnj=jf%nysNr6Gt_tL0noAcRDap?1?9?M}bNToU3-RLFnkfl`00? zjEWNgeOFfbqx#6a(XwO1WKo4$exX&%*h=%Be?|})T_x%~C)!0Q?`jS_%G9w*rY~l0 zz?9Oe_i9T;uEo5KV{;Z>N_44Mj-buDz zf&DcAfaz~7n$UiRj++=RUZaXE4H1DjN-k2XR*eizClw<+0XE8OM7uOySLSGT5)-Y8 z7@ ze)hDy=w`e_Z?az~F7ULaKB@oX?ucbTg`J-^B4`GUa};|$?&PrYifDw3-a+P#+>I&p zs}UDY_>pny=!s1ts4l=|T+_z@y#r{82T!-+{7!C44-2J|Ou^S^gvb~2ac85_7yTD6 z#`ML1Njp6iA@9AZrT_h{)g+srZ%^TyAxL5!Z2>Mig(5CJLWj~+=p{;9HBq~hI?iF_ zD?&k7F0EVC(SbS$xl72_nSWef9T7M(GZhLtK zu{(%RYl@th9tz$mUvw;V1J3VNpz38A<5>S1*iWYQ$v<435UZQI=}C3N_6{k#Y%oUB zK-j`4%Z$B6KeiU-N!9VsXg?^NB;{=63R=`B2AQV zi!bF8yjqXsXgZ-i?y4x?%|;~$U(m=#V@cB@#qU-wYrpcF>3;!02`aQwe1 z{qkB^gDzJ#Ay2qTwsJ zkLv&8lg_jP)Ntd-#-e;)BYF;j0s+jVl9 zn9+OBV+{BX?c)Yw%t-Ys;FE+F3$p63>Ghj2#kj(|h31mEYN-(5t@WlkSc5?Xky=~pS3B(4>rC_74c zi$gvx0+}Dsbl}o*)4$q+wn|QA@%7mO%(0>#-^64_h_mEllk0W0K@7NSOO3~2&BQ1> z(9g!@n)B3F`t(r_Q;+)hQ6SEDO}D0Innot{wp%kcj^^7j^UdbYaS=tl#`aZJiF9u7gI_MCvIp=GT+i3(w zNoa*v`Ky%F-3q|Sc6Q9dFH}p;aJ>G6eNCNI;qJ%mbrAOj;56wWxbdcvD{1gWa)mhq zVbW#0stYWguvagTpBZR>d&k-YIGJ+9-f|t(BZgM*EuK9`+(UG#&j)@lYJdpnkfQD) zihQJUZ4(a7=}BbNu9KI3`J|cQD^+w1{GB4u%v>nf=i84x zOiN5mVc0TDxpGBtc4H(&#yLLDJe08j$=sx zJPFvvLW_>jNiSx}>NVoKqGKRX!H4>|uxZ6l#tFvn%>X+}!3a;ztB6?`K*SXY|=7RjKkegnGgh zciS4eZs~a%>bWxA`W(tma!mq8rkYMB#Np0vLQ)#pQZ`5m9Mk>0@evn}x(g0f%U(5^GDCa!>Vasy?Bi? zs%xeWFQ~f|9qOkAzTp^}kM!gSnR*VMv4@iTJP=Rm?**@-T=^jFtert3Y4#7Dng-X0 zZnd@F-TJ!^|4}!1+ruq2eNVX3G1kDSBVUqJk!uW!v8ts!FCB#fKSWT#&*!+(T#iSg zQnkN^p%*91z|Szf7G%NZnwbu+{^~G0BqD8lZW-zIyXHS7h0sy0UTr6vN%wvqMa3dm z&T%F&f&u~L-)B42eM%R?!fin00Pv!o>6=*~CMJ}!WK2|XO++4APWzmLx~wWlfjeu$ z+a)y}GlDzH_= z*kan#T`Z?b-ZBy3mfZPVgr&=(71ey^f7j;f?6DKPnY%c{Ei+m$BJ?_md zoXz*;tG5(5w5X=&bs^<|A}24Ag03r}GC=eu=(s`4WA{#4peZFT>^9*lS_W8Go~^jC zqT1S0Yc)#x{aJ2Eb8VT+kYb~MPS$8jF~9PZyzHj=sNS!Pn6SJK3 zSg=`DAXe)e(K5cqe$<`pn@f`3=sMxi-wMFplf^T-X!%`fdIb zAaGhKE{rsD&Z#Mx{q7;n;x4l42;~HA@+meQ}#<+x} zhAq^xn~|q#H1!)`GY6ciEXwx5|J6uK?+MK)N2!e}{8>&>p#0(Y)? zOaxgZnAp*YQwlQc7O{>WWpm4LvXMoPzDX?Q+M-D4uyL6B0nkCOOEVtq^__o0xeh#?j~`RLwL zv9vy!`D_FXWbK2;Z)P;@LJ@a4`dK*|bZ$z}u;9;MQ~;aB{y)T&6>l|VNut)w&$V(L zt@fp)pE+SdY=GLmf6f)wZ^67)R;mo6<*qZSx^HYh_%XNNjNRNXyoK}A<;x)Ababco zWumBxj7w$a>|EvTV!Hm-O;3nR5Fs%cW>ZT5hGNEccM~%wad(C)Jhq*&+$9Q`(`nK= z6=z%dZ)z4=@uxE)7?D3Ek}=((EOFwAF9pkm0%%98v;F>OUubhdzqBCC?q!~!EQES| zc4cw^RM`y1>nn8MLuPul`5(S6expnzTF9LBj8j6|gK%}i0FI9QPXhg5PQtr`O$oV~ zL|lVpGGOVyjmG=3)-9^~y1Lf*k%`mCzz?&cVi)JJ>?kf_h|+)C_!pZz@diUn&D4@-Lm_ydQPG6;Wpjw#taW`*t!^$*Swul;Osd z@7RRSlzXvE$e%bJDY|yQL~tM9LW(~-c`Ikz02bm@?P5h!mr3(iak<;2gZWr|aes*( zSonkvexy`N(XnfY(r#2LO!F??k)Fa*(GN!~Np1_p=dka1Xuebs#bos(r-(d!Iasx9 z>7)Ks(AjbTnAj>JH)i{$IHBQE$~MJW=3y~;7Pzip3JhFOvkj+9Es6%_ z#bEa&@H_??NS)vYMd#*FUz9RTy%0xvSV^KmX`RCTifQBC(b<)p3w@6hz^^U#o`8f{%tQSY zy4k6VUgo3Dk#JPr@IVo~!S^t}cFhTw)E8AxsF0cq)KeIrkW1J| zQg4#!ziGW^h%md40>ZdOLyS7JB-oy=J~+$k4p|jZ{1Y@NmIC%9`eMW7@ENS$4B|o4 zRKMddhnQhAWCV`*s3$tDZ`1YKE^3cZ2z;m05*6R8y+BP_1AmikX7X#+6%iOFKh~Uz zlRQ}ULViumH+u%0>@1-$@O`GT(vKqXjjgH(f2B-$Der-&n)(+1{3cE7bxMtayl>WE zyRpirz?AcuHEkIAeVI%4dtdSIlG*!nXTWCT9BRTGQMUVcT~XL{)k!MS-W;M6WTq|4 z>Yaj<3)o#3U0kf>*WLWt@}qhrW76(zjeQFD>G8pjQWcvvHIeOynaFnWM%61k#Aur5 z*LX|NX4r5U!9WJ;3DE3a|EEVM(l@&7+dbk#11$#aq+HTBZf_?;!Mv=z=X2P>)~wSO zXl!thk^8SyN8j;m_E;U^68I#wPiLrVlE$zg-Rr_2obY6T8B#4df zsNU#ha&{0RVtGNAw&bbSO-^|#J2)Bo=wS9EYWC>-=R#9x;XVIqO7{o{esdT5ftqf% zhqODAK^P3;&_HbN*5Y98iapY?L|x#1g-np^)LJ!uM|m^hy!qf^W{^2q%71tuG=rcM z0b*9}pDS>M2b5l&*0q%~in=X3204~kA@y&Iclh*><@oB4ZivR&_OQt|srdj$=OBJq z&nvz%GZ&%lisFhWMX{LvH)Zb1JDZnfcwljCWb#?QCPR1oMIvkbFbB`?P`lMqW@HQm zDM;bwTEj|4tpA#or0{{n>zPmXzTDyR<>4RM5-L~CpD-3_qrSeT_ zIE)N|$wFyW(0ij=rkgzg~G?-1{mib1Dqck*cWcV8ongV#M)m1F0}m+`?`Y4$979P~TL zVh^m>L9gVI6eVf`RvCETkGIJ4Mqkh+6I0cN`li5bi@xkW;$R5Q{nJ z^d}v(5^D^Wmt0WY=o^#5D(}P(zy>J(IcZrF;26^9A1s}R>(Qu|^OrPUSTNg2+DqrJ zsXTH=^#UWC?p$Rec+Nh&7VlZ$-rhK|`q3sBJaVjqfPpe2Fi=L_vB+PFHW9X$aX19+ zTVhvbrH`(qRgPJo?3dN1($fQ#6JT#{vv%r&aZL8kriM}Y>fI`uPfL{Z`b(aD_Ty19@`vW+>;H?JsK8`eMGR_;w!y) zEx)Y6mM=LY3qnb(D`xJLmk>%=E0iolwJ4*>14%1`Yi>&Dv zFEQ@|w+WT)h56eFIQ=a`&Q{|Qv~asry?MZ?C>(#B2ed4<57g|YIj3-<`qaLv=mun4 zFJl;crPH-$bX`cO;N4@(wka*VuXZLDo7;g?0DmyQeqdup@Qil--ktje8r(F?ucIye z&WM-V<{OGHgpU_mK`)gBoga#jzKA? zf&^aJDG_fm8os3Y4xBZ$7-`zwc+w+-1WIp5o0i`oDGAUT)q6kK0RLO+lv~6-{RO5C zmtvsiq|hvgQQFVw(Pde)_;JujG%jOZXj?u}MV`??%Wn?V9Q~ysFR38r1vV7;VEaPM z^nNOrJXMkH@Y!A^V88>`0X06G<`}9J9WgY^q>WY3!17t?Xw0#(QB$$MG^}_a=nemX z<)i!~SpoU_4&%PZWjiC~DUyM3yLUBfB1jzR5qB}#gkSoD!(jn6k_41WET1pQ=ehp0 zLT)wJ=<||G6drgqKC>MVKHD%-HKDWy=h4-^WeZ!AF<5@@@FUDt=Ew(r)pGN&of!r#nqs{sCB-6Mn*=i4T z9klmt@hN36SbvSMXVB;)?jl`HjO3HBa!t@UB&U5t`QZ$4>TJ;4PAl}%A(nXEKR7Yfq4J|RW`(g*%!3?*86@e)r z$q6+O+m|1{3Kht&emd31KZ2;gCsq?Fsdh8jV@&IvcmwN~hysb;TbDy)s$VrDZ58}Xm4Ef3l^PIECZ&Bri5er~TW2jgabud1Fs zEwz%yi~J#k_eJBx46ncO=x*m+)traarAI`GmjPZm{*F92Y0z4N&l(cvTMRyHZ>+eo zfGe8n-^BVsDhfHqjI;zK>Z!jw3ZPLG?-j0RJi6W$)q|xsG?UEkg-LU8X6%ly&$p_8 z3(XWHZ1qQvPF^=n%yo8r|6X#6Ctp`SSahKwn>nV|StFXtlIXRy(1M5+zGhp%AB^cyNzGziA->(Zu z$Lncp+$udKYfja-W7CZ*fPluYzL%wgbpn5UalP>F>eZ~NiC|>8yjY0ArWm+0@lk!` z%PxlvRH{n~N;gPGvlO$|S8QuK)mMm0n)M9j|GYrpwPx5XIi7Z_XMPtbkh9SaZ`|`T zRaHd&`OxsX?5i!2MbTYrRN-2EZrjgxW!=ZpMKV$LBW$J_YvQTaI@-p4L*w_cDJR-a zUd;<*=axWt@L+(jHBLB=F9tpPGuSD2++v5ow9F_1q2aW*StB!CLL@DOI-MV;=31F# zSFIR= D#Cdf6 literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/1-piano/60.mp3 b/src/extensions/scratch3_music/assets/instruments/1-piano/60.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..adb7052b715745b0f68533236af0d804b127ed74 GIT binary patch literal 57227 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 z |_Fjz&>G@en?%h17y* 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 literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/1-piano/72.mp3 b/src/extensions/scratch3_music/assets/instruments/1-piano/72.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..27451fc6a1914cb91939644c065d0c098a54e4af GIT binary patch literal 46418 zcmd>l$mSeclHjBPJW+VT>ZVdMc@CHp`Nn7x|pD} z)Jv?6|Ggz~7Iv&QWdO#vhx>R5%Yyvx7yrL}qHhfU3lPQ~B>=$MRpE3csRTHDB}_|% z8#yyZmQQ!qKzl%1Ve*aiqlu^6NpDS?>k{UbR3RyuH^daV?D#n=(`4@)2EZ#ANn zCg%rgVz9wcdag$o;BxwL|qO=Tt7S@TbdRHEeG=+!jA#ybm(d)WlI}8=3 zKMAC7|Afu8bfMAcX#jxypAWyQ{5LF8O!N(G2nRr}pZ7Sl6TlnN>RdCa{W_Ki3$$CH z@i`%z9RkL1drZJbBEpJmyhKe)**~J>`V=4%UM?HU9uVup|LgS--g2~H%oyfZ-15g7 zZ+~a76x+MK%MwfzRa4h|QO6)D!vmUzuWBK(l(}@O6xxcRd?*$eI-$qu%ZL3wF2E?|4{%f_HZ%1DO3R>HK&>1HfXhY6~mdR-EE} zhio;@;^uB2hot$j>Wr|;I=|8oZff|PqOC!BM1&17%EhPy% z!-*f@9qCP9e&ydkxHZ?>(1c8Ty}y6t!CHa7u^XZTkcywlBAx0=e&oAIbdSo}PkGRl z(P`5R`{yf-zD>0rAcz7~pp@tFA~!hJJcoG5U92*Fn%BwIZW!2(1##SaoJaaT&6{4N zmXTTRh`zfI=nE-~53n>naZoYf;Ey90GdUqE76?BLE8EWXF=Q5COv{hMD-QS_&1iLa zYMu!i{Z1c+;(lp^p%tqSzx;g5(@eN!%#r94Wp1XM)j37*!ep!8MqkpJsBWo)R+KkH zLbFfmf@y~^1ev|J^)-Wo`MY3C9~yl->R+vVo?~$>ZWxJ)4WMlP9bOiFOu`Go%&vw> zVc~N+7IWd_JtfII-2@7^@~wjv=WF14GB9Hs5hjeh^vzL`3)LhaAWc^L^=6e-i%7s~qfLMMKC!cU^!*wWCyS zJXLH!a0%lZ7G^YJpCTS{omOpvMsFucspG}4xR_ch8DZl9h|n(*i;abgVLyvO7H`Qi z8=0z0MgiDHZ%R^YmP1X8R^6vvsq#8cR7D5qLkgY!i<%8&OoXcm1C zT!KT_o{yGbq~Zc@{ZriTV^q3bd+JQyeF;hwfEX#Fu;_ls<1aPGXPxTrHQC$ThvMdG z*U+)DQd6=P2nMWbH{_nrw_qPorsD}u0mvlifhmmfDXjeXrvM0Q6Z(oeUTGG~Nnq{; z;$v*n`kfzUn$=&@px3U$RUvhy_(qwF!%_@IUwoO4EHzi#d-&L0J2YzKPzwjDe`#ip z(ZONpv(0Ar4Pdpy8=x93;43;o{j~ZasMs)K*biC6bM;an1E)m6bn9&6CRUM{-JlDG z5dqFoMY;AqVTynTN?LW5<@$W(i9iz|VGJ z(8!H*B~5mf>e_-;ivP?Wv#=*Lh|;Z-6yw#jJXV*BArQeNq0OInx5bpQ@XASgq5(TE zi@wwn>i5>G)CQ|Wu;TQj5V@ND9bDQ_tc=g5d~S`xol98V_M(i@g3fJzzot zi|@3m^!YHsE>BI`Ji-)DQw=F#@Hh=_KK+HKX~{y%Qs?DPY;SEq*Kb)> z1Tp@IJhqUu-PvV6j_O|=y5Qk0_p)&n$nA8onmDIjAtJyhMgCB4zbB-BgANIqP%s{x z1t4(&V#JSfl@?<*r3Q35@X=)s7JqY)qYh1P!Nj78KmUV@LsiWW{K#}a(DIrWj5K4N zXpR5&l7~W!bHxdO&vK}b!hQ8>gRtKO(&J9Vn%f(Oc2?&UFEY3sp9mr2UabaY6ap!b|SVJLRv^t^D7d7;+KSrC2(nbhl z$X`+tXS;ePKIPntX@aw8L}CG=Sf-WY2x*=}quYkh%?I~sp`dN)xwbuhl_}=a5z32> zXQG5k?75xbquA(`CJ$`xjT*3T;d=EustuFl3r2a%uND%QmvLbj$qxP4{{PVdMsheHf_TnxU+tVF3bndL5-`PVeH#fe9`WW9OFDgb-2bl1 z*U4wiy%+Vay?$PdbeMufy7miZIA@N(t|-QGAln>;tB>c2MKVUPYtdseG22AZ;O@n$ zFr&qlCH~|J+h4d8Cc@|Co$Ri%-sro6O-W+B1Wuls7U68xWHYo80Joy1mOLab3TKfO z8TY|;c^p4n``6-xmNGR>ugRrID~R3m#ItiMC~Fw4a7aWxi_KREoDe2OxnM4nQphe6 zyFQ{eutmkF@%i(RS3&pRtQe^Oz89p4SJP$rW(3(-ra3V< z3_$Zs4QG{aN?8B?M-xb*HieKAE#P^&t&8pfImp($@M)UHf*go~9EbrR2ydXg6OQ}7 z!Q&BaPyl`#DVNkkRUNJ-bmo_a0n6ibF=7IWDo=N@)4-1ZiZcaXvFCM1px%-~{7hf7 z)=;IWa6WIN(MOWWt>SXgWUpPK(YtT9y+HC2062lkjUzUt0ujVQ>O-vFyz6XDgkx+h z_4GI7W&`2BH# zu7fZUyvCOgAP@ka9BvBLYn_4j#GNiW;C|hXhQe7^EEB4Ilm#OW zOxs}Ywx5*1#+C|GPcf`WF}irfF=vTIR%*$cx%|raDXi=$@<&RkSlH?r9H3U< zC@jt-<4$oQ!6QsYOVt+Zb@-Dl zCt$|XhOp(+X1mUn$c{6IX#rx%hHIQR;3n)o3DDlFKY5%8|g(c0U+gyu*=04sg|tZK-l+b4f{Fj#hYL!$r;X_AW?KKZ7UGeo?d z&uK-n|0fej&Ibh$ryL~{3{DpXL)~yDr(asMfC2&+V58V0@}an2@&3Yj08Fn>JU{-~ z`xU*i2->29I0K~>qCJ!IREL)kYT-1Gy(VKM8mfz>+!m{lw^N*BnlHmYqRMc?*&+wG z2~Bdo7X=>7od@<`Cgb#f^I14&q5b_fY+jXn=A~|9%q9*_fYSif5vrUJ&a+k{t3Ynw(jsx)(8X34) z7&Z?e5Wz@%26+%KIZCEzoi5(GY0uLq^BaUa;dSeg+Y3@&|#mP_f`nRpce(b-0 z#M0}$o=GEGAOp7py>pfEk4bpqWmuwYxNt*;dAVGjy^Wlo_3&VIaY&EEO!aGZv&2qN zewli}>+gI}+kn2<&aO+=dcvF;h=oB54s6B&HtiTnxRDc`!amzX8exXdB47lNp@dCZ z%Lfq103@D$e2C-wOlWnwt;~edO_mK>WcE%<9Da|(9XL>WWHB4<1al+tOl8gIZ9SzW zgix5pZ7~IVG?D4fmu~EUmLQEsmgmgE=i#~RdSmJ0b5!Wtu<0v&b?R`HaP-|II|2^? z1}>sk!OFwGgC18>Vq`yYx{I3R#_FE8`k^Hz9u=c_o^dwo{48qDQ7xG=V0{swSEXMK z!**CWGNLrnIc%JksQY0h0~tJ4*_E%pqNXYljV5{d=K3Yl#k`>sIp5i`|G@k!G(g0<>R~j-@!!M%!+hA2d2DARxEa7RX%fH%~^^$05f5lsD z0slBs1FfSypFu{y!4oM5RM210*w~!;jzoLliFTvJ2S*k7CY~y#(Dg{(EX)psNg=Eh z$t)oX2TA6nlfA^UdtcwN<+^yJBBUMd1AZx0*<2oT?y+LOpmULr$0m?!UvE17@sE|U z`-%u6CUJ@;pc9u-_wad$`hg`&I*#R}-|qn@jE~G7WvJ3Gm#Q=9diP{9U7K4S{U{(M z)f;4#903CX;xH$PHcq)v3JXPnB?&Bkq^`ZGQ;L?P%~+oxN!P`1PVY>%(Qf~*PoM{o z9_4T$hm1DY#hq^76ZqjswaIH0V4f>gt(X#?tqK07ML75}fhy_Z7u#&Ec6|oP8_F)m~Zno9`6kV(Psu{JcYjK}qL4#o1j3y9v~P z>#pP3Pj5J16xI8uUqObVps9cJw`?26UW)djyaX=M2AyGd8<)F5WXw)%vr$loP7sGF zi#RqOmgLv|fniQF>H_bwV^*LD9l&?s^>Vf_7?hI}!Cz%99{4@K5(7`=!4OizNDK!A zj!-X4-qUQ|Ru)2Y_~Ae9zU_q>;;U8f0HPkR?qO>Mh5V%g5?0>+n3MUV=8FDP-OsFT zZHVm+Dbow-u%UaBAsmdVlzqCNf7w&tE{j1GX9Lxki^3{wQ~O^F=% z9nNe2s|3hL%+X`oMZl^3C;@}7QVuhD%>(-#b-KN!7Ovs3#wa5t%dGOsEG4&Hq$!V1 z>=RR+@tk;a{;7RyhM5f8E!jr>uerB3)-R>y&%M3pj#tCb7kAcj`$wG_Dp>a7UK-9j~Vk)**k6mha?-UGw)Ag`o=%wDjWZcD&WdW{h-wHyRT>p%H z>-{eXe@;C-;_CMuJ8s6E7wE3QyX^!+Nl`{EFGX~{l{k@)IocXrML-SwE?TjQ&0xog z??BHwivvKk_nZEto!J#Uo=(-2e*ST{W?32cKng!jpI3(3sxVJ#QQYSDpFHCW+SnlM zN#od{L-}i&@U!R%@fAxgS_+*o;Rmdl#(D?)KnvZGv>dI6Z*k-IxxM3MJ+i zvK45KNvuIH`UVcdJHu82lsF7{9ZVeNNb`{Cl2nXK*^P~5U~<7t9zdXhfjUw+kRvAG zy;KefME~Is1!4Eh1tYL60Wlx(k5u2vMWYD}H5(-|-`CP~y;Xm<5UQvAE8!P(OYAVy zv&+UcZ{0|1(pTE8Qy>TJ$aOn+*S&9k)j3v!gFhhhYU?+<_9=4CnmqNZnvPj4jkw-xTA|-To|1ESP(X?mOHGhdKV3BF znxr+R#7(O?T_+)px1!M#t4rR}Sbk_kf%R1oaO_148-ch_ba`gTmx_B*wl~5`qhncI zt6!akITdD@nv+D)@}U=T=D)=RN&TSxkbRW0Dqtm8<*&t!A)5LC0x96hmjOP+Pz$*H zzBp7TdD=Igx6^XtN6Gz~G|g5M6$=4uaHNZk57K9twp!skpF%QSkXq4qycQFs0NdJE z=k7lk>OYmmzkhprs58wV^ZaaULa^L|_vD_R+?^x>&vD*H1COL{6z7kq;M~?<`TZj$ zAMdweBP14( z`|Yox8bFM|+n8%IIV=pU=$$l4V?^f5^@}92Z_jzDFAX+JcmK--0BJ!12U5$#9^L9B zkwf4q@njYT_$>vS;4B@n7wtW8c+Jhjn?dfoU6M$!+MIp7h!n4Gh)~m=<&l*wA#JLW zrW2g}dK-3cjL_)w{pQrr*%$$$>Ut2>Msw)t_2O419AVj8XaWPiFVEg1h#;$QrSK@( zwzNI?1^zz{`Hno)bOatJvVd997euXLk1iCH1NJF?8#nTt%I1Fqz{>Z@g&eU znZ{{}>I{VFHXL>xE$N(6*T-NQ;Ahd5pEb{YF-(hM1%9SHfB=FK&!_Prnhn9DsZOYb zkya<11aCfEiV`8apUm^LWZawDP5>I^#)32%(5OF0r^tIH!wVd+r17ONgP?25=0a^Z zn-9oR`IWlZqi7vu`UV>P73XHMTa_S(_&iLl`;G9hd~e$zG$R))id`yPrA=6kqr=s; zsZ!-nydO;Pipp$%3;W?tcJKfOQiN@?yBgN-HGhqhMTulNWJ zg#7gbQR?+aH=gIiTC}oyUK=isrIScLR(I(dz!V5Wi~Zk`=}Ml^p}0j&e{%UncJEUr zqC1}_9j~Y1Js2=Q;c5a;Hl42}YzoXO?ig)$@0kCAU5y=#P65 zdIR|p^;Cb=xWdw4DF-c-C=j9!*v3u@J2%qw3BY{_DiENT9w~IF-dr-!v~`<9;DkrR zfwl$~J0EmXZ<3^^dQZ^tr#QhsMP{YT0CU=CL?dQ(=MA*(Ru0Q?!yXZRW% zilN>sJo)y?G>>Yf#MIMZk#In_=tq9`=jF138!q05OV&@t3;M}?2VkOg3`$B;4ZY|=8?n4$XgZ!TOb2Bdu+pT5zQQVD$;6mjMp zV3^l-TlD8AxA-S+o9DR&k+kc5i_3z1{I6F0DT`t3R{7QIPX8QF96y>1e&utjli=mM zYI??uzOE;EjN3pl*rxokTEAOxh{gR)$v-NC1;U($0jj(CE1RXrrf2N)D@Fx7>Jp48 zj22mDdS^XedD@EiVsdn@7BW_0|BXE53BDSr^%nUM)cdw4v4R89YEkk@%*j7H6WU6r zYnG&J!25^8a=7B)219d5ukX;=@(Z(X%LV5gTY#)3#%uKL1g2qvy<>1ax7;)00|F6> zU*UuikAne^Dr6V5Vj{W(I>q?c3#;^J#^Mrgg2`m-L`N&yy!>Q5P+@56yLj)sJk7fN z!~F@wX59iJt5DrcvvH7y>v|N!kF{(=Ojl2g43zA(G@IEJ#NzyW3jPBJ?^U|o3xa?4 zGKxmi?lVObuqb-{MGoga{&??2HukpR@HW!|3G4dW)p$LKgcvJw@jPf{!RDkk>^AHf zTIXQrx`-Wdq9*#4-O<7lxXFAYQEN>1fpWaJsqLZnyB`6IWO3bVwgXNJ^dct{`dy;^ zIc6P|hC>9ojGtfhEOk(^s!3a&9On~VeHY{W#usAp%OgZAsWR%udhc<37zX{QB9$rq z`Xi@4V}0XCp2t5hxp8o-g4t4y=C=f>bF*k?zLf?^wgz}rYu229 z28t2dhmR#i!JpKk@WtkeQ*G}X=*I#95(I8O*eP|9RpvqaKeA(Ww%B zk&n}AFCa6HK}0K9r6fCQ;%7wqi&(m8G0BvjyZId_kK3>)g86^r6^dis8lrwaU-nyeWb%PVT;^>uI*wPRyx3N6)29#fYh?Yrwc z|66;y^x6@4L@Y&vcIT+1(tYpAGUwgatWjFY{vqA1S8K>23SuqctD;-@nbXNq?Frf$ zL9gn5fr{-xH&jZIopq5NSALj$^Xs#`SI*Sd)SFxcRktGAz!v@Y&*QI+P|!mVL{)5h0}AG1-zqBbnM`63Uk56*8g|61|%oPwZ(({ zj9~G-Ae;Q_cK{;Kv4my>y?!q6^s&a)gN#rDNU+ib4n+;YyRFcREI9wNHR+WS&TarL zSw=ccoj{Cz;jJZSEf2c`FY&44-*U^iC<_K-l>tnR)g~u0-&#s;20>=3a+xkGW*x7F zxks0TKHZ6NTB0Oe8Uyh4>*clQb*1j^8j-+8QoPDzD~R|3cT!be#+&B=sQ}xk9wWxB z@yxzIF&Lg9O|wTZ58AxS-su^0{m+(K{bUZ_%!iBdeL6JH>bz8UtjU&++su1RGhB6y zGLdQnrc7+DZS^8;QcCdSh0gee0VecK0;mSf;hRMJ-XgmiE&gPUnv}LRYtn zkII+(e+T25-p$jCbgx0)O`A(`r3a7yk0pK*cRwMzHvvPf_gYFr1TZJ!%$aV7s$VNt z6J)GYfY8`I6~XQlZr6X4p8M;k2K0^Ln{uD0a26`3Tz1pGdTo8lb8~*p;1=EzMH$uF z4-h7bGVZ%B7<{48ZZqz)%;097kXTwHm@$=InQxUIc{B7#&}Rt=tu% zs~YYSJ!G1Y^h5q)bYJvK7t%-{f{Fnk$;snG^qcT}Ab0YQ{lE}KebBpT;Rk5^&7-TO zeTuspT<($hhORooB_+jpb!>$1vCM{%)fJ_$`3ehw;6QNEM=X+~PU=yKXMlT@p5^$$ z3+3FJ8pxX1G0HC}wY7(=aIcfYW?Sw+yGOj?dX4RD6~*Y5DiVHoTwTA3TJ?nM)}Q1TEx%_4yRbzmm6a4 zY8i5G^mT@YogWUK0s3x@%rEZ&1RMbI$bDw_G;Ussv!g2EP?yw4QKBWFp+S*l`^M=D zxPoUhZo!x2M_6_#RWzP-99C%a_XLe6LPN!yu?9wQw050`g$kG%S;2$ti)E%B&ELj# z0dc*j0!$RVxzjve9Fnl$dA`8I>!;PertA?g;n-{F2W551K1Z)SQ5NWnV2CMiCVRq{ zBKpAQN2z$@s!3v7m}bu_sdeFt6%zI3EIqY=Qb@3+usM+S)RdogGVlY7{X9zi591iG z^{!w$Qt>VmT3;6?cgq(_9afOSf1Cd`DzL)uU{?1TvU-0XwHu8EvCPN^z)8_DoDBRn zLd20&&bP=2((8N2?g89G_%x2Ki{cC9wg=C@ zAJk-v56T@uT!4J|YJ@Rr#V>HxrT~?@s2}+fkcsdANOM<$F5N(&^}D>xh&B-@~3hxT^LkK99WFKO7yLy~jk4 zOkVL^tl0k}deN6`JuoD=CI*nmVw}Kc&}VF?n*QDXelXNOUK&|3{?e^971{m%T;0}B zP##}v?)NSLW)u^buyT@IYNkUZ$Nd45l9DXa-jMm?LNaQUK}43@${gS;>_+)V~@IeGz{Ro2cDr>);1zl0OQP>KFI~5aSMyR>*dr z_jxp|-K4nfq8+F@+zsPMGo-C$B$h9+Hb2F`%r^cXMhsW0RL3wCT%OO+}jc_6H#8SL1 zw^oIq&uIEdyL^Y>Ii$<`!hcbFVgZ^6NL8nWq?jAjur9-AY4S|=p;mEO8qTv>Eg8YO z)MM*kCYG$1+nW_bBoDmByh2x3)EO4Q(7Fvj77_Ivj7kwiz69?&G z8bA_+8TJ&qR`UUb`+W%B4Ifg?1pGy8>oyw>Ei4Ht)X4aIZ1({k&Jg6(r)BoW0pn?H z8AtU5d07v!F2!LAB|bWjX!UR^czdsQ-=sl>>WI# zGo5a~@u=T8OzP`tS6ww{-#;$v93XsEsTcS^px9>^A9|3 zOiVYkveVYJ{s9CKj09Q1b6*|6A6uPJnQ*9>QgrE*zJwJt^2hUC0Ff4p-qYzvP)?kq z!CLvFxa{E3n%D2q3Gq#Mb@f*63$%87#>^`a)W0ckLGwb56!Xpx zxbGo36~P#qMs67E0pTo8U^}}NH$AvgTbRzZT=_BuuXfCPX{E~H&F7>xHd1iua`Iq` z?%u@d{xo%d*+f)J*N3h!gJt33x!v8ZktjQe{(S_&LMWZ`z#3yPxl+F;pSTZxrP~Sh(3NUa#R|M}a?~gWo%IPj(!o zlvFq48b3MBe1#8Gq`-L3C$M5+%)cI^z9T72Jk-dna>TOGu+4(0Q!6Ao0jOogKQN4Y zvvsu$L~>Eg^!gQ942c&$v$@rLwiSep6KCFp$!p8TSciWBdEdb;kIyxm{~Bhs zxYbWoTkdq6HIG8}AZHD8OK7wX`uYY{qn-mv7{pgsyg4sTBZy{f@14~kgfmAJ!zs0d z{@e87V~`3IaXs{LTjJ1*d!g5=DcnS9v!_S@&6HrS`GZS^=lzrVmzsQ3XF|W|_+Hku zWxx9;8W%MQ5nz{CwQaI~fSQNoQR&9q%%L%DLd~0C#Q{{xzPfYG+k(XgK~01E0rF(n z1-j2W;Im&#kr@OW)fj(qCeLf%+;YTb|1Q@t171l+1{$Dd9V(h#5Fc0Wr>d#kSgcl# z*xML?1^td$wgVI~w%nS=V5JX3s7<~x0C75jYM?>^FCN1 zT$rJJ0UJ`w$N{Sb>Yp56jyD=D9K)=T9h0l+pF)iB30Ja&Z*z0c7`FqNQXFozb@ z=-hc=8u5=fbJOs!tfzlZGiExuCdaM_g$Db}TKuiv5%8Ss?9xe?Iz(KGWl!{@mXodu z4*wN-qn**Z|7O>4q8tv@EX;9jt`DSepZ-*3pv2=d34W1JJ1>tZS*th9pY&^!I?{29 zPGns>lYr+u4u`QQ={~OD()@-&4zgR z0*SGuCwrSU^e9;TtG|J?U=ujCwvEOy>lrXo%VW>mBx@!dYD$Gd{;XpdapNz$|MA46 z;*ng4QbTZEGW$iXMd{H!2n~6kyr1$3qfXEbONtUr&Gu$OiA;;x`7jdI~SBU!;XxR|ro(NZ_NSq=_r&kj z_M|O|xDub)2kpz?>7837K79}D=EONS5hl^%#yx<%jVB+%QLZ<^{vAZq>s(c>-XvO!IS$2o;!8OywB{Z~9uUm*88q`>D6j{p=H@ zT*QVHHz+x6Ex&gG{57|Ut%etw1IO_`EWENv5$kd=d-mb`PgtBp)9eBK*bX8cM}uBH zEDX_gg54AN+Uqj?j zBWJ$jT(oL)UzH7g7mBQ6~^@ln^)0jbQVJs>{Pg|CywWS~ALQVVop5 zcaOV@H_@=!v)iWOm%tuKyA@ueBNlD$^mO#Eg4W*@IQ~**t>$&2IL*4&Pam>}5|&I{ z#(`8aC^@;ePsQ=&#)sDl{XdH=Fi)tnEh31lTXnF8P+T$u8jKV%RWW82UBz+oSBm8F;$i4(xZ9YD z4VZ{&awVRp`+U*5R`^?OAvF;v)8-c0>PG;G>^KBFM!y9<$K?lv>z-cgK7c?109BN* zA@z*xm&Kr{Y&ic{7Ds2I{6?zvHC7DV7L~+YTr0w9(RRG)Tqya{K=t4uCQ0eNGZkIrPhihHgiU&{8UMZ3c z_4-~it^@1awT+nlI}1mqJ%t%`Z;0Of^>&2gC_R9H2Qb(ydnhRO z8>~O??Gryrt+28+!%b3iDCLlPne9Tt1`-e}L9A`_m^8n&ya4D47a9N3+_&BZ*Kgb?-v@d&Z<(Mlw+}$c2a`IZ*_Ang9JT@Se0#GYOyW)POzQ zXI>&cqIwniShS=59W}UwqkFZAlq|9+8~n1gzk6ez!b+1#nf)V)65cCGsW%?Z^aLDQ%J(k={e6ALnjlJAe%4r zbE+ea;ygA)sU)2|xb?>-Awbo`Wq1$2Xtz|&NoDh(?7yM)b3u!om9 z6<6cm@xP^rF(I;Tc9^l4Jql~nitUVNo4{MtMF2)TojzP}d-k&0x8?I*^Mw%#@U?td z7G0^e=6G8LSr7YQHY6f4yLw_#mbj08+ZFdrdI1zYr@& z)e!JU2dvyR4N2l>N;Y$9s3mhP46={dUOk`Y^C5MO^~& zf-IF7qS+a--;T@$HL?M1oZT&pu|e67N)OBdDlWQg z6@~Ti^!l+1o5IvCR?(|ldGu;u8o zP9GbI#mgU6zTc*$g+uYm5YAgKA>*c@vVAkV*2&r#*jsxEwT)scqd#;s)_+)c1+{#~@G?|yatj|=lZ31|%EcH&l#>y^CgedCg4zEvCRgS?> zrhzhbkHZ3yd}yy8bM)Or;j#WMg7 z`9^0uJoo)M2CR;jrcS_eP-79OpTh-|Xgd;?FU+@pg#4_bAq(lqq7{C4S6S zNw7>0A=Z>Qt`WF-wdKI}lk1EgwI10e?|?Up`kj`6Wi8LtJ!ct!ZxqFpYYZ z3Seqf3ctCVwEfF8puC)=UmN-x+?eo{OBHeVYMGB~Nv6XSE2gnmFdZBFno)6C~jO%9}#y8yDh6Krbb!~Ue z5Jb}xGHUfhpD?3s&OM$JL{s1MZcgvbIyDQSTf&}cXqr|C4m*J;X~f;GvjVeZW?P0BN=4M) zc{_S$zt{r~@O&#SZo!4<>|dsqwWeA)sFML4r{CUv&-SexS!WsHxj%I1K(4$Zf~9j* z1Ez%+C@5f4)pqAPArB|NbT&8a< zdf$z9Ssl*zPO`E-<>Re6;oK%+IE~2gCRDdFxNBBZlfiuDOPQHF zIqae1fNsDm*9LN?YTeel0 z{<@WmbD?KG^D|FD^52#2QFG^n?+%qPJHKwT9pkgzz`~A(i*Qj4<;<)0qPfr%%;cYR zaqJr&*3ci8waq*F%X+?qWPt-??5x&R;s)r)XDhfieC+{dE1g|D)7!O-p4$1fs(jBOAp$dRjSE&RiBjt|tnT#No*cr9 z?s~^&Q<1)PH6gT0&uzDRj67^pbaXVnI^Ww+N-UAcIL7aCe9&Co`@6`v{Lh6Gc!YZYIRX|qQ-0|6XaN98-# z;zg?IR@_Z!a7baN6Sn9iIUJNalSx5Ka}~?~m9~*@X;g3B!*JdYe_e&XOj##=hG9 zq8aeQ7_9X#AfGq8Lie`4_Hj!>%T+ z5Rt{Oqg0kL>(m#f?mFj#L>4NW^XGie1QCBrJtM%$d5g5&=ZJABEU;Yr za!va@1bglv`;08}cpT;Lq}hhtmYvCN)nVs-NiGL{!vBgwQ0^=`zsuC><3~{C?wTo{ zPB{i>;5*Ti5kzqE3YOk~1BmOBf9f#7O&;2o_sMpf+Djy0YdmF`uh#uA)*kXK z6_eeh{VG)n)wav{APF=8Qq!D!HZ*S@+_zU5qznLU$tufajAC`M18OXiiDHC?TC>f% zIC3O$*2?|3OMEF%mCM}CDU|HM+@+b!k^jUuJN@Xc*2=tZN$qAVroyv*L`n{`>L3J< z`M~VGnaI)!GF7xIHazbAXe|{B*)P<@;t%lKNpdRsriOonTP#IQg?}1^&}V*FtX6k{ z{-6T9X3}2xNUKrp-roR8UeDdKlCq zbC!9xkLNXOyAC`si5p>p_4 z7xPbAUxiMHQCjvbJ{}Q~$lQN_@;AXK&F(9pdgh3PlyU_q_7WcQ2qCQQNWTZvDKfV2 z)YO+{1_$R<%nB(hO9JWQEAT)vzoG$Bh4KdWMtzGJhnO| zE8I)|23|(Yd#32Q*`*G_L+9;zW~eVQ{-+X`#a9}@z<3;TuiK{P2)B=ksyMV0*;0wM zr9u|F29-Ll^A8}9z({HL*bqZ6>`z*u{*`af^Air-YXW!lb5=lTzG6G(RD$x401py@ zR2?Q`eQgx9#EIG}IZf;J$uH!M!j_om8V}oVd!x@bJaOP1S|+&{-+tmMWL-1}qu9_; zoE$r;9`;(1o(`j+Z@CttPX%e+!Y)677CBi_xiW6#1sua2mRLsgd8^9FslzTJw%?Sr zemd@?X)$;m5abG`$*@Gjxo+aPD;F%54Xj$@c+6Q`SD%yeuxKJtEN-`}6`e&Y3hp4U^8ugzgC&8}5% zTZgx6kWgk`?bt;oB6>Oy#Tq1BPejVqQ@g!~&*+yr7A+08ihmhMSTyB>^uhrxu<1xd zqzNwMF!?vmveRMY;LR}hXqTw*#d4t6Pa+LZ6~LH@!if_;e&KJtNV_~#^zi;YwWQCs zxYvBWQy?8UjNNeNXPBu7S$G%AT)te%~?2cbfLS;X#V=a@s*J=Rf$N%`H~wkfNz{3b~ANmCfOq4+u}@bz2uzT1!WGfa;PampvNxpxe+faW$6Ko;o)Qlen1@Kd0N|!nFw_CE8rXxwH<-rxatCv1d z%jvVz>50_W5Th@s)YgwzSBQ0&|A=K_W%8|%cYG^z<22FOG ztZn%@MDmM~gKYi%eHKmQKnI7_0jl&3W&5@Hfhu7ZkUPWr&N)S>Yz^a;J1$N0cv|vj zR0{ZG%dma4ITfeqKS~=3f3}nfXdCLRrdg)?K7b0kJqW# zXNen#@D$kP!7!Elja_Ha$+u_L!>8|TS>GQlVnUE#gihHk;xdvGCOMhZto-$$&C23_ zl}egZdbiPijo0`Mvtv3b4jX>B3z>f9c_?E*hi9~cTn%^JS0n5HUe#RN>zOjqvC7S} z=wW`iXkt?GK9IDI;xhHO2w1Let$X{;!0eDieaerMv$57dvG%v?RDgFkgf)A zw%(L|EyKApGjrS~qm+wB+^$FWoH98{fz-_}37j<|&7)9-#I7#W#`^*PMHbyXR}C*F zmx}$89=#6#+=s<~U>dG1R7#JaZk*2ADui+{uGnS8mGt|OKNLuJnj*)2df7pexmGJ5 z=Vq?4RL{-w{g4%@9ld$&nsLws&212 z!_IiRIc1EPey3j_)smlKNY}Y__$lherwwLwlU4x1!w`zGyy$=sF$Of`$h-n2;viK8 zqsBzWEfe&{rPz)dWu7*6hj%74d_ZAK*Zu6+zt$zQ$7m_LeNm2t)8H2OlXXhEC`m4J z&`RF^+hncKk;bg8`;YA$vkMmt1e2^L>^xU*Ts6P*tH>{E#-ornv?cK~VhqGqj>cmU zTeDzzD`XvPxNJNN0Vf<^rkobRWI7YH+Q7cVzoVw)3aUS{M2i|A64ZEw>s1eXC4J$i zzFmP)htVS-W3-53A@5L_AL=61W^Y=#CRY!jhmIeOf3GjyNIn)L5L&balU9$nHNq>Y zjeE2nIi9|Vh_568QV2;&H+SOQZI71>pw<=Pk`GELF!6ywUAYyuVh;Cf(17%MNaj)7qJ{JP1V`Z+khpO$&MBCai^4Y7O zN6d3F@!6OPi1ycK9vrX#{`p5Kd(~!xU?5IUd%&_zC{&ly-uhqr>0Xv}qF%l`9fVl- zXEU^|oHfU(DJ;~=_>+@zqJtQjxPQ7n{Ks7>;z_$*+a zlsesYorknAEf?-X_wjW*wNxFdCeci0JAjZ%S?y?mf|9>t%fXfZx!v7eaM&g&)&M+Z zBam}kV#O`BApWSE&;Rm$9eXv&XAA`*HBeIXOKWB1EDOc$5o_8~RFe#XMe=dZCZ@y34psZ1PQo<;N0O0+I9vTpo(05+MR#iGOE_HL{Z(O}T_C{R@ zO`n~(uAGK{<-%~6fc8;>A6vC)XU?T^pR=}I51_*D7C0g1PK%ASSHeq<`$lvMX#h*db81RYI};Gl>E*o> zina){|K~zTcqhj>^}^vN0h zx0r(F(bN(quBSmQ?=Tme^G8b zs%S$CU>6tN$eN0_=eJcj)P(Dgoj(;Bsd1}hCM(JN`^zX0aMrPXUN`;-1UP%e50g%S zoB;o*4kY}6a_WYDt-6<82p0mL;)Bc<8^6-E;L{275-Xd)l51%Xjd@8Dz7Te0A%FS6 zG|f1Mj(Ke^a52;of@ zuWIIzfH_Etf`3+!BApG>)AeMd=o}QQ^h&tKF1EW2v19C)=yBcS6J=j(Ud<6AA9h8= zKTNo1sCu+tX{_cc3n?18ke_zr%lo02zAOg-pijGd3VZ?eSz#TiiCa&GO`;S~pC8aW zIwq_=4}NYZ&0D2X(*!+Dba^s~HXy(JX}vJca12t8$&RU^Z)UN!vC^I>*-&r^9f|SC zv-J>$<1LobHVEoileCt@s*;7+l?EBRP91#%>&rfpypV_ap%8ppoqGW~`)*o)f2D8D zbS^7o2<>ptI+b6jX<(q<^M{BQZoK=HRVzEOyDFl9(${^j^BB>IB`)rhCgv=gJ%l^MtbBJ_c# zYa&NGb~wcGt}5g@Q+ljoUeC`2FY>SkX~ks2=zH&E7obW{JGL1uqc8m9QnV` z{XN#*1TVa3o^sSq|5dw|Qp$;rZ=ou_A@vJMiZjLM;xs=wZi37l0WV_M+&GA6=qKT` z5YWT%KAa+ipk?(vxf}+nd5bcnK)4kCjXYAseh!}%>cFk{;)N2Y0+(qYhJT~oerBaAMKITRimR+L57k6uE8~8y?hZ4c!POWFd9`TeuFykuV`?5-r z%dU63Ls-0y+9E;7dteq{@0THFA^Id zL9GY+LU@MQE%^vWlVw@snP%+ETPQ#L=cl;?6>Ex^E>MAV5(MNGaZ)Sgz9#E)Oj2Hvs49xVXz;}w-4=q)!1aJmM^T_zsuMVA`m2I`;(D5a&_2^7@QE&RSQp z`@P#E#o3}t0aY|$v;q9vA5hO|y%+dj0C~n%U=IZE_uL#e@ zuN%5u1=Od7xnyTLa(~HX^_1~j8(n9yG>OL@E9dyas!o(4I?-c*F^h%H?8D%b`{=zl zohQkSZVFFHnPV;l^3r`zvGLRy=u3Rp4vgH}MqiWC!a= zcKWxUl-}kRlGVOl^lsX!TFwkwTDI>7BBPsdKvw^xP{}JGsu2nDgvYx{U^l#&!Dk_$ zA>p|tAc8WD+9Up5p`3UwerNq%{8UUgbjff``R8N5=?v5c;l84NK=XkDdLZ4%%)-Mof? z)_S4yo5Ex?L@0Z3i_;~+`{K}|fj1XA^pWQskam?NRP5hUI?_L(a-+XA6q{u^ju*L{ zFQBmhs^1>AvhSj;F(WCF5XWSYm2!a{v;1zEE33OQ65yAowmqYDD)Cgq<-JF%LB`OS zjB7J?NL_ce6Xe_6+1YTbqIE- zu#wrIk#Hco6dTanQ`3X7c;zgkGdQwVL<>hv$)Eyja=>-*H7n1lB4W87a-n=bKtNK@xCJV=7 zouvm2YnA>g`vuFyBc?!0lOP~qoN3YlO#9|q)U`J>Y3{XOy-c) z1HYddb|m4>Vy6sDeR8uIA6Y0WoVYmV*gwC?k>w3p?Qu|k$0G1mT{>3X^~wX@5!A<} zdRrSj0R=8rG6{)0j{%NMk_+$BM!wN#B)sVt;0XE^A60zokDW>3JUK`?`p+&zii8V2 zM1ZMA?P_aS^odDC5oukad4>ls2oSK=UW~y=-%Yv3pqZ z&HIk9%Z&%&sL;ngc(gk}DsFun`5c}r&UxzBI{WH^4rNcrvh491(k`Py8^H1AkNz9L zn{;0!?%~g2UdE#90p0he!ZR9~ByJ6gmUH$_Su@#@BPgRc@m41OdyQ>wSDH4?>7x6> zhc=~zd5d$`vUP>Dd55aPu`G&(i#j)|7u9ercZa27)_$)l>lO!?mAW9;Ch&y@) z;rA;bI54uM!#(DQ&Gt)7QD&R)GOr&qY5PTz^ATTEoOiZ;{R)t0+m^MXpM`+11SfMxDuNhhV-uZ-@_vI6r@K(#)3YaGU1Eo5aa1#|RjUG!8!xIUx? z24WtX>Bl|C)$@UFN=#sqf{QxyaKR=xb67{fx8ip{GDWZ>WpLJx8C+jE8Ic;N`;nky zf1w&{oM%!OG12FuTcZyjuYzXcKjt2a#!=T?lr!tZkq|Q2F;HxOy)n?cJC<)Zbv!%P z*H*2TtNn3OopD)o1O`LB^R07-Pfq0ZHzxgT(k`;!%il4PJ+j>tEuYlz+YO*lkH8QU1{Xo}+iO;qdp|xSP4N-gcOe#lz(? z_2SN|)kszH&m#u`cRSEnDcQqluLb<}VYFK(Q2mt2!B4k5AaiSsdix{gTvHBB0C|PX zTcdU3cUew4#jsAf`?E=8zwUWmajXLA^(Ii!tNPKTB-v#!&keeA-e`de( zs6KB@@^`t>u+3|*E`?qh=8TSm@xT&ea@y&Y)ax5_Q&W=`ZarbpEkx_=vSrFp%F^;% zj}5Y#^K0WgQ}$%EbUgE#BwjJzeiZwZI45jrK831|d5$BUgxXgf#$nGwz(>MuVR}x~ z%8(HmZY?I$tdX+pes&EMJut-1UzgtD+a!s#VH;r(n?*JJu^v#HlFe0;>>JtO;tSr? zU!Cm^P%T!EBG0XC<#F`XM?ZaC=37D9+>BmYlFN^~@&^Nz4%=%cBHK7+#IHknUXGF6 zSyGgTfRzAxwAoMp%>$!(8e(C#VaurXx?*bZqvVgD#Jg3EW1q|!&#Qz~`~ysXm>nw^ ztUr=)cec4T*5qr4XVkJ6oY+iGDw+jMrZi60NiK@$UF~V8>}76cz{Dt~R0@6#vwdfb z91yX3IFbD9blKCRK#J;*`P;|L6@e0!PYQ-p%lObisCjcgDFOe^vk-8Q@G6UGLH#;x z^VsFEObK;?M2%Lxu;54nS?W6A7}*{jR;K=Yr~WZQ#9XdMk1ZQ9I5V{1O7}fJ+-|^ftkug0DWPf!IyO_jaGjw-IcnAea=0O44+jDw zS=4)Gb%DYiY%-UX7;l9&F&K%=5ZO;H^IC@a06jV%5P3SWClWEv^^Z8NB|wDQUfVz4 zltZe3ko}VVX{ydUD+-=wmCOw!TV5uTY{hCVHrToixtQtT)&{i2QRVW=M>GmqE@_dZx~%jC8)y z<+U3y&J zuxe&Q0L!x7`}YAo^8zGOS>I&ARnvM!i822E4)y|UxlS(UM}?HhQ1YgWY-XPdZ(XESuM*dQSDqSL(=v zbGjhuHFS8u7@XKF?fCBE_r;c9T~b=K)1%OKz-}hvxM@AxrD8S_3kz$f46Z>@l*RN z_o*;0ozG$`Q2KF0eSNmX-Qdo}MBT-whVw;QRhqGRj|20Cnk+w`%;gqbT@<$~5kuxf zY1sM9-L5;VrMsc9afCwvQ!MqO zJc^zw)=!aBwC?)ded|Fs%!P?nzEcYRboTx`<)Gthd)i{nT8n1d#=Y;o%0E-&IG0A} znO%{P@=!ZRm~Cm4@`&G{F!a0;QBSU{z#O=GUq!@7SayKQkI62hjqdW@%9SQfbkRH^gVYT^|0aBIJ z@U!d2_}Apn z{USv&Pg^CFpZ{#>oVgP|^Cv(zhef<`jLvoC{iEffh)ggRhdu;tuAzpPu1Dh4({?9?mYyhIH65gQWKnr_C?7jrK>01^~AS3 zHH;o?{_PzG)hr`{+9dQc@$p#HfOP~P?B9&vohyX*Zw3q@1iuYhgbs~c_1#zmT69=4 zIMfY=v#Rr*E1UfE<;y4^8s-i=!t84EyO_|!$6M<}jn7-lTqooWOig1JFBX8=t^Z>mbNJieQq1ha5(%T696~6 zrOED=m3*Dp$9kl!m>3_prVmY&Wo1l#tDG-LpXhECx{s?I-k260L0{6G^;#v9x_Jm# zY&?QKY>XH@2ut?>WASh@b}4o*#pHjvWVXwENxyxqPK zFbd!F85ct?>9Asc_hgzp#vDCe-8J6dw;#lrmS)>4vS%wOLZ_1bJzcZKTCf1rdv>9k z)`9KosWlrLJv^le_IjfSgYiz(S_cV+;u?@P6I=tzme~$eYYI28V5;B%z*GNdScaU? z(dXiX6A(P?Une{$s*U`Ownyh|hE>C^nVB_2gS`~IS(^jK@D)^1NVC-4Hp~QSHox#X zCnG^&J{Fd-H`IdvB3=BFqn?w){zjP&(^Y$c2=ES2K7zzD6z>#2ENsGwV02N2Dbsx# zJ>SS?rXhn^9*EM7Q*E|DvW;yJza<7loS;2S6pjO-Kv;suc8|a>#P9Ii*iY*?tfB7+ zcJ$CUeFQm6DKGAipQ(uXo+B`Y9t@e`Aw*IWt7vY+z2zHHChkmM!0hX04ga{6-k@<`rmOqq~ zVh_+KN^BV`2OXJ>I<>$@ET;OJ9HQ07O0aO)O1_+zFT-J9>&{M~!wNm(-g#M8pV7vB zuv|fv*10N%KK!Lsx(p-|l;uRQN&~HRi<{iD8_(xN9n0w27LgDbn#@^1M z%ZDOAQ!lLTJr|7osViY6o?vH=zmrZ>{2Xdhee0SJ@b!n=zsnXaY`xIos;JLcVZt}? zn$I0^bZOAVWZ+BxQ-q6u4)3>m76O7!FeybSwZW+q{0mkEY{=)V;Us6#0hu|qwI@0$ za4{?p+EVBfThvu+6PC;4h~QdL*Nrlg-yKZ0e}0_HvX;oyNw#%nt1{rzni;>#eXrjt zd=|2pUT!=sKpZ{UWN{ol5Ducbl?w+#2h404MG%#%}TmmSiV0pv7S>x>P zK$J8!kQ1GKd^P9hkR@kl#Iq0(dp{*gsSy}gJKu)*?SK&D)x(*e*iqPv3iq|X;a`NC zGP<%#e3_Jtqw^g_z6r|tAv(8qohhzi{rd>v?lJ-IG-9d zDrlrd?0BV$LVj2o-pl$2Dsj=UEK~|M)!(^5x`P^hCKUxZ78&Kzm|C;^LgOmRfsJPd z-o4)J;F)MO|6sjqhV`(g&CY`L@~(QS7<=OTrz$>axFjD0U_Np583U#J{1gFj5e*`L zQT5mvMR&TQ-1_+MCY+yzfD?{wYxnQBo9liK{wfFZzR)wDnr6|dUoHL2m2B;hmg&_l zzX>zb?%?Zs#ckX=j_mMh#+WEdR)$_7Mu`fy(Nm7>QOc<2lo=9Hf~0i%J~f`~>!8vI zinWScyI`tt>^h@iym}l`&I@(ojV)6GuEq~4t%Ch%V7vv+Rkf-TobpiucC?McR}T;v z?D{(2T#SVa-G#mo-AU-f9NXri+AN*{pbqpkLCq}eX%VjPLKPYy%T?7ypd4!{#KDcVmPUOoSI^i!?B5Wii|{BG$QRIR>ns=aGIz$ZsF@mpF=#7g4X z&d{f5D4DUdD>ruoeddvck==H`43vZz6P2;3LKHu4S)&S{@2J1qzMXAXG zMRBsCKM7P^T8D~E^vH8QOkGOxH|)dVQUV+qAJ&H7*mK4WGo8bnRE6i{C2ki7j~1Pi zP})}!Ec&xjQIK#R5ot}E2HSMmuF$7sLEa!EE5CjcDuw@=50qUJB?Y2hq|iEOgcmVL z&O)T*F>(((Eq;CiA8qzMJ>>~;82QhQGlzG~jL7FEChj>Ej(--H9N}9e*z(t}TJBlu zzJ#wDHBN*qbO1JxJHlN5s={eS^RR7F9drx$bwXmW{QE zRu`&Ub7X;2)j`3elN4^!Dw}t4k&gl!M{k?fKD)1-YBAo{GOLZ7h#vU^q%!Zy@+N>r zzCwS}V)!wH1|^Sa_TXMa7$`HZ@v(9-ks=h27i50bO3q2=Yw&SnkXRohQk&ObnaLz@ ztDAL84~w3KfY@z(TmJlU9UclG$|yjHDQZO8x^h-EUEg>_>HCzl-t-crIYAj*3lANW z^V$&jqS3kBR4(D>()NCBA$yuV<}A*S4nvW1!$6d4np?f6(&Dx|i{I15@QYD}xv|B~ z^nL7cF22#M%Dj7^DeEB>_19#ODkDjP{{sKJq^|Gzxrk*{I94}FT^WAq;Fk4S)VIsC z_@f*?CAQTfzlb-EZO7qW8(h_0lR}whuv7a0u)%PvlR)R<%g#7yXDIYUL3_lzm5IDD z(0P^2=V4*IUg`ug7t^H*-Lq~BAKg}?`t-rktnk18%DtMwE`;1bxw6T|r8&HNkx<^> z*+^Lb78+n6VedLngBmfB*9C2bs(^mW@$XOL(U)qtsYIOFQLM1e5TlAUhQeK+ycjJ& zaIKAxi2g?unf(3%#n6W+J*3Mg(`x>vgOKY5K;EEIBGOvDAB^J78_XfU*VwC7w$pXG)ft< zN_Hn&)0O^y9l9KKw7M15*=1$w(WxdIBxGuurn2SKYO0Xcjyku{g&Q-cCHZA~=ivG# z(F(R$@w_3)O}7o6mUNGX(1>wo3}XLvS0Gr|S2mcH9=AfWK9`9oNg+*Mh~d324qL5b z?YFCEOCUtT_4?-yPD?c92={&rk?|BU6&r~Up)1;4lhWL}Gpl?*0`B=b)xL_iX~%~x ztyIJ7Cd)7P!rt41X;II^wD-}-CCJ%-$&{kXryf6EA4xX2=v&o*nQ66+ z@hB&$AiRDH%}C==fngGtoEW7USs+BT=>4L(N5BnytQHZvpSibVxY#wnMJ0)MJ2};< z?!7q_Y<*dojDey%$?3$)bkHV{y;9H2wXLi^dnKJ1M#2$2(bt#o>g%0!&i5mfF7Us? zJYu7**KcZ2jrKMaQIkfrnZ6>VJ=p5HP)}$7yJ*li<&?b zz=SK1&M!jz!c2ov8eQ>^F@yN0RrzZbCxDQewtC8yJi~(xWQ&I7Ny`n?cXKd`s32$$ zzedvN+@?lE^rf|eHjwgo>JBiEomsj z@+Nm@Kd$?Kv&SVSk|a-Er}vakld6){d_?TKoe;L`jCfl`4nhO)BKo8ROHQX`Ovt_K zQ}N^3P1R&@wtV>!kNa#xDEgUzW^A}wvo3~wfSX&(u%ZSBSv`)xEEdDJ(MAyQvt?t2 z<5HK?g9^M##|0~d%991ZcwzK_TSq;hg zh_BM!zCB>P)@zF{V0 z8tjz1C@%K9N}_W9GG@<U-&zM8S!4F7c969zuJ4!T;N^fT10oV627>hAE> z6I({BW>>a0O?!QU5} z>#j+>NeR{*PB24j&20UR4*#Go)%k_qNILFlSDH#>=Afx}%(De8)&b*1hH_H>e(R_m zms&C4InXM*ufhc^>7qmLEQu?zN=6&hRkH>1>iPDx;HP}4snR1Wa{JfKiiLy|f(Xt9 zH4ew<5mjGYp+?JGz0Wf*TgqS>>$|OH$-_N%9$_Bvv*|^u{lh@)GkYxOTyyv3Rv`lt zorQuEGl?o=Z-Dc$VXZ-`O4mUi%U#H3p279QxD5Nf4XDRgbYCh%^pWEoA^GohCrVq1 zxw^%vcWsJ#=o>FY=|EFew2FH5$g6<{mL}i~S(sqND$5FXW55P6l$e;_l>I6bwLFg?=b6L2)7{D zP@qP$(8Nps0aIRQzivlKVF1{YV1>tkT$RYw)`VGCSki#zHqV~=0tp9kf(<00ME~Qf z4I~p+!VTfwubCn~{hkpUCr-uBa#c4zz$pVui2TM|fzyNxAkSh=!w;67kYVr$-M;4 z%)<_^Tn^V3e2kY}|NE1c!>)gQ4u5`6|yEOra{}+}f!TEIz z`q|r?&EKb0bxw*AXhQ`E8m!S(Nx=4Amj}{eBb60797r2P|C z;1FtW`c{F7#d)>5xM|)1Qui8~XXi34+3UIO zGMk+eE9pp88X_*(_~jSGF*Q-)5ga||rR zXT8Z)92t!j!iSzyjYjhU1|0OHKvXwCud6(G%imA8sp--7}5Zk)UPw$gH zL4C{+rp;**RL!3kG-emz$f;$O;C^cX-%MK@`foCb6%X>?Kg)i0Z(2}|4%^6E1iuJ` ztaK=6t#=?`m}?_GR^E1N?eI?1+w>+i6B<~ELZwIGBtCmdUDQ})u6JY)gDcwFUlck= zv-W2+ikuy+TO?_wc(8`*H!<>~oh}_x+Hy-<&ML>)E0QJ#2I%tsI5~A)HxhekPU5RB zR*Sm5)H4zv#^K-I7pAJ4wdc~Oxy&n|UWz`NonhBn5Y1n8Lu1Mh?fBM8GeCDl9Fu75W5h^PX^Z zq6-WpV8l1%vtA)SB2fNj()B3fEgU|+00K6Hgd8;7@KuBL`saW~(9JnVGD%K%%iZh{{# z`2?G`oh8b#FK$-w($!&MQ+}Yb8u?7}PFdQhDs%X~nfZzJLaMgD7)Ni;oa~@ova(b{ zj|Pw^Yb!blJYKUd!3aeXh@pee_hu~X^!yI}*Y=2ugiC=%3qmxhw6-xoVsM2}iTpS0 z7++T>!dw>=?5G2!5q#~bW~<+7cb>gs@YHC`=at6LvMi^dX@D-nO9RK(;jg6 z*YPcQb{DRhXP2{Ws>5rM`#Tq9W~{#yy$FHorRCtLC7{6c_6qBJa9DVO4Rv0M1$eWebeP8^fh!w-uxIVQpsxrt zGwwHb$}x3Qq5m7#hZ%7f!_*WA7mWl)p~JNeg6#NG~5 zJ@1I)c@b}%ZWwR&uPD2T3E`Qph!&PlUWs#}AWoJFn(g{_eB<>w=QRY^A*&@+wGM*vpFk`HsP-h{=)*;csyW+RJA)wS&m*K4AtS(P<M=2LO>9ouudwLQ6R(#J9X^CPP63jh zx|%R@4tpXTK6hWf3va(~dXk4h;kgVe%$JCRHxpR5H*^q0|w zgImGkWI$WCwWS6lIQ)L%?rQ>HXKIyP9lbJ+a`!nr=Fsx31{8Qq;s$)dV8;4CrDB7& zsX?sjhgEHiLa`aYop^P>KTdYW5K3eS<5fG(snxFM`Mu=%(=GJi;{2=iTnUa?lKH47 z%e=%uZ-U40+9uh3WS7pq*{nwikJk8aeoxpB_~U6l;;_oaD%`x2nKdp`kEFdrUo5%T2!41GE4LLbm=3xNS9_ z!J5wcRG|?!6zRs9#9LZ#a=x%Y%4eYXq(7%lGV_2 zHiX_UE__af=;RCQJ8Y|rCIuBb&i6ENZizV;`0L&KuqbVHqu*=*d;>5`8~|u9!1i(G ze7pBfpV&A$yzOQ$_{^Q@z84=O%5QcO&K(>dW>k&b*%bwhqcN4;b>s(?3zgesB!SED z)!?vFF>oc&q3gx4k;Qr#N%zzG2Xk{t1&!F3QP1Nm+lqAcS^q%x6%tNvB`t{6tF#!A z!hQla#FDpyek1MY{Vg7nx(9N_=J8)^v%HVT?wfw3eayboQoV(zRcwR$dNh}F-#(&x z)&>>XD!vs{Yj69tS7Z017d};t1-}rtg5I8X3u_Dsi8;tq;_(7ir>uN9Jkj{y5OL!O zBH%V+XE5HN((YxuQ^xI_KNwpfKPNn2=)ZH1&#%gBtnePg`ry^)4*AP>J&P2GG9QCD zHN_>nOfI%rO}43+d3AbUAFQ0Ad;KIyrESq$&Cge{#QI)R4(LYkO%mk~stqJ9-(cA# zykU?985RBSb?FTG3Ol~Ht0~qf+IvdWD^ds=I%9r|m-(+R&q^f@$6hR@uR$`kYC#aT zh#2b9C0*nGabJk0U8u&EXWopO#`)can>_t#W1^uyVD9^AFwgsg@V@)d#6?>>IsiK% zR5bfX(u5FetAi3}bdoStwj-lkT6^p5$Iu5t`Y{rZeVR^)UTYTos(FcaqN50DS#Ob; zRuIvM1;4v!=wa_@a83t^yI)iS>89yd?F8jk=f&v>R@0V!TA5ONYq?|L>Wh^{^|`G% zV)RH0y&JvoT$Zq7fHpKolNegIfszC!xVCVI*8XKYdG=KFaGZ$zXQkE-KPxrqQ47~> zZ_Q;txUaqfdHUD#S-2CIagN3n;y=4@SPtW#dh}3Ll~0+^HcY<0941-`bfAn@V)Qv& zdtm$Vq%|?IwSQaOBx+7%rzT{n5vjTpiuq%llc!*jyO?@F6$2%5ozo4#>_k#f3)qQJ z_(GUEU-~7&i2c|Pd1ih0+;p(V{Z!h99u@`?yMs<3qtH3$ znrkccinoyJ9zi;4AKM*svJ*BI!?lD}17zXzgg*Rut(F%s13PG!a5?-v(AvfP7 zun;TiQ*3K5DW7mPx025x>jx^Pk}P|OGlHhcT83%wKX_)Y0c;-i{9ML^+H zb$M5-0Br`)-s9=1Z@%upgEOW}VsT;3qJh7xwJ^u;kEo7rMq2zUoFOwrD+wNnP|J_f zReC1KMB6f-Rv=EJ|IZwThqSw)r-!a*PbCb;o+Nl?;kV1dHn30e)Q^->@VhSfVW<+^ zCBJkGzw(2l^=Q3w`;?UD1GR+b?hK8fCCZF`cjKvx@I}xfK%>8Zd(K(knwU;kdJnG< zgKvuW=La`OuXe?nz7o^Z(Q9u|=-n!%|?N9bkxfkamb@IHMcDKu4b zfvovk)af7TE0%Yy9F%_M8}|(`M=huu35^cg+L~;-x@!tn9Y0V0V0oGW589e;Py26u z4j1O^{$;4_6yd6+O%-J$`yn|0JQWH1Z!RrDsa7SO6+*lT5~>!W-ckW-fH`pxG3&!n zS_3)wgy*^$%*+rLcVjX$ z-6bwM$!aMt>z$5XMyX8m^G({PBfpLI71bZ~EBKv$`~aQ^l$Wv!fY%n%e7rT3C6F4i zmyf?;7Ky-~k6o|}I2@im8;g-LdFdmX zMi&73&k@~79aYQ~MFixgG5pD%sOY`#1u9Z)ClQoK$a7y6=&^s_ps zCLj9J;&rREl#9-jO_FBPu?L5VU~0P>m& zvhA!6bEKZ!cpA3V8Phz!2O9}%#(=hZTYkG-upAbZER-M}{MR7lg}w7mZA0HpMT7yM z^Clrl3?d4o!(l`IjfJKjeL@^;gVqAlCD1d2a6L-M$xmT0TI%aoB(N&36_BvLk+rh= zQj+;js9$-Vsa>hTpA0z@&%dhSlH{e2n@^`(#OgJcMKh260U8Ay{?zwm2mL&T-ch+) zP;pFMrZL5w^}^a@*mggkP@+$M`f(b*+_$y$1aB%9)2k%NatJZ~iuz^!=kguI@)UFD zkX?m1GEx+gaGJisd^S?V(PzjaC5TFcExVin@g9l1pgd-P3c-n$$V6?rm?7<3<*so9sKdz4b=i~Ry~acb`xq3SjG+f#ufhI z5gopr(#b`$=!DwV)U9_L(bwgbd{W${i85Tap@2w1>Hi}#{8?7Yw0>G}HCK(Xc0~T9 z1tSovd{Me_h;Ro)B1ROho{A{yvbt?Y2ryh-0(8GbUSGn}7z1v&l zk)Pc0N;j4jEgqC2vWH7~)r35K{oU zlW>LcY&{(vp57Qh%-tIta3po3DH?Ob?%vJkavuuDYt;Y47vym4u}a#SaAT_=az;TY zRYAEkY7$s9dXTwZ5U+qkMWFoe@W=~^JmzH%k%`G=rZ5Jh$BGG-)ptjW%hs*GZTP#G zsL8#!r5#X`4c1R9OT{{W{VHWNNj%eisf zXQ68$`6ZJ_rRn&Zinb||=^mA3`akjj#Ln7BsmHfaqdB|Df>sAm`{Z1mk37VmZ$?Y2Pu`ST2kQB{E7r7A_}_{asnh*7D> zf1x6s1-Yed^RsY&7sFSfyym4i#^x|wSloyA)_S1I|)cE;3^ zS3pn3<-l>i4n;luLTPD$j;+tY zT=@C^3D5P@e%k9i>V4#SoGm#7lHMIRD1rwe-A-ezB`_~b?OtyK>0v}H5jONOihZYWdR2F;(9j}r0g{NwPLN#EfrgHF_~0bTN2i7d8z)-TZTje zd6s4rM{fB!ulk3pk`Z!g2>`G9b`z}h#o zZZrMSKP6kcQP!K_e*=5=xW@YUJdA4oTUGWhg9Y}wD5F}c?G}045A%MT4O7g(WvKe1 z$H)<{@j>j*XPEkWuV=}1;B3BsleWrJj(1w{N=C$vL{jtJNOd`Of98H!R*dM$GdxA| ztz-48VC5h83W1A&37iim&H*Y4=Fng{2SOTHz+4+;UKaCYz15AnkjYUegPk;qroz&k z>3ETl(Uj+V+T+R&T%R^-XRevG+MkQ~`Cd4m#KAgl@Jkt2h7hqJWkuL#hBFt7ITZ-N z$z({yjUQW=A-CEthEGB4FG{~!cCj{D$=ho*L)I1h$LW)=-ND`rb^@BIRSQw&wql!dfq?MaD zr~Z)!8W7~(-SDF)Wk>m+a4wBaM}Tz$n~${>sD`+J;lq*fr(RqZFP|*15j@r8W@K|L zHq7~#i!Qc!Lk)bj@j~Xe@JQ|eJ1WG^x5p&KUzTl>?F+%P?}GTB7x5R+562lZBMhGS zInPjH2A`brm{I{p9BW3vMTqJ>380O6dgE<%Ei!G+S4x51hdtF-LhL8s#fV&JG+9qj zsBk9${MXHe{pBD_GK~Fa;AH}KX~nQjc-Jz@%O&j#LI195()*<0zYYyT_7u#I3U#*; z;9X*tWgW|L))h%z;g|Q=kAqnxLrSUvVAY7*$!N1oUxGa&|6mT(AHSz3to{aUH`RS3RDH&6> z@@Qcvi|rH5#*;&Zqg`fFKq!;~kf-wIl+IqB)v!2U7WnZCYr#CHr`6zI5m~mVoFu}i z`0v|~x6(`B+I+4Qduki4`+|2UIMi$x8+z0F2fTU5JvOQ^;6MwgieY5ISnEqgJyGUM(bSP#0TXKM6##*30VO}0yXLE=%ig@TiYIWkSzcbX&Hj<)r)*~r&UCqM zt%hvu?RY*3w`vYCqspCI&~zy0t=eB&3g`se89&I`MM-?hS!i7-Sl%hWJ`dT?tyAhu zcxYIZzZZ>6Glu(!%b`@7j?d$-I^Fg_cXxwTRro4ebn0T)xrm0 zjRdGlf1S7DD|$S2L6&KfUVlZNoD56tfccRNp>N@p&BQU>*V$XU{t1^l(tCMN`QU@L ze3?V;hjcj4i+dJe_TH?!P&J{H{7k?PI^jMZfC3^8n$E77a6!Q!NmX5la~H(Ym@U1Q z`bx_`zXen1%?-T$##L$3n+~Ovl&0v8WQq_JkrcWTj3qhZd8#DLZ*KRt*+7Kt!gQ61B=|v`)@w8J=1#_am*L-hqyNQvHFCQ-z5Mnc>=(< zVk56dAJyF|c{t@h95EgK?%pwajZ`bsjTh3_nBmca8ww4xPz`K8_Qug@Dr*DROPeKs z-ZkE@dyOjr0H?;;?TNR+8Kd8FQbHGZ6XqV&NlHAL8ku`OqxGdWW0mss8rTZy49$^+ z9~k|hI?Utm;-JaJy+=r-0QKz}o&Se{gPwb@4(pf7}w5reFWA<*UD9&|%5}kh45=i+Nw(j63f?(2E5Gm% z9@MMv3jYcJM!od}jrr1jZZ*y%U$-r&6ZuzkVLHKJ?k1tm8V}|=Z(}$24&qq#EB(cD z*`+)3Mlmqo52MObuEL?n!+=XG!3c;$}*GlzNkwXucZ*NiuDKQ7Mm?e%_-FY3jP4&{o84s$%{3NpS5{=Ca@NIfg# zBJr*KBN(pIzZ6CC9i|_t?{^rJ3HhiQ@GpH11!F zN_tP8Xa#hHm}ori;S8O9;HO*9v{?cU*@HuC+9}!wul_q^`Yv89BBWW*^Wa8w^kF2| z(#-XuRb@qBJwJ_H;;Cxnr%8N`=egvrK1TawkFW+u;WJA85l;N1!b zEo10N?P94TAC~VUU*T=oE%YlS&ki2`3biz|421v}%plLsaB5qNfq6QMv8(fMsT_Bd zH!I1L4XNE`?ov!SRj^yF-4E);sZ4K#mRw*$Z(fuMzF}mHug*K!f zLJSeau}FM|gpUhk;-|uO5H}8h1VSpB0Ih+T!Q&)xt%Jh5`f zkA+gL5e|siGK(q2x_xre%S11a@qTZ{dsFwm&0}zj=RlMEX0iXSu-2_+amS{VurcS2 zMIpPd1%=!VqV0e5$Eu$%Pk;r((1RCI<^$IgFvl_JTttm>+clugUsOTK|DO((?gOHq zLxf4Kx4g)O>Gf})k$?PK(IUR7Ju~0X;|1O$&WYWy7a6wm3x*R8ao`-TaHtlBZvLs& zb|*VtUOyvRHT0oXO*SFxGeuN5dfFc8e)>jhsHLeF7hOxarKbz!kA|H6) zF72-Ylge8bD*toP+C0+C)m0FicyQm72q~GRvpwrjym8I#3ivK~*}rfP4Q$srY+A>v zC*i9oPU>`u@D~#Ce$u{wAEHWL!az*__;Y8i+yUFZY!0nq{ztyIkf^r~X~qj^!&g7< zSEk2(WtqprpHAoNeB~EG6f@_Ha8ILP3JfXJ;5=3s1!Pbc`fKpxxi&+jRk8}LiIZ|! z44**9oP(6F;X>>&+PBl&b;UJH0qh$(!R##@{guTDSV}SM&m2fUiV|mhN_ofzujW83 z5GIL{{P&k02 z`ugC76;gdHYb{t2NUXFwO-+76*wBpk4?hLljw2rNTU&T(P1L~K8taghZ)jXWfTf8A zy2Pr(zYLn!sKv_wldSjc3ZPX?OjlO_cJHBSljQl1$Di*NwJ$|7|MPl1D)z~N<%d?> zdR(^^{JsMI3j5rD<6O;lV$lpvI|+ag7Y6OnvXy-@w^@ z8&4Bex$}H9$*!|f!!hKd;r9V+k6^Z9waQ1+QuuF{N5lyvY3|au<%p?S>}^!3ERcLR z^nhvQn?qJ4#LNaRR^ApH+pv$=14$z6i)B?@=puR=bL7^-Dex-Y`Ol=nDbD0b9?$T)TU~hhDksqlaUT zbq|bTj>ax4Oo@fFGoFV#Yx|fLBfBSYRJ9_Ic5l-w)Xv4vSSdy=w8tZsuqT8!^xVQD z18VOkm3+mU}25_M2Eh}as zB`*C%le)r3X=<*l*P-2C-mSHo6t$~xe6`k^0-z=)It80F)*S+zUR8;BZWnKm%_)YD z^aZfJP{|YP1bKS&L?C@X}bbYjJ*eh+Apr!=hfO*mvhWIb*F8V zncpj_T2qyj?Z9EyjyxKQ2OPhh>Mjbi-!_)*=3DlCn*OVEl+{?l+`BR<^Y6pnc;TeO zaW?@1Zv;4+Ba$H5CnK2DY;^w2QquMZTS?_q0G(0}g4Uq~=Q#$ZkUhQ4fRKwjH+sY_ zYcC%&XoFrEf4|RejO{GSIYZ9vtc-52pt_LFk`&=HYQt%2R&ys_l6s4|GPAQEc$cEJ z!GtC?5sejJ_|d)j;I@47=RhPq5vm<0CX_SwD_K^LKzDjzbE3R|R@=#8sofRLG&gF-cf zdx8#Gk(79gzxAo{fr&`DRQ#EEzN2@$3-UFfcNiKt)gmS~U6~rg^aM3L zxsrM&B94dAQiF#s&#%+~pZ6(P6G=@o3aO0yFu#LUmmpWH(>U+s~k|8 zwR(Dc1w9IFl=XXKjR(_&?-g%VS!#tUG>Xv7oO!r)#oZVXBrG9t9a;-IR2OjUf`ycf z>-$Y0@t!CuTLx1>z{B*Vl6u2)j<@a#m$HMs+EqAvHrkkEE%)$kla?vRSypmn7h$QS zqpvw1%xY#uvImPs;d-6Q^Yq7skTK@|7F%fUsf$8ifv`EUyY2S235@pU>=HUGrtJ6< zX5v2M7=;=;=KV{QHE^QvEUVdYs5!L;%BjDhB=FlO_l)O4D}JYHAxWty@Tv{y0vaw? zD<@}s@?oMQh>yAFcZOI(Brd$75@K9*ztH_m{6E0fEc*-CPU7rspaTMB#Z~nsRi}>- zL!!ST7GaE{Jzg`#TJ^48R#~j>ni{rzK>Dh*n6zbC=}Ek$s3=Ux%58UPZ8b9coOh14 z0>>qCRH{Dgbt8VJ%ExyllRk`Y$KSXQ|Cc2qoJ|M6oI|4_q0IN=uza4Tj$f~$^)47P z9l0G^%&v@M<}4S^yT=M#V6pY~WS6VQd{Z?$clC@Gv)p@IX8~ZV;Dvg?8xeVS>;Tg+ zG4uUXTv=jPTt#j<5rI1!QB%C`4L!FZq`5z!AYj8^fdLN->0M49#9f`ZL7faSX8pDh zA7J-%X7t#%ZT_If!QaH2KJyECB{j#$l7Wm<_{P(34#a1n*hAdmK6dTVxkXdsEsUcq zEs^IT{E6Dy`&cp4-$^z#&m-bRXgi4RrsW&{kfNQnoKzfR(A{O-KLxO;B8jUb9rMNp z!!AsWsVO2K);%&ND>EJAviYVNYF5cF--XSX(eud3Lz65SJR7x)ppTRTy2K9GH#HA* z$c5ddFcBn#N$(#p8CLCq#U#anJCKCCFlJESY>b*XBnmU5<9J|W6atOr*EN7AP>01~ zzRoCPMk*EziYO;!#RRL(Ir;SH>PJn3C>xVQ9hOgV)dXvmqPC8OXOLT(0&lFwiek4? z(($5)D)}C-(^)LD4e8a=M6*1kNAPn`;(MY1u)Gam(amggaVD?Dp&RuD{MkcD2dj1^ zv9cGLl14kf-dS~pZUf5*^Mxu_6H+Nx_?I}Ip>m!Or9#@#dqOlqUR z9y6W1|>%N$1C8n)8$T?lPQ|Kqre_D>4Pd3ktJ-X_xKKrbJGVc+W`hcEs^YS{v=Xj zGKVgRkm8?5I;H7DL9b)&u+|+rfHlscEX!3k)&fx{JMCu)9Ub{WPtZBe2~~by}~dJspg zu0K@Der*{X`Ut$_2B3hdgV6)zbo$}SB`o8Fk3|zRv;$m;fEf^J-U_txy9zH1oRff% zpf~Md{N26*4wz+j;0SfN?=rOS3Y&_r^H1~Nni_9Bs1IO^vje+@_tLmX5V!llO6&$D z8-karjA_u+o^T!PQJd}pUBkvZ=(ZxMoodU`t!kf6Cz*0?f7W7qZ@-{A8nhH}Py%$% zlsxG!ms}(Yw_aK+TesD4U-Oumvh-@l^zRU+HQ$&C0fbbyi1kLTtSi<}DadEJVGleU z2|0w0RmkQBTh@3(O17Bma2@5ZcVg5lHO}>qGilP28!xAZLGJ>|&kAed3FcZG4GW3Lk>%8@OKIpmZO~<(o|t$BUNWn&$T7faxCpYyD><%A z8SlDR@z4ryGvbd`!mIsNi;FtO8dgirG38E~+% zImgK9NsY#+3_Adxr=52X=Pq~#m3s{<=#}*D6lO5-_3RIPTl1y@*r(Q-Jc z96gwA`j3DU5Q1S zs@-0|MQ#tLd_w?{g~5Zz|0td!D}lxOaMoA8Ja>p=jelh(;}K?NM<_-TQLxH76gb6TcHJN64v^70#`VSV>X{1ejv{+|1jWvZ44@@ zG8E|D?>JSrs1qIeC9TzYF6~BR+8Gqf|Hrc-X}7?=;#(;x1Yc^%nP5gR<2EMpScSw@ z(I>$g2b7&3H|9AMS2wdxyH3kEFBTiia8Nl9H7lzShzgx2%(M;AA3hL+Ybe$Yj0xb8 z&yO$Ygt_rOeiqF3TCRC0g|3KeTJui`Vj1=jwghCIhe=-GShd4xEC#{uk~Jmc~Fw z$J6>f!VK)Kq;#PuIJNxYf0PjL>Hz!mlQPKqmEVKztS=x&Ng7QK#UUO)fS zhwE8lA{d@>nRVxE@Dd1e0tMjKuCXTjScF~mzflkD@bfv4meXwnF%lIic zFZ*oF<@0PbQpM)M6$7{g06SbM++{v_*_qVMZYG;~B|DmN+=}QgJ6wq1s_0sTAkA-QibGtVCSL5MsE!#}l0?{fG6>@{Yfsd{6WM1SG z385w}3z-l)E+V;yGTaaGIHdboQx|nA3Gg8tnp9o{(^4{bMXMsY+Q@7yx50jHb!+^r z>bFLsqn78%F_sibN|fl>_SI_dPIUf3e5_;PA~Nc*D&G?2F1OcFi#~{*+`41dl4o_rXbP?&k~gbN#ml|&&J>e5Q}XG=Ei-R_4jjAP^vKlvRmp#WVUl{JcZ#V2iqTZ==2VVMb7gcksvM=ITDRiZ zWaBpKUsC*_wrZ5FMCJXRP#_H>Wd&`UAYj|9l^p|SjyFS;;J5OXwKN}}HLq?Mkr!)a z(8N+$`HBd?g=P476I^#9>yvQ&!MwV_ikv4srZTST!SSi&_?=LAj`h$&;_h|7K8J29 z+h~$N7;!1}eVzU?FKcB`z@cYnC{wvzTj__pV~9;#^tOtN^Lsb6FU(jA<~v-k-0m$ehk6*FYDybM(x0v8-6c=La9$?E6bC&|Tk1fdCT!FEh022M4Q>?0OqG z0fn!lx2(b_Ce=G#lTti$d8L3G75mR1Rku7bgYRPIvzo+14c}Df+rgh{3G_ckZ!QQ0 zl$GqOwK9;Wx(Vq(9(&=>#%rsD{}&mt`57-(v}(x~kLsn+KhYMGqQu`EVXp^wLPbII zzG2Ln!m^a^L+?3zQkU5pG95Bu>6kG^>@RkSe!LcXLL9Xp&|H8m zDh|wjKO)rS&dt*Y27%4O1vlB%5`n#PqWN|aB3K+V^me_=$;$=2A`a6G0|rbV{{YuMJ9)v)sL&?)UJ z0?`nucZdy5SE%H+WUzf9$`8}t@A;~nfmUhojbJ_ zu-ESg-c^@C`nd%-SiGMjtaR=n>hN^1nrjDY&8KH;_o92u-Z`1F$eiu(ScH~qnJyUR z3VvQj;3?8d^?lAEKIMAFFge7nlnXjLG2l`r)cvkjyI;l3lwVrjO5Ro{wOyIUM;)cR zTEs&YDlma4sZ&!dzph~&ByPmxRRH402Ce<4K^WZld#NIbLXStOlOoo_{~Uw#C=L+g zkz}oaLAgn-F^E+nBxus79V4ND>Atp*)uYkVxoG>RQ~#mQlnM{v>3+s8QS?O?-b-r2%WosC%SBr5h=?Qh+Xy&IviwiFR z8(LXcJ~N)9sarKxMse^(pnl7dHO<|`P=+SHWjZsz`v8YBSpu#Azm^=1<~&Zr_^a** z9<0~Dt~A`k_}ryR!xX`5*WfeKpe=+YXs$tPqXM_}o59)-3A!<^QZovni#&~gtswP3 zt*uYUHhSJnZiNzmsB6&bku;il3sNPD=%b(TN>p9uo-(db-BeIG=g5tL3uek8aI8Yfvf#+boLUu3ZuVe%9(378`xg1B#H$)|7#v(wSF)fSIa9JB!_Ifln#v zkKZ5(2?R*)B=a$mWyl1sE7XWz8z+4XhdSTE|L9!lY?#%VY##nNX`2Up*BFdeRkr;0 zN+Xmx5l2E67r`j3WiZ;Y6YDZQo@9Ywf8~faXqG0?Y%ZfGPFsO7X9V=Xs~0;w^!B&a zWn|%g6cbvT25zd))ii<~X3M>I49+lp`jCcJ*;LUSi8TQ8d}MkzEH* zjYjyH2yy{JDBzvH;fy;`V7G$3GHVuj4IEunl(@5HB%3?qQBiJgaflL^tS;}7x(xnS zZ<@Zh4gK_B?7Tht3QG@+Q<{ypHfJib;Hxd(Pn)-jOu4Q3i;u3qV-$sZ2TcBAtI|DB zJy2#p-karJ)XK7xqsI6u@5O#LJ^Qc+XonOOEXpwiP8A>Xx`h=U>=6x(WN%L%Z<^{F z@eEpLMgO(nFjC2NP~-i}93Hc`QIMb&Yx?vFl3L{t>+d%)?39WQ>ZR=iH^XdLK;i7| zKDJ2nz>{MMs#NzooneVxV4xI%=9FaN4Ii$n zap63Y0%oin%umZ*64$=^sa)N6QdetogeepmS85@+Fg<=RklC1`cOK~aY-85KWBTy7 zl8A(Ks3z;EMEnu@tE^>4R>yFmYDZC<|^Yr{;!&70RxKno^&+BL2FRF=AZ9I_}UwUiyLOpO+QZ%fv|_P)FKDlgS8bMzE&AM*e^g75qSP2O^# ziIi7@s}0N2N9{T(_C~+xkHloU5E0(=s<<^RY9OEQd_gw(h3WyjyGz64u|;Qy9a}>~ zN`r43mf|g9tA5hjS`?f7jH}7^#;-?IK=H$x#a5^J5p`x-t0qBT<_|V#nhn)Cznp8B z(!GR$PMNjx+~k1{-wUss44Eh_u4fZ^BLyA_4oMLbNh4)I{nDi_Xx`7!(TdW?PjAR= zxr;V_FT={5qPYGl^biO=$4bC->XD!A#i2;7P?qbIlb>tWA`OgXD5}pOtfBR}wai@) z?lt`h)}suC?p1Az6JJbBhBta~p?)-Wx^?n0d+3$M4(i=DIH20A-YlEYL{cByDpd}} zVLQ??B=oNC2o3$uXT^t?faOU88=Vg~ycTd@ywRVAeu+t4zX)SJjL}f%Vcw;n@LYR# z;y@RhRh5g2`Qk`nM=gEwoHw#X=g>RdcBROwxM7hQEQ+-)I@n6vxYg)8l4ifV^}eE9 z`TWjvCY!m^muidTl6ybB@vlsi=dVJ2TiEyyr{iP4h>tk%>#rv@&|7^K2OoMKjQx#&7l#E||+J8nxu)w(X+r(NFci-*8%tV_;sN^Xd4! z0hz*IpB0v1{sYXAz2J{Qjb|Z|I6++m&Wx0N+qEhX6)DM^<#n(fZ5CG+sGCX?GXEOt zy&Zs5#ZC+#=;MNcpXX^7zL{A}-zCHo#i^HoE&F(%C#P>RN=yIMtW}J}W3(4{yqilP z@l;;-;f1fc<(r{%HU9KLW0~Ah7lRcJPBK$nqJsc?7mNB!z?(hv!ruR#>ZUkb zO$O<+{Wy}yvB0u$1BxOJwbC#MK~gDivB%A+3B%&Skhdz#04^T6-ujzp;Qq^~*L4ib zTTqGK8R@gR`j+?rqrBLRPP@m((t9nUPutZ^prd||*||)5G`iUB^>8R)H>9$OWM?SA z$t)AcjJ+^0SRR`0U}V808THi@&sGcAZ!qo?t1 zo8XDSk%hYaJVJSXCsR|%J0Bj9mLVwO43(po*0~5rQ(G5~6umy7-TQdLKy+y){XcYx zyNS}g;BDJ0}~eRQVASV5`1GXD2FA5d@6e` z9>b460DqnXIVeCu;8^U`kUfu~IR9-5auw=uv3H!9>u;Cquf+qw<9CZh$f+1tyR0Yu zwgwN5Tms*acT>7eBh~d;BPNMaGAgVhlH=ana>@YpaxA@?jIm8^N5fZ-R~OQ()r3l) zU>qWtmyp|YKZPX!JjZ_x4hw;$#xP>DQ)nf`;HkbWI~X4bidr{fJ-UUGgDKJR`&cN| zj9eb|S9>az_c9Dby$(4k-jPl!HDy9H06JBr_KY*aYvO)`B3Xh?Um}-cMPGOrgo-1M zFLH+n|H0R{xK*seYY$|!zmM2TUIWrT5M7kKBhdG)zMJ1unIm?**}$_K(As(pUz<~_ z*i&U=qmbrykgclB!X%#071#V|ie!@0e9v;D*&+<=7{x+4{PBsKQ-c`t8w#y_vcW3X zZP!{#A{Yt)k)}OPFmjtTzTU82s*L(@E0auyk*A7| zMTm}rr|TZAvvU}oNO(DG)UCVm1n|_yy@GcnhL$(|_fg|3u(^4dT2ml-I z-2X7%4^aa2&WmnNO&mt-P{IoG+D5U}4n!BhH#ud+QEEYmo`c3li$_m&asu+}(uXS5 z!N-C_Pu3Rq^#Jusw}!0be3LDLKrR(7PPOlh_F-|v?cb>tA)wo*Bu{=HuD8C91ujl3 z0j_g)s#qTeUQUTj&RccQ0;p0k2gYe;nDy;SK)Veq0dxy|38EaiL`V&7sTnY%0L09Z ztu2kAK0P0cK3yqjfX!xW#H`HYo&~^R9VcadwayJ*lR@JCOJN324HxQK2YD@-9n`XT zf8;aI!JK5`YZ5186+X7SJhKkdro}qrcMh)sT%BX5)(hmzFfSd%-FF^c*ng7!x1Gvt z3GiM?S1(2XanO6AcH%+7eYPHt0YM)2m(yN9StrY#gZt$Y>9`>uiYxB_#1 zdl&p_A_@`~2p*dT)9U@GiP*J{nVFs(qaxy_yOPZZ9bWsY(yNDo&=Nm(4|jTKQAWU` z!WQZbKo{gU^Lpo{6^{;|SQHP+bd>#iY4e;#gbqZuI2P9nk;Cp_g|4~(dB9;j^bn-Fd%cl^Pyz6qT!VI`A{6rRf{j*-UIo@qc_lT$>rC?ps3FR zfeu&?a@?-_`XC(c zDPth?frZNRsx8A6LDBVLZC!y8$t^FED*L4jO3FWI>!ajrA_~g@&UR0h`JuEywTa1_g5zJLX`a$w0{g~Qt$7Oco^yTpp+F{( zuut~u8#ew~d_lHi}QBBSM4fF=f#(rl(!luAw@N^JEqAts95R4Jq(j8!3 z3=DACLLdsvz~Aq(m=h2Le|@DXB7Xv0Q4Ekqej>Uh@Dc(6IV=$d63`4jny0HOE+qX} KNDTS^=lg$vggT!9 literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/1-piano/84.mp3 b/src/extensions/scratch3_music/assets/instruments/1-piano/84.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..f32a1da73c948532fa102b80ff65ffb4dee668be GIT binary patch literal 30729 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 OBL3U|`u+dc*Z%`t%94cu literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/1-piano/96.mp3 b/src/extensions/scratch3_music/assets/instruments/1-piano/96.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..4efc40bf0c536e7dee1ffd4ba085ead6a3c2664d GIT binary patch literal 25596 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 literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/11-saxophone/84.mp3 b/src/extensions/scratch3_music/assets/instruments/11-saxophone/84.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..7a961d0dfe2c257ca55ee7f1ca63a869a10e5c14 GIT binary patch literal 24649 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 KpMU*-{rNxX#87Pj literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/12-flute/60.mp3 b/src/extensions/scratch3_music/assets/instruments/12-flute/60.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..0189b3effe290f8e5e4ff5a068796407859e66c2 GIT binary patch literal 45669 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 literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/12-flute/72.mp3 b/src/extensions/scratch3_music/assets/instruments/12-flute/72.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..7b57139bf7fff48e0396e3853d73b6451d624357 GIT binary patch literal 33812 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 N1O^;Bn*IO({txvZX%qke literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/13-wooden-flute/60.mp3 b/src/extensions/scratch3_music/assets/instruments/13-wooden-flute/60.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..c898b844e6e3383ade3ab42b5ec33e298a03a4fb GIT binary patch literal 34383 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 literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/13-wooden-flute/72.mp3 b/src/extensions/scratch3_music/assets/instruments/13-wooden-flute/72.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..6a7a9e99e9826955cdd38633defd14888cd2b479 GIT binary patch literal 36776 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 P|NXi+BjcL?zvq7d;5#Q% literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/14-bassoon/48.mp3 b/src/extensions/scratch3_music/assets/instruments/14-bassoon/48.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..5592bc64979f40a098c71e19c7be4acdf0e16ea3 GIT binary patch literal 27567 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 literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/14-bassoon/60.mp3 b/src/extensions/scratch3_music/assets/instruments/14-bassoon/60.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..640f3de262fcb50e2c4ffe4b4a301c654de39052 GIT binary patch literal 28049 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 literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/15-choir/60.mp3 b/src/extensions/scratch3_music/assets/instruments/15-choir/60.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..489247955c62bb7a57bc82f3f47269cdb9e3c3b4 GIT binary patch literal 31410 zcmd?R^;^?#^gsUGr~zX%j2?Q((>w>`of2XXe5F>53b+zC>BNm|LM$`SiWFoxIXOo z>PNpq&WDQjx%;fn(p>1oUFC-JF#Udu-Gi|yi4V0e%*$EMduv~jVNm8qU5QpY6 zYu-06`5UPFx6b8rCm5p;&mv_ryO=I~Uf6h!Y&*?Z}`cfsS)3wWDkgRHq*@jQ!quNNK z>HXB}ala2nldyht^{R3<-!sMMEWi7M;7sIW8nV<8EPw`RZzN*puU41oTW1hJfC2FH zag};C6Z>DdO}SU^*VKUt1a%Mv1u>kS8SynST zA_bypk8j^pv>d)BR?`ixlfb1%nc_|bkJTs#P8pa6qrq@$aF#d}zxWa+J_>b?SO9$rFo?S`1v>9wz(Z5&E zwxmp@5cS8MnQ3-9(axoOF91A|eEdl)^#Hj{uOLypALjfW;~pfGmjiCAgJ9<`EGb%$ znqLeAFZ3&17j%RT+QR?aUtIC?8zdSreUdAqalARH71KtNgVg2(5D-8r2f0$cxMImG z+~#3rb)6I%OSPeIpbYa}y?s~``>6ZfuZxi{na$)ws@d-&+)Y>J>CRemp8+t~_(UoQ-*x8*2!&Sefpe1h`G&aQ0C{pgT%5;|N6?s2U7FN~<;_(jxnirxheNq&HzF_|IML^wPT!He1UyJ|%+(s=-i7h!}u+l56G|#`gWT>3WMV1O207SNUsCl~kh7=R^@V2MQ zxwZA)$jw0^_-(ir2Cb{;@gE%GV}eftE1IyJ!niry%EEB>y zmn_~yJhFVk*Ky3DTckrvt&kOV??n(yNI0M+c8s-f#xEUg$Sx6%_-_}m$G@;%+A@eN zL&gf_FtISr!)^)=!VuN6J=pLRc1rNfXMip&{WFn5{d#Sw5YAQZ-7AJ%Uax{q?$kvJ>+?3Oj^uD@A zW;2@DscA@9Af;@|LJ4llo^+{0Eow@)3jS<7ladtEqG8%x%AjU2x32BRqa^+}yk0;T zpD8H5*FI8Z!E&ZR!~CtLOgOo0G4MJ*D5Oc2&kfWQzRyA(XXoxaM$Y*J?Lp_i1sP{CCJ# z_4?Bf<$Y<*2I}Cg3nQEC5(pLAIkAl1VH)oYc#%l+DU1Lc>?y@tdanR>N7E`vn1hs1 z*A-VeAb}VL;Wd$TWRT$1RCt&4DbVigczNvd}5NxFcK3Bvc2LPF004 zU9T#AbDVc~l_qc_^vK!Vb7$wgidv``?_H(ltEqf606-5cwi%%?bOwdyni^@$kjxEI z{iqQKD)@)|uoBbAp+DLT3>!DK8wO7p8M2P^-m$ly(F%QGA*yi?)+I6ycY4ZXli@CC zAmY~~yVLOYi0ha&=W?ca@4G^xKW&7GR_d~-PkaPuszU}Gf@lA}zMA#P<|wavfcF5j ztdH-(!$Y*B`)MKwZ9o8l6q1tKrgY7@zGN`lRc=(SRfj_o3#{yx`9Z_bzSA&&6Jkx& z>l&DNtt1nvn34lmhDPw_>zLoKMxYIa{o3q~*-+US?Hd4;k1X6)5MsqwY(w2L^x3V- zx;)~aFaxG1fx;E6E_BwAZaz;V|6)bN2gY0;xEaPpTuoA+K+FcQTJI*9Sww+l~| zC!@qBDy(_F(?dGRA~+QKs@>7J7BL z?B+b>ew48leVYGt)7AF(nI#!N?2a9;F^R&>#9js>O7U&)DIro44-=n0Rry$#S>DiG zGiH}ao!+wwyKA#zvS2~nb*Mtw#lCr!DP+mgQ~Vk_@rEkE>YyY*p8_>Cbug=`5Sk~h z8Z})1yF}lWf9D!U-F%~TBllEQwYFJmR5O}iP_f*~VZ>Dg4(9gF-C7chQ`vvWl|{yK z+!}3ilD|_`LBb_RZEV~dmBo2{=6k%k8UtQ_kMykkK}a(ocy1UKhQ%WQa8bZ-Bvt>FQiFYxgE+2I=+y^?$XJG#5X}$TsRM4f*aN zY}`K?MK{7WxfIQ38YUpbPR9MFD_VdzR)dt3HTUluL}3+RH{~d;^M|24Qbi}ryYM8;NFd;&WLA+b)k zbd!8sgz~y}W}D&s>Ec0FHQx=9d?V4U)`!j!H$~qVW^4<_%d2N+rAI~o^_#={RP~0` z8pa}vd(n)b(hTEqzA3+x!vp~O>=fq%B`s=bKB!FdpXZ+gw8DsCxJqr5Fa$X|p;1=J z7!Li^_Ax+iKMc|A^L0*J`q{7ZxBJ!f_wdKC zv7uwXS8|0@*08tFpUt@wuOnXmb6iEr2xF(o3c4SRU7`;K&sUS>$e$qz{Sf4toTynb zxg4wq9johDNM_~4E4Jx_?PPc|NKV1T54T@C7W!4#XF}wD?f1IR%OrzllJP{?m8eZ8 zgyycGir6_bJS&`mSa*2*Z{)Md-`j9K1A0c2Ps;(cOKZRTJO9e)z*0Y(j=J9FUhe67uIbx|z ztas$OX)PK0o_p__umHlAZtof|(|9dO+6I;nLgJouUvOm4WW4TUF3s8B8K(@xSCU)n zPPKTWmy4tPlK{Re0c7IYq2bOX(vUT7o-0bO8d8sZ9B|4OT?7!Qfs`V0wfd#q6=GDS z(5PG;Y9fNP7=1E$E8zq4LWAwl!}0WY52dYaK))f6$O<$n_wv(%{j=I976F3K<`+qR z8^L1SKyWR+%QxG5^+Cw`U8PH)QBRR1rV>1*ijx2@lkG|dbj!@~og)Z_&iMe)V=LpW zNVp^STXJ?9mhV;efBKG~x$r)v@L0_-Ev!#oc2x9*sj~3OgPThxpYn%@9_S|KHo=5z z4}X}z0P!1w;ny12@(0M4s~DR`^y93%%hR5O2+`FcDb4Qh7##LZ2t_TVfEQqW=;60n zejEh`{Vwhe7H|EsGn=zevIR?o0>~YyJ*<>v|HV`OZ=*)_nM|u*z>0?)rq@6%uIQYNA7`&*B(Au(bj&2Uo?2?0lCk%zSKiviT46L>oCVRYxr~BhX-Q6G4Yis zk%pl+9-d<*;}gryPJEweOHni0ZDy%l9+up%!OLt3O^{CzxU{U79xH3GHZ@iDi39-J z9u``YzUdD4FKMtVq3I8Y-P^Kf?am?-gGxW)q?5pPt>0YzUgA6$Uaj}(cmm#?ZA<{# zMUVZ82o9}@Rp8$PAh%0wf{}1TWm^eMAj49#gKG5~RQ8{XD-T~Pz%w8K>WXYP9nBv% zpa;drAsItt%xZ0gYc~6YF#FfynwD~wacpPNoSh0YHPy{5z{*-^$l6&P#+P{>%k>i_ zcoar3y)jU?>EF2pR`W>u=E(c2wW^*>7}lItNp71 z26lFmhoSrv8?Z>H$eW60GBPqTh{nJc5X_?cOH0942F(J&(J(9CP;iGY&NUQo_H^B& zgb)VcL*h!$sN_i4e^n+~Sn|ZQT7w7q@>;=_whp0Ilprp6qzR~kK*}Nho$j4Dxf$k; zRkAQiFUbv-mv;NL3Qym{bls0o{3K{dpp$lfuMcUWM4mLF!-11Lg2B}7owe9u9__mr z12Tz>yWEk*2Es9XZdnB&7%OTNy1R|{|M_R*#Z23)>ii3yyB{p$#3(S?MR|Zt)6LJcHhEphqfYZQQ5W_f_4CN zOgvHGZ@y21?@|6^0_?L|y}e1vals~Dyr~m{pZifUH0!NU=vjO*6N|WvbL^q`Otia~ z@~bp#Gg*9&H&P_6H9|MFo;A|j_NNjDmLgTXcf>I{-|y8S=E3I;@G{;5h80oR=pO8y zhG48I!Wn*pOEcn>g?E@ZE+g>?1l+biFNktS0jzjEYgMV<{smI>T9Z?$7L7%s8{*~) ztyD@s-8)qdMoyAJVvO=$?wRb!8E?F&qTd1W$H_R^u<@+;WK16y@FghK@Z zNJ}!Iz#;~yju$oRx2sp|aT|xdlAjGTJV-QdQ6b)%+`0a8YY~nT7$@;gA zp;Gq_?{JKp+Eq4dC#IPu$Ams(nt#})!e|~{*pf%Ac$-sG)M#3~doQ=ofyWj(4lWcL zF(-}Tk4ss|=mK~;Owx__qT9mB{68fTn#>bM0r22_!@}cCNomPl_DZlyJ`5OuEVQV}4z9GqU@c!(^mINrt;q;o_Edl(wBPEu@hkJy< z_@vk!@Z$ZNN@%3L`5p`4oBMakD_tHzZlz--i4g@6TOP_!Xec3Q>x4c>2wgFFW;#HN zrA{N!sc*0<2`t`Gt87~<@R~^;Xm~eu-8+1IM*rmeMrv#Xi*UC7O2g<3&HjKvWU8o@ z%e}ih>XE-C6f)oS8@|f|MXnT7`ScclEI^6)-@nkdIzgWfYTjJd(^_{28DNtekW~H>tndHj*d+Xqo0k@OTa}az_yUT-D^o$8afC5R? zL^^mW(*ey^$uXv;itnGPjd9gp_pe8b$d05)071F}j0hs9*-}j?wY&+v*`B#_Wy$60 z`t@JvFVCdzE3$^Uh}P-1zMdNLrhb7d*I!*b`SpnAT@RPjQ8pX3rYal`cnJ(&j?0yF)d{e_jo`|s;_ zrdjVRpQ_B_$~8DC5;oW$T|^>fH@sHTyrZqqzE{qPMJ4TVOJwsQkoKqGSB|O-(h4uL zhCF{e$MSDNo0t3tnvB1u^fe<0M)zK&+D0wp@dB>EC{t|D!!Mp%kv;k9Ab9Ao=;sj* zK=BEa8Cy};iGk;~GH5z(#w;r$Ryg@dWw2QmH+hXw3yRMfYG^J9X@n6-&mvc;?+UKI zz$<^F2Cczzqno4EzaKrbb1ap7`EklPR;aeNmyRVe`gu)gf6Z+~ncJTTib>-qCJ;mz zIQR@x{Hy=JNipXHJc5v26?GaiqZLpDOkEWxGs8@gOAFSR=M?8oea7Oql2(1HNnU!Y zcm=%0b-r&WPeBuZh1W5uW`wg0MDCKx@6%O3@UVO?#kQ#M=+@(mS}r}_y*O!%?fPG* zjv5pCvbIU{yI|^KrU5Ak(g7+SVJ(;;S3HFO91W0TSZpi+A%H*xP`Q)q)NgICu;MBM z@wqfR`CQ@F0K7T7N3-SnHo`1C2KpWl_P9Y_qmy6c3ue7;wQiYbD;T%axu(AmUC(r_ z)bYA-3;%&c{TE`jo@xov@8N<2xY)qcOP@MU*g!YfzQ=!0xBLcpzRZy5Ax8+}znHrJ zPByNUs>uf*a$O|j-H?3p-qpDjzYsJ?NeT}%x<^hYQMiZ+p+6F>rJD2h#M|cc!ErxF zI0MHua)_JmA5Ym4Rb&0gyFPzhiY$ zHqxjIAUc{~b4V`+AqXhS!g$4CcC=E7SnC()D#q@Ic_USOk+R~w5}ezKiu28G85rfI z8}mxs#mZ}{y-d@0$TU4*1IOqvN|Ww55do&ZE)>$fsM8gFg_Njx{iZAHlGVi0{ZH{T zi?hJ1;J^gAhW4nK>$e#IpiyKRLs`I_(!U7h3JSVDq^*kRS+?39p6}UM;-(9H+pIiz zcwMCaTfRT>d00zc;=lH$Xz^0bQbV=3yTSW72YQ~836AUh?z}V4h$c~s)oYXC60C@@ zmnMe@X<8bIL1?f|EdQQ5J&$B|HXe(^r+0Y}0Sn@d_@95ArdN3U7atDFh|}Rj^yiz2 zu}%XPLwlqtajsa5)bl^+Og=^=fjx9U>I)*3`i|q0<&rCh9lZf5tvkEf?4>^zMbGN! zS$!w;_Dj;jv#@QJHBFJ4FDfKCsitCNR%6G7My%@2z<-B#Js7f2^6*XfMbNTSLHs&8 z2$it4lzkNzhfkpao15qtVKYN{3q@Bs@ja`WeD>2Gjonrkj0OTy+S zNH*H8j{S^V+q~n~4jYtb(yyKQ-J(IL{jTI<8l}wed&seK5P)0gLI#ZSp{tfY&Mm|Wk zJdHQsHZ-Vd#hbV!AO2y+r)Clgt}XxMB!GU%vjIT$@slg;tDBx(+W!#rlD%3Av1Bl1 zM;;zy*~)`I-UJY6u!(k)TJ`JID@eTFGipBbGq3ltFLpYiYyA5{pwVHG`&BKiQnFgV z(a_?)vnK1ok4FjIg|tz=Uq3Sc;LI;RA8odi=S;Fy056^HgkIn@y{A(F;9Pe~w#T?i zKp%}+d*6D4F~SsSA(M|Gwj?4Yf?s_iKx$-3r!Y&_m(p09X@W&Na&c> zCZNQRCL;dEO`=t0TlXcQZ8&vk*SX`wFZ8X;)O$yfs2_*E4MwA}K2JKihs8p{xw+Fh z&wzyT*BRl^9xpgmx?bm9{PNTPN8VD${uF*=i1biKun2A&E^}Hn*~cK#rbw^@+@$R3 z+Ho)c8>28l)3QjE>br7FmT;A~M~lvj+FIcLa@V0dtL{kyPXk*44!R`kAsEsHBBO;G z;uJ6Xvt^|ktAA_22U|hAtsR!uIQJ1T>sI`Wlw4jD$w>Y_D}S^7%Wgc`^iOlA+%dXE z@atu*MB`c-Ukf@4K&R<;f*8>{jX}i7600=mU20R?AW~?bhviZVGh=9$?4hj3y+H6hMC-_Q z=lBD+$=X7=ZKP+hQKC9s#@pOEXz!ZsxzF4jc=-e5q>QA|1?WwyU}-WQM= z+KZDbyRYGB$*%8H`cZ_RvJ2FM;We@7*qUr6qtlLz(89TWHrw))foqi=-$|PU_SR@sr@qGxlR0@{mt$3%-6mg6wjgbz?f0-CqX2$#=U)U@`c_121<0SOkd=Urm4q|Aw-Y zOQis#Kp>A899hNhL0XB~wvW)evA3S@CGsW3~2 z-bx2D@?4n8bDgEp%9-{XUNvf~(;J%NeC(Xozd=i;&#dqa0a_~h2fdoneUULP2exrhCyCm}D)kDA_X%an2G$g|qL%3sZ} z)s{E1C+KV7U7DW*d=!~-FSNl~IHd&PCGZr3Aw+?!RCwSz9}%+W4ZD&QY~u5`GKc8Y zNO5_|;~rs1jYB{357ScQtA81cVlUbs6mwL36YQV@EXErJU?Hgy?JN*GI@ z!LZ|L3W5_NSS&$+WDAoHC!Ut-5SD}!Nz$ODy!E9C^#~lB?oO`Ku;E$CiPwNfO%U4*Vl8a5V0-*Wz?*D~uxH#)50`OUV+fP~RzMTRPl#WPTmhYYzC zL-F~2Gdq(7dPFz&Npu=x{%W0_6HSi?)s5Yx$pvj%c~rbKef65|hq{wW&?cA42ti&9 z9@#>)fnaho*RaA>{m)s3xmX~U$k$z13nj4nM%0VMsK*iA6TE~Phd8@v<%Q{r*Z!QF zJGA20J=^6{`{sFsk<>ICH}uBjGx|CYc-}S=jO`t)i64F?7OO5U=k{|0yx;*muya@9 z`DN%z?!73M7JQ#JreG!+7sj8Qu?TYajfmk@5$lO~EbCexA8BGzv{K5;T)G2xbg0@a9aCc~#tG`zPYyJy z1CHzC=2*gmKii+;G8|hU$y<|B#yXY2`J+A>G#7D!;GOS{RryzPho6}&;ywH)z7mWD zsCxqWwXmkuw8C&wZmAgd83#X8BHARI?DkfOszJn^8_ddI-U~o~TYux^$n-O%D5AA` znBm?k@&>MbCx~?~-$kK_MO1P2L>3*czPEvTTUvZt5_0x?uyCo;`gqm~ysUj->mqK^ zBJ^anh2q_1iRZJ$gPIyFgbzPopoS`q5I`WoCY9G~)vx_n{+920INBQkxDE0SM&DuZ z2-8>@^U+0mE;pXbI~)&|!AEqe4f!tb4-~I8fh&SW3qzK1-rT*&^(@B&5hmL0%dVwr zBF2~o-8(Akhh({#&J~< z5ltyYDG5EzjayKe=RJW;=Po0kU24(ok0<@>vppMWdE!sbRYWC5!iktg1?MURl*V)m zBW1B1JWW^9ONk{N)tv4)XbmT)nc6Af%UY@oP z?$iK3AnCYfr(M89_OEA?w6IDBrc3y-Ji_1OGkUTnM zMq;<&s_i@RJ?tl=RR@cE(+(__j!?rzM?^knVV5eWExgou0Ry;3<~yU+ zqI2KG(i0D1Mad-FL=8Ez$KYkUrlj?Sjmjfy9hEA z>}~fyl|GZZ1ppKfq8CgZr+G`oa}E=$kJT*h6cIc z{;-e)bo}Dhd!F{rgB}LV(=t^~Z&RY@hMa%P=8!v8cTPv?^rn0Vt|Ypsl0|gK;m0L} z@MhH{Ve#T0z#L`-v;H4uBbr*&8t{|VU#wMf9ddQL+^kV(7dj-ei_Zn+<6|dmBU4`N z1}u#lvL(^Ec)yWbmb9yQ-TuS%gAT_%wu_pTL`T3V`+d0a)-9d{K)chNp6R9pso zs1@0^Xj2612Q`hyqGo~V?`8Z;o@$)*N|j62q-gNp>=Rt zwM0aN-`@ICdF_P5fdoh^B2&4xlT!~(m)GWBvNWC%2p5$Gx#A__h#|j&b;SUC^&OltUMKkBF#Pz=N> zfm#X0D^6e!V^|tDiPE*T-^=4!mH6Gz@#BHi9xNqv2;3Qq6Xb0 zAk|BzuFom=Xss0n^_WR3@jq#gTJXZ4rvZ+^Rv^&js16@8ncNQTvl>cQW( zI+#1EJd8vub`!j-fW=|SmQ0lRH)N($d&?MD6lY8=(HK}+by}%_%uT7=lS>aKqgzkx z?DcyW;gjBBYtvF1IlD*F+(bTUqLv=)k=V2>8-}NMTk^q$y<72~D^@qHslr!7w zZtZh^mgOxrElygj4&RcWx90-4z8+F#^5gq<6rL*NW_^qlxn2WBq?By=v^K3hJvS&w zuM-nMpaxPG@P(=KZpj}0gv3|p`m7WYXx$KhGKy#B8gxnhPG&|bzMH?Vk`G1(57VOZ zSgc$wMXbn67BpSbGlR8F%l5TkzK%U_u`}5(JKt#hwhdjDaSmSpb4|A*v2abeiSAy| zCB@fBL1IRckygsC+5Iop1U$gWTzorclSqZ3qA|vyD7-MYNtO_t?7>P`B+)#EMP82v z17o1NN}|M~Bt>mQF|*;%^QK>dNi=_2{bcPK{rA6i7k41#x-(sZ3+> zzJC{&_u9d@TTgTI7^+S0-64yRagqP6YWllpZ#rSS-|&W?uVsI%2`5kmV5fvj{g+38 zaa_Gh{rax`CgUdUXxFF}^0P+ou&y!F{boKxT&W|(PSq!kn`fWXho))9G>xQ4%v(Rf zmBb~%=~$z14Zik#GNJ@W|BMMfZT3rRE#GEJ6S8FX@3q+cB6!(lb}z{8D180R%BR7U z{_(r>LG4?agBMS1I8H%^ZUPi8&Xgsw_`VV?eM?Be7^h7{0;f}wVXzysw{#;$utW~T zS0nr-_5X;oOZYRmCkW+_xj(%0t~U_x zBwt3+E@2-;^r`o7orW&rad^=3*mns)QbN{5G_=QFJJN~j_7I_!{h3*;Li2xAaDNoe zb|sc2x9I= zq1b-1lh=msz-RDz4m?>NQAxlYoZOZx#Y2uiJ>v&WAL23{XbH)b44Y~-tyaJ7xqOuG z+BU|~A)jM4aD_as$d{$}O^V3!)FwY#an!@E+&KrCRo{^sLX~{|)x2r8dxt$M(o|yJ zlDt5J)$1A$jTXc1CmS~0pNCze8mC|>d1QoUZ)?X1#mrcriQ~|#yTgy(n)Ew-E(K4^ zC01L1_x!Xyqb0a?v1;LhKjHu~R^rIgy)dH%FZj>3+gkmgD2mq6GBhB@y4ejEZGd7|1T=thS+dP-^>U`dg(I9 zTLD~&o~z{oEA#EqK++w9;iOuR#GXeE0mVZ8M+Ek;04WpQgg(uFj&^>S&bmFNCjnL}ngPbJX(ai#kVFkbrsOY;I}M32m)xp3l z;+ULsg-HtjJb7wtj1p3I_|XfWw^)*!7PPpZTU5W<8$N%LqEe0P$#gJR+U4A|Ft&W@ zE2ckC3YKiLUBa-%p`Qp|y%Vz+>tK?%ef)m?~9IQ8SqY zIltZ%qMW_9OOPBuW21rCQvSq;p_O_yN} zAS4k|g=6k_cpz-JC&pZv1P~ap)HL1rqKvAP34g3Ebk?N;hC=P+?=R}(>b_^MdN_Mt zDKJ2U8>?l)Fh#8aUNA+!kAZX+RvGaNH@I%%Y!{0XE-jmhCKCT7x%W54_Oo8xth>ri zasQmVfBF06Fct+x1CZnDeG7norgxHsSO5|;t9o5Hhios_|>w}`FD3*ph0|Gp-cu4DZuaGsx_H9lwc&pVeAnU?vdS=^<~#H6pYZA z{gUNn;xQiUieOEyNCLqzCnX~Do?B0a+gsEg*AjwIcw6?5=bXhy%XA^~pcki?cRiE2ZI5v&`x{k|`z z>viipi-#DmW`vN8P(YOj^TxDL_ihTlC$6>@GtIFy{8X=ZdoJ{k4A&jTmCnY)cQ2md z2mc-xA=iucG9yhw8!w7M@DJzb2Qz|#6euk8bq~2kj>KLkDt?IOqk|};!m|J|W&y{;FJsh>ks{Bj5Kt#A#aICWlq~m?Kii#+h@dK8 zh=U2=&(aC)1`~BL0f~b z?@*zt%E?aEZEcTwFq?3{ZM1!DCl2v<0opIEuCApV(}$vOJ`V14lzg54e5^)!Q{{$~|^CxCU;Md9v02s&z zLQqKns)0tG-Q{}@%vpF%d$+uq3d%uF!OE)?!^A2Y7EG_IDQb`MAx4jwP7meTubjK3 z7GY-VpMJTjr>6zou!kP`#-W@G4r*YSGNxRc92h;0@{VQb38y1ErD`PX&xN2y=F6AU z&sKE~VgIcc|1AMS=y;y+IvD!)aA!pc9b+IYRhI(HG}S(`NHXRa^7IAbNKWbj*gYQQ zTGj4_rCKh2hm%+SKCY~ML0%Nk=r9vL6@5A$7^kvdPVE@DKGYULlvqD&pD6VgJmG!a zWg;uy1#d9s6;B~l;Ft4_VRy?CIJK@ASty`tA6Rn z@-K$Xz=o|%08utN`$Xy+CX8pJGbjMF+!KzP=7(YKVlTNT>9@2p1k=6CML&>YQu$Bdd61OL+RjH9g}JMgSAyLgWAHdc6IP zrQ{kIAPFp)`ecwIO<6w1IskbJx)x~Nm`L=J4gfWJA7pKMn=+65j_}~^GTp<9EV95- z#V?-=T}nk4K4vOG#o^r$HMHB(q&Xsl0=KVq@0(&pW^2bOIoS`1_jv}dZ`V&6a1&PQ zeEPh8P7__W*mxR>{~gpW<=^fB@b{{ZN#E?GLxv##3HxLKb!xBDwe{NNwVX}-l=O*k z12Hu`sv|L<2Ivc}T5!ZUq{ED4x7=H=-MAlA%K!etdg+c-6_@X-dM_r`X&&GjIVKHx zAb=a@R*iE`%Jm83W?$dflJ8vHUP^1fl=Q;|P`x-8Cj!duUv2=D4(8$Cx=NDOlDwXv zC*xZ#kMUPgdjQ^Jc$FlO<>JmoMLX)lCjXFF_E=j+Qi+Dcm4r0m5pm$NFTwf|DX$(t zFFsqum^!7GHwhVaqf=a}#1;mS-0wc=MRE%lK54p9eRUQ0u{_DYSY3@LogP z*GXh<00HTkr1!sO#JkwUeK5CO>5x>?){p@ zF{=?BhSXjVDC3g~P3OJ==~&aCv)1E@E3BI-?=K1kam!Y!?0Q6Jo+Q-bQ}$s$b}l?V z;hTp89YKr(jZ}e-U?FC5ySUD!j42y`{ZLwHox$9+FRs*ny|TSdPps14%MeCn)LItR zwX!GWn8x@v*OAZD7I(L#IIvlh)QQd76PS*zM>)EkU6^=?nS2ave#@1p5Yo?L+p;&5 zw{ZLIY5L@~$4k3(*4U{A4Qi8!5{tsLI3EapT>H=;dD1 z07UACTbvD2Zr5#FR$S5H4-~%-L)sTvNeomb@wKiS4~r z5qZ)2a%=ArYF6m6RTAZ@j~6mveTW-*wmS*(ArSD9ZOE+buFGed>Oytmw@N&>(KL}; znXlsapV?iwR?Az>6wj|Sev4YMpP`Hh?s-*5KJZtkp9>!$@RXjSbR7TO_;LUjmy4Hh z0Cvm$WOE0MDGH`6#gEM^MBKqu`TT3qSTU`1vkv(-Bu8!D34i&|>#E)#t%~;TOn7%8 z4ui?^q!G;=r;6FhGZnVkzv4jtt>JxO-NW4Eob+OFB>SFa_pp)gB{$W*(7zJ{Esydx z*3EvOT@e5;8@uo0&4=1({a?>DzR<0n! zl^j`#P)M4)WXYmeveZLy;%}Uk3fp~~E{2(Q?daItIz{1B7UDs}GVZ45>5v{( zw)Y|Y3Uq?T)_1%|WgK2z<$jl>XR;%0-1E#KwX6skP)0KmN;d`H>i0}`7(XKb1Abdn zm;fT)s@4cVlSs03;L&JVB}UB%oL^5bV>A&tCDa`ZDx=w{eL$?F|5koZLV*Uo@RE~V z+w}#_YlE`=@}F|-dCf}=Uwy+>fcsqEhub=ztUt@vva27DQNQHlxMj}ta@Y9-v(l_X z<_nQ*)&rFS2P}a4Z#D)EPxa|ms^8vT(Z;!qb()+5T;!SDku0<%KhdHpv>|9JBooD{$3t+mBqkt zA~8lmfj;ztj>F;Wth-Yf-|?VNrR+?=hc6>0&q`J@s}{lY?4w7XgZtMvKJqT&Vc1R( z-fNFPd?wc7470YU++?VtS2YD*o0!DD{4u;5qm@)_Ml<4LY;=>!*7H|awqc-&rZMuc zYYr~Dimd)j%%si|rlF03EABhIPUe!)%x%V&&M8kVdNR6ZJGgNcmq3|m>fnBE&70U*10I4e({(j@$g0T)`4-CY4qa;0-Yy03NC8~&@ijZ< z&S?ASFh^ouLIS1$(nUd)hO5CPm$)l!FS!_CeUM=RgdnR7HcHO)r(#uv1!ds&p) z!4y2eZEd3dtVXL(`_F?&4V;u*Ae@%USi!mWT=C9(0UJqECX*>A1#8J04Fwzq+`GHd zWW$YlD1*wj#0ShIP6es$o-?bg`X6a@XYNRIoHhLZJ^AlK0saIr$)5kV8-Gjq=>cAT zgUmNUohn~ED@}zUmp&Iq=hRz;@y0Nj-{!lJdL8gIVzpLXCBZMK%rHC1+jch=^*X@3C6OKTU1u_}3hIO#d7Mo1XMWgF!J*2@MTt>a7w4 zxFeQ`XAA=2a<~Z}*n6o+EtI69wy3o6K;9dshsR%gCZ2ULHh=dL0M)5xHS2_9p@Py` z146n%RL1XAt_*(X;i0|qdNF=ra<3tRT;pC9cNgY}WKXTP$Ls!z{{Amfgz#V_;T&d1 z?BVBwgu*l#v#eFWVzB&yZ7Z--PSsM|W0_ZTLr~lGk4ABL?+*k=ptAjykm(P(Hx5Uj`a2<+TJP}qN_7|Vl@{JUb`_z@)d`rc91YOl*5u0UnnAaN5_Z0dcVG_V!3P6pbYFfTIHVhSTw%A2uDBIO+W?;j5>DMdy`M0c}lHLEVwjAvAm ztY++MkaY{Am!%swR58X9Ab2u}-CzsF+q>xe!o_3Qi-n@`U3uaGktPp{HknL-4*uWW zBMN}#{2RXSG+EYUtWzuGYqjum{t%a=RRZ*CAOX@TyBpVIW5S#L{td19YAof1+$38k zzG0b|Oda5jq|wG1U{g)3_&byVK>V(5@kg)QVYqXZy8R&sjRR_8IZM4!$3N8DGt;n< z#Qr?=y)ju`npJ!%=V6RAa6Jg>{(<){^tKR3%D{$9rqlIfz`8IhZiYr_wZxk|bMS_? z8$+kYo#8uCzePl8yqe+@%it%!Oa8slm`@C2F}eSIYir=*UC3i*k%?a%<{?qErJiO} zmv=8;{0-~}2pR-$B9w}WRQJYJ1}XbLl(bQoEWy0V76^rvhX?2Kxr2E`z1w<11ST+I zQ;?17_3QP^>sgzD9rdkV@H<19998an_e51uY^b9_&WX4UByzx{LrZcR=N`+_BA@Q; zPwj2Eukq(L*F<-+9I<1tsvo>#>5j#ZlyJR^exMsK1K`mITS|2i001a5!7xq`;>zbP zG)_IyH@w^-MhgKxjCM&{s11|ZxuwVppNi&zzug6p_@((t7RJ3CtYf%T3@ywsYyKc612p=UEoQbyE1i00~HeZ3j9}fFZ5CaZyN*` zC!%V~2>%TM$Vm`2r$o4}Mp5X(1(XHlq(2N0lOauL%^X#qb3)yunEnHS0Z1A6Mv!3~ z>loTv*dig^RMY|0Fu_%@gI{}@h5sJALxbm>VO*$23e_M0}U3w z3;?47!boTO2nzsL!nRjC6-h(_z5cz>ZLrIGbs#I7By93A^u9n5@rp}^fH12x&=k=U z?ah1zkjV305ke3nUs&x0)H6bcg#xxJy=e|`-4~JYvgfcw-H97bykZ_xOW&`1o|A3q z3KU9jTX%yKf6F8xIP{7sg%C&i-)q?P9b3Fh`|-n-n!+*vTVJI{;z3wRT5e%;>nsu? z$hmmI+w7ZgIP$d>Iu$jM?#77j8bl|N{J++|^Q)=u3HKx+5FkM4p&F`zmlAprB=nB- zuF|C!0TmPpJ@no|s&tg9ASxYcBGOTm4vK(SP%Myp;_t3?|ABkHfXfeicxLwO+0T@X z_2kJc!Fe8)dUX_*M;!G&+Dx5l(OFpIO6)PZ#&>R>h=`-RYxx1U*8_=1jQ^6B792US z|4iD0UG7phnz`vO;F|lhkSPB~n-AOO0ul5u&RzNlW`e&MiA3GEr03+m3W`QL&Alnr z2S7Lgr_jAz#8mibK)jC;q$SNp42!4Ne3CaJBoGq$POjT%DY$g&L8Mh#S-OaY)*~cl zhR-z?9qOR3O*Q9Zii)FN3z4iEIS!4xpsT(4iD4gqb$YiEEgYw+yGr_&FgUA5UhHfy z--Wy#07B~DciIQejTKGBbzmVL$VCDC;AJjqE9e&fCNnqgwE)gbled;pEXI?r`ah*( zQJwaUAJ)W%x6AE{7n^MvdU$ABR@7M^moyU0Jb#QjsA1%uIuX$Eb@|0pndfy}y~?*t zEH&$%M+EeQwd@OZM3O!*IfXNpl7%20o7n)=2o!_9!9c2>1)Gzutc|TAr!&-nm-(*0zxwqbtYAs+vnKg6C}S-Rc5Ev?{z{HT(u1!zkbZTiWe($3RM(aH=xkcAf23gY zc2tR@8(R4Vw{nkqm9MU6lZz6e{x%Ywd~#@<%{(JT*ug4}@bS)Ny$0pr*9*TF`A-ld zOVG^j{ulmac6xLOg{mIdsN&U#sZ@uUG2WRS=mX$UoKh_+05MnH=jY*n#(%dT=52m0 z@h+ldU@5JR<l3c`&L~d{*APXnmv=^p{^g z!bXcxj^vx%dzOCOTtr^I7AZOk-~nKbdcJ(JZ%mLe1&KVDg_|aWKm$6)Mz9I@pkj{o zeCRV(l`wfN*I5kPz?$&UThVDL9ZNm9O4a^v8U4#bhhI!~zb3LMFhLkZJZ1Tx3(|xh zS8&a^7ziMrI-%Qjs$UUw>cxf^ev;1g9s^ytgTM>Skt9*9S=g0Nc>;U;H;hA8I)mJksOY@If<4I_g_jR0j0^Pz@(y7ne+#31Cj7Mdp90#*y()PY1 zk?kC;_m3JG|5K4CHUFYT<|qgaBqbW1_`%T>ba4zZ^<$AtI`OmPP~DbQ$%!{67InH&IlV z>$KGaTLeF)I6bbV-19w_+1$!eVSFX`#h}+Gn7_;Q;toR!LOUf*@#)}m;m@QWm-&sv z0Xm03+pa^=`PF6fUeFP|80{#H24J8fxRKKsvL(O)6n0guc_(!}o~!;e`!Uar7IAM% z5nTJAc>~pD8z6@{TU0@8EiWr^-j6R;%ZYCBidv&jF!z|b5xdhshz`?3(Y`ySoPjYY z$3Oujr^odH7x(11*Eq2+Jl%VKns~ggzEjK{^tYo%=3;M&Z26@}PU<9*>AfKeXuA4H zda3z8Jw+6|S8t&pC;|n`8dcb~mu~m^I>#c%7Xywrh{?6e=1kfx#v3_1Kbs|c4I_VE z7;l=AGa8(U?imu?@<1otU+`R&X9cQI{@*%z>zelVWE*)aF*jn2DlSCdDPJW0l6^uw z`p7DX0KhPyw}UKUQesbK<>gWo0_6At|M>($8t_hYA1w1nai0%;sxfrgq3pEY1NOWOu7FeIY4)yWri*W!3W{b&u{^ur-yrsy;Msn6eQv}?>IZgI|7A-{9ux! zqoL=*gy5rWJkh`BGi>Qcp}F7l_5-7m*1Tz{nc}P}wgbdKH1G5=myH%$qo9{o zg-d<&+E>$PaZRH_X;inLq&{n9vZY&g4k9)*@sxD-W_kFCfSE@`=i(UtiSX?9=PFPJ z0K!1n>~0Od?i4<)J^O$R0(BHU_o`~M2le_f_xa9e>MBF>SS&(jdB`%Xx!`hp_w}1} ztc%V1u3y8|2+Xvdh69HV(hvr}U=E+mk`IFTKCc*R0@7+MOGOUv$`WtdxoJ9-#G;G! z!WDD47R-3M{MS1wgYhH)Cu=&8WSO8NP@ExEgqDP$<9uTylcs^ej1S>{Ej5*%-9=nv! zXt+S^N1VM#hK2pucb){y?Ne_w#dGP0U`Mg3o4KIh??^D?efER-FsWfS7On*VEc6?X zE%z@@c%K(57dH6k7=g6%Rn4XkpEf9SYvo?5HW})vBdV(JhbLu?>%cj@nmDb;dAV4m zR_^-CjAfby=5kWB(j)#RmGKAuNv4HSRlSoKkA! zvlFSdkZ_-uwZYBHF1McF>X$8DP7#+CK)b8txx?TZ^a7VXD!icc)cHDi!AW%ih{R{Z zMCZq63;Uwol;#l=4<>j++YSk&vpCVfOEV{WOfT*hjYdvnP^p1YTSWd<_n`k>s1v0C zRMaH-CQV7mR;5*X;E}pvQvuGYc>Odb}%)MaO7U$v`sFsH{>GqnVr}n$>j-=`W;)02B(MUbGHnqzB=V z7xOK?)M^IZ67)C^AC*wAJawN%PttuwE5Sbhp^sYsbmATz_Y819@j>A12{>5xaH4@ctpJ7sj|{&bL} zrTd)quAOQf#fX)OD-6L-BEA6^{0VEmhE#TXpGn)y#W6fQZG2T6 zF=cJ)iiF|8SC#&rbsuo&VjcZ@kN%D~lkCu(O>aq|A7^A`V2VyWw_c8b5}hq%T(H&7 zCtD9dKrT~XI#4xUKP|Y{3C_02z(LIbn8J}zhIcaLY8;d!Y=c_p&#ibpO3}vzBFif8 z&Rgoyy1>DZ_eNn~2r65t_`rmflTVF7>ux)mAkDIzeLQ-`A%9)ZbFyjUU-aeW$Z^g~mWeR1LT z%GPhW_Yo09>g1Q3#X5`md2!B$ewtA zF?G?Iu#EDskj}YK@&1xs`|zj*e#(j1X&k0trkUe{vCffvVMMCFa7eYXIZGn_=U@qY z4Q_7m`(c0O2^L@iRD7D`Whn&;j96UN^^0em<7|IfLR~Ut?Ox+lc(`4R^w9$826K&H z5=n1=uHb8};}dS2lT*h>7r$&Et_f9iW{mo5RGYb3>_M~dtlm-eW)S2Xa2E2qc!7mN zeeU!2M*d(5aQA{5Y5Pfe+#(jEtTqSZq>lszIBDMl`;x$8RbK{d%m=dpgzQ9GB@=Js z^<~V5P_Py+uSS*!P5@qq6|@W2GUgri1A{uijBGz9MqL#$;{IEj)wCa7m8QUFSxkUO z&6=c$7&}m2$Oy4ndX*>RUfiV!xI8Mg3=|ce(a|HQIi#B1VfuOY#)Rj=k0+MFS-#qC zwt5?a=hP2QrV{7T+gTq`{aOL1?u))Hm`oVy)K6Kd-wSdbE=Xl5Ma_Ih25sKOryO8{ z_pj5nc_Mi;X$tFJ*XUCQ;Nzk;5zK_eQO=WcVXap#-@ocI)l^zu<&JF66{8q>I&kIahP85=n zggaQW%lo6~QIunffw%%RH`gG2LZ)yAsnu-#aZUhb`$ zU%xHNU3NLOByl@tRyEwLlzoVFxpdXe;;nSFPK7SJa9Wzix8*4h{%T5=Ub)D+Dl@SO zW2Kf(=OInm)1X6LcIcTd>5LI0s75+V=69i3YTXuOf!rqmb1R5V>{F&B=#&@ocH9Rx z?vC-K$3|H~v%w92ZPwFd1N@A)n?FZ~x4&TG|5|b>!Sejz&4`p|S>xlOI*XPi@cdqlpi# z+j$`L+$mA15?yUNDKuJo3W%CB(dk>F%;iav>P-8=N@mY_rHTA{laEPQc7+YadJt%np+{(?wifn&iJxI6XKycYvOg{ z!<+HFb>G$=o_@L%2`>CFSv2_{Q^O7UM@CT)(tI1iI--y3-@)q!SXOs!i=cyk1!*; zLofya-dn;Rc5nNaE+_mZ=~rZS;ldKN-|tY_b`l{mtfXPL?_qnVQ197GoGBRV^gS57 zVf{^)8)w#HAeF)mq-Rs01aA(iM~Qm-JHy@5Lb&HzBj$fN-mIR#C)%|@Wz@cENu5n! zm&Q*(<~#p_uc##J`VTDL)0#t7!d*^gmlm!KMk`wuTa8C8l^hJexcV`S>dJye`&Jj% z4c&v&Ix_fYdqS0+G5>fPZW^*BPyp#Awg1ZM>T^CsG(Yog60=)Ic1T0Mp(JFavYcO+ zU)LT~)Hk9O3*x96_LJ&%#^O5(DT@(qt2r`FM$sej2}8L2;1bB(izd%9Z_&}>ImL9D<)Nqk<~&vF2}q8=P`*Q zAe&=*(E?d>bb2!vXg@{0bIuy@C}O@WTeMY>tI8DNQps|u-oK#v>O>f>0jVBMW4ncj z?F%KI6WI)^)-{T^8ep_<+yzH+bWWsKR$P)zU%qd7hx9i+Xkx>Rybkz%+Omp{hG0OV zo@UJPekD%AREF#q5x}dyhZn%kpGs``F5^q%CU~Y1O9e!7&MA<>RUHO#+_}*iMF`T_ z*?Dat5pED_m9f|JWh|qWDzlH42G@7h9H#3z)5YPP-Jm|n!Gl5`~LSfNb5 zZZDEPPV_-$W2GfXKz2wZ+z*;9B2}HjsiQr5L4|y_`WR1u0wNr{_!nA?>to3S@g8cl zIz{SO;&e>TFxaCPLqM=%MRPmu6ebM@u(kVS{_>Z$fX4k4qoB~nJLC8vlqI)sqWWP1 z8Xv=Hq`qB808Z-KyT4HK^hZ_qxLe+621@e@R=S*X*RW59umjw;P&K@l+1m`|~5E(S=EuEwrI9QHpfd<9AvZ zVfbYCoqh=&iosqJSUv~JxqNtm2n9=s&EAzEL%r8y6XNj-gf@+F7s}xkQSQjpsCc8y z7fuCwmglgau4ZnE&@<#KW7e%b4Vb*9%J<+19Dh}ZL=7WVoJLWJv)KG#Cx=vv?ye*$ z=E~j3f~3Kv7xy$MI%X%1Ag|Nspx4lMUt^HkBtUEGm8A5 zGfj7ER&Dww2=;D(4YleW$?msC(oIc0>lNkCSm+)DeUK_Zv@?fG#nuS&EO7Erj~+sPEQF z+~syJ)iirD$DLKA4K{6jsD!DAshzY%f+9t_gw7KH6m(6Bb+mYg-pO^tLr>3J2KF*l zB}B#E?&0|laSihnS1yNl-21y!&doC(+T$LF4X-Q&(m0n?e06AC`1hClZT8=9fA{gU zK_%Z5pLLagxjHz}c8P87fl9dtuaFUw|Kx{b-qG&@1@r@}qy@_0-uiH^V=E5=00F=Q zChAaYcKXMELI@>_z-7BJFN~=fmKUjTdFU~ZTTx-$%^RLyV%%=+OfPbiLkkWd72OEZ zpZ~3YX1x~Lq(;&845Ogt2AB$W+Fe&&8Vum+;=?HYDgDdOHGE~{>a6N1tp|Lqhjil% zM&qzy~ZftL`H0^43)sc>mlvZBf`c1 zO2GK{iyO3u3bD*l;o+B{4KkH@iW`L*T^L-KFdL^N!aI(C(XHLqpxaZ(h?cMYAgXdX zBk%nO7i;H6{|lvKZ&L4n==~n~gH0nByg8q(DvQRoL&3irARj1Tj0wpYZB%OhX21_& z*#+;a9c7}Uw(Qbwb&08vqEfGHSiWcfz~uMS2+f^>*c@cp03(Ho3qutID zb43Oir<^Uy=i9N;HX2S48S{fC6w6ND(V*eFMUgZ3OCi)Do%FHbn=!wIH^MvOeSLF; zkEBNHv*WP*klaw$R6~+$j01QF0TacSN)0#(u)fTiohyUPWYc~DO=-9@ z%)}mXos%sj|E-NXimU1{)qIaQIp2t#eKv!#n3&fzLInx^*C*Pvk#^a0$zTC;&q{_y zUhssH#$&;?$wrbyy%BNiBE7iUwcxqh%biCL+1#EAxo}XW56p30`2P0sTe1YdFXn>W z3WiMT)2lGzM%qx!to(BIPQkcL1fT37_^*b-;d;hKvKwI{q{luapTsUStk*!`LLOPV z5esNI^ismR-=r#=7?4W;a9*C26zp~8p zic|kO$^V)!PMQ_2_DkE$E7=cw^iz#=$VwK7^y6h89`qCg7*>Z|tq~1vE);djB|TYG z1`7ivoE~ujPRp_~x8U;?Q*PZWP{8(|;pOsYT`wK;9$OY-O%eon#qJoypfk>^bACr7 z1F~s_tD$kU+$!efu+2ykNv>gSbkP7=XLBuR!T9^!WqZ1F7Y9=1vH;!RlFvjhss1}= z{(QbZNj8@?U3F*EeFG1AN@>2}+85NVWDvl<{Eki~V=yNBnFkha-J3&5;IcR0H|a1s z8}G2%c>q=7MkVzO_Vlu`yq zS44GjRIvm6Gl%funuin^)mXIA)1szwC;6!aD;uKCD=B*($|b6G;TF$ z$)P3$ z(0?kK4Kk=8kP*3>B*sYw0S?KKZNJd`k#2n@2kfVP)-+sz5$({M9_vdhsDAL>Gehiw zOVoHyAouGl>pfyoIs)`XL2sUSZiRbzzji*A0ZPWCq7S`dWdhwbry0YO?!)-6X5N>9 z3%kFv#TI+zT+mG?{iza<)%U~Qnw81@fu{-+vxxlBezmW~>V0$M4uV`OK=PwaH9`U> zkXZFgtp%D+C@clhmCLzEWB7oP)~JR3wzdZ4mN+!lj1lbUZR{n=7hKBo=L8%D$;&z_($D0;HonM4vFL6Ykruz2Ad5NdUx7;o@t`@r{3wjaD zizmQe!y@6&t8F==FUTMO1Umdf?PhUsOa*K0v!`QC34kd8Auv$M2s62)q7reYL@YIq ziS1W1jkQ>Moi^&8wLV-HSPYC13~ij;&GD<9!Kiak#ae|XF%HMj^eWsmd09ZvXfwO{ zyP9R8LYYO&1(b#Nst4y180MMPg0vDp}teVX?2j!h$Z(THu^57)92@xD20uasT?2 z8D7rN9{$?jt1fTDa;0-yhIT1 zW)g@e9}ZLiEq21}0GylEg8mTN#M1#x#p5pNTQ<^V5-R)a*J9|stwdS2P6ID(a1SmF zrhhSaIbKhRy4%f4OG3)un2-^!7YE2iV&HQKI$G6^iyAe#u zhXaH_Kl(!Zz`cI`gyTF|llc^Y0#MedWr0U)+zOQgbak$H!fksRNL-odKw0^cUVLc; z`uY2A%Ae|(xw{lEa5xj!8{&y9>6IRA-ljc8|PYH`Vux^Q+znDAD?+518xVk9~oNIwFnCceRLj~ak_0<;BhajB`k@cys)5E zNI$4~V+j8#B$d{3h4k~s4aZG`xni}%{e0Q54h9SsG+fEr*Vcp?SWLJ_dS*WaTHiWkLU?vFRo3NOqAwVoKo3)9M=qL2t( z+=1I9@Tdd{C0m<7Du1dr3X`$zgaa2aP1r1B7;CjNE;>h2iI>fV|F{A zc81_NSZQEeGKTuuCc}yKsyF0xPxH**ib|Mn2vve3u-9o`libGK*#>AGwOS6?=XQ0L z?dYu?OK9ui@j*oUPrQfia5V3+W(GG?*rmUbB7gaTOaG(556nILfh8a)558YPWrHsG zm0Q38i)xCJ!DFNP^Q%`{FvLGA2GHytO6-AL=qKZcK9?CK zAdFTz?>|{?SdNHkWvx^g%k3@cqWDadpE7&>bSs`HcxS`4Ywn&L{mnC3#l(e^YMD5sbnjDi2VtHNe4(~@V+Zcy=EgG|mpr5K`gh1nxd zL}?(C$aAvhAAR#Z`>IiWETetN?Q&n}A~wp?BE0OM7I+Akx=*D?xd@!9rr8-kqM_Br z;Wk|sO@{}{WyTnuNAAJGluriF1znNxtz>W~*@Zkw%DEB}o|Zri6VfIEe} zlu&p4EUcf{-qGd3`6hdUG6L$cv{E9i43qG=ETwO|ICO=OpF<$X9o!5^V&!OC$Lw(3 z_;C8kGt&AMmc?GiYbKyx`aIpjFMQ|6a)VN>cm(bzxF#vvzZSiQBV^D~qB-1)A8HH% zc<`|j>bgKnIBrf_#}xwk#^jPsMYbMVLV5+*gZr_$B8LwPT8|10g>vH)Li$io8(o=U zIxzlNtmZ-^-@tZcabNYww_TwRjeqj;DEqUFO`U;M2zNMcwKt-8)fz(i7kEyW!ay#ISfT7Qm`YM!AVgy#6 zk53jqeXqU@j86A_eS{CfYsnVgTfaBA8R7ddV0tRD`l8%Gbb?uuD%RXlg`2A}U(8GTAurxi)o z0@zJ#3Q(AyC-hjq#vq4ccGC1%a91!R&hBlj$XMhWCgroNVxHw;{a@$D|4GOd+ZR^v z=lVE2@z}WteV~pKh6mVk1f!x@Zh2~)lu^7r6@YH?FlSfgzWpsY5EB{#D8GQfmy?xB38Z3QgHb{k-%c(_WU8tN;F|^r@=4>LQmx{LytN*-H^i^o z$C=BExC<<5_ugu_vCaO%@DtTb0;K)t2Q5W|&2NuI>F- z-3`;IuyDa_b-evGqV(khbFj0EsqE9?UhMO+sD_lW#V-o#ugX7aoMU9SV#RRj?0D6@ zCS9&OaH;3nxB1&XG@QVE;L(*ay-3Q_ze@Vl4x)R?n-r{Y<$nPpH$X#Kz=9ky8WLvW zE?D9A`|vNffsA4(=>_Sl#&xhv+v}aS3VTWu(g{=85#xeqbCK>Krc?*fh}mcL@N7CI zMId!HrDU+n;Wr7CY4Onnfhh#`jwy%KBK!551JWxxS?_26s9iggNu!B5dgHB@I6^l& zb0Q-4)RVSPycenY;+T0dt$uab49rsj``yQmT>YtrcMZ1gQaHf#HRxRMp0?^p8K~8W55*#{UCrIGiJ?BKjSb36J3yQWjgHuZr}ke!gRO8npexLIGKD zCtIf={L`v!d14f6eKe{n|kX!-<#m>b+;TZT&YVCH` z;cIrjsri)eU8zmr@p#ek{xuR*%B_}ET_i*tWMJib} zDrMJ+y}4;2Gx2=A^+F?r#bb)gktc<0R?S7tQyzs!i~{8CKm}wV z{$~jXAg>Rm`li-H7}4BGUTNL;w4Dik>J$^ukolwnH`+F8G@FsV8Y+3aGoOEeF4Ct7 zCFjzWQV>NkE&SpfL$kUKVk(ZFnnqLFH9cmpzQ@{*eINZ^x1TWRWRNEm(|`VVN-1yG z7GIMmO;v>Z!m%G&D$*ARK~DmCkJzpUXLpPuktpsLS}9BACSC|yik;~5@Fwb#{0BF& zfg*C+eAiq1MfvPHLYfbg{f+Gq?Aor^`)VN8lqN^a<^RRp$9k{zvy@1pX1N|;eW-9| zwAIip_axjs{Vv6OU89q+5KB#&9Er0QOiBKtjl&@slLieC1i}ymlB2aM_rN<~LkWB$ z=jj;8i~s;HV$tr_8fqvm5I3Zw$C|;lkEBEtAnbiN%w-EGSm=L5C%ob_#7~+M`$GY%VPLabhoY_D5!U~RSN8hwC4M$ZthMrTdx50U zmr!eBoWBOgEag#~$Q8J+;f=r;s-V4hl6HPVKaIEPihIz_aW8EPq6EV5x7;5kN>yA# zzR?-XQxRD{uPY^oO=I+otP5s{Tzkj-W|s8BpiNN~hg;|E{!GU38H6(iN(PK7X$CV& z)KpKU&wq_b#Rbr&7V6QW8mS;jY<1V9hgC#EUZ zH##*0(V@5ZL}9)MRj6}}bw*=&C{yWMY(=T!Eyl03{1^Q^;BPPY8)NGnXUf=qZ*%95 z!sbHC7^�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 K`|tm6zx^LanboTR literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/15-choir/72.mp3 b/src/extensions/scratch3_music/assets/instruments/15-choir/72.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..0e3074f4328c3144c5868aa8946cf4ceb720e823 GIT binary patch literal 29022 zcmd>m`8(8a^!Iya7=yvscgDUX#u~DWeb15#sm2=0u0CX&v6Fo#vSyb(RI+4^WQ!Kr z%1$B5{(fe9zTaP-f8lXmE*JB|d7am}?{lB~oYxIJN$v&y-!CgykGsUb(GkBN0D$*x z07j0WLZTR$SlBpu`2>VT#igWW6%>`#uv)tMhF8ojuHCS{jk9-hc6Imk_I>Cd96|_> zjEhf9PRq!7l3!T-tg^bcuCclORYzxc@8Iyr==kK!=h?Z1@2l&Z+dI2|4v)`3qAfFH z4HF$%NhL)eviARlB!?D+8*2cN1rm-j*#|=Z`@#P&Kfx0;F+dPONI(|=@HxdhpCt%R z0l>~b{|{cHF?c8dd3N{=^04$GKLmyET`U$0q|cDkytWz@GqDFt z{p`K5&pS85?#YZPcfZ{UqE%gg;KVJu?)w+#;ceLV=$23Q9S{UB=qF}anVA7_0HFBE z0iNJ`$pM_}wPU@vr{0Fmo69bwMy8~F z>exRak8H9=z3CXz`TK_KSn{et1PZVKpt7gc;zb0$%y=}dy>|pNDxQyHF!%Fa69X3G zXVa&;%bvyd59JFSQkPfjz@eA=7d~ba%>3YpnBUPqVG#?C+Z=EmKby2e*b{7!|txa1gPJu?U3G6o{- zO(KB|PmA1C+V(bDe8+t^_%(O4?WnQLLn~&uLuq(Xc5yf~`Tpx3h*Fi^3OiX-W$px- zhf$#4==Wcj$!m<}!Cwr?uPWp22^95&^#{$iELyvr{|)_}nW7d^O5=Ih_MjbzLCq_6 zG~21oPbckA#F5KaTCm(AM&nFO5{2fA2Y@Sb(eR(v`*1dWN?;)^J4N4$ Tf?z$yF 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

VnzO8xF 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 literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/16-vibraphone/72.mp3 b/src/extensions/scratch3_music/assets/instruments/16-vibraphone/72.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..ebdd5e0e6730e38209519074f3d9decdc05b70cf GIT binary patch literal 23547 zcmd?Q`8!nq|37|aF~%5-eJn9!Cp6YXGS*aN7e)5HEZN#;?E9{)*-3UqwqyvYD0`(8 z*|LO+vY*e<^Y#Aa`!9UYbz!dKy6(&4zTNKk`(wb}t< zp)pK2PHrAP0fMNwq_iwa>G%n?Q)J!KXARC9TUc4!Ty}7A^St8i8xVBk)*Wg@WK3K_ zO4_~5?A(Il(ua>KYwMppZEo%8?CR<58+bP~GXDP40x*@To0?NkHXKKIwH7jsJIpPltov_y$0<((YZtelv; z_`+7FtcU{c_dGhv0)pGNYF+yOY=!O|dLuR-3GUi=qo^!?ekS`B0I^b5vc2SWdX)T8 zcX?rEu}AdT=j3A4&)YUj#VVf0t7UQZ$t7=~SS2=8jD*f-CW-0%Iw!9jkib8&q&1Nu ze~g_Nradm6NNBiPl;B>J=;wY@qJBnh_=vW1tA5esdG8zLMPs7lu@VQVXGBsZz{6)p z^mkwx9KaEPXdM3=PSyykc^eYd*di+yqfsq&A$9vk8Sg;TjbGKK#a=fx&beMflcYs+ z;?quN1SG~4Wo;U#%V#5_^d5ln$3)SFE(>~3!5y)Mc7>`Ks^>7<*F7f|%0E8PubvMl zE6x}j!-N5xJ*+P!O~M`B{fg03@v`ILAus~idOyP-r42>iHLigxqboSTOT^g3A|$8N z{oKQEL&v*pUVO_CRVr9G`66!qc@{^BcrodI&%V60c_dl23f#8h)qPZZiLx^&=kr_v zel-VtB=&!tL4C(0)_cMWd9mqovYjYLYMMS4CuR(&~Y=@Dfa96OY3^u3Nt zUp8j@Qs5XKfFTbL0S>TC`>WNgo}O-#6%XvyiU;7g(KvJL+*~)jaXVWJBvT19=?`2s8d(33H!I%Xyj`WJPi!9d=v@fZemZ*--rYurEFzTd}NcCu5G-MB>H@8i03 z;n9klYM!G+Il*&!6=Jbpx3ps=o0`C3eq=}6xAo&A&LCy9k}|gG^&iJ!S(FP2PLRh< z9UcM#V9xS8asJywhtiCNz`TZMTEqnL9so|(2|)9+8>sCV@m%U4} z5QNopj>nthx6IP3!Dtt2}8}l%R?b$cKO$*y zk10FLf+(Y+NTsOapv{~A815|SN#OxF4*oJ1<9`yHMCgsRMyaZ|{Sn^;>zQ7xmjC7Yr;IJHaOvwTJ9~%L--E2nO|`Z~~Q0XNatl zju2&yCyc~j<)YUu-cq^3B5YhX0K1U;&iUNqdv=9BL+0Cqao0RAd0G{*%PV|m*;a8# zxbMhq{E)Kb%Uj6Po(e9eBXf23d57eJx9Md5sd#RzMamaI;{Nk&?1x7uYL@7yZ)CUy z<|#g77`DOK6g4gtf{jZ4UUy;9dL8035gIisBw zcP=@dQrtP&;>KOXm>I{W9UUjQO}3;qB<-1Xr~d^HLgc;H!81NJ|9B7nY7kimu)Ye} z>yj8V*B1KFWqiNR`|D<-DE%y-3&Dsht#>K`CIiYx8o^z1H#cyuq~myXVCl4fhMW2%d4q){ zcD*~E%H*O}QGURU)GZ`!R9(91aGkMLaDkj1@%sn35k(XnzOBVp_8{em1sfGWhyb6+ z?iR57_OxX4j!3$&d21c9?#Ov#qA!-${86~bGu4h|+Tbh+fDcHSDJ?X*=b4**uE?FL zOSd$Yljkw*C_jhF*moFXBK&OvN5m4I?`U^CIlIc4jsxhhbljszZ38^cosTGHbR!`s z=g<`~R4lFISk-3f^eq-BGn=ol#4sV~!vGjSnAgJ83w^0~{WhcY`YJmxUi#}Oi{`EP zKHSG@rC)5q37KYm3_8$c#J4NHtcpJCbhBN?^dqK9yvV9eco~_fR2N~ zeJ4_$?z|k;m_0;Of{N%Y$h0qyMG>dIbE(cKpX~7bp2E$;f8Of`i?GpVCI-PQ!i3=x z>UXI!iPd%ZVjrV=!?4?U?ZEf=Fy$a8phq}R?(*y*`OzL3D*%ay*K(koEXoh{p`&7L zD00=eoQcs%E}N6Nd&IQ!4#F_qEQUyYd4sbAF7m9h{gkV;FN)duyX%)$E)mXOLcH~- zZz&r*JdNYKg_YZqZFJXN0o6YGgZO*>6c9Xh@aLt_5xXUD>{X71#v$9UoVPd%0IUS& zlnAvE1@9=1uJms2RW4#fz4I$>}0V!Q(3o|?1i=`t)N z(csDR{%^ze&np&Sep27TO4}Ocz@KGy9!2rF)3$m#;QqV8uh0oPjoSlgJm6P=jJ=K~ z4Ze+vIQd$sMNwlG1q)~7!0(U@yLd^)lG)GXD^@$BIGQhQxq4c@d$G{h^0zL)48HtI za^cs_xm)9nANRrE`A6S87`wLccIipS&{L`2@`W{s1Gu?WF(i&GX{cj&8zZCs__Rdy3YTl3dZ#?g_=3>>6|n%rCR6ktBzvh z!ZlQbjNP5y-*l6fO|>zn(!AX!4z6eZ1*2(*p!{@tutkRQJpYjC-+e7kG9X8FJs`mQ zzXBBsSemm3HP?P3vR4pTcP_G4I0GX-@JBZM44%6&LqeOfSaI3(JD$%xb!%^LZo+eQ zPf&JTv7Rw~gu_3>Wfy#z-2sAHAHla(hge#%6zZ z93>0A0sl6MdS#LaGX+w6g4qBH(`j^0xLniB6tn=Pl8YFo}zXlK4izKj}M4rqDQF_7{VE6ec_tP1WkgQMF$1$;=q* z6cfhlQx_9KxCQ(;e)Q{z{JE4xwS&)+v^Os{ax8HS+!m(7tre4qmfWT}htIdx2i)Dj z+Nuj}hjjl^gd!|N0UQbqcY{;;PupWqnMhXd+`}+opkj~|h1IEr=?n3$N_n&4XkPr2 zP@ZxLe%DJ1!W=xc$zOQ9bCd6=kT+V1e{`mYxkf;+Hq7gq)dFejLmmf1k8mwmt}fI8 z?gdp_N|WL7e770l*n}V0XP;r{x6ar#O=ezrB2H^MT9pUGM-RN5coW6!CZPy_aE)}U zE`#e`{<_TzbNkKwoU!k&g3me*g7S)gLqcybafs`FJrsYD03*R@WTcjD0l^8&dT0fD z0IT9JYPhRIj7W4*>TnJx`4uZh$USfvQ7L$$>=2=yeM%3gTQ@rfBk(B2{(8SP*Auef z=H~Rn_cd?cey5z*3NKG1+x?NJ5?&DOS>MemS@3?gUmFbW9B95j7U%{nVpAk}ooCZXHe@9(O3PKEcv47x>%Gl>3S@lPJp)(UF%L;6CScO8rB3EoyNYE)5aOo))=|3zvTMTrO$g_a`rI8m8X?t`41_l%Au2OFKJfzs$E#zJlP7oxE)|H~^!E=OM`S zeAklM?9bpG=c5W^g|c|;!s`oA7mFng0zCO(Mw$j=>v4mp=C20C-01r3YR!#{Spa9q z)h6Y|%Yvc#S3O^9_`Pe}`VBIHODh^a?jTt2ruyyA&D#`+%|Wau76J@sR0?3{aI8@P z7jRE*BL2A9RyR#Fi6S4rUG(YLwF+CSPwy|OMn%7UUFLnQ@6Z+TRK|@ksB9sLSCZy7 z^AsCswcx4Bybr7sfxd?O$#cINHf8 zO0suP-9Kl17mpY*6O&T}c0YTmh47Szi2N1jjco8QBq%hmU*%qpiUbD7Z@y|X$TPx?TP z`xNlSfWm&IrL=7R*r$J#tuc^g=nfqYM#X*z5wBUCFLX&3g<8Z0y!uuG4AJvu9nTUD zpx8spN=R-&;qxCHsQh$KN$ML?VH5XM79#7Z--=@st2%W%vYuW^bVZmbzJ3-ZW+~T(E-SG|tE`uOqcO5a#ZMdljSF?{ zcWI3Gb`R(0FEF9PZrpfpI_guHaq}&|2=M*W-jxACthzZ2w+IaIl)owO-+6K6NVP%V z_(A>B&9D0xtbTBD+5OY1W_FAlN5G@i*9DC~EfzhRVJCieq&>UtknGF}ADm?6n`O1o z@f=xk_b^ym@%a`reh{1rIUK2*2f#QxDXc)IBgfC*$vc_u-|260!BgQi_PU0YMYQxS zaOdN@4#RgGsbw1!h}FU0oMaq7l5>N_{c78mW2C#Hje?f8!WZUve$sbo3<5)!$;wE_ zH!@VUy3N%7JRkSe7(DQ19~yXix3|sWOY{ESlb^qW;8nrRq3?&1FZJA00tE1e9mB{s z1*XLCQUQr|k$%N1hZzn-Wz@MUQ?(i45Su6x2xSD6UKDEXFOfN!Tu~nTWWj6LpHRSX zo2)u!PG9C~PfVf{WgKEo#`CIiKVZ{VJS*z#NI6I_4Fb!)O{%dSda<`>L>vl$MZ;|r z$wp11vJ#y~;OX)<{c0c0U(+P|`(}F-eq(7mKaZT;lRtXmE-<_7_x3??hDn)`Mzc-o z%m|`}<2mKKE3NG&Ca6P*qc0hs1)1-TRX^mVhSOCF+YDNRL536(t zY~f_9&b9yQ45PcBX!R`-qJ8|_ej@1^>9&Iz-nagEkv#Im40EFdg5LQ47i7kqvb}8k z49h-U8{=|EB7f(z?axZ4ZJTWubJ`z3p}uPe)q~SU5I=CZGUck#!kc|x~_!mCVZXnA{k8#{jhAuMq1g(Y%kpubqrfg^jX z(qY_c4tu{U)Uq19s&WbJ zTdaNE$@;5yxABM1vRR*MyM`MSF8drZjsW0Lz&%!Hd7FAhK_6D|R)~pHKXC&Ue+)(= zSXtR{!g)W~!wav-yQ&)knQZKh@3RNgiSEL+ZU)adgOvOeV`c{yX6N_5R%Nr=PrrR{ zbcf|ua0f?FYvj1)gAS-m>@uH`G6zsc3bw|PmmiAAB3OsFUL6Jyn##BZX(hBlg>oTvk*RPebz`RQUOpXkzQO3zJ%ZcJx3Ylfj`rSSr@}u+F#?`m@X_O-j#l z0CC227!zf(5PT|Vb26kZDGcCURg~EemqJ_|j;Rv?`aXELV#(Ti?jQNH>?j~@)z)rP zb|iu4?8v<@4HtqsARCQ|Y#e@xU6?I3yJ=ZH(m;K`5OLmo)>@hiE6dneyajd{(Vs@y*Q6e^XA>8moFs`Y;< zP~WB&*AFUj0Ca3XGZvn;noP}#N|rF_nkW5BZ~(TOB7Ruyvy$f2q5dq>M4Njs7HQ~{ z_Z+8mTV$?<%}u`g>^YVBhUE)&siexC%z3U4n{g*Tv}hU~?-v!+cFJ%2K!FfegG3Jq zuI9XvIT{R|Bv_46O#fndbI&9_6ae7il18x~j(#C=V;q@bI$4svJQ8T9T;`WY#U$qM z^?b2)IBna+TH7aiG*ykuzI3Y{cEY{*lF_)5K$duLLV_lXa!bal7vG3-%>Z}{{3~pE z58T<8b-JS0;64KJ+Tk8J7_){tx5LH&bKOg>#>I{3$THXdSz?clCv$59m1oLEXd%%G zxD+jv`WnjIkEk9`HhyqV2hh(koHGsA)18LtN>zwWtWE@;6XzqSt+YNjDQ!3s=m75Q z1Y3Uz;drb8@!93kWp*~l0aPq8%f=n_pz0VEbl`xifOY;>4-txFWqmt}Tyl4Gv~fJY(;^eLxLk2rk z9P$N!W@`lZgz-L9j|Y}}qC*CK<4>YPB4^y#UeL&7Zn7r4mknMmftSpY7jViAP&H6p z)*P=Jcs2hB^r@(N+jrfcg=4ZOQ#V!!9EI^;*xkLQcIBew+9Bno#!ELPFZ7H-P=`xp z>k)kX%b`AW091g)YaOD9rO6_VKcr`gI7Bqr%9l>F;Dh~WUZi*-KOxpyP%3w6+l-td z0gXJVh5=tz=kw3yBTA=K`@juvd)GH>_gpt3(`vz;%9_!v=d~?%f1yqVoV>Do(5@B= zz;sLB3X$dh4nB1SsQmVDSQ#C;*)cT+b+!|@YMeRj>PY6$%88}Vy5U?S>LG!TkPOKw zBQIVXSR^bV=eYagJT6}klhHa7^eBHlb4^3ypra{w)8gVye#PlpsP6r|`^)3*nY?<{ zLw%sqL=6+J+MIK+VwqQepT~~|5L^{oXy7D!MYxuJl*p}9SNVl*QDvElorKKtDGRzx zMwJ^=mDk=4nj`8ew1nrTT8spDj+YmxsFV{cj`B{P|ER5;JTIATn1D*-YW(k z9w_KzI!!6$x&O$M3jpvJ9;^w_COAqe;OLM>E)H}*UwnTMcHFGb_Tlt^vn65s!`+?} z1Ue0Fe1B-#@%9;Y)@X){n$$&^xkmWkm4xrgfs{WFJFfCcjlG9R?_>p{|25W-Z;MsX6ISI4g8lLd{*r*Vg>R05Amy5V0| zM*=VaBh$i^dza5bOthYoJBwUaH>-*Wj+Z;Rg0E=#nr7zX<0JfKzwCH?iL6iJFF0Q2 ztr5ZG%Wzb0_K!U9>bebr@1Na#ReSSJasI?^P$i_wqsPM)a*8M}zQd{s2N>#{psG1v zcs_nk3F-?#Dh@gLO?M6%%D_v9j=x;W#KfEwbGiU&cEl>VOWM{l?-p~`^d~##4oX+N zxUg`GAum%*asG{(mP=}o;Jwv14>Jzf)LIAtLsg$KG^yt*^6-cd&14RoAUnk^tpL&7cVl!f63Y%!h1aXzk@<#qpLOF=sc0MErzN~l5 z-|Ve`fX)B<0s|ii@I)2*GCMayRg=&5IupEdy5~4OK-WZaCn)slsaa_$71M+aI0?;S zPou2wnyZf)+h_4Rp1yU<=Hn*kA^82!7h{uVoM;li@p--Cs!yf+#kxcqpI&)3c(`s)j5 zutq0%T4g9)oaXr1+x@R z|2KcabUPh|TDs{(T&dD$!d~}tI&3Nynk@@&g?&oiPe0N2-`Y-=&w3?2&y!hr5W1!4rPP**! z1<7kwlS4cBI%!Fm$Qgyx7+5QgbYGZg$i@xm-Xr4vU|?S|V^3+|t!S*xGy zCrRAI+w`Ryc=R57do^YH%#+n-N!KXG_LP0cmnAL75(NLS?^+Gr4&MK2#|Py#=%Mtc zEF539*5TDeuzb4h-gR+p=$Zi|5Z7hjXW(M)?0elxW=Q~{M80&910&!$`RI{5M`mRy zF*{-4afQ#CB%#bLH_XGM=ETq6xTfc(XS>QMOTdv|y2pNP7Nt1fl13Axjt)U=>LSgH~~X#7!R|4yTUQhzKbjbBsxTX0OxiXyq)$`0(RhtG12q!`NblYHf(z3WSBi zljin6i|pm~q>02XKbjHtyP|WAK<1pNka2io7x?jGUQ9#K{eAO<@>B@j4+4!?d%{xgsAssm+lGst`%ibL8@eM=qo) zoCyr0Om>yYDDZAu8yVfo5VoMC;RVk=CU-rMOGNxo-M=~5 z`2v~C|6};qIqu*m*;98bh*y8dc>jLMl|3mpGI;B|WO z1mAG{1o5$a?tbhXN1R*ruq{R z%V}&In8I)u}ry$hyOO+x6HYf!6sU6%~aJxxqK6DV% zTHKsevpr<6IY6;nKkHk?Oj%miWsSk>&2>jNox7V4bqscn;J)iD9D#ZyGBY9cHYKF| zhQ~D)4TX)-MF(SCT@%dr_0MP#X@PG0SjJS#dIg!vdy7uP!Q7g7@r)#H2EQ(?$L5A{ z`JfZ)(%Sx?l!K?W6sva--SDsa!$yXj|J6-K4m-J(pR z7rz3yA3vhz)4Tg&Gy6#s1bZKMKIJ4g1I=VWBIY4YpG)i~C$vXJMgca?yzv;0=FVJk zSko~p4Tl7Y-1;Pj^ls0ld-`=654YR0~1`75=$EBIZ96rgg=}^(NW9L$cQH- zE0RLq#Yty_M)^7XCVgir9*X90;POGu2 zlV2@Yt;sP+oeaq<$sP6W-=Oldkt|92 zV0#4XQu^Oy3QP48tqz=>Hj8(L<_@#V9n18-15y$^j$`^4T$|Uj&Ijh6`tTCmKWGe= zZO93i{8noY1<;=Bw?%HY+Rcq4+)&@eDMPCcE%YV#$)cI)$aVIaPJ+#j1s_~)_;fnk z8raUHnSEXRqIucE4wS>`-FTC8oJW0k%7!or?hCZ4(*ctz4}y+-iGuuZF_l{xGayO&{jGsufM2&wOl)0_RB;K9OBj9Dr2>% z=n43c0a4oL`dI$UQw%4kqGAWNGvsar^-O@pu~qv8;?dZ-_B_QB0oqtVdODKGST+@J zX@BfhjIOIBf+~GnDN**jcKiNb#(uHc#!*Cf$YADC-|~~e(ALAEa>#6`HL`XRa-f5a zc~kQiIRJJ-dzIe!(RB%Jk<d=tm+o6%@=i=FiQlqJu_zU7y zezS!-u@Hz<{LIIges^#hS11F2p~#x8+v8EB_*Iw^_~nUkbH{-m<1@z>0(V4Wzk=Xk z1-z*aEc^J>+VyXi%K(HdL9Jps2(@oHXQ#)6m#3% zezx>e|7RuEw>_OAIhDr#0l3soY`|o479R!Nmso$@b4jAr>LK~#^(F7s>jDU9x_(7u0=rg{F_I}d89nH#Ib=9#@3@h|YY!}D*{X!1GJ&=T+>km-~G&9 z&nyMW92!>={7@gL&^0(oRt3%$1~bjw$$J+6<_a$tkuZ(cS%2`JhBgaT^;*0p=}##i zZXy@SpK{MR$mm*GIUEpZnCaK6o@VoWeKP2GJTT^0S_~Ott;%+Y_|>=oph_rO_YR|; z6mYzjW=rd4&t#!wrVA$nuW9hQ^St3aig%hXonYPRj*6$T#_wGs(JiNmpiN|Vci%-9 zZ~mHG{g4hWZnt{tSdJVO9=#cqmO4&>W|zm$@M#JuaY5@oi5u=aw9h-fb@BV>$xH?| zF#}4B|MUT{xT`WN!APPvlgQ>Ie($`#43(>bk;6L3u8m#8PlfR33}1FxtO8|!;gi9a z{8L_bQtc1!e#*=(ZR-C)+1>x}EhFO?H?Q=<#>aLI5NwsZZ|ZDwo+?M90h(9MCI)5B zU(Q9+R9%_q=6xC5^r;2zA!Kd&UKs6M<9u$4Lj<|mZF;rZhkwFVuziAhQ8D(tmP7D) zM|kS#`wf(t#e!6`WRFJa?7t-{wU9>OX5HA;OfDR>zr4Q2OUlmG@5YX3VhtwZucsy) z>cdDiP`P?^1!{%8p>5!2{9Z64BE*sdOFz8-#qjm`k;CFBqOJY%2W zjH0sO^eqS{qgC8ZwsQuVsX_#m za2TE`p6+wJ2sccIe7%v)<56Aky}Fjs+$wtxsnOI(r`ngR8QEo?LBE~7SlxmGLi7KQ z^MJ)>;6|ma$wl@e*(4DBv>C@6?#Y%3)=ODY5dz~|_2CAWnjK=j^y!cv2LFvNF#y)a z584Kb5N{`n2KJZiZ6{CC*5C6t+B3#I1LG0g*X177@=C5;d`Y~X@(KYGBogOUG+4bbNX+fDR`-w>IC|(hc;_7X#4p(&B(9-^w51{yQkgN)Z zJ6K>{)uBC$=nxvsn>mt{O%=@~cN+v5&?_O|I!(gOe&uS#EN!szWaE`fmHL(YGVUB$ zjt6VB@6T8bT9@U6e|DmOF>Kmcoc{xHi&%`9ABBg;?{xUlU;sJo40$Iy&eVi0^0F6A zt0m@HSqw)ep5v0%bmMqPaBQfy*AmIm2&`;hFpt94CS=bTrdf{vyd=Ueg$MToeOhuN zHqs9^f+^sE$3{=8(lSvFpy%t}stzyo3qS!O(4F2F#_RHL{X_C%oKmxGyqdGFmtzLCx|7vU0vnX?}jmau`zrRXhT-3C`qTA@8YX4J0q&B#X zHQU9%xx*a@Wuk*D^`f^v8zRO4{tn-_UN$fRmLUH@XGAPaR>H|cyOW@Mni_JJ*f`62 zPT*AkLEMe-8lrdUQ!m%N2jbC%g+eZ_HK*Q8evDa4aO;9rGCyj@t`J7wd;T?*gmTTT z-%3XmRUn`Ut^5E+oR8e<)XTygW|6?Wk}486I{3Jt2~M028%89*x*Ch3VO5 zMn)zpGC$aQUHa$768+j$X{RRQ4KIz-qUGigAB%I}P4=xag2C?=7)OD5IX^{)lolvV zH+#*z_oV8LX@H6SvFK^7hlo{fj;F=5Plmi>h2W8uOn7HfG@t+QE)aG71wu70`Z)27-ew*V|34) z*c07$Gw&L8NLqfr0QFG0Bm39d>(%~_#BNkTTR%3*?r3U;FJKNBz#xZ%zzcxA?Lw?| zIZYJDy0j-MmRPaD#o$1>LtZTE7!2@v>X_)I!vMSWWa8rand%B7%6IKl-c$8cw1XEq{~n8IhqwFAG0-qI@T<01`%nTX z3hiDRKB}(d8sb8k52c1t8E_YlR{hi^s$fbsA;@KQ85l)mT1SbADIxG4>A0(T*>c;Ej@UE875C@O=E1q2jJiTd($N{JFB z9)n(z6@_kN^dS*+ql|GQfgdb1nv{&M zLDTfj3yyr5^{afY&0QWoP#j4IaVx5qwU(1g3mq~=r*uMe%K?le)z^moXt6}FHZ>v) zMP5gv?Csqzisijq8UIRZt=`J**!zv&AgE16(^J3$?eExhg|kC}OSbVA`QUCd>h&iM ze(KErN_}A+&JjyRrc;0fxXxjmBB_i9PNIi5KJpb^?!1f%;8@CM#_9W0!{lBPcnK)x zt^#zlo-}}da?kSB$?I0k-A}JV9yhFYxA??al~IkC-DfG&rzjvelXukPe))2L=JSD1 z8X#CU?sr0{S715#j&lhTm>&Z9^m)jV`-TKE6VS`dkyZONkhbNUWvw+Gq5s<4AuM_nWjuR*xPm$vtx><6IHd(?GaQi_zNKJ2LEmQ{o0Z<6tu zV@2P^;AylS`Lr`G+Rx0THo7X!7O!96f0ng@y9|7}?c@nZ&e`bVRgbl0Bj);lBYOjpeCkZ_dCo4a#kuLx0N=aFJi{7{&wsw9q z>zCzH?8>smP=QG(=jR8|fB;ikG@h^j_QRj*5bYN{O`{H{6no?P@< zW33=^G~mgmox0pHS+(`;W8gNA@}C|3mUmiFCeA-7An3SRu@Sm-8DJ6oMEeunTm_3$ zM3Fkx6y^JA-!utS)vRbZR+Z0QVfkC6+`+&aR|{kL=Vkmi-|cEIVWU6Zw+G98lfb$1 zx<;nTs=)gk7j}9yzVI$p`>6P6jkF2zPQqM!VqFyr-z(ZMieJ{X zh-^QNR^fL77K`j2#sf*nacqFjW8$dF#j+p|jrTw5HnuW>nc*?QMFi@cP+&}B;%0}cypYN}gd1E?s_;1+Hac8PC{u6Ba?TO2*I0`c-wA79xbyDT zwWM<$-5OaP;KR>3x~m3!r`jiEEc79?k%LuKG!8`dq3Gz?DTrmKI~d2}uGucc8!hYb zyJTl-9noB=q9hU_w@Q)S3wzpkF0y{+-(_7@FqQW38kCW zgbiCL)$ot!-W)BrB?EYy1>UC&IDvI6)gCaGf@NX_c#huSH4x{wwEk_$Y5mfW=eDc3 zolyX<*MngDqSrRd#0yEk(|@X$r=fsM(cVnBHnDK$-bA|V zJ;hKg-&I<5_`eGhNGi6pSiEX|u22;{yIE6S!f#$>9Dh3W1We`PhTtQ5&aMK#p%4j% zkD4)Ce{5!lt>+}$6OFbc&t4?!s5ncp94tP}FcmtcL ztxg0&%F8=m1LsrMAR^^~yndrhpEX9tv|dsUN;e()&{|Snpz{(3z?pd$7z*!sH0V1% z2FU*x_A$8@l2v}X4w|tgjfsj?qhmQ{F|jnwa5lJ>r|CD*TK`9FW(;d#;2e^Ty+#4u z0q$o^_(ryVQ&#lU=97DR1>z`AN}Jf_2A>QQ01UNSs4(D_5YBl~xo&i9W-tOB7K<0+ zC|llJH`4cZiwL4i0y!D3*?+s}7XT&I?N%cImmlT-L;a$nr9uY?exYxcXfu6b^e4D2 zS$j#3BzMM|iH2}E9hG>DLrr`Ut9j`03{(cZg~G~use@8%X=5HomA+hL=b0~`>MjQD zIGJQN-mY^z<+D%sS(WR%2_zrrGg_uRN9$U&ZK8mc&9WIz96}-}_Lgz<(+~+kD;~{2 zj!6c(N=1Tvyzw}B%2$TmO%^|6TfQ%QWG-jXmI6-N$b55xMrwCYum|C)+!!;V9{C@@)+`jSQ8b?RY;fL8EU&V<4Wxuib3HJfO~KOP%T3*n zTQR{;ve-EjOZgq@R_q#AesgCaHGb879z5f0!hR?(vX@@U`o&$8 z0n4ZA&R;gC9gbKb1f^#IRz9e%9ot_U@A&cW)ks_Gi3QI{VR`x7c)f$HD2k~xz+vtU z#K4UYJp@U`tX~kWnJz0NE4nE4OY}3nzCZ{^Xai_Hr-oHel|)ZsF!q)Km;T5sLtelK z6?bq(#hN$uHTk5Az9Ex`#Xk~fB?2NJK zRnqs~^14x6oj$7*nPw~W(O)`)IWrD;@3RlPeinX4fZCh^-5q%|<-eHmTy~SITi6}4 zNM5;{enqYDN^hy2VvR&Oj)$BJD`sFTel;OMC-Kpk1J|p^O&2K`B_o30T@aa9or~wf zJOo1!98gfMhF|`}L-ZtHs=KCOuQ9uz-|8Wwkc$H5Ozi80 zprUg#IN-vH*oSa*f>+A>u#a_;Q>^ccKxm>+oZ8sl|J8T z8I$}Os7xYr{SOMMT##9Ha3lJ~A2u_y`uS9@PF7Et&bQgZl#ocVW6e1vF-EqE=)U(N zGI5MKFSCsodzOCVK*}mY@7FtWFytq@kJP29VoI0zlb{4i^Q%7d&7q)fP=b(bVv09k z1HV1RC3DIX06I;103CiDW8o?kBUTG!iUhhl#op=ns~Y;VRQcn4I8F1pF09!+M@ByD z&u{tNDTwel*pKp_GH;4!aw+f4tI*MS2rcCh({H#w} zq888&xb()km<}Vs?P*iTzVctY*5B3Y%1@v(gto%%O6RSmMFqdR94s?fD3hQF{@3yo zoMcu{o+&(uacS?Dp4FwVr0~)P+joqN-Em|XN#a8<&kO5_ctxhu1svxxOA#^FGCseI zznpAnZMOCUx8#Hd1qx4b(2Z$8e&y+yBNo|g{?dPw0`8|JeM_zn7v-*`VM%e0?Aa&jnjJI0qw<3I?A6ROqx3P}yr zd~s&D$Qj4&;Zy|~Y^`TNrn^$bm~@;wfh;h@5O$v{zF*=E$FC2=zYn8?5x_*79b5TP zO1z7iJ-oz2-9xEj7+`ozK>iWPw|*MJ4G$^YjyQ}?#6<2?#xz;&<@9GNVHe# zJ|$#kX+KyN)-8KWnflB2dQ!f1y_f>7j@|X}Dx^A<*q#m7e#*FX@yj1E$bFY>EOh!Z z>QX_=A7TBX9Pt0E3s@u3s=r8LI@USxbHnV!7rF#^jJZfDCl3)Y^GE$MI}$!zaSw3L zC>Ycnxm0^6d+pZ)GEoFIleNICM)?O4A zx-zuZ?#Zd^LWL#XX=W8U9pZkK2oO$qV_6vb8=e?8u^GMqLhw%u;|z{T=ki9(t=hmPuRm{Jy@^GriXoaDyVbqPRFqKlA2|HEEv7!tVQqr`}^dnC}E{#cfC7 zJ{b>zuGoKfL;yp{G~t>CBL`0`l&f;9Z~zLzNeS?XU(-`aB)v#X*px{D#-xh?Bwr7O zkyn!GeA6Chxr}})$HePMIDfNf*9`W&+&HZzil~L0;GpA;t+IE^(TnWc!tR!H4cr3A@th(^rEQAOHwI7u?pTc2meJ08~R;br{&|B zf6yDie7ArmeY1t;7-&d~uX=i%0!k0Y=gc#|A9V47Zh|FV zu}i@G(Z(}A}F#Cq=P-@FGB!vDT31tL^5&qL9pWa2Yuzk4uN;0}Gn zDBTSgla@&Bg)B6ZvU#zD|v}(grl-`rl2>0vM)_aR8YfeyFeK8q8vk*RZ)Xr}@FD>8j3h@rn& zdIM+WEFBN%6JH4fOJ$T>xA&bP(b@MfhsR-r{OHCn*?sx!VAJcnZN!?J71DFB-}&aL z&%5ZN~gz9&8c`+pTr5asWBDD&y2s9H&t5?wTdU|2^Wbql;u%Fa++o6z!}4 zuyGKfkr-7D=ZwsSSJXcVBb&mp)Kt)_hajE&vd>D5VMHMfW~&6=j`|Rq4N400HPDy+&FDnvdO|nY~ zX@YSX*>U{c5ZyH1)w>N5X0jdPNi=C zUis0_eiA4}AFqAvpB=fq>ziFUC+AmLW?DcQW2kFi4xLFUZwE8qx~hv=UoFTk2EUupndg#qh@V2_=k$_e5X4t}*He@~y@csMPF?0p zEcA&1tfF}p0a@D9a`Q@{Dh{vp(==s^w%Jeo^t(&iG%qUFWdLF2f9dZAdY=-v}ntUQYEK-r>p~dTp~{)AeW`izVdEO0|^}6*UEdKAzqrI>{wl{ z2Pr!{7;3Fua!;ppA5|mLx_e92iI`M*cM`}&gdY%Ks3Mi!BP4GT^{Ap*q zzBDt>Yi08Fr`yZ6sk!7#%Kf9f7hzN1By0ntB!sGt%hXC%O{4hI|Dj=yQR7&<z^Cil zrfLW#Bz~NwIhY;=_;c*)>IZt=wXiGRZb(aALgW+XZq8c#qt@2PjS_6}Gl}0TieIX5 z^V$oh8d|DWc@JFt(uxmA<(uD**81ZC{)+e=J1ya_>7w)k+8;hYI#yJT5&~U2a}@H36U&BhtO0e`I3H zWI{`mX!q!L@J7Vqc$M042G6$NVY!z0vIa#jAZ7V3MBnYQ5bLA4qB|o}H#-x%z|AA| zQLNFk^pc8TcM;`{L;JKLNH=bQaZDF!R;hz5a!%oSrm*bC78y;S#eAY1Rad|J@Wix{ zm!4iAwzgbTb%`O;7%0a|Uj28&E`L~lXHNJ$ypg|b`BRtW%w3^{=LIjm(bWa)NKx@A z_|lMK%#lwTr-+GXPeZ(#xG)*0ma?i)xTKjv(P{-#XNQEv9gwFkWM!aU!vcN^&#PJ{1=Gh}>50?nxdh8Nq|84ut0(1kBxO|Ct-HH9ql+!&wI6?;+srzl zUp#%x;T(@{6Rc(cijlr;9Xl2KTE)3{iRDR=%iRlRpcMbuef$g^9c{lN)<}km8p8I2 zFcdLu@SOlzqw9vJ4r(DEvM)r%Bz6qc59VagZ0-CXw*fk9{c_G$Hn#LXFWtcImi#p6ehd!n>4 zo=zG}sYy44SWz-@9APm6z*Lr%inr`9H#GLytiCS$IBW%SS(NKnCwb>;W&WG;Fs?s^ z7B@0Egz&>El=(n7CT@37{m^xGI1Q|ScL|O&{dPC0G2Xh|2vWo(P09Nz{MS7p$nMG- zlZ7-j_L{r-=c-u?PYo|bG+~m^~UjGTNwg3$ncJ_+J$G?7+EYx~~R++#8?c)2l zF9=dBEG>jzw2>y^Y76ONOLy|x(^X6ap&@-!x$7(4CgxBRQqV6EW%Y1%*I~Fw?HDHm zhRAK{O__e?O6p&)3hsiZ{?!`f7fH=FLMn|=vyV}DftTfTSzlAtWTx^(Eo8j)HCCtk z>m~%<`>jR-a{%LE^1b174(o0aC8pB#q+gD}V%Pr~6qMZI;>w~u*9}4YAI#|}*l3_v z7Yn3;XR4rzbsq3ASy~zauoGj`MHtRE>hw6iKtlgNVFx5^TOU(iVDvmPX;3GWYyfhJb zrZY6|N68B@`*?FQ&Be%Q4=vFw0mDkF+&d|yZ=-UjOfOZ_zkxW;ko|cE#gao%Jfc8$1L#ez(fz2F zQ9;k&KQ0weEoUQS|L6CT1kD;QsxW2l57bnQ7A={5AKeb&wkv(=@NtLO{C0uakws3R z;#4U3#{mPHO~tPd<(MbA)CO|sVj^vEC(4U8$K1l*CF!r*^-1DP2Sg+?jP=y#)H7QS z8jL=|N4t00=#%Xhuf%ARk}uCIH$gK!AAKk{-wfjFn3N1KXkJ)MxEjG!Ly`N!jo z2;fgCD>2@tSZV`j;mkbejTiuI)l5|1!T7_ha@EN z`8y9O+}Arh{QRe~cmWpvGmB>lu;Y0IdZ&o)>JX$}D;ubDqeR1o>IS~(8yj_&3ZqbX z(=c5s0!)D9Xc@QDJ(Awcv71M`zEC2RJL%8^+?7w=W zK`u3cl_(=<1N6E-P9IacfzGIpMlj2Iv&SN&qZW->0yUMrRe$2rt2HckwQFaeG=k#OSgE&*gjv7v(8IMbCWQ#aE zk+Uv7%7z6xbPlapF@#Uwd*7s$nc}=c{!{r5hOHP+>(t)ZVV9KB7sT8Ga0D#$BEK3A zcjmE~3scr8NZyht4Bw*AM0RnfKi(QOtY|J09-fU-f1RWMX&Uwym?2How5WMLs?W<_ zamh^^s(x=DMuE6_Y_0!I8-3-G_wee6ML~jTB(j;QyHzQH>eq-=jFN1(MPyK%9wWDi zguSAIC*~8;b2DEIdvxU|KnufW9xLAUB6yf&JsoV^;$Xdx4SPT#f$&j>Wx8feNzAu! ztf_=}l!%i*O@)FvV+49H6-6hr&`q)a3^=B#Tw&myzc?|7H0ARVUkCR-qeGoVNdLx3 zwq%954ZOX?#Sb6bvW!wh9(*SGuvfBG=M3XL&aXMPf7K#l4A#O*J^`%`2`j9Bu4v?>5xiqd#->VDX3@iXS(S$&3mNAAgO`Cj>O_0BYnP6euCiTp8T>XDO+(ic zPZ;3A+2 zJ)JYb#Iv9`;qShO{ycF~qp@>j{bJKV{GtjJn{&2VBWVDUs3OO;kQT)`Z;wz=f>%%O z=FWTiu%AIXrRZ%V$Ub7d5}!J?O5tYpmw!Y=&> z>gC`sff7DansQ6gs(=kX5`1&fa@?0zBu|hb2~W1hs~0T?x!L7eF@s^Q zR~T4n+g{>muWvOvczJyY_XVx7;~e~o&2*F=dU$zH;loL4lIKx|RL6Yretd$UiCc5f zOLOC+l>NlV3=pcB1&S9^rOmq!I-fvOE)J!ci>4GmToX!m-taAwQziM#6}`w;YFXF| zvlc3p2ueH=+@)FRh7LpJTW99sMGOeIz(xL;>7jdr*fw?H(Vle2HhILb>iHX@Ddo|z ze*2q^PE_H-v;F9cK?Yk)22ML|tQy$#ZUEHs2)(5<}mcx6^iA zQfqIq3A`gthh2E-2O7wD2vcoOoEr9#2hovidY|C^h}jRXG-WZkZd{Nyd}Ji3UGt!u z7c*4A^pJhS0Gjqh|53RkD3ct6=92p*7a#P(rTV*9+g;xnY?T*f`tY36aG0-+W8mWW zIq8P_KVE?A06PoA4u_*Rs>snv{Qd_`!SYw-^&uBKFA8cZT*6c?u&_4b0(9<2?UEk} zkic#F=u)HEQ`9&EOj2U^xF!lxi$0}<@R(R*A5*PbyEvmIx;=ji3m?ws?4NR!B-?tp zrL`5_x+b7_(_MX9r|jdgps`k z_z49y5{Lf?JgwIv`ked{;4X>+76uP>PgHZ=ap567Iv2#^cF1Q?N`=9+ z26jfwAI-grhT|`+j}P`O8Y{g*?B&92a#oW^W=k4gkND05KCy8l$6`s2AfN8$xnX)0 zBXlnmcrqVGMK;{Y@Hm8vt435u8HFE!*ttXspr-z!7$@41Eb>g-PVbK~{>S&N5IQ?n z0CN9AM^VOUA=8*Bsm|0Eg8RtXIuWH82e82A;Im0qCdt*e56!SU#bRQYdvOrfCuX?( zo22``58}C#hRS^xJ+bxRcs=*AN==Ni7r=GYQ6%(Ij`3!RuKET`_F)G#*f&qf`u)u5>b3dv>o!Fmp_erNy$O^Jn{*PB8g;XkQ}tmI zbv4VCEg)>>^eN&|C4riw?@^K-D;l>Q$Yb^R80mFQvL}>%EypKn8Ppsv&8Tdr1XvTe zUp0srHey0!xz1Po-u%>cmbfX(3Q zftuAbW&8tIJ9Y|>KC%u6qAT3sQJ0^!^HQs>{F zmp{*|ea4{Jc(5H(@6kM5YG&i@Nfx?9D;Jyjb+Tp@-j|;F6==}#dFZz9()|)+^f=LY z0}w&VW!p)b@Wof4F65R&EVS@}Ac#xivop>SAydKFXpeTNow}ax>6X~4G<}kE+1UlW z#P0jc8lhfx6qQufHMRAPOiax!ZR{MJU7maSyzmbUeghASh>A-{PEF55Q8wk$cv|x2fGXKl8m;l21*!RK~!O{KJ zmjQw|!c4jo%AT20SiQ=7^~MQbhodjk-FvG+K(;%wBl?V}FxTC1SC((0=zeRRFYsO% zz0&L6UZ{k6?S$zcwnDf@|L@n*de3j0OD=}MGj*n7k$5~R`~YzO3}x7}Nl?gvx*+Op zS(79K#~Sr=D@8(*e~5ay(5lKk*pV!R8D*1q>~!z7y8STWr$594#SK! zV!&+Jm_3CQFU)ZPH_dN?HI__?21*N4!~$(4xkQv(4h%a*#rk8G+Qlsb2i%0Sa}iv| z^kAIibl7%Srep}a5VeQZ zEPWX%Z3urFf?kP03(aP-NkngU-`gZNwRXd9EG?Ch!!C>hU6jWUO+Hz;As{y`%`2Cc2e*ZF$UTA3B z-yJq;rW|?fQ0nVDcJC9Hnq)tI)C|eS4)sAVJJKDLCKI}DJLYRcPLw2Ai+cgU;bcF` zJh2eeFa0mZ!@xs$!$~jrt$*$RW$*?qFZC_K!&(+rQ7FEWme0x0nfWC&deQWz*9qQb2S#f zYui2vG1N5AI_GhF>9i}($vz;|z&+a{QE8e-C9K~O{GP-bZ>x(OfrNcAC z+V4-@@K9#TfV6eafcyG-nf(x?Z4Xxr2!!(NZ#YNv^3>kbPHN0{J2wO4Dz$_;GRfHFYZa zu?rLQT(*x34NkkfgxS3jBxo)!zVj-BI9xW*nMsM!xw%|(S&~I7b^`Li-<_M-YDLaO zk59B5_cC>D(VB+PuqBObd<6z1*G&#r|XHJ%Rywv=gegNo%!1oCy}`>9FhI zD}#k29z2@@1UXi;IPLS;ZRK`(Q>#17UUaY$MNXj|TmJgw?M%8cVD$|#4}OmLxwm_= z;uv-<9Cc_S8t)87Cz}D5|HP*7p{-aNJW_U{7-)~RR|N|AO1_-~_a$mL_JF=m4m14# zDz}0_zPzr(g;hUydhiH%ou6T=VPz{jRO>4{((De{*3$CFe>~CObZn8;`TJK>T?`{i z34#UN+??!g`PqH*PwZ;zeeLZ%c;WL}cJq@@)7&HWK{bs;*-ZqiwAkY8^ZO}eLK_p-!*IPbvo2E=nS&iB!vdi)3mttNSv;CO< z*1!J&hemFzseGp2XXlRsu72?@A7R9#zft*3TnM12+5a-usXmo7ekE1Ps`{rSY;nq@+qiV1-aCyV!4R<64fn?&YgVUAv97IQ_ zPRMxM)M*mPsfpWNSUsbxnP+k7TXa7df@7b&FnH%CI|GcC!|VUu1nJs8&)Y+{e&7D@ zJFBeOoY1s0^51)V|E2-?we5WkYNyWO<7L6#rgnYAzkN@S`=iQGZvqfHCTnO9#HLtV z;}c6{@eF8`SrE=`-*F%BYHDyK2OtIAAVVSgU5O^o0iZO_4Gzyh1EHa+$mlUC!vkmNv_&~kO4r_Dts&g0Md_+{Zpee0J2Fe28+_0 z8I2wel6gzbY#>~)I+~%L#pa}s&5KF*SON}JP}~{Uk0asB8RO~|L9Toang|ANtEET| zYG-W@j;`L4RQ%cZI_Ul_*wr*ZouKk}-uVOelI8;L3wr7w7nLvN1y$i2ao^0Q@{r%s zKw!ntb|c#QN|uU>(ouzAwCeEA(n#Q@8dLola3@H5ey>OO3;_Nt!fpJ~K@Y%z!wl3> z!0jgQ3RS!K_sqU#M)~ScQ35?fuOwJl34@(MfMP*eKwz6xVf4i|+%>~4t?W`Y0&2{O zh}#-{(GR?%1l{|L_R9YSet8le0!TOYnv(ah7yaD*h74y~pU_{{*~HD5SH750g%+^O z37b_Rp9`=JHK7M8+R%hCB3eEZ|Lh0ZVW#-5$pPBwL?ivczZ=ba#nces`)%1U8UaYu zTTc%^!+ZNMW)zR318Nmk%}7iuCHqN>%ph{@n`ZXTN!nW#endLf*Af}L3SuxbD;TO< z-Nzcb5i+e=S;;ISZ?BQ&a&3DY4;RbqoS`mG{qma7317d)vy!uax!elO3|}pwDWzrE zbNRwrS-Oj1H1UzQp#O$CixU7oDFc_q>LI{+aNUNtO(q5iTOLF+`T!gzC^c14`Rqxe z9ba{IZ`GHcnzG;A(g}nD>3BKACZr<7C(q{bPG$E)5C&oo(kr5RbCcTG7zh|bcGK=m@9shD2tA<-ib#Z>_(uTp)K-n$iPq_#C*E z)=>#$mRkksMzl~U$^rnFi{8Z!7$A{x5ZQ2RCX8i+OmD7E;`4*{!-MO={sV63wA!V) z{4<+Y-bGdE@L=hPf{bB!F@u_?hHg0~!?(Vsj1xJ4z_x-j&p_Ks(ZR$EdHk8-E1Ki! zmS6>7@U{7mbPaX7ybTey#Dzy;HsE_?w=G(xlE$jm5zH13WhR_Y9|w>|I6_RoU4ra= z`Ggm6f~?&mQUcMVF@-W4>3vfc!GQC^@-z?ZqHsp3-ZHhM{BTb)d)e4|9e){^`iYU+ zvhPHeB`D|}7}$%_q@=}6LYNplX%qB&YJk4&D$S;amV{Q!Ve17H2oT(Xyj8PCCtStM ziob;llVXkmH^;c`{lGO>|8?=%D**U6%(ELejD`dHFYM6aL|+sY8#oeK4!COGR8993 zif;Bq&wOX$JSKNWBQYUWGXoRzCur$SQjwCy^cK1!nKP(W^~MTF^V;W_W*jhLhjG02ZqP{Ji|bz-G7yDU=7eftZpD zg#dTuUI5F8{T6_fl*GYJF=j&+<8MoKiR#3{#TB%qp-;6smDmQN)pL3U^w>;~137kE zRf~v4+ZcDnZ6thP|?27Qi_y1Qu`|&deJ+~KR=%qXumT}Aq4{$s@OxM6Kf$YDHq(v2m{0^4=Nb+fXkbt9y@sqkO&G@ zW94F@b3mXNOBGnW2D~CNuVxur>BnXfqQ9lAAH0VKPF$m|cqWu=dspr9rs7LIpNuaX z)SAd*H36u4Brsw!L_$-DFyv?6-Kk$_QRikAk|5Jkq`VBd8y=7;!3}lJ7|ux5&L38S zbFGpnf0nFeQX&6cdvH)O5%}fKsh$#l)Uevfi^$mUWmWl8*@g^CCa+DOw z%>)aZm*2(c)s)ZXZ+xf(@IyGzFT~QcFaSI;zq(qa*C zd9Z(zL#qFdybwdH1q)*goIlBQ0xy9hQP7risG6{V~9t zF(8^5R|RxOI7r(`5*F!cPhU<=U7B3{kb8(g#9x$QsNA#5UE|zdK1Y8;J)DSUyQ7fy z`L~$_&tdLNdWY9JPtdz~!6m<1BesS}u53L32wTOE?0#>(P?uCC|D%Ogmv$;v52PUE zII?{2V>MYS1oGH(nTj_%##bZda<_VVw{V{bWkq3g$y>@+ISc^1U#A2Xh(m2aL{+>J z#kR9m=R1v3LM}smw7h8`;!mHX2;sEmA4izFvwv5w4?#~u32nS?);(ycVj=aR!dZi4 zatErWN7lo5t(et|Dq(H`Im^y!ErJ6!C;~XehKC&n&aO)!q zL+#&XMpeDZG0ixx=H{UB^p}+aZuL+t7m+cl+HrWS%h|Ds_rN3p(3SulNp~x!M23L{$PN?-Zps`}@@=z85 zcS#Q`nkOdZ)(-JUXg@>)7(`T}F4xfFW4m1KB3q_I4+Wv!u`S_YnaoGYi!cj>GVg_! zIt+lrL{n2Je%jW>#MErYzR9Oea5(<<(_7oh965`yLO%c4QJ{D}^EOFW?<(o=@1JcJ z(VV1DTDs_Qw875-BzgEJEOn9>dqHidRrD#A*ps!ueTOE>lqDO%-Jb<&H7KJV!Qs*9 zqQr1C?3trt7Lgy~SK6+upxIRUS&ShLs0fR4aXJ$wj%9UVPg}h=ts7&i0=l8Y(Lp%b zypeH=>=#6BnSG*{5PiqgxYkq#xPyZr1X$3Hk;i6E@_zPtA-=q%cd(1IwX2% zSkTeW08kke3g+G8P@Y_B00+?r)mlFTp53?mqhyLOv?7cxUJmez<0p{Ck%xm=ey;4` z7-h&ZXxk1h?!0p2vx&eQQ{jv~!x+$#UCeJbD{QNo6AKqJKG@}huz5N)Hr|L^596d0HJ(2+F1 zN5JaV$a~{5B4q+%5PFn)FpA8Jt?JtKgb6@E=5Q6rKzcuLRpI=9Oi%LC;N~R zDBwB*>(UJ^9=1bthrw+Vr`9o_)->+NTF~Tv>&vIr^C{{4LGa9wDs$$%7a~^oO}X<@ z8py=zhE`GmNKy&uVn167pVHt}7f28^b$h1jft;=%c2_u9@&YhoJl-f67TR zet<_RldFWmi&r0)%VW2@KgcKg{mrac^>Ld9FNEc$yWHb4MVY1~w{GZQ-~P0-O25Wm zxEjhyS)cS$lOHRL`NbA+h`%$8HkvT#?N!vPkV{*_`V5(jTJXp14MkaU*aN9(aKb;R z{k%)u8KpaXQ$DfJjPi>Fr41+=PXwuYBq1(D3Dbie8viz3D~!)}sP+yuh{}OliB2iS zwfUp0uldpf*1ju~+BuO!z_aH(>fCUzdV-ugb{tamb*Qz9Ni*niJcOuE$ZGj`^-_NX>~SDJHi zrwEbVGN-2EJ(sUUFAv-TZsP3zfq8TEuHG2u5dVB%w&i&8K=WKaKiBr~5h(|ADQJ)I zIX0+suxj{=+Ak0Zl+|QJWokoeGQh`{B^RqlJlNq=mWzj4LABJ@2Uu+hF1_}b{6)3y zwF1Rbc*=K9$LE#O2c9zGQv{QB~xlFKXj`E5UH9f!#UU2%E602~n%mlui| z3p8{(J~-3xDRQpC6jE1AOtg4kIH1y{&xMy>@zX|(=`rquXH$U)9X6%UT0B^)=&EH) zIxOu5OLdkkfA_Yt83(s$O~{I?SlTf?nPBStTAi#K>4BSsZ)bLV*_5BuKjuu;x z1=5{+{Y6=DdirTVLOT3Wu^I?|n4l-X6Hgc9RL>G4LFF#OOirN3rAPYFN|D;asVZ$P zOX9Ou>Ttl;7h8}4i=Ny+2pp~WNdCAiN!Cl7pN*=%vMYzsF(w446%768qgZokGW3&J zcytT33UJMe&u&2N4R^p~0js0=z@P1vjKF;`h%pu(NW}v|rvBT{P6OTHWw`>Iq{F!S zSeA0=fV_S2G_4Gj=Pj;{p625!$v3jl$_m6N??m?%qWMsN#ut!1J^%PyS65YNZO7WQ z&)xm>8AM*>+K>WC&k^r?{(>_rNgQLjdRpf*bzOPcz;4_YF2skarAo0 zSXR4KeOOd;xa8834UJ%U4JCjacOk=0M>q0p&rlQ;eb_Y88~k0^58hrH7r{kLOq3w= zd61gsQz=%KU6{9mc#ePA09&`c_teDvf9Z+@1c7f!H+(DGNv3mdZ-f2Gg&~(2wOoZO z`<(1N46;g6Y7NC-`0iETx_4o#{n1IEPHu3)SgMlh)xuqA4*~R%n$!b4W47K;#bLtG zpttDk(|Kcfb&cJqIbUtB%90-e$sXRAHnAFdf@op9E?3ZTF*wIHH0%im2^B>;pUDXt zW-^mgH~M4_9Ku>W7a^qF;KUnFuvt_dPx}P9ZVdZ+_#Pc@`jQip>t^c1xeg#*cyUKw z9QLM>8JS&fp~4mbUdFJ)ZTzsJA4mnm31hZkXQF>uI_Nn4D@E%~Q^27EH=)B8&Feys zUB)4T?;?_DNO%f(m`>$Y7N3j9U0lR9V|;#(Ia16^O||^_?wuNPoUcXsN~pP}*F%2s zi?-P6rKJC5;W1`Y1pw68*wOG4QZK!;z#1>Gb=rDZ|4$&5Ths19r42dS9(J8#+RH)$ zl@#?9Ux)KVWlF}h9dF#Wm8tXvA||5J*w$}DF)?cN`5KRN9VWc00`k*lY}1XE?pE0n zo+~eEt%xUh`ZWj0Lx(X|Qvsyi0Azn(?O-w>06oU42w8+;*I%$LzM?c4-Mu`9EI|dA zT@#If$QKOHIFOEMY9*&OdH{hC4oTRPZV+rJ$4gDfc8&(_>L1#t1EO? z11-Q#lR4x{^H(Oyog+<`CHY0l_y~w??4U7hi~^gx)ohaa1z0kj6oR=%BAr1K5yT}8 znfsKLS}GLe@AgBh%nG`2J$kYxh&g_9{c0ePbhDerO1tn-BDHGV2F#)LYxq zsujIny9px69M4Z1V=?YG0v?YrI!FD*$*}qkcP05llwYyx_nXksS!NbWuqTi6; zGKekq!_b-=feOANaCdY^c9CEzE-mGx0Ko{Ii|bdtM6vs~J^3tHC`^W`{b=Kvb&ZWHm!5s0pT8Gx(@uC!#J(EsiapS>$9y&5FF$ zL!FLQ%7Ok@uEUpWiX65klhJwcvU#8(c3Yi6t2nrtHwBx!`>j-8KLFerYUhpD3=t`+ zhoKl|7lE^X@_8T?8>9_K)u58bl1`McC~t2YQJTS`Rj|cl89g9oW}{ZXD)dt^0GZ&N ztdw<7^U6!2$D>DVaH9Q9oT`{35T3K!XsIO*`6~~iQd-$_Gc~DP{>_B^3?C3uEs0%J zhyDx)T|L9Q1yHgJsG}_<(({f$QxyAIHur@F6zHC-hsB_ulfxTiRzvJS+}Xf8pc^nM zW~9ZD$&qNB;YVSyu5*HLi6rVsahh)lB;gL@^IprVe~J0h-Fx>9%$=VfxcA$B>;OIb z#Gq>e|BFUnrn^;KK_>?Q=l(xT8Mr^jV|qjwkR|YKq_7y_hONjeaSe?A!6{C57#xHn zp5NIc$WVn?ZhwmHm?!9syUXwQFwsJ{V2;B0 ztuc1eMAl{BYNJa=hEEk?TBZkF03aWSH~VbDdxyEfvm_2T-1oSDtF{ppRg61$b18^= zfhij`Hu%3XpRkW=AbOnxuEBh3PxpvOQeH5g6iK9XR0NC|t8ktLxxJqLx@g}2#|P1S zVxO~_+RiGm{hbjcejrC!yt~6?akH)if*&}h4IBUI9bcRJA>}hx4SwNu*W)@AyvXY8 zk8zQF|D`Jsgnm=Hp}BFVBk%CRNlQPGC1AaGOd#0QjYx{eVbPdpLK6TfAJv?9u_!*> z-1hT1r)K0coqTI1?iT-SZ{6CZ>T<<4+1cybDWuYA{;GvJH(NXI{5SPYxOE3`c(*M! zT)*&wbZB9tr(^^CdU&<}wg6?qFAeM$&Ss+|cqfiw;?#uuN*KRDBWe}sh^ZA&?uvvy z5ni#!lFL98rJpp@d+W@q5d)KOmy${E4;AdqNgg==!Z%NOteld|Pmij7i#>x?zm8+E zi7Wno_RGa0;#6}ubjURp-ipE1Y4&I9J!-iv$EORCyU7@?DH>!6qNi-&p(KI`j7oVw zf(H=r;Dl_e(hU_2JKc1Lz2)saA4x)~aXz>xhuT;UC`@{ry!7yP6n^HMIFs zNyu}9)5^3`2X;h;nKO*`6+{WOTkTE$X_aJS5rUHv!#J3k6vzvCOpWFQ|CR7|SM3GR zZp~>UP5G>HJFU5SvTkpmu9J`Oe(kbz^W1vo;UcHTXAja$3Uq!U5QB~D7xAE*?{jaR zaM)_LT_ipdsIs%AkR^E7gn<^G2#O0-hr$_he$W(va!iG1D-8|cO%Z0rbti8=Gfdw+ zcs3;*;=V4~&~ULco>%4HA=>6Pk)SoLnKNzpKBss{_nWgjo3Urq`?MxR_qy0h&l5&q z`NGvSIfv{fGY3nKk01nnleL{J{|05L* zL>ROw*+A2>GeLJK+TJIl;>tEom7w42Um5x*jt^sgRP<};Vd%J#q@wv$C-d{K-{pQA z%{k#xe^@~dZ}@%Tu`y7Az zPhNRFv&MDhS8gZ+=KaZ&Su0~6)07%ucnT_|OV}K85P%g06o#nE1>xwJg#2dVV6kRU z^-%S<{^_^%C5kF;H0Vx1V9+(SP<)mlFy%H=NgN$}62S)4(-zB%NR z8P?-DWGj-;k(I=j2@JliBtAqDu4=6Xa=oPcm@uLt1gA^Do7Al|@CjEKD+ayz&$B_= z+pCfdxg;zzd55AXQXflFMly2p9^-%y-pH4?(3=_i% z|Dg&O%LU6AJt}AS$&A96c9H_hoU)8q_nzM?VIfi<3ztQ{{8w=KDuH1j+U#gRRXf+y02T=FyiBLiW9+Y%Ts#Gh3HU7 zkE){;!J(pl1~0*4;}I@}4u=i$ZsmMKe9CY)&kR&pdiv`mgL(`)f;@C8WpI%qUHA9+ zq4lwjomS9ey6IoR^XSz)A~33NvblRKjKo3DS>b} zj6_l^J1O-21Z?d~RS-pn{^PZ>3nj~mfCieq zZosn(tjha?o6Hb$q&i4}<=VXxXz7WG7cH7xRW3q}Nuv`wve4++2i(H(LY1H~jB$`! zU(2#qb^>3Bs>l$S*M`J442=?PQ_Rlx`*#a;<4>N8mf#;9BTuu!A95TGi15#rXhX@x z&R8BNDje!Dnmyl{&nG4S6Nf4HxjoMZl_{UUQxEQ=ie6fzn`~r*gCk(fOg^qXih9g8 zGpQw5_@}6S-|V^6nuTsd$W2*%mE`a25|~|}8M(g%V{wzph^<(DV$iEGNYFYk%DmJf zAcuSoNHX_uzKmzql{BS!dueTI1&%gzY<%@0yOo>ltQ! zAA6SLs7(@))J`L3?+Jeu0IYO*P9+B$maN(1C~`vwnDF!wK@X&2!XeeD{jm6ye57+0 zMOE*V7?J*IYStjVqjy9DcyB4d0=Pe&qxe2%iCil`G3)BqAT~hHRLY~~dgBW*SbPqN z5{%(%+LFCyme(Q-7v;T+ey;t(YE7uMOSf8CK#AW{|LrD-6+bOzoy4=U6c$&wAlO5}WRJ+OU1>{*A|e-yG{<8cmwZ5h0?%HkN@-Ag@x(miThi_(?ZH>3 zhRM<>v)UWSJa4pCjI<*t_-DyK#R?dg80_ zz`P8EFZA!rWg9gWO6%MU=y`J|h^IxoO|FaHoy}~8R)|$&7-JCnzoT<}0D+Nushj;+X zG2K0r;;tY0AN=oM28ckl7Glsyz;KN~B%`dsmKe zt#X0Bc{|bL8$qY$TK0aSQP@?MlHWBOPhpv*uWFmc>uC3|W&OGM8t&%jyse_dQ+LHu zJR%q;4cA;39O%pZ@m-rQQE0zj$@9q+D@#@i7@wCrB~n?WG~3DWG6>})IOU(+_S3X_ zoSR?&!f+56`Wb3>uvd#dpiS)&qa+w-^^oIeK@en-cmwmraTCJnvWG37lqrvh*nr3S zm*b+Vz#JxaG)|H`opM-4hwXU%M*E{_K{6I%^yF}w#vAU8rN5Q$SI(qE9yBvh!Ivkh z^TIgU5Whi%7TZ3JG~}Q8an%R}WNGF@islBDUtGYHrlDYoO4%;JSisOCg9NE&y$RVj zbacT@5Nj*oI`8X`)4zWD>pb!q_4$fQ+I7y+CF>(|&xP7tosSsg3DQf;Oje3VAs^f} zfu~>U-74*)dGW|>ytA>zTpwv(z%TzN#}Rf;OP(=*v0X$s_0|j2R|tGL!}3-Jk*CN7 zjD&W?`M#?h*Iaba+q~msq}!e0)wBQSNUml?jOFhYA4_eEfhRD(@6XGUvJIwELbMaO zDr0PZes|Sdm+?{W>oGoisE)H|dx=?JtrZITU$N|rjBK{BFain+2c@ERs=^pe@T&?s zTPFtrxo`t+cyZ38ZJUFkLU_R=isD7ADxqlGV!7Nx%*4gX@6LJuR*&EI_jeS$(>eg0 zsB1K{-apkbTd4|Imo_i-a9XOU^ZAEfB`PHu2dW)(tvG6QqznPB$i!jGS)k}xV?CQ} zTndvtRUl@yPO661e7krUKh^{P0R((FWPeipOqOt`kEXJ>5=u@WSUwz;1uI{{#B;+$ zl5h3020kKmRcOd!7u*?o=e6GhTr*E6KAV5y@+5ooq{^XST#AZL-AK@5QtkSM|83Do zJu?J{c;GkbC$?V#*4j@QdU64;qZ6lv$MudCiMSeE^4#I2Wj+)?i-SDAKn|Y5Y79J+ zu;e&O={?BiKa|1jFuZO-X(QYo&CfaOOPw*rd+LLq2fRf@V7;JJa~s8%Zd3V7vm`>o z`=Td*Zb(Xb|4p-=GarKm8v*WM34A@FF+1eTCOb+(@O2)>lBbl~cvoPFnXWzu!sXK% z6d@Te9K0XVKk8)})fX)P)h>d%V}R0eAP5%TMjPvSM`9^!+o@a(DfZ7CF~SD095$)( z(1zgSiqTYJn6Y7yu5YlfSg6B6ySnx9FLxWFvaIe05{*xJnf<=+?6?+$ICS3 z)4DBlRE1MSS@dTmL&8-x({9tHZF25VVU`PhDeH~E=EbvNLPNOg&a;^53h4cQzoZB% zp(J%$w!-b2^#@?z_2Bjxq7S5k;o40oQXN@KT3RZRWw=PwJ?D$aMVKbom4jwDFC~{R zF;2_;i|&Cx4HUs;A*=a%uzZ6l!8OJ5vM#=1hrZ$2!qtkXMIs;2_l%`>J(YA6Qt8-C zR71&EfL|NFmi=_YaA-JV)0pF{I`8Hp>YUN9Yn?oo>sKiT7M_igLu$G9s;XhrkS+!( zji;o4Xk-!zk*4S>W)9|QAtD5HmdWTm^-d%dyCssnk z$EkeY-v<)(1H5@8L}bIIpMC(41=zbM?S&KhhbS?UAO{vr7Hw~2yvrW0;1i6AOD50_E*u0huKf+m8 zX^KUuv&H`CYV=t+b+o^!L>>Sn4Bd>s*g`l|EZ-p%f?DdZGj4m+r2?v$< zjHsiuQ|W%x5!T*hSh07VW}%)90?XNhMe`zh>+$jtN6zA}HAqVWHSvKGo))Lb>w!lO zXLfWM*1xK$7dTE8S{^)`3a;~dO#F<7w4{#4sl7hOZj&sQBX|i9yH9Zksq50 z-`}TP?5#|nE-ULwTCpN884hor1vx2V4rDV?VCt3~xMDo)PXc0;zn*8Po4XiKc*<>B zqj6wCH&*tiPAy;R2h!L4I#}rp!XdkD7-Z+Cy}+px9{fvMuVlU}1o-ovbe4@0H$Id~ zBfJ1?{ee_2?g>M{1F4vBLi$P320?<743 zb+D5b3Q@{C&OScVZG3QO;P&14)Y+>?B2tUCDN$JBuV^(c2L2*6;^y| zI^G|mU~mp~g-0aKD97EEq_cbT2w2Dz7wi$8vX2&4`_kZ1!%{Rw$3JQbOEJ?mTn@_( zmwDwFY6W_6+W3!0Ka2hf3P=BxdTLx5ZsK9%`32F&P_GQ3sKgJ6hd6(K=Zq3m!25tu zb>NJ7A=Zg;xP=A_p;2nrx*0J_);PB1g>AG0% zr|viOSqvX~$HQhCkCfK+4N#k<#hRqiFojxRP)NXPH|au>h!VbhEsJvBih!6pd?XP- zmp0u8*Jlb_fD=riA{7NfU(Nxtr`VlLqi7sbfypsz?YaSM%l0(qy1j~N@DWd4E~4*w z|J-gB!G7@XHkPdQV3*StvWyfGg#D(WI4fNVm-`j-3UjM#DFismFs}1up9&q|CDq%( zs@~H^byvC1>I6awhC9C`d~)1^*d7_3T)7XhA3lfV@2U~V{55Ubf3xPToYk=XREKfWlQ;%v zb|I&?@u|a+uwZ+15q{QK`NQ3u(SRAoTDT1_#h`}L2Q|l524ZTyB4{HorEw@QGOJ9O z?df>%Y#O+>OuzV_7Q>c^KM=8ar$xXVe`<`$ zEl~E=#6!CF<#fD_v!t)aX7Zw2-rlEfO%u-V_0xH|+4q+UpP!~>=8QAy6U(*f-_Tz* zAHR=N0!#H$wAEcoIx7mA)K7owdKrQm4d2JqZTX6dqEo!xwYpuk$vne&2{B%KIoXb@AmiuH8GXWonNH` z$W%iP8?gjaKRsFqXvKy-G&ODf6R`IcQzO&pH;;sZ*2EBdRDx(qd79|s156Kc_vSbm zIQLOHbMCdbxOPeV6OPFoPrBCU47#4EN5B~e%7U*B$z z_TmlN=Ni^5x|(0C`B1rBR!GM$5Q5malJB2Y<=vo=M?K~ZRxNsCtk^rs)R^*4#to%K z)Y^u2_73f!x_mgkiHcgP>st*n<~EslMmN%s24Ro|dwpd5soAdx9jC&p`B!AV4a2$3 z*xk=fN>UMog;i#|9mKUCItFhW$($d3nDVkcKrZgaE5@QS^vcKfo|5uHX1$ds`ZiHm z$`-UbA+a;(`75AC=+7?ZMxoQRmGQ!u8V}pkMpf4P#RtW8h#=eMpB}`j}r@CHh<5* z4!(_|kH16RMY`3vHu_5zlaG%57Dm%0zxKj{sry)M&pW2iYVMAQ7WvrTMVksWtooW3 z>%EQ*wlP9oUXOHafrikR`9Es&{uI`Zh#nQUQ9`E`At2xa+o|EotO;Bqh<*&24*Vv1 zq-&zPaJo=gxKlerLgimQB0N)=0LG#DqcG+FibOq-RT#ZA{|^|4YL!USsigM_a(=Dt z!Lb?-7X9s6+}b7WKXY4!$0_%%vIZs@Fa{UqvWE_6wY(7Od5&xPU(N;*Ii`y@uCSL@Wi)Kzb-Ng& z{r*V#uT&L)Z#BCIHu^f_?pFS=f<^UEu#vndVBI@LqPjRf`WbMV)M(I=-Mao#{9)C* zv8gDbF5d3qx)EYqxIMO`1ytSVYf`tkTB-<>ZJ=%%)Dwa=t!^VM{OMW=$!v=UFiq^jMG6k8@M5c zvl&#?XXK)Ng8BpVFQ_ENur$@V}!%BCCh+HryG`=V&jf^nhdS+}QkBhKc2XzTVd}nX4b_Z?|qP-`o(}cSv28;8Zp;>#4KW$C64?x{2KW zmR>y6RGWS!w%^fz`xbRLa%}#XTd}V~EnozuKtO|_b0~_!+%l*ng~pgtvO18jM3m5w z>}a3VK{2T)Bi_5Y$=doML{F_;rrSu2+jW-Hl;>0`Qcl0>y!Fei6NGFTF4wKT z`u0nOTezJU#ym{kfcX0NcR_b{W}P+w`J#3#kapeAR5nIT5wwsw9Vh5vAY4i3qO8DjfmgEG-G+WE3Yl>9uaiz5&j z>MTunrha7U#yWN;{;LbHWr=cw(#KT+&iU$jxNEP3Ozyvm-9BAX@?1h6+|XXJ#XLWD z`3MoSJjt#g%Yx3-+}BZ#mbg2_Oc?r?5u)E$(MsR(dyte23bSz0`Q<%}`sz-AL#!Zm zTW4{acG7{g#K6UKoF53(FTX1oh7=1-g@Q@?SQv;ZGL%6BzX;g z)oo2zN;aKs({4KZRp%dBje0;Gh0*G3(R4olE-%dN&8lB*lg$D=dvP6cxk8WCpMv3^ zFfeiyc_s{m?>G>H0ZCk~CIl1PLWQC8$%#(t1}jbpcCTpHtARLq5}!Rhs7jZ!X^`o4 zS|+`ZUoab9jRrCH;n>&RaK3M&vfPGB-g4Ud?fR78BQF3bUPPLIbh=kSz9(aWJ+zd8kxtRnqZ|aKlc^skmy3u@@jSYM42GDuScsJKL1WJ z&A^RX)MYZ|pGRotWTxE{qFk2I(3qVxwWaI4zp+a#u@P_$L!=-zrp6y4h&i1qYvbqV zF4NBqHHbtOp01_Tk8>@U6$X)eg?e0DlrDnd?=?e?>aRTJuO24y0HD*0cx=p#ciF=A zo;eMtGFj#7)?D~r)^dgB`T+ziID`f@1kcf}>CXL6$0g?pu+W$av2`90v(Xb1Ob7?~aC%Tk*C6`nINTIple+CxjLII?yX`tf`>g{jVgX+a>~NHo?a9akQ`<>Jf|! zn~~Olid&+4BS8QAy`oXIqCC(mb zgaZra&O5FID?j-lEl1Ef>E?xep3+%!iG^I@41OQkUA*+gQQsI%gQ#J)!i_dvNu z6xB&1+0kG_to8#a9fuOLaH7aq(X--<Zo{NV=S_pO{Kf3=V}=#TvO#0k=FzHVeM zktI?Unhpva|7MXJ7?-40SIjx6`CKM@1>6-IxjMzewX{lL-kI2e&n?)2u@7CmE=zSn z6$EU=giRwHTC89H0|7+D@Sm71>B>21uczL(Jit_7W}>o6>%ysszkqt1T2;=F%m0oS zhln5?NRq72=KfD_I zr=(Kz4e$RucjxZRCC|(Qtl7QS+P{y>e#b589bSC1``!<`jShE8@mXbhnwl0g6p|)$ zcq*C2#>dr9EUW7e@c&;0nm>bEtE)44&OOurN}Vd&zqZKsZ`lKt6^$a&fNDoFBZbhv zp8@?S(nW5+N(yXkb#89xx9!83u@CdGSO-;C-O)W;NjpA!Se5*H+%x32+BI?5nYY3@dM*d8)_ZcuQEqnI!239~`G5*{V>;!6H}RI8P5V z(+OG51H%V?gl0AO-`8g&ORY4vy?{UfcpESUK4lm$+=ln6%_KFdZ`+YWswsX7)wCqj zNr#@fzk2g-tlQY3V&y)IBsDpk`}T6q!%6F0AA0CdE!k9ZzaSvY1H7RBHfEAk?`V>` zHZ%u2>LX>LB_%O_M~p*Y4!1>XLju`dwb41=KUVli+!n=HLb5VsIB2gb5HBKwk$-tx zGJ`Va%k@}~N+X%7b{tbM7#pn`Iimay`9#nEF5LCRB}WujD~hz$s&DDC`V{C;F|`VemL~M;?LRsOeT=iA?d@PHffQB#hBrE z->=IQc`my-BSo{rDtqau3Ra+id)*OMLwf}o;-1^?viGnuceqNm6bE)#bfkoTs3Y0I zD2*K4z}9(4W)=tT<|9Bb1DC{@%pup<3871WCe5|_sq|(1Zq_ACSFQ;o57SaBiUt3t zz)agoN&R(nwDI2P`pmi&75I*!xmbL!jkW6y_9~OhJG>40`>qaZr8gs8f~TwSI0HMc z#aaAfZl5UK%7`JI@FEjJ0N}3ez~`krg}40w4In&F!wl))LkIc>RIh*W3!tg72c!4e z;Y|~dk62{6Hhlbsz_mv>b&3VL{xC4KH#zIx^fUdNw6W!CLRW?T)%Cj*OO|CPzx(Eb zmJG!JFH=Bd4+;yfta+xTqJpfmxPmt2E$5?^sooT9C_QuxS%E`Ek)4?-7y%o%rjB0) z78_S+ERQqNP|PUQH%204GmxeVBpXackC2&+=}7m>F9@=1B2TdzW;;_vkFcNkvFadK zn*cjKd4Ct1(H&6vzg&6&f2{g0x$rlU{3I)WW4Zq^IjLc_M?(c8n0Vad~?#wcuet%a?hmWU$ukI zZ*OR97%g94T}6o)tW`E%ZtM?>%X14e?AfNmLsrOc7?(2%@sQUw1U1ZP`z>^|OaC33 zQhOHA+$t0tj>R(=9Z`9BAQklPqox1&U=tyg390Q2gQ{#`NJ-nif*i+p>{)+moJ*MM zJrtY#>w^k2FRd>zIZoc0B&M2+_2kdSNNE^nlZ)2U(34%?o`bMw-TqL$KV>MDWQ`~YquE| zAQDGE>(bypQd@L+t0AU{4yV7G)voTtl7GjzffTEex-1}Vs_Htum`ry zW_<2=4{|=(*TdNi{L@WEvj^6lWeSRcfkDR#=P)1GicII1@J?|TY{!h z9ebspHs)I)o8RZk-B$8A5g~c)P6fZ7JQ%pz<})N~S;E_)h+=YJ@)6}$B?`UDnj}Y| zQ{5L2c5QrE*&$9j|D{R-zPyB$uAHi^^IJLv;gBM~c*4aDe>5y5%q#OS46;k6XoG9; z0dIG-gP7<-g9Jr`w?lP`jy(hLff2|co*-Nvy1?gGc3niAb(i9}r`vh(|g(dM!$8>Z5yuriMahlvs>tvBOxT0=6n$0={Q15AK`1_mob# ze}O}UIkTqqG$WuC?>;(jb zfVY7!aUMRy%YnN$<0Gbx{%d7uc;7$+?Jrz>2Kf;$q!tl=PL!ync)W-LlZ)f?y5VzT zdP2_mbEi3-cf#V>;eG=Ihd*2x%U%zgKJw2WeDw)W+W71^${XgtWylHnNrom0132{D z=GIOrYx|r^!0uu9zDJ9bO{tkACDn)fjL*O2hzmLmDFV___*T<+N9fkr)R75k0>M2 zE|ggZ`)F}Q8AcQzq^Fr0hCoA$YLPNB5Wt4Wm8Pf2N@uV;$Tl;pT&b+N^R}R}Lh8HA zr%T>MA9)!i3*JoBSc~8=>fHya??YZCLKDF41<9;my+(;K2O4&I!U>zOybz7WN-! zC5O9)sq2(9y9nb))1uP`VXs2>b14P1^LD$J)Ia$`Pv;&s79eto2ZOGBT+R!>?0BbW z#%n3;>MuUo`}R8EW)&m|XVRsLeW_k0ZpHgN5NlOzRjTEHffmDlOR~4{U6$x#8n}EB zfk0opAV`B?ul*OB+l^Jo%fME8geEY>d!8JV6~yg|^eyLzP>40*M=lxd^WwALXvA2- zPchaV8gjbAOw=%AI!0(j@ir{iO%^hQn1DouMij1jYCn$`l7sUC0$usOo()=*uH~i4db5!o_ z4c^TCiWAv{)cd!yX@Vv9GO<#zmMXrdj!vxvGbo-gcy}DKEtQ(4JYsg~yW>$P26*C= zas6X%$tW z*b15|K|@x19Y?mx>E^k=rhZ7HcW`V)cD=R>{&luRzEMkviv9uu5j;gEgW+q)!{zKf z&oZ(cX6(H!e7b>S*`S}vdW+7M1wvWO3S_n|uJhX!Eke<4UO$(MwQ=^}ycWz?MgDJOvAPUI#%yA6xva+z6lpj!V2v8GDGldmqgku77D0 z*~+3B1MI>Z3tB$Q(&HAnnF9VfY!~KI3#vy6FREb@Xl~0BGU*OkP`huGab_*&E}K~Zm3Td`D5z{MwtX9AYSo7@^agp|%m%*7I>HewA$bY0miZzFk}EeQ5Pu zwowCt1$UcdY?fZSA?(@Mp-Cg+NQbR9yVJ)DCc6YvPskMzO*F)%*rki)#S6$lv2~b* zC%L&ccC;ua5NaTiilK;n6-QLYG^r7Y*?naM50^VJ{6CffF#uDH2os z4-RK#;imW*6zBqJ%&rReyHjU*?pDXRouj!s2ev66Nni3$rTxAhR4?kW0&t$wEYnH> zPM0^2mmjY!WGXERdOHD3yc&JD(T4)ln_ zhjkm*d*upNA*Cv;+H{_TV%LLbE&LCVZyd{tS(E* ztzg0e3*T?K$dAP;V#x@rlI!8aCPz(8vQ*m4^h~FqAtT4mbW&kqaQiY!$jx|#Gvu*WC$l9EJ*+!#Pbj-L z=z}C}kc=pqt1cwAz?LHWv$Hk1ArmoAzJob>A`$`x=d5vkM}%^e+%Dz%KX55}k!#0K zHM!cYem$#+{PNVSB!Aj!iGOl%#@pwS#r3OZVhz6@QRZ)KvEc&=b}ZzWI3Kpse@DAd z`p!9Md+2=0hsXZalk+!6Q7O_<B)!6c@KujAdw7Peb(4M1dmckEUoD8bkaWpQ5#r^5>T3nN)iJ z;O`8oM@-igN|)x1L_#l+I*%8+&<`pk6 z=;az@LTC~Li8-Wc2tp7jN5_o(?3xn9eQ4OWCug?<9$@LtszBWZ4@rd7tan|_A$sl-Mt*sQZDOp$Z=8;JTnrP|lmcNB)Zh3Sg3ov?N0{bdyeCIf@;_rXRZ=PL;Qhyw|9xrR z$+(W#&I&(rDV^&V40(NeM(D`*jz83_#V;VB18@yi!6yepv_G=T{EBh;{{>5h6|f7< zQlrb7ENGTV%0?zljdcdIOKIZpCOb|jO*)JwI=hoOIcJP8c-^)`oiQB2dL7653)VxO zv#s~Ozius}Q(^^ii=th#+s{2io0kmrpY!Am?6*#}kYAGi|iRl1^nkRa70P=@GcxMtX&FvJt0j0!*mo#eet zfCrkFO*RWOVxX@YL`KmY1;$q$=cy>Rd;tLmfSa)nJ~jVNJJ({<3LgPm(9>vF;YaiicZC4AG#-^t6NwPaM6RS>FLYIx|3<1}&SEl&~do@a*9R6ds? zX^}8lE zt1yAua&)Ey-LJE#FRUlol(6sL5zD=_voa$HozIM*8wQ{Kk#dro3pNykGzAMM-r30d zu9wExRYITpM_7w4kwPS8oVg`O`-$ibts-k-RQX?*Nv;SOJ_It$6Ood9O)dM7%VGZ$ zIm%)(y6)aX8C5Dtl$=H?bEKUp93MpU>)`j3OE#lU=bj;g?=o}lpVgDw%`Q}}2(VBw zJv+KkaQd;g1F)^D6|VLUtx7VOEpn5gS7xP8u*7h;S!IPq7SFV}7kmWC{^sPjL9Ihf z4V9`2Au9|Zn%Bvga$D)Vq$zt7L?>AyGE}9EOh?;xtOMt5qq?A9u4n`k854OE*U;ooT&& zdNwvC;7B`{EYAnL=`H@nKEf%#6%W_7)}#{pW~ z0lkCG-5rh6yPTcyVrlUOSfJVb7vlnPL5Fb59^P7h>GCnf3<;Q^5v@Pcl=J`z!SB{4 zWJto0XaH)HHb;n-=UfXKu8kT46(=`Pn;9SPwS$7kF29wiwYjIs{LWUjcI}Rhbfb&M zuez)01U_WO>mLPQ+rs`GZ<12tNcQkbIA^IA5N-yN^XI8naRrREgc?RH<$HI*5V~v>m16M z(p0Jh+2zK_!trhw_qB!`A0r}^GkYZmgalv}8}B+KQkmtw7anXk;k}j5W~p5r3qBhy z6$5cRmO`h&7S|&a<=Th;4$i@s8>(=v2gCT*GXH-d7$FfL4>9pJhom5dHe3`iQfz0B z2CKFahSbzqpvg0|7CkGjs6|i#|2a5U+}>-7k2^@en{v8xGj#TLi*;9bgCg8Dz7Oe( zHkJK5&=*BnQf%Zpa3?ZG_B>gw$&MZ4CNDh<=nrAXD;OXD4XOXf|Jfd`qEsqK8nPEj zi|bTI$Bl*J$z}VS@5c5c><^1_a_|h##&MN$4TJp7Pvv;q_{_Si46hj+Hi_f;AJy8X zUUW9<4#?r&z80m}=A?W?p$8H_?;Tl)H+sC`+0Bp(_K#ApJ}n}m!nde^+%e{Rw-T9P zjCd8o$JmO7uU4;-;pYlpj%U15D+brnXm1_9G`MMEhPZl`0qk^b9iEs0oVxMKhr11n zgmrhO=dJ_TqmdZ`+JTF_J6puuFX`lGG=CeY%IWKN5FP0 z4ST=(c=EteTSb;F_cCpUwXOKjnVOnXA_5O|Bpu>#1931I)ZTDA32CKdAEE+<)6H$@ zad@eugHdi=L{lDxUOS(qqZ7L-IMYiK)*mNY>*BgGQcEl+KXh4_Fm(n z04a*aVzh1f+O99kaJYt@HPiQIwTga-nw0B3g`wKTCxK-2eI33l0-{N;! zmk)SQRz$Hb;vBh(9c7>uDeU0DTDfKR%dEpKe9%w}zLg*IC|0yx$Bzpx*CiI`)$l~O z7G|S^Mr6HM0-R@CGXXyR^_{lwMIe&lv3rh?ik?;=ZHXRZ@Vf^ta?5_WJ{9Jcwz$ttA&kNn~12-3`+S3-Mu`Lrx}iaIz&zdIlo z4Bc6xZB+gyMA_6qGk&U*D(r4^qa1oYaz4dCewC z7O-mqn#)51*3gZ+!+Xb>E=)_6hRTFxNrQ%5O><97PsLSvXu#sdH7}wVB63VAwlb5X z>DG6q{{$kq0XPZp4G$cIUB126k|=TfnsA4xJl(viUOkf|V^W6S|KvnC#g?4&*Ac(C zy$^-H&(2%>o>4-v8RH8~Yk5~MivRxj4G+EwOs)vQb}d1d-2r|MDs+2mWs#XZH9+U* z-*M=591-mIVTEyGoQ)*ZHuvdFCU5GWCb%iW~6XgCut+3o@|FmXj=|dG!riLTsz#;cX`q|KKS~> zBS7J?F&j_J4P8zQH9y2zM}i43F@&M%NbO3%vy*?rfnXA5w8E65jwQ~<8^yIcQ_wv!muiV2i~A70lF#09Ot+) zvrqSbAi%r)e8HD4|MyGrMIsuU|C5T6dKpo&9mScZG6Ok>B8VW_$* z{jGn=N@|p+gj>T7T{hLK(y^AFJrRKxSkC>LghsWbmK4QNm6k9Pc%jd zpZ8?{Hv?XyVtTQJ`&AZt9uz*RrX0LqR(KErg7L3j;3tX2hq$|>xz2jrPS7 zi}rkmvMG{{!C$>DV9CY{qPx{fceik1!}W7^VIt^^yrVx6FGK;&qRcvpSO2d#;l|oq zf?s&SghaizT$!1Y0K~A-Lpc={6maIx)=F#k47q%rs;W6)7OFD`X@_(Y6AovU+4!f- zhQE4G8S!VY(tNGo5d{lSoW^oD@Qu8?nS?pVwrTva&mq(cs7O`wB- zhI9%%NNx3BTf-t&4Rz`1i3%*HT&*MV-;gLy;d_4lo&U=H$Fj57piP3|e|jn6fLEYD z@a!;C_>KHO5Og$@s~Q@nGE{;5gNvAH5o#k;NqbIHL>hw1cqfiWc#Y!;s1eq3g^{B+C$w$*X2^}xf9 zxYIw2c$)&~C*s1Eu{TsMr*-ugbm&|t@$#sm{JS_{i;GOJP}BNQvihT67=;~vZ`7}O z+%85g(Vo{|`_{c2AlLE*+**~2>pUHjCzqX4X7L-=l%KR}{u!jI$F(n@)0Mz-ivC864ynBkMS>8xeeA@;Fq=D7)2t-&_fS(IqMmK z7O0}rCZmI4bZd`HL&q5MjfzmqSm4-d=nUbF)f}B_5>Dis-PrD`p!fLtME=4fc9j1r zpKcsP7k?#@ z-=^f=PD?|ACP$JIC6L(h0WzJs6=sLXf(WW=<5MQyPPds++*j3i67Lw4Ar6g=%)F2C z_I#kV?`q7S?Ym+&uF5K%4(uNG6ZLm*NhA>wc*??s2%>wg-i)oY(Qz&K=ffSbY_XZX zO6-WHP)Q-Iid!qVnm&o3r;n!)yJD+a<&wA`TREe**grMQs{`33KyEcS#-c)6Fy3Xy z)c$vt*{e#%+8Dirrdt|C0L~y&Ej4e|ag`-cRbqg*ds{*=FCf4x;D5pJFSYUTp{eX;=*9j+ zlJip<$a(@tQpR&H94)v)F_fKc_@bvRe;IH4Xpkgg7{KTzU9`sg8jGk7TQ-W166u2n zK+;wE6iF1HAPgPi!VwI_VFz{y1I{3zCnkLO?G^RewlZT)fu$$799Ho7o8Bwuy*mw4 z{C*7_}{nS}_iCf>eNyxl<%DNAgJgTT)<3(Caka@_gS*Iprh<68QP#+uG8= z<4`K4$S4lxnA&Fi$qY(`5G1B9o+um9x=lXQDHDrI6$Q27Jq)f;l^ZctvxjB7xT9N} zCPvse9EaHo-zqXW@Jy|HIcrJ=K7p*cC&ov|m;FByK)n=R{4r>5?Y|U%m}0N3p@Ty* zm)c&1Z(~@RiHU>_ldw?%w5V%;l-B1fMZsS9S|H3+I`{XciG*831S`XgN&gr>bJVU) z#1=aaeO%Ensfxm%2c_nwK^*nt=0~kxC;yc^iYdwuB86ERS>88!i;D`R!C=mv-v11# z(u;L9DamQhcrz8HgF9*(6RWRg0(27iwe|6aM94kFhB~lOtih>GpPpJ%#k4Wzarkra zV|25UxNFalgdz{lnt`MYJ_gAuSqBz|x#&UUb8*KW|Lo>EDsx#}JTzsCFevKhH&5zf zby`K1{VO})JHWB1Txvd>&DA<`Lq8GX6~W>U2*L0&Dp7+)txom!-q@%rg{7cW#D|Gx zxZXtal$i?Kcy6|Wkra`6hg4HpBHL9yz)#M-oLqjT_OcAnJUr!n0nRV8zy@TklWjwjI);i{_NIj>mJ*oboZqGNvJH1@+Z;3w+4{h6RUx{}YD};^TMOvo}>x*mJ(w z!;D?Dyp808lz?IquEpD9dc~f9K)bmzH#~({H$D>V$ciNXJIxB#BbU`MkR@-VNr$1& zH=ly^pm^2JREs8`!?oqP>XYQI^pWbNb)KBW5ks8Z)Nhl|i*u>1Rd!PihDK(o`z(Uu z+C4XZ0+~#{mDfi0W^luJa5#w?3CT>H)*L$F_T+aBMYA!cu!fBZuA9j_kHpZ@Ybvpo z$l@CrrHT*fwBnBPLOSeQ@}#s#`~I62k_5b}gvUjO`okCbN@1GVoMI|n{rq(p`x=+~ zW@|BVM=hIOcJ@}3U==}|IXcLWl0mwFqqEFS<@RlCJ%GV*UIu(chEba%m)p7YPo zuk#i<^NvQ!Nk0}`6%OnsI+;rCCMnKBx2`mU08CT`z{pM!tI&8pG(4Fg>NXRymMpY1 z-D)sRx&{JZ#0(<<-BfjsJXq?F49-_!Vl1qNo5DGp%u0+bCp6_C%uLLISmgj|i@tf4 zCcU1eqpDPA{91jRM>sL&$>+-Grg8Z+F*WXB8&fAC4J}2*SP2@o-p7ehXN1R(gl?g6 z!N}vCoaW6x`bAPe!`wq-tOib@`EM;$u@63F#J2eLKNm{HU@!!cX`!vei4e%Q-^q?# z9<5mjSe#!|c(&*;I z+bD=pcnFCgiy+43Au_Xzxxb>e41vv<_CO$C1P~S1%;WkaueyrH_*z(&*5ePuXv|@H zZC7iDiJ*+^Mv|+YH+vNRMKMPQ5hc6Is-d$>wt4VVjK8bvxV_$Y_oK#3!=7W`b&aUC zZ5rK3z)KV8oNjTVvPdDtkX3^>rY6{`AQkATz^)97W58ejCSi^RV6?0#kG?(?wDTqY z&h$nhMHO{>0LQrl@4sM59Dq9wpAqfSTKsI@^Gi(gtX=g6|MBzzDlhH)@!gD3W6Jwu z|EPHr-%?QfR!{=Pg`*Rr?!wLa>c zY(6AB&3^oO1T5|t-WE`g+H$e9u)IY_cL?7DCiHtTE&~xh0SO)nC?3{wbY4|Vm*{(b z_W-?zw(_aVmPR!mmCZy1jdbuAWnfwx8qva{WEM5G6%R&U@zfw-5RR&tmRie_M;zKG z4UpDoT#^CG$rGYNUMztW@JhTGzCozp+TnkR37@A0&~eg5{wP+b84I>oo$hWLtqLw* ziK4F(6SSUUIbOgA{Y!Vs6esx*;ayvAJ0CBKcmT8(Xq1q)*zrXO#br)NrGmw zDi9IqKr?$kBK!gZ+!8X2!6zB&TZ?c@D8YEbD5dhVXycFSyQ4EgP+Rlc#9N-w7GBGV z5TwWZis%DZY;mX4;RkmHd^>|6>)T$}MK7^0igVqV9l{Kg0#Lx6NINhkz2C^~)IiOOdOi4usozu7`7s&H!H8Y5{QEFC*JCJdJ)v%^CDS~nB z-)FUF=K8b_6c_rnp)vlyf=xROe22yTv z&?f7*7NYy1;A<66QUr>%K{g94?6}9En8$oL2oX=C-JfjBTwp(%t0-MlQ;G5N-mb7{ zI73Mq9@w{s& zy@@oY=!$9H0&})r5+hZ==J^?9+arA{)3oL`dgd-`>^{+&NpW?Ik^kGPjj`FL_A`@f zi29S)%jBl1O+i+qhIp|i)S7mT=0>(K5?xOyivbq0Ds6yYZUY$v_M6Y0u}YxQa<%3% z3g}!gy;uT%z$>L}xI3sHHp7_{IY1}tOZz1H&<$N4x@Z80y2}I6?)K?(6ZqB2czj~H zy{_S}PqnB!MB}{!g|oDA9u66GWi0D&751}RO@Zg-y868MiSGA4-mr9awbV5CQYXWi zWf|f?ZmL)Y7gXZRktnn6ZwDF6s5lky#|4#=nc`8g0;!4ibGsk4gexi~ZI8X1-lwJH z$p2a|y5Ti4(sw(&x!oV{YAb$va7pEFJP;736d7BSEE^uwU@V&>Liynl#h#oi&*fog zroa5QX4-ymp40-uDw7n>Y-jMB1r}wz=7O5Sh?&_8T)@JXHP?}4Y9>D@Mv4NsEnwUL z?NcECbB9-wt9+-{v=)0!dw%fK1pJ1MDYHrET21ID|O+E=#Ei%%hI0U7OmeAwJ1q~L^f zAly0`p`mTYF8iSti3FCfk5rWEEG8z;1X zsWC})drd?TlJX^IoMXjaO`%wtB@nw#K^waoPhL7gY9JHcGXG9ajdenf%@79sVh_u5~TAnwBVV zS_*}4r6K`ufHRsLLj6b8_H;#0iPw4^m(^(ECH1RBQd{ON!Q?x5NwuX=t`Kt8f~1|LEIEWgO|Z{@Bc6L1^UcRWxwY zz<*47>tw!@49z11z84Vu$Va<^VMg=CN$doYTQn9d_yYUKBA(MS(3TzUM7zNqBi7bp z#`-Hg+v@1PuPVzw96dhm@~HD$ zj0qMtAw(hgDjHMG9}AWkvUAhy!xqE_d?c8*lL|!zvI8-^^cDX(qDD>Vw$kp^EhoIT z*|}*KW{*x6RP8w<|AgiLw6Xml z=}F}2dN)~zm7?loSZQb^G>f=^a;zvzar%?6V}S=SgBCzWYsdNy8xVu?-P$8!UF%hh zlCAv#eR=QzqEv%qRac$`1(jCWNJ~gAQ-7B8`@0s77{xUAXwChYNIQ`h@f9q2X;F3kdLw zYbkK1f%yRKLN1eENoGt>OJ8y!%@aa_mW3TX55{ubDm59=&2rh1USTI2MId=B(>EviwYny>V{pLNIsN`qpK4!$1A-+zVYrE~1{TnmTid|s?dpDax7C3L`|5EZ_#O@s>W=& zU#R?ZFXLTt>4Q75(yu3{irOh(xSEVzYfJYvO=)gKVyZ~G-%S!UVxOPj;kE9;|11G_ z1`VDaGz*tr+<`8)>Qt)Jo{4vIBsk1SCD$cM zZM#qI9rx*T_%1W8l{DEtIEbk7iYu!0s{PcyLd6% zNsRhdTsq_?AT}k|4%CTEmwvm$AG*;tAi1ri6p(HJRB07(ieDQm4idp_W<4sYS&wcn zCF-=usKE$~^axRKt%)ebW?4_rp0QaIg@DOh-$Q&%^Hn@xr?C2J>L-)$bVX^FB2uCF zUi!x2n-7rKbfwHcDRD;C2zDG5a%Iwc6WoVH+7U2QeP^8$3!SF^wCW5^qZDyp@D9Ho zmDSdgm!^R!n^-m3r03-*9FNQ%^VK&;*y(hGurDgXdL{=dBM|Mf@zANI!p Ad;kCd literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/18-steel-drum/60.mp3 b/src/extensions/scratch3_music/assets/instruments/18-steel-drum/60.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..e7b8585bb63251141ca3784131ed5a5e594762fd GIT binary patch literal 28015 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 Tb3h={Xb1%Q|NQ>{>*N0c;5b?; literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/19-marimba/60.mp3 b/src/extensions/scratch3_music/assets/instruments/19-marimba/60.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..54b7df80b9c086bd58b919b98001cb1ca22d1485 GIT binary patch literal 5229 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

O^5#MD0t9&he8_1_ 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 WSfaro5P2+EO)D!&$yxn>fByqAAN>{p literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/20-synth-lead/60.mp3 b/src/extensions/scratch3_music/assets/instruments/20-synth-lead/60.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..0c90c3e32e8ff2bbbe59c150b0ab055c2f2e841c GIT binary patch literal 60288 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 z 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 z zj+~O>|B(>#2vgHG@(wsWAj?oj?v1_B8dK#?=onAP)Tq3(I3)(c&UW&*g$E=#npO6N zopA^wTj|@AN#CtL1iQ)emp9`a*lW%fRhFm6>n$8skCKBwi!2{K>Y0qI%Z$MIeL-rr zHEUsGuyuX%ON#wcB5NCoq!G=OTs9OE9;^0@$nR2O-Dr*}msJl6()ekR`!UgZsJ70e z!ybOHt=@}n*wb?8a>ku=kH}T^GBg1Y~TEC7&?i}?A4dE7bqHk!i;=<7vmVca$x>tk| zFa&T#fWrrnvm~l-6wFI0S*wG_B;?u2@3B2_q^6yMMyTK$KDA>G3Xsx5 zHP-xS`wERIIh@uJOHGV7OL5Bl@+=+BW1Ok^$piu8Kk0ntnBW~%>tTWLJdlfhk`nqR zH!y?B`($|GYifv@kg&2;2K8V8LjRg8{_`F$QJsE5EdqlRX0<77gWc&-Dz>ETh|r@K~1CZgTD`vg((ahu^>aI-eF`U+`u)V3RIR$=@+Y4j3=NWnR3TXi zS<%ew&6mE;!5+1j1~_C45ZFv5`M>l>GQMT0C}Pc-kmnTcNzBp@k>P8N{6F4BtVc&aHWX*BERlYyiM2jDQ-dWur#Xdc^riDq##SpLlZ|t4Y*>o!l0#uj1y% zFSJzksU1r0<@4^`lU}&%tK8BUq8Y~PY?;IVGLT3CtpYa;e;TR^O=<3OMYrtf7i>6f z^zW++#-*+tr$@~3woKme!{gX$Z*+SNZSJDj#jG6xk^X_QK=e6u%QqDHu$|t5=9cDg6d6%>&0VgG($6lV`gE5 z=~#7D>+mRdDqqeaHb`Jw{;KAny{Ap>4$P;BJILb+fBos-!k_D#kn+ufUzThhivy-& zba9%Nf^Ut3x>q75BLsCuc`2Avrd-}nu$=HP%(&}@yn68G%1{+N9X*fYgn8cy5b4pjb9Cx`SAJM0LoX9GJ zvA*wEeWz1rdX_Col0mG`nl)(xUY0DvN+)VnXA4JHq`TqheedVF!kl0L z1@Hm90Z)SXK~*e2wg(9~YbaGB?4bxj9>7Y2y3ik!)Fe+EMnO&Z>_yj@2`Y_pEr%x`m1V55m zYVj|&@YX3ij~O{1rjH3fthl8RN{c3KI4MD$UylVRza@`ZMxRNlcT1SAJHuJQ{K~rz z6GeI@rCz^UyGBz9vPVK53>5Adh)fY^cfaRz){=;b82t3mFSwX#T-{SX81~LtK|_BMJbdo6mZcyWsqr?!AmC zLul73%$8g*J07Pup=~MM&XNcA=TlP#t+@irv*gLLe9Ef$1Yg%_SB(J2%X#bQ*Tb^C zhR-n*;V`tWV@pCzm>8^nyS)s0&Fv*@N&&YdGGTpw$0cl0YrZhW|0j83C| z{g0kYA6Mh;3vxTx0WQ7b0?KJ_mVA1Sx5Ldb*In1EMdSH@lL)+|<#YBJi@3AV=&SCW zS~U7P+e#boT(JdJ2cRja=5Qz;GNJVIGpFq<;=&+`h^T&)=YY7KRb?<8iP#qWB}nxz z&e)}}aKzD(IbGZ{y2ZD&m>hRo=G%$wNC2kxo=6ky$y0>qEL`NkLR=_zG2L=A!DR`v zCfY?7#w{;%qeK+f8M%fgBn}}R>AX=k?nI-1l)qU+;=@2_AdgX7^micO0tS?5RWJ&b ztQEt9+TY8&!r6l9VxKZc7dOh?=*0Qj?S{q%S?=1}nx_)^y?W^O3Z5pTpYtxk>x%jD zzZQsJ_`fkNx=*q>TQ;4N4cjEcE*719j>zqciOQyf5Kng{?ZEc~apIr}T6?>8352JM1D^a*KIzNEF^fq;jC^pk@5$f;c{%kE88O$bsu zBp&!=hoUHh+459b|1u5?R7cJ5z9ksU(1=hY>I98~>*!{Gb|3*%fS4dCu6! zbdkq%hFL4mn!`rhH3K&sFI1L2$T}X*cS1j=(xeug5kVREs%riZH5^v(+A98(GF-2S^PhBuu{CXJ2f%%3Ddnv8N7aC5$Q` z@L7EO41b3B!JhQ~hx~$`YQ#)m^O+n+gy>*tQtb}{x;0*UE56nPXT;>O)8!}VxK%j^qEg@B{U)5i|EvXJ@=V@<43R-@H zo`+91)?zXCQ&;?(ch>}Q9ThBFC5#2C=j<`tV$G!l8g-N1%fbtmGYt&G%liaFRv zmXC*iQs?)7KeQ4hBQ@JE1EOZcAHkcqH-4O@}lQOAaRO;(U zS_BM$rK+Q-=qL%LM*Tz?Rf6E~Nr$035J&*12!=8kQC81E5L#Y6VkMLI!Hu2Gr24y; z#{MFVAAPF#yTWQ*H^)C9W#vpvd&rUg8%?8C;gf=*-NuI{&Y0azFOJJYS=T!uQGQd^ z0x^F$2FzHK9y{WB2ww)Bgw#cdt?Y?(=8xy$m96<)4*;%L53XUPmyMm-G~C_xSEZ%5 zs9W&tf1M)yJ+`#4bN~p^=S}!uQU;x3070lWQQ_wsNtX0lOosHP$B;8`8d11k{Pt}W1RVybe>hYh)H{?*?s5qULO+X1i z>u%pjVuAbxuvT+$UMiDK=NGNA4Xvn5HP|s|{yliw2B+^jB!51d!4A^8j*%}LPK z3;CwxXLA`Y^;AKI-hW0@Hl3F_MvuVrH(#S-0R$TuQt>9dy|vkjDPBr{6`%r>LXOzW)M^#l2%)!(eup;bkc3C8z+$H-Eir<~O$&41zFpcs|O zTCJmmHh)*l8}E#Ds}r@^|9tt#?W9^NT2>K#LVeY`caJskr#yW)QL>Y+VJPD3t+ zBo4A8p7o+iHyeke4Pw$230g=JMH4!AX<{PCm|^3Sg862yGhSQwv_G)PDtDhjN4H;o z|KRL5#Y-AadY8=Poyx`Xmy<55ooHpg-@D+^M{iA0aZp<_FnEx4g{edo(DfJl+-si3 zEE!qdz-ELUIoyFjiXu&5P(85IU%f7aOH|cThH-FqZj>jAEqR1Dr4M=SKX^`yCEjB+ zC}-iM-g;&+^G#+}Df}gm@}ooi_f>KE?(^PeE@C4r%33dar`=R`f493~1mD6m?;Vno zgcU`2jo>$hAn!Fx70JucA&&feetIJu7(A7WYZiNB-^^}b@deygKrT(a ze6G@7GVcgaTuvxqMlf62$vPiF*(kEb?4@pn2Nhc&9_tB4w`-jaEhjp6!=f$$M z=3?%Y?uqmkVS=}kuj)F8J)e!pXeZWS)94!+z4eL5Ur>FiXOZoqStu-tSNjsa&ha<7 zze060Dl#Tj2qR$O$Q;vRss|b*&Q;BRjxZRCyx{9D>;he z=;%;WMhJHqmBqaM^A1)goH&OIbMo4&R)!B#YVp=dM(umJ*cras&-NQVZ)#;d?Ry(m zz5kA(Yy#3Pqt>TVvEnQ9%(n(LYB;8pU3XZ27yJ3c3`U|mqZEtKyfPpnyFP=$2q-9I zcRGR%kdl$A9*F;C!(ew+0NsIXXivdZmh>ur#5PLPWnwFp+$$kRTUTG#thX}26+ESs5F zMN9enYrsTT`gRUO-WlL@&Lp&je>MUdb2$J<;bH(V0Jzpm+%WJ9{*ChzPE2It^Gds$ zLp)7(I7oq%kZ`1GA$1+sMc zspOa0eWC|{{Z2k!34QzZD}e~B z^rq7P5Q%bC?&&)^E{BC`5!W2ZFK6}F;j_J`_9=L3MznSd>sMmI&8BVwWcJvM2iGXG zdRk*I+g1OPCKZA~=jZR!XyGUT1y;Wh1Cw+)Z%LGXvDyToxTEj8Wb#u?zRM?4aMk>! zm*2|gd2IWI-i95{vNhF`w*nZFYBpc+D&E_FNGE0)*3(ouFi#5Wu4@WF1_8Dpc>#=p z#+JtKUvR<5LOcTWrA_WcF$>b0nm-O*WaZ5_u0Mb<7#c;~Z_M>G`X75Hoap{z&r+Ey z83-J{lCgm5p`1~u`)!SSwAePYN-{RjN=K1q>GCfY=)tdvR?gW`5h^8)o@G(`XFF0} z!eviY9*hv-h7omC=w54I?oNO?iiGCs8Z8uOsNC2>Iw?h1B9<(J9)ng{S}yC&Fs|0d z<+|z=2BP^*z()%Db9onH(+<2&t*x8>?{QLid-66{_vf#_6OeI!I>NS4*5f{hK4+bb2xSP`?$fKg%IW9Zy_!l-1UBGue&y*_fODrcx)W zvrr_5JR&}cQduTn?(3PT4(#h?0in>1OLxXJS4N~B+2GoEZIYyzy7XC0Z_<5tJl;DT?G2U$A4DRI&*1))#2+Fy3G5< z9tOegn}npkHY+T|7rl8IJgJflyg0*}qXu3v0}5(u2Hlf^1IsEgpVf-8mC)#mfA0k_ zB~X=6Bn*tkqys$!{>Fl(*Vz9)mSQHk>ZoAIg5rS8e zmsjBlB*>^~A<^p0f4 zGGbC*Iu}K$Kp6sGDI-})N`J#S??8Y?KuJJ%0GrL5CDjs@wQ3?Z4%!kp%f5B~4jigY zHO@5YU#eG`8p0Zlpyx%)>}vzbF870mH8WBJ^`TfRK~8Cw4wSK5+NA7E5Tj^HfIy2p}p;0L?J?Dgz_oWuMw=Cf$q>!a~&vMO&Ofr{M3Ic+4$1K+rZ|~ zEt`yCuVtwY9z8xAC{@6ja$SjDfgR_=bh3Ui*$O?smowI58z=kn8#@`-q%1@8wB$?b z=6OrZXG&rU?D2&`%(|Uw9$8@)FsE?)&>PGvv_;%ksYBbR9fx4#^YHX`!_LvD1EEn= z>se@02_)x%uB>(s+Vu!ds_vXNVxIlC zKlk`2>AI~IXdVn>O8ki>aUBn+=Iu24{d_U=2;aHG9?R#a8uzs(u0O7&vdVmWf&(So?#0}P>EM?;l)5cV0GcrGh@~KRF zWiSZu68?<6T5a9=amOAyAngXsM?M>@Zd8CS^eTI|F=51xWM0B6dSpJo<5TlR&|Y;N zr@~&P#Ge?OJ{J}<{gndIwP7y+eS??Pll~6%E;?%M*r52#;8I6!)n;wAYQ_S6(hrj5 z$fMshHeOg6_J&?ukQOEL>)JJ`!h2WJkIV>jli9p+NYI26B5p~SF8BF6++42p!$s?A zhK!ZK5jMfLV!$f<`L|d8BOUoBM4Q+y@!7l@-ut_}1O{ZsjZPYo%CuK*=;x5azLFzE z@PjW33neN)OSuPiuQl)J(zCO>j(`HNyAe$_EdxI$bSM?dafuSwdOXJjAxj*nG=ms> zH`1T`^4|QXBPi&5KIQuMb2efSggS|k(CMy6q^~nb>}7F-2csE&v?)3L*b36G=$|}58Eqx*$|$N;*NQwLBxs3io$hu=XMmyR%F>Nl7{*e1uV0W>juXv z@(LYWgrjeiEZrqnNLiY|TLOUJ^3cXeGVZG5UL#6Md_recWvw@Y7A38TDmJBvEVfxn zqA$rfUMK%XW8OVRwsU%gh3bDZD?5AkW2dF{rhPNU{_TrVxC$0KJbxPt@$RK?B}7a^ zR^G{8h{HmMyy`q(s=uM{EOklsGu6}WtN5Qko7U0WY2dZ|cwc9Yas-4~!6cDq;2kkB zjtt}u1bhJU8AJ78wPy9Wv|6H7@t5t{1d0$C!Y&~l24pfazwz)^&~?GHJW}5OdZ~7@ zC9G%x>k%-Gbfj5ViLFVoR9G}P9Z~0uw|&t(bIeHpq1uON><7E;&h^f_Yt+y9V=rM? zr(qAvq|(0SLp`{k&?PuR{}&?ETgTA_18^Bdivi3py{m)iFDA9g>tjc?ATf_-v%*_K zb=JIPXG^C5%34Og!1%>Up{+ynY!u|)Co{z^h|m*qm_XK$TRbXBA|T6Ql$MH@I9kng zeX4xwg!?o$T<6A7tKx&|X!z3$^pw?J_%(+)0mT!25QabIJs)#ypFt5wFv<#aedYXk zrz5y1GA2^x15ii)R=6s(OZcm}&2lp!h7jq=FS@l}*wHpEHJo9lLKT0C@-?*DS=R1k zYm3yYgi{{*J=58^t`5o!3!~4*>M^!_%}^}Hf>>u`Q)Rc%&gCpmZnQMvj|Sh>xdEY&{LT8Jl;bX#rTAYBQKZm~Z3ojDKeA#4%E06`|6dm( z<550X)m~$+a5)D%?mo2(-$t}Qg+FOQn3B&7Yy^IYDMY{KfB4?SLA6Jn3i0lp`O`Ye z2?nG&5qY`Z3MsRQ;Ts}VgG7=uZZEj(60XX8wb2b($h;R7PFlY9F(b&9Kazibyy0L2 z%L@Q!YZ4&AV#Jh=PbbHW%0)`Qdg=|VKnxkQVmo`vOU+bCA8os;yKsrlT}AKRFC!gc z)RV^5N%A8n(M6hi3ajC9QQsqFpBW&V;TFT3Qt5qn9Ivjvd0L9;F^968_?NI;GwsDu zG)8E!&**+)N4mMXeq5b*o*MbR6MZ9Ko)omnyRHVm8=*ZkL|Wr=1-Kyo=R&0NXyy8* zR(lL~5Cn-|yuwgrd_UP3!UzJoo>wLm(ru}@X@Uwy3pOeUjUTIjX9?iJJO>|T#opR> zwRTu^*oaqrFMYf0dTPmWp+b8PvIJ|Rk*J0dP`0}V4+m%uUf1=mx1R=0ZExdO-HL{p zAg8|PhJ&|7$sRKVsvUsA=>D!{WaA7Yszfa^Mk_jvof9EC{Gj{s^uOQg`e_`sYog;E)*XB@jCYWaPf`d0YkiOKEa6dTVW~(0c+UHG-p}g-u>~6 zeNNw?D+{6jX1)sTD_MLqoTFz2=<~cp7Bu?sD$|Q_w&w@@f2{$`2#Od!x%yRuH6o7f z^LAx$au)&_61M%_s(je}9Nr~O*`=(kQGJ4q12+k>?=P;Wprs|Q@kA=5KJ6W$ikXYc z?#9X7&mu}QGc~P!@VctQ++wW5Q1G+3piIEGrF{d82mB!-&L3kdik#Q3KgNpXe+y|E z*$}cH@~kF`$woclNWJEb;X93D?JRx+7ps;kJI>F4Woz9IhE91@;|&^JV|h!#Hsx>l zodXP(S<=Z7#R-&p&{W0M0rFEKG+>L!otxd-a zltl8i4n+0R@D$lq%YPhV&!h*kyVJU-@3l(8Qo>6cB}D-#D~FPibM^--UdfqgCah zaNOBu(LP=)_1-rU@^x=m_#-2y`fsa3WEZ@G^y}EhI7TJ66uVWAVoQ$FFnijMl0Ag8 z*ucc4!1Ik!D?)0+o|})Uq*91t{X=oV8)f&W`7S$Bm-$N7E7iI-=&J_baSIqz1n|p5A&O=t-SQ zcR&5+vu->5M(J=x^N^uv=tYZZq!(Y^F~@uS6Oo~0LfxmrF1s6;K;g>!Kop%2OkB!W6#RL8VRS%O;s&1VhGzT-Gn2b zYC=dDAA*@zQmA!eK^o>s8mE+e&hOJevpHA>8GIRXkWZl$GrnhQtFZs|{*H@~r%X5% zOMvL??QXJ!5U-zlsov8R{JdxmZ|%ubdw|F@%Fb&@saO_riFp&Qj7}I(H17lp1Bq6{ zVg$imLw{A0FlwYE_G$h#hKUo>=PJ5IqvJ!Ox^QiBJoCV}hb}^`I=Hb9%X2(yLKmMM z$I}P(;1(x4hfy zIm(EhJ(JtO3Qxzojno$E_XRH|d~VVrV14ZpGyo9fR)cFf(tUsDuNM(Xg!GccUnYYQ8C1XOkbN(C$LBVZ=mLu`g7a7d^NucGbQ7W<%L) z4wXlp2X3Hj=J)mZ;0N{C{-0>0(rXx$>Q}4Q48*De+TVwQsWTnC$zp0aF^N+?!lzFt z28yD$78M_JdrIZZ`TB^j>F?8_f<+H^q=h})crnJQ>kOf$>4t61Yq#e|3^*L9k-xATXw6SbVZS*@4rjXpiVuaFMPDSI!AstPZ;6+}* zqfO5~tGX`6gOEkc!6sP|U!xz1DH{!ot1@F(Q(^F#x*rIe#0L(s7>xv)_Fg9eIrZ-4 zTTs_GY(1luOONL>r#H&-+OTU(bxsOA`COS4q}VoN&IVc%W)X_?u2b0fJwUjCySe9>-)xTB{M(%T2 z(saLKI6aU4(EIL`TF2d+y{6NDqim+ILZ0&3LqN)V*rmm>(jK;&f9+q46OlfEjVFrz z^gX-JoUI7%u=vLzg2KPU6hG}b$c`l$6y=B%S;F+-p=z(%>-=}~nT0-eqDS}}H}v5( zi0VU0jOe>UaJvg1DS|K7fc&0hT3%_`p%IU{`%q)NL^NdKb;yq*=O^RQiV)^zVb+Lo zMIp77>Jam5t-35=FpF7FK~{c# zb<6LH@)utJ6gt!g~jntr?E&41PE^si>C>fGP%d-ihHtZc$s zQbuBoM~{}^zNy0BP40`LfS#PBFy<5MFVx_x}_s}OEa7Us&_fQCk2E7qys~nq_a6XmNq$G%gVy6#Nm<|ieSmDIk z#l=lf|IbCn`pB-K^eIu%^Zd5UZs;p}cFMT-N1@7w%a_gugZ;S=7Gor^=w(#$BU9cq z?UZ*baZ4pDnuPi)xA!@=SghYaPPV!dZkf~VEGR;sMu+FUWVYpW!~^FRpV!Lvdcie? z|K&=QMP{vGHQX=VTOUU=F^;mKV;)BH zO?$J`D(~dzx)+Dik&-L$POg!bq)jO=-;-H~s8#o0(#g{Em7~}T7WwWhH;U=08DvfP z`0;rg4$6w`kV!%`T=RE2PdE)`TB%Ts!E^L2Cj@=@`Uw5+pA|LbeHK(V2k;bvKwa4y z#{6|R$B#^XE^5235=kn2F*UBWQ?FwD2D@aVu=i1ge2qu%mCk*Crc1d$hX9dAgLT<# z_7}fxKQ0Y0%Q~WFDmCMxcoo--Wpj-y_A>kQiXzoYBcx=APspHaMc^b-@Pd;146l=s z&g&*T+UWv~zE`M)I`Ugu2M5+5Z4^T=QpxG4pZudIcPeLu(AHSvj4@`_74*|F{ulCr zbbXLL;Fc3H=UurGBDO(8Q`WaN*s(?|^UaPIOfH;HJ(lAgfBqa?xlvB*e5SzFJpySb zF-j5hIg>U_J5#$hbe_>pt+N&~cVfPuhV`{PsC)HTT<)(8h5s#@mpQKUD&r_!3ynV5 zEs?k<5n}#dYosBD?vYdf=(LYB}TZ!9W?C zaoVT*f5lTn|4jHF5V53wFLqs7sXC`p?01qK&MJg{Yo?|3ZbC>Cj^Tq()^GR^cYA z-kcTj_xmIL^I^p-;jppa{$^EA&N>RO-ZYCl9AKW3IqVwN6_bfqAK;%Y8t<4a=P_S9 z%k5!$c5XxpntyY5z*L+3zlO5ORP>b2B-F%2;B;SFxgXJz}E-iU{2wjdIghz z^YI=jtljvuV2+N=s{UI*!`CQ6J(-c<&|j@B=UGeDs4TaWiNjHv`d`JL$MedV2c7E?uf2#!^tS!C=p~O+X4m2yH#Yb6hUA~2EaM5bH^U?2r?!RI8e07IpJWH z9}>w`heKG=(#lvSwJ)FR9IdCt%VRC^H|DUWErEGwxZ~DmeN^mQZad1Nw$foOHj zeOB2B)DnB8G22!1ID^BWu!5{tUegb+J!yIQRpLKr#50zQ>lfi01z`AC{>;isIM)pY zA_1V4SIrw9%`v#1EJ2LYA}7R@Pb~iaB1*|?)wghL7$0fQOJ%%Q-X`X?EfwAE9hcyl zbJ?4)pngUk+6~*%n@t?L)y8oM_-lecEeHQ(!F5W3r{%>eGMy^H%B`RpRyzE=!%XGs z>Em;zaP!{l_yjb^n9_CW1F-A!b83sNX9V036NX~`H^Rk2k(Gd1GYA4%1@{dI0yt}^ z#%5=Wz|$vmj_9w#h5+#o4ZGe7Vh4I9GY7XB_VqsxSy%YZYRLUd{<|r^MCK?D^){TV z~n%y6Ag;GBz;D#eo7>SM)u ztDA70Z&SXns@&z5%O?U^6Fg2|0@%2@+d~)(j};USMMgt8g@#4a{#}PE9RCbQqjkcS z?d(lUylDZj@DOA?N!2;KNlqkwuo0^4N*n#(=!Fg5b55mntrE=EIa6K+SJjvn3FJ5mwI-AB{!1J)ySE;`S$#poJBEc*B#CSHIJHn0 zV}iS^{9^$IUU$vZjEOKW&Ey+zW4zk*fMNz#`i!sqjh@X;1(>AS6XR5hMobNxe#_v_ zyUK%Hg7CV?TR2Ez^{;EqYW-BGr&8bwz@7GB0i;vh$_JY@Yd{6)LS5kdCya4nMnYR@ za@UywaZk&V$P2UEbo_iCdGY>@us6+YnMD?U|Nds>M1-R)k_nG~Mo#N~P*ykp%ji>> znXCJ@WD-|H5bNJLLDRe4sB&`F?9%4pp4F-`=7_7_h-{OJH48tY#^!XkSpRW`7%6`(gdun;>HS6zn@=RDxK%qIs!e9RqscsNFT6Alw1fHKHE#?L^ZFoRAK6 z*5&-w{5UBJB64$+XbB^WP6seRtvPA!@(FHLQZaPJKE);CmzP(;S0NISEXnvx&D_na zWm6}Kc(R_mKr{-PjCO1bVrg zR;vQ`WaX>QGPeQ5pNd5bzbuSX<{WRHG+U#uEL?`gKu8XpO!L;B!tY#I(YY8S7I1|~ zf9H_FE+}S|{(bzD3*(MG5EPjYpVAvJ@8SP1a742nMAE2ZdaSt&$|(?Dv~ zs+(Qw*_pom&Gy zGdAi=@5$9H|6>n8cGqV8Y-vvnvIksZbp3RC1%c>0JmG%5M_=cobN|EWho8f@vFO3k z0Arfe@sdbeUD_WB80LGAREqf3Jzv)pax&@++pKz=VqR4|EKgxsYxBy=oq}@TDA(>F zTdLn4dmr`Dg@YGqasPEbo-F|efB=9OE0J2Hc&cA)fYAvAxG|C8Z~ht^AFFz|RIFt8 z^7CnilEsFsbWFjRkEil)V|6RuM~nXU%}4D(CFI`1VhR!Dqrn47y7S$-hPo@(y;?pw z_rQycqWm+KF(F&NWP6_km03*Z-REA_S*Lww=VEK6wB8_?# zO9CzcfUnvx$Rl_Zz!mq^LlA^9@%9+ZIH-MoD}J4=vWl`sWU(^)B5{oHqDZCVeY(N} zsn+=4#+Du_TRW7)#V*+9+eH0bM>1_lzZwZ`g`gPRFbSO%m?sqDAisfADmX&TP;2F+ zjyc`J@Qjl?YhtlAOxwZy*tc|%qe3?6?tQ?oqAcCP>s_olN94XB75PRd`eHa!f5{+S z9SR~Pk0UPv)y5kq7o=9L=#EicNz8nK&3izW_3i-SsPeM?G;qmY*yTmlCnnlgbwi}$ zV<=`zp9*{5cs8I2EfCfs(7gwhr-r|^o65?yv@tx>ex8}D^52|` z41;u)NBNCC&KfHx_YK%6ySMzyaYAT`AN%>|^~Wy*rkO=c9KG7{Vw)q3B8Y>iA0+O? zW>w)yP--+9-!px|)@xUJz#l4l;+r+2;EY#^WoPZ!jjsIZzxe(*=PIJ<$Rcj&>oSK9 zI76t-Z=gh}1GWHgxfYS^{f?e7^aGbOr4_Pu!KcguqxWrgFAQ?@0em*-v-NA(go!-J z7rU03meO#@N&UN&TTge(?FRe4tjt`8ZM9qO!MQM7%Zv@zL+pXu79cR2_S1QT3~ziYFS z&fX3CE=%$MOaA1sbD)IJV-1rb#rd?NYD{k283ya{aI&l1G6R*LcBa_E0!jYu?HSsu zVa9mwB|uEdnDR2qJ#NU7K?UB`94mW=i4wcION;W7w!4&HMLlcyypd;BXJXR&BVw-z zvLarxhGJCUk1^L2^dr2w9NGU#+CCDo*j4XyuewvBw z@yMzM7|3|%&2U+s6y`h@O<0(>v(VJCERs4BClrYE`1_093=3bifYO)+K+(^PNIyPg zpBG~s*u!N@)YLGk7NVQZTxYGKk7O=A)|_#Fc-fP2qn0-3kFIM&Z^nVF8JN=XHUS*c z0a~#6%&P~WRLFz;G@f%=MoezA`M<_wWKx0&QM6S*f3qPud9-MDr#;jtXg3Ks;?Z4$ zgB`{(rgqJBM$Q-SitB6$@wR0hV6XPSdI!z{v8s_ZQ~Ejh4{0mp)CIkfIO}H7Wp2id zt1{n{nh-()yi)lLlNT98UK{SWu%Z$Cl9pbfbRzW|^`dG`GuB!|>n0xE_AV>-sj zI4%WNx$+l+67YEzD=8Vi9XJQ<2eh7u7e2X&3*^a_OUyLLOyU{ztr%D{kXm?J^s9+E zduyY?bA3(He1NVcM)=7|^O;RYGd;;swjaSmE9dT!W_Mc2vSCVjGix=NbWu$2Jrm~& zm2kM%I9~l4hRYa3XBzdTh7I_#<-RlR+6m0I5ljRfi$$VPckIDML32PClE1X4Vs*W1 zTkv9gPr1q@(-H{hWA^}3^4>5A{}9KX?ahf%3#UoL&u~5~rlp3p?cDFx4Y!Y3JU3Oj z7QKma!een-am;1PR*Nj5TC!u|nW^o)^jKpK6D4d6Cfb8UgBmFeYd+6oMXJNI@%lSB zJHY{WoB-!_;%RlrY$Eedxl%x9QjJk@MY7_PG~Kid}uoOAg(sQ3Ri= z>vO5fabB{Tc?KWk2fpO=J+wD+h&w6$Q|(Z6CAQ`C^{1AcCjrZNIQrVAPz>C-w^aex zmEDzrp5rNY>s~RVl|}-j{#pdC$`?kA`REFTU$e^nckH1+LBC6Z#cIPEQRU9vhDPkT z&k;K(O9R77AVWaxJUQKZ*xY*5qOgK>-|(e~y%W{rl*mt;28YPvKTfqP212eP?;RzU zWk=IO_Q%U_on4n4n}p6D%vk^BkUTjq8ZMhym14g_jlz}CH$?YilDN~l?8v~l5!8s8 zP616QI8;t8iowRlO2i*kQ*rhOpXQF>-}oqH9njD=8b8NSqVZrhzV823{_@)Y^uWc; zpZ?{g#7^1xoJS$YP~4F~5kaq)Z`UF_kF`dN4g0>8vjsa|z6}nGxT0sbirjHQc-k$p zWo>>a72FsC3ACxE`;hcmi&9c3kF7^V!wC9a89d!5o^8@}Autrr}^Xvs*x6C8BHga)*f-UPbE zabI&Vf82})o?pyhb_>-p-z)WhI!TzY%Ql+2Tr3-sMNwpEC$OoGnK$S%k{Es&ND>Q% zDGwPMzy}V6kz>?Mc1Lp-jR^CSm=jZyH8!lYHkG6{Z%%9BPG81}tnCZ4Cj_!7yV8$m z1%e?{oz{A)9q)szpaP9u$G4G*&s}C;f{Ry*870WQKR;tvVDGy8T?+la0)Vt@(DK-k^6iX@Yc6YIiP#0YIaVKpi1jvwGz!*@D6bU{G8PoQQFJ zwJx=+Y&2dJn;~s9KTHM6PAZ8UsF41^I}Pb`Ga6Dwhm~;A#|2Hj3s2Q2a#xP+mUJDd^S_VI4Pg;R>5Mw0^=Gg`=Hpy@SQVUD7hx|8m14Kfi%Z`gg5;&q;PkPJ2>ER=T^IOG#XlAso+Fl?wezAP!WaF{3tuBZpNH?-o(ydvWc7KHpGL^YL{S?Qa|WKc5u zcUoZ~(|7ME!e|-!n^kD7$PWgUOC~(PjZv=+d0z;~|9*9@nCFvQRW76XcUqo4M)6OR z8^g0g|HqXH#G-c3HwZt9+;5SlS_GD!FH{{{=;DxcyB!XDYA8r_A_QG$0-4$>hT6ef zmGaw8FA|a2*U{a}!Av)IsLP(UN!0K^)Nik$@qoL=sa}#0w8253?bUL6B(fZv#M8ci zR|p#dqGWj)TB7b^a4?!N7%*Ql#zH0qN>%;={V9!UqF(edc0AHv zW6tS-H9Ey|nCsu4hw!gAENz+kT)OOsN-5TNq%%!`>2Dv0c!Lmd2nhW3^Vf0$BUUWQ zEKE~wAtdqh$^OqJTBKatw`dA}+)o~?WtvveRpE2V}vUbkl$%rQzHIE@;^Dto0i znVFqh(XEC`i*hpP)gv>i*2p1BGG9TV65XQ2yf*&heFNcbDW&v&{nsX5!Mx8zQkO+jUK)>br zBTY>+iw`e%Df3YAs1~XW?_(EM$YgZ?`ssllE#oc?579)^25%h`&hly)i5sG!SMh+j zBl_2g$GJ+d67N>|Z9{N`8h}w+ZW)3`K)rBakA^IySDOHdB=}8D2z?+a$tNvKH1|f0 z_?J&AB;e3cq=qqQbWQiS$lAs-6}_PjzKbINhn*4aOq*2{67#XbfKZ+m&#F)x^DX&X z%SU+ef1sB7Wqw@N0}R`d%@4m#1X^3!wqV6ca=J5WpiY@?;(`Z>#|Z#l;^vHpLx>Md z5r!86!kO4tq&CxpJrm*Zv^UcSRi4mqT89!Wq$d^vaeaAEPxGwaz9c(ztDvlY;p)Eq@vr(Fnr=PM3%ujJ zF}Fmc=;YvonGJdlPSGSimt<0@s^B}3{7qbsX-_N%Ok;3c)uPxE*OU3^uU+9c5s9ZS zriIUJ>SD%kMFapp{`=8$Ye-VL5Cn3g0mee;?i@w|z$0D9o8*i@f5qR0+_DQ%zrcQ~ z0(dY0g8n^uqwab zb}twhVX0GrF@XjY>KSb;W4Y%TPZXd55_0!|IHys!iPf=d3u>0?dLQFg8Dcr6o*&qi z!Z-~reWqt_y+aE#UP@7DU`YsWK@6U6lIEHXkd42m@!yLix?29}nfmyFPiC;NAqppF zqTI+N?|y@M&SBY^$7G9#f}tXK8-^I&1lG0DFp3dP(B@w_5(x6Q&y?0-668A5?>z8g zqkd*gh7@5wI;nsoG1%RhI7HmH(B1Pl1|4-NiJIuT=K1o#5gGQTJ2o_~|0 zVh>INZC_|hn=PYInK%)a{llSmYrseQt+iwEFb)(700ZDQ+TPEh^Obx0y<@%Wq=mVU zU!@U{TPkRDtRHb@UFW^y_4!yZ^XzpnkG_8Cm-APl9&J1|a?x^E1B37R#xR%6@qA4u z{ji93Zbrckv2WD++_Z#+2FC_w%IpKZQFm6wp*?NK{8wYwuuv2n_%KJu2U{mXA;85+ zz%MlHApxdzE+MJ0fUx55fAmHI5X=cuTP)kp4qpOF$61W_(DaCs}AoFEjJe`qB>12+h@T1T0_>NYf zBY&Wk^``SNu(P+iH(b4i;8Fy9#!W(%kDGN$FZ_)h8N`wLMPl4J+{f8B zCiw5zXoy}W=08bm|6k>TMFN;M-z^Kle=9TuP2PkKKRS>@z3o3zf9K8SE_wd&NU^#a z_N_f=`g?f(^q+O3G=Fa{NAw?jhVudSSbXJT!{LULIp0{ZD}+rKRgjWGg7uE}fsHco z)vCz&44@wSG=(rY2!~)^XqsaAWpsHhB*v9G%O{o*&&6-~S2(QYrt(?O3jJ>il?*4B zhf+q>q#HkM_;LIhA#n#`YUd)vt9}|Y!ZFPA4K`ko4~>Hx45dNQ(Wj*R5{j;zsf}4w z{H*-$&cWg z&v-Qv6dIMU;GvAfo(-QZ)rOZX9;eotuwzr`rMlWZ*u(05tuH$ob8T3cqQEhpu*Ihw z=%9BKO?tb5%3Rwnsv9M3MWJ38`8}%GIH!gK%k2^bRge(Qs(w1!dgmkrEMD?8J{~4! zhCSgw$z-H5#$#TBWe4#~R$fr6@!q6{23(}103&6iJi2qTYdv_8jHs08WHSSg#h#+-B%vCk1^O%b)diEKh zSU!T7M00GNNTMmjM5Mh4JRiCnj@lI6^2+qK20#-@$`D_N69?mQqI3rA$h&gi;Z0wg} zudQC?d*Q6x?udNc->?|0v7X@+xi{p|Wg2G7JCDBCzWwqkV7zQCkM}l50jLv(Q44Gv zc*tHj6b8aiU7>&*8qjgzM$Z zYQ8vth+KYnso#tAzRltHOaqygr8R#M57;SrBBXhDp}s-$$VGhMOg`b3eb8aEDBd-) zzndhmP=NXhESU4+o|*W{9yq~Xvla!P?UpSUdac|_{*M5b8sT;-99)rdUUjga{6PauAKv!Fdh$aIX0moj zh4t$54{2n(WosSSWf3XnwIQZ)$sHHr>pe`^3;5hS!>U@t70GzvS8^5>2gJ~as|aWw zm#{45gAz@GRzwkBm2d8&>&SZZy^eZz;?D-2?JZk=Ody zENe{TuQ}E<-UXo2Dg8&-1yN129~zj9>xp{p0h55h*Q1!!A-ou3vj{RWZXT?f`;W?e zobHaa=}92*nuVZ+8(XaCuwm&~EWisr;nG{@|gZi(yqu8Xf1C&GrG)UDXUA9M{oyU+oQ(H zdi2|Y5@mG2YK+W;384Xf@W7-f*6wo?`q@G|(0}wse9*M87@8Mqvr@V*RgrhASpHU{ z_oWai&6^}!vBs*%9F5D4#jDx;?>FsZgMZ!uOmq1{BPyS%fBO|w8tnz~A@ScebDzIg zxswfpp0|m;b2fO>JPG!Si>t-8vI#!*&E3Hf#xNhtyUIM}s(PWnH%+W+Sgr z3EnWCz*3)*HX`quqm`g1C*M2BSf6|jy=l*MKiw9f+re)L`T6boYK|;!2mj|;5pJ-4 z>ognx0UMwkvq1wyFN((|3#16#Gyx^1Ucn`F2muHqA;8FyGunIr%;f|kOlswJK)O1pM_f)%xfvWMv~9DjT!niz$90saGy7~n{k zVhArHQ4luJ{(`{1!N&1L6*L}=;z$+X-)u?oQIhNVKFFlxv28x4TiSEobI2=ai*}yL z+*Y>X2FA#H!GyzIu21rKA8ng9GQQU+tsXbRhoDtMl=b)gf$MVQ70?F}>lK`G!u#`# zNX;UFeeRCFk4N?&vX5g>qb17#LX9p*M5hC^D3qmsY~OQ^8~rk1(;hGpc=#hPPa<`e zV|QIQpDre{a)|RC%?Z#47*tD~@XRPZ zRk@dd&=o2hYI6ync$|JNs7yuu_ubBl^py+;(j3rS1S*aVZ2l(s{l#QMszOP6E`-t- z(p3fLM=yU;61dF$vST`feKBk-^2i568HrvBe^Z19X#{x*fjewI2#}YiO3QI8mIS>W z?-C%*KTv@98?*;0eED~v$BJc2I8Ny5Lmfow(bNLURkT;q_kyxToiZ##8IQ}FCz=oiFIV65;i{IN$0d3%UlCkDNLsS=Fde-zbOib3n z4aJ`Y7YU$!_N_jl>DY?e0Q(sibaao^dBWjS5Sa)kf`~dx|KW+)nQopZNh7tZAq|#1 z&o<yAKR+0V->+ws$ z&-Jygn2$`he=wYD<4t{*>tj=Wo7ljk^4zPoh++h>AXjzY;W1UGc9xRWwUxFJU-cA` zeOt)kqhG|afEnY@Iozj^&_hNLC<4sP|FHd`Z*x976xjq}qwiGLbgFB{tm=o;#rT*c zq?iw%ZP-23s8O6Kc}YpCtxj9)w_~h9lt9%TPna=lMRv^CE)JJ);-Mk>Rn>*}!LkK+ znY+$myt)dWRJlS;U= zfAcjt=V=yMjQbJ_B~Yz0nn;=F*#Tk^0+Imc;BO@jAEEO|rX*^ZAZ__~=m=fIbEy@C zuQb}@NJ5hNxfKBZ=_XeNXLl{b?TTtpemOEjI-~Sg@qBpt_E#5!-5_PC&7TL>n#okJ zK?Q#gwBuyH3;SYSnk*kMvU-X7NR#UOIjC}nvdq2WjtSQ$o=mw8=Adj7U6rA z&+Ld;z^l;Na(F;NxZW2&Wv8rMI#AwH9HG-&-f_g~ZNlFer|v}K@HW=HWYHtj`#B9d zUjc$0#u9QzHt#pN*`3;fuGw(%+}=IFWTc8pbPd2gR4BPCI~hY8e|Y}=-md(w{q0fE z*E3bKM#VB>dx}a$;;|`_m;z}L9=3*6(*qvL`=s!M``Cq@Q@LPM=CdYZ6q`Bf?l!Aj zs3X1}0~A7*;Fm|%CMjDvyN*=a`C|tr0%hvIk5=xKz*SAaXi(kyTg1Z_Hd&UpO-?;g z+ogklt6^dIlI;6HZQm!OFP5c5vCBP+;Xhbfy)89q_x~w}ccjp`vUPWbx1Va+T1lEY zw>~4rea(t_R0cw_b%QsrN|~rme2Ic3Hl>15s7-F+Q7#P;{b&&4KiR>-!{8?~Xz#%R z!Q^-q4!cc?MbTkbqy6hqIi?rPf-m(Ck5UJ{>F7f$CN%@gcuwo7S`qtQv%N1^BdW0h zTBuW#<^XK(W2Kp9Q^G-QmbX~sM1TF8TzgKwkkqxgRNZ`^YRPL(i3)b0b--aK9=>wA z)(7-u>^^Y@7PeRqPn?C3&Fe4#qqJY=9MhkL;7IfbWQyoU>KH+LN0|5^kXV8u4+!!% zqOFffD=dT_awZmVU?I?XWH zmwK2m%{}Kx6T}L5@Mqp~JPaRH{BR~R8?LQWDIYwTbnKiYb<%WFNYEV|7k!gN5ZS8 z$6_INr|w$r+fiPwQ?19Gv&FR0kA98+YlZ(jLfCzycC9hYvHl5laL}{4 z-zj44MX`i?t$t7pvkPp zEHs_{NB1K5^VSk_X3G^EizT^#BP9)v8&ouU(S=lyTX;5`jc_ z2{?V88V>5)T&~Q;pn;)RWIQ;O96dNqMs$wtEE|enjsCUXyj4P3NmOxz(s^&FTr%uQ z)e8`g%^GKJ!voqmpq?TAN=KONafP5aWcBdvClfOnfAj6O!F`t@F`=%?i;^!~p?XC& zu6q)L4(Aa4UnEku5|1=qwL2qd>wR| z&W#0zZU^`hYH&ZMlX+ZDQ*y7jeyr@8Uy3HDy|^O1w<|}twP+*MZlY$am(6ezi|hC( z-OK4SlIhQ$l`7p;yg* zW!XQ)`TDPc+Rs0IB5!xDgriN$9wbS7`XaAP1rE^UdijauXsw)re!RCznckl zFz7#MPmu1>0&<4|Hx&HQ0aG%35%Llm1sr;;M}}y_5rC5UiRF%fe8tWVF}7{>+iR@!NCP}FKWtorH9kv*Ib6Twj4KMR3o2#_7!fkr%*R9 zG5$tVRw`+dI^qEqqtDf9*{6$ef+^#U;PxI?_Ndr=-{qNGd7F|%tB2KB+EvER*mFLZ zW7aWc*7})LV46B9Eo-Hq^OQ2vpU1VrTO zoRuaYCWALS5Kn}|;7uIvezR))?sM08oBO9x%ucSBsBo3%%w)p9MHxvi@K`<-(!ccO z4@5FYiCUWqqVA-}9JIqW_ob2HfY#6d+qvH0mOEm%U{ME>c12AD2yXrMbWa>)}VD5v--e06p&+bY+q)D-1{Ap1cgqvqm()w;5DB8k2f!0_*kOTTD}dqT3~d?Noq}q`{;aa|yujjr=lq5QYEe1! z#K_$=njJL9m#`l)at39dIChMNlH=`sb?(EIEP85$r~5ACnfoNZg%BOt_MXGn4i($a zs{XO=dcO}QoQ20$Y}af*6))~yNpg-QKe!F)D!jf;YP!;=SX9TXIqBa#tvEVBpwfXG zY0a;Cp7Qx3RXA|4Yt6@peG|2;EJKQl>|R6DSvb-MYKx5CMIe!QVsaU_Nh6aj@yUq~ zV}0RI{=#`O+}`OuX&91gONrZRAq(Da4fgPrSvC-MipTsi7Uk#vs(fG?UKVFf9IP$y zrggIO-~Fh9DO_1=a4nDW=z#5x%+tDKyaIm;b-dgy2Cg+7cyC++;3z-<20jUOZNi-H z`i4PDWH#%l<7;13Cw*s7i8dT@2+1Iw)O%avVnRl=$B`3QS2^@M7!rkz8DpAK#K z_qfmR1$Q(x%4DCnrZSd9x4AUshBfyd!6P^?`H7!R1%L)Gnp5`b0%_=PVTEf@V*shprHrr&gjwTc& zhXm_;&AeK4*CWEq|FsDrBwv9<55T#oqP@G!0`1W>zeHX6v!#fBnu_u6A6=$0>{(sK zujJNEdu=Lx$k+R`;wHZeukFK4HBEsb$&slBp&l24^ ze~z}{HI3aVuFG4yoiep6Co0kloMOG0KI_kV>5zNY5Fg+Se+XU3rz73d|NBfB;Qqtd zH*V!h4H;SCFKz3z%SZFwPT2iM&2hA zjbC_&xZAE4Wwzhuu#>$peAT=)0KQNs=pylm^m) z^lbM6>MSWlD}gM~-*w6BQNUSHie7eBDNdR^$VfO4d%#li$U5&!2MIw!?z01qB2h;J z^W<8z;fO%V?f8KAv=vj7IW<>g$ijI4m@odLjNUWNx9O;sgcMS|JDIF5lV17!E5+tj zi-$SF+RIl+>x!$z#NouiE1iyCO>)a~bmMVx;fIr4d0YdTDwe$@wpFdjA#KFy-qxuq zDw+m=YuW5O3v@>5HAMjrW#U!>3L4pix|__C|8AoBwigltvIx|c-)FE}KY&_rA+wC~ zi26cZ1Ms@T)w!ttF4DD$D(#p=*1Fd2K~pl#h@yN&FXk|A#PzcN0B==@c(!k6Q&s-a zIfxi_H3{y@uJN}mSon}fzLndG%6zTP{ckD>LK6ng!o#Zc43TuoiofL`KEXoWYTE^) zeDVd99+Rj*7mAnvTl8Vn^(LcYI#iRB#yASqVA@gTk2%jX=#;YN#k*A9GqH?V%)!S- zhaDwohF?PFz3g$Z2*;jZMb)iK)OWnTrWOJY%> z?c7SLqNE>SqtfMr+RIh1Qj<7mNR{=pQg3hZ)un@bb(62EwnV858eP<$JY%N(2HVg{ zCMpV(=h;w%z1w0ral@izz}>A=#18CjJt={$QA2|h`_gX}Gf;OHDb%Sslv`s^IGPq3 z0+4G`PetY4%lQ{OFgnTAc6Wi?aP}#&$KGnqX~Gn>X%pnFMJ6%RKF?lIX8bJaG|LeC z{yOU5W$t+13(X=aE4ID)^vKYjCxt(}Kva7z`PEuq;tPM=i{KAif>kJ=&9TCJI_)lN zH~gxfyZ~f_J6C<6@6-wyu_vB#-zS9hjn74w_@)%)Obe9UM25Uge~onTI_4O@O;lU> zH_A!uQHIBp?Q>!RrGY;|}8pv^P zxNHgZRpFNE43;GBHVDvjtfb$ur$G0kIFQnQ!?&^$b4~8Qala)JUmR#GJdT!g$lVcZ zV#BR7Eg;K-yArduXgYEyO+BFN5FEC!EJz?68rKdAp6vbUnB)5$|E*YJf!;Z8tn3p6 z>ZcFt{;;Ts=yH)A*#n$RIJmI43vE;jr8Nd9iY3C@FO~g-c6Z=N9!;yhV zjnRl{2f(7_yeO^FcKz6j4dF~TC#O2VR3iZuH1S-gk_r@bloiHg!BXNkz1?3$MJ`@z z`={%Yu8_U&kNbFFAV8TRQ07>h?DR!zS9oNr({Yq?PcArm`#agSz-m*ineo$q!N0QL zTs6TclsoJta84(AOu#n7 zAU&WA3a#DZ%)`f^x_CXqtwqe!&jN!3Wq?Th zR5mB(Ohe2|XH>OenLLSyjN6T;Wfw;?K|0v#k;E$zp=kD6VAKQS`VaU6kR^jh`RvMjs{C-PH4(T{{aZF4bIC~Zbwu&EF z%^};v7b}iD-B+3V)(-@w!4MYeK|JIdw}gph;z*5Ql9{$&ziel`=g?X9-YJATF#KG2 z?IPt<6DvSs&TmoyHq3Tu9#~xaBTE5X8~B0y?8^))fpIwi{Dmaj0O%*s(Q9*Zc9&P= z@(vwDvt!^9b7Zoek)7mdLfG1ZPH;Dk6a1YsZI-Um^alC_bD(HtC!wg=18uN;a$WODj0c z?mHdZ6N{9T_s&vAuf=8*8*j~7zX!Z6qY65l?{n`DtjJjM#3LAgK0S#X(!_Xalv%!z zS9pU7M!aIT@P223oY=AR_lV0JC)aj7&9(1A)$+Ecfs=LZoUcv}s6T9IX3wu@F3!G6s0t1W+ji}O9#FQ?b!9>AugzxWs} zSG8dF#?qjZhR_mA)x)>A2>!8(B$?o!YGK9jmE+GD!ZTrug3Y?YzRv)m1~tL}kS-6F zCZmVyl?#P{qArK5`l{4Rngc^f(yL==YktcpHJSBlv4s6u?uDQ8YL>*>7e3d3T);EhZXqw;Of)v{ZdnqHnQ1W)paqIy6#^5%@gtBVDfJ9VZh8#-P4lC%O-&`ckrGb0o6`nmdM=C>ac09@MB9-<^!|v(o zxhO$O?IS|-VluLh%E)#>QaOjPWciw0DghGY0X10evF3^A>N?92Mi)H=0#s?isj0H`(P_MpudX&s8|p7vQ@`1 zSU9~}pN7@1yZ;o1!d_J}^jaR5I~YzMRY(oDhD9lU-TeNo(c-U`3(Gj4E%gWUZ<(Fc zM4E9k%R43<@fvI;J~WPEXTv)XnKe|eEwgBATR?sLzLhzh42&vzhw1ac)f<*8YxB>p zyYX@V6sllzo9=r66=`agXRf%nIHD4*umH%b(2Auq&kuMD8>zD48nJFmbCJ(MV?UH( zSuANrQ3kX9<_zlZew{*aZ4zxpH7@Mo<4m7H5#f)rRZ(44<|}rL&lzKoAZ+_Sc}bvQ zuu3{`Mn4%4n|@^=vu!v(pyuebW9yO0!xk&wVC%GtJhQyAM4U(Vn7-VxcMA;+V#EXL zjQ&#;1_3eyV6UO^hv7*bgM-uA67-WNL~brRLm@g$C8~KTpOo zXErKgAX)AtmD*<9uAtT|E9r-Hc3XApsuBmpm}{d<`=pc?q^~LXPhmi6KmM^Kt2WfD z2yl`llK60uQ`#z447adMNB;WC5?%h);3t7kN{ex_dqsR+rXyJ9uO(RL-37SuSuXf( zqD>Mk3P+x-R$_v5h%hQuYRN+sBxHk$Y6x($>10Y}`2}ge^G3Abh`pt+wTB>U!hsPS~N)vqGf4X6Z z6;F&zY7;ifUD1Xk4#v+eIVCi`W<0B=6n6H9(JSQZ(AW%AD(9 zXC}VC8yc;9(Iyjx;Q6T2n9Yck(qn+Motj-lE*CbOoMl+f$*G2(aqDd-`!_xzQ_dV% z+D}cqc5hoXG6(2^X_!5z`=w_L9vmB28h%%EcPn+e^hy#F}0he zVhfXNscA?*`f#4(jli9sG^N_{3TS$4&gSf%U*r)OSu*M)gCZ zbzqqp@hDL<6rrt@? zcF#51aFigD_c?$t)r|{!BHdd342I_+Jhb+Ol)#v0|H0gO-=j=A_9Fv)XvvCL?M@kl zGk|F|Q#eTX#Y@PC#nTNOvV2k^c{0Y6H=8YI;Z6w+rr2E8SVcV{GcUe&xx=rPH7^*M zPo{@~TkW0y>u!PZr>eE2Ay70k8hoYJ8_kvmn_Jhu5UR&E!l1=}%uIb+p48|dY(&tb zrZ~Tt9ctp}1LU>{k;NmJTx8@r`M*KimjLN51gB-xQi;4btonhT#4FRpuA)x^Axm@q z3fm4%#yU(v>~*Co3Md{J-LwX5wQx~F54T6s)_hRO=6&2CeV=f21S{(PJ(n34C24Fn zG74xL0N@7PXH-mT5Eel3I0O$fG>4g(E8cX2yyq)2K9RHd7x_{23)v$3ufKbqXvY25 zUxmQ#{x^}PMu%z*xy6a+x$64`Tb}^7rW0o)qop#Yimx6!U;TEX++Tb9NMd}(d+d=h zP(lH#P^Dj6l(N!OkPhBciQ0-r4Gef){SD^jyY}@3BqGifFM-+4(>?>1QikC|crO6i zSh%f6`1WF!)y|Wuy!*vs)~$*?DO}!3sUIlNv~Y7gTaWJ>8^^_*-~2bby7}K$_hUU= zACbjEkZ_uU`hd>Jizi&q58xZ$6;{{ro5jE?WE`|p5zW`KK22&Z<%(A8b(^Qd2S(;+ zpfsIRo34kH+Q~yZu=SU;XPq5Ms44TEvD?kk*tO%|r5}a{F^nNTC7<=V*Y6AKFHb8a zwmcF;dfxE}qS_T-aIr=zD=VPxr!$m@V`cC`N@!$D(!nLDEwrk13Yu0{s`RBzUDCOP z-=9d!MbK$$bifggPm{q~H=&5~$d<@95Hz1-w%@*~d$CobsJ-y4)lJs!v)RHT0-x1R z{lRjnu!|!^+xc4bq2blBB(P(B4Ag*zQ_4nMVIQwIa~d5zz?2@%hl+1L)v-07<*M&6d0j z*y9AmVQBcIVp51Ak}zk2;Cy<}fl)rU|lrOUx}`|4uma|)C35~#^Vu4#u)RafOJ^gAc>jU>&iD{riM z7_Hp>f>dx%|3n0gVk)56h=WlzhIzKj8jo9Xkw7U1YEIw}keX6#VYw55ebr`BLcGwU z3g|$5F8^YPft8ag1yh7SS=|M~*<@D6a`X+)uf?KTzOaHsyW@gUNQ?q1BabC+#{rc*E;G@Ui_c}mO{A$&561&(l=7xhI=-pq1)P>>ZeDfp+ z(QlV`DpqWnNnkrarSsus|CF**lb*s{^993!P`Z8oKnt1acq=|mpeGmyQDben!+_eJ zxZ*(s^USoD4f}UC8)<8&yqUFOv&3)Vbq^zmRGhqmnt#ew=q6?>-MphB8BnEPQ6ZPW zuX(Rrsb$1Dk1OmvgoPKu%(FdD%V1q@>zb<|LYHsx9+ER;M_h4Ha!LET*!a49e~1ckJilz{h(-W2VEr zbxpt7uPn-ki1|3(b}44_IOrRFIk=bw>sssU2LjTUUV`)4r0jtX9|Qbxk^^KuAo(<* zk{7k~wjAz*+Z`2}lHL>Fij}&4zIkNdH+1^LXVdvP>I;rApt*5%V|uzAfIb~Z(lIj(pniv_-m$fp5|2V@~;Jg~) zwl1_c+&sGvy_}(&HoJzd6>YN>+&aoPq4Xr)hrQ%>H~qhh%){;Yuk)kaGq9a?JbR1W zpQcVf!d7`|r;^7`PRSH*ErHWf!393Pq$vieKaZ!ty9h0y?M7>QL>fc5;OAZEY{PBdkkmTr~@t3 zU;awpvvcL>Vzgo&+IuiUU^5c`4tPLCU1b$u22HUWwG*hZZOCC4$7 zPVJb1>Wk!*2)K9t!hQ@6_O;Xat|9T@``UU}B4^#y2%sBr{V>BkD0?zB1*wV5*2$)elzELnXxdZGH|$p+X*! zc!F;Q!a*1iKofSJJw?N?MHlly3>YhV`4&Nn{n#8YJTxRh&%iTs&xzCNuQ3m#)5`i< zgbGDtRzAPpUg5vI-x}ED(>yfufy&c6RXzDZ42Ui*d%VBq=X-~6i>aejx*oy1%EQDm^{aQ>EdtP4auuV5JZy)bH{jiU z8d%^H`YXf05HkRRx@UVENQLi^3qYBt=Vjv*Nlw7%ol9{GTN~bM55e2FXW>S$(rQ&W zKv;$voh$|II(P_qt4E90IwZ5G@Bu|(i}oKMx-$w39~C}B=6to{cRLO7Y1>k4$~U48 zJ%}TVfO<_aBJ?P8Di>z(jdXT)unXkA_w6@B4-lF2s@dC0{^nC;J-6*Ils(r_|MW*2 zE!|DfMgW6|jimr&Kx?B2m=tF)SctmAsbNsu-bIZ#F|r_4mrZ^OVhBcP3&eAbw;a;mXQ4@EgBggF_$rmR zMJ-JBYTFoVg@J>>F`p`-tGP7VTw#o#% zq2iPr<(U$~a{CZ&>St!kXO#!nW6Sw_dHdp250+1-c2v{t@@0wh%O`^sEy(njH#UW5 zYJ%@&wYCfmC%wF!goKuS_T K#Q6XJ_kRFVIG~XL literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/3-organ/60.mp3 b/src/extensions/scratch3_music/assets/instruments/3-organ/60.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..a329b732cec12fdf74629d6562b2a398a8f50c93 GIT binary patch literal 26939 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%0DvjHORzuHfP4G;#ZzlE zM?0(XoUqcj@XknQHAB&#KBex*S{-RGs`(MT`=epR`H6BZ;A^F71g6nodd*#Elt<~m zb(MLgeE^sAAy@Qb<8|P1JQ)w}XZD24|PFcH@F% zaRAaMQCERo^z<`Et}817cka=89a(n5A8C>h9jaSJZp`|%VS)z{PYWL+RplA_M}_~@ zqryZ~m(Wxw6M9-QDd^|9=6FW$lPXjtq7;>f-h`?G)PjjzhLEubU3g&(^r57?*9oI0Tnt8YZ~=OudmH{~={BkS=@lX=P7 z5P;x*8&Bw|$G(6_2*}s><#+b+N`DhHNMnQZl#A&#UFC~wMDJOBACx-NnTK#Lrf7E>kQ5D!`c}>8=RN8~^o6 zRrr0Dz-ildc7NE+H7{6+U$h}JzmW`VF<6qH`Z7e=Xugw{I`rBBhfgK^l}6q;e^HyN%iA7AqeI>O9i|0 zP*m)Hed^O1{bK~Uxvi>^qfT)hZ=U>bBdAty+pyXNZDm6Jd-+z1@IouNh_u*8%w5VX z6gk7Oo|(n9fy&~QQFE+~4!cjg;vc>o{S0iJDf=Cv%(yv+KK#cA5L77ICR898Cs`N# zKww)7o^n!yN^KQS%hYPuz zW%I54sRNfj2|4Wu`;JWZ50m{K@6w8YKBNH9FbYyS9{%KETptq$JvK7P+V(mTqn0yL)p0`+9d*&{p>5L6A%!)>I~J@F*n$0F;x zjNG<5I~Y6fV0hqVfBl&NCNZM=b-&j)QG!~`rubE+>;wd(Ohy?wN<2m(3#;bGEMMoK zVEsAx>>Uiww%gvdBrmxvlOy3c&z&akeLUZvp>u}fcU$M-H87ppQfWPglz}|*=h;O` z`PIk%3xp&|v$()G01%tlnoNMVlMn_bp3AW3iHiB^b|a+n4;jf{OTu`*nqJLE zCrgeTo8AQgNXzP{qoIr1jzA9f zD(H713zNwm8%YsrSr&$zo%b|BGas0=sR+@Sr z*9pL1o6jx8F)R%y*E(~ohmHtDcB$hl!nrb%sv;&+byl6?K7IKf=5jhe((z)DCs-Fs zvf{}$Ll3zn6fxZLuA1AiD0x&w>Zif&jAOpMBqUwbcd5^3apkK#vDEIIL=%`?T({2U zN^!F3FOdlK>QqBsGivYr@8>-K&NqU1azTBE;aIu2k=z?u4k`GWt=bNCCny3bb3jH^ z5!D0Z{q{K1V&#|!s1PKJzD)yC99uCR1AA3NRbF0tqHJ0cC9!!Hm@xlzHez-6TFxNg z{{*xFTB2B5uoVMa59%m?PtME>;R)VE*8ra$P+qcff(tw%NE`8l{7xt&P3FDdE=~#ldTXjh=zQfcemz_YAjhkPI+IZQb+Ill1+ie&^VWkt>TY z!@0_u_a%xfQ7Mk0|NK>Ipnnw1Hx|8eaS6G{LW~0c`cu|6@05&h^jf$1q!4 zWK@(}+7)oXDl+c6CnCuOvr?8YFYGWP-H0fT>H1;1FlKGCa*4m^OEmM!co+m8j5>Eh zk~SK$xAm6*+O^uyV>Mh3wBGB?OK(uS__tgF_x|Woba=+>>GY8Hoxi(+hc3H^2IDZn zdS}1aiYEW`UK~WN3GBBS^|8`mzNs(?Fw#zfXCnyWwHb|x?cgap&B(2_@ zOna9vgY*^(DnTlXbA`u)`2s+JG^hZd0zWTy;hFOT3lr&aoERpW!4k{XV}#SpBibJt z^1nJU^P+mZ&`weY?!>}5z5D3sgRrEs4sR=oKq7bP<#N14^`2UG&Bx0ZaXyAngW;*RnRWmfnXYhGmH-Tp8c(R#0N-eFF!qDNSHByx9?7_=REW6- z0jt;y(a%{@rTu z`_KA#R9N8O-%=(6bARVy(!76Q#jXHmSFpStsyPs|6P->tkv?ry#D^=JjcPY2LQoL|L%`x6Q_fXEdZ$ppDYdl Qngs9<`CmTv|NYkg0W#=DO8@`> literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/6-bass/36.mp3 b/src/extensions/scratch3_music/assets/instruments/6-bass/36.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..d967d830ef56e0a9450a3032a47e1d9970f2f0e1 GIT binary patch literal 19738 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 R!vQ!AZqfkUDz%FG005K4dZYjV literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/6-bass/48.mp3 b/src/extensions/scratch3_music/assets/instruments/6-bass/48.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..5c8ce5664ef7da7d3eb1c002d4496edb1e6c5df5 GIT binary patch literal 23175 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 ORRTCe2Y&y5{rMjW1AM^% literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/7-pizzicato/60.mp3 b/src/extensions/scratch3_music/assets/instruments/7-pizzicato/60.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..589c65786785ba934243cb6d3008597ac8f88fa6 GIT binary patch literal 15102 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�|fEK0Kh| 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 literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/8-cello/36.mp3 b/src/extensions/scratch3_music/assets/instruments/8-cello/36.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..c337dedf2cda849ed2ab020ed1d17db09789411b GIT binary patch literal 25512 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 literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/8-cello/48.mp3 b/src/extensions/scratch3_music/assets/instruments/8-cello/48.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..c4b556da2f46e54069966a7737bb23b9c9c1a664 GIT binary patch literal 36240 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 literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/9-trombone/36.mp3 b/src/extensions/scratch3_music/assets/instruments/9-trombone/36.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..95c289ba3e421e368ec8ec03551b282771eb52c5 GIT binary patch literal 28495 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 literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/assets/instruments/9-trombone/60.mp3 b/src/extensions/scratch3_music/assets/instruments/9-trombone/60.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..4f00cf119d12e454bf113d17d30f8a6e354eea1c GIT binary patch literal 27147 zcmd>l^;cAH^zNCVVdxr=7*bMZC;?H1ZX8Mw73oGnLBV2%1_3FNlDFps?4G zZ(`!#C8xg6%*rn;E-kODZD{(~(%#+MKlo{6V(Q!M_r=xq&F$ZR4vtRFKu8u&Pg!4G z>WaMFBjU#YJ(4tvpHxp7fGu2{!+r~~^}ql4|K$}tq5BUY*g2#z&y9D2-hp9vmjSp? zVSD=T1b(sSDnDgwRWj&w^na3Jo(Q3^nW0za1E(I8J}&&5b~Jxr!pC_D1o<+V`!vqO zN%`6w*QzDdARic=U4GLS0@W2c3#G?yFpgT%K?bsDBA*Aj0KXOV_YRU4p zQRohnUqf57JxOe+vtMXR$Ml=G#kM)kQR#Ub&@q1t7RW*5wv%Pg>?0KESy{+CdLK1w zJN$Yc%-#$B@icCfpA>hbSP%ageD&-xwQ|RzDp4k|9s#1GGbH}my)J-82o;F`PH3#a@Zfv3`caBXc*0Km1I-ilUdoYH>MAc^lb3Hqu1wm zY7}fvV!$`NKJ(Mz`_^no?Wl>F*WOD$F=Yh7^EdP5n(FFBn3_cE5Rp%UKRNE4zbVVa z13=-6<8SYTWP?f17!V@p4qJt%bO9l7fB>FYbqNy%GFwKxw#c^pPUYi)Oj#NsS2yXDPdQGjL%&!6Du)iO17bN z-20kb+;Ao!`I^Be)2PwM7E_7l5AjzlmRI)iWa%|gV4H^XfV=mCTfyy9r_7}+@+f7l z%Ma~2qhsxYD4L(r(L)~bOLf{bn3f%Oa|0kvnK%rl#M4~*t72Y(>R!%}@!+6E!=nGf z=oXg(5>G{zC&lQ<{2y+lAQ6mC3nuQbM~ehF-qLzK{Gwkgv3eW4fm8Se?(1LgmX(b& zvzamTvP1hm4X#g?!-LuYQ5zgNM?PJI*|T-#};6Dw~8p?}yL*m0;;HjOZ>N@Dn%vV11KB$@bJapa&_-v59oQbM=U4 z+i!+kB;i5A$sI41+bZ>teiJTX@m8@`082U7D6d3SI|UC>051>v6Sj+BGe`=HQc)u# zp26{6eIlrX%z5rT#8a|GqF%yE)>)BT(_t&(&Fj1&$}nJ59`r!-2Klu;?;68j8fJ|< ztd=o;I+`F@RMH;z4yf8Dby0z8f=t8lwAjaAmr4?MB4+JRdn4#XSeTWhR0W4VhpF*@ zxV7l?Q)btqHjLeYw@<98~pdRkNWCJM|B>3_035LEbZ{gI)Qa9%3tj0l|S9am{}ANsjWZK-xfV9 zBaZQ>rNUDHYHHERk*LU_Ar%f29u}>w<{wF zk3aYEhbNe)K}Bla?0z7)vX8_rhKmye3%|fBJcXsGwKS>Vg)0)nXkG*f?zsQtc}}+~ zT$^WtAiuO=MMIAC(r`7H{-={3Fb0qK(G-h5_!+x_#PYa=QDXR7lm=N9lo5t-$_!d=f>pCj*>X1xJV)@wzT z^C;AV8-9RONcx={Sq7d{a${3&oqE*9T1wj1RBoO>+}~qOg&Y|>{B0*A!j8B&d*6J( zrQ^RmHXNi4@DwZ6*+{61R!BT`FD*}2Pc@nczaD)L6cZ^5a-}ie=2C)OWULwi6U&9l z1aMj63n>Q)J)Q)X_ez7LV-*mBzwD7gvZ@j8j*ZZ-s##xv%0Qr23lcALznmE#ohS1# z%`G#l9es$V;}=lP@1QQkaFQ6$h1Iqm!pgq7D(vJ0HH)s<{Jeasd>;&u*O58_6Sja-!GCLNyLT(W^%GOm*L0!GDDq#nTEm?IsA{baVnPqg1*qgO+Q41@9s8TsvsLzm!@}O= z$#pj*C}<=S4Vk=ol0xw$r;`4-_Jv?0xl~NW6?O)>bsgcmo}O9DG|@4!mt4CGH@%f2 zL?y<5z3MK1l$i5cQ7DUk>JP!|9yU}>37je)8El&TproO1R#2wYnvw?brE^E?{sYv{ zlf(lxl9@9nH|53*{FugLQep~?RmSg$q0g*-V+aPpaf11h!*X^Zv6`Xwq@r(Xr4U!1 zv)W~_U}T?{SdxlI8O~RQ9C)<;`x9xROKvIlUPFX!zo1ALJn`EHcN!xP9tYt(qJPxe z=`@XsdpUv^KYqvmob}h$C$s=qe|NO7Zbh)e|0G!$ZNpz-gZ0wPC24!-VNScipkuU& zsw7XYv=<*5PmWf*FUK!KLS{dQ#^qj_S>ubpeBG^>o}f*)77C;L)n;zmRQ?zH$&7Ma zGST=>**Diq*Jm%;Hnlb-MBG10dI?E>)|61YFM4adz!yb1K-zz$JJ0JFaz2hGj-DE| z+}oRZD4ukCqE}{**016le8R1N?`C9bY}2#R30kc-zGe4ECGsmbox%~5Y69ddQpXsE zq>~`rPzn<5q|RDvbUENRQ1G!1qk6B8(>UJ8i%7AjfD!%~Y%M>o>3Rr)Z-}yIbR?!! z_w6sNu#xsb+~|Aqc(HUVcswx#z{z?qJONIiei0;LurA7z4S9C`dyYD7s-|QOt=E|_ zq`3-@JA#;;kiizDyxR?oj1&c`EQa@J%tTMw|HZP%1P>4dlDek37ZIdM9#UN8XY&Jh zvzw>(f{}iGac-Pf!Gzjws^-X+?9k?JZ;LvC1c)>jsN~n+=DMed0d1?}(8^mzoO+9W z(TW2R)Rr0g(VyBP9%8>fSIJUCIf#8n(qe1+W3puQ5SFFHYdL#N1&7yy?VpVOSy77V znSSn1cxUvPe&4Mn7hEk29eOQZsRK`R{f<(*tp(L_iL%?j^%67aZJ-#xhT0<|m1L4f zBCp}`M8rgoS&VTjCPe^JM=0$gyy;*Fd09@$q~*wRgaIRCvv zRtklIxqyfl9f0J2;Y~n9oLnvS%+1W?78D+qu@lzw@{?(}K8xNJI_lnCg3~5q%kDRL z1WJnWMvu}GI~En326$?(`U@ur7*q)NM&XP;C2Q3Fd@IZ(NLJ$=bD_~>2nc?`HuSV! zhTgmytfs*K$X?@csBz=vXN4ttnK%k#`cyP7Qz5&TpFd*@SB_L0dB&o)z`~JWxaW=t z4ZS9rac#PnX^c}jFl#m<@JenqNtu?T{=fb@ImftKNW^~eueu-R=1u3dw~CeipiV9* z%GtkSi#~wz8vazXjy)m?%Yl#0NEEh219&up)tK7FiiVI=%A4x&`xedm zP1kiMFF<7nsD+NM8rW@Gx4ySu|5U3;cEz~v!Ou%Oy{`vuXfqYOH0Y(6ZPxsDgBucb z&Kq{~Tl$ka6Ye-%C_H4^>0iqm5d8P@#}@!NP+p$N+JREdKxbZ|=83+d6^Fl}l?5ubTQlfC#`6?5A?yZVN*lg?}&&-MM>>GhQXxJI=a z-ye!RdxwEO5IhE3>cG*N@&ac6*roF5IY{5N{R2~|Wdbzv|B%?kz=v|4nD>Y=C13w? zp${biF}^QRX0L1Q$K~KWl;-BuCP%(!CAd2*xJpAMTHR!0_mc#zMD!|Ul^*UbV15=p z&>7`HLI1S)!^b{FaaD`UHkhlQ#d*XZ9ey+h55TiR5Y){gU4HkW^*&^Qys^)BtrXV& zgv7%;5O7m|GB|}G^Lmn%pcS2Rn5OcLN*g0wYOaLlRw14IQQap#!S5bajw{njr^h<4SKvS$WwgAEJDR`wBp#dgpTMTnsov`?u5P+5ihPxVCM%U_V{Py53R z(s>`6os4?xj@GWaL>LEJOI_~ntz4YWiAM$xgJ&8aJ#kU8MzN#+Eb7Y?k8!nNIt|E;ueLlzs;>2KL3) zFW4Lkhd3iX`tB2Jfe*m##V6Z}ZaQz!C9=I5Hn)XiG-~fI3iTx{r)lRx*-hZA2md|& zd3O*oUxMSwJahm@&)3Fu6fIKD;!% zFjh~UsUYbnve3i37-|VM1P!iC@)u2^5zxHQ-US(r1 z3la)uLyQy1YkNUF^&5k^gP?O8@NBadPDQcEWZ#NjX8%ab!)ixlGFVDJ(t-NQspv5f zW^TIP#n0CkH7K&r)_aE!JfB%Cc~}*1N(1#1R$VX{VkAi9!LDOw4qfiOImKmLN<(_1 zY_6`@6NX^^hA{jR`5Lx^FS`YgRs8`Y(sLz2w{f0xup+G(K#4~xcmDRs@HV=$`}TWM zcwq{NUT<*b!*mv$!LQpH+S=TO(lUPMEs=x$rBA)44`Y18uoMQCcq=rs-p>pk69c6|^@;LPcD(mLX8njqL3j5ubPwpNBaQ7vgEP<1 zvwg=WLpGd$>`j43qA%y~b7NA|52_c{evmqT2);1V=2t62VT#b1^Pr2waaoRq4eOQ)troOo0Ej5UyJnb4ADj;-(eOp!x;U5^fm6j>AFkW$g7=}vI*mIAU2wHR&G8%dLXxP9+($w{cm!b# zoHnhWyjk@g=5%vYgZ#U%r|E|=dF-spHECb-64K1o>aW)SP|;tJIfcul(FyK>TK}{@ zV-5pU=K3D~rMhO&XS-6(OpMbHZ`Q1o`v7{B9Vl1@n6{j}pOOg_fh5-|`0SzJ{hH%C zBk#6u6N_CXVnS4zP{UbIg;-_U(I|#D8mb=HpWZpIy&Mc<4Qu2JmeaRuQX5H>*p_Gf z;9Y_V{Xa^-$z3Vvxpp7S4A-Go&)T9GW4%!7WP`vLU0W0Z5IO(Hx}YX8M9RQ9fAL~o zF`HHrGOl&gI*x;guB}a#k$rI3;}SwzRcKe04sh4^<;kNx%xK#w+q)~KFgcO@eXGI^ zlq5)snEm)ov%)U$mcC}{gWwI(E332^F{nFr%}+X?hid1o%}Zk4@qyGP=WSWT69N(3 z^gUQOPy(Y)lw^)31d|X*TSIxVp_j4&$ztBMkig+zBD1aVcm#VF7@Z zn!}J&YX+tGfeiNu??AFBw`LBvw%T0@TnsenL9;3QtDDOG4YTP*(7=kkq*;cDvgJ`+ zNs^3Bu0}U;JClC59I#I7PL=cj^6D;wUtZ17Lao#JM%K3!A`+J&fT}ZOTx03*>SKZ6 zKvdj?E0O~UIS4w4R#?*I2@eaK08tS#!BP!4w4zn@Xn~mn8E{!Rp&`0Fqcr1sdLkXi zWv_j$mNCqH`^^c>$n#GPqXkcdf0dbBwq86{D`EssR-MM*3Ww2pdqX;%k2e-OQKA6& z7&ow%Ws;*8C>KCVDnG*BXHt>JjCucJOU(F*9;1oqgU-q!td52phvg8O=_|{7jh(E{ zd-Vk+ZzWXRI`%FtKVt>&M^?Hu#<+5QhMs%Ul!v+V-yDYD=^#Ywv^rZXq=OuqheG-g zsP_IRm;3!UI{TOdOYRM{CnACmiNz>n({ZqAWivJSFi8qU+mbv>Dh80vNLeJ-xFp+eVSPm>#?^>!ODRAZ=|z93=g z#AH=f`KeDoul>~jGxVVZJih+SYgTsLsCVZAp!!To0G+u{J@-~XJ}pn6Kk|L@#}a)VJgZd^aIz?wAnhuji@1u;JA!hlMj1shw0e6DqQGy z{E`W?S@c89^y$-UP!LH=s9sjnQNaTMKk^_%4$RN2|4$zRLM#YVx~pyN8SUUbROrSY z#?O|hoNvaw9}ukP)AbMNqy-G+L<}_h)(W%||G_#2GVd=L2}G?TC;f2ibg#WB%41zK z-5-Un-F*950^Gl|H2D0D$apT_^t*?U*n&Kihq4=%)P}YoT1@#L(e(&QYR*eYUc3V? zIyzD15nOacFHi8Z{d)KOrKGcWB*f`UenJN2Wpgfy&5|irUzZsu3bfxex@~2wXiO&= z&!5c?QQ?_e-ptKGZntSU@%l<10Bh^5(Kz7Wy3mINhHxjtK=G6LGGo=dK5aQ!OOXW@ zKpZTb$xhB6r_%nTA~rN=Cuzc`c2{|{rzNxx7o}R0r$JklJiXyuY#))r!NwG@V>#vE zEuQchSzs$A3W8H-erK(Fb(5cs$v7d$+j|~EF}oCsB?+J{i2J>1Asf$78N(l^%*FTe zidNQiv6R@j3gtD4P&+ThMBhyzRnuqe%F|A&W=jhPM{;M{DQ^fLP4x@iP7B$v2_cKn z{0N%1pUj`P{+FVwTj-K)}N=RPZQ>-Wv8aBVLjYCr_Jc;q&!5b;&~4S?wghq_Y*eS^I}xF)m8( z@PmA=E~HHEllq${?w{&6xh^R}dV*EGg#oxrd;kK@z2l2AK{}Qmo@*x{6c1bA!q`>Oipk=M{6Y z0{Uf(mRF_)*D@weeBbtIw4NM>Mo6#jB}{ccxCse8{{Gu=9p9f#aR()nN1wq+&4AGk za3>dpk>;f*qO6X$q)hRheJ_N}ow4ZrHIHX2I?BNfd@b$f?jxa`5noCpC5xj!(-;$p zUq!z;;fz%`ul_aX`2jZ%J$mEh9mHEAJj10fN)gDqg5U(5XO?lwj*N+qU@Zp3c13DwU@r?rYCN%DvKJ z%bN$~oiB}>LXRzR^XvbbIh{|M@0LbE5bec3x%DT|3INFU&fDgN|1GZu^(Q09Ir?wG zxmB2g#cA65(G|ix?R_{;>e!%eK(J}_cH0sWS5ei>Ro8;Fv%0I_Cuv_P(yjQ?+?PnS z#I=|)bNxI0?HOLJ^7%nzIQSImmW`@!QEff@FI_l(A^GoChnRpk3=%KhThF{5?Xdq* z#v~x)Zz&b~9YIsfb7)#bOD8SOS2g&TwoQ2f*B;B3e?1E=P5e&embtZ)SgXKt250ji zRq1R>_>aoBdNpv)z-6gD2_xh`wv1J2zwI^srZ>~a#o1-)Ab8U(%+L=kLI9D!Z?HI+ z0?7b=1O}7Ch`$PmQ0E(#0OG0Jh?^g*s(Os+TH^R!I|OzZ<4vv+jmiD}{PU*Er|Vj) z4jXFq0=u(*AP6sAmP9;rzB&ehwR24cVG8*k!0;bSf>>XOM5(v4bqbw>%uw@PaFWbO zq3R7aPMeR^WI{zgvkUf#r;Wpc-{cLfL&bexONA?tgb7ih!l`c@O>j>)7SRD&M`E^B z`>*!DtGA|q|NK+PBWl;q-iEZ7(qL9B#e~o1Nh>6GnI(kA+C&JZ-diJ^d?FFYz>FYg zM6b1V=wj)~dlowBn?pTf^SE%51d=kWsM##({TxM?UOZuvL_YS| z>7@Q3#kY6hufWvj($V|nJfFetnHm?*!?}Cokgi*OGM7yCpwK$UBYTU{>kK@wAtw3= zRWxFVIs{L|r2F?6hw2n#LL_o&1q0g`PRb0UmW~rOSl+fSWU$|#ld+4SD>xSmS93>q zAEMdQ8$I>KaBpEAM|wFsQ$~&77fWrUa;xN*X2@`L!N=tIt-bd{+3G*9S6{T?AlQ^x zzyw@s9pPe(bZf6P_mMz1uwj_oVOR3l;j0{|%j7~mY(x&kJRM$?_V$fThCUTEoaFy< zUt2TkD~&Y?SJ`dJ=WWVOV^%mPSg$Vd)Fpkv_q}lc-7s4P%HF&% zcg+cjj@4U5jBds}K;@Q<~7Y&1g z=UrB_7o{)CXhTPNJOi%Td#JZ=BG_@<0ct2+DUi^WASqNCp@${RoAY8^E)z{x?+-!2d8C znp}vf3IDUML#;Xw3){hYd&lL!joglJ(?;4g z$f!Zc`JhypVVNc|fACSbj*GX$Uc-aCoAcl|AKXRVUT&3^lF} zGTO=Zx_Er`77EJ?adXqfN=$~O^xAn%$J(q9CcFk3UiC`HT(x15Hxzq zeReEmj2|DSbRHVWn)+oM zA=MlcLSv|-ab%zyOlC3=`mIHK@bu43@ZZ?kDY%}!>trZIq7jhQec|k9M@P)i7((M; zpB5~qB%@M{0l?68ee#ZrB5v6rHjF=X&k%A1m;%jN2*66`KKn*~N=O$&AEy4D{u z1v%$r+??M#Fz*xsjUN)GA6#9n{q3X|v?pwM`b-9chI6Rvx!@f5FZWJOMW+ zYQ2uLjH6?hTKLipFX&!ru=ynlrZ}cdd5NKGGM3c{XavDTIYbgagrMvNuxJA}IcaG| zenR&GfBOlW7nwtkaREHb)TDs==hnCK)?WiZdi+Tyi4d;^HBFMDcr3E+d3L<23O4+r z^q1ccJZ>I8`BymiQnqzV%g*@EElA)*p-NaXdmsQ8{CNQ?oIt}vfiZxFU{x8bGQ+}d zH99-&ZEWV2Z~&<%>rl$puePic%){XPMgw4()g$%hb>$Iy-G9fn19ohgvr#*$Cmp$7 zgmy6(Hve6OSkV|3#bs05YgGdGaF3a5B>qxBIpzC&>z>K|`bRwcN8QunP)+n^iJJUN z9M1;_*hNlME9dYjvqbEXLbDVPnTYiG=@fR=ICwO&<9(8<8z^L{+&?ebq;tR3klsi`9OcpzBTk{mRg9t&?50|AK_3m65X- z4DtNz$;a+40M=nPBxBK;ND+yx^uT6j1{<}<@%-PM%>#M%x^Cufj)U-2;c`ZWm=*bN zn`w3qn6#>6gIpk&=>uD=>0Ked)VeRs#p{Mq6JNz^OC@)1|4@yySM^I$^Vnaz8MAhz z&lLjYllfzFO*nU!Mc&xdTi$|u(wY(%hL4J!?N|>bVfQm%LWc--{T^z=@wfBP^&ruo z@gp3tL=i-?Bp(&A`aW9htx*!L&4NRWpQ`_`?vRaCmL7PK;^_QyflFaY=RDf`UVbd2 z>hYU|>o5N(Wip=~Qo8>0i)Y7y&`hSLVYQTsK&pfQ&F#bLuQ*L$Ay>8czc6 zyu3mzKoRF_5lgVrzLAZbu0@i1nJ%CI=6a>80@KxG=W{tC4LWDmCZTaMaFSB5!KTQAMMS(9YMpSW)77z zR86g|LctVSD$W=T=sij0fP>8B7varBprMC6VOw+YBGH#ge}t2|Umb8RWd@M>lY%7G zd)s&FU2I1b?vd--L})BeTgn^V&GZF!qeaP?!1MI+KN|neV(xyU42P4<=skGt3?>ty(lvUa296HQ8&G_uW$~q2K(x$OY24KUcIMTJsqQxGa)FWy|$rr`<4eJ z>NJLjf9|=LNvVcy;M;On)x+77pU}tIBC8x0vk{>Hmkte7*w)YvZo(7`N5?JZz>aer|NtD%Y@kHMfFYHhA+$AlKr4aAFC<4xSR3e zJP6}|bt@+J!U&`Unns9XI%_U=p;p$1WO8)#c;Ja&@lFbrpZo)KhpuJwax@Oy@YE91j9lE{=2q}J-3j$v+^s<_%Y5_AHEnCzEQhdT3w1gb8>PKACORR z1#7{nf_o&9#}Crt?1f#5RgUXfP{kCKcOko7WZ_dWf~1 zJu6ih%pu~r>EzYqGqj_oX-ghC)Lt)_m}-ubL+ugw_?ye8sf2KT2*kUo_+v>>m2O3( z@$z3ppZMrla0+fd>^eL{hu)w_^ky~d9S5A+xk1GN>Ej!#GmelBPYt0}4c_^2E#?b- zh+$L}aZ(0u`HL@O1%>D0Pg?@n7Fg8eiP$3!!>MJ&c&vW6CrliNAjffX?6>Cn@qAxK zGC8mR!O6-O>vV>+(L9wt_{*c&y8;DPgQfqG40VT3J2;hJ^Q4FJ`uWAy5ctD*BrwqK z@)pgb>;t<*E)t-N7Zyx68fP6qMb3MvQ;5+txQI!u;a9a$0P?L$;S-htf_V8z&fM7z z>eZ*he@5a=ULE2eh{xaOZsj&43*$Q9vsE5`{qWp<9(`Oi!Wgh^CagYBOsWAOY zDD&9s^Aw|?LM-DZn>_p0(S_Y02x35_ovA5kR?-jtc?{!{N1x> zwQMqB8Q&MRQ)rqnsdJ8KWl9Lsw5gF2E6yv@eE6i70Cr*^WuP#zufJ#Hq4}#bTl&R&E-nv&J`Js&nR?bjb-a`Pu!UE)o^({K%__3}-kjg7iAZY-^a; z7yuA(T6rzH41Rx{PGE!NK7(LsLuapzk;qyTj(hSh%gaR3bvLH3+h&OGCe=Dl(}GT4 zyO>t(@6+`|Lltm;9hXJ*?bjowf8-)X3XmLd)OC}M7k>dNbk7W)8Wz28#F<%xW;~hdtWz)@5!_8d@J1(%a_v|_f8AJx~A@F)(8K7fvu1cErN~15zrhvj(c2-C2T;d z??ufLtdej*u-c^y?co3MI8C`D2P65f6Zoi>*Lg7!Wg;NRp-6S1%#39e6o$4n2&RF_ zUt*_(h_9XS?)Ec$257@u1W zFg~o&+^-T`Pk!Bh#fFDIafyrtfdGaWp2{_aqLr+U#h&@}6D`JK>4Ya<+>gYU+|P6c zcQrl_#-EMQJ!6^6E>|C>&3Ixaau`&0sgo$_$&8HXFYWMbb(#B+Vh8tF-KQ#{I~0uL z1$59h7;!pA-_w3E8=6ZD7o1ke%vKbNIr-w1*@6X~pQNI>m|%&a?|pLcR$VPUL<(X8 zlFwfAvYW_RSMC`Vh4FE%vroRtQf+$A@X^lR$qaGS@^Iw3Ak{P0;#cms;m=3+4un5E z{PNj#>igvbNX7fLjdopd(VH2uE@9uTjs0Jf^xCFACZ}xcR%H&!47P6TH?S*OB#6t2 zapt_j{IN~`AUzBA}hKcR!4xioM1CQ67 z%TuJz@evSw;FoSRdp@*e4HGzw7SiqEg+&DN>ai0c*r@efT=YrE)Rk4KJNZicst6ZG zV1UsYQivO@7h4xH3d%IgxcPDzNE!+Jfsyc~a!%gUAd+@j1ajF{gkP;~6f~9ATHpF& zLBZp$WpcMKWY6+SL^T{Mvt%B?8b)k1^=AM*gm>Q?y%XYcVBpc`sLi z+*iMIekh*XN;;YR_Ja z4OAdy&ynOCN=C4JEu;$%5~+YA)fFiWhHFleMA8~>4K=G-QpQpU&fc*VvbpeIRsw=9 zU8W3b`5IFMp<#xbxb;h;m$kZ|dKkj@pUfyMDEJNarARR(4ZLPzu)w+gWBgW1M+=(m zRYTf==lE1!eB0akE!roy4Rg8{P)7vPU`!!f28#3=(!Rp|@F=*W&r^1&ldTBrRPlaL zBYHgSxvTIvpF&p02Tzmqhq3vjMSxYBikF~-?P~?PoJ8ENI;A7SDJS_%#?dcutGTw1 zEGX4Qd))Lw+)~@~ODY%80R-xiDNO0Uc4i*?$~sg}E)@4WB-14o39A!95G7#=Wr67x zQp%DEe`5z0+DmGQh#$q9(}g;q@R7whb~>vQ%ulImqBenF!C`pHXPSb2*DG)NK_@so-gN3eY;$W}phOMfmTkR|Ow!i8 zzEKYy8t4<-*lmOR&vJT1;H9=%T?(QR%3jk5ANs&g5d?|e*-xtW*#jGc25g&p&l{3u zq#U1odS5c?b+ZNpLw1>qDsFzZ09yv@XC%3LFGl3hdQ;jUL8dmM z)m8RuD{py&%?}vre>d$sw9?OdGGM#98O5M@>ps{e5!WkeG3Qa*v@=mT;Hm`G@AIz7 zAVBaRd)OnvSwtg;R&-dyFqP^}0;)$P=XsouTtp!PX@h_%^8zS&m&qKhZI@#E@QrUP ztJ(0F6=XHz&7onbMrPA@)qJ12-2HwZqiKx`roqjJx^h*mkY>l`8%OpROcs0PAo#S0 zbsD1c(2XuZuObd&vbxq!nFNJD)r$4@kdOyyX@~@{#q--NkcYi@O#d6iOuxak; z2S~PKvTRKov8!-Bo78WPW&veFzg)9ro4Cn znycZu;4p+(x>V_UF^^;1Pnj|q4!WJ=Frx%G%r+oyC{bv58ny`7{UA$_Yp!rIz9$_@ zl618MssES9z71wnDym4efA@SlH~b1gNpxbET`6VKE_IzcxAhz!wx2k4Ts!ivc5m97 z8;Zfbf2hM^xYKW9-QC}H(ub);c)Xw?TihRwI*+z;c?y)=m0ARioZf)-h`F_bu^c7r zQx2!rI0Zr_LY|;#q|f--OeyWf0l~m)5Iz2;yMwle58SGMkO7DEfi@Lqf|!Q@ivQ|8 zo|-)Fzv&Qx@u$qkS`*mi8ZAstMK*g($AUkc0?%&+tcT(SdG+7Zr^0zl{z?SOBkmTR z1~Q>ri8C|`4PREfr1j^NH5x|kdAq!VuVybd<}V*9caA%!CxVC+rs5$n9BGh^TY}M~#3Fe?KKxGD~>87Ph zcMCJ)lUMgY7P`gOhG-6*58PMS2hcEY=HBmTqZwVyY|76wac4_|S) zuhl<1-@bF&_6%k7dQa5xA!OYd^JNqOFc$CrZqQR3a&rh6|6Y(bs)IjQ6nz!t< zDR^1?^)gYA-UVS+she!kXHP?}=uYI*Ihl7w{`T$-MV`(~m^dOyfg~^3JR0Mt0)PF(e9}De; z7jXb#wCZQ@?m$+_M8i+!rf$~C+kUa#Zzr*@9lq1Z9`wvvPTMr~AuEl3ajj4-C;7)q z>-Bm21q114VEL`d?~+tM(^e*mdZVrKp=$WFzscE|7k`P>=#y4xPG5L%5Mmf{r-r!1 zTDtdg9t^0np(L@o+Qr*G=2jbq^xTtS68>CnQ~z~a+@}2U?i1gSb@MNyZ@j{}<&vZZ zh=64NNi7>kNjXVI|7P?Pre+`wn`uf)RUrgX54j;H{jYP9i<2p{FUqvMz(+X3VH|FQ zRpC!GFM?TxF`HJjWj(Hrp(I)_a7&fucUJ8=4z>v{{$m$FzK&sgkYzO+5IH?nTJ!i# zZb4NR_tcS`z#O(2&1k!Uq3+j1)Y9(q2l5N zG`XL?G$076!TaD)B3&OSA$#5<~2> z;v9&lda;U^FF-%~+orKlt@_v3IqraDENaq1WkQ~WDWq~EocZlf`8uzx(NSieyyuI1 z>R0E_^GwGF_IEi@?nDAoh$q99>kz@NZyo<4rhy0UJXg)#6vEg(MvzHLXLAf(jmAS= zVI$Xyg_?x{BVBxOK*TngMr!z+36p2`Fzw9MZdumYkLe71ZiE$i;i@e0S@mUinHFa3 z$-dJ2o$~Y6Zvrs$=HaN@I;QuSAywDbYddP8+z(^gIS9E${_@jX1mloCP!YgGgjc20 z$ywO3@@O7M-wqPIZ>>y7ggOmq?EsH(%Y?pbm7D3uBqm@z=Mkpsy~*ryFu# zF` zbq8m@sKZ_@7y}2WTlf`!jhR#L?;5p;=lX$Qb@pd8hPvo~FgytP&lLfLP&%g6J>S|R z*6}*D_lE4yc&eH+9d6?Q;?I-hVE)s9Vz-*`AYxQo>uv){RG$g5Ygn)-^E*wR`QY=c zq>fvaWHR%@E=nms5vhqCBOj}kAgI7Cxt71C7pn(t7p@334O&M~swlRuNEd{r>2?x- zLU==KY-wM2WVV0N4oGvjPEH8TOaf(J3*h~utvKi-D39$&jvx3tj=hsf7SSR&O$r?=UWL!Y$* z32kI>?oJd7j4RqAHHw&&zA2APHcKCA?&btoq^Pc520A=c%axq}`7P;G*IGVU2K-k= zw3q%BzSt`G7eM3a1@4FW3 zciv%RyL)ggVJWqZg5|9g`=6sm+<_3L*e{ClX0z^6-c19UOW}>bGG|TGL2$mfNAhNN|B##c=t1$MLgr#9O2GTVyQ7goY3`Wt{vYyqM zbm!oiCOM+sY~S7*OrOWqH~cLbt~`^i;)*YLSeh|!eTm7L7LRWvab&QA#AsO2W;Bp?sEZHRW`cU)ckUf0`qQIq3;v5 z=f(*DDGI9cw8ATln}+uG?zhjXgZnwTYov(gX*-h60|n2TuigJo?pj^Y6q1U|!S?~=*XbkqIGSKCyrRE=qZ>D@1&V}~JX;-t!)ix#V) zHItS?X}53Rc*J%+5*o~T33~e)J5~2K#V7iNGwzRldPS$feSB}t<70N8FZCygX@VBF zZLR!~0HM|V(!KY0NX3fm@I5YC_7P;yIBYU|9wQzJXOXgn;#CovRtuvR5pa^uw?R37 z64mHcr{Y@uut`blmC}eEHSczT4Ow5eKSxK%_+UH3ng|NB4ZIERB{uS4jV*_~sBjAI?LR~adLCL^h6IQBX=y@~9-GNMwpY!V_Z z6bVVPGSByQdVKzbuix(5<8fd2>$cDHE!}oN1+iOCOYGM zMha(k8jD2GQ&Cgp!FmgWjfAPjMB#`Si?F^GTifj}kt`KLD*edjt+6|3WAwNL6VGez zx1Dc4d8v5WCV`Tjtx1@qMfR<~&!sgKK40CKcteTHs(u{|R%$~)*iyDl1JiEYRO*=` z6&H&rGC`n{=*MAw2T?khujn%p2zWa5<-3c<6wz@)=u0wzKhZ4=Wpxh%U~!V_;NojN zCpCY!DQ>QD9$VeO8?$6~j;^V3_dtN}+#> zyF#0^Jw&#CH;%ooo7!>&%RFpO>hxdkN)UD}i&>FOXG<;UaqY$wx7P~2RCH>JSArY8<&;y1xB(@ROd!XrBUZHTDfxH{C=!4B)P?)e24c87eO#x!^|9_# z@WVH`i;Yhut@cV+|C=_5xpbGj;#W9)^6m^!29v_O{an~)8H(A*m+#WJa3fpvA*!Qs zBP|qFqy>uxZlA6FU0Ilz=C(5`ZC{fIzr)@=_eSD7f?;A_>47S5SXj}PRv5=HJ637^ zc(ndSPUGZ@mL7&lotay=x>XqGP7O^l6u38al&=_m9Q!(1U6%L|XyFw*zw`!AJjC$6 zqrc_B2&s_+5)Pr7q#iZ$1OQ|BYk1%h2AL@C?kM!%nAmxvly5edqr=!N_YzGXpqkhT zcd0US9rVe$JJ%*^p;eDV0nSUf(P{3-0}y0KM9GH8f}}IgT4&2uoat!A11_*K7gp;^1^c z^8ne-f+|%YH7Mveb5(x(k>{zOpzWObIsS zJ-)`63j37793>K9$`?-}umqKoKezl;O@ku6CuW z@JaqZCKyw_FZ{q#BfHAnBj7q-uj|4g&$yNS#jB=CZU1MuUIfy?%;uS0%C%?jUf$#a zf!4_2?JS2+b7b7rTnki-z);Ap0a7-1)($Ypr_~jY(vFq#a%F_`PdoY?LImW4&br z6}e7ZKy6+Ls$c1;JQwwa3)Ea7ARD>A8{Org?=z}HBz*s8FT)t@5C7o+LRrg#Mis0a zBV9LRkVu#b&ZfAuW<-|Jv6yO1sgfWqXgKYP;nB8wDiN?}-+rWcS_Sb+m$UvGW=nF& zP45D`WxI&vUm>-l>F&BUeDBcd-ShB&O?ptOMT07(SG7Pi+joW9idPUw@!zQn zm05R&9mgw>Itp0HqkbsXKk~Ki*0KOm=Uw}GhSYY1fv8yE^J-LQdHc)m^5*+p$GwDY zP8Ij^?}Q!xu`Qp@%hDpxP70mRXfQ;O_XPTog=|{`{*5;SKv`ukA<5+|gK#_qv%b!# z>9wPPAYMR?Sc-mB!m+Wz`Ch618fT_@$m=P^{|OFX;HMu9N#;|(lyi!AT4pz-gmJu@ zVBdbr>ZrxcMom}aM91)l`rY?kA*{7CvQH;K?crb9!8DUG&if2dR@o;9F(Fln=fECU6^sn3f>aPpY*(|30HNBuI^yxDd-dPj9Xn46 zRlT43b}4Uea{Sn3x-?JdR^`3h9BFTYyZ)2+AXl!2YB9dF+h&@zLyLtgdz=ph?A>=$ z+dU9w;Z(AM?4Lb6ieg{b~EO|O!I9CiE zv~y%C;9J1vB_ei%?kltOv*uHlAG$vEZ!}*!`LmExxH@ZhvjsJ6}+W;@M!*LO2Oq`fpHgmk_SY{>aO;q692L6VhiDq?DE@TzK{!jr_COy zxHH1*P~5~ev#&wy!IIY`U>pW5Z|z#@IzxZk9rvkzoBH8Zqv=c6IEpSXTZf;XolXMXO;4G7xDpne}>eQjC+cD;qlOfP|PLoR=xXZF>_KKjvmWw z-$Rr`OPY>+#rz7Q&%VD_lK5FgI`5*c_Ye>CLFJF~o4Vhv5CLJFZRT`lJM zeb*xPZAQgs)5;EAg{qR99%rph3+2WqIBRYLS$h2{Enam7CZ~^l5PR}E-_oZ3PFJen zwQ}N4^uPKp3c>(_?An0xg}T!sJ9P?DBxIVhC2u#8aMih>0iQj9VN1ktZ-ode-n}mN z@$Pn2(n%46A$LXM2z-{d=ced>&wfa;EUfN}I&19|U#y%NS^Suy@ije)izvL0a=M0nydS zpA3w^q^|r&XCPR`=0iOiRg_QH7*VK9EKAPc1wt(a!%1A*hnS&V`>bCRodpFjQCuqr zK(m2631hek+)1gGQ_E?0wK{Qm*)v<-Mf={5v)9()oDI54QLknW{ltfViu=7AY+slo zcYIu!XSwoG?&^<2AASU#t9CWj?3E6HoiNXMs0o1Zh8q=WZ+vOESJDJsqqy_BeJ!Vy zyS9ihowo(b35epJ+x{u4R}L9a{?>BgrfoSD1I^pGs|y^Jg#qtmCXC!FMe%2zT)Ch_ zHhV;yf2?wA{UuVsJ*T{`Dd@ecV8XY&Ik0EuZ^qpz*SC>Xl;}XG;~>Hz{>j0rgYy%g51do8wpL^?*4v+A|GSbE0~3jP zYT_o&ug*E1;w{^TpQ^w<&p2?=63oW4Mf-$EwdQ(nQ)OpraQM?s6futtB&-_E!i@r7 z&B&@fd^JLP^4%1yISbTi?HBSWCX@ZvOBv0Is39H43Y17r=guw-?vlNyAmu#NL=+_O zZ0(ZI!hMXWLLHy{cXf}f!8qy5b?I^H()Q@(=E9@U zj|%0~otvBol(KMTq_WW$VBFqR7g(fm1giY0|ZQJYX{3gWrC zK*Vb#v!pc@?W%l>XXcS85V76gxC^bhgvnzP*f=7)$i&G-s8=h;_|b&Ssk_^hbMD z*LF(GWVk)L`2I10zOq}TMUn*P@_nyE2NbX@0|YhqjMRgmVR0Yh!6A3fK!l5r>0AIG z^^^{gCq`}51z8nBu10U4AvR^iv*Lpym>q-6xgpH*pq&fWE)f}QspM+?R|@km?h1`9 zi`N})I2qxz939`>dF!C@(PIPa^LJFc8LQ{PwZw1LOl|Vq>1eMoA6S)EMh0@ISMr(? z2Tb2nm6PXrOCNZFk?fl}{Q@AzfDM0J<%=`Q6`WNcf%j64Ifcy&3Zh-&dkB3Hm&Pt= z@_AQ&j^b!yX-2M#-?>q&k$;-uv-Hq8_2Qkrq`|oGXT)SQA84+>TV4fIH`V0I>MO=x z@;3^y{$tFD2J$@V_-VI_fiO8^W(RY##n|Yfl+BgYVayky!oM~R1-1$ncY3==qRb+@ z2Y#~8#&-3vX}WB8H}Q80u^^1k3dk1lF+@VOAw;`~%V@2Mi8R=(y8PmaeMe zA^QF)%+SL(ujgx0z0GvFhfn9 z^7#FMC&B$9J^knCD`W-HA+N%{2y5qX-zy_(O`I|;OhTNY{ z($|GoK#QaX7AWUuf7qe(gnSYCzq%E}YZ__e%?pJO!Q2~|4uaD3)l1mvM#!@fJ;h1P zJb9ac8E6@^jAyq$_lZENEa@e*A>L-4gj7Z=6-Mc9IVs3Tjm6R6);qfUk~?2AhSa^9 zJst(7BCQ<;bn`)C@v}X)F!aZB_$2=aaQhf_WkqRQfQb5{=Io&j;b!K? zpwU?dE^J~vUmc0!@pK+T7hoijN6PB_gLP>b{^4d$U0BzA z%<=ZmrPC;ZLb4?|*MWKH!ExZ&cX|Rl-aI83+}S_1W%F|t@D}mfQ>-MYo5o-ShNNa1 zIX{d0{b|sVSc?7)O6F#uWX`BbC2k_My^sr-(EeDS4MihFtzl2i&T?c{fPz22-jJlr zZj(l306lnZsGQTSR{~W?vkq~8aG2HMmsQqfe9dXdN&gpE$=TNagWPz_Z+#QOlfsLN z*k}T;5s;uezMXys!kQZr(O^5PC=ez{b=Dg9q@Gl-&+_mgubpTj-RoNH&1)#6^CF}k z-vNKohoEXXcw8k^_u~G6{w0OH2lGmQN}6Qg!Y;W0jLWMpFkOfW#?u9%cC2uF2lPk<{^H`o@urg(OFUw^pG;n zSOSWtr#~$t%Z8QrCVMohz=Uz*EAdb%)xIez$c)lW5^IDiVWWDCO|xV4=7=F4`LffexIcC>aNtVZ)3I zknlbV6F^_m=aAyJ3d;)IgMc5Vseo!x>(Zjf zI3;>|D}HS=vyQj!yvCN|PXnLj+!uw8t7Yf>l73uX|J8A@QO!L$d9d<<4qC}u1sFbc z=zULSO{d0;rYX7Np&*L%u1v0YWRl7dOGZ9GwaNW@92+wjf>J8K{1eZ>C}@zMP945* z{$YXXAMa0}PKmU=a~`?__qoiIBZf;Y$c-SJq2tqw)&TAa_+_iR77{cj-I#`#rL$nH zr?tG2OO!(p2=c<&X@pqzP1HOe)(q0!Jt>H*elBUv)}hZzZV-hIP9tD*e{52~kwsnw9X4qW%0(p0o#-T)A$&oE=d$ zX7f&<68Sxui!1kh@{P0P&+7SmdgFI4toxnt)0N?{-t~tafXkHuDwJ*lMW|3BV;l{o zwz<$>;0DUxTa7;?BeDitAsn&&q{3LTF>g=L>xF{juG* zrbzPiQJW2-W4k?fpH=eWey)3u!FL{I+kKj@{S)3VaW#rxDRc_Vs;=1Pm3K;^lkR?B zSMCfeyaZWa5nT<|M?CW6ipl4U!Q$loFqKCqZ1E1Ddza{ zk!Rsu_5L>JtIdGrQiF%Z=mq~5G3P`76wd*VlzS55=To^sY9<7J5d~=(Ik9ctA9t-ll%hrMN~usUIcJ~rfG z2QST3QJn7EQ{@ER)4;4BEydVf{(34f0T^<_C0F!_5+#Cxhp}9tIb(Xgy6|1WlEP@E zPpmuJ{Bt^3APgdbji7VkEKtRYK!j+R`Q-IrT8`6L0XF*;xm5NR%tblPXvcU_#*ZRT z^^vM)TXp5zX55me_B{@=hXdoL8q)v9C-icfH_p1Cf{k_nvgLR1skuXko!XaVn-SdJ zZA;9r0j}hcn1lYs#)J;=OZ_tX->G6UiC+gIe_Rm(>z}8x05~cnZh?11fh`9*a+41i z^z^&EHj)Zo6dm=-#c|kQike@nA+LwWEYm?4E=F^(HkMx_AXa(pg4bEt;N3)tb4F=D zS7kV-3Ie}kD^CBg$zbC z)UYCS+!j{el$DlbB9@#c-%IL^QOt0Rjk<~gjB})zghENY9i{F+zUmBPF0Qz%9qDXXqRDU$ii*TsCNjbiOW0nrC<^c)FP3GU7E z=O2kajclgP2RDx|8l<8SXIikX(`hCBPO+ZS*ct&`Sde@!7Y-$bvn9;!;1n zWH0=h)c8bRx;tJ%+Twb|+9ld3+sw9^4Tz1AQbF0gY)G8jj!QiE5B!kE8E|4UYiCP= zHM>rMuS{^vd0F2M`w9*EXn0DU=$g0Fdw0UA*#pn~woB4O}&Ge7HioK&x z{ggE=X1EGp%J2rnkK0FWdLI>4%FN9;h)HW412%*_Zmx6Aq;Nsu_AU*Lix}rUNLU$? zFYEOQ;FcQ3;C5-1zc{!133lE?A zWy(o+U3&fbLPfgp6ASpUssBv;2%l^cU(B0T_#NW8pR?M^H04Nr^VJ`K5eHr>`0!|9 zm}SCm`ll`xcJ@VPC0&uiz1Vx~$Sfl3<6IOqt3=;T-2{7Yyr!!UI%s+f2s?>6eWw2WRbK1JY)^LFl8P@2$a@glupD#|u^B zi9YHXqs{y09KsmHL8dzYL|~#|sTs7-dAR*)GZV8d#9quMhC!~AHWnS3{o$SY!yRaX zrl|EQ!F6h{{7>GoNub#^rWDT*%=nI81E5!5qzC>r@sjP4+eV zUy0sqOZYg=YQsS33-a^BkMB-7Gl{*yG-%z=9KT@(K@>_g0+rr7mN+1nhAziCT?n&^ z{08-T10pZ-Na+R$lt4(p(HSd#eThnWs;FU7f>!a$W?O_bO74+Rj$t4}Cq=WFAq)&O zlE&LBPN^UO9uY4ofyMDaBQBe{bRh!8eZO-eeDAYbo?*OuNwrxXb?4Qd)St+$O}WJ_ zFt}>7SxrHWf@Jw1tMzZBR2`G{55-WRcjqte;gF6Hh{n~^I2nUQNa+tHGe@mpq7z22 zlG)X2)%%^9Ff1vWR$jbB#lXDTXc(m)f4xX8=XpfVl(Clkn)Z!Dys9&%>|1|Ax}0*= zc?ym7L$8Vdtjkl9Z8kU0f$Kx=OW(yoVRAV-MS|8a!!=g@ALNV%%Aj)_pdnTZy^_J| z>sosliH5~U%V?wtNr+%$h)9ni;=5jF=3FUEc8w4Na~Wyp&`>$Xoi$g6jmc=AA;vPWL4V}JHF+i;i?4YiEU)vdL>N0B-0D{E z{QVaZYbx}`*_NB9QJcK>If*;Ix%Sq1yGDy(1O`$kL{U;0lmXHv`s?SKKqMDHTQytZ zm0n1sCYK!Ok!YfY^rMYqO*)ac&r3Pt;7|wxZ5ND?srWH2ptD>`9@V-rhOeWYRcUWC~zxGmt;uOe}@16!-Od-L3^S?cZ zkZyvqN8#P6InhZvo|ph4u}Ek(CvAvs0W!xQ^@JpK+VEJ0(V5_E$5O*qGG!uW)c;UU zwM|~sbR!|@M#7>-RS+X*p`_Ci42FUuY*g$v(>QoWHhNf~Ev|AFs~pQX{KG}; z@)NU{JMRaT%s89qcI5bmQYx?Of@hw*SvxG9^Y-*`2w|jUU>Th94F$!M72M;T(nNN5 z@-r8Q%GGYuJ& zs8`47T)nz(K<-+=tW$(FzqE;1lEkw`Pq-OUVwof#IY_6PT^0TOrx?&8|H1jB?Y?c9 z+B}>&Ks%+TSQlJPFwf$2rSzh+o!Y8si%;gopvtc!PqAA4QfMdx>;KDUMPn#~VtBS;k~t~1nDB{yxP76S?p zvs4l{4Qgcr(a_QrfFs28vOqDE@SHB+~j%D@-)SZCW!JjKF&UPR8)kePCD~l zy|<;ht!=!6(j4ab$M@Sd$3uc%YHa?IKUUzA4yfi8QW3bVxB>ineo#lpvqyPW_ literal 0 HcmV?d00001 diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index fc07b6479..9a200796b 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -26,11 +26,11 @@ class Scratch3MusicBlocks { this.tempo = 60; /** - * The number of drum sounds currently being played simultaneously. + * The number of drum and instrument sounds currently being played simultaneously. * @type {number} * @private */ - this._drumConcurrencyCounter = 0; + this._concurrencyCounter = 0; /** * An array of audio buffers, one for each drum sound. @@ -39,20 +39,35 @@ class Scratch3MusicBlocks { */ this._drumBuffers = []; - this._loadAllDrumSounds(); + /** + * An array of arrays of audio buffers. Each instrument has one or more audio buffers. + * @type {Array[]} + * @private + */ + this._instrumentBufferArrays = []; + + this._loadAllSounds(); } /** - * Download and decode the full set of drum sounds, and store the audio buffers - * in the drum buffers array. - * @TODO: Also load the instrument sounds here (rename this fn) + * Download and decode the full set of drum and instrument sounds, and + * store the audio buffers in arrays. */ - _loadAllDrumSounds () { + _loadAllSounds () { const loadingPromises = []; this.DRUM_INFO.forEach((drumInfo, index) => { - const promise = this._loadSound(drumInfo.fileName, index, this._drumBuffers); + const fileName = `drums/${drumInfo.fileName}`; + const promise = this._loadSound(fileName, index, this._drumBuffers); loadingPromises.push(promise); }); + this.INSTRUMENT_INFO.forEach((instrumentInfo, instrumentIndex) => { + this._instrumentBufferArrays[instrumentIndex] = []; + instrumentInfo.samples.forEach((sample, noteIndex) => { + const fileName = `instruments/${instrumentInfo.dirName}/${sample}`; + const promise = this._loadSound(fileName, noteIndex, this._instrumentBufferArrays[instrumentIndex]); + loadingPromises.push(promise); + }); + }); Promise.all(loadingPromises).then(() => { // @TODO: Update the extension status indicator. }); @@ -94,8 +109,10 @@ class Scratch3MusicBlocks { } /** - * An array of translatable drum names and corresponding audio file names. - * @type {array} + * An array of info about each drum. + * @type {object[]} an array of objects. + * @param {string} name - the translatable name to display in the drums menu. + * @param {string} fileName - the name of the audio file containing the drum sound. */ get DRUM_INFO () { return [ @@ -175,94 +192,134 @@ class Scratch3MusicBlocks { } /** - * An array of translatable instrument names and corresponding audio file names. - * @type {array} + * An array of info about each instrument. + * @type {object[]} an array of objects. + * @param {string} name - the translatable name to display in the instruments menu. + * @param {string} dirName - the name of the directory containing audio samples for this instrument. + * @param {number} [releaseTime] - an optional duration for the release portion of each note. + * @param {number[]} samples - an array of numbers representing the MIDI note number for each + * sampled sound used to play this instrument. */ get INSTRUMENT_INFO () { return [ { name: '(1) Piano', - fileName: '1-piano' + dirName: '1-piano', + releaseTime: 0.5, + samples: [24, 36, 48, 60, 72, 84, 96, 108] }, { name: '(2) Electric Piano', - fileName: '2-electric-piano' + dirName: '2-electric-piano', + releaseTime: 0.5, + samples: [60] }, { name: '(3) Organ', - fileName: '3-organ' + dirName: '3-organ', + releaseTime: 0.5, + samples: [60] }, { name: '(4) Guitar', - fileName: '4-guitar' + dirName: '4-guitar', + releaseTime: 0.5, + samples: [60] }, { name: '(5) Electric Guitar', - fileName: '5-electric-guitar' + dirName: '5-electric-guitar', + releaseTime: 0.5, + samples: [60] }, { name: '(6) Bass', - fileName: '6-bass' + dirName: '6-bass', + releaseTime: 0.25, + samples: [36, 48] }, { name: '(7) Pizzicato', - fileName: '7-pizzicato' + dirName: '7-pizzicato', + releaseTime: 0.25, + samples: [60] }, { name: '(8) Cello', - fileName: '8-cello' + dirName: '8-cello', + releaseTime: 0.1, + samples: [36, 48, 60] }, { name: '(9) Trombone', - fileName: '9-trombone' + dirName: '9-trombone', + samples: [36, 48, 60] }, { name: '(10) Clarinet', - fileName: '10-clarinet' + dirName: '10-clarinet', + samples: [48, 60] }, { name: '(11) Saxophone', - fileName: '11-saxophone' + dirName: '11-saxophone', + samples: [36, 60, 84] }, { name: '(12) Flute', - fileName: '12-flute' + dirName: '12-flute', + samples: [60, 72] }, { name: '(13) Wooden Flute', - fileName: '13-wooden-flute' + dirName: '13-wooden-flute', + samples: [60, 72] }, { name: '(14) Bassoon', - fileName: '14-bassoon' + dirName: '14-bassoon', + samples: [36, 48, 60] }, { name: '(15) Choir', - fileName: '15-choir' + dirName: '15-choir', + releaseTime: 0.25, + samples: [48, 60, 72] }, { name: '(16) Vibraphone', - fileName: '16-vibraphone' + dirName: '16-vibraphone', + releaseTime: 0.5, + samples: [60, 72] }, { name: '(17) Music Box', - fileName: '17-music-box' + dirName: '17-music-box', + releaseTime: 0.25, + samples: [60] }, { name: '(18) Steel Drum', - fileName: '18-steel-drum' + dirName: '18-steel-drum', + releaseTime: 0.5, + samples: [60] }, { name: '(19) Marimba', - fileName: '19-marimba' + dirName: '19-marimba', + samples: [60] }, { name: '(20) Synth Lead', - fileName: '20-synth-lead' + dirName: '20-synth-lead', + releaseTime: 0.1, + samples: [60] }, { name: '(21) Synth Pad', - fileName: '21-synth-pad' + dirName: '21-synth-pad', + releaseTime: 0.25, + samples: [60] } ]; } @@ -290,7 +347,7 @@ class Scratch3MusicBlocks { * @type {{min: number, max: number}} */ static get MIDI_NOTE_RANGE () { - return {min: 36, max: 96}; // C2 to C7 + return {min: 0, max: 130}; } /** @@ -457,19 +514,21 @@ class Scratch3MusicBlocks { * @private */ _playDrumNum (util, drumNum) { + if (util.runtime.audioEngine === null) return; if (util.target.audioPlayer === null) return; // If we're playing too many sounds, do not play the drum sound. - if (this._drumConcurrencyCounter > Scratch3MusicBlocks.CONCURRENCY_LIMIT) { + if (this._concurrencyCounter > Scratch3MusicBlocks.CONCURRENCY_LIMIT) { return; } const outputNode = util.target.audioPlayer.getInputNode(); - const bufferSource = this.runtime.audioEngine.audioContext.createBufferSource(); + const context = util.runtime.audioEngine.audioContext; + const bufferSource = context.createBufferSource(); bufferSource.buffer = this._drumBuffers[drumNum]; bufferSource.connect(outputNode); bufferSource.start(); - this._drumConcurrencyCounter++; + this._concurrencyCounter++; bufferSource.onended = () => { - this._drumConcurrencyCounter--; + this._concurrencyCounter--; }; } @@ -491,6 +550,7 @@ class Scratch3MusicBlocks { /** * Play a note using the current musical instrument for some number of beats. + * This function processes the arguments, and handles the timing of the block's execution. * @param {object} args - the block arguments. * @param {object} util - utility object provided by the runtime. * @property {number} NOTE - the pitch of the note to play, interpreted as a MIDI note number. @@ -503,17 +563,110 @@ class Scratch3MusicBlocks { Scratch3MusicBlocks.MIDI_NOTE_RANGE.min, Scratch3MusicBlocks.MIDI_NOTE_RANGE.max); let beats = Cast.toNumber(args.BEATS); beats = this._clampBeats(beats); - const musicState = this._getMusicState(util.target); - const inst = musicState.currentInstrument; - if (typeof this.runtime.audioEngine !== 'undefined') { - this.runtime.audioEngine.playNoteForBeatsWithInstAndVol(note, beats, inst, 100); - } - this._startStackTimer(util, this._beatsToSec(beats)); + // If the duration is 0, do not play the note. In Scratch 2.0, "play drum for 0 beats" plays the drum, + // but "play note for 0 beats" is silent. + if (beats === 0) return; + + const durationSec = this._beatsToSec(beats); + + this._playNote(util, note, durationSec); + + this._startStackTimer(util, durationSec); } else { this._checkStackTimer(util); } } + /** + * Play a note using the current instrument for a duration in seconds. + * This function actually plays the sound, and handles the timing of the sound, including the + * "release" portion of the sound, which continues briefly after the block execution has finished. + * @param {object} util - utility object provided by the runtime. + * @param {number} note - the pitch of the note to play, interpreted as a MIDI note number. + * @param {number} durationSec - the duration in seconds to play the note. + * @private + */ + _playNote (util, note, durationSec) { + if (util.runtime.audioEngine === null) return; + if (util.target.audioPlayer === null) return; + + // If we're playing too many sounds, do not play the note. + if (this._concurrencyCounter > Scratch3MusicBlocks.CONCURRENCY_LIMIT) { + return; + } + + // Determine which of the audio samples for this instrument to play + const musicState = this._getMusicState(util.target); + const inst = musicState.currentInstrument; + const instrumentInfo = this.INSTRUMENT_INFO[inst]; + const sampleArray = instrumentInfo.samples; + const sampleIndex = this._selectSampleIndexForNote(note, sampleArray); + + // Create the audio buffer to play the note, and set its pitch + const context = util.runtime.audioEngine.audioContext; + const bufferSource = context.createBufferSource(); + bufferSource.buffer = this._instrumentBufferArrays[inst][sampleIndex]; + const sampleNote = sampleArray[sampleIndex]; + bufferSource.playbackRate.value = this._ratioForPitchInterval(note - sampleNote); + + // Create a gain node for this note, and connect it to the sprite's audioPlayer. + const gainNode = context.createGain(); + bufferSource.connect(gainNode); + const outputNode = util.target.audioPlayer.getInputNode(); + gainNode.connect(outputNode); + + // Start playing the note + bufferSource.start(); + + // Schedule the release of the note, ramping its gain down to zero, + // and then stopping the sound. + let releaseDuration = this.INSTRUMENT_INFO[inst].releaseTime; + if (typeof releaseDuration === 'undefined') { + releaseDuration = 0.01; + } + const releaseStart = context.currentTime + durationSec; + const releaseEnd = releaseStart + releaseDuration; + gainNode.gain.setValueAtTime(1, releaseStart); + gainNode.gain.linearRampToValueAtTime(0.0001, releaseEnd); + bufferSource.stop(releaseEnd); + + // Update the concurrency counter + this._concurrencyCounter++; + bufferSource.onended = () => { + this._concurrencyCounter--; + }; + } + + /** + * The samples array for each instrument is the set of pitches of the available audio samples. + * This function selects the best one to use to play a given input note, and returns its index + * in the samples array. + * @param {number} note - the input note to select a sample for. + * @param {number[]} samples - an array of the pitches of the available samples. + * @return {index} the index of the selected sample in the samples array. + * @private + */ + _selectSampleIndexForNote (note, samples) { + // Step backwards through the array of samples, i.e. in descending pitch, in order to find + // the sample that is the closest one below (or matching) the pitch of the input note. + for (let i = samples.length - 1; i >= 0; i--) { + if (note >= samples[i]) { + return i; + } + } + return 0; + } + + /** + * Calcuate the frequency ratio for a given musical interval. + * @param {number} interval - the pitch interval to convert. + * @return {number} a ratio corresponding to the input interval. + * @private + */ + _ratioForPitchInterval (interval) { + return Math.pow(2, (interval / 12)); + } + /** * Clamp a duration in beats to the allowed min and max duration. * @param {number} beats - a duration in beats. @@ -574,16 +727,14 @@ class Scratch3MusicBlocks { * @param {object} args - the block arguments. * @param {object} util - utility object provided by the runtime. * @property {int} INSTRUMENT - the number of the instrument to select. - * @return {Promise} - a promise which will resolve once the instrument has loaded. */ setInstrument (args, util) { const musicState = this._getMusicState(util.target); let instNum = Cast.toNumber(args.INSTRUMENT); + instNum = Math.round(instNum); instNum -= 1; // instruments are one-indexed - if (typeof this.runtime.audioEngine === 'undefined') return; - instNum = MathUtil.wrapClamp(instNum, 0, this.runtime.audioEngine.numInstruments - 1); + instNum = MathUtil.wrapClamp(instNum, 0, this.INSTRUMENT_INFO.length - 1); musicState.currentInstrument = instNum; - return this.runtime.audioEngine.instrumentPlayer.loadInstrument(musicState.currentInstrument); } /** diff --git a/test/unit/extension_music.js b/test/unit/extension_music.js index b9e3c8afc..93106297f 100644 --- a/test/unit/extension_music.js +++ b/test/unit/extension_music.js @@ -1,17 +1,8 @@ const test = require('tap').test; const Music = require('../../src/extensions/scratch3_music/index.js'); -let playedDrum; -let playedInstrument; -const runtime = { - audioEngine: { - numInstruments: 3, - instrumentPlayer: { - loadInstrument: instrument => (playedInstrument = instrument) - } - } -}; +const runtime = Object.create(null); + const blocks = new Music(runtime); -blocks._playDrumNum = (util, drum) => (playedDrum = drum); const util = { stackFrame: Object.create(null), @@ -22,6 +13,10 @@ const util = { }; test('playDrum uses 1-indexing and wrap clamps', t => { + // Stub playDrumNum + let playedDrum; + blocks._playDrumNum = (_util, drum) => (playedDrum = drum); + let args = {DRUM: 1}; blocks.playDrumForBeats(args, util); t.strictEqual(playedDrum, 0); @@ -35,15 +30,16 @@ test('playDrum uses 1-indexing and wrap clamps', t => { test('setInstrument uses 1-indexing and wrap clamps', t => { // Stub getMusicState - blocks._getMusicState = () => ({}); + const state = {currentInstrument: 0}; + blocks._getMusicState = () => state; let args = {INSTRUMENT: 1}; blocks.setInstrument(args, util); - t.strictEqual(playedInstrument, 0); + t.strictEqual(state.currentInstrument, 0); - args = {INSTRUMENT: runtime.audioEngine.numInstruments + 1}; + args = {INSTRUMENT: blocks.INSTRUMENT_INFO.length + 1}; blocks.setInstrument(args, util); - t.strictEqual(playedInstrument, 0); + t.strictEqual(state.currentInstrument, 0); t.end(); }); From fc61f9e547820a92a4346cf7b3cc96f161c21697 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Tue, 21 Nov 2017 11:45:11 -0500 Subject: [PATCH 185/272] Select target after drag end --- src/virtual-machine.js | 23 +++++++++++++++++---- test/unit/virtual-machine.js | 39 ++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 994de9860..263248b66 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -36,6 +36,13 @@ class VirtualMachine extends EventEmitter { * @type {Target} */ this.editingTarget = null; + + /** + * The currently dragging target, for redirecting IO data. + * @type {Target} + */ + this._dragTarget = null; + // Runtime emits are passed along as VM emits. this.runtime.on(Runtime.SCRIPT_GLOW_ON, glowData => { this.emit(Runtime.SCRIPT_GLOW_ON, glowData); @@ -692,8 +699,8 @@ class VirtualMachine extends EventEmitter { startDrag (targetId) { const target = this.runtime.getTargetById(targetId); if (target) { + this._dragTarget = target; target.startDrag(); - this.setEditingTarget(target.id); } } @@ -703,15 +710,23 @@ class VirtualMachine extends EventEmitter { */ stopDrag (targetId) { const target = this.runtime.getTargetById(targetId); - if (target) target.stopDrag(); + if (target) { + this._dragTarget = null; + target.stopDrag(); + this.setEditingTarget(target.id); + } } /** - * Post/edit sprite info for the current editing target. + * Post/edit sprite info for the current editing target or the drag target. * @param {object} data An object with sprite info data to set. */ postSpriteInfo (data) { - this.editingTarget.postSpriteInfo(data); + if (this._dragTarget) { + this._dragTarget.postSpriteInfo(data); + } else { + this.editingTarget.postSpriteInfo(data); + } } } diff --git a/test/unit/virtual-machine.js b/test/unit/virtual-machine.js index f0887039e..40bd6bb54 100644 --- a/test/unit/virtual-machine.js +++ b/test/unit/virtual-machine.js @@ -316,3 +316,42 @@ test('emitWorkspaceUpdate', t => { t.notEqual(xml.indexOf('blocks'), -1); t.end(); }); + +test('drag IO redirect', t => { + const vm = new VirtualMachine(); + const sprite1Info = []; + const sprite2Info = []; + vm.runtime.targets = [ + { + id: 'sprite1', + postSpriteInfo: data => sprite1Info.push(data) + }, { + id: 'sprite2', + postSpriteInfo: data => sprite2Info.push(data), + startDrag: () => {}, + stopDrag: () => {} + } + ]; + vm.editingTarget = vm.runtime.targets[0]; + // Stub emitWorkspace/TargetsUpdate, it needs data we don't care about here + vm.emitWorkspaceUpdate = () => null; + vm.emitTargetsUpdate = () => null; + + // postSpriteInfo should go to the editing target by default`` + vm.postSpriteInfo('sprite1 info'); + t.equal(sprite1Info[0], 'sprite1 info'); + + // postSprite info goes to the drag target if it exists + vm.startDrag('sprite2'); + vm.postSpriteInfo('sprite2 info'); + t.equal(sprite2Info[0], 'sprite2 info'); + + // stop drag should set the editing target + vm.stopDrag('sprite2'); + t.equal(vm.editingTarget.id, 'sprite2'); + + // Then postSpriteInfo should continue posting to the new editing target + vm.postSpriteInfo('sprite2 info 2'); + t.equal(sprite2Info[1], 'sprite2 info 2'); + t.end(); +}); From 0a15190b858bfe2d2ea7810fdb15af53a0a423c1 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Tue, 21 Nov 2017 16:48:48 -0500 Subject: [PATCH 186/272] Broadcast message functionality (works with creating new messages, and switching back and forth between them as well). This commit includes a temporary workaround for the issue where the default broadcast message, 'message1' wasn't triggering a var_create event (filed in LLK/scratch-blocks#1258). --- src/blocks/scratch3_event.js | 10 ++++++++-- src/engine/blocks.js | 3 ++- src/engine/execute.js | 13 +++++++++++++ src/engine/target.js | 19 ++++++++++++++++++- src/engine/variable.js | 11 +++++++++++ 5 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/blocks/scratch3_event.js b/src/blocks/scratch3_event.js index 8687141cd..1bf798f42 100644 --- a/src/blocks/scratch3_event.js +++ b/src/blocks/scratch3_event.js @@ -56,14 +56,20 @@ class Scratch3EventBlocks { } broadcast (args, util) { - const broadcastOption = Cast.toString(args.BROADCAST_OPTION); + // TODO KARISHMA adding lookupOrCreate here temporarily (LLK/scratch-blocks#1258) + util.target.lookupOrCreateBroadcastMsg(args.BROADCAST_OPTION.id, + args.BROADCAST_OPTION.name); + const broadcastOption = Cast.toString(args.BROADCAST_OPTION.name); util.startHats('event_whenbroadcastreceived', { BROADCAST_OPTION: broadcastOption }); } broadcastAndWait (args, util) { - const broadcastOption = Cast.toString(args.BROADCAST_OPTION); + // TODO KARISHMA adding lookupOrCreate here temporarily (LLK/scratch-blocks#1258) + util.target.lookupOrCreateBroadcastMsg(args.BROADCAST_OPTION.id, + args.BROADCAST_OPTION.name); + const broadcastOption = Cast.toString(args.BROADCAST_OPTION.name); // Have we run before, starting threads? if (!util.stackFrame.startedThreads) { // No - start hats for this broadcast. diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 8776c6f6c..9117e991a 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -365,7 +365,8 @@ class Blocks { case 'field': // Update block value if (!block.fields[args.name]) return; - if (args.name === 'VARIABLE' || args.name === 'LIST') { + if (args.name === 'VARIABLE' || args.name === 'LIST' || + args.name === 'BROADCAST_OPTION') { // Get variable name using the id in args.value. const variable = optRuntime.getEditingTarget().lookupVariableById(args.value); if (variable) { diff --git a/src/engine/execute.js b/src/engine/execute.js index f5acf909e..3d2e5aa6d 100644 --- a/src/engine/execute.js +++ b/src/engine/execute.js @@ -171,6 +171,19 @@ const execute = function (sequencer, thread) { if (!fields.hasOwnProperty(fieldName)) continue; if (fieldName === 'VARIABLE' || fieldName === 'LIST') { argValues[fieldName] = fields[fieldName].id; + } else if (fieldName === 'BROADCAST_OPTION') { + // TODO KARISHMA (scratch-blocks #1258) this will change when we + // upstream blockly issue #1395 is fixed. + + // we need both the id and the name here, because + // this object eventually gets passed to scratch3_event.broadcast + // which will create the message for the first time if one with the + // given id doesn't exist + // (e.g. default broadcast message, 'message1') + argValues[fieldName] = { + id: fields[fieldName].id, + name: fields[fieldName].value + }; } else { argValues[fieldName] = fields[fieldName].value; } diff --git a/src/engine/target.js b/src/engine/target.js index 6a5c8d129..9a6ad7286 100644 --- a/src/engine/target.js +++ b/src/engine/target.js @@ -92,6 +92,23 @@ class Target extends EventEmitter { return newVariable; } + /** + * Look up a broadcast message object, and create it if one doesn't exist. + * @param {string} id Id of the variable. + * @param {string} name Name of the variable. + * @return {!Variable} Variable object. + */ + lookupOrCreateBroadcastMsg (id, name) { + debugger; + const broadcastMsg = this.lookupVariableById(id); + if (broadcastMsg) return broadcastMsg; + // No variable with this name exists - create it locally. + const newBroadcastMsg = new Variable(id, name, + Variable.BROADCAST_MESSAGE_TYPE, false); + this.variables[id] = newBroadcastMsg; + return newBroadcastMsg; + } + /** * Look up a variable object. * Search begins for local variables; then look for globals. @@ -134,7 +151,7 @@ class Target extends EventEmitter { * dictionary of variables. * @param {string} id Id of variable * @param {string} name Name of variable. - * @param {string} type Type of variable, '' or 'list' + * @param {string} type Type of variable, '', 'broadcast_msg', or 'list' */ createVariable (id, name, type) { if (!this.variables.hasOwnProperty(id)) { diff --git a/src/engine/variable.js b/src/engine/variable.js index d75c0b826..4aad9ffc2 100644 --- a/src/engine/variable.js +++ b/src/engine/variable.js @@ -25,6 +25,9 @@ class Variable { case Variable.LIST_TYPE: this.value = []; break; + case Variable.BROADCAST_MESSAGE_TYPE: + this.value = this.name; + break; default: throw new Error(`Invalid variable type: ${this.type}`); } @@ -51,6 +54,14 @@ class Variable { static get LIST_TYPE () { return 'list'; } + + /** + * Type representation for list variables. + * @const {string} + */ + static get BROADCAST_MESSAGE_TYPE () { + return 'broadcast_msg'; + } } module.exports = Variable; From f610816e72284677b3c00ef57cc888eea43d451b Mon Sep 17 00:00:00 2001 From: sjhuang26 Date: Fri, 24 Nov 2017 21:28:48 -0500 Subject: [PATCH 187/272] Added wasStage parameter --- src/blocks/scratch3_sensing.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/blocks/scratch3_sensing.js b/src/blocks/scratch3_sensing.js index fa129f6c0..19357c88e 100644 --- a/src/blocks/scratch3_sensing.js +++ b/src/blocks/scratch3_sensing.js @@ -63,9 +63,9 @@ class Scratch3SensingBlocks { this._answer = answer; const questionObj = this._questionList.shift(); if (questionObj) { - const [_question, resolve, target, wasVisible] = questionObj; - // If the target was visible when asked, hide the say bubble. - if (wasVisible) { + const [_question, resolve, target, wasVisible, wasStage] = questionObj; + // If the target was visible when asked, hide the say bubble unless the target was the stage. + if (wasVisible && !wasStage) { this.runtime.emit('SAY', target, 'say', ''); } resolve(); @@ -73,16 +73,16 @@ class Scratch3SensingBlocks { } } - _enqueueAsk (question, resolve, target, wasVisible) { - this._questionList.push([question, resolve, target, wasVisible]); + _enqueueAsk (question, resolve, target, wasVisible, wasStage) { + this._questionList.push([question, resolve, target, wasVisible, wasStage]); } _askNextQuestion () { if (this._questionList.length > 0) { - const [question, _resolve, target, wasVisible] = this._questionList[0]; + const [question, _resolve, target, wasVisible, wasStage] = this._questionList[0]; // If the target is visible, emit a blank question and use the - // say event to trigger a bubble. - if (wasVisible) { + // say event to trigger a bubble unless the target was the stage. + if (wasVisible && !wasStage) { this.runtime.emit('SAY', target, 'say', question); this.runtime.emit('QUESTION', ''); } else { @@ -100,7 +100,7 @@ class Scratch3SensingBlocks { const _target = util.target; return new Promise(resolve => { const isQuestionAsked = this._questionList.length > 0; - this._enqueueAsk(args.QUESTION, resolve, _target, _target.visible); + this._enqueueAsk(args.QUESTION, resolve, _target, _target.visible, _target.isStage); if (!isQuestionAsked) { this._askNextQuestion(); } From 7e87f314fb3cfd6ac8d6aeb3f6b15fcf41542281 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Mon, 27 Nov 2017 10:06:42 -0500 Subject: [PATCH 188/272] Convert menu values to string --- src/extensions/scratch3_music/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index 9a200796b..e170cf396 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -103,7 +103,7 @@ class Scratch3MusicBlocks { return info.map((entry, index) => { const obj = {}; obj.text = entry.name; - obj.value = index + 1; + obj.value = String(index + 1); return obj; }); } From b78bdb4c934feeab429bac7c780f54d193c9ac69 Mon Sep 17 00:00:00 2001 From: Andrew Sliwinski Date: Mon, 27 Nov 2017 15:00:53 -0500 Subject: [PATCH 189/272] Address feedback from review --- src/io/deviceManager.js | 2 +- test/unit/io_deviceManager.js | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/io/deviceManager.js b/src/io/deviceManager.js index 2ba018ce3..9f7075e52 100644 --- a/src/io/deviceManager.js +++ b/src/io/deviceManager.js @@ -319,7 +319,7 @@ class DeviceManager { json: {} }, (err, res, body) => { if (err) return reject(err); - if (res.statusCode !== 200) reject(body); + if (res.statusCode !== 200) return reject(body); resolve(body); }); }); diff --git a/test/unit/io_deviceManager.js b/test/unit/io_deviceManager.js index f4d32d06f..499b995fe 100644 --- a/test/unit/io_deviceManager.js +++ b/test/unit/io_deviceManager.js @@ -24,11 +24,16 @@ test('list', t => { const deviceManager = new DeviceManager(); deviceManager .list('test', 'test', null) - .catch(err => { - t.true((typeof err === 'undefined') || (typeof err === 'object')); - }) - .then(body => { - t.true((typeof body === 'undefined') || (typeof body === 'object')); - t.end(); - }); + .then( + body => { + // SDM is running + t.type(body, 'object'); + t.end(); + }, + err => { + // If SDM is not running error is expected, continue + t.true(typeof err === 'object' || typeof err === 'undefined'); + t.end(); + } + ); }); From 12acdefb5adafe0e683d0e192282bbea02b416e5 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Mon, 27 Nov 2017 19:15:05 -0800 Subject: [PATCH 190/272] Add "browser" field to package.json This informs webpack (say, in `scratch-gui`) about the web-targeted build output so that it can resolve dependencies correctly. This fixes build problems that became evident after merging #805. --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 98c0f6c36..2ccc80891 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "url": "git+ssh://git@github.com/LLK/scratch-vm.git" }, "main": "./dist/node/scratch-vm.js", + "browser": "./dist/web/scratch-vm.js", "scripts": { "build": "webpack --progress --colors --bail", "coverage": "tap ./test/{unit,integration}/*.js --coverage --coverage-report=lcov", From 88dada5cb86ce507e0fe52345b377c8d879941ac Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Mon, 27 Nov 2017 20:00:03 -0800 Subject: [PATCH 191/272] Use UMD for web ouput UMD output seems to be working well for the storage module; this change adjusts the web-targeted build outputs of this module to use it as well. Also, common output properties are now specified in the base config and removed from each individual config. --- webpack.config.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/webpack.config.js b/webpack.config.js index f2d4c880c..0fc99b26e 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -10,6 +10,10 @@ const base = { port: process.env.PORT || 8073 }, devtool: 'cheap-module-source-map', + output: { + library: 'VirtualMachine', + filename: '[name].js' + }, module: { rules: [{ test: /\.js$/, @@ -37,8 +41,8 @@ module.exports = [ 'scratch-vm.min': './src/index.js' }, output: { - path: path.resolve(__dirname, 'dist/web'), - filename: '[name].js' + libraryTarget: 'umd', + path: path.resolve('dist', 'web') }, module: { rules: base.module.rules.concat([ @@ -56,10 +60,8 @@ module.exports = [ 'scratch-vm': './src/index.js' }, output: { - library: 'VirtualMachine', libraryTarget: 'commonjs2', - path: path.resolve(__dirname, 'dist/node'), - filename: '[name].js' + path: path.resolve('dist', 'node') }, plugins: base.plugins.concat([ new CopyWebpackPlugin([{ @@ -87,8 +89,8 @@ module.exports = [ ] }, output: { - path: path.resolve(__dirname, 'playground'), - filename: '[name].js' + libraryTarget: 'umd', + path: path.resolve('playground') }, module: { rules: base.module.rules.concat([ From a71e06af433e27d2c36429476740e6196ef71a52 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 28 Nov 2017 12:29:45 -0500 Subject: [PATCH 192/272] =?UTF-8?q?Clones=20get=20a=20reference=20to=20par?= =?UTF-8?q?ent=E2=80=99s=20audioPlayer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/sprites/rendered-target.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/sprites/rendered-target.js b/src/sprites/rendered-target.js index 653bc4efd..9e181b957 100644 --- a/src/sprites/rendered-target.js +++ b/src/sprites/rendered-target.js @@ -137,7 +137,11 @@ class RenderedTarget extends Target { */ this.audioPlayer = null; if (this.runtime && this.runtime.audioEngine) { - this.audioPlayer = this.runtime.audioEngine.createPlayer(); + if (this.isOriginal) { + this.audioPlayer = this.runtime.audioEngine.createPlayer(); + } else { + this.audioPlayer = this.sprite.clones[0].audioPlayer; + } } } From 773c167987258a098ddc938949ff66ce17d98468 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 28 Nov 2017 13:15:48 -0500 Subject: [PATCH 193/272] Check for instrument sample before playing --- src/extensions/scratch3_music/index.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index e170cf396..807c3f792 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -602,6 +602,10 @@ class Scratch3MusicBlocks { const sampleArray = instrumentInfo.samples; const sampleIndex = this._selectSampleIndexForNote(note, sampleArray); + // If the audio sample has not loaded yet, bail out + if (typeof this._instrumentBufferArrays[inst] === 'undefined') return; + if (typeof this._instrumentBufferArrays[inst][sampleIndex] === 'undefined') return; + // Create the audio buffer to play the note, and set its pitch const context = util.runtime.audioEngine.audioContext; const bufferSource = context.createBufferSource(); From b674a0c047afb91083db2369ce9e9c3a3c6ade9b Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Tue, 28 Nov 2017 22:33:27 -0500 Subject: [PATCH 194/272] Code cleanup and refactoring, and getting scratch3_event broadcast functionality to look up the variable name instead of getting it ad-hoc. --- src/blocks/scratch3_data.js | 33 ++++++++++++++++++++++----------- src/blocks/scratch3_event.js | 14 ++++++-------- src/engine/execute.js | 13 ++----------- src/engine/target.js | 1 - 4 files changed, 30 insertions(+), 31 deletions(-) diff --git a/src/blocks/scratch3_data.js b/src/blocks/scratch3_data.js index 8ec4f124e..0a382e280 100644 --- a/src/blocks/scratch3_data.js +++ b/src/blocks/scratch3_data.js @@ -30,24 +30,28 @@ class Scratch3DataBlocks { } getVariable (args, util) { - const variable = util.target.lookupOrCreateVariable(args.VARIABLE); + const variable = util.target.lookupOrCreateVariable( + args.VARIABLE.id, args.VARIABLE.name); return variable.value; } setVariableTo (args, util) { - const variable = util.target.lookupOrCreateVariable(args.VARIABLE); + const variable = util.target.lookupOrCreateVariable( + args.VARIABLE.id, args.VARIABLE.name); variable.value = args.VALUE; } changeVariableBy (args, util) { - const variable = util.target.lookupOrCreateVariable(args.VARIABLE); + const variable = util.target.lookupOrCreateVariable( + args.VARIABLE.id, args.VARIABLE.name); const castedValue = Cast.toNumber(variable.value); const dValue = Cast.toNumber(args.VALUE); variable.value = castedValue + dValue; } getListContents (args, util) { - const list = util.target.lookupOrCreateList(args.LIST); + const list = util.target.lookupOrCreateList( + args.LIST.id, args.LIST.name); // Determine if the list is all single letters. // If it is, report contents joined together with no separator. // If it's not, report contents joined together with a space. @@ -68,12 +72,14 @@ class Scratch3DataBlocks { } addToList (args, util) { - const list = util.target.lookupOrCreateList(args.LIST); + const list = util.target.lookupOrCreateList( + args.LIST.id, args.LIST.name); list.value.push(args.ITEM); } deleteOfList (args, util) { - const list = util.target.lookupOrCreateList(args.LIST); + const list = util.target.lookupOrCreateList( + args.LIST.id, args.LIST.name); const index = Cast.toListIndex(args.INDEX, list.value.length); if (index === Cast.LIST_INVALID) { return; @@ -86,7 +92,8 @@ class Scratch3DataBlocks { insertAtList (args, util) { const item = args.ITEM; - const list = util.target.lookupOrCreateList(args.LIST); + const list = util.target.lookupOrCreateList( + args.LIST.id, args.LIST.name); const index = Cast.toListIndex(args.INDEX, list.value.length + 1); if (index === Cast.LIST_INVALID) { return; @@ -96,7 +103,8 @@ class Scratch3DataBlocks { replaceItemOfList (args, util) { const item = args.ITEM; - const list = util.target.lookupOrCreateList(args.LIST); + const list = util.target.lookupOrCreateList( + args.LIST.id, args.LIST.name); const index = Cast.toListIndex(args.INDEX, list.value.length); if (index === Cast.LIST_INVALID) { return; @@ -105,7 +113,8 @@ class Scratch3DataBlocks { } getItemOfList (args, util) { - const list = util.target.lookupOrCreateList(args.LIST); + const list = util.target.lookupOrCreateList( + args.LIST.id, args.LIST.name); const index = Cast.toListIndex(args.INDEX, list.value.length); if (index === Cast.LIST_INVALID) { return ''; @@ -114,13 +123,15 @@ class Scratch3DataBlocks { } lengthOfList (args, util) { - const list = util.target.lookupOrCreateList(args.LIST); + const list = util.target.lookupOrCreateList( + args.LIST.id, args.LIST.name); return list.value.length; } listContainsItem (args, util) { const item = args.ITEM; - const list = util.target.lookupOrCreateList(args.LIST); + const list = util.target.lookupOrCreateList( + args.LIST.id, args.LIST.name); if (list.value.indexOf(item) >= 0) { return true; } diff --git a/src/blocks/scratch3_event.js b/src/blocks/scratch3_event.js index 1bf798f42..5fbaa5b7d 100644 --- a/src/blocks/scratch3_event.js +++ b/src/blocks/scratch3_event.js @@ -56,20 +56,18 @@ class Scratch3EventBlocks { } broadcast (args, util) { - // TODO KARISHMA adding lookupOrCreate here temporarily (LLK/scratch-blocks#1258) - util.target.lookupOrCreateBroadcastMsg(args.BROADCAST_OPTION.id, - args.BROADCAST_OPTION.name); - const broadcastOption = Cast.toString(args.BROADCAST_OPTION.name); + const broadcastVar = util.runtime.getTargetForStage().lookupOrCreateBroadcastMsg( + args.BROADCAST_OPTION.id, args.BROADCAST_OPTION.name); + const broadcastOption = broadcastVar.name; util.startHats('event_whenbroadcastreceived', { BROADCAST_OPTION: broadcastOption }); } broadcastAndWait (args, util) { - // TODO KARISHMA adding lookupOrCreate here temporarily (LLK/scratch-blocks#1258) - util.target.lookupOrCreateBroadcastMsg(args.BROADCAST_OPTION.id, - args.BROADCAST_OPTION.name); - const broadcastOption = Cast.toString(args.BROADCAST_OPTION.name); + const broadcastVar = util.runtime.getTargetForStage().lookupOrCreateBroadcastMsg( + args.BROADCAST_OPTION.id, args.BROADCAST_OPTION.name); + const broadcastOption = broadcastVar.name; // Have we run before, starting threads? if (!util.stackFrame.startedThreads) { // No - start hats for this broadcast. diff --git a/src/engine/execute.js b/src/engine/execute.js index 3d2e5aa6d..4b1c0abf7 100644 --- a/src/engine/execute.js +++ b/src/engine/execute.js @@ -169,17 +169,8 @@ const execute = function (sequencer, thread) { // Add all fields on this block to the argValues. for (const fieldName in fields) { if (!fields.hasOwnProperty(fieldName)) continue; - if (fieldName === 'VARIABLE' || fieldName === 'LIST') { - argValues[fieldName] = fields[fieldName].id; - } else if (fieldName === 'BROADCAST_OPTION') { - // TODO KARISHMA (scratch-blocks #1258) this will change when we - // upstream blockly issue #1395 is fixed. - - // we need both the id and the name here, because - // this object eventually gets passed to scratch3_event.broadcast - // which will create the message for the first time if one with the - // given id doesn't exist - // (e.g. default broadcast message, 'message1') + if (fieldName === 'VARIABLE' || fieldName === 'LIST' || + fieldName === 'BROADCAST_OPTION') { argValues[fieldName] = { id: fields[fieldName].id, name: fields[fieldName].value diff --git a/src/engine/target.js b/src/engine/target.js index 9a6ad7286..39273fcc2 100644 --- a/src/engine/target.js +++ b/src/engine/target.js @@ -99,7 +99,6 @@ class Target extends EventEmitter { * @return {!Variable} Variable object. */ lookupOrCreateBroadcastMsg (id, name) { - debugger; const broadcastMsg = this.lookupVariableById(id); if (broadcastMsg) return broadcastMsg; // No variable with this name exists - create it locally. From 80b4dab1048e3e1d6a65a96f6f1491fc567a0f99 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 29 Nov 2017 10:34:00 -0500 Subject: [PATCH 195/272] Decode the encoded argument information --- package.json | 1 + src/engine/mutation-adapter.js | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 2ccc80891..aa5de51ad 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "babel-loader": "^7.0.0", "babel-preset-es2015": "^6.24.1", "copy-webpack-plugin": "4.2.1", + "decode-html": "2.0.0", "escape-html": "1.0.3", "eslint": "^4.5.0", "eslint-config-scratch": "^5.0.0", diff --git a/src/engine/mutation-adapter.js b/src/engine/mutation-adapter.js index c40052ff7..d1984d30e 100644 --- a/src/engine/mutation-adapter.js +++ b/src/engine/mutation-adapter.js @@ -1,4 +1,5 @@ const html = require('htmlparser2'); +const decodeHtml = require('decode-html'); /** * Convert a part of a mutation DOM to a mutation VM object, recursively. @@ -11,7 +12,7 @@ const mutatorTagToObject = function (dom) { obj.children = []; for (const prop in dom.attribs) { if (prop === 'xmlns') continue; - obj[prop] = dom.attribs[prop]; + obj[prop] = decodeHtml(dom.attribs[prop]); } for (let i = 0; i < dom.children.length; i++) { obj.children.push( From e5378d323d3eece585f8e48a356769eec529271a Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Wed, 29 Nov 2017 10:43:07 -0500 Subject: [PATCH 196/272] Adding unit tests for new lookupOrCreate funciton, fixing a bug that came up during testing (using lookupVariableById on a null target). Skipping integration tests that do not work right now because SB2 import of broadcast message blocks has not been implemented yet. --- src/engine/blocks.js | 9 ++++++++- test/integration/data.js | 4 +++- test/integration/event.js | 4 +++- test/integration/motion.js | 4 +++- test/unit/blocks_event.js | 14 ++++++++------ test/unit/engine_target.js | 29 +++++++++++++++++++++++++++++ 6 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 9117e991a..ed0cc4d8e 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -304,7 +304,14 @@ class Blocks { // Check if this variable exists on the current target or stage. // If not, create it on the stage. // TODO create global and local variables when UI provides a way. - if (!optRuntime.getEditingTarget().lookupVariableById(e.varId)) { + if (optRuntime.getEditingTarget()) { + if (!optRuntime.getEditingTarget().lookupVariableById(e.varId)) { + stage.createVariable(e.varId, e.varName, e.varType); + } + } else if (!stage.lookupVariableById(e.varId)) { + // Since getEditingTarget returned null, we now need to + // explicitly check if the stage has the variable, and + // create one if not. stage.createVariable(e.varId, e.varName, e.varType); } break; diff --git a/test/integration/data.js b/test/integration/data.js index c6cd71d1e..63048fc78 100644 --- a/test/integration/data.js +++ b/test/integration/data.js @@ -7,7 +7,9 @@ const VirtualMachine = require('../../src/index'); const uri = path.resolve(__dirname, '../fixtures/data.sb2'); const project = extract(uri); -test('data', t => { +// TODO (#828) Need to re-activate this test after sb2 import works for broadcast +// blocks +test('data', {todo: true}, t => { const vm = new VirtualMachine(); vm.attachStorage(makeTestStorage()); diff --git a/test/integration/event.js b/test/integration/event.js index c4f3ee58a..648f8cdd0 100644 --- a/test/integration/event.js +++ b/test/integration/event.js @@ -7,7 +7,9 @@ const VirtualMachine = require('../../src/index'); const uri = path.resolve(__dirname, '../fixtures/event.sb2'); const project = extract(uri); -test('event', t => { +// TODO (#828) Need to re-activate this test after sb2 import works for broadcast +// blocks +test('event', {todo: true}, t => { const vm = new VirtualMachine(); vm.attachStorage(makeTestStorage()); diff --git a/test/integration/motion.js b/test/integration/motion.js index 689b21871..dbb24a119 100644 --- a/test/integration/motion.js +++ b/test/integration/motion.js @@ -7,7 +7,9 @@ const VirtualMachine = require('../../src/index'); const uri = path.resolve(__dirname, '../fixtures/motion.sb2'); const project = extract(uri); -test('motion', t => { +// TODO (#828) Need to re-activate this test after sb2 import works for broadcast +// blocks +test('motion', {todo: true}, t => { const vm = new VirtualMachine(); vm.attachStorage(makeTestStorage()); diff --git a/test/unit/blocks_event.js b/test/unit/blocks_event.js index 2e62125b6..35a1f0b4f 100644 --- a/test/unit/blocks_event.js +++ b/test/unit/blocks_event.js @@ -12,7 +12,7 @@ test('#760 - broadcastAndWait', t => { id: 'broadcastAndWaitBlock', fields: { BROADCAST_OPTION: { - id: 'BROADCAST_OPTION', + id: 'testBroadcastID', value: 'message' } }, @@ -30,7 +30,7 @@ test('#760 - broadcastAndWait', t => { id: 'receiveMessageBlock', fields: { BROADCAST_OPTION: { - id: 'BROADCAST_OPTION', + id: 'testBroadcastID', value: 'message' } }, @@ -51,15 +51,17 @@ test('#760 - broadcastAndWait', t => { b.createBlock(broadcastAndWaitBlock); b.createBlock(receiveMessageBlock); const tgt = new Target(rt, b); + tgt.isStage = true; rt.targets.push(tgt); let th = rt._pushThread('broadcastAndWaitBlock', t); const util = new BlockUtility(); util.sequencer = rt.sequencer; util.thread = th; + util.runtime = rt; // creates threads - e.broadcastAndWait({BROADCAST_OPTION: 'message'}, util); + e.broadcastAndWait({BROADCAST_OPTION: {id: 'testBroadcastID', name: 'message'}}, util); t.strictEqual(rt.threads.length, 2); t.strictEqual(rt.threads[1].topBlock, 'receiveMessageBlock'); // yields when some thread is active @@ -76,18 +78,18 @@ test('#760 - broadcastAndWait', t => { // restarts done threads that are in runtime threads th = rt._pushThread('broadcastAndWaitBlock', tgt); util.thread = th; - e.broadcastAndWait({BROADCAST_OPTION: 'message'}, util); + e.broadcastAndWait({BROADCAST_OPTION: {id: 'testBroadcastID', name: 'message'}}, util); t.strictEqual(rt.threads.length, 3); t.strictEqual(rt.threads[1].status, Thread.STATUS_RUNNING); t.strictEqual(th.status, Thread.STATUS_YIELD); // yields when some restarted thread is active th.status = Thread.STATUS_RUNNING; - e.broadcastAndWait({BROADCAST_OPTION: 'message'}, util); + e.broadcastAndWait({BROADCAST_OPTION: {id: 'testBroadcastID', name: 'message'}}, util); t.strictEqual(th.status, Thread.STATUS_YIELD); // does not yield once all threads are done th.status = Thread.STATUS_RUNNING; rt.threads[1].status = Thread.STATUS_DONE; - e.broadcastAndWait({BROADCAST_OPTION: 'message'}, util); + e.broadcastAndWait({BROADCAST_OPTION: {id: 'testBroadcastID', name: 'message'}}, util); t.strictEqual(th.status, Thread.STATUS_RUNNING); t.end(); diff --git a/test/unit/engine_target.js b/test/unit/engine_target.js index 70bf46e99..4f663906d 100644 --- a/test/unit/engine_target.js +++ b/test/unit/engine_target.js @@ -173,3 +173,32 @@ test('lookupOrCreateList returns list if one with given id exists', t => { t.end(); }); + +test('lookupOrCreateBroadcastMsg creates a var if one does not exist', t => { + const target = new Target(); + const variables = target.variables; + + t.equal(Object.keys(variables).length, 0); + const broadcastVar = target.lookupOrCreateBroadcastMsg('foo', 'bar'); + t.equal(Object.keys(variables).length, 1); + t.equal(broadcastVar.id, 'foo'); + t.equal(broadcastVar.name, 'bar'); + + t.end(); +}); + +test('lookupOrCreateBroadcastMsg returns the var with given id if exists', t => { + const target = new Target(); + const variables = target.variables; + + t.equal(Object.keys(variables).length, 0); + target.createVariable('foo', 'bar', Variable.BROADCAST_MESSAGE_TYPE); + t.equal(Object.keys(variables).length, 1); + + const broadcastMsg = target.lookupOrCreateBroadcastMsg('foo', 'bar'); + t.equal(Object.keys(variables).length, 1); + t.equal(broadcastMsg.id, 'foo'); + t.equal(broadcastMsg.name, 'bar'); + + t.end(); +}); From 5a53323715f9cdf7b270d33dc2ec12babf0840ce Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 29 Nov 2017 12:00:00 -0500 Subject: [PATCH 197/272] Update to use explicit procedure names and ids --- src/blocks/scratch3_procedures.js | 8 ++++---- src/engine/block-utility.js | 4 ++-- src/engine/blocks.js | 9 +++++---- test/unit/blocks_procedures.js | 2 +- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/blocks/scratch3_procedures.js b/src/blocks/scratch3_procedures.js index 22e2f788f..645e582ed 100644 --- a/src/blocks/scratch3_procedures.js +++ b/src/blocks/scratch3_procedures.js @@ -27,7 +27,7 @@ class Scratch3ProcedureBlocks { call (args, util) { if (!util.stackFrame.executed) { const procedureCode = args.mutation.proccode; - const paramNames = util.getProcedureParamNames(procedureCode); + const [paramNames, paramIds] = util.getProcedureParamNamesAndIds(procedureCode); // If null, procedure could not be found, which can happen if custom // block is dragged between sprites without the definition. @@ -36,9 +36,9 @@ class Scratch3ProcedureBlocks { return; } - for (let i = 0; i < paramNames.length; i++) { - if (args.hasOwnProperty(`input${i}`)) { - util.pushParam(paramNames[i], args[`input${i}`]); + for (let i = 0; i < paramIds.length; i++) { + if (args.hasOwnProperty(paramIds[i])) { + util.pushParam(paramNames[i], args[paramIds[i]]); } } diff --git a/src/engine/block-utility.js b/src/engine/block-utility.js index 9fee1f7b6..6ecab07df 100644 --- a/src/engine/block-utility.js +++ b/src/engine/block-utility.js @@ -97,8 +97,8 @@ class BlockUtility { * @param {string} procedureCode Procedure code for procedure to query. * @return {Array.} List of param names for a procedure. */ - getProcedureParamNames (procedureCode) { - return this.thread.target.blocks.getProcedureParamNames(procedureCode); + getProcedureParamNamesAndIds (procedureCode) { + return this.thread.target.blocks.getProcedureParamNamesAndIds(procedureCode); } /** diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 82c5e21c5..5b330afcd 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -206,7 +206,7 @@ class Blocks { * @param {?string} name Name of procedure to query. * @return {?Array.} List of param names for a procedure. */ - getProcedureParamNames (name) { + getProcedureParamNamesAndIds (name) { const cachedNames = this._cache.procedureParamNames[name]; if (typeof cachedNames !== 'undefined') { return cachedNames; @@ -217,9 +217,10 @@ class Blocks { const block = this._blocks[id]; if (block.opcode === 'procedures_prototype' && block.mutation.proccode === name) { - const paramNames = JSON.parse(block.mutation.argumentnames); - this._cache.procedureParamNames[name] = paramNames; - return paramNames; + const names = JSON.parse(block.mutation.argumentnames); + const ids = JSON.parse(block.mutation.argumentids); + this._cache.procedureParamNames[name] = [names, ids]; + return this._cache.procedureParamNames[name]; } } diff --git a/test/unit/blocks_procedures.js b/test/unit/blocks_procedures.js index cab5e04eb..0285b23d0 100644 --- a/test/unit/blocks_procedures.js +++ b/test/unit/blocks_procedures.js @@ -16,7 +16,7 @@ test('calling a custom block with no definition does not throw', t => { } }; const util = { - getProcedureParamNames: () => null, + getProcedureParamNamesAndIds: () => null, stackFrame: { executed: false } From 799a8ab7996717751cac24fcb29adeb007310839 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Wed, 29 Nov 2017 15:25:34 -0500 Subject: [PATCH 198/272] Update open and closed hi-hats --- .../assets/drums/5-open-hi-hat.mp3 | Bin 6414 -> 5998 bytes .../assets/drums/6-closed-hi-hat.mp3 | Bin 3338 -> 2555 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/extensions/scratch3_music/assets/drums/5-open-hi-hat.mp3 b/src/extensions/scratch3_music/assets/drums/5-open-hi-hat.mp3 index 2dc63fa30366ffeac6a86ef54c6cc95325258444..9e9e62b5599986b2005b0595bb8c56d0c2748994 100644 GIT binary patch literal 5998 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 VaSZ@&0DwdU0FeLB?El^1zW_(^OvC^H literal 6414 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 literal 3338 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 X74ieXNkx+n0{~iOCAggB|CWCP{dmH7 From bf5d489cda2253e10ae9da335a7ea9f303934d7a Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Wed, 29 Nov 2017 15:25:40 -0500 Subject: [PATCH 199/272] Update crash cymbal --- .../assets/drums/4-crash-cymbal.mp3 | Bin 17392 -> 53609 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/extensions/scratch3_music/assets/drums/4-crash-cymbal.mp3 b/src/extensions/scratch3_music/assets/drums/4-crash-cymbal.mp3 index 1522b05cb210a9399ae34afef7e139f68149986d..bf9c664793615bcb5f5422b770b02d70e3793802 100644 GIT binary patch literal 53609 zcmd>l^-~;ewDe*@0tC0p{?bDn2DUg8G<|L>t;X=e`l?i=Wp4gkzq0wBJ?z#}4~Vq)VF5R+0+(K0Zx zvU76r@(YQGOUlS9DyeB|>FOJqSXkQHJG**#{qzqC3y+RXNCKv1X6NM>my}o5)Hk-Y zc6Rml4Gxb@OwTSZt!`}X?j4<+UtZrnJU+jEfc{HCMo?Cig`Shc39|kFE{T}0|6kreUJO7t2#g0p&jkP=-fpDzWBmpC{0rg(bi6Wsyt&Rh49VDx zpvZ`kCA9rp*5gpGmEHIpZDoJeKdOh%as9WoY+h6ii&;Hc5i zDBq2-!GM8_PeZh4CmUWsrtoDm5ixY-eAsp}mb3pp&SVYTi^?7$9jA4NyIgAZ2x*dZ zjoVVQ)2gk=-h8ASD~{J{esN-hY?;khXgFf%8_E|DU!!oosu;(Z@X?C&#f=-%4Xx0ibo2? z9&g4Ye?V@v5{&o(Vksur@>`7ZW|%*OP<{DRSSF$HsW+q5x;$#=eu4JV$(9uh%JXQQ zRjy2Io?@aqG%_aX6wI)PHEL~HDm6>Cf(vrkqskKPb)bl8#x}jd=*C`(HXK#UU)2ti zo;*o7n_m0oYN>fzAEW2!!9Bz_+u=WFPgkD1>f48@n>={Cy?(F1Cu9y~&Rn0Ddi;KG zT}OY^R*4z`cihxJ2#{_wSJmce zhU?-&=3N?hLP#HFpD3#Xu^lF4(wJ+LrM{J(EX7;86$=_! zI*B|}6$w*8DK9}PFHmGGlv`k0J~`dRY}T~3aJty=ni4V3F8U2=c^BgNQl5x)HkYz|N1k+jOTTjC#93G zT4v?(e_gw7@$&x#bkw=vO?90IyAgkd`HK}2qOld?8HgI6M;1pXNc3`9 zWJU@AB!8bP0f<>o&_eSdDWT*iU5;U)nI1%mH)Mudnl?RdWXP@zoVMG(bJfOFRW*bt z=Rd{n7{MEqVZ}#dr#G$2tS9iw6Zq&?U~N7^B~?>x-zi>0KBWruas%6U@_1sGy)MOWJk^`EPsDjMIh() z8Z{{p)SUG)(h55NG5!y10IF=5`8g9p{}t1jZ&+;mrSq@Ush%mt{Hk)K-E=szNoCYk zNx(p?Eh5(4ZvHhn9AzDB{V@@usqPqwtiWH%jDzjNG*8)>t*le}EBvhrp(}+M0Ug3epl3Iks-R4{p zlh&qn)y74nHDNsm6IAj_CEay7t^cPt;$P=~1b<3GWnx9(Rz|@SQr9|^FoqC;&qbx< zB`!w)r-6D^C6PFDVP?J2dv)D8TH@?xc`f5yvnEfZ<#A`XtR2-f`w|AtF#uOL$-h2+m^UV52NT4!~Id1D8(@MSO#Sjuc7#jn1e z6)+l9xQtF#tI90Vkfk7J0I?P22}jfqWA0))+x4JGq2sC!W}-8a|!4!f$O*V6f~V@6tkBs@BB7I7KNDA8@l$ ztf+yeDID$})zIGIPNhqKdOl}Y7QS407=>2pR zV*>t%*OeL0=sxl7yJmV6d{8!tn-K!RLB|<^~07`j3pUF{1u@P-c&5X+R?);7Y#MBUvw%E?iB+!I(+s*<|9HZ-SX6{ zIDfF3_&9KL^nXV!t00F6CB2)Cx0RYcPCxQ&ji7wChHPz%qBCoGn06aRe zRd!DsU(7qxF1=fcjA+{eMsupsES4GEgY&xOqW16Rf7_q$7SfJs3q6q|CEndopkr#P z(K@75Er^#<62TUlmXY9mZ`YE=snc57!7KAZa$+8zL;UKt5;ttB)WKRk&Q4a_>gll? zD@;NF>nj)rJi6;HtQYA%>w?CgX}}S$hOJysB(5t*6hsqoQDL?A)nGA2ztZ$FB?j>b zGYPp2QO4u5s6zWE-^Uq$G8?SE(l;!VaskE(3&oi^bgrnP5yCIsC1e%2lPw7mh%;n+ z`kcf2quPh!YZ@93%hhJ33glmZ`XOGvRdjcjQSnJyPB9jY%jZW)0U^q5q-Xx`VJYOw zx(Gj3E!sNVJsT#4pUnn{yy_7~kUHubzbErpJ~#_QEnRMC#8Y59 zrPgvP*PGm#GxjgoLwRI#1&d0=u*$qx%b9T|p(=Xnk!mzIm1LrvGtvepQNE;T(k&;Wt3?K+9RA&78oy%X_z>dQYBE-{UNp^V`f)OA>3EiFWQ}N6!MF zA>ykheP$9Yf{ByB2~qJ_v+pq)777&0h|NL?KZf>{G3$GK1Ienc^Nt>NLq<*NdbJuC znK(isCH|r1yCNMryU3kZj-e;B5*0hibQfcz$&3fX?_a}+VH*9C7q|2)U_;6H8SS5F z5FRw)NTWo9YaTgxIKLsC<6dUXV$A(@*s5#oaMb!A@;9lGgyCEVqcg>gj}lhSS#~0g zHg;E|H@4rC9DV&Xo>^~rlB^V-P#y$PnAoi8DVC)^1opT? z=0S;MEyB|4clo(Gjbt0@65#}n6MFSFEF{emxxwI@nIx%Vo{E3dM=mqO^(l&O$4X|b z7V%`SzNszDd`%j$^8_25xIH&5OP1sk+zVkC<^b)(`s zdIX&P(XFUsOO^>6vb18>d=}26q=@LCioS)+jKime*Dm{)q-skfio~T|-OGjiikWsb zRnUF-v>ph5jAn1`Nk*Uk5&E}AdzCzZ%0o_F`3#gL2OC5;jO~v-+?WgV+XSsckFOdHQDYb;E72R}1VuK*YmNofL&8Ow) z(ac@{ZQ}&(cv9KS#{|gAik|B11lQXtq9OnQKPRwrjZ@37HanvVY!k|+GN|IzmEbY{kxfsX!5_Y>A3w?%*P)n5^3PUsD^(qx(jASq{*hViPLzuW`moNchbji6@yjn5`>p+w@O&)cs>T$wg(s zlOCtC;d#$yH3!Tw9l2!e5hy`oSa*Wn4X%jBfqO$BZ#u$?Rnm1LTtEe@n48XYWSJZp zfMbrj!mOGpkO^~BUyf&S`?Mx3wx)VberCPgIW4>ei~X=#96MZiFYf5|?dR3fn4&+} zcNe48Ds~tJtk9l9ma`xVC51N;dvSiMETYzBzpQqzz5WM{0k!L@0O%Y=Hd%A5$@#8K z2CuQ7W8$8LIl)hn&N2rJNNu7}D}!R31*`FYDg)Qt>(I)VP%u)CMJX+xS8g z5>{Bm1yLf4F_ae}I|ACq?ErHUlSQRdY2$7WYrUfLhgGkJBGeRB*J#$_DE^qTTwQ}^S6r)o493jZ)FFf{q4 z6ZKOKpp2@hsXA$xFz~h3sy#KMt=CONgb*H-o`fiM|GMTW)O;19WnPw4c}rb(-1pw& zJg_7BX};&-ta^wM4XehI67H-~k70TD@mCnT6P`XavN_4uS&565I@Wc<(xHqBN8{yC z|6e1oYqo20MD*&5JPa|O?)8sE+%OoK+1~?9_P7*O!_Cm+do~5~P-s)~gZYqYcH{wr zqfs)YLv?u~#a<*NLqqpDClxs9ju{#E1k`JGDFb6uueKSAjzON&M{)y=EX)H7XGvQb z_ogn)ATg6)z7o>Pa4{AFl5?1jv9d%tGn!zL+z2G>6(hap%=!dlGB(l*om*<9M!mkm zg-uF>L?8r9O8a)c`uY`X49SsMSXDZ!lN~xoM@8P33sfaRs(uxG#^ZuA56%obUuuo^Z^)cEde*E)!FfR*Fa_t&HUh#6(chAQ;|p+ht8jQOi?#J zOVW4wwkV^X$$z?r{c6_ndt}kYzSCov-mYT%sW|F#)lpzoWI}07hK%r`C%(T=6w|%S z-gwv)(nvG#9!N5wXptNpYWD`0I3oc7;6f|EVx=l+z>&c-Xh`T}nbm)o*|Oodb^d2p z0E{JbkXooMHpTPJWh5j*@pCYVg6jkw{S_#}x}=qn8C!Vw=SK;eAbE z`r@2VBt!`NS70)sK|WcEu2XZYC{*BcRPfU|!IU&SE-KeXOp zKcLhUB3#gnvYG|wL{nOnnSoh*51pa5`%vc^ z*Qwsj=3;pGpC5Yfe8MEiAoG=)SS4Q3`|WQ{Dg+%3HQ=tviU8F*d76f#Vcgawr|zfm z)27E@s_}FZ@kjDh=X3m?!zq-NLQFcoq^gJ$~ZL=shj z6n*q44AdM(k=41u@|Df?iRmNDjJ&&bjiCY z%!Z!t)&41$1Gv9|s1%Ob;5ym2jeFtvU`211G-aSvajEeX(Rr!-%^HD`Y>|tPZpKRnbE54Fo*%HabTC^7@ zZg~y8kgWJgNB{39iBAM@u$27m6ie&zqehFbZAia!y$cBjRQ&1&Zv)#61HfdsA9J+oVyYHgK4z12pd((SzN4`qTxir0L^P=H;Ay&GfAvN_>GawC~UW^*%g z+KbSny=ypkgl4BSLk8HUomofPVe#@+9H6G_4U#)PTvC(T`5w|Hdg=$Qy_+Z}rE}S*8n6K9 z%`qUmLhbJYji$qjpH>eNa*W1ewqSgDuo)6+%!O67*iCOAM%VymoJArCwlN#c>N%#$ zzhUM!5GiA&MrxdBC`?<`+_CCa<8)TMGwnk+B=x$(@b=AD=U=#pLMO*g)YQuK40o)9 zkxJYyj(3sBSRFUUD(IOzBh%?c+`EJ*-^gLZ$bM1;UfJaMZV3O^vFT(jD-{!ceKz(; zSC4Q=gRn}w*e1WgAAfr}fKaBZuHM46IG;PoTvG7{!T_K9Ov?0ySM6-5wF&uMk)F5< z+T)5-I4tC$O6riU3t{WW^pcc{2TT01RWlXUGO1M!DPvF-1D0&t(eNpfGqz_!lmeUe{JY?Nnw7l~jmmg|`lXR=hE|1~3l4;)#+GTc`{A1Vb<-OnCo;7{U z-fnhNCBy(BF2hV&o>GAuX*xx348ag|ekfvT(`5C-@@^uz5&pcR*cSNl;sEL!FtPpA zLA7CAuG0D~l$ZngZp&%FBR7CrrVc_h19<&y$6Fu{v7y6wKtukdrA$$;ig&39se`t1 zb&r#vbWIqp4gAj*->$|i*D48fh5Yw&#oy#(A&$vql12qgU&XPJ2{C-s#E9XmZRU&W zMIDSc<-J7T8Hs#KO7gSoZ7K%ylsuLt|2E}S8(B-5H%4rUzFgZwaaHSAH#TgJKJq!~ zZu|n-r>-s0+^>aAQbn)mabn{iemIbrrCKR1o!$qm!%x{PJYJS~G@D(}o4PvPzg1DN9>zvJER(j8*G>GjWPRz1a$G6tx{BK)v5c}xm2Duqs+Y4(bM4X60^5oRLG{07A zFDcQ-Nc_ixE=z@0=7J24+nY<>J9wwwd2OSn$FDR3aWOBOR55D}G~h7f$$~|VkmK}y zR8g0T3ZItnxbKKU+l0o)d5n9-2fpT#hyWssrI-I66yhj?5V+D}Vc7t2&8>!NY5q$K zm!Xb8%WWD;o7jC4qakMg0^2o)iRP|A%-klFGSKWWl$Xa|YBF2Plwk5qI)(U$i9uQ! z8V1)I7(LRBN=y^J6r#GC#7-&-Z`})xbqh8Gjgh7lgj(sTk*<|+@$qBLnes|WFrB@=1BX3#sDHt+{s+?vD1TUdXS{+aHhugwq_2Xo0 z6l$K1J}@d3OZJ@D2%`>34ogpdb9DrD|vLfpIou27(QmQKFQjcqY>!xrivikfS zZf*=B06_7=sV~ZV&4Ebx3L1|UMTu|VvM#2PQ~G7&!10`-S9>Pbu4-h8??qFAL$j7G z3yQ5v?uvvY0x^MjwiR6~EG=%Ez)o`T=lwxFNpyvS@Pr|(S`%k}nnFEptoamWd7uhg zW#(Z3@^k%OlJ)ltVDCC2a-qO63Ty~`8FNW7^c>d41C8Kmd;$XxjNqS_hyVhKj|lj# zkz($m4&^Stcc#~hrQR-eHzbg%pw*&dfwvFm z(P=;Vt(mjsS&|rb8+f>Nc;AwVQgp?Nt_x}b<899>rz?7^Gm*Bhe$tw@Ua0e3PLBhy z0Emklg*$>1C#2GLnjwZVX|@F{>E34mP2ka63jYF2n*NMORqHTVNfciT_4sDf?f@+n zMFFGtVEDZIFeYBivWa3ksV`@y_kM*RKB?0%IvkcIGr*7hMqhRzYqZd)+@e4NAFeKADZ$?5%swgwr2E3rZu! zZN-xQaC&vu4_LE?4hO7K)<91Dg5lbukG9ON1MS`k?4{TPM4bURY4pO0gyx1z&f6Z& zoA2LvTnO@D1vF7rGU10}vL?UCaM zCP*JvU6^sXfFHzYvHK#H)tgTiWf8@!qz$4OnM=%mX*b(WMmLCe%;>xZm3x)RbXNDw zNRA50YTu8)S%~QShNv-t4s2e7<8EcLzn6?K%*bD15!DaL^x0QX#)9q z+2p5h;9PbCf%rfjlJxgOM~d#)Q!u}@CARj*C3~yOvtlzuMgpV`cT5`;+UxUQNgAu?M%{(3WIn<58LObI$c_?By)Q0=x4D*1E9owf{om7$6(zZmfv;- z=Kv$dY=<_t4gRN}?#Yu5H3uaXUD~`l%vY#<=fypjup^-p7acOYW4~4v_Diyg-fa}h z=IF7>8`Dq>8u!43*`~#6vEyJE(az8hh=}3Y;Bsejd-cc68GMuTTwiAi*Bp$l#&p zJ;NoQ2u&w+7UF?q%+wUeG4z~YdlOVYP@#2V^?o@h7v~%D|CsqPHds0$p*n;$QkXBw zH3FqRQx@v>ImDt`UyFHRO%0ODqfH=OgY-P|F-HCb4iSK|WC-$Kx_HToZi zTn!ejYqmYMRpG(=t4mQr#@4c~j%!#otwtlP?LBNt^vR2RMpy5eVQtcv?@}0DB$+*p zcL~D?A!GGn-~y?nP~&y)?;<=6umT`THsiLYR1_aaF;hT_CP7Z%n+d#(Xpp{CB79hq z)~~&jy!;{!-)B0vphXd4naiB1+>g{u$IxG-X@zzrVEMJVYSi?LQ8HA2S3=e;QDkjH zwnbe=z8qLlSvY1%yH0xz5vZg%j7Ry%JcUyiIEYx{g?INyB~snt?}u4TW;ie&zj~R` z&+%0)Tn>#QVLoQbEV#Yq$CPb6ah2MGffj{t; zxKV&6-RJFMndgH1xjyT%TM6Um=oIY-GmGB%m%64`e)rmbhRQjE6{(vu< z81%#zi!4nM;2M-DLQ;3qlBc1g;9KlC;j1k~iL?#zh0m0(?g>9bjwJ=;czEb64Z#kmf_3eg_Nd<<6r%Z;6z^f1c@h!I_59vSj=MDH8;JCi7+jjhuAn zkWQ_W==%CP?(hqukSl1kBIT{qM1p9;_YKwRYr76HE0OrDqhMMYHY-sr*^)AB3&A+; zZy{LMoDqHVl44C9W3AHy2Sy~g$FGx!3Y6D3d&QS_rIC>YKU6vO5)>6ev;r|^g@4wR zm<(zF02qdqTYyNuz#0ou3GL&_=@pWe1=DzlC#(rBn-aT6?J1{deXBuB+tRSxHm%yC zEA7d|{wn$i>vDTq9C2A1$=$X>!A>Q*%CcfzQu!}MH!PK@+YRE8Z}atHyOpNFgEOUz zMqvaLnNF8@b-OpHQ>D3j5CL=NRa7ub>|qn00%|6^Y)B*sSRhQ5mNqBTPey`-|Mk3a z^=r<1bJ(t(u4I*Qyq<5`^UtJjZnm+rB^qDory4|NsK0C8)UCw3{Jw2yrm+?Wze4zy zK{s1dtVGS7UH=m|m$SWp)IxHtr#1xGU|g7J74&$1^ABlLxP3%a!3If6ARm*Y#y&*& zjg9ih5}X`Uj+my%`h$Oq$l^R6o(%r*bIR5DXqho+>k{TFb!aQ64w|ZwE@pm8X^L3< z>^^%*4o3@5xHOH`#!zWd6Jz8D6ifKT%_mE-{ZYoe4bK^!cVlZSyF*EmEg6$5i3QJ) zqot-qH-{+7P(@S-a=0wy-9q{w$jC@MtMXmuAX>tZ7=KQs8J}O3FG*8o;YaFiL`rw}Ix!1Y#Bb;^J`(k<{BaUmCpI{Lk%kIL+Dy4pY zVWl>tQt_k;I9+hOIAOHsq{;F6C)kJsR{ZkUP9sGEkw9rw=_I;3V`_VHeM6R5BjYmP zndAfdX$kBkkW&|WPO$QBsxtNR`J)r|^036{Bi8uQ`8&2IW4sYI2^I%&#H&>8aCxdA z$T_L@UFTa6{AGcfWBzNf*d4U)_tT(_J)k1wkFw;hdCoY~FIQ{L8;Z!0M}v$j;&fI{ zV14s1%g1T`;+Kw!Le2IHJ+erm0ltf+f8rD8no5y^4Gv8Qy;PMHQB#u~EtS)cX;d*v z`u;puY#ZE%@4N6Enr8P~6TN|3F1Ii{-l1-bC(|=ezTe)gleTfUD71feUp;J=E{`KU zmL^b2D4?Detd3I8fdJhd-=k49u!8Jy`Gi6Lia%w>5!1dv@3w8P}^o-XkfKC3@3Og4HMpz*BTE!1u zPK4=Sku0Mc16`{4H0O4!5jKRX? za%sensKXq<})8-h#Ym{cKVnzq|Dd*g3#{%1z%<>Ro0N>yrw-cx? zVJzAOSS5?VMlI=D`2EdYm&f3a;16P}OkV6J&6gIY(q{c?p~t9bg5lksveMI?+4g%C zW+FXsXS*)69u*FLZL?vGS$xR@`0(MNy9TFuev}mXLaQ)Bcbk17ov&~{Sr+`?KM=L~ zFGkM1a-2Lb$+HgC-(E^i%x~Xy_v(PTTYUFgqrvyRWogAiplAe@-TsRiM~B1I(IlQX zfhsYP42+h%oU@aa}&qeCvQtj5BixzQ~&~y@jZO;qAP5*0mMlIDG?i{F#Q!> zlcRom25KQFm%Ve1MMKKYmo67WXWmj>cX+qtHU|x9oA}dn2B)~KtQy~tPVL4%0;M*H zI?I3#yE?CH#p+)6Cz~e<08m|b4PQ`G8m=Q`3`ca<5dtRnX&-m?O1z0WELl;Y)7N7@ z_ZgP(zv&~X^`>e^7cr&MmYE`d+gSPS_=pj2hypX3Tti*ql%O+V9@EadU1O=-foPTx z@<6n#t=Qc!j)5zJLT^T7cW=;;5<^mt7tRSxR=YI%wghj2-hihkZeMnf#)}nsypBU5 z7=S;%)cfdBtO6QRK^-6)64Ul6e6kbPpx|D1KqwDmPw2 zXhqFFV6I-eq*mesUX;YL%md4)kjmmX{JwD~yXlhbqsTx*RZ88@8_~1mpskcSU#*ZP zon3z(Ek=x+DM&7;BzPMgiLIIhCHYme(O%UFHN0+_0p(0&G#k3Stq2{`?D4?ZHYK{0 zu7!Q?K12C+L|#|1`ed=;?PIrd6}Tx*?bf06x6IVjw%T{3K)CU;uzaTvBsQ~NI!iWL#4zoJHr=091A1VCxl{p^Hx^+8~V;_zl2me55AC$goacPx1CuX)0v zaI4)H*f4)dE^rX}5?#?LQDX7;olXn*eAjZ0MJd>4 z!>!5|rlPo3wHiWr8B^Xp9I;#2Te%@__@QXLV`sV6g)pcR5Q<_=hNE+C_j7Vn z=(D}7Sybl+b2s{x=nq7sVYQh_tPr-{>!tK3lzdyO(Ue#+Gm{Q@WMZ*lNS>nEo)S3a zLL&8M>JUP&EPZSXI#XBlx<7&_rv~HX{mnCGr7m0Zq2r z2}VxRlb(E=&{hBM{YQVXe(OKeqMNDip4O+CN$btc;dc9#(0^C@U|mTSGvn=H##{mb z*j=QXw1(dXuz!Qtukt^E`wBqW0kx2fbGz~kG~Gb#R}TX<_`lK&;<*`#6&f=L)3uu~ z12==^z}6V7Trz!cC5@3~oE{p!7>|_X0LOD3<$KSc$BfVyyTJ|r}U5~aOd_HgFsvfy7ejEzuyRI~%2mmpGm-UU)SmhP=b+XQ&TT*|;zlaUx<(^)J~a(?ClvYY*QV3p6&=bwFTz$gz zqK|$RK@`DQW|fR$`NwzwgUr;s`jT8}5?9+}_z-f**vM@=0eS|wn1@Mi?Ub7N_m(aW zQX@+fD>H-U84h<}GP^%Zw3u>D)5kJdqH`RCo>^hZ82x_-1fuNGtJl^;tj&6Tk9=Uf z&9dZ39E%wU{QM>;O`H=|N#xV!M1Sh?F!_U;a@rSB+z^@hVL3C7fV@PK{ciVGER=-Z zP{Z+68RcnH^KTy;kgxpi4r$$4t{WxGI)}d}-9j2g%LrhC^E&Y6kAfD?#Jyvz^|TMf zCiUV`VG#ojx6y^V_~Qo_*ZbkG%77BqmdkXPIW~X=q|4>^3T~GHlcp2m`|(!q@>wQE}CW#*fm9UVTrJc1bo?=hfZ0a zjDNO=@Uaox=N{HdEhN6jD3|??L~t~kz))Tc{R)Gu5@pOPBH)c3RP%eqP>(a@5UZk! z^wQ5pU};pJY_vdRF{A6LrCFFAuL6U0*47eN$~^$hk9xciant?KEj3lc2CXe6wm;PR4{tY#MI53bKB56B#{=Z zik9hR1t|)A{?Q4h2>khr{P9hm`fE)?Lj+qTTs%i_FUk)?X5A-s3xDlo&KbQ+NtF?a zR$nuPfwszUlyz}?XS}NylI=z3#~TIS`$pmR1Q7A~5k%4H*c>6DzjBNaKBk|B(X@ZN zw{9~ettV@hezP)ol{BS!`;s3W1iij4Ir@_anlKweNirGso~^ISdLW$}BDGt!j4t+I zU=VF4i!a}y?QR{ibZIU|S)@Ep3iRkk)^0~-lSjn~ns~Q6BV9>UZ#N?Hkut3r`)l4i zdG>Yi#_LO*FUYK+y8V8jP5*s~Ea-RL9&fKuCItXs=L-lNEp$=Jhoh&zGUv$}w$)=| z2))3C{Kq(d6wN5@bEa>*rnMEH>qw(DD4Q~^y``oyBi#!LK$O*vdpYQX{WbK7iUd8_ zLN#CbzIy||HN&rHut-X%6)kOwBM^%Jy3;uNG-&DPHT)7u@yJHULYYSiR;F3z53FT( zDE%OWKh78hQpy z&Po+vmK2A+0x%_f&X=rE=zV#8o1edm7$?&6g`${$WjBRAJevxC@^Yl-zH5C{8zvwR z`glfBRdCfF`PHmnVI*R?6;P8E&U#$9^aS8w2Z3(QsJuijF0qiP}-t%;>t!sk;WUZ zlpT~S!i#P(hXcR?O~B~CkLI={S2 zk*YP+*D_aRWvrbnq9_fP#K_3do}KduDk@HC9m95Ij20wEBX%efvu!7nK*^PLMINFm zD=$lqCZg2JHA-!o*3$ZJFaBtXpi0b(yc+}ZxUd4A>ZYPZBD*|Krtwm3*$lzb;xTv2zp=jy)x>jRs}>Ev zCEwmtM_icN|Ikz4y(JE}YOivtSlTC}T&|AYTE2hLQpKN7kL@)Zorde&xJ~b&3EWUQ z)dXJElcjPOHuGG9hasp^1Vqxd`XbmuhY485q>(D;Lv)$Mwltu$CzOLTEd3j(mDbv_ z{t%p(mLc;)A44)L_<6RTY8guG4*>YKTHhw5N(kH{D4Hc#flnP@i&+<;nf=Mv9#rdX6HbJMh08goad}%{{ zMuo2PD#)qpr|A5pS%@?QiB#Zc-;!D1>|u)^q6>EkkV-@` zDB?r~GjJF1D5BLeO{uGf<3^fzQxVf&ym#OV)^>27%nk#}`6h^tRJKr_>&#W*Xt*wP zCu}!hhIC$NN}V>itgon5FdFr{iY82CjGEFO*|-G>ReM}QFYK&`)P^fcNSX7~GvzbZ z*9is8u62Jk3GW!z&{M^3X0}iG$>>nD2sEjST?zg;T*=GJYDxRO<|g^b^=Rd=`24<4 zlIHiJ?n&3(_1-Le1PCdEOTOjc_?&)yx}@wHaktMkR~ zlcgvCjAmc?bDp(bg-UDQ)B+wsf`o@h$Bz3RkGHp1*P?>N)S2a0X)-b?pC%DhYVln- za&Tk5@5=NwgCXohmr!l*QYR;i;i!LS7p15bigh?~#aCIWcJtY6*LDI;tf<8HxWI~e zev&n{Rc6A^s9x(bij@xd&nDZzqE!mefKztS3-%h55vSGO_Wmt%t&*uv9t^%gMVga0Urod>ewjJEVH-Ez z!=70?kq~Z$n8H=o_$DT%QdDNuqFT#}0ki4HZeQ_Usr;@6Bj?nYqvgD$OrEFN|F5~8 z#s_r-ym9}SPA1?8xO`QZMo;ket9f{SiXe>XDy*QGjyP}9W~v}eDUM;pQw+h=cSx37 zy?Ev%EL9lP{LyT(_SqAl*Kr5Oqgad9Qkl(*^??f{HN-emDRq#%oEc*wuXvt~)*N@QinT}I_~~ZL z&)zcE=yi$A*{bT$?@Kwfa7f?R>25k>HjfI_ytdm`LVk4GDAg3Iv606W zA+?Z+dF?^;YF7m%u}iDedHYUX^TW$5r2~P&DmUUUbDCxiA*j-5(%-(ELA##`V2W+N zyj1e0Nl`nuiS}!Hv^LRo?kxG57lN z5mxCC5%W>C4Y+{!VmlUe2Xr&%(POmw*_CGala!yhJiw!K+xiqMQ%IN?$D*9Lt(iR* zZLVL|Rn+Nrr;L-|w}n5pRFQpqV_&$7JH9LCzTTt+S(JhOK2x>X=&A?@E$h?Ir?;yhFN;9%rvR1vkeo2Cq1qv~k46f)Q(FZ9hmtCfr)*7VIydB*{c$@j!Aq zn>hxC-embucrHlWICC{Cvr-@lY57MozkI_$Mh?=S_()^X~yDEaodgKc?es2ZiO zg{`8S-?OrE7ZDvmD;3~c3o+?$Y_5N>KtNhQtL!qojN`s(?EY9sM=B8n*%CLK8U}DM z{tn`L4i?uy1{e|18{@bkkB@jAF1c1W<+aCQ#K7nls%0~WYkb6b5BR4_5v<}wQ#RQL z)8T3(7Lr0uA5EHm+mb3)Cr(DI5Z|=sL@M3~w$|_Y?5@>48$)Qjo}QdgdvpDqdZn9| zeI<8Jws4%(7t77n^HcXNNW8bZ@t+b4U|Ey#(!{ZkIaaC|TCL6x97(?OJGes746x#kDmaf6C z?*DC9%l7i}>STM_#>w`{=Hjw-vTd7Nwp*@cd(~>Sp40dD`~$sC*ZaDC-S=k;V9wG| z(Q$ubM)fbi74)UFy`s|YTZiYp=HSExAw&?4`|zus(nv&uoS-5sWEjYxl!`{=&@?l3 zH7)Ecb^p`-j`Fskv4Kl4F=>YEkhW+w@!XcDo=mwDwDqgLSF8iw5nGo-gA7bJPrsu4*WE+&O&yTmj z(cMyh_p4oDBJ>gwSb0XcvA=-Yk+e{Xce&j1H*!%9W-s(ptsrzt#xFmU-+@De!li(i zw~*tm4g)|ayi{=N8HuhIH%#Poz0I?DO#GZayfLsjnLTAI#qayv9d{#JRzjU zjI%2$RAVKYnmq-X%S;gL5T%cY94pv;Nlyq*MRlDWULnaf8jX!MjgOl>(=81E#-~op z8e|;Ep;3~4{7NAyS>~SwWWI2ltgBz7npAKZ>&n_{QcKC_EUmw^w^xOL;ohxG?YtPdo2Xq zJZ1K$e-?k$778l1CNbXR9)1>nXq|Z7aAaBjC+ssr*~X(*nO)`%#DaM@?+;MGB|pV? zzvx>Bx&M&*72;Bt1$M**=nz+3SF=7_X-swZ?wtYr4+C7Dlg3u@jCw4vQ^H2dleJ$J zs)3=6k3?)k8^Ra^HD3cL%7f~+23x~>)xuo*d9e_EV|b#H7fBtl&&%~2l$O-WL0C!{ zMA|^lN`IW+l}R6{EoqwfNs|XBa#r*xg@Z$ey4*t|IVuoPHtuP{c=BYd>`%((U*lt? z@(#FXp6=dc9IY;Pj-C$@JWR=E2lu%I_!54h&1|nF)5t_Dk!d^aG~umt5jmXmBe(TT zSmk@4R}L-JE3329Z&$Ij_Mcy=SX`Q;rFZ79pchvBuum@vsqau3-JkW!-fj4sX`z>j z52x2ggOYr}ko-%QB&Modm2}`+b|YU^y6K>q?EtJsw!X#sg?-C(PNnyUV(2A}Q7t-T z0-1u4vC_l~A2Fy$(DuK=a`kn2bM4j)qMY_LH!4VH4Pj@r$P-)*Sx0*BoU5I@2cd@D zgxZP@2utx$Eko%hJUv$z-h^o4jg}8E$3&4py?MM^!m;q2X#*fv;DXbBftW4nfvArr zF~)|Tyv4>|%f)xk`gj+jO`i$W=Wu+KF^3U2o5F5IB9BUMoF4(uhPPVS-?I7I$%pYm z?IcARMXbw*G^tWe2>zza)7$XJ)E=c9ZZu2Rp)i1IB+_zwI`?cSmSUiwQkA(5H8)WK z2tXvs+jaLefh>RPPoutFiStTB_(nHj#6B~6EtFCV?seYT1TqbRnEP%X!_5Fzley{9 z2<49q#tL=JS=v-eUL=*)%BbeMQ7{!ApAL%DVKy{2uRMP5Wl_bYN+gvK03ycew^R}= zYSob14?S?=^gU2+<$u>)EL(4Kq`jCH83>cu+#SvMGi|*k_O<2Ii(u|Qi?>vdrCO;$ zObPFoO`_b_A0n0_Nwfpccb#|61n2IfX$L+?8`@dnMp+C$J@x(<@sq&sV9)JpF#sU) zaX~HZj624JI(*mqEYhhM&G5APS;q6&aa|U;N+{|Tj#7w%8=sb@vbjgk&cPq|$||Hq z(%jd6_b>t285!+C9ZG>`bIjwcq?;(om$dgATUo1aJz!(lcKe?b&D&<)+uK{?h^Lx- z%|?y=q6R-f;1#$x@dQ=h63T))8Oe23kbSxMS|1K8=3!qf2+#ws>kw-xApG}@i&sUn z`8m#qvt3k67H!(AGzCe2OLv$!KdpWOrmr^h@_FNl!vURmJ7{klm}l-~5fAGl`^+?nTx9{2e&#K-?TXMTpXP*Oa*eqTv*r z@*G~5MWkFjA8|GJ)}0!z{-fc{8c*q8Z##vSF+@$<)N$4;q*q`(RlgvIOr%sc>Yv2DS2d9_O!rh>E7Dl(LzqaQkxp)5H8?BM97@Q zGOPU52K{OvMTG`Pz3(FB?beo0Q`zdO_xU2BqG>9Ghb1S>97lZ~Cm(5YN|tN5;P{W9 zgXK|GZ^?ALMMYJAd2m0U}sF8VoiaqGD9 zD$D|gtreK1gF8={2BLyfSWd&c+9RDrvW0WF2XI^jO7R~j9%af3q#ZS?@>qH~B{->F zvc-6XxTOdcuue_USeNlhQLds1ya`GO2Z!iRSt8bmN}Yc)yaudC4ipt>Vt@8vQ2eEL zRuSn&5eS9cb85|ylPa_`%MrU~fP4tAT~h8AEY$sK)`0%b*lq)KTr)0>n=wA zw0-XP8TBp;Up4hth?8^>w|5y`^QoyABMZ~vHL+FdSI+J)vEYs2&6P4?r$rFQ#z?CC z@`sy3Dzs(cWBtDjg&+Y3K%0ir^k_NXcCzu_Jg!=4=f_Vy1K zlU$!Y@ih9zA$`ot+XDt_#)IoI+L-=>R|I0gDUKVjk5V(2afG;jIv!)1VII37YM6do zQp!bBMM3{0sR&2np=`f{Xhr{1gbNq$BdBI5{%$fM|~lqU;4(< z;-7Tfm%4w1mobSp(&EG1oXR5L(+|k2qc#`lfw(m0)Q|N_Izr;UW~I6r12j()>-PSP zlioeP_(|eVDIV)qkB5h=K+<`_)ddL;#&*hI@4z7jV%O*?L&R6R_EjKA37HZkQ-56z zThkJwFpzM@k}MTYwdAWoZ}JB_XZ*R}y=VOQyBCF}SkIj+RbqO5}I#f7KCLJ6WSc2?p1#AwZ0(qBM5pGV185TWYK#KCS9buVyW>Kolr%$$-_ zAY4<2U!k|+RVOq*v;0rC@N&q}ETF(O&8xl;;@n|gOx=U!h-S55@ZpC(D8MJNdr{mt zQ>?_aJ$`zoLjiQZ9$|X(r7>T2dq2ekyVUMmhk&caLH2{D9V6Ql*CQOoWjWoAQlZC^ zr(o!7Y|`jh6ZSZ4_G>r7siB|DE?*2|`nMe#Yq$MgeiY-gcgcm)eS>Gx za*Ii*siG(B%98rSHjocptpJqf5-!c^NQ-!n-Y`%p2A=?zap*eiDbOO($d`}`0FicEo zK06?}4tJy_=~1BT^p!n~ka!iVo8`QC8$5GpJlsBppKScN zPLC^{t=P!~T#KH;36?kKLXb_m17ETZd(QM7)nKNL1U&Wzyvg${ueAAHmkZ+O_dHod zZ-TwwWk(hJKHKE~aHzm`FgJY4Deo=;B`_&NPw@y+cE;3!gdof=u~nZt);4*qbT=@Y z_}5qmZ0Ylc8z*TZ7ev`D>b{XBk;XwuZiA<8(cCF>d(k0E4mMJ0l4C&n>r*n%wU=ea zcwu3BMQG(G%Y;t$OT+laiHOmIF-&MIb#Ks;@&k5=N0OROkuH^v-kOK6^6oEwc9z4w z+5loR$3n0h~&rIB{l*Qsw3 zqqHXS;1aYp_HC?A1D{k2_9@cjLBk$RB@(v{V3q7i@j15=I|1sD#%wx`&*DfgW}+(X zA!zx-p=5v7ae=AQA4jps#ePuqi-rAS=Fgz)$209kCZYcx5_3de8Zfl&oH@mXJDdMU z>jZxN#)t$_(CF>)(Mk5o1K?w2@y=4{z*NZq@pI#*T^R=YcPWfIq^kq<;Yx&UmAYHy zbOj2=ql~{aXzSFjbkld4=9Bk&q_X176>$ToW4vR2b>9Sgr=m(nZHk6TphZz!R%XQ< zr<}{;6@)7LGby49hwuZ%H0|#$b(;e!Z9PYfLQbfw0hVfh@@SUuVvXCwt?=fQDSyVf zLR@U^6s~K*Fg~ncIwon?I$e~GTz2SwvpH1HM3F+ObiQ(zA&(aN&TwfhqZg49E}Q7f zQ4_L^(V?G<8*=Fh2p%^t@*@wdsD+tnqF_p5B?~OxrY16n-#?quQwJku*m{|ZL&@4p zvv!hjhVA9GxEEKhSaD9$&Vf(kHK&cBWrYJZU9N&*ueIz&P%;ALE^}if{mww_O?jQ+ z_e|+BksF8FDCl_5V>wl9pr&Y56UQ?H;Pv<0Tgm66&~DYyzZ(`OeZo)UetsxW!07Z) zGl*Y>LRwEY>cL7QoEJ;QFV=Vm8={VT6_-3Wao+u2Tiz3c|MiaD=*A;lI0R4LMxev4 zHo48J%QL}DrOhm}b=85@V~a*NcrX<@R0gGW^%GZ+as49B>TrgM!agTbB)Rxdm|ww| z{-HCE#jXv;6!xESxPn+zdTyhNudker1aTiJo9@sH>cNlp+<^TZCB+8hXSaL^}*A>Ltyll4)KE`%65 zlx;zB-g5Hbz-{vw-QV>(Zfdl6POs_Bb;YKjsnWKyidn|DsRhIq1=PExs|N4-;#ItY zzdKhpX{eUPhH=9GYCCYxNCx3W7OBU~QrgEh8WhJ5BLdMylKSGMn1EICANI0+1`F2w zsMK2@nbZ8;ttwYaXHw5`2{_M+X1x+nr`U7LFGsY7zzMuMH)$F^hP0zTdY)d7->{=B zf?M-q+qBGBA)tTUXSo$@dIuW;D!D^P_C1$vW-0FpPt%ts7^RLv!zjCCG^y@<<oHQIIv2QyD&<#i6M#S z*4FC&bIfbqXEVain|j;R`%TJz@kR7-J|`s*3THysw$0#F%miwwMtb6K+C=%>xwVb+ z?MRrUKR5M({mYKn(r(g)qIQ2%EBJW8Wz&YYSA~BKok7h8ZTdq<)tvpIxPTJUj{Nj) zP~woBE!okvB3A1W_PL|L7yS*Q-Q=4UB7NvdPeV z$r*)_|5yNMC3H8=kO0;maVcuiizBu0Ukhuf=)+mOrL0BlcsL|CBCY=s=`V{;Pv*Q{ zEu_|(8cKExyBYnPhMMOL5_}EVO;){OySNa-;;pSvwJx)^kc5KzGLVsF7(FZ_Q70bK zgN4*7!g}sLUuu~yO_kOmN#5j<)o#48`RoI(lFtwSC)Z5gk;#}Zr)_OaVUk8uQ5mAx ztbmOS9(p=?VH(=F;eo5wET%`4$&b`^dldqfs3%hz=DSl|&)c#p(K~-pi=R08rwQ91 zVvmQJ%kIstBPTUOTjbH6!FkV3btjK15YTR^?B9kqF|kTv`{rr%)AubKF@f&Z+KVKh z62!vm<6&w34nNZSS~+ZBnvkF9xe%G@KelqAY)ZfF&=tr<5>)dOW;|$bRkjynr*=a{ zeo>N%dWpr>ERvmoRHbq6?GAxYeegUyB;HNgDVLzXjw>fFV?n53*m*Lq&Z2O$c+OJJ zW3Db$AiGVYjfX6${bo2m4=i3K-^EJLBz0gEd!ogUAU!fz?eZ>4?L<4dlU1|>+k4J& z+mS4Vi+EF+eVXqPUURC<^}HXDddYkL-Vm7NK1>cAX)^nNtYxbhQZ#yHYvPu~M&lAA zxpSBdCWjPDRl(Z}aWKwmGRO}qR#V!#Sq2^y7k%8fHC!@}R&{yP)$`nPw7xfMIua#a zbb>bbWbBV{uAj}hgC&_M$nQuH;CNl^b%~wwjaA%0d90l>_A}1wA3jr{Fa)HWq9~2( zx!AZsN3z>^z0g+G`64TvP^1RjrmX>m*oec7V(7>^Z%{AS%W_M*(yxzOE661)k};qT zH=s+IG1n2a&%33IfT}T82w`1~ZPVREBn53U6R~7cq*!$QV5@3}UCIgEzCd~ZpV4_AOt1A*M znQu5wQ1PA(Kv2Y!)Fcxk5Yxt&{x@~Q)Jw8=iF%QDrpTF0Grhqh>S%W7pj}@Rl|kdH zD7wS#a4>1-gI)NXHHCJzpz3d@`usQ?4xZY1gYOUP=}%r@n#cX>;#ztz5Rwx@L9y6G zywpEBQ(*Ql5y=TwJHR@-!+;(uVzn=wm>*qOQn}Yt!WkLIXw712>e0BP{*k0`+%FC# zB>c;-Kv~}Vl0d${(bMt8(KSEeUgb#`L^kxsIt>Wt0yo2(K7H?{^M1d zl0Mb3gts?KIu0o(^h!0&E%M0MEGbeaJ0=pB1A+f=KP+M71}N+23HJbc(tHecUv<^v zbRy^`xL32!ZASC@Y|Fnz1dRB1$RqodX>yXk+sHQXIrN&cig3RXS`Qe5r2d_?Mj{7s z^K!%;5W7D8?yhhG(-aFJ4}`UQ-~9PChVttH_dU>^8Wv*$k7;yyZ@+KDHjRg|KFvC; z6+f$+4)>E0CrU4Mr$Hy3jd$9zHY{UF8;xc3Nk>UmIL)`Y0_p1UJzR-s%f>MU6hKzO zjFs3w!5eSw@7`ik#n3n*&`4sK`$b~p`O_h6P?|cfou?T=}gX^iZ4y8B@RAggmlg1R;7qUc@Y6+1+=VqPrpRxe>Kt!-4FArm&Md8z-+uB$v?l|6 zO0?7<4(r_-J_M#=>4=_pZ`t%#(Fuj8fuRu2s8%r@i`?Kv@L?nNwd^h#lJ3TL(fnEP zwrLW1UA0x@Z^j+q3JZn}IEMQx9jbYFxX_K#;$VB$#2RWIalz)-w$)Q$gHk80uin3H zRU?V0MOAggjkG^oh@6e9Vsqa7L*}3n<+y08#1W4!rAI2=<%)$S9WDYLPt# z5W1t^P|B-~?zCBCwMpk=sGh~!J;@4h_^-_7&17KJ`^sQxCvjo%_Wdp;@<=t2z z!_FCeXgdK91!@v@*^jHl6}WndCmh4CbN)_n){|nn!C5WWc5e06M*xku+MffkI;E*= zVK`4)7D{4TQmW4io%!V+A`cDA!({ezhI$`S3ln>a!E@f3~WkpZxskz8&M@Lx^~A5xks^iq2p}QvTqYTy)!{nLA!f zFO~Emf9&@a6xZ)GFa8riuLzIe_i#b@OR7mRI*9>@hG0)@aa%I}!Y$Rp`DQrL(5X$f z*l4poitFT41X1I$R62I(0ud}|G?F_BMxCQ90MY;ah)QkZ_Q6-} z>pULxAboT)8fKO?SLPi37>U^ss!oal1|s18XwUlJ*RykF-&J{MeDNvn!j9Gzy?;kG z(%l6-0(Z{X`qq|VVvvgDQb0Alsg#7@|3g@UVq(9vXJcrWPO|OmP8YQ5R{GVE2Qui9 zE%ocY){}y@g&VI{-~vU2;+Vmov)~!v`op)nzaDk~QZ%_uB;?8hGo5fF4|-Vkp`ZOm zT(GKe2c(tlG_bImC~8k__XXrbxyN zT#BLe&N8}Laz@P3sG`|4laGdt*0?C5E&itE;m@mPA=vveEvqsjGF9aWdI8kO&s02bgl}1sCRJzeq z|AoqdC!7S|GNpt8*R9(4 ziIx_|B8Sa=XdToW1 zN)~$9!7LS&xYXC^CGW5>&i`KGAc~75Uk6?z)!hWFQ^AqCgA%DImCNhs=XJQ{w-%|9 zd-R_*1pXY87KT{E?hj6@r|`5%ohIetnibP&ur?GIbICV*9e*4}0$iXcW%So${AYsh z#l1_M$^Df8bH}v_QClWx7Y=Jbn-??&U8echWe*(&^5_|P9;gA>w>Lo*iTg2_3m?eXarn#f zkXc=JNx=jn&}neS^eayR~|8g1mF-K7Jpq4}FApAmJUcbUzBiLa3O zJxtdKCt-p*er21Eu&7=L$T3m{sOj-oEOZ;K6=68u7+kr1&LSotL8tS>E3f86VD@C6 zD;cu0kcv_*CG~yz-FLLkn(R7ywiPc5=hIT+@{T>qDQno4iClzTIQ61*L!f&ZE6;!J z2XrWKMu6zKUD{FNR$4gCEOpbttyHWTRGZz z|9rjin7z4QYA76X2;Qv;d7j~3>Ny16nL~y!l>|KZUikZx4`-{~$glmeFe*86b{MqJ0+~x0&1xVE`T@xC< z&?t%@FHzx05k%&n{#vn;6}-6mtvI+y-Tiq`ue{&X@wdJ6R!n1s`WIVj3eK=R$;A!k z{lUxv80~Qj*1;xL3h<~Mf^Dc-TLXa#Q`NOL5zsdLG%bccUC!#VU@&G|ajcEFs>`e* zV`D}DUo!8|k-5(hYeW1KcVd9&EBDi}-*QjTSfgC5fH|JG2T%wvz`$_9jCknc|% zn~scV#A1Q^n@gG?LV+7(dZHOLKTPx+UJSrZdBdAya9=@gQM#^9x9>pefuHgbePnU0 zg9p*CX(9r3h>CM*r`$>jjN%8rGVVm;22J70|{ec1=nG^gfjF- zr4|Y*34j%}Q&+2gDaYvCt)Nm^2}8{KzXPDZs8sfgi6I@=g^KuoB6h>RP8@v+cFFuui}r0(8#fapTqIG9vjS#! zml16C;d^&Wsvpx2vC*cf&5`~+?nr@CjMfxA9KO1Ssyf zK`!bP)IbSyN1Nvi5TBHeJ_6S8$*?jGgyMJPPvEX7QL0)aNcRlf1j#&__wn<{N`)c%~a0e-@o`54)abj zGq!fYoaB&o6HoK^`8pKBMak)Q`DO$rGhB)dLQp`xz{l^Ycyi@5^o6@^0U;Uj@T{efy)`vh8>N%tV86B!)sB*%7MtUdR*fmi(zu zVrPwwVvDaI3ho^!<|fIUx$s*Up(&*tIIb5&Qj}DXVZlLH14zWYy4c$lAyY8s0mgP2 z;OUnD1`YhX!u6_{u(k06Sd$lGv3HD;DbzG)$p;fIpcqd&CcU{#+v!bPHW~5|2a@m~ zGMxFp4^>Z{Z_}uWK7Fr)j}pPRsFXc=XAxp-fGL&^s(t6$le0^ zLzta4$XI?iH83kd&_Q61fD?5@plU_a#Dq_G-yBI?c|#)+G!7oNks8I|K8AwXa44ST zV*8O9A;)sDjx z!=(Clb(HRtU`-5kBh(7qpYNmmowec;QCDQILJWkmN@Yl*QsRY4pk?#PgMS!saophX zx4&$A1uKmJGD33f7}QcbNkoXK-m}zb7F+zW})jff8n&()7V|@U6jY=_~*7SSqZ}` zK9k&>bu*aOX1{or0{^S7H~s~}-H*_^opt5jWGtM_kIp}&Gj)BUJpa36M!!s|DL1d) zjv2_8f(1jrOs;OFN&Ib3wfnALI2-p|s)ODaRs4O-haU(Q6&HH%>4&{DyHGHSXb%)& zKS2j|GAJOW0#{N%&JgyE&rdZ2xgh`58R{iOF*0M@>Z^rw~bgd0>TVuyhq6t?lwZwnP8`qh%Q+#4>O zkAcje#NxBL@U@*(u2oGY8arb^Y`QQ%fKMbu{^IS?P)|R}xxzuXUJr z%>cMLpXsrG?RoxE_@X$5PkaF|sW+|5KtxLrf~vRCH1E&-HX@{fc|GRBy%sMQaq32PWr8LaI)z-OlFEe&Ja$5P~yo zX@37_E|*vv5mBzm^gNL`6|~IgT`lpL15bb45)Pw%qomgAg^rTN(q1qD_N~K{lHoy9 z@UQOO%0f8EsT?!cR8vLM9{lFa7&UxXIi+|BNV8svy~Y4#n6ZD4ly1|y!mbt(v$hxq z;Dv648pUDy06KD4O%kPf-i~g=n?zLA##u8 zsNlO8yk4f;FY##O&S^1flrv`wH<#%O@R0gHez6^jgnI*PNx?&+HVu z1a6&DAhCtA;2;b^BqNtduAE!G{Avjw>;6W?aaJ9kkES`Cnx*~daDcP-WQDOTvIYSo zJYpz_3)BRrd9e9ZTFZx6*Ef-x5^%C*`E)A#bt8MC>*urRi_}n!mA((Im?Hvgk*KkI zp^`yDAQaE&O5;d*PV^5A;$Kb~VBpGXg-OK52eJ+U><)=1wIia<^j#O>Mjy`yJ{@U& zI_Sv&^Ei!Cd!20DL))NX--6?T!p$_2$cdaN`J1#!5fe0)c%pF&(^!J9^*xMsHur#9 zmE>|lJ<7S**L+UC7L$VS3j5kT>2rN^GZXVNjjc`;gS!{o_j8Y6p~sVuysQql>Lzv} zKD&7I2EJ=#xRhlaIt5Sye`HCjI`lh%-@%3rOrC?3>kyG-bcvN;cy!8|yrsBpqChGn3o5eh>aruy=>KW=}L#klX_q-nM+sBU4k75(=shUK$V8eH2E5 zQHBtT`70>BSN-}$n5?UE7Oi8M`;ooIx5lDWeKTgnUu`+sKLJa}P3`yD2mShD#n@p- zVJrlAAtXbV8zljTCUuP z%TkMgnFWNx*?Zw<2_)f@xuM0v-j`Y|s2Yjw&>iaOB+XJF#YJw<+`(?~N(Qq*P=z9# zL(%~H{Yd=I76bQ*NGPSH^|?9~Pw^dWj6kp?y}-M=znk^QF9u%-;Ywf@wj-F@GiJR@ z_0Y6U)Z_ll#03||Ka~68nE;o=jYS7+%Gp6m=OZJk8lmTc?NSiv$u=x=u0Ny>ImQuW z*O=jz-IQJduO$*DmQqjE!ln~+hi%xdhpBQC5%U z5}>f^qz^QcLn-POAAu^?i?bF(507h+SNjnG1>=Q`$h2o7b(atgtEllc+ez;cSS`$Y z_ZEOkUR@rcLs z_i(qa_Wfb+uki=(>2-c?*aXdD344b;f1IUFt95;22YAunF3g)0+Pz zqU&(>Dt3O-`7E6t8GE&*AQG|%-NKYQArU!%iib^1FME5;J!HaO#`8%$F7B@3Ob3QH z{4V>+mLzTn1H^4LkwfnI>w%+D6?TE4^Yr-F25D_wio%3y&i;3c`T@5!9L(WBPtgcI_-%g z_S|j5ouK|IazlfJODNY2nwMr?ioZuSn8DWtseGtVHhkJMk@>E45t#(gFr@4SL=!`)&FedFo2uzx27HDsYW)d55@}yo1fOddrj_ zhe~aBjrM^?2K1F=?3dQh{|Ebrw7|P$IIHf+FC=;?6D`n!v@mjqWhx=SeRoaU`tLM z<_CVQQJw_Ve!>m6swGwx2zoOMbP=4|*vNhz^2A;*^!HbGUgEFnn$T3l`#XF1Ci`el3UC{AaCNWP0V^XPKmOYEL zZUfC7H(|R}s|1I2Yn)M%=Lya6&|51%bTzIopVyCMFli1@dr|x$t7I1|##~?aUUP8{ zo`oi8lUuNBS?R{Zs2x%IYZ8xSjq^d0g$OaGI@z)US(*k>1o+vT%8}vwz>%6b^+)11 zJNi3}F8}emL(@i-#pu(Pfae07pCyVD#+D0zxVy81t-+T6)!OEU?>dZDM>-F?^BLd7Fw=c*P97#-C(Dw7 zMsvaz;+Al!KvB91>29tfL}Mo0XHMl&vMbIjQjbYsI_m0&U$pi%;H1w5)=fN%ug0UR zp=;61fJSOU39b>>JpLr(Z~2~) zaVVRs=qQrb1JI7etU6E1CtA!RLwopeEZ)T3i3ssitP6_v{hxJrB^?2o>pN+_ujBz; zVd(a=(($*@?E~qF{g`g8YJkFUi_WRxDV*&)QdiLBn_QcOpWxu$FfcmGUHqNnq|21T z@ZUg%_#6uFU?T;ljPXI3jdhwpd*l~JJc)&*h~wA5?k&G3B>zFa_M~AsZg>aj_2P$u zVhd7`zxx_?F7`#7EP#!9=J!cHy2kY?J2`LU3&%H1+=ehLZUNC+S!p-uuG9vrTMl?L_W)fg)ynnx(If;jUCdi{y^9-1UUg&$HY5e>P&Zr1WlQwtkuh>rmbAbvQrjDd^NbO4}dgkyhzKoyYJAT5MA#073Ib=he%tm0=75)^-zCOw588}f^F7P+tTjAu2NC! z^3KW;=y3@6yjmf^q6l)WBgBG*Gb_-qrYs2UH1xTF8J&hNTtCt<_rYL_`k`@LVW|Wz zSB6XWkB&={$Bg1nPs05@^Tj5*be)L3Q?td;^-C4xQgdJLFC$tye0r(L489-XYCl*b z(SBOLvlJ?DfsF>jQjA^qlF#1ZC9h>N;t(!FG3<;tgmbE%3ZdaYNl_@g`VScsrrjcy zG*7vdXEcPNtV@Ws{N|Zw5)}v=)6JKxUZp_8|MO3|7;Wd(EFC0b=ES2x{cElT&aG{7 za`NkDByN6J@JUDIG!m@m&^`@DI4oSH7=llM@lz9R49z5HI&MfY*{U)vy5P}w>i%!G zf4$7qsUz1c0~s@mOR51ZtSN1|cM1iRH@WfPY*dO!{twY|6hD(U0{>HbzvkD__Mm{0rJxdqa^+9mTT3 zwLHM#F3Gaf1xUM6hUi5BZzj7?qTyI6A*WAG;Pd5|-oJjQ4;wF=%Ac`ByS{?LLLm?S z>FRHDMnefI+lD9XFeQ~lnXX&1{g-nek|o@PnS(NtvA$`x)`RQ{LUSPcfG5Mb8beI5 zQUIYeKP9FE1D+T$^08RLjaulpv*{7i%nXllMO_;M5i7QZu%VquUJx!B*8j#`{N z)#6od#+P-s+|?axC0FF+*hrp{;7jv6kt~?YaL0V>SKyyTiC6KQ=YG)XJ5^%iehXev zRuQxI@DzJzB};Y+!U(ZxITAXux|`DH7SE-KA9aFQ%xNYT58Zl-)?Auvv1W{_yYDUm zvgWa*%=cb;dzZbZaY7nT+1o^PoRM?K6>;DF(Lyl4(+({j(9*`-VV7C`6?N2LLplpe z1*mar>BvNi5n{(F)WyN`UX|aVf7>BpcC=XAT05tOo4}+<`Gzr{bhvgxD}LY1ENyt) z@`-kYl=W}%lHpG3CqAmlL5qrC$y>{%kDR1*i8zDZ99WPFB$0VYR>ec)^kW9|q7L2O zSuYcb9UGlPZ_UD_pjPL^#AbB@`5G7L@2kboMXx@K@TI~W*koL)ie{GrO+(Xzo14?| zLdF!PY3~qMY4PRAiuNE&O&(FZ<`^3pENv(ELEl)#l1(`1t5J-#wT?ROLwB`wKgh?R zlFWn!_l{oD$$f{6)O@f8;l|P5mLEwsYZ5L4Wpkn1L90sm~M`J&2*qQ)s9e^hE4RTS=LgpIr8#X=QV6JwmGdQt7P z8u_AaBp8&D28p`(*T9IgD1l_EiG4G64jnUv(%8_}(C&zs!*X0(iLq^#%6h{N*EQXHt{f+9#t z*08HUW7QL$@$#v4csdJ_9cU?~iI`v`g@O`wN(0#A^Ag8lQM)1esOv0FMOm3^tfbOK z=&079^3z#V6P|#*%I@%K0yWb-v5}d8=?-QGYIjx#&JsVeLDgN8+-v-p6c1!~F)1ZI zU~pEHK6RSn-je41srk|M!FDXxY-3Ur-zPlG9O4FU9w3$1!Xoaz3A*mEis$QnqMAU> zd}>WuICOy`vW{yODX5I^vqNhx+zr{iTix}%4N2Zi!s&O{{Kgq*nGT->N0l$uzAopl zRRBHywUV2Nf0Lsb-(;#JGJANN3rXr>Sn3@(ySU%r@Ex{o47ta0yE)$;C)^BC+tDSF zy6fROFKn5-D&+{#)46HAz~N%75D=NBDD=I_p}xcJD8R6WhHyHtkK&!|j?S)1Yi(GU=G5)i^-jte_?}U8?{;>KBJmOMm!FasQ(cQ&n3|&yn zs4G1wUbDfrir#5eyo7|@(k6@D?MKrk8JZv-(=1#b{9pGeqq(hu5mx^l%Q}Pe5=?^o8iA zkImC)*fa zAZ9`qNe}HC!2#sWC?2n>Y*4sV?z6po-agy^;_P4Nqc+n@LtDx9Ee*m+6-1;znelL${b|u^?e6eC`0JGEtZ)F-Z zmGxzVz*N}2L2Xc;M`XurH-wRyTqrF!#T_G;jg*KlAo$I^qjY6)bVq zw3V6^P=jWQ^8QJDJQg~dMW$)5qO*Y2-_EI~46k7|2LBl!qW&Z*=l(>cR3b%`)Ap%9 zb^qixN6BkTC>{>TmZ5(I+D}a&$7MREWu_K=RM!!R#1Hpou05Vut-Zx9=@Qhi?b>o} z0^UR!KpF)?T_@e`IWtR@Odk6~8Eow=iol}wn6$E9b=6FlsL1&ZRJM!wt8IJGG zMz3{PzrC##HPL_W&}-pmuAQa;`lP3-eHb2yYpe%__s@Nnhj zumuu*qGIr?!6lOYIaeB0#I2*#6*jy_u>#;Y!lYW0s+nlsd5}uCVWF`$Dy*eV>aGkr zHx-C5V$KKk+#xlcFp9L!7GZoU)F?}r`|6jW!^^~EtWcYFwBAn0-BZ(JAS_b1-WVUK zamAYdO6*@&Ky4%@0&d~L&qifU+2Xe%vjzuF5@8` z9iKu~=zSTYf&qJbvM@xHj`*<{jX!h5r%2i3=nEcyw&|MrgS1< zLIk`obg>yFriOHQXAq-6q}$~{_YxuTVvmwoQ1G=ZvDP}U6LH|g8^I%O)P1&qF-MbH z`kP=4H?vBvc-lWX@BXW@BRh*8mhR5e@Ml*wA!ZPc2R>Qi&J~Kv`-yUjmt_kAsVped zgAL%0!G@3T1B8bFK%-zNf;~gDD68|;`IKsv29d*tF14QWO<63u<%_g0H$pk-nP=xG z^3rP0xgv_+nR8nN7^a!%d}{jXlNJgNnPb%OSHjF0sy?q|?9X8vsPPOd)UCeLDBn3) zs4<(O)R=g5sT>R94-FM?sg4G!MpGcg+k`ae*-_S3^eudY1*N9HefO-j>+H_VB}Ja8x;p#_yL-sp?=)9 z#WZr(Y{PA>Q=|jkR*7+0PVR_))e#hJBTHDe&{nrcM;@xJTbHF4HNk3`mA;DxUP4yt zMn6Z7V#P5bzI$J_Vxb3$LB_ZUs@fp|d1cRSA_mbcz((f8XPS$-M@&+H~Fxv zdSbZN@zU%acYGE#7-Z+W;i4KRf2rgaB3IZg7Xww>NoRBwPIYxW9P9Yx1l~|k`|G8K z`o6p948nQyx+_*r_`U%jjMzdNv{+}7GFE#|IzeMLwIh?aJGbtq4a7F?JUb7suBfg{ z*A*8;>DUC`?Oxz^CD==SzsgS#EPFndgceF^zzK!v)Qs)7HyAiEYdNz61p;J-u)@T) z=iyE??NzexdBqo+bZmPEZ4oNs~2ogbU-H4Lg;h3QyQVx-DNB zF*a`!B!)rCq|yJ&g1{5&OQ95p9{Z%@Z;Tqw>dQnatnFgku5rGuSS4D9PYJR5oYPj5 z@e?z(am00X|EQdM2l74NVi8)6`$EZs?V6+vB#H_k;kDMh4gzH$t1S>5ss!vOmp)T( z@tN7seT|qN?{dto`tHfJZ9`V)Lpt_%Xlm}zkZ`=5eDy}!LwthI!!<5nv`ZVV8Y3c2 zg*;(NqY{YIm~j>dDz0$DqGDDFTp^;+DL9_8(Wf)b3tyRU_lQNJ&~36n^t>LsY2ePc zPb7LQ;ZXE_`~G>$^G)0E=l$==8Y+O2cSeiFhbWr)6&hfbv?s-VK!(FX%Yu!NHE91Z z5lGKV)FwcvE9cPIwFr_yI+gukDIOrX=6^}(8z;EzjPhNmXP907x#+k_#bHt+nnJ@a zHXa7Q`70)%ERAiuN*Dt{rZs5QKRuKpITNegq1l>sZ|0Y5MQI!A3I-Y*F{F4=B_`dN zrT4jD3~dCGrP?@BcPBTpR#ivZ235{a>Gdtzm3wV1&(?}VmxLOzc(m(FaY(E;SF+*y zgNC4BYWj2}XrE@@dn50xX@Q3LvLvmbLxX}qowM{~xEBkR0U<_55EiQz=koFIm?#!h zLJAoJnk`{h{tQzhu}H_cjMF~vZTiv3#6pxPc5g5RFB-omN%lui~3 zN1e{Mp=M{XRD888m%y>)Z_4;NHC6oGqvmo3&H8V-U0VcMib8Z5KS}rLz0*TAM8SxP z!@)u>F8Ju`RO-$jXvosJwf^;C6wjon5KO({q5mT%r0qt)P(bcLJwF?6Uxx8Oq zZMnIdR@Zh;>q0hA!)uH2E|!T_6fkq5iV|Nf*gsS#T1fS&fDSud-_6d+ps)pA{ZCB{ zqmQQS?zdVjrSsg=#8WxiPQC(*hgG;i@4wR9vPD@|r?_Wq)2s9pk#K6+3Kgp+=wqpt z;zQ;PO{AoYkM)*Z3AQ6eq3%_ganheR{Wk?4kD|-dvee{%i3Xwc8dZ#*{vCJQKEG#i zkNxxBI#fT1Y3u~|*(?3yc|!n_9kThrRn6&_W-FnP^b}3^k6&CW>zez1D1CJQsKjGy zt7)|Dm?D~Kxv4P5{a@=_g(BgXA1uC&aJQdYpUV!*3gYBV<>tnt1{I?EMn?*AJJJ9mf=#|8FA;eLR5QzMPASd z-Fnh!Z>xBqkR}Q0(gi&MJ6pQw88#e`ht;6OI3Z?uFzgEeNN+<<^G8^7G0)6CVxt{bsO{PnL&SdV9=}X^&Ht5g=h|r_T}4#OQTWgn1r0v1)5>eA z=p-FRAeBx*TIZ03C$2gF`1)IhQ^wo{v;cBeEvqNpeY|HmZ*^qyu#tj+NsWbSzGxr3 zkGrNl5&Wkw`AY0^QZoDSTF1p2z5d>`N()Jd6cqHiz1)Hn1-G;|;Yr>_WW+J3$q8u& zne_C0RnJ=C7jadZ^(Qpe?99BRuGfnt%&&^g23(Vh#=r;c+nOyU4a0|tzeOvamf-5A z%pBZ{0rY14`2Y?&AUU!41GqhjCM%)v)VB!xe<30DiE1pI#j@!a-r(zU20W0fP00@q zu?Sp4BPGIE(|Gnm?7&{unD(bw=xMW((*eIcwic}47`ijuhSe!nw+;NFsSC9mnFY}Z zdCLk7^@Ah@UVp<2p3`oBkAHTD-2ar>XfxlUv}%{Xc;d-Ij`|&Q=f;gg*Sgb3wq$Fg z^GKMcH~#NGr})}GM>sT#>DgIcWB`aa9CPHg1vaQ(&H$_&jM+nlJ^5v_=w?o~^A+eR zTfrvj3;Ds&yjXhc-yjkL^f;DGcl;L7S^N`g_%zvbdh63vlQZmCEF)aT*to(1tQ)kl zC5@-CC-vea~(Tzb3Xc1+itOQI{o0Fn+_xH}O8f2sceVT9}h!lu*8n zOsw;BMoT*ef3DWT5r0yBkY%?bX{yEOOzC9~&ljA268V1Zj*iOUPI7o8&5pLjR<|1m zgC0ey8VH!Aq!Wqmfx#SV%f|CDysi46U}Tgq(n^!RM+}?-BzLaTRo72wvlLHyB5FP; zm8OT4)1?^=NL|eDz3ZrO_?mg^5uw;oZS7uUXaH#AMIo`DpbIp#X^ZRh!Y?$8!Ubxu zi61OQ1timfvp1_Qx%J2MPJJ!!QerE$mC||@_bEvyHgOT-!R-+9iL!b3BnXvHjF&c5 z!ia{wAycOc&UY)DJBO0tT_(d)ox?^;1M)t3FwxRpIT(JQ zo4n>JMPp#4ruDR4=q3tRry$JT_*?4k(R1JO0F+4QLip{|9B^c-Yp4jozmA|1ul@t? zTKvmkTx)d)W@J`h#|6pJzL+K}WIA13NAIN96$IprEiXyHi_GLIk!5G=jb*zXnGgue z91|bwtI?O&+}2UfpIDC>YJtEc*l_iaO!>xIP(&n4={fCO-5;D%QDkX?71c3gf4xMs zLWkxP5|gT?YiDALqur&vREeU+@mN=U-0ZG|ut6E7P!m-Q^l1w-69w-{8}BY2q5LX%89Z zzda5TiiLsBQCwE{FrqfoI=MYWEUI|t)T7j_CRe+iE!LzvWjSdzTrLWSKp8P18n0aNeb#PPLQTT8pl0(Lu?%%+AudN?3T{+_q zr^eGnO-A;1FLu%~*#YO60{;iu+(}PNVR!uUu;!vL5Ok{eg-PhvFRn~i1U$w?H(d7( zv7+Qg1oCCARaXlcw^%Go?XPEChFzP^TsQ|6v;WjCO6)*PzS4~1eL%LUBG1=;ho|I6)ZAIDX)vrTC<~`*=#3XD_^msuSk~3 zI^tP|N5I9=XIU7gMutbIa2y#!dXfN5`g_5-@M*Nkdqo)m#_son$cDJ#|OT zV}0*PlGT}^K?*3JG_PoaH0@V|oQ$te3oCc<^O1FGKWp)DzK{uQZ8H=# zF=&VXgh@1^)9Ibljy*M7`o-CS%S6~j$8}MgXR25gyO{nl8dHBFEMu{tNm!>xW=l_r z{#l{c1SvBK_>cCju0ive)Y`h?pvH@c7+(d0+xsUEe=aRKG;1XUKDKv8xW&iD%sYD1|=&5XQ@jff*7dXgVb;<`TnxRHx-MUI)knTufQ%?r7H=^lb^@ zrj649rSK~GO#FXed7-1BNZsx;QswUpCX5X{(G!cfk!SYkK>UMl;X9x9b72!`M^jNs zM(2WubQh1DDbB~FzGFo&K%uWoe`<5LS&iD1vp*AD2g5ons}gJ9+QShIK3nzZ*v0_$rC<2{R@=JpC5DpkDgMu>n+MraAJd;VwL82gw__;#3Ap3R3qbhX7H|Gc1RPl8r?C>u|ztvLgmgv((S&qg&v z`!w+3SZcr1BTof3<1Ak%dX`)Z5)3 zuUaE!Lo`=-3DYI2eJR6xg|TL&m5jn;Qk|HtW|s!?!3U#E>ei1Oag^^1DN;H$<=K&m zF{(wBJ5KMXM3-+3U2%c6pvVYsHPR0p(*r8|``hIM5r0Z2TN8B{o@IUjha8ZCoy`Tl zp?GTa-}8PQAWtBgX8vsm9=QVIY6X@Z*x&r(Vfz_LnuFV7H{uw{60Ccjn{whSpw)mz zBdzEB89hV0sAR%5bmb@*@O7DZrhF8{|DQTHzsSri$Se{)xwwr0>o)fhXF>mnWwV;e_X8O0oT#ar@W;{ z;0omp4Dq5;XN~?a2;HlKGg?*oB8YaNzwxD`k9S%H=#6aBnRF(bYM`UM*XbxnSy%^b zJS8oeDwZ%Sdi8#hJ8E;J&~ETjXA1Cg3ueB(2&XZTqnHzpm1}~+$W}7E33u)X9+B>yU+4$yd6v$gS9?AYz8d(QhuDBV*$Z!kyx?0wqOkc|O z#*zO^nLcjz@o>t>>+t{n$8$_`TB2fy5%?|UG%76Iob>;JdjnS};AXBsi6vNQcLN}< zu36BMb*oOH#|0bBqrA&gakvRrEUr8FltQ_I7g|U4b+K17a4An)Igz?``gPSdJ`L%X zn7B2uRwGNy#~|6m``hCbn-puXpCOf-@CkQ%xqczNNG4M+zDej+rB~(sZSVT}pQJS$ zGt0yg7}D06KRkCwN74^`S$@%ee8-a7=L@YGU;NH8sVLgW6qax?ot2LQAa<@<18v%p zuBRtw6?Gfy(~H^k7Z{^d{Y4Gg8L$@EXdfV{ziYA2fVgI05r)P0^!xjJv_xstgz{R4 ze2%IuwUm>Ubp>5B`U3~ewMfJQ%}`d;JX+c5fqV_)&+2&uTzV zRWLKRLYktC8khc>?_kvwrND726%kvW%0j85*0>k2t}%Rprv!7BA0e9D8vFa1Rgm`= z<`*>;F+U|wgDJ!EIR0Djyy22@w%mpDhu)U(4w-{Ys?LELvq1{m9r!K^f&09}`ypNtl2nd|dETojH{SQFn)ty+T~&tD4}I z@B(RzVUT_?_$*fR7+W5%=6g8~U+$!^Py1vOB%E$=wj0RrXpNByf3GNi<%Nk<9;pEi z+6!EdJ_w+=!qNskvzW-V^qJMNA6hbQf6~6Nnv!0zO0p*KR!h4FZC{D3R{Y+;)<`CL z_gO91Loa4&j2+PL$1uiy_qLc`dCA!6rD&%s%1ezA{nRtxZ>I%Cf1ooKM+BvB#`4KQ zv9DH+_+&@4Y9?ZWHrlU~pHTCybZkO8c&`GLK7kK62V3S=J=iug5@Ads{^#w<{vu0v zC{1*VSg6M<;;OhrF`Zs0|8iG0uQznPhYceYZxfyJX*C;q3y-i*_DpS5>H~+$mZHo? zb^W>*34!`66-GnCo+fSm27bEjEEqP#{|2d`0I4U%G}V;;K`I=UZ(-PPXQa?6O2rja z=c;VcrzV+Pd{|0VuFe53rgR$Fa7$K1uEpS4~K&Jzd$!)o)BD>)b)xAKTk$_b(z$F|q zM{dU5m2H}o#TdY$F(K6u&Z=f{3H*_)$d} zl*2<9JqefyJk`Pj7mrt1C`EX3dUXAWM%iRLnq=>s!HAu?q7WQCzZONF#9NNbuYb}_ zU=>Xu9$gUG8Fxd7^xr5X(8CY!%C_)c$RhU(I*^O>RzKZOP+ z`=p3$1Pb@Y(gcfNw6{{_C=Hr;82vtkHU=Qoq?D!_&q%zV`k*BYHF90DlXk#Cx-_W~ zQfLyqV;BLxV{lxjKN-7oP!?qy5F9mI4IqS>LZ#)dxNSa;DdOX z!&!jwV-=91*Q;)5*7j`qarLH~@o%r5pQx^`BXu1;-_F0j=|A|J2!lM8Mn9guH{?QF zM_J~lfk6y8-xc*Tm+LUXrVGRtg%6g3$E~5kV6*y)OR`yZholMNq{wQ~$Mqs_OEKm6 zsWY`W;`2M>Rg0jM8pO%3nynCpS_Rg%qh{Ck8J|#eAjI-{;DpL{vWv_hoa$GK<9?y0 zWGd;HyNjPaad2v5&9d?xT#^?f@3UmQy_vXH9^r!wh>w9heUKbT*=4q94rz(cZz}#Q z^4dH4IMYjJG-wz@S%UapLTJxY(%-d-*Rp)ue_3lMnnnzKtQhQa4*Rd6OreHmg+gn#^` zd8X6jQ$TWMJhIfkhIk1JE)0Iu{>gOBz;f(zF8Ps36^%pSu8#2N`_5DE2LgK`Vm+5K)j&mXQ(jhL5l?2{&mN|VA+X4Rw1uR zoIL7`lG@JpZ}aBgw;IgWx6c}L5(7iKH!h;*BA6L40wk?Eukz`MqMDjdxATA1u+uj_ zS~!S0cQlQR{ZuRLXgUE!%-kPfgUvAu6RE06je@G1&A}ld0iFwTHHd`z=-eRGAS+C3 zz@hK{%5C@vP4chyb{cK#!4jx}E>s|$w@Io03ryK9gVLx+sSm$J++9lsJw$Q9uNbYt zs(5^&{Wg3B8X;_={>}=iX&X(3|vEo zndTm#d%H~ZuC&9V4MTIyY!0fQk^n$aV8|(jzT>`4S`{7u-pxG}#t1?DsF_Sv*Gj$+ z`-@7o(x%t1mH6FNW(WIzrXyr!fz+biLFS*tUM1Aowe#Bn#Iy!O^$lg`)4O4YkfKd0h?Q$xs1&hxJz%C>`?Gs{ykmjuGe4K ziL;tybn+$qk$fOSerEaIJRvxa#mV3xEc^XkDCVwQuq-T~tOha;alfTfRvZsf<2Ao}Wn6$V+2IHQA%0=3Bm~s?cy}wfR%$8X*gXvr* z%9d1BbVRg5PdEQ^j>%0hd}p@#Dy1x&I#y*@%j>s{Ix*K8j%wwX%H5h!m~VDpVuZdV zXyH29>wG|d)FV+))=<#=;kyDGkhY{mQH@W6Fi%_Jo<04wCNB^WnX_%(o#zT%|kxoBMu2OM3CD-SZU*W+5prlYtYLy917{wiG zF&T}qjr&x19|BP!f5j9d1l5zia~NWC6S_p_XM%MO{Vw%Tgwx6yH=u`yVqQgUld$k3 z(A3&+Xu&d(w_gy;0*Ud^jq|Z8tK)&U%9BZR?X#5)!VRicKE_33oPw>~X#HrR@_Wm} zmENXGH|(#pYvb=nJkQ>K+-H9cfga~Y;17UmgIo_T;6s-goNX)H>+y-as}5GaC^$fO zIy`H61c+j=+0f!|>zsoPHNh7}15&(^sj3BM27b_*y9c9=%5l0l#w56D;?75rIen|5 z99?Z56poH8%XPMv!M64z#Aukh6EhN)b0^*vgRZyzk!D5Zg6=1Y^{tKZa|=^e8kC|S zTjSigZ0A*XxgSH5n=>r?)OAMArn0ZDE%c{?i9QvR^53E%>c@(c*TfI)^TH#?Pas1k zN&xZPFl(kd@2~M<@_J-C6Wt$%7aah#ihpRp4#J>a0j4E2+GU;x5*f~=;3LA}RMajd zvapI`#&WaV6tpz?IbFzsR_VF!Xl~BM@N5}}kyz;^bzR8v?70-I?ePL??TtT+H7Ex5 zq(YdR?Ku?5<2qHGtwJn#f1YLcdac6QWJAOhlk|1oE}yvVVn|<8>?`}^`qK^erR7r* z00tPJVuPi_q294G?X#x0!S@{#h5!($e1#O%g3bfO&E{OesB=CYV7&|uI5-j!FIa3^ zv6WJ2k?5WEXQsLs0l9cHOL1Ze`z%$@E)Y6BDuY>*Ev&oS*=fL4%Z0ziM13>!6S_g`khrBx;WDz zU5c=RuRL zNKJ??eR5D-DwbX*vOt;@6!Q`1@c_$g#bnj22J%G>=ICLF5!DybBYW`*>mV14Kyowi zW=ac3(JKx5w@gX?)QOHJMMlyPRC$v8ELoGIPg##+KVIs;g7hbdqwXLv_k( zHtWjf{kwkZe`mudY6B0`vw+07);*o*Ix#1*PpK=}~rhwczBZ;Q_SIhK)lc0Hr z)UP0dnFI*Gl+<5%YsnPx!c+&u1^;fpU$UR9T&WYEPSP^j_Sno$_>^iPKvJL{lFub+ zAlrW6=qsgiMxu*J@Z)*(mmbK4HhdUS(#po;+7*q6A1y{A%xBhI%JFYkGp5yL**Ago zxo>K}C2hweL?@_`&`3Y!M3F(_OFP#hFD2>!$K|6X*tmAnV{XU*vhxmDb!X3?hip$p zQ2=LPP2_Lv+f$Xah~sAC53q3p(y-OYKEg^quF1DpSFQdQ!SR+XQo#L&s<(pk3Wpx1ulnPkN2;J#(Uz56H6i~g*D-Dy?}q( zi=oT%i4g;&1<&HZ+J!;in7}qjQ(mv%N+6V7@w*G7U9x6E zw*Iu8PavgtKB1D0j5!aX#gC1V zeCx7Idy8@mc&_BbI~(>t(JoTQrvCiRR0#@Kct9=ubk=@gU@#I^ zd*aRSoV7k2dhV&MSBV0Mr?3tChU%n7lOzK@x0hANF>5JT>txAJgvu`(hlfIrYgTH} z!Cs$*vyhJq;j+(6<#eqEoU=n70vINW4~jVGb*=n*Okz=l+$(ztcE^7OoRzr;gC+XR z^~E9Uq!V=~{NpOdWTsie=^j21zKMw$$9Hb5hvo@s98cSQI{2S0t6 z8N%av@;>Fr9b z;zwwqbu}>{H~s>#h_+omlq$ch?a?V)@6Y^BU(pea^@|4$my1LZstvw|@LgEbvF@>7f7L&Z`XaZDdkW=Ju?wo? z-6GJd_P|qwSE-3X{$b-J5s494K>anL;#WVlsb)&_p-(w|K#{>>5FM`9=Ci#SJTj;7 zD9NAf-!R*e9rcngCse%>LYU#)!y(j>izeKgLhthfkL0CK-_xE%^ceT#!~hc(`VUa0 zJ?iuX6|YrNf)%yt3fCz4$VfXa`HbmumjW z6n%eh)%d~l8h>H|=d#Q3>|1i%^bgKuy|WQxN)G_RM9{tsV>u!Y zFGHF+Zw;dJxp50ghk%OGzx@L$bjy|@iVf?PUCQ5I-TnH6Z_n!~mIJ-LpZP4Yplz3Z zq-j>#a4OC6#_}sEwZ!^T$8xgy@#_r6-`vrupp7h8e)% zraH!Q?g!XV0jXn!A2B;By@`@5JdU?|%EWZ^6Fxao6nrD!>|ow85B%?&zq#jhrzyoK zdrV8yiw*gO%jCOLosE2i_>QsC1TLpabHi$h$^>rR0o_R}r&;G#sg)!bl9p7rgMlADBX!+c7k3U&vPNBJGn7!t8qKSv2}#`AC*`;;_gFdrKYM2J2m-gAnV ziuWwnP{BEWN%VTt+Zcg6Ikw5oaOjDNz39lA(!Tz8v~_cIYcDFMCCT+T(;W3HkuTbf zL2;Bsg+RrP{Rt$zb~DRVnhbjXovi$v$}SiqrSYeK5{30@n8g-rwNa5iNf+-Us4S+B zc>HH32?I#2l=_d^-W=xc;f3v#zF#Pcpdy9!ONeS>xjB#9>-MXd5{Bu>4n2nQM<=*b zevR5>B^8#$2{aN&_Y~Kh$>#x|dw8)U6ASsY*}XiSD@<~Gl{JMAMKW06eY?-f)%?;! z6_)B3sUrAeY5rcUEYB`)!S>^F6|aEG+~t2m;qT~B27lrj`$<)PgyK}LSD7pN`)U`Q zP~IJiFlaP=M*(Y|p3@^~?lA4m>DO*HWEoiR**e zNPu*UeBx>$O!?-n1Fn$x$kHi}pZ^Gzlo!Q=AXz$KM8d6`)E<6A1_5p~B({ z7*Q9hGl|hq`xt_Op@>@LN;2WuywH>8YjUkCUa75QJ)4M|cgm zC@cp%iMY0;fl*%{%sG*=^XMA|GqTA-O@pYepMTI8`A;;pw?oLNMu5X=qp*#sdeb756LXCvjrql z+A}q7zMLV;ZFE5ME!;kb0!KJ#bNzPz1ltEI51B%GTqj_|tjrgdu#XY`xlpvYkuPn6v0Z`HzAsBtk53oN4 zq;jQ_RSTgG)Ha(vgcn&`%4^z&9~bq(e2NO>l0fj+iKT!KRS|ixuVF6ZWr2Dg1=$2j z284_2II@l7h=Dz8ybpeL!_Wrhud&8TvHop*^@KfnAb{6tcWQE8;l_-qYP%_o7M!|p z@czOn6Isnybz!%7lxr<;KDr^*TSRMVkqDcTPChX#w48H$V%xYNs4iva%%#Ee^WlAl zg$Mce!J(8u!Q+t%S_+b!mnb17F(Ii@TNR*?V@V&+vW_tjK^|S3)zo<8fbT-7MuS5~ zFy_m?cL%}~A6Jv?_y?g=9hAX>5K?et$pc-H($Ca@=)wwY$0|oiI5qd$mYao*&iqwj z#A-}<=G1I&(h%#O@lTc>-bGw=qegDYHhqittGVf9TJVExXm>Z$VV9L2^955HPSUKE zYKvKMdstNGPf7I&$?pbFZ@$gWT`_N5e+6RG=mCJg%?3T}(FrrRi zv%Mni?6h{?E{v?Ch?EHw9h^g^m=1M(=U_W-?$2z0RAw#|;Nil=zBYVU;d5C2e)jm|<+SIUjw{TT8_)Y+ z@7hj-2v6I$=HkQz0Ll^qDZUL+m`j+Xj3RVT1C<>{8u#BWjie~n@@&~PDm_w}V2)=f z-(-9Q>5?QYMLE(549^oxT^$AWkX&A$)G>}RSEPMP1aYGt!^A|y{pKVt*TgcvcG)R} zIn&9GEgUkKYU@+X8bkV6{YGX4N3Vu9x44{0#>kLl>Gn(88ua;6BdRm8)$`XCxs^&Z zmEOgFc5UBZwmwTGz#jdW5$K7(?yR0>B7caJUHf3OHX5rq4P;UvYH0P_2iWidsfn53 znC%mlz+S=?hNvcbC2>5mo3{6-k5!V5NT zq4c7)N#(o^v{knoIxsUv9~xAf3-gsP&yP;FU5~QyFwx&zx$^y;rkfd~Ok%1O=iTG2 z`Q=G4QT<7%gR8Y3@Qp1jV|+IM7Wch9IrZp*s z2w^nWDWk;pQDd)jo5!3wIZLcH3S~@qr<@G(WCYaT2=vrh2EiEfopuPZn4OYs`wp3d zBvkr#>hT9}J|3#x=w}{{AfCWZ6p2~cbLa7DHV6pKX?8dXfljIwpN8{tPnLh{4b9xK zJYg@?(HD9@^YhA4JTKq+Tbgt~JOwZ<$?38bU=?c>6+hvNQ6#`9hgyArjSNV^hxjPh z$3dON;2#cZ;4AW2V_Wv7=7K@yjzXrQN@O{djy_I0d^id{a03ySUeimw_C%u@v=X)r z%bO93uDLq@EXK3dG<749(_~VT1hq2kh`++x{~03mbMm8uj0;*qei8pianunmqs94o z07<3D#5ve#xxp#Sxec%DEuH`JO~}vpy8f?*zVThhO1@~O)Pp9Ffjj^}73phR>YQ4- z>zUf|*J2JlR#g9|Uz1adY&hi%k&kBIzuQrD9A6`z4Y;c%_suyHck8bs=Xq3SZKb-F z;Pg4sK6?a4#?bc|Zw#1mXi~PIXM?aYO@>&~p1&^Uc}PLS>^ou|$a>(m<=#N2=oeh{ zl}T0S4lcSRdEGMp+@9*nI=`7cZdW?q^D&C3PGp~^ey9A_M z%*zOIae{qTIzx z*!Lg89rr~5%9UDQ2CZdhe1^~5Gf0M+$jJprR5*09Uq2A~nW}yVz zl_)aRI7|M68YZO}nACs)1Nm6)M5_&30^zRMqrs&djzv)jV_r*yRegro2v=k&4zwwQ z)_*eZSBjz|%vi4K1i5S>f=wRm?r=qPw{J+|aB9E4bKkxwoOE8k!D1ygsE6zgu+w~Z zl>;&H9~qsNobUX_@FsEntEP~d8~&_G1S`SvlD3u7eB}(igDSt&w&4QCSKAtjQ?tcu z0S*RzbnsN5HlIjm;XDw_ z`OzC8(^7!X!*ICU_mfaN|J83%aiic;rUk{du#ouof+g0$l8Do?ym-~|yPF#0k&3%} z(disls< zOwTJ53O5n`vwJE4qD!h33j=Wnp+Z9JcQq$2_ zQf$~>^ve-Vuml1QlVw84@)8s!O6vls;!Kff$d3G4zDX&)S_*W0Ow@1-HDhx%3M*SK z9wr+HE+$+XEO|Mt-&=HZyX?f%KPxw(7ZHk^AFKPtA}{`EI(e0CD{yA;K z-69KJ^z8k7w)O4$BG(7bA*t)5{>Ig$K+mlseE6b@3WZD+_`y;HFmM!~tA&uqL%=Kz zL)9%(|9h{}8HxA&H$-YXI`RyyU)MThh-qpjD^)HmL$di+jhv8xf*bzi-{`OKKICwG zoi(>`{)M4kXBYGDj;bBAIIgsWIAnS{3J>*7v?ceusin;xyL}b zI295eOP6%*7vFnwv|K^v$S*JaEv|HDxVP`mX~HkQ8*06tW{R7BO+Nn=(l>TVLI=au zUKG!_TXlcfz|%||UI}!({T@AVHB;WqUjyIvw5Vk{117TrAZ7oLo5q;M7fFtVhHqDtP(v2#Hh8~^%W&}3?Rt|OK}2{OAE=$OMKM^54L~NWy`c&E&k*-!1OTZ85{tAv2pLH&UWaR}(uc}v-rgm%{4AKzBxF-ARXr0#Ly%!< zW5SGB>@8ZL)lYK@b$jqsVhUxHZa4l|9w}{2GuX_R`?|oV%n7Tbz|AGFm#kvOnyu{( zF};3dWYL5T9X>iI+vbvO)qJ(nmFJf`{=yMYCENFgnX_(hm0G$Py&&@bc^*1 zQ>^+YfMgp)nWzdX(W4`2PM>Yk8_y*LSh}%K@itPkeyqo;EfH%qyM*W)jdaC{Skd!8 zq~e8~)+EleBKhzXz5jFi^X6afGrd6Apc3+~JKy!-$!Ow95pQP(U~1A4LqDRCl7$Q4 z6Cbn$j}w!<*s1pW^JIKI-w}>6=M(J#nN>@;r<7^5H_>-x2iBH$j6Afl(pag9E*kLR zIM{}nzgIgJ4qMZfMXQ(~*k@M5axaGk4W;t-XHyPu z4Zo>4$1c;KTW`47{a*m83RU$$HLv#-fB$)Zh@z*zP9fWOYb|5>JV|}MSBiFL5C8xG zHq@rb2u`)$&6}d)CmeTBr!r;ZcOU4z6W3!!=*7~urrfcd!~gqm#1(*&*ySIrJrBZa zG^6zNk5LAPjZlK`3NjXF5_9qUQwuo5LMSY%HDcSUBxPo9W6XBfx?pjVA?)rATq(TL zx2-T1WcrhL)qf#(&~DbF2F>Id4~-lYB+}pn=K(;G;NV4Ka5~!LwSdEu_A|X>#oBBr z%AhH!LQzL053xBMfB&U3x~+@ix6NKO|MG})Ftst)6Hie&Y&W)t^7?C$_*ArM$OrCG&|L63J`S6d*H4D5z`|iJ#QeI&$eU)v(&WcF?`+&p&0F-^19jq{T z%2+d_^z;vi&;S4cGStfs1B*+ULrM@SusJ$3FGHG(B2*;ckyR z^$~gD_&(#nl&{odP>OQUoS3Xv1}v9`6fX%&1G1<}`qxiag3FvCSJ0B%wO7Y|vJ>}) zSX)TH|F7VLI}lSC@SdLE`<*!O-*Pjc6pXc73#^vR(th{7Q#xOB|NqSNDH#dUDxM&m zv5boOWa;hX#A3I69nPGRG5|MM4CHNKL=mKc5kiAuQ=#b9YzB98JhJ~*Z_AFO z*1-xuv@%G5hGL9j>@q2GF?*++hnB+wj#6tLb1nK)zDtY`|C#g24tjbzEr+i{16FNE zShNg~a_1i(Wyae80036hvBnFYa#$!xDXTLML2)YV@&}AV&m6^^|NC&n5CD{U-yN(l zddg9uBlPwTapw~i@oyfea$9eW(ZF!%C2<(7x8_R?$Z6rZbcW2{4U!c$%v;=?yGtT4 zRVG&s9a{Nz%bQp8zXkR>iAK4*@lome&7Mrd?%r*?%kIVVvN~T!YIYNStf)l2ornsl zb0g)EdDr|APx<}J%6eWF@XA?Kt2bdz?%c@C&m@SY?V@3Hq)yGyDG*)&q9j3ZJj{%f4UUtMm($vMQ3;+du#SH)gPj>i_$2#07woVT~cI zJq^kVA-MRn?VR)>}(!Qu8i5<4y`Sv2uS-QPl6E z`_ycRaWc(C3b68~{DDX-Sz9 ztjMetPMWrE+KSn062?KKKB0!m&K;y#4Q?f$zL|r!!PH^dYkcNc9hDN53{feI*6M?V zQ2v}z2+%>ut3u&=YuvHHx_WUenLD6(oN>>yB004Ve0KC=exJv)~aKr}ylWn6P ztT1zmJ|Uzvh9S8CJh$S#*J+5?dNkdki=3|jbxmOC8v<&`;v)lO3lD@9ho~XRks_ly zC3NhZhB~f*@|S8Oc!{yVx~I&$`SA6&Y~&Nys3?v3r!H~Z{>`dk^&m1A1DOOdF+qb* zijZSf5=oIcgECzmH}frW^YfG58^-_t_Vb=c=Sx`Ws7;O#d9)k-{p?QKHchswl4|r| z1-5bG@V)+rP+^0QKW7%O%l6pXa8yJn9{llApG6!wU;U6WjB0imVVz zD=bq}8d1$o)8By=$1(Itmc>ws?FhZ7U}4%a*RR$z%ByLk$cJIniavOznYy~Z?uRg^ z+siUSFEf9!JEh9j|DLaP*8DBpe}M${{CEG&eF@#mDLm$|lj~zZ00Ddd`*6eqfDx&o zBdjoQ!ce6n^z@FYcIY6B>05&euKd4;cuyZrPt{RtH@Zg9s(4mz z1!7`$Y}HsLkV|I^v9t&l9%;wY{&#W>t(DejpE}oKozR0F$Wk3|ohRp|*0Sy*I+1}Y~>!=Yj-0w$D*lE6yrJkULgDgz`==Yf+#5+>LY zm{gp)DH3Y_4WR?ez~iB1B^_;P!#2-8zhf$+AM&_Pkp_p%>6IfUs|)!~;}La^{HnhV4EVThKfRE+uC*JTRsJQ<-=ZO`Mcv!w7; zHYJ-Uqv|6nT%75+h;<j^syI9i-YlWm8`d%z8f@JB>|FdDY)q`Y{H&}R5^CcA z+Z@nq!tm#u|NqjlcCh^X1m$z^0s!Ln07wJ`R8(wiVhRcd1~xVx9wBjYSy@$8Eq#3x z6H7}wJ0~|cZ*M=p;Nb9>n1qDX)Xd!6qN4Kh>gxKImX40z-hqM9$;sK-`T6Db_3iE5 z-NVDvi;F*hZf@@HpI%Wo>i9_zm?K2sA}W9qYskKvgIwhAf5`#hfd&vxM$IF15;-8*f*=7RY+&rJ zs9L_St`e*&3tZx~U?Wd1i^0vi3_+krMeJh!KOt;p{}fSgf;lU$`Sq)& z=<+{h!v!o#wpwq620$crF?6Pvbq41>XJUdusLUyyWu3Fp3#~UZRz%vdriR7Hv=4~@Wy}O@B9+!XbTkkz+ zX%r+RlG%K44Ju&lFUQRl&4N3lZ`wSDJIOjh=Z6F&i0N_ndjUH6r7`Pf#3K1n9 z9S3?17)AtO$F>8fOV;Gto9#N&OL;RK-Vo>YyTAI=n&0HfRq^8P$5L^ZVjb52bJqjkWj zAC#cCY+7#3pdE6KwuR8gsD_*os`#WJDfsw`{r%0y?(fd*Ubh=hna=Z2@9X(8gUGqY z<*TVbPpzRS_%sb_kA3c~&koWP-0t`N8*&yA1OTugB9ldOE&qhQL$8>|U5fuP>l$Qb zYoTEsTQo7RjNdet*LaD&7TbR1x4h<4F1|$O)|8*_(yCtqQCURR^tx9$3 zO83;vA_QWwzP;kk*=};;3~4`5`^?-tISp|d}3ni_170Ps*= z@JjN3U_%FBtu+Ft8`i`|*ckc3%TZ0^GE$>(U&yoUs*jxlZPGNZ8f*1H}s;ZVam5o8iLfZE-Ow}xOF&C*IivA+ zxM)E;@mJ7-alN~ZaosoXYNOV?l|~Ng>?vf0Ua1rgfq>J|`^0Hy4yn9^+(9aalw$rO z>gvRhus$=hMfaCo^iWBq0nC7mmVvxj{!wP3`(dd-w_h{t7~}iyL3{RWYCrgJ z-*g1U`I~Urfh6wFQ$mOIQ9KoFrJkSBX|yx8UqauK9$ z;$gZN=39`YjB=M4bOfd?Dqj-=>ys70!Kvy{9w!H9AOv%*9Gn0|rQVxoU|c%3j&_tH;08PW^vjAoyrYR=Ulx(~D&f4C#N>O<0?&DV!kM@vs^!rf zj*R5~vmILip>OM_61XM{n(e&Ov%FZtu=i`p{V7^XDWTPb(5Y!#LxKur$uBi@2qO3v z*aLeCwR0II?}g3U>x>U?t32YIW_o-JPRhc_n>|Y+ zg#|#psO$%>c2tT^Q0@6vKw1~ITed3@;O4RW*Sp7kpfevYdR_y|C@OZ8-(tik<_NCt;0=2j4z$PfrlLzfwAF%DF(C+o`wdd9% z_xOK#5G=~V^P@|stlAfrQj`pmAR?Z8$M7Q-Sg~uDy++o(F0N}V`y}XXM_rSsG#D))C>V}@3B_?4>fHU*Y-u;6hfCH^i4Ev-n^bK#9^S zs4oWi(_oRRYUV=esTzdkAMv^Hj|~#cddh)2Jd0$zCATy)3JH(eQ#r6kJVTP9#AO(a z@TAnMDU|$L)!c@A>9E7Ko2C_YaIMnp;6y3uoK_Js6pxD&NNqIkD9^rf1dfs4r{m;8 zTfWRM^2)^1S@n;s z{y+q9wG7~x^8#QI&|61$zFsu)r85EN+fJ3!Xmn{axsxYC zeHGK23o1gSQzAUO$;4NLTCC;>FQAdM=1<+xR!u~M9PUVGFWk!|q%6N_bag=m;uEjt zde`vGx`_*b(`%oZ3(C`@k5aIAbn>OdRIRG#hsmM4RZC}`ibX1Yk-}L%ELF3=E(c`h zkCGL1rFI&y?$QyLhVn+pSj`X5(xQ0?^{(d9I#%Q95zQU5{It zX&98J4OcMfSt@D~dkEJO#bn@4hOZd$i6KsRI`Xg0tQ*1d5B&Io(A?H6cqfigw0Lmj zPW#Vx3<0Zw!TK{o98(bNwqE5~9q8hJ2PR9iDAb*!*vV{WVqJED7--iedvk8V3iU2p zT~jN#iD&P4JK5Hu-iEi2EwDcZIqC{tIKi$97!z^9CW;Ji%&Xq!)1_=2bi$0TtdbMx$~Dv&fU<9y0N3)V&{T<4af%qfRuwnwAO`++ z4j0&>(WnwfbeZ+&*6+GKnShp#F2Oor9_y`!d(YtAv$GZ76bKRQ?Gi0kPYH>H|C*)6 z#cu6;@#6Vo@8H?My?k4t##)m>FQ?kQ-7_$ul3uYmTezbM8x6>n<-TY+S6|Tvx<9c4|F79blbTyt6|YlxZk?76(jbFE5&K}A(i&l~I9#UzG(2;Zc}0?Iooz?MA7Ceg}~ zJ{cDv1YO1MLm0H&!YWq=^+dzg&Ns7geF6mTBe!wX;d z3#~x4q(fA~*Gh3BwDOFXrs>&_=a83kZr*&<{CfwALuR4@*fTs0ha`P;jx|Z}i84Y} z7)Bu#3IH!UW126oz9e-VQ~iK0l73ZCHA7d15Zg2{)kx7Y;8c|nwu@`q^kiM@CK1kX- z2B$C}J&{J#X|& z@)Cgn;x+{C3#qMEazyBcBz<@7921alrTOjHzD>&$r9G^=$jLxoj*CVEBY%7cJ@<*l zL+@YWCS5gp%TarKEZpPWQ4*4ltfQhnK5LphiitAI9_l%y4DK`l6bIakivgFUi>UJm*^ltD!Hn zc)W(#`;bTtt8bRr1U*1Ot~yJ%YiDFRbWe?Pz#p}&9!9pVrc6)daVC4=McY;cfu~Rm zl08@H_tir>LYL*pQUsT1jpd6r#L7GE6F;UVsE8JzeDgc{FpmqH-E>8FT#3r06V(>f74S zv=;|LO>0-F-gqIB-asrU#*?6_iiB9=F)%a;)3jvzA7qfjlcd}&cdTFEP$f?xE;`*& zNb5hA7nR;ZEBdc1A9VAk7zP>XQ_=3|zESNw=y%`6X^E44A`P`u8{{<;p+%XZpfgeR z&kgVa>6*#f(?an>2F>(*;l&vn!fM)a!0qSe$`3O0Kk;Z;Zqc$i?e+`2Y=dU5g9?VJ zYcW=hG)akTD%Pdw*Cgq4(XOMAE}AXlieI+1{@82G)YlkV`{CY!v`Rj%2Kfe zof?N5X&txBrSB&Bwc$4<$6y$O>i8LRYnqW;YRmUV5K;E`{e4g-QoV6a-0#c2v_CN` zp8W1FjwEVZkh#eU>4Wlh>rxYceHyQxo@Ta(V*jDMk zV;oGt`gN@8j1ZqVO{0xhdNUp_s|n!OWhNuKah>F~r1hUgKT$-ZN_mKRDa+JNsg|PJ zS|Ia`d)l@9t_p>lj1zDHSyJ#!6Jr0}8PTPskO8hM!#x|)f{a>ygljs4eKM(ww1*m2 zfpuIW<7{6tPWaA?1gO&%zcQvpR3o8UwXQLNHKZ2$inrHu?F=MDHEpR({`reJy{?z< zXRQXY-J0r{l|g<>MEJ1y`aBt%+tF1uhnfqvt|qr>8x0<^66tszn!uh^cW++4o(si3Nql?bvA z18J(lL310MDzq(-Xi|^5s&s#l)0)vAXZX8`n+k+PrDXaTc}zE~DXK@t7Q6~FHWnUh zqRg{SF+oMyA(4^Y(J;E6E7B864$jZX${QnM-jcOy$dySr!T<~Eyde5B2kC*DpPoVt z=}Q64m_Ck7bg>r0b|(BELtK+5W!U6VPVUz6ex%mpDJub#bG*nCoG?<{ZkQdh@*o*t$+2(qiJ|3Y3TG#Kw>A2yX z=r7S+8rRBdu8frxs1)X}x#WDB;1*%HO)|AoyzN~krnX*WoC4o8)F#Ww3tvWd+tZm0 z|J6R(0IAoRy3@UEQ{Z(rpCvp`8+4&LM-~`FHc^Yd)5F)JtIh2&IX;eF6QNg zaZG;;q&W%8g`{aQ21DBV)v2Idv*?heG+yj>H9EVc7?LViY?I!c7}Ra4aO0;^3hCp9 zy%{v>wKM0SgC}VMAzZuB(=bX~8RQ|_Xd_BTP*}eXma9sENBm&L$r3iiD+<+;zJ#!+ z=_GjdDpxo4QddH~$VOS@_{W$nDCW4Z5$&_pspo`dQ_9k9b1I_TiH-wa3zB z{kNgO2Vmm`>P`zT40g6K@P!d1Y-(yd&{w@S9$Eb1(Tr4%Q--eE>}TCU*|qV90?emt zsj{=j_mr30iEGTO7I27WNN~$zNjMi;n!9({Biql{**r~YvXs}&QPL*Nmh)GvnujCB zttDaMT6^(GBW`oTMwf>~>T1*W;gjLh9^6F)(I7aLj8ltL5=UoA0!>`jZv98+zMlDk z;JqDr{X+)j10SX;w>&kfR*B;LORhP|H#gHWx4^pH^L#n~1rAz{d zu6RL2wJaECx!ejZ_7X0s)sFGet`11VGPk-kJQMeP$?>>e>1frgZR!y7x?pdIO3l@`}AKBkRefe&F@RdtI9ezp1*;oQa(wZnhy z#i0zbUxk#!-O|pqPa`>B$ifT~7ODgx@SwHH6Eg!wU+%Oeyk!ly0&gjORC~r3>ugS# z;`inRW}mDt>O|~^RkBj61I<|s!zjCj;59W9TIhNMArg=C#HXjt2wKjL)wB*zwK*Qt zH^;dUYYkG4?5H1pjWDDe&b0{A-rJ+cjJ!hizv~b8 zzH2+BG|t`m=-bE%E+w4z*|=w7{K7XY>YRTGp3bD-DmLKUfDLCYM-_JMMzagjr9zRK z(nk~R*p*g;fbH3T_g-Y^rjY@6PQ@~Ji}-rAlP85+rWUJ*-}Z`MTlQ$W!feZwi0_d- z)^u)c&^Kw#)k-JFbYaj*qPLjdO=Ebr`kegmr=xY;tYXDHtx>Wnepw5g^z%f!BT4w* zIwl}h$XfGL*^>>N^v~g?PgTqC8di!zqNeJXY`3wS2~rNfdR9PqhVPm>t?-NqdK=VH z%MKmViuJKl5*R}n?i3hGWljkp8KKOaMwU@Ea>G6aG1u3j)ikN7E0VvA2Hf349lHKt zaJ^1GctEAWJ!B{{{ZJmr!d$eYy8p5xX~0e$NXla#MAj+}PnS?IjDnI0l)mhK$Uj!% z{`U4Qac%vJR?q^R7KiS7zWesQ@Ks$%0l?Ttio)%%hz|Zo4??CbN4n@~C0W7*;}A1; zF9AjSHo35lSL}}5hrmhIV}k5uCfS&c)>H-j5%^5NdK%bvq34d`mg0Ag4hyhrQC)kP$uO+fq|-1s%dl zviMM`y=8?0A$-A3^`~8HeGh!#q3&#P?xnEe3@af*JCC=<^^sCspTY*fd@&DVru?UD z7(nuMq3#9i!k~VGt#2At$B!#On%qd*WnVPlYe986A86!PspMf#Jq0k1OS z+&inrlV7J6MuXa4^tZ}Gy(lI9Qpr-N6RxSxB}#lw<_4z~RJsd6aXS3td&ZWmz`CEu zd)e~E-}Nd`nUy#IQlKU?$)<^Ybd=9*xX^S!Y8gHW%8E85D>i+rMpl05k-C#F@n_B~ zVJ~>n1}{*KsoF*w{qT1hf%zL3=SzVL3Qey3;GQH0AM19{yCkKTzSjMEQW4N-a#ATP zx+^YNLH!(9RsDxfne!m!oyDI{UVQb@F<$8L$7EATz5c7b`HfQ~Opwi)mGh-kn-*fK zq+I`mhq)@{Czj45i3m_a(5nFW?=;^PEA^=h^DONHX5xVd<`xq&J(-bE)HJ z^$G*aL;pgEX;8S{);EmIlj!U|(XrZP>Zq+I?9_OE{y4|Fmd&5wD*+V6+I-DU zW0^CDST?dP8>32zw4|$Ch0)Vp?0RWot0W1A6`X zS${yo^D?|(otYG`J$nx$dp>hA-{*jW`=u4Fr1btk4rj5$skMbRogpo3th1wy!<^-1 zgXw4ecyoEo?yZYBeFeF(Mzpp%dCLWpHpg<-in!C6s%t#l=j&CT`(FR_;Aaud`aDzy zFNC@Lv%kHGRG3;-CFav7SRiY_l|CgM2j&RNPYa_h)g(atxN(M+r`rUu#I=c_PQkEc zMIp-xMGcOc-+57TUUP{WDJXHBq-ZRzVO=MX{9=B}jJ!=2wpfX=JX^gbi-&!^UT_RSEafi<-fA$=dY`g<}cZQ-V_`PqfUe*?i zav5!*jtu}*_8)K1Ge=e`hW3R|~~5SUtQ63{|Grtd+Q;;J&_E9+)`-~S*qCugJbnSge-_;T)n8)0;-a)|&EA;#I}u{Rq~+5Nn@+$2Mc4!+j0v^OPm&wP0+Dhq-XAscXYZi)vt01gTGyu|kAAq-;x@_}hnsoT3mf3S7^P330Q$2ajD)IVM|K1U?;& z!(WY5dp8uvpdn&H9nC!~R4#fc4iP^saZWN;IJ!R|$Y~wU7MZA27`z4ZVC%J+j*>1| zV^uoW;qk`rU;OOGzLzQa^_46r)t$LZ!Ah@vd-$Dh=7K(lnBhvO0hAxzx31>k$~LrD zc+GvP4IBF99nt2yTGLfdn&pMV)aiUm?0A4)L_g|LzWI`U)UI_k9`p7pM58|4z?Uj^ zT!XR}nZ`vf3MJ6L+uAY}I{;a~Y7@p_s~FWX_RIw?0+i9SYmP)^e>QG8{7<|JK;!$g zDiu=TGt+r*Fxe^ErmJvdrh}t5`RyT0=rp(Ao-FNTw6z9&(!MbvyJ_VPY(d!JRHK=y znLEAI%jMph z5@YeU&N16}JQhOVR=l!qbdeo~#+-;7{a{+A@yfYY z6n2Jj$@S+#^9qRdp4pfS+hG5hj^XMJ<*m!G1RIPr8?-4R)qi8dMuCf80|2DDF%7r*IMdNjn{)Ucy2pzhKS6)>|XPlL?hMU9&1 zJGBoN=PYBqi{+XA64duQ;NrDDPe$s9z8=;{F2l~7WAWM`RhUzY!n37tNHZ^?X*J8W z?rT`*`;B8S6@297Bo1c=5jV4m<2`(|_lIh!O@6y-pq zn>aS3Xta%N@J^ocS()R3dy~qGWoIc4W;Z%Qv=D>2;Ed`)H&YZl>AORYjpQHvm~5>` zOPJb7E>cg{om!NxiZFM6a3)32A?rp9xoApUrfvR2Io!J|0aP~HYRy0OpaM`$EcGv_ z(1S2)Y=uG!|Gsm1n}Y*0=gnOcWuw+~p1c&o$};0R8`pW`m_>Zr`KHJtrQf=tMwTq5 z{9u;yzE=u0MKEo-p?|~q>oSM#(8(GSt1I#&h@yDpl6MEk=y%^TNoPgW$9`33EEaT< zg>|fcCCWsXXD~Gw(hTUbyqgkoRi{m_n$F3HTkn06_#{VS)k=-3Q4ph9=FFyRdtkgd zucm;byUyC%UKB0FG`}s~lr<%Hu_OY8ZX@*P*S^w@8-l0|LasAvc4r4pjcvQ~y7&Y0 zO0g@XJ-%=q{JU>1^onsMw5N9@plg2$X`SC_3xVYh-9J&LYQ|GI!NC5h2NHk=wAB3! z+GnuL48CD_HFThTwlZ!oUjB<(fpTW{`>+5#u&+HO&mA!(KFe&kPdho*^{&+Zph7zQ zbziQ22aBFT+{>C@&Qi7az6?JrvUzkdp31Sqr!6?jF&!W46kih}2A4NyPh@o4f_;3qLYY94sOYiUr+WZ446v z%m~|h>MzcsykBEIKI21INae04I0a@j$#5u)$JF~D*MmcSoBZhY8(xpd(dOsD@9*r{UaQT% zGOVm08s{6~JD&K(A3kVhYVJhrg8ZQP&@vdIR75 zs0`w@En#D~eiu5lYcDMrzimkY3{pr#&`svOhG31BA{Wcm6xyXn%c?sUA8yFJ&S*Du z= zJw9-V@9yC#tuMpv)8;R z#h}Mxs(KI41RA5K6ee##4Qa#mI@_8ACQB(Dl&&adGC^lj{w3h)$x&YW!ejsFH%^+G zj+}Xjg1goDi@e>vhaF?s?1lO?1`MMkPdQWJs?^TN`@^swsfvIo-+N~Ds@m@L_#4lgoEP7D8q~IGqA4NQR^v%+a`8fOR?d_ zQ!tM71d$!-w#!)4|~I&!s)&;EI;8T{0Kw7E$bX!a2#>>X&i28WVSI zD8L+hZeCn=zHws?B8oE&^D_3Lx$1v=VB4D7X=)$5H(DK>Vg53!<#$Y)rY=lk>k~4V z`K?!Bo7NJ!R&FQeIFh3Oud0GUJ{N=;-$L=s;mT1FrPYqu?EK!~E z!gzMIa`BK`c1yjZEqP!=w?XTi4)-GWfv`7kaOHVqoW3sqcYXf$J_an^bARdWY7ebaKQn`K%|ue3_<#H&w2WME9-ZexGNMa8mBL zxxQ7@>>5mtBF@eO(t31+xflQt4Lan~p^F#@Gnd~Z4}b{&@oW|0?EGKbC92x0Ua-O0 z2(p~MhvB=bQZA4oECJI)RgL(`AFboW8z`;M!jYOL3)s|;_4(K0MGN-!nTO#xt^DV= z+|a&^4~#&nn)fm^OLlzro^UDV9zCupAi$KfrLqVxl@;X`c(tHYVW*GENr0|D8Cge( zN#h3Z5L1oUjCbw}W~M^iSS5BqMqOv50RfSElc`nv!v2LIKPzT6DUa8$7(4CHbI(_u z>sbeS#!+Wv9*E_9j=bJwd42VpJ9HcBl%6ByT60EkDg&@7;z>x#P%OWP7__TcKUANQ*;pPX7=by616 zd6l-yXJ&!`I%qj(8=0r%=6()?kfu;{zeTI_(VXmXjx5kd5vuKhmlsMXRmmMg#gzT zTG(SzYUggZha$Y`03cY-^qBp|D*`r@v`0h0pgB6Q=}w6=C+*GoLwnlg%YCbm8||8E1zW;ZE63P? z8AReaZ|O4m2CV6Y&Z}Tn3JK+{DGaTE=~5j^I}rg%i`aw=wYR!_e??23c@32~bJ)nl z&q+yq@)+I9$i!dk^wJ!z{Yu4X;(_vnLtU#gqPoAnu}VZhVF>ey78em^5#~LF4QEyl zp9pA9lBZ1-i2J}Jv9oRf$FeRN}pnEv?-S^{GaN^4tnyX4Glpz}b zi?18P)}%F%I+8XPbiU)GMFce&%?ytxqn6=~c8zsm^W=c+@eepOz-Q1_ybzq)BdxXW zxyy3<#p3Y&ZXaIm=*z~){E@CTy?NyJ_v2ZujcC#1xmW##D{Erpq#pEQp{vtf{=dFH z!yK&EE11E`OfelYxy!K(U;fl@^#4}8ZMPKd8b@xSt~iadEdtdrjFIVXU*FH7W?{1j zm*foK=gMe4Oifi%!b$x3aJV*y7X@bz7CjB&o#hP|lWXSVm_qESSTC$O*xf(w1-d6Y zy7fu-;W-6q%}VoK5CX8fjsrzFq9lHnJiZ2i+;3yt^T6#zd-9188$WSL;qe zRV?V*oH^t%aZV-k0_^K#=Jw1L`j!+`^EL-bsrvPY!}l5l|7?c`K)rO5zo4Ak-D9Hb z!O8GBXzF4P*fMO#rCy|LNbRKHq8XLe9N#rpADU5xbf9ME;W7O10fSF^G(0l;P~7)l zyS{C@{T<1`Neh`UMHQO5U{0V5DNWX~l31^aUCHlvtJap}MyB6d&s>r~M&)Pb!z=#_wbQEIZ{efa{)+1LfZVKc zh7x}ED$A7{?h};9RDQw0l)Ol*zkMvlbqgg-Z*2r!=}Be(RSznet^5UR{hm~^TO z3A*iv#KJXEAOoB_?s8hYMBEfc(o}Yx8F};$3rgKZM;-G-8P&&=J6^xs<=*doi4oA# z;>g|bdJQI>kI)?--ur2-7lOmHHr#SUJ3=Q#(CR<3?Glxyg@sZ#XASfzSLBW9q_*ij zjwAQ?W?Vb$mD#-Exm~gqi27n)Qw7V?c3U)A9EQ{$xdk^h5w7;RqH55`P7;~IUg?X) zPrWz{5v(N|vw>jev~&D+vn|~db{9l$3y2|sG5(j&%D|_30up3xB|qcU9tES7-~$C# z#{v*?1oTX#q$n%Ob=)CTi-3DXPZ6>N(y zno=d#Chh5O10xJo$NJ@Q!(-UQD;WsJ>l<3j2kD`bWjrjtE8MUJ(aHCP48G*k6;2=P z3x*t}0@73^Kcq&(Q`jc;rFPPKpOV5(cqLZ@gBZ`jJ$X|}+$x6m=j(f$1;4)FhYqbP z%-)^)y~>xB!*<$QgpvMZ3{($$Ntt7(og=*!CQbKGJ%|9bLR-<#g4`Kt&500CK`-fP zMW%U$0h#B<66a&CkKi@QP{cz;KvI*LAPG3kzq`Tu{xqT2W7E8p>@`zrO zUhU84+dm;-I+pXPO)DwfZ(Rhc;JD=1i;8c78jnD*0i?@(eHN=wWz<9=19&G=v-g zM+XA6;geqLisgl>(Vp{!+v_I%X5`^zSoP}RU#k759t;5LlJzHWGgS!9CqB102Ji35 zQyRSsQ8OO5B;RbbR5%Zi-eYL}WI|L(v3uwdxQUj4kZwYegiat`d##tk=B1c zXeRO~Xm*ha6+*BC_N5&pDV+Lo`xPE_HMNfix68GAh7AuH-Hvg?;f_5^1Z5S6mxo}M zOCIKAUBh42XKCMkC@YVFt{z6u(cMnZ7#7T4p{HuUVuH*foC@u|W^5}JLea2fO^Riv zdcPMRERBY1+C3;MGOVc6p21Xid^aN(p<{YY_)mfh4M6z>;Y0}T429{_LgX5-U?^fWcUMkew7VWYWap4os ztjZfFvI3D1B&xTvDL$A__xHA+`m76p8=~fOsbEYdH(0P$)!FV^K}@}%heowMV{qtV zcKLz}6>-jtWLW2EPfw-~3=Q7vU7`H?0l>yT^y^Y5`X0$qoAY+QHEk6H<3-cd#XOlo&&dZ}LZNp0-K&K|S8}9f%52XZG zU0qXd5#`hm8nu+g9LEXaiKcay(6bho)tUJR0x|#vNmukZ6N9XSidOJ*`_>fm=gplN zj-ia6C7do3_yeJc60gTG(Z$T+)eQ8th2N-%C^oe^i7vzDi~a5tF&UhapVwWzdoov1 zU-`Yu!H1a7qw}R}<7E5XHS4J~|LMea(aMnib*$9{3u2c;*UJq7otdxS>zkt`o~$9> z@ZDSLh>TCXfRK|ZmF~nIoI>OBw=-$uz@*%j1?W~iQ_Fteu) zH*36WQ-5A`Z&)@3r9E(0($Q+1+s;85e!ijyTLDp3(_uF9aepp4 zy6&ROIAF^h73uLcL(kF0%#>7%m23phEKUA_fF6Ki&-dlG5JcfV}biIM%i%Jn+32@Q3p_<7r{Vs&C`wGHdr*E}d^@p-b{3H@==zr5coO>cxZ zNm+jh-&9W-l=8R{#p+Z*UT^~S2K}z3j}Yl^3((ZLbf(uGDJ}n!_F_;k*9{a0b7qTnUTV3*fp>R{yNJ@cEq$CAoWmQL78>D?ZvhZyf zaiH(ife-O?@N%Bo&QyUW@2_268r9EjPS^hj0ww^Nh~mo;rHjclrDYFfhR;`04~7Ll zdQvi6CHG6^#K z!28Rca$iU(HWo@DVcXo^Z;{UU_SwsSzYB`hH0R`-p(LmvHY*rjEuq@Vr*hcR?5a z1CQc$u4`rJusFYOl_sgx>?BYM|2xf_RINpRf9m) zM~UtWVoeZb0FQ{uDqqZv_g=B}872T&y2d|J;Q+{B7<_vTV})DnM}l|oy*qcOu5fu^ zvT+6ToAdGEQ$qOL6DzN2Sa*eWsNZ`wHO+NMk*7*3WdEfaC9QukS_F4SX-XUs=>zdF zdUnZYZvB#uT#D^x3I^0pCTA1XSLa@ZFFGI52&v==zY+m}7U7Zp2x%K%Kr@P--JJ=K zoHzDmKQTfHv8MT=m$593JjKU-O_N1Hb?r^7Tb)3|TVttXtBfhHW-jI$yQj~yg6 zLr6lt=UMt0fkY@JRKxtZZ^K=L!LA);sG+ubS~lc)x%~BWAD{*AOC=3~zQ3Wfz$$>Y zM|x(w!;ZcGEB_(xlZx7L(AYF=oL!O6KT?qZNN5N=hne^$F=Q4#Zn2*)&M1v`mW|wM zLz~kGii~FFQB)qnQk$&kQrjg+#&dIP?fuI5OUc%dex!CJB+dIQ)U&!rhTTQjTdp2U zi$ysvRio|?s=P0yMusnVRcnBCw~F+>>9lX&b>n(O%gmYJ;+qUZgN4{{1Xq@t_MTSH z4sznL%@U=6Iw8Q~7uxK8TQxZ=z+4}tP#6jiXYu@&2X`HzxFu#K%`)(%Cd@?9Y7&w@&eGZ^oWe7-uQH?$}nUAVr)LgE~WCRbI#!%CeoYm^hw+#)&^%! zK~lxpY#jTa%2K+uoSljGxkHHW$5vySofz73ILVlbjS6H|K)In*6?xPE&Gd*+%YqVh z0X`kUlB*iaZbPe^`WK;A<9C11`}^~wyBvS&B!7Ww+s+@xtnm-#HAti;vk$dGI4<(v zw&On>rOyYNP}KhB0A?vE3vwjwmq~Q0M~}BQ+O8~GzkIQvw7wJFzS%LnB)LHgh;!7t>rN&}yK8g_#m(O7m4RCO zK_Jk_3ztsKU+)-^YR*|yJkTG&=R19$&jUd4*wpu~`uSR^-u^7$?2>z>p0@cR{UvoH?et`#>!^wIht>EIaBDTko z4oS-idO=YsYm+l9VDThI8P#3NEfDCe#wN(N z)-;s(3#c&b?6avX66W8xF4O-GdKDRl3PLc+X4oZF-Q_|Basmp?g~=X`#rbVF^TCS7 zG{s75_i#OR2E`(#mnp5wWnGdcd78geM#SFGRVnYew-OtkN^|JWaZTEDiR+oB3Vf3C z!UC$YwYw|*Wfw4y2QrK(HavV7Me_6tAM8fTZGVl%^!jy0;{<^FH zT1FI}Ix2V-7;M?-L*?=PG)ybn0ll>>#d}6qxa5iq`A^MRb=nBQpGb3+0)aKd@>+12G&r00K$c zig^5RoK$0}QKBwdQ*80xA9R36pcB#{4+St`DJ9hwb)^9VfzAnxKSOt=tnQwP444JWJ z9bep!XU5aviazl!{`UTv(y$Ig1jEIAqbY!_BYozei~&m7#Xv-FpcSibp>KTKZ)MMoU^6IW33?9}xWi_B+4I ztjl|+@?Ry7CZ(UjJ1%%Hj$T#&>+f^x$Z*q?wR`TYH+u2^X2z8&^ZHG~_y50r`{nzl zZ;L;#j+Du4ah2Y7`^v;cOF!t!{{~KM7#v}2_F$Z?lE4zC@XREohoS3<%j<^U$1dk> zx%{ofz2tvz@YlJ;T2pUzrzM-_x-AZSv3+9a{{P>;{x<*r%TO{nT+<`XCb(fqoa9k$ zfedC5>F&ROfmvwo{QoK)Os(;buWouehlXqWUcGZSy!_UtMStu6{=alzJxFPx)yCz9 zqC5}RMTVufS!UZ!Wni$E2I>TY=R3o{GROV@EpUW``EUfYSpqQbfwBh}7+4~K(mzZ# mM1?H~g`F3nXB0{i0NJC$e1L&*2{6Kd_LwvP?V-p-?3w}7iL>?q From bcdc951eb1429d174761c4fd23dcafaa2c0237a6 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Wed, 29 Nov 2017 15:27:07 -0500 Subject: [PATCH 200/272] Update bass drum --- .../assets/drums/2-bass-drum.mp3 | Bin 4513 -> 1877 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/extensions/scratch3_music/assets/drums/2-bass-drum.mp3 b/src/extensions/scratch3_music/assets/drums/2-bass-drum.mp3 index 176d5bacceaa2d19957ad4de92a3e9b4f3ba59d6..bc25332748272a81fdaa8f751d4bf6a53a50f09b 100644 GIT binary patch literal 1877 zcmezWd%_V0bP$o5mkt!;2Vyn`2KG<}T{IAl4kn?2ljz_rI{1$UfOZA=IQqI8>seY9 zvFwC7$wWbg-Q1CZ@d3ykp^asish4MzyiIN6H~ggWCi!~hwAoUIqW6XRrfnLK>BvO!9VE>4;EkX zyBXB8t7Acd`Kp3@CKu!Fy1rR0l5yj{YqL~OWywG1#V7aP<69bjZfQctVYUm~TMN(B zEnGMM=)7&MvhN<X6-%t*J)Wres>}z0>`p zSaY&;j#pgmjBv?kx3`-_C~t8wTI5-}xi0%xT7w?1Im3pm#1nK zuD)<2KUC;p0B6+#&1Tg_3Cn^X1U0R4&q$jP+}SkcrM9)r=Yy@)yTh~o|1JQg1cAVI z-?uaJUU_eRS$df7Eu&g%Sz7G=`?>vwRD<^qMH|=e`-j;Mm%>R8` zMLNq?x1d)~RIbL`-%IrLTUk?e+|0|X>1|Y7^5i+mpVPbdwna`8jr%+O+ywpI`Q`uX z*E~x-!7k3+y5@N`pBUQ>RTTxwWlD>f@I~ zr%uJKR&}{<6mmB5!og)(Cx0zBs@dDE7Wvp{2^ZH+qho4Jg@~-SfN6~@CdO;7y=-rM_wTjZwe?>gP3u$iDUGpQ_xA4l(x$o3ecC^4Idd+l zshOc|d5H1GhhK6uZiXn%P+w?h=i#-8xpa!anavYU9X81|VYz$iTS5QEve5H$Yj5;j z_|+1@sU-UFrq1t7VcXPTXH)hLnaaeZuMAUM7E1C2E_a&Uy<4mN?o8+1);ON1jhJvlXGL7-jElY4zjIW{Y!p>*SuuXAiz^vc(tT4|+u z$RLsbS!0pWisQ+JRm!v3Oy*3_|H~4uj zb27@XP4kMd8COSFFQ*(YM@ztj(9;s1mP`q4>ThYEwfv;<|2H--ydSf-%&T}&@}}Fp up`)e!$Cv;Aufb{(J)>1f;Qw!dBizgf7#NoT3r__G29pK`1{NfFYB2%I8xE%c literal 4513 zcmd^@XD}Sz*T+}%wn329e%5Ni>OGA9l|GVeS^X~b~oO|cqd*Be*!+H<7(^wYE2!S?JkDbuZ*4pK=&8kE9CzIzXExM$6q3@NV}r)FQ2a%zGCSw zdsm!ZLHNtXSr2qn;Tn=6@^Wq@AOCY3DKHP|CshE^A^J*xW>bt8C0M!YK)eRK~O#_=C3r(;m;OIIs7Tn$$Vo&Slc^7?etN1 zR8*&qRn++FGxSe6%3e^(9ESk5-Xx2AeOo_`5iK+V%59G>orMlmnS&PO)WYT#^AfRi z^%>S;uH3&%g?NMv-ijSj#jav3l<{@^1JzHzi+OSPJ|2;!)+-u3aTNgWr_20UIDq=@ z=~c6GcIG_Rl5G5=RkqvGP>_4Sc=2IuRv-UWJP@|FO!3L*ACI`yM@R_xXC2o7bj@aV z&G7�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 H{tx*df?EMk From 68053adf7f293ca412312f0e1c2b399597325fc2 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Wed, 29 Nov 2017 15:35:16 -0500 Subject: [PATCH 201/272] Quieter snare --- .../scratch3_music/assets/drums/1-snare.mp3 | Bin 5557 -> 5112 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/extensions/scratch3_music/assets/drums/1-snare.mp3 b/src/extensions/scratch3_music/assets/drums/1-snare.mp3 index 38970d352e35a6524e09e0832bb265772eba3542..6cbd0c8c1a961347794a5ca3410b3b4d7a2f4afd 100644 GIT binary patch literal 5112 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 From 6b00f97804d00db2fa9b1fdb98e7577101252cf9 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 29 Nov 2017 15:46:04 -0500 Subject: [PATCH 202/272] Fix test --- test/unit/blocks_procedures.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/blocks_procedures.js b/test/unit/blocks_procedures.js index 0285b23d0..5dfecea72 100644 --- a/test/unit/blocks_procedures.js +++ b/test/unit/blocks_procedures.js @@ -16,7 +16,7 @@ test('calling a custom block with no definition does not throw', t => { } }; const util = { - getProcedureParamNamesAndIds: () => null, + getProcedureParamNamesAndIds: () => [null, null], stackFrame: { executed: false } From 80da989f0145d1d4ce8ef2cc2addcd40ab7a5035 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Fri, 1 Dec 2017 10:29:32 -0500 Subject: [PATCH 203/272] SB2 Import for Broadcast Blocks (not including the input field functionality for 'broadcast' and 'broadcast and wait '). Currently we also cannot import projects where messages and variables share names. --- src/serialization/sb2.js | 59 +++++++++++++++++++++++++++----- src/serialization/sb2_specmap.js | 15 ++++---- test/integration/data.js | 4 +-- test/integration/event.js | 4 +-- test/integration/motion.js | 4 +-- 5 files changed, 62 insertions(+), 24 deletions(-) diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js index f6f03bd18..ae501bda5 100644 --- a/src/serialization/sb2.js +++ b/src/serialization/sb2.js @@ -88,17 +88,18 @@ const flatten = function (blocks) { * a list of blocks in a branch (e.g., in forever), * or a list of blocks in an argument (e.g., move [pick random...]). * @param {Array.} blockList SB2 JSON-format block list. + * @param {Function} addBroadcastMsg function to update broadcast message name map * @param {Function} getVariableId function to retreive a variable's ID based on name * @param {ImportedExtensionsInfo} extensions - (in/out) parsed extension information will be stored here. * @return {Array.} Scratch VM-format block list. */ -const parseBlockList = function (blockList, getVariableId, extensions) { +const parseBlockList = function (blockList, addBroadcastMsg, getVariableId, extensions) { const resultingList = []; let previousBlock = null; // For setting next. for (let i = 0; i < blockList.length; i++) { const block = blockList[i]; // eslint-disable-next-line no-use-before-define - const parsedBlock = parseBlock(block, getVariableId, extensions); + const parsedBlock = parseBlock(block, addBroadcastMsg, getVariableId, extensions); if (typeof parsedBlock === 'undefined') continue; if (previousBlock) { parsedBlock.parent = previousBlock.id; @@ -115,16 +116,17 @@ const parseBlockList = function (blockList, getVariableId, extensions) { * This should only handle top-level scripts that include X, Y coordinates. * @param {!object} scripts Scripts object from SB2 JSON. * @param {!Blocks} blocks Blocks object to load parsed blocks into. + * @param {Function} addBroadcastMsg function to update broadcast message name map * @param {Function} getVariableId function to retreive a variable's ID based on name * @param {ImportedExtensionsInfo} extensions - (in/out) parsed extension information will be stored here. */ -const parseScripts = function (scripts, blocks, getVariableId, extensions) { +const parseScripts = function (scripts, blocks, addBroadcastMsg, getVariableId, extensions) { for (let i = 0; i < scripts.length; i++) { const script = scripts[i]; const scriptX = script[0]; const scriptY = script[1]; const blockList = script[2]; - const parsedBlockList = parseBlockList(blockList, getVariableId, extensions); + const parsedBlockList = parseBlockList(blockList, addBroadcastMsg, getVariableId, extensions); if (parsedBlockList[0]) { // Adjust script coordinates to account for // larger block size in scratch-blocks. @@ -166,6 +168,23 @@ const generateVariableIdGetter = (function () { }; }()); +const generateBroadcastMsgId = function (name) { + return `broadcastMsgId-${name}`; +}; + +const globalBroadcastMsgStateGenerator = (function () { + let broadcastMsgNameMap = {}; + return function (topLevel) { + if (topLevel) broadcastMsgNameMap = {}; + return { + broadcastMsgMapUpdater: function (name) { + broadcastMsgNameMap[name] = generateBroadcastMsgId(name); + }, + globalBroadcastMsgs: broadcastMsgNameMap + }; + }; +}()); + /** * Parse a single "Scratch object" and create all its in-memory VM objects. * TODO: parse the "info" section, especially "savedExtensions" @@ -227,6 +246,9 @@ const parseScratchObject = function (object, runtime, extensions, topLevel) { const getVariableId = generateVariableIdGetter(target.id, topLevel); + const globalBroadcastMsgObj = globalBroadcastMsgStateGenerator(topLevel); + const addBroadcastMsg = globalBroadcastMsgObj.broadcastMsgMapUpdater; + // Load target properties from JSON. if (object.hasOwnProperty('variables')) { for (let j = 0; j < object.variables.length; j++) { @@ -244,7 +266,7 @@ const parseScratchObject = function (object, runtime, extensions, topLevel) { // If included, parse any and all scripts/blocks on the object. if (object.hasOwnProperty('scripts')) { - parseScripts(object.scripts, blocks, getVariableId, extensions); + parseScripts(object.scripts, blocks, addBroadcastMsg, getVariableId, extensions); } if (object.hasOwnProperty('lists')) { @@ -317,6 +339,21 @@ const parseScratchObject = function (object, runtime, extensions, topLevel) { Promise.all( childrenPromises ).then(children => { + // Need create broadcast msgs as variables after + // all other targets have finished processing. + if (target.isStage) { + const allBroadcastMsgs = globalBroadcastMsgObj.globalBroadcastMsgs; + for (const msgName in allBroadcastMsgs) { + const msgId = allBroadcastMsgs[msgName]; + const newMsg = new Variable( + msgId, + msgName, + Variable.BROADCAST_MESSAGE_TYPE, + false + ); + target.variables[newMsg.id] = newMsg; + } + } let targets = [target]; for (let n = 0; n < children.length; n++) { targets = targets.concat(children[n]); @@ -349,11 +386,12 @@ const sb2import = function (json, runtime, optForceSprite) { /** * Parse a single SB2 JSON-formatted block and its children. * @param {!object} sb2block SB2 JSON-formatted block. + * @param {Function} addBroadcastMsg function to update broadcast message name map * @param {Function} getVariableId function to retrieve a variable's ID based on name * @param {ImportedExtensionsInfo} extensions - (in/out) parsed extension information will be stored here. * @return {object} Scratch VM format block, or null if unsupported object. */ -const parseBlock = function (sb2block, getVariableId, extensions) { +const parseBlock = function (sb2block, addBroadcastMsg, getVariableId, extensions) { // First item in block object is the old opcode (e.g., 'forward:'). const oldOpcode = sb2block[0]; // Convert the block using the specMap. See sb2specmap.js. @@ -404,10 +442,10 @@ const parseBlock = function (sb2block, getVariableId, extensions) { let innerBlocks; if (typeof providedArg[0] === 'object' && providedArg[0]) { // Block list occupies the input. - innerBlocks = parseBlockList(providedArg, getVariableId, extensions); + innerBlocks = parseBlockList(providedArg, addBroadcastMsg, getVariableId, extensions); } else { // Single block occupies the input. - innerBlocks = [parseBlock(providedArg, getVariableId, extensions)]; + innerBlocks = [parseBlock(providedArg, addBroadcastMsg, getVariableId, extensions)]; } let previousBlock = null; for (let j = 0; j < innerBlocks.length; j++) { @@ -493,6 +531,11 @@ const parseBlock = function (sb2block, getVariableId, extensions) { if (expectedArg.fieldName === 'VARIABLE' || expectedArg.fieldName === 'LIST') { // Add `id` property to variable fields activeBlock.fields[expectedArg.fieldName].id = getVariableId(providedArg); + } else if (expectedArg.fieldName === 'BROADCAST_OPTION') { + // add the name in this field to the broadcast msg name map + addBroadcastMsg(providedArg); + const broadcastId = generateBroadcastMsgId(providedArg); + activeBlock.fields[expectedArg.fieldName].id = broadcastId; } const varType = expectedArg.variableType; if (typeof varType === 'string') { diff --git a/src/serialization/sb2_specmap.js b/src/serialization/sb2_specmap.js index 9e1034bf5..cc0a56964 100644 --- a/src/serialization/sb2_specmap.js +++ b/src/serialization/sb2_specmap.js @@ -656,7 +656,8 @@ const specMap = { argMap: [ { type: 'field', - fieldName: 'BROADCAST_OPTION' + fieldName: 'BROADCAST_OPTION', + variableType: Variable.BROADCAST_MESSAGE_TYPE } ] }, @@ -664,9 +665,9 @@ const specMap = { opcode: 'event_broadcast', argMap: [ { - type: 'input', - inputOp: 'event_broadcast_menu', - inputName: 'BROADCAST_OPTION' + type: 'field', + fieldName: 'BROADCAST_OPTION', + variableType: Variable.BROADCAST_MESSAGE_TYPE } ] }, @@ -674,9 +675,9 @@ const specMap = { opcode: 'event_broadcastandwait', argMap: [ { - type: 'input', - inputOp: 'event_broadcast_menu', - inputName: 'BROADCAST_OPTION' + type: 'field', + fieldName: 'BROADCAST_OPTION', + variableType: Variable.BROADCAST_MESSAGE_TYPE } ] }, diff --git a/test/integration/data.js b/test/integration/data.js index 63048fc78..c6cd71d1e 100644 --- a/test/integration/data.js +++ b/test/integration/data.js @@ -7,9 +7,7 @@ const VirtualMachine = require('../../src/index'); const uri = path.resolve(__dirname, '../fixtures/data.sb2'); const project = extract(uri); -// TODO (#828) Need to re-activate this test after sb2 import works for broadcast -// blocks -test('data', {todo: true}, t => { +test('data', t => { const vm = new VirtualMachine(); vm.attachStorage(makeTestStorage()); diff --git a/test/integration/event.js b/test/integration/event.js index 648f8cdd0..c4f3ee58a 100644 --- a/test/integration/event.js +++ b/test/integration/event.js @@ -7,9 +7,7 @@ const VirtualMachine = require('../../src/index'); const uri = path.resolve(__dirname, '../fixtures/event.sb2'); const project = extract(uri); -// TODO (#828) Need to re-activate this test after sb2 import works for broadcast -// blocks -test('event', {todo: true}, t => { +test('event', t => { const vm = new VirtualMachine(); vm.attachStorage(makeTestStorage()); diff --git a/test/integration/motion.js b/test/integration/motion.js index dbb24a119..689b21871 100644 --- a/test/integration/motion.js +++ b/test/integration/motion.js @@ -7,9 +7,7 @@ const VirtualMachine = require('../../src/index'); const uri = path.resolve(__dirname, '../fixtures/motion.sb2'); const project = extract(uri); -// TODO (#828) Need to re-activate this test after sb2 import works for broadcast -// blocks -test('motion', {todo: true}, t => { +test('motion', t => { const vm = new VirtualMachine(); vm.attachStorage(makeTestStorage()); From 9611401e1c34147265bc3d24f271051832aec954 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Fri, 1 Dec 2017 10:31:04 -0500 Subject: [PATCH 204/272] Move pen and wedo into extensions folder --- src/extension-support/extension-manager.js | 4 ++-- .../scratch3_pen/index.js} | 16 ++++++++-------- .../scratch3_wedo2/index.js} | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) rename src/{blocks/scratch3_pen.js => extensions/scratch3_pen/index.js} (98%) rename src/{blocks/scratch3_wedo2.js => extensions/scratch3_wedo2/index.js} (99%) diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index c3346a22d..af0dce066 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -6,8 +6,8 @@ const BlockType = require('./block-type'); // These extensions are currently built into the VM repository but should not be loaded at startup. // TODO: move these out into a separate repository? // TODO: change extension spec so that library info, including extension ID, can be collected through static methods -const Scratch3PenBlocks = require('../blocks/scratch3_pen'); -const Scratch3WeDo2Blocks = require('../blocks/scratch3_wedo2'); +const Scratch3PenBlocks = require('../extensions/scratch3_pen'); +const Scratch3WeDo2Blocks = require('../extensions/scratch3_wedo2'); const Scratch3MusicBlocks = require('../extensions/scratch3_music'); const builtinExtensions = { pen: Scratch3PenBlocks, diff --git a/src/blocks/scratch3_pen.js b/src/extensions/scratch3_pen/index.js similarity index 98% rename from src/blocks/scratch3_pen.js rename to src/extensions/scratch3_pen/index.js index 37609952f..8b6e51cbb 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/extensions/scratch3_pen/index.js @@ -1,11 +1,11 @@ -const ArgumentType = require('../extension-support/argument-type'); -const BlockType = require('../extension-support/block-type'); -const Cast = require('../util/cast'); -const Clone = require('../util/clone'); -const Color = require('../util/color'); -const MathUtil = require('../util/math-util'); -const RenderedTarget = require('../sprites/rendered-target'); -const log = require('../util/log'); +const ArgumentType = require('../../extension-support/argument-type'); +const BlockType = require('../../extension-support/block-type'); +const Cast = require('../../util/cast'); +const Clone = require('../../util/clone'); +const Color = require('../../util/color'); +const MathUtil = require('../../util/math-util'); +const RenderedTarget = require('../../sprites/rendered-target'); +const log = require('../../util/log'); /** * Icon svg to be displayed at the left edge of each extension block, encoded as a data URI. diff --git a/src/blocks/scratch3_wedo2.js b/src/extensions/scratch3_wedo2/index.js similarity index 99% rename from src/blocks/scratch3_wedo2.js rename to src/extensions/scratch3_wedo2/index.js index 1fefe0e16..ad1fd14d0 100644 --- a/src/blocks/scratch3_wedo2.js +++ b/src/extensions/scratch3_wedo2/index.js @@ -1,7 +1,7 @@ -const ArgumentType = require('../extension-support/argument-type'); -const BlockType = require('../extension-support/block-type'); -const color = require('../util/color'); -const log = require('../util/log'); +const ArgumentType = require('../../extension-support/argument-type'); +const BlockType = require('../../extension-support/block-type'); +const color = require('../../util/color'); +const log = require('../../util/log'); /** * Icon svg to be displayed at the left edge of each extension block, encoded as a data URI. From ae38ace665a97d72d18f7d27b58be7f0d150dac5 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Fri, 1 Dec 2017 10:32:32 -0500 Subject: [PATCH 205/272] Fix path in pen test --- test/integration/pen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/pen.js b/test/integration/pen.js index 7df798e7b..bb9f7c828 100644 --- a/test/integration/pen.js +++ b/test/integration/pen.js @@ -2,7 +2,7 @@ const Worker = require('tiny-worker'); const path = require('path'); const test = require('tap').test; -const Scratch3PenBlocks = require('../../src/blocks/scratch3_pen'); +const Scratch3PenBlocks = require('../../src/extensions/scratch3_pen/index.js'); const VirtualMachine = require('../../src/index'); const dispatch = require('../../src/dispatch/central-dispatch'); From 2091ef06362a4bd443d7661e0294eb626c60931e Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Fri, 1 Dec 2017 11:06:46 -0500 Subject: [PATCH 206/272] Add icon for music extension blocks --- src/extensions/scratch3_music/index.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index 807c3f792..6d661bd24 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -5,6 +5,13 @@ const Cast = require('../../util/cast'); const MathUtil = require('../../util/math-util'); const Timer = require('../../util/timer'); +/** + * Icon svg to be displayed at the left edge of each extension block, encoded as a data URI. + * @type {string} + */ +// eslint-disable-next-line max-len +const iconURI = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+PHRpdGxlPm11c2ljLWJsb2NrLWljb248L3RpdGxlPjxkZWZzPjxwYXRoIGQ9Ik0zMi4xOCAyNS44NzRDMzIuNjM2IDI4LjE1NyAzMC41MTIgMzAgMjcuNDMzIDMwYy0zLjA3IDAtNS45MjMtMS44NDMtNi4zNzItNC4xMjYtLjQ1OC0yLjI4NSAxLjY2NS00LjEzNiA0Ljc0My00LjEzNi42NDcgMCAxLjI4My4wODQgMS44OS4yMzQuMzM4LjA4Ni42MzcuMTguOTM4LjMwMi44Ny0uMDItLjEwNC0yLjI5NC0xLjgzNS0xMi4yMy0yLjEzNC0xMi4zMDIgMy4wNi0xLjg3IDguNzY4LTIuNzUyIDUuNzA4LS44ODUuMDc2IDQuODItMy42NSAzLjg0NC0zLjcyNC0uOTg3LTQuNjUtNy4xNTMuMjYzIDE0LjczOHptLTE2Ljk5OCA1Ljk5QzE1LjYzIDM0LjE0OCAxMy41MDcgMzYgMTAuNDQgMzZjLTMuMDcgMC01LjkyMi0xLjg1Mi02LjM4LTQuMTM2LS40NDgtMi4yODQgMS42NzQtNC4xMzUgNC43NS00LjEzNSAxLjAwMyAwIDEuOTc1LjE5NiAyLjg1NS41NDMuODIyLS4wNTUtLjE1LTIuMzc3LTEuODYyLTEyLjIyOC0yLjEzMy0xMi4zMDMgMy4wNi0xLjg3IDguNzY0LTIuNzUzIDUuNzA2LS44OTQuMDc2IDQuODItMy42NDggMy44MzQtMy43MjQtLjk4Ny00LjY1LTcuMTUyLjI2MiAxNC43Mzh6IiBpZD0iYSIvPjwvZGVmcz48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjx1c2UgZmlsbD0iI0ZGRiIgeGxpbms6aHJlZj0iI2EiLz48cGF0aCBzdHJva2Utb3BhY2l0eT0iLjEiIHN0cm9rZT0iIzAwMCIgZD0iTTI4LjQ1NiAyMS42NzVjLS4wMS0uMzEyLS4wODctLjgyNS0uMjU2LTEuNzAyLS4wOTYtLjQ5NS0uNjEyLTMuMDIyLS43NTMtMy43My0uMzk1LTEuOTgtLjc2LTMuOTItMS4xNDItNi4xMTMtLjczMi00LjIyMy0uNjkzLTYuMDUuMzQ0LTYuNTI3LjUtLjIzIDEuMDYtLjA4IDEuODQuMzUuNDE0LjIyNyAyLjE4MiAxLjM2NSAyLjA3IDEuMjk2IDEuOTk0IDEuMjQyIDMuNDY0IDEuNzc0IDQuOTMgMS41NDggMS41MjYtLjIzNyAyLjUwNC0uMDYgMi44NzYuNjE4LjM0OC42MzUuMDE1IDEuNDE2LS43MyAyLjE4LTEuNDcyIDEuNTE2LTMuOTc1IDIuNTE0LTUuODQ4IDIuMDIzLS44MjItLjIyLTEuMjM4LS40NjUtMi4zOC0xLjI2N2wtLjA5NS0uMDY2Yy4wNDcuNTkzLjI2NCAxLjc0LjcxNyAzLjgwMy4yOTQgMS4zMzYgMi4wOCA5LjE4NyAyLjYzNyAxMS42NzRsLjAwMi4wMTJjLjUyOCAyLjYzNy0xLjg3MyA0LjcyNC01LjIzNiA0LjcyNC0zLjI5IDAtNi4zNjMtMS45ODgtNi44NjItNC41MjgtLjUzLTIuNjQgMS44NzMtNC43MzQgNS4yMzMtNC43MzQuNjcyIDAgMS4zNDcuMDg1IDIuMDE0LjI1LjIyNy4wNTcuNDM2LjExOC42MzYuMTg3em0tMTYuOTk2IDUuOTljLS4wMS0uMzE4LS4wOS0uODM4LS4yNjYtMS43MzctLjA5LS40Ni0uNTk1LTIuOTM3LS43NTMtMy43MjctLjM5LTEuOTYtLjc1LTMuODktMS4xMy02LjA3LS43MzItNC4yMjMtLjY5Mi02LjA1LjM0NC02LjUyNi41MDItLjIzIDEuMDYtLjA4MiAxLjg0LjM1LjQxNS4yMjcgMi4xODIgMS4zNjQgMi4wNyAxLjI5NSAxLjk5MyAxLjI0MiAzLjQ2MiAxLjc3NCA0LjkyNiAxLjU0OCAxLjUyNS0uMjQgMi41MDQtLjA2NCAyLjg3Ni42MTQuMzQ4LjYzNS4wMTUgMS40MTUtLjcyOCAyLjE4LTEuNDc0IDEuNTE3LTMuOTc3IDIuNTEzLTUuODQ3IDIuMDE3LS44Mi0uMjItMS4yMzYtLjQ2NC0yLjM3OC0xLjI2N2wtLjA5NS0uMDY1Yy4wNDcuNTkzLjI2NCAxLjc0LjcxNyAzLjgwMi4yOTQgMS4zMzcgMi4wNzggOS4xOSAyLjYzNiAxMS42NzVsLjAwMy4wMTNjLjUxNyAyLjYzOC0xLjg4NCA0LjczMi01LjIzNCA0LjczMi0zLjI4NyAwLTYuMzYtMS45OTMtNi44Ny00LjU0LS41Mi0yLjY0IDEuODg0LTQuNzMgNS4yNC00LjczLjkwNSAwIDEuODAzLjE1IDIuNjUuNDM2eiIvPjwvZz48L3N2Zz4='; + /** * Class for the music-related blocks in Scratch 3.0 * @param {Runtime} runtime - the runtime instantiating this block package. @@ -395,6 +402,7 @@ class Scratch3MusicBlocks { return { id: 'music', name: 'Music', + iconURI: iconURI, blocks: [ { opcode: 'playDrumForBeats', From aab4a45622c5448331306ea0f7b2304721d8e37d Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Fri, 1 Dec 2017 11:27:54 -0500 Subject: [PATCH 207/272] Minor Refactoring/cleanup. --- src/serialization/sb2.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js index ae501bda5..d19175dca 100644 --- a/src/serialization/sb2.js +++ b/src/serialization/sb2.js @@ -168,17 +168,14 @@ const generateVariableIdGetter = (function () { }; }()); -const generateBroadcastMsgId = function (name) { - return `broadcastMsgId-${name}`; -}; - const globalBroadcastMsgStateGenerator = (function () { let broadcastMsgNameMap = {}; return function (topLevel) { if (topLevel) broadcastMsgNameMap = {}; return { broadcastMsgMapUpdater: function (name) { - broadcastMsgNameMap[name] = generateBroadcastMsgId(name); + broadcastMsgNameMap[name] = `broadcastMsgId-${name}`; + return broadcastMsgNameMap[name]; }, globalBroadcastMsgs: broadcastMsgNameMap }; @@ -533,8 +530,7 @@ const parseBlock = function (sb2block, addBroadcastMsg, getVariableId, extension activeBlock.fields[expectedArg.fieldName].id = getVariableId(providedArg); } else if (expectedArg.fieldName === 'BROADCAST_OPTION') { // add the name in this field to the broadcast msg name map - addBroadcastMsg(providedArg); - const broadcastId = generateBroadcastMsgId(providedArg); + const broadcastId = addBroadcastMsg(providedArg); activeBlock.fields[expectedArg.fieldName].id = broadcastId; } const varType = expectedArg.variableType; From eede8105d1ecca28464f26e8d1436069376c22ad Mon Sep 17 00:00:00 2001 From: sjhuang26 Date: Fri, 1 Dec 2017 20:06:55 -0500 Subject: [PATCH 208/272] Clear answer on green flag --- src/blocks/scratch3_sensing.js | 5 +++++ src/engine/runtime.js | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/blocks/scratch3_sensing.js b/src/blocks/scratch3_sensing.js index 19357c88e..b23fe740e 100644 --- a/src/blocks/scratch3_sensing.js +++ b/src/blocks/scratch3_sensing.js @@ -21,6 +21,7 @@ class Scratch3SensingBlocks { this._questionList = []; this.runtime.on('ANSWER', this._onAnswer.bind(this)); + this.runtime.on('PROJECT_START', this._resetAnswer.bind(this)); this.runtime.on('PROJECT_STOP_ALL', this._clearAllQuestions.bind(this)); } @@ -73,6 +74,10 @@ class Scratch3SensingBlocks { } } + _resetAnswer () { + this._answer = ''; + } + _enqueueAsk (question, resolve, target, wasVisible, wasStage) { this._questionList.push([question, resolve, target, wasVisible, wasStage]); } diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 8131bdd86..a8e044e37 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -317,6 +317,15 @@ class Runtime extends EventEmitter { return 'BLOCK_GLOW_OFF'; } + /** + * Event name when the project is started (threads may not necessarily be + * running). + * @const {string} + */ + static get PROJECT_START () { + return 'PROJECT_START'; + } + /** * Event name when threads start running. * Used by the UI to indicate running status. @@ -1057,6 +1066,7 @@ class Runtime extends EventEmitter { */ greenFlag () { this.stopAll(); + this.emit(Runtime.PROJECT_START); this.ioDevices.clock.resetProjectTimer(); this.clearEdgeActivatedValues(); // Inform all targets of the green flag. From b2802b75f12660f37b9bb39fb66c9860d78f6e4e Mon Sep 17 00:00:00 2001 From: sjhuang26 Date: Sat, 2 Dec 2017 08:33:32 -0500 Subject: [PATCH 209/272] Go to front in stage does nothing --- src/blocks/scratch3_looks.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index 6c8f4fe3b..1429b6dd7 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -410,7 +410,9 @@ class Scratch3LooksBlocks { } goToFront (args, util) { - util.target.goToFront(); + if (!util.target.isStage) { + util.target.goToFront(); + } } goBackLayers (args, util) { From 48505fd7e204fcaea2d8893c1b59fec0295a513c Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Mon, 4 Dec 2017 18:48:49 +0000 Subject: [PATCH 210/272] chore(package): update webpack to version 3.10.0 Closes #620 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2ccc80891..0830dee92 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "stats.js": "^0.17.0", "tap": "^10.2.0", "tiny-worker": "^2.1.1", - "webpack": "^2.4.1", + "webpack": "^3.10.0", "webpack-dev-server": "^2.4.1", "worker-loader": "1.1.0" } From 34b0aff6370bf54bbefa24e25745a633796bb0ba Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Mon, 4 Dec 2017 18:01:29 -0500 Subject: [PATCH 211/272] Bugfix for scratch-gui issue #994, where executing a broadcast block from the flyout was creating a conflicting variable, causing a fatal error. --- src/blocks/scratch3_event.js | 50 +++++++++++++++++++----------------- src/engine/target.js | 23 +++++++++++------ test/unit/blocks_event.js | 6 +++-- test/unit/engine_target.js | 17 ++---------- 4 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/blocks/scratch3_event.js b/src/blocks/scratch3_event.js index 5fbaa5b7d..5ee2fab1d 100644 --- a/src/blocks/scratch3_event.js +++ b/src/blocks/scratch3_event.js @@ -56,36 +56,40 @@ class Scratch3EventBlocks { } broadcast (args, util) { - const broadcastVar = util.runtime.getTargetForStage().lookupOrCreateBroadcastMsg( + const broadcastVar = util.runtime.getTargetForStage().lookupBroadcastMsg( args.BROADCAST_OPTION.id, args.BROADCAST_OPTION.name); - const broadcastOption = broadcastVar.name; - util.startHats('event_whenbroadcastreceived', { - BROADCAST_OPTION: broadcastOption - }); + if (broadcastVar) { + const broadcastOption = broadcastVar.name; + util.startHats('event_whenbroadcastreceived', { + BROADCAST_OPTION: broadcastOption + }); + } } broadcastAndWait (args, util) { - const broadcastVar = util.runtime.getTargetForStage().lookupOrCreateBroadcastMsg( + const broadcastVar = util.runtime.getTargetForStage().lookupBroadcastMsg( args.BROADCAST_OPTION.id, args.BROADCAST_OPTION.name); - const broadcastOption = broadcastVar.name; - // Have we run before, starting threads? - if (!util.stackFrame.startedThreads) { - // No - start hats for this broadcast. - util.stackFrame.startedThreads = util.startHats( - 'event_whenbroadcastreceived', { - BROADCAST_OPTION: broadcastOption + if (broadcastVar) { + const broadcastOption = broadcastVar.name; + // Have we run before, starting threads? + if (!util.stackFrame.startedThreads) { + // No - start hats for this broadcast. + util.stackFrame.startedThreads = util.startHats( + 'event_whenbroadcastreceived', { + BROADCAST_OPTION: broadcastOption + } + ); + if (util.stackFrame.startedThreads.length === 0) { + // Nothing was started. + return; } - ); - if (util.stackFrame.startedThreads.length === 0) { - // Nothing was started. - return; } - } - // We've run before; check if the wait is still going on. - const instance = this; - const waiting = util.stackFrame.startedThreads.some(thread => instance.runtime.isActiveThread(thread)); - if (waiting) { - util.yield(); + // We've run before; check if the wait is still going on. + const instance = this; + const waiting = util.stackFrame.startedThreads.some(thread => instance.runtime.isActiveThread(thread)); + if (waiting) { + util.yield(); + } } } } diff --git a/src/engine/target.js b/src/engine/target.js index 39273fcc2..4e574177e 100644 --- a/src/engine/target.js +++ b/src/engine/target.js @@ -4,6 +4,7 @@ const Blocks = require('./blocks'); const Variable = require('../engine/variable'); const uid = require('../util/uid'); const {Map} = require('immutable'); +const log = require('../util/log'); /** * @fileoverview @@ -93,19 +94,25 @@ class Target extends EventEmitter { } /** - * Look up a broadcast message object, and create it if one doesn't exist. + * Look up a broadcast message object with the given id and return it + * if it exists. * @param {string} id Id of the variable. * @param {string} name Name of the variable. * @return {!Variable} Variable object. */ - lookupOrCreateBroadcastMsg (id, name) { + lookupBroadcastMsg (id, name) { const broadcastMsg = this.lookupVariableById(id); - if (broadcastMsg) return broadcastMsg; - // No variable with this name exists - create it locally. - const newBroadcastMsg = new Variable(id, name, - Variable.BROADCAST_MESSAGE_TYPE, false); - this.variables[id] = newBroadcastMsg; - return newBroadcastMsg; + if (broadcastMsg) { + if (broadcastMsg.name !== name) { + log.error(`Found broadcast message with id: ${id}, but` + + `its name, ${broadcastMsg.name} did not match expected name ${name}.`); + } + if (broadcastMsg.type !== Variable.BROADCAST_MESSAGE_TYPE) { + log.error(`Found variable with id: ${id}, but its type ${broadcastMsg.type}` + + `did not match expected type ${Variable.BROADCAST_MESSAGE_TYPE}`); + } + return broadcastMsg; + } } /** diff --git a/test/unit/blocks_event.js b/test/unit/blocks_event.js index 35a1f0b4f..672ea332c 100644 --- a/test/unit/blocks_event.js +++ b/test/unit/blocks_event.js @@ -6,6 +6,7 @@ const Event = require('../../src/blocks/scratch3_event'); const Runtime = require('../../src/engine/runtime'); const Target = require('../../src/engine/target'); const Thread = require('../../src/engine/thread'); +const Variable = require('../../src/engine/variable'); test('#760 - broadcastAndWait', t => { const broadcastAndWaitBlock = { @@ -52,6 +53,7 @@ test('#760 - broadcastAndWait', t => { b.createBlock(receiveMessageBlock); const tgt = new Target(rt, b); tgt.isStage = true; + tgt.createVariable('testBroadcastID', 'message', Variable.BROADCAST_MESSAGE_TYPE); rt.targets.push(tgt); let th = rt._pushThread('broadcastAndWaitBlock', t); @@ -67,12 +69,12 @@ test('#760 - broadcastAndWait', t => { // yields when some thread is active t.strictEqual(th.status, Thread.STATUS_YIELD); th.status = Thread.STATUS_RUNNING; - e.broadcastAndWait({BROADCAST_OPTION: 'message'}, util); + e.broadcastAndWait({BROADCAST_OPTION: {id: 'testBroadcastID', name: 'message'}}, util); t.strictEqual(th.status, Thread.STATUS_YIELD); // does not yield once all threads are done th.status = Thread.STATUS_RUNNING; rt.threads[1].status = Thread.STATUS_DONE; - e.broadcastAndWait({BROADCAST_OPTION: 'message'}, util); + e.broadcastAndWait({BROADCAST_OPTION: {id: 'testBroadcastID', name: 'message'}}, util); t.strictEqual(th.status, Thread.STATUS_RUNNING); // restarts done threads that are in runtime threads diff --git a/test/unit/engine_target.js b/test/unit/engine_target.js index 4f663906d..30ff5eb82 100644 --- a/test/unit/engine_target.js +++ b/test/unit/engine_target.js @@ -174,20 +174,7 @@ test('lookupOrCreateList returns list if one with given id exists', t => { t.end(); }); -test('lookupOrCreateBroadcastMsg creates a var if one does not exist', t => { - const target = new Target(); - const variables = target.variables; - - t.equal(Object.keys(variables).length, 0); - const broadcastVar = target.lookupOrCreateBroadcastMsg('foo', 'bar'); - t.equal(Object.keys(variables).length, 1); - t.equal(broadcastVar.id, 'foo'); - t.equal(broadcastVar.name, 'bar'); - - t.end(); -}); - -test('lookupOrCreateBroadcastMsg returns the var with given id if exists', t => { +test('lookupBroadcastMsg returns the var with given id if exists', t => { const target = new Target(); const variables = target.variables; @@ -195,7 +182,7 @@ test('lookupOrCreateBroadcastMsg returns the var with given id if exists', t => target.createVariable('foo', 'bar', Variable.BROADCAST_MESSAGE_TYPE); t.equal(Object.keys(variables).length, 1); - const broadcastMsg = target.lookupOrCreateBroadcastMsg('foo', 'bar'); + const broadcastMsg = target.lookupBroadcastMsg('foo', 'bar'); t.equal(Object.keys(variables).length, 1); t.equal(broadcastMsg.id, 'foo'); t.equal(broadcastMsg.name, 'bar'); From 2d2b691b6f0e5c9f082c3f85639185c4fd987784 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 6 Dec 2017 11:21:00 -0500 Subject: [PATCH 212/272] Return a default falsey value for unknown params based on param type --- src/blocks/scratch3_procedures.js | 17 ++++++++++++++--- test/unit/engine_thread.js | 4 +++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/blocks/scratch3_procedures.js b/src/blocks/scratch3_procedures.js index 645e582ed..3ba743d8b 100644 --- a/src/blocks/scratch3_procedures.js +++ b/src/blocks/scratch3_procedures.js @@ -15,8 +15,8 @@ class Scratch3ProcedureBlocks { return { procedures_definition: this.definition, procedures_call: this.call, - argument_reporter_string_number: this.param, - argument_reporter_boolean: this.param + argument_reporter_string_number: this.argumentReporterStringNumber, + argument_reporter_boolean: this.argumentReporterBoolean }; } @@ -47,8 +47,19 @@ class Scratch3ProcedureBlocks { } } - param (args, util) { + argumentReporterStringNumber (args, util) { const value = util.getParam(args.VALUE); + if (value === null) { + return ''; + } + return value; + } + + argumentReporterBoolean (args, util) { + const value = util.getParam(args.VALUE); + if (value === null) { + return false; + } return value; } } diff --git a/test/unit/engine_thread.js b/test/unit/engine_thread.js index 533f72523..15fab7c02 100644 --- a/test/unit/engine_thread.js +++ b/test/unit/engine_thread.js @@ -110,7 +110,9 @@ test('PushGetParam', t => { th.pushParam('testParam', 'testValue'); t.strictEquals(th.peekStackFrame().params.testParam, 'testValue'); t.strictEquals(th.getParam('testParam'), 'testValue'); - + // Params outside of define stack always evaluate to null + t.strictEquals(th.getParam('nonExistentParam'), null); + t.end(); }); From f51cf9877eac972f733905d4de5b0f6b7aabf8af Mon Sep 17 00:00:00 2001 From: chrisgarrity Date: Mon, 11 Dec 2017 15:41:45 -0500 Subject: [PATCH 213/272] Preliminary localization (#777) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * localize the block and menu strings in the pen extension * adds .tx/config to be able to push translations to transifex * includes format-message to localize strings and extracting them. * add setLocale function to VM to allow GUI to pass in locale data. * refresh block definitions when the locale changes. ### Still to be decided For now just extracting messages from the pen extension into their own file. We’ll need to decide if each category gets its own file, or group all the strings into one resource. --- .gitignore | 3 + .tx/config | 8 ++ package.json | 6 +- src/engine/runtime.js | 43 +++++++ src/extension-support/extension-manager.js | 26 ++++- src/extensions/scratch3_pen/index.js | 130 ++++++++++++++++++--- src/virtual-machine.js | 16 +++ 7 files changed, 210 insertions(+), 22 deletions(-) create mode 100644 .tx/config diff --git a/.gitignore b/.gitignore index a733474c9..015fdc57b 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ npm-* # Build /dist /playground + +# Localization +/translations diff --git a/.tx/config b/.tx/config new file mode 100644 index 000000000..b6cb702a8 --- /dev/null +++ b/.tx/config @@ -0,0 +1,8 @@ +[main] +host = https://www.transifex.com + +[experimental-scratch.pen] +file_filter = translations/pen/.json +source_file = translations/pen/en.json +source_lang = en +type = CHROME diff --git a/package.json b/package.json index aa5de51ad..d6902c5dd 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,9 @@ "build": "webpack --progress --colors --bail", "coverage": "tap ./test/{unit,integration}/*.js --coverage --coverage-report=lcov", "deploy": "touch playground/.nojekyll && gh-pages -t -d playground -m \"Build for $(git log --pretty=format:%H -n1)\"", - "lint": "eslint .", + "extract:pen": "mkdirp translations/pen && format-message extract --out-file translations/pen/en.json src/extensions/scratch3_pen/index.js", + "i18n:src": "npm run extract:pen", + "lint": "eslint . && format-message lint src/**/*.js", "prepublish": "in-publish && npm run build || not-in-publish", "start": "webpack-dev-server", "tap": "tap ./test/{unit,integration}/*.js", @@ -37,6 +39,8 @@ "eslint": "^4.5.0", "eslint-config-scratch": "^5.0.0", "expose-loader": "0.7.4", + "format-message": "5.2.1", + "format-message-cli": "5.2.1", "gh-pages": "^1.1.0", "highlightjs": "^9.8.0", "htmlparser2": "3.9.2", diff --git a/src/engine/runtime.js b/src/engine/runtime.js index d0c09cc70..7ab5aa2b1 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -385,6 +385,14 @@ class Runtime extends EventEmitter { return 'EXTENSION_ADDED'; } + /** + * Event name for reporting that blocksInfo was updated. + * @const {string} + */ + static get BLOCKSINFO_UPDATE () { + return 'BLOCKSINFO_UPDATE'; + } + /** * How rapidly we try to step threads by default, in ms. */ @@ -497,6 +505,41 @@ class Runtime extends EventEmitter { this.emit(Runtime.EXTENSION_ADDED, categoryInfo.blocks.concat(categoryInfo.menus)); } + /** + * Reregister the primitives for an extension + * @param {ExtensionInfo} extensionInfo - new info (results of running getInfo) + * for an extension + * @private + */ + _refreshExtensionPrimitives (extensionInfo) { + let extensionBlocks = []; + for (const categoryInfo of this._blockInfo) { + if (extensionInfo.id === categoryInfo.id) { + categoryInfo.blocks = []; + categoryInfo.menus = []; + for (const menuName in extensionInfo.menus) { + if (extensionInfo.menus.hasOwnProperty(menuName)) { + const menuItems = extensionInfo.menus[menuName]; + const convertedMenu = this._buildMenuForScratchBlocks(menuName, menuItems, categoryInfo); + categoryInfo.menus.push(convertedMenu); + } + } + for (const blockInfo of extensionInfo.blocks) { + const convertedBlock = this._convertForScratchBlocks(blockInfo, categoryInfo); + const opcode = convertedBlock.json.type; + categoryInfo.blocks.push(convertedBlock); + this._primitives[opcode] = convertedBlock.info.func; + if (blockInfo.blockType === BlockType.HAT) { + this._hats[opcode] = {edgeActivated: true}; /** @TODO let extension specify this */ + } + } + extensionBlocks = extensionBlocks.concat(categoryInfo.blocks, categoryInfo.menus); + } + } + + this.emit(Runtime.BLOCKSINFO_UPDATE, extensionBlocks); + } + /** * Build the scratch-blocks JSON for a menu. Note that scratch-blocks treats menus as a special kind of block. * @param {string} menuName - the name of the menu diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index af0dce066..3228f5c2a 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -78,7 +78,7 @@ class ExtensionManager { * @type {Set.} * @private */ - this._loadedExtensions = new Set(); + this._loadedExtensions = new Map(); /** * Keep a reference to the runtime so we can construct internal extension objects. @@ -119,8 +119,8 @@ class ExtensionManager { const extension = builtinExtensions[extensionURL]; const extensionInstance = new extension(this.runtime); - return this._registerInternalExtension(extensionInstance).then(() => { - this._loadedExtensions.add(extensionURL); + return this._registerInternalExtension(extensionInstance).then(serviceName => { + this._loadedExtensions.set(extensionURL, serviceName); }); } @@ -133,6 +133,21 @@ class ExtensionManager { }); } + /** + * regenerate blockinfo for any loaded extensions + */ + refreshBlocks () { + this._loadedExtensions.forEach(serviceName => { + dispatch.call(serviceName, 'getInfo') + .then(info => { + dispatch.call('runtime', '_refreshExtensionPrimitives', info); + }) + .catch(e => { + log.error(`Failed to refresh buildtin extension primitives: ${JSON.stringify(e)}`); + }); + }); + } + allocateWorker () { const id = this.nextExtensionWorker++; const workerInfo = this.pendingExtensions.shift(); @@ -175,7 +190,10 @@ class ExtensionManager { const fakeWorkerId = this.nextExtensionWorker++; const serviceName = `extension.${fakeWorkerId}.${extensionInfo.id}`; return dispatch.setService(serviceName, extensionObject) - .then(() => dispatch.call('extensions', 'registerExtensionService', serviceName)); + .then(() => { + dispatch.call('extensions', 'registerExtensionService', serviceName); + return serviceName; + }); } /** diff --git a/src/extensions/scratch3_pen/index.js b/src/extensions/scratch3_pen/index.js index 8b6e51cbb..e194a1d50 100644 --- a/src/extensions/scratch3_pen/index.js +++ b/src/extensions/scratch3_pen/index.js @@ -3,6 +3,7 @@ const BlockType = require('../../extension-support/block-type'); const Cast = require('../../util/cast'); const Clone = require('../../util/clone'); const Color = require('../../util/color'); +const formatMessage = require('format-message'); const MathUtil = require('../../util/math-util'); const RenderedTarget = require('../../sprites/rendered-target'); const log = require('../../util/log'); @@ -15,7 +16,7 @@ const log = require('../../util/log'); const iconURI = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+cGVuLWljb248L3RpdGxlPjxnIHN0cm9rZT0iIzU3NUU3NSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwYXRoIGQ9Ik04Ljc1MyAzNC42MDJsLTQuMjUgMS43OCAxLjc4My00LjIzN2MxLjIxOC0yLjg5MiAyLjkwNy01LjQyMyA1LjAzLTcuNTM4TDMxLjA2NiA0LjkzYy44NDYtLjg0MiAyLjY1LS40MSA0LjAzMi45NjcgMS4zOCAxLjM3NSAxLjgxNiAzLjE3My45NyA0LjAxNUwxNi4zMTggMjkuNTljLTIuMTIzIDIuMTE2LTQuNjY0IDMuOC03LjU2NSA1LjAxMiIgZmlsbD0iI0ZGRiIvPjxwYXRoIGQ9Ik0yOS40MSA2LjExcy00LjQ1LTIuMzc4LTguMjAyIDUuNzcyYy0xLjczNCAzLjc2Ni00LjM1IDEuNTQ2LTQuMzUgMS41NDYiLz48cGF0aCBkPSJNMzYuNDIgOC44MjVjMCAuNDYzLS4xNC44NzMtLjQzMiAxLjE2NGwtOS4zMzUgOS4zYy4yODItLjI5LjQxLS42NjguNDEtMS4xMiAwLS44NzQtLjUwNy0xLjk2My0xLjQwNi0yLjg2OC0xLjM2Mi0xLjM1OC0zLjE0Ny0xLjgtNC4wMDItLjk5TDMwLjk5IDUuMDFjLjg0NC0uODQgMi42NS0uNDEgNC4wMzUuOTYuODk4LjkwNCAxLjM5NiAxLjk4MiAxLjM5NiAyLjg1NU0xMC41MTUgMzMuNzc0Yy0uNTczLjMwMi0xLjE1Ny41Ny0xLjc2NC44M0w0LjUgMzYuMzgybDEuNzg2LTQuMjM1Yy4yNTgtLjYwNC41My0xLjE4Ni44MzMtMS43NTcuNjkuMTgzIDEuNDQ4LjYyNSAyLjEwOCAxLjI4Mi42Ni42NTggMS4xMDIgMS40MTIgMS4yODcgMi4xMDIiIGZpbGw9IiM0Qzk3RkYiLz48cGF0aCBkPSJNMzYuNDk4IDguNzQ4YzAgLjQ2NC0uMTQuODc0LS40MzMgMS4xNjVsLTE5Ljc0MiAxOS42OGMtMi4xMyAyLjExLTQuNjczIDMuNzkzLTcuNTcyIDUuMDFMNC41IDM2LjM4bC45NzQtMi4zMTYgMS45MjUtLjgwOGMyLjg5OC0xLjIxOCA1LjQ0LTIuOSA3LjU3LTUuMDFsMTkuNzQzLTE5LjY4Yy4yOTItLjI5Mi40MzItLjcwMi40MzItMS4xNjUgMC0uNjQ2LS4yNy0xLjQtLjc4LTIuMTIyLjI1LjE3Mi41LjM3Ny43MzcuNjE0Ljg5OC45MDUgMS4zOTYgMS45ODMgMS4zOTYgMi44NTYiIGZpbGw9IiM1NzVFNzUiIG9wYWNpdHk9Ii4xNSIvPjxwYXRoIGQ9Ik0xOC40NSAxMi44M2MwIC41LS40MDQuOTA1LS45MDQuOTA1cy0uOTA1LS40MDUtLjkwNS0uOTA0YzAtLjUuNDA3LS45MDMuOTA2LS45MDMuNSAwIC45MDQuNDA0LjkwNC45MDR6IiBmaWxsPSIjNTc1RTc1Ii8+PC9nPjwvc3ZnPg=='; /** - * Enum for pen color parameters. + * Enum for pen color parameter values. * @readonly * @enum {string} */ @@ -201,6 +202,49 @@ class Scratch3PenBlocks { return MathUtil.wrapClamp(value, 0, 100); } + /** + * Initialize color parameters menu with localized strings + * @returns {array} of the localized text and values for each menu element + * @private + */ + _initColorParam () { + return [ + { + text: formatMessage({ + id: 'pen.colorMenu.color', + default: 'color', + description: 'label for color element in color picker for pen extension' + }), + value: ColorParam.COLOR + }, + { + text: formatMessage({ + id: 'pen.colorMenu.saturation', + default: 'saturation', + description: 'label for saturation element in color picker for pen extension' + }), + value: ColorParam.SATURATION + }, + { + text: formatMessage({ + id: 'pen.colorMenu.brightness', + default: 'brightness', + description: 'label for brightness element in color picker for pen extension' + }), + value: ColorParam.BRIGHTNESS + }, + { + text: formatMessage({ + id: 'pen.colorMenu.transparency', + default: 'transparency', + description: 'label for transparency element in color picker for pen extension' + }), + value: ColorParam.TRANSPARENCY + + } + ]; + } + /** * Clamp a pen color parameter to the range (0,100). * @param {number} value - the value to be clamped. @@ -246,26 +290,48 @@ class Scratch3PenBlocks { blocks: [ { opcode: 'clear', - blockType: BlockType.COMMAND + blockType: BlockType.COMMAND, + text: formatMessage({ + id: 'pen.clear', + default: 'clear', + description: 'erase all pen trails and stamps' + }) }, { opcode: 'stamp', - blockType: BlockType.COMMAND + blockType: BlockType.COMMAND, + text: formatMessage({ + id: 'pen.stamp', + default: 'stamp', + description: 'render current costume on the background' + }) }, { opcode: 'penDown', blockType: BlockType.COMMAND, - text: 'pen down' + text: formatMessage({ + id: 'pen.penDown', + default: 'pen down', + description: 'start leaving a trail when the sprite moves' + }) }, { opcode: 'penUp', blockType: BlockType.COMMAND, - text: 'pen up' + text: formatMessage({ + id: 'pen.penUp', + default: 'pen up', + description: 'stop leaving a trail behind the sprite' + }) }, { opcode: 'setPenColorToColor', blockType: BlockType.COMMAND, - text: 'set pen color to [COLOR]', + text: formatMessage({ + id: 'pen.setColor', + default: 'set pen color to [COLOR]', + description: 'set the pen color to a particular (RGB) value' + }), arguments: { COLOR: { type: ArgumentType.COLOR @@ -275,7 +341,11 @@ class Scratch3PenBlocks { { opcode: 'changePenColorParamBy', blockType: BlockType.COMMAND, - text: 'change pen [COLOR_PARAM] by [VALUE]', + text: formatMessage({ + id: 'pen.changeColorParam', + default: 'change pen [COLOR_PARAM] by [VALUE]', + description: 'change the state of a pen color parameter' + }), arguments: { COLOR_PARAM: { type: ArgumentType.STRING, @@ -291,7 +361,11 @@ class Scratch3PenBlocks { { opcode: 'setPenColorParamTo', blockType: BlockType.COMMAND, - text: 'set pen [COLOR_PARAM] to [VALUE]', + text: formatMessage({ + id: 'pen.setColorParam', + default: 'set pen [COLOR_PARAM] to [VALUE]', + description: 'set the state for a pen color parameter e.g. saturation' + }), arguments: { COLOR_PARAM: { type: ArgumentType.STRING, @@ -307,7 +381,11 @@ class Scratch3PenBlocks { { opcode: 'changePenSizeBy', blockType: BlockType.COMMAND, - text: 'change pen size by [SIZE]', + text: formatMessage({ + id: 'pen.changeSize', + default: 'change pen size by [SIZE]', + description: 'change the diameter of the trail left by a sprite' + }), arguments: { SIZE: { type: ArgumentType.NUMBER, @@ -318,7 +396,11 @@ class Scratch3PenBlocks { { opcode: 'setPenSizeTo', blockType: BlockType.COMMAND, - text: 'set pen size to [SIZE]', + text: formatMessage({ + id: 'pen.setSize', + default: 'set pen size to [SIZE]', + description: 'set the diameter of a trail left by a sprite' + }), arguments: { SIZE: { type: ArgumentType.NUMBER, @@ -330,7 +412,11 @@ class Scratch3PenBlocks { { opcode: 'setPenShadeToNumber', blockType: BlockType.COMMAND, - text: 'set pen shade to [SHADE]', + text: formatMessage({ + id: 'pen.setShade', + default: 'set pen shade to [SHADE]', + description: 'legacy pen blocks - set pen shade' + }), arguments: { SHADE: { type: ArgumentType.NUMBER, @@ -342,7 +428,11 @@ class Scratch3PenBlocks { { opcode: 'changePenShadeBy', blockType: BlockType.COMMAND, - text: 'change pen shade by [SHADE]', + text: formatMessage({ + id: 'pen.changeShade', + default: 'change pen shade by [SHADE]', + description: 'legacy pen blocks - change pen shade' + }), arguments: { SHADE: { type: ArgumentType.NUMBER, @@ -354,7 +444,11 @@ class Scratch3PenBlocks { { opcode: 'setPenHueToNumber', blockType: BlockType.COMMAND, - text: 'set pen hue to [HUE]', + text: formatMessage({ + id: 'pen.setHue', + default: 'set pen hue to [HUE]', + description: 'legacy pen blocks - set pen color to number' + }), arguments: { HUE: { type: ArgumentType.NUMBER, @@ -366,7 +460,11 @@ class Scratch3PenBlocks { { opcode: 'changePenHueBy', blockType: BlockType.COMMAND, - text: 'change pen hue by [HUE]', + text: formatMessage({ + id: 'pen.changeHue', + default: 'change pen hue by [HUE]', + description: 'legacy pen blocks - change pen color' + }), arguments: { HUE: { type: ArgumentType.NUMBER, @@ -377,9 +475,7 @@ class Scratch3PenBlocks { } ], menus: { - colorParam: - [ColorParam.COLOR, ColorParam.SATURATION, - ColorParam.BRIGHTNESS, ColorParam.TRANSPARENCY] + colorParam: this._initColorParam() } }; } diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 994de9860..7c1605d47 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -7,6 +7,7 @@ const Runtime = require('./engine/runtime'); const sb2 = require('./serialization/sb2'); const sb3 = require('./serialization/sb3'); const StringUtil = require('./util/string-util'); +const formatMessage = require('format-message'); const {loadCostume} = require('./import/load-costume.js'); const {loadSound} = require('./import/load-sound.js'); @@ -67,6 +68,9 @@ class VirtualMachine extends EventEmitter { this.runtime.on(Runtime.EXTENSION_ADDED, blocksInfo => { this.emit(Runtime.EXTENSION_ADDED, blocksInfo); }); + this.runtime.on(Runtime.BLOCKSINFO_UPDATE, blocksInfo => { + this.emit(Runtime.BLOCKSINFO_UPDATE, blocksInfo); + }); this.extensionManager = new ExtensionManager(this.runtime); @@ -552,6 +556,18 @@ class VirtualMachine extends EventEmitter { this.runtime.attachStorage(storage); } + /** + * set the current locale and builtin messages for the VM + * @param {[type]} locale current locale + * @param {[type]} messages builtin messages map for current locale + */ + setLocale (locale, messages) { + if (locale !== formatMessage.setup().locale) { + formatMessage.setup({locale: locale, translations: {[locale]: messages}}); + this.extensionManager.refreshBlocks(); + } + } + /** * Handle a Blockly event for the current editing target. * @param {!Blockly.Event} e Any Blockly event. From 25ded4cff78c9f878f5a0f7b7ad304255f271326 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Mon, 11 Dec 2017 17:01:23 -0500 Subject: [PATCH 214/272] Fix spelling of coloUrTertiary --- src/engine/runtime.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 7ab5aa2b1..9c7f3e9e4 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -602,7 +602,7 @@ class Runtime extends EventEmitter { category: categoryInfo.name, colour: categoryInfo.color1, colourSecondary: categoryInfo.color2, - colorTertiary: categoryInfo.color3, + colourTertiary: categoryInfo.color3, args0: [] }; From e8fd5b1f13924accce65bc5af6cfab7dfa6ba97c Mon Sep 17 00:00:00 2001 From: Ray Schamp Date: Tue, 12 Dec 2017 12:17:33 -0500 Subject: [PATCH 215/272] Replace playground with benchmark --- src/benchmark/index.html | 81 ---- src/{benchmark => playground}/benchmark.css | 0 src/{benchmark => playground}/benchmark.js | 0 src/playground/index.html | 145 ++++--- src/playground/playground.css | 73 ---- src/playground/playground.js | 402 -------------------- webpack.config.js | 73 +--- 7 files changed, 76 insertions(+), 698 deletions(-) delete mode 100644 src/benchmark/index.html rename src/{benchmark => playground}/benchmark.css (100%) rename src/{benchmark => playground}/benchmark.js (100%) delete mode 100644 src/playground/playground.css delete mode 100644 src/playground/playground.js diff --git a/src/benchmark/index.html b/src/benchmark/index.html deleted file mode 100644 index 9e6b885a4..000000000 --- a/src/benchmark/index.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - Scratch VM Benchmark - - - -

Scratch VM Benchmark

-

- Welcome to the scratch-vm benchmark. This tool helps you profile a scratch - project. When you load the page, it: -

    -
  1. loads the default project -
  2. runs the project for 4 seconds to warm up -
  3. profiles for 6 seconds -
  4. stops and reports -
-

- - -

- Try a different project, like `130041250` -

- -
- -
- - 0 / 0 -
-
-
- - ... -
-
- - ... -
-
- - ... -
-
- -
- - - - - - - -
FrameSelf TimeTotal TimeExecutions
- - - - - - - - - - -
opcodeSelf TimeTotal TimeExecutions
-
- -
- - - - - - - - - - - diff --git a/src/benchmark/benchmark.css b/src/playground/benchmark.css similarity index 100% rename from src/benchmark/benchmark.css rename to src/playground/benchmark.css diff --git a/src/benchmark/benchmark.js b/src/playground/benchmark.js similarity index 100% rename from src/benchmark/benchmark.js rename to src/playground/benchmark.js diff --git a/src/playground/index.html b/src/playground/index.html index 6282014fb..81ba4f577 100644 --- a/src/playground/index.html +++ b/src/playground/index.html @@ -3,88 +3,79 @@ - Scratch VM Playground - - + Scratch VM Benchmark + -
-

Scratch VM Playground

- -
- - -
-
- Turbo: -
-
- Compatibility (30 TPS): -
-
-
-
- Renderer
-
- x: - y:
- size:
- dir: - rotation style:
- visible: - -
-
- Thread explorer -

-        
-
- Block explorer -

-        
-
- Import/Export
- Project ID: - -
-

- -   - -

- -

-
+

Scratch VM Benchmark

+

+ Welcome to the scratch-vm benchmark. This tool helps you profile a scratch + project. When you load the page, it: +

    +
  1. loads the default project and enables turbo mode +
  2. runs the project for 4 seconds to warm up +
  3. profiles for 6 seconds +
  4. stops and reports +
+

+ + +

+ Try a different project, like `130041250` +

+ +
+ +
+ + 0 / 0 +
+
+
+ + ...
+
+ + ... +
+
+ + ... +
+
-
+
+ + + + + + + +
FrameSelf TimeTotal TimeExecutions
- - - - - - - - - +
+ + + + + + + + + diff --git a/src/playground/playground.css b/src/playground/playground.css deleted file mode 100644 index 3eccd2625..000000000 --- a/src/playground/playground.css +++ /dev/null @@ -1,73 +0,0 @@ -body { - background: rgb(36,36,36); -} -a { - color: rgb(217,217,217); -} -h2 { - font-size: 1em; -} -#blocks { - position: absolute; - left: 40%; - right: 0; - top: 0; - bottom: 0; - font-family: "Helvetica Neue", Helvetica, sans-serif; -} -#vm-devtools { - color: rgb(217,217,217); - position: absolute; - left: 1%; - right: 60%; - top: 1%; - bottom: 0; - width: 35%; -} -#blockexplorer, #threadexplorer, #importexport { - position: absolute; - height: 75%; - overflow: scroll; - border: 1px solid #fff; - background: rgb(36,36,36); - color: rgb(217,217,217); - font-family: monospace; - font-size: 10pt; - width: 480px; - height: 360px; -} -#tab-blockexplorer, #tab-threadexplorer, #tab-importexport { - display: none; -} -#importExport { - width: 480px; - height: 360px; - background: rgb(36,36,36); - color: rgb(217,217,217); -} -#projectId { - background: rgb(36,36,36); - color: rgb(217,217,217); - font-family: monospace; - font-size: 10pt; -} -ul#playgroundLinks { - display: block; - list-style-type: none; - margin: 0; - padding: 0; - overflow: hidden; - background-color: #333; -} -#playgroundLinks li { - float: left; -} -#playgroundLinks li a { - display: block; - color: white; - text-align: center; - padding: 5px 10px; -} -#playgroundLinks li a:hover { - background-color: #111; -} diff --git a/src/playground/playground.js b/src/playground/playground.js deleted file mode 100644 index 995502d7a..000000000 --- a/src/playground/playground.js +++ /dev/null @@ -1,402 +0,0 @@ -const Scratch = window.Scratch = window.Scratch || {}; - -const ASSET_SERVER = 'https://cdn.assets.scratch.mit.edu/'; -const PROJECT_SERVER = 'https://cdn.projects.scratch.mit.edu/'; - -const loadProject = function () { - let id = location.hash.substring(1); - if (id.length < 1 || !isFinite(id)) { - id = '119615668'; - } - Scratch.vm.downloadProjectId(id); -}; - -/** - * @param {Asset} asset - calculate a URL for this asset. - * @returns {string} a URL to download a project file. - */ -const getProjectUrl = function (asset) { - const assetIdParts = asset.assetId.split('.'); - const assetUrlParts = [PROJECT_SERVER, 'internalapi/project/', assetIdParts[0], '/get/']; - if (assetIdParts[1]) { - assetUrlParts.push(assetIdParts[1]); - } - return assetUrlParts.join(''); -}; - -/** - * @param {Asset} asset - calculate a URL for this asset. - * @returns {string} a URL to download a project asset (PNG, WAV, etc.) - */ -const getAssetUrl = function (asset) { - const assetUrlParts = [ - ASSET_SERVER, - 'internalapi/asset/', - asset.assetId, - '.', - asset.dataFormat, - '/get/' - ]; - return assetUrlParts.join(''); -}; - -const addProfilerPanels = function ( - stats, vm, panelName = 'BLK%', panelFg = '#fff', panelBg = '#111') { - - vm.runtime.enableProfiling(); - if (vm.runtime.profiler === null) { - // Profiler isn't available on the local system. - return; - } - - const blockPercentPanel = stats.addPanel(new window.Stats.Panel(panelName, panelFg, panelBg)); - - // Store the profiler reference for later. - const profiler = vm.runtime.profiler; - // Set profiler to null to disable profiling until later. - vm.runtime.profiler = null; - - const stepThreadsProfilerId = profiler.idByName('Sequencer.stepThreads'); - const blockFunctionProfilerId = profiler.idByName('blockFunction'); - - let blockFunctionTime = 0; - const stepValues = []; - let lastUpdate = Date.now(); - - // Collect time used by `blockFunction` calls in `execute` and add a column - // to the stats graph of the average for the last second of recordings. - profiler.onFrame = function ({id, totalTime}) { - if (id === stepThreadsProfilerId && totalTime > 0) { - // This frame wraps Sequencer.stepThreads. - - // Push the most recently summed blockFunctionTime. - stepValues.push(blockFunctionTime / totalTime * 100); - // Every second, average the pushed values and render that as a new - // column in the stats graph. - if (Date.now() - lastUpdate > 1000) { - lastUpdate = Date.now(); - const average = stepValues.reduce( - (a, b) => a + b, - 0) / stepValues.length; - blockPercentPanel.update(average, 100); - stepValues.length = 0; - } - blockFunctionTime = 0; - } else if (id === blockFunctionProfilerId) { - // This frame wraps around each blockFunction call. - blockFunctionTime += totalTime; - } - }; - - // Set the stats panel to not display by default. - blockPercentPanel.dom.style.display = 'none'; - - // When the parent of the stats graphs is clicked, check if the - // blockPercentPanel is visible. If it is visible, enable profiling by - // setting the runtime's profiler to the stored Profiler instance. If it is - // not visible, disable profiling by setting the profiler to null. - stats.dom.addEventListener('click', () => { - if (blockPercentPanel.dom.style.display === 'block') { - vm.runtime.profiler = profiler; - } else { - vm.runtime.profiler = null; - } - }); - - return blockPercentPanel; -}; - -window.onload = function () { - // Lots of global variables to make debugging easier - // Instantiate the VM. - const vm = new window.VirtualMachine(); - Scratch.vm = vm; - - const storage = new ScratchStorage(); /* global ScratchStorage */ - const AssetType = storage.AssetType; - storage.addWebSource([AssetType.Project], getProjectUrl); - storage.addWebSource([AssetType.ImageVector, AssetType.ImageBitmap, AssetType.Sound], getAssetUrl); - vm.attachStorage(storage); - - // Loading projects from the server. - document.getElementById('projectLoadButton').onclick = function () { - document.location = `#${document.getElementById('projectId').value}`; - location.reload(); - }; - loadProject(); - - // Instantiate the renderer and connect it to the VM. - const canvas = document.getElementById('scratch-stage'); - const renderer = new window.RenderWebGL(canvas); - Scratch.renderer = renderer; - vm.attachRenderer(renderer); - const audioEngine = new window.AudioEngine(); - vm.attachAudioEngine(audioEngine); - - // Instantiate scratch-blocks and attach it to the DOM. - const workspace = window.Blockly.inject('blocks', { - media: './media/', - zoom: { - controls: true, - wheel: true, - startScale: 0.75 - }, - colours: { - workspace: '#334771', - flyout: '#283856', - scrollbar: '#24324D', - scrollbarHover: '#0C111A', - insertionMarker: '#FFFFFF', - insertionMarkerOpacity: 0.3, - fieldShadow: 'rgba(255, 255, 255, 0.3)', - dragShadowOpacity: 0.6 - } - }); - Scratch.workspace = workspace; - - // Attach scratch-blocks events to VM. - workspace.addChangeListener(vm.blockListener); - workspace.addChangeListener(vm.variableListener); - const flyoutWorkspace = workspace.getFlyout().getWorkspace(); - flyoutWorkspace.addChangeListener(vm.flyoutBlockListener); - flyoutWorkspace.addChangeListener(vm.monitorBlockListener); - - // Create FPS counter. - const stats = new window.Stats(); - document.getElementById('tab-renderexplorer').appendChild(stats.dom); - stats.dom.style.position = 'relative'; - addProfilerPanels(stats, vm, 'BLK%', '#fff', '#111'); - stats.begin(); - - // Playground data tabs. - // Block representation tab. - const blockexplorer = document.getElementById('blockexplorer'); - const updateBlockExplorer = function (blocks) { - blockexplorer.innerHTML = JSON.stringify(blocks, null, 2); - window.hljs.highlightBlock(blockexplorer); - }; - - // Thread representation tab. - const threadexplorer = document.getElementById('threadexplorer'); - let cachedThreadJSON = ''; - const updateThreadExplorer = function (newJSON) { - if (newJSON !== cachedThreadJSON) { - cachedThreadJSON = newJSON; - threadexplorer.innerHTML = cachedThreadJSON; - window.hljs.highlightBlock(threadexplorer); - } - }; - - // Only request data from the VM thread if the appropriate tab is open. - Scratch.exploreTabOpen = false; - const getPlaygroundData = function () { - vm.getPlaygroundData(); - if (Scratch.exploreTabOpen) { - window.requestAnimationFrame(getPlaygroundData); - } - }; - - // VM handlers. - // Receipt of new playground data (thread, block representations). - vm.on('playgroundData', data => { - updateThreadExplorer(data.threads); - updateBlockExplorer(data.blocks); - }); - - // Receipt of new block XML for the selected target. - vm.on('workspaceUpdate', data => { - workspace.clear(); - const dom = window.Blockly.Xml.textToDom(data.xml); - window.Blockly.Xml.domToWorkspace(dom, workspace); - }); - - // Receipt of new list of targets, selected target update. - const selectedTarget = document.getElementById('selectedTarget'); - vm.on('targetsUpdate', data => { - // Clear select box. - while (selectedTarget.firstChild) { - selectedTarget.removeChild(selectedTarget.firstChild); - } - // Generate new select box. - for (let i = 0; i < data.targetList.length; i++) { - const targetOption = document.createElement('option'); - targetOption.setAttribute('value', data.targetList[i].id); - // If target id matches editingTarget id, select it. - if (data.targetList[i].id === data.editingTarget) { - targetOption.setAttribute('selected', 'selected'); - } - targetOption.appendChild( - document.createTextNode(data.targetList[i].name) - ); - selectedTarget.appendChild(targetOption); - } - }); - selectedTarget.onchange = function () { - vm.setEditingTarget(this.value); - }; - - // Feedback for stacks and blocks running. - vm.on('SCRIPT_GLOW_ON', data => { - workspace.glowStack(data.id, true); - }); - vm.on('SCRIPT_GLOW_OFF', data => { - workspace.glowStack(data.id, false); - }); - vm.on('BLOCK_GLOW_ON', data => { - workspace.glowBlock(data.id, true); - }); - vm.on('BLOCK_GLOW_OFF', data => { - workspace.glowBlock(data.id, false); - }); - vm.on('VISUAL_REPORT', data => { - workspace.reportValue(data.id, data.value); - }); - - vm.on('SPRITE_INFO_REPORT', data => { - if (data.id !== selectedTarget.value) return; // Not the editingTarget - document.getElementById('sinfo-x').value = data.x; - document.getElementById('sinfo-y').value = data.y; - document.getElementById('sinfo-size').value = data.size; - document.getElementById('sinfo-direction').value = data.direction; - document.getElementById('sinfo-rotationstyle').value = data.rotationStyle; - document.getElementById('sinfo-visible').value = data.visible; - }); - - document.getElementById('sinfo-post').addEventListener('click', () => { - const data = {}; - data.x = document.getElementById('sinfo-x').value; - data.y = document.getElementById('sinfo-y').value; - data.direction = document.getElementById('sinfo-direction').value; - data.rotationStyle = document.getElementById('sinfo-rotationstyle').value; - data.visible = document.getElementById('sinfo-visible').value === 'true'; - vm.postSpriteInfo(data); - }); - - // Feed mouse events as VM I/O events. - document.addEventListener('mousemove', e => { - const rect = canvas.getBoundingClientRect(); - const coordinates = { - x: e.clientX - rect.left, - y: e.clientY - rect.top, - canvasWidth: rect.width, - canvasHeight: rect.height - }; - Scratch.vm.postIOData('mouse', coordinates); - }); - canvas.addEventListener('mousedown', e => { - const rect = canvas.getBoundingClientRect(); - const data = { - isDown: true, - x: e.clientX - rect.left, - y: e.clientY - rect.top, - canvasWidth: rect.width, - canvasHeight: rect.height - }; - Scratch.vm.postIOData('mouse', data); - e.preventDefault(); - }); - canvas.addEventListener('mouseup', e => { - const rect = canvas.getBoundingClientRect(); - const data = { - isDown: false, - x: e.clientX - rect.left, - y: e.clientY - rect.top, - canvasWidth: rect.width, - canvasHeight: rect.height - }; - Scratch.vm.postIOData('mouse', data); - e.preventDefault(); - }); - - // Feed keyboard events as VM I/O events. - document.addEventListener('keydown', e => { - // Don't capture keys intended for Blockly inputs. - if (e.target !== document && e.target !== document.body) { - return; - } - Scratch.vm.postIOData('keyboard', { - keyCode: e.keyCode, - isDown: true - }); - e.preventDefault(); - }); - document.addEventListener('keyup', e => { - // Always capture up events, - // even those that have switched to other targets. - Scratch.vm.postIOData('keyboard', { - keyCode: e.keyCode, - isDown: false - }); - // E.g., prevent scroll. - if (e.target !== document && e.target !== document.body) { - e.preventDefault(); - } - }); - - // Run threads - vm.start(); - - // Inform VM of animation frames. - const animate = function () { - stats.update(); - requestAnimationFrame(animate); - }; - requestAnimationFrame(animate); - - // Handlers for green flag and stop all. - document.getElementById('greenflag').addEventListener('click', () => { - vm.greenFlag(); - }); - document.getElementById('stopall').addEventListener('click', () => { - vm.stopAll(); - }); - document.getElementById('turbomode').addEventListener('change', () => { - const turboOn = document.getElementById('turbomode').checked; - vm.setTurboMode(turboOn); - }); - document.getElementById('compatmode').addEventListener('change', - () => { - const compatibilityMode = document.getElementById('compatmode').checked; - vm.setCompatibilityMode(compatibilityMode); - }); - const tabBlockExplorer = document.getElementById('tab-blockexplorer'); - const tabThreadExplorer = document.getElementById('tab-threadexplorer'); - const tabRenderExplorer = document.getElementById('tab-renderexplorer'); - const tabImportExport = document.getElementById('tab-importexport'); - - // Handlers to show different explorers. - document.getElementById('threadexplorer-link').addEventListener('click', - () => { - Scratch.exploreTabOpen = true; - getPlaygroundData(); - tabBlockExplorer.style.display = 'none'; - tabRenderExplorer.style.display = 'none'; - tabThreadExplorer.style.display = 'block'; - tabImportExport.style.display = 'none'; - }); - document.getElementById('blockexplorer-link').addEventListener('click', - () => { - Scratch.exploreTabOpen = true; - getPlaygroundData(); - tabBlockExplorer.style.display = 'block'; - tabRenderExplorer.style.display = 'none'; - tabThreadExplorer.style.display = 'none'; - tabImportExport.style.display = 'none'; - }); - document.getElementById('renderexplorer-link').addEventListener('click', - () => { - Scratch.exploreTabOpen = false; - tabBlockExplorer.style.display = 'none'; - tabRenderExplorer.style.display = 'block'; - tabThreadExplorer.style.display = 'none'; - tabImportExport.style.display = 'none'; - }); - document.getElementById('importexport-link').addEventListener('click', - () => { - Scratch.exploreTabOpen = false; - tabBlockExplorer.style.display = 'none'; - tabRenderExplorer.style.display = 'none'; - tabThreadExplorer.style.display = 'none'; - tabImportExport.style.display = 'block'; - }); -}; diff --git a/webpack.config.js b/webpack.config.js index 77ae2068e..0095d0dce 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -84,75 +84,14 @@ module.exports = [ 'scratch-blocks/dist/vertical.js', // Audio 'scratch-audio', + // Storage + 'scratch-storage', // Renderer 'scratch-render' ] }, output: { - libraryTarget: 'umd', - path: path.resolve('playground') - }, - module: { - rules: base.module.rules.concat([ - { - test: require.resolve('./src/index.js'), - loader: 'expose-loader?VirtualMachine' - }, - { - test: require.resolve('stats.js/build/stats.min.js'), - loader: 'script-loader' - }, - { - test: require.resolve('highlightjs/highlight.pack.min.js'), - loader: 'script-loader' - }, - { - test: require.resolve('scratch-blocks/dist/vertical.js'), - loader: 'expose-loader?Blockly' - }, - { - test: require.resolve('scratch-audio'), - loader: 'expose-loader?AudioEngine' - }, - { - test: require.resolve('scratch-render'), - loader: 'expose-loader?RenderWebGL' - } - ]) - }, - plugins: base.plugins.concat([ - new CopyWebpackPlugin([{ - from: 'node_modules/scratch-blocks/media', - to: 'media' - }, { - from: 'node_modules/highlightjs/styles/zenburn.css' - }, { - from: 'node_modules/scratch-storage/dist/web' - }, { - from: 'src/playground' - }]) - ]) - }), - // Benchmark - defaultsDeep({}, base, { - target: 'web', - entry: { - 'scratch-vm': './src/index.js', - 'vendor': [ - // FPS counter - 'stats.js/build/stats.min.js', - // Syntax highlighter - 'highlightjs/highlight.pack.min.js', - // Scratch Blocks - 'scratch-blocks/dist/vertical.js', - // Audio - 'scratch-audio', - // Renderer - 'scratch-render' - ] - }, - output: { - path: path.resolve(__dirname, 'benchmark'), + path: path.resolve(__dirname, 'playground'), filename: '[name].js' }, module: { @@ -177,6 +116,10 @@ module.exports = [ test: require.resolve('scratch-audio'), loader: 'expose-loader?AudioEngine' }, + { + test: require.resolve('scratch-storage'), + loader: 'expose-loader?ScratchStorage' + }, { test: require.resolve('scratch-render'), loader: 'expose-loader?RenderWebGL' @@ -192,7 +135,7 @@ module.exports = [ }, { from: 'node_modules/scratch-storage/dist/web' }, { - from: 'src/benchmark' + from: 'src/playground' }]) ]) }) From a586c5d9cdae593a2ed635265f4c3453d61f8aec Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 13 Dec 2017 15:37:44 -0500 Subject: [PATCH 216/272] Revert "Fix test" This reverts commit 6b00f97804d00db2fa9b1fdb98e7577101252cf9. --- test/unit/blocks_procedures.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/blocks_procedures.js b/test/unit/blocks_procedures.js index 5dfecea72..0285b23d0 100644 --- a/test/unit/blocks_procedures.js +++ b/test/unit/blocks_procedures.js @@ -16,7 +16,7 @@ test('calling a custom block with no definition does not throw', t => { } }; const util = { - getProcedureParamNamesAndIds: () => [null, null], + getProcedureParamNamesAndIds: () => null, stackFrame: { executed: false } From 0fe7eca0185dd8907c49f0657a2f0f613ede106b Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 13 Dec 2017 15:37:58 -0500 Subject: [PATCH 217/272] Fix procedure name lookup to work with undefined procedures. --- src/blocks/scratch3_procedures.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/blocks/scratch3_procedures.js b/src/blocks/scratch3_procedures.js index 3ba743d8b..7fb31d28f 100644 --- a/src/blocks/scratch3_procedures.js +++ b/src/blocks/scratch3_procedures.js @@ -27,15 +27,17 @@ class Scratch3ProcedureBlocks { call (args, util) { if (!util.stackFrame.executed) { const procedureCode = args.mutation.proccode; - const [paramNames, paramIds] = util.getProcedureParamNamesAndIds(procedureCode); + const paramNamesAndIds = util.getProcedureParamNamesAndIds(procedureCode); // If null, procedure could not be found, which can happen if custom // block is dragged between sprites without the definition. // Match Scratch 2.0 behavior and noop. - if (paramNames === null) { + if (paramNamesAndIds === null) { return; } + const [paramNames, paramIds] = paramNamesAndIds; + for (let i = 0; i < paramIds.length; i++) { if (args.hasOwnProperty(paramIds[i])) { util.pushParam(paramNames[i], args[paramIds[i]]); From 256d7b3d6c7d3cc044bc826d1a2a882a2e9c9f18 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 13 Dec 2017 15:53:55 -0500 Subject: [PATCH 218/272] Parse the `warp` property from the mutation instead of using directly. --- src/engine/sequencer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/sequencer.js b/src/engine/sequencer.js index 0c796a6ea..faa40b9e8 100644 --- a/src/engine/sequencer.js +++ b/src/engine/sequencer.js @@ -316,7 +316,7 @@ class Sequencer { const definitionBlock = thread.target.blocks.getBlock(definition); const innerBlock = thread.target.blocks.getBlock( definitionBlock.inputs.custom_block.block); - const doWarp = innerBlock.mutation.warp; + const doWarp = JSON.parse(innerBlock.mutation.warp); if (doWarp) { thread.peekStackFrame().warpMode = true; } else if (isRecursive) { From 0f82e2a84dfef85329655e62861057795440ddca Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 14 Dec 2017 14:21:57 -0500 Subject: [PATCH 219/272] Be more cautious about parsing json. --- src/engine/sequencer.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/engine/sequencer.js b/src/engine/sequencer.js index faa40b9e8..2db1c6ed8 100644 --- a/src/engine/sequencer.js +++ b/src/engine/sequencer.js @@ -316,7 +316,15 @@ class Sequencer { const definitionBlock = thread.target.blocks.getBlock(definition); const innerBlock = thread.target.blocks.getBlock( definitionBlock.inputs.custom_block.block); - const doWarp = JSON.parse(innerBlock.mutation.warp); + let doWarp = false; + if (innerBlock && innerBlock.mutation) { + const warp = innerBlock.mutation.warp; + if (typeof warp === 'boolean') { + doWarp = warp; + } else if (typeof warp === 'string') { + doWarp = JSON.parse(warp); + } + } if (doWarp) { thread.peekStackFrame().warpMode = true; } else if (isRecursive) { From 5e6187bee79441185eb3b0595673bad058b1c983 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Thu, 14 Dec 2017 14:37:08 -0500 Subject: [PATCH 220/272] Add blockly extension for scratch extensions --- src/engine/runtime.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 9c7f3e9e4..2215a02ab 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -603,7 +603,8 @@ class Runtime extends EventEmitter { colour: categoryInfo.color1, colourSecondary: categoryInfo.color2, colourTertiary: categoryInfo.color3, - args0: [] + args0: [], + extensions: ['scratch_extension'] }; const inputList = []; From cbebc28307caaa9044ea460b3aa6613b9e799d90 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 14 Dec 2017 16:46:31 -0500 Subject: [PATCH 221/272] Return a promise to indicate when a costume has loaded. Parallels the way the `addSound` method works. Needed to enable selecting new assets automatically from GUI. --- src/virtual-machine.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 1c8df4df9..92a8d9794 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -314,9 +314,10 @@ class VirtualMachine extends EventEmitter { * @property {number} rotationCenterX - the X component of the costume's origin. * @property {number} rotationCenterY - the Y component of the costume's origin. * @property {number} [bitmapResolution] - the resolution scale for a bitmap costume. + * @returns {?Promise} - a promise that resolves when the costume has been added */ addCostume (md5ext, costumeObject) { - loadCostume(md5ext, costumeObject, this.runtime).then(() => { + return loadCostume(md5ext, costumeObject, this.runtime).then(() => { this.editingTarget.addCostume(costumeObject); this.editingTarget.setCostume( this.editingTarget.sprite.costumes.length - 1 From 5cb0f5d76d3e2e728cfb833091b775a249e19e06 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Fri, 15 Dec 2017 14:09:29 -0500 Subject: [PATCH 222/272] Add separator to extension block definition --- src/engine/runtime.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 2215a02ab..73d1e10a4 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -617,16 +617,20 @@ class Runtime extends EventEmitter { blockJSON.message0 = ''; - // If an icon for the extension exists, prepend it to each block + // If an icon for the extension exists, prepend it to each block, with a vertical separator. if (categoryInfo.iconURI) { - blockJSON.message0 = '%1'; + blockJSON.message0 = '%1 %2'; const iconJSON = { type: 'field_image', src: categoryInfo.iconURI, width: 40, height: 40 }; + const separatorJSON = { + type: 'field_vertical_separator' + }; blockJSON.args0.push(iconJSON); + blockJSON.args0.push(separatorJSON); } blockJSON.message0 += blockInfo.text.replace(/\[(.+?)]/g, (match, placeholder) => { From 437cee3c14577b0f5afc22bf3b3621e283ae5dbb Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 15 Dec 2017 15:52:04 -0500 Subject: [PATCH 223/272] Cast to string before asking question. Same as say blocks do. --- src/blocks/scratch3_sensing.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blocks/scratch3_sensing.js b/src/blocks/scratch3_sensing.js index b23fe740e..75ee571c7 100644 --- a/src/blocks/scratch3_sensing.js +++ b/src/blocks/scratch3_sensing.js @@ -105,7 +105,7 @@ class Scratch3SensingBlocks { const _target = util.target; return new Promise(resolve => { const isQuestionAsked = this._questionList.length > 0; - this._enqueueAsk(args.QUESTION, resolve, _target, _target.visible, _target.isStage); + this._enqueueAsk(String(args.QUESTION), resolve, _target, _target.visible, _target.isStage); if (!isQuestionAsked) { this._askNextQuestion(); } From 39115169cadffcd08ee40b396af6375507901659 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Tue, 19 Dec 2017 11:11:38 -0500 Subject: [PATCH 224/272] Return promise from backdrop loading --- src/virtual-machine.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 92a8d9794..0881af2cf 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -444,9 +444,10 @@ class VirtualMachine extends EventEmitter { * @property {number} rotationCenterX - the X component of the backdrop's origin. * @property {number} rotationCenterY - the Y component of the backdrop's origin. * @property {number} [bitmapResolution] - the resolution scale for a bitmap backdrop. + * @returns {?Promise} - a promise that resolves when the backdrop has been added */ addBackdrop (md5ext, backdropObject) { - loadCostume(md5ext, backdropObject, this.runtime).then(() => { + return loadCostume(md5ext, backdropObject, this.runtime).then(() => { const stage = this.runtime.getTargetForStage(); stage.sprite.costumes.push(backdropObject); stage.setCostume(stage.sprite.costumes.length - 1); From 9613046b2febef2612e07d8c9e4080e2bc46895b Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 19 Dec 2017 14:47:11 -0500 Subject: [PATCH 225/272] Add optional menuIcon for extension blocks --- src/engine/runtime.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 2215a02ab..c425fa334 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -475,7 +475,8 @@ class Runtime extends EventEmitter { const categoryInfo = { id: extensionInfo.id, name: extensionInfo.name, - iconURI: extensionInfo.iconURI, + blockIconURI: extensionInfo.blockIconURI, + menuIconURI: extensionInfo.menuIconURI, color1: '#FF6680', color2: '#FF4D6A', color3: '#FF3355', @@ -618,11 +619,11 @@ class Runtime extends EventEmitter { blockJSON.message0 = ''; // If an icon for the extension exists, prepend it to each block - if (categoryInfo.iconURI) { + if (categoryInfo.blockIconURI) { blockJSON.message0 = '%1'; const iconJSON = { type: 'field_image', - src: categoryInfo.iconURI, + src: categoryInfo.blockIconURI, width: 40, height: 40 }; @@ -735,7 +736,20 @@ class Runtime extends EventEmitter { for (const categoryInfo of this._blockInfo) { const {name, color1, color2} = categoryInfo; const paletteBlocks = categoryInfo.blocks.filter(block => !block.info.hideFromPalette); - xmlParts.push(``); + const colorXML = `colour="${color1}" secondaryColour="${color2}"`; + + // Use a menu icon if there is one. Otherwise, use the block icon. If there's no icon, + // the category menu will show its default colored circle. + let menuIconURI = ''; + if (categoryInfo.menuIconURI) { + menuIconURI = categoryInfo.menuIconURI; + } else if (categoryInfo.blockIconURI) { + menuIconURI = categoryInfo.blockIconURI; + } + const menuIconXML = menuIconURI ? + `iconURI="${menuIconURI}"` : ''; + + xmlParts.push(``); xmlParts.push.apply(xmlParts, paletteBlocks.map(block => block.xml)); xmlParts.push(''); } From dad620f01574b70e34c29ef1464bdba747ca0fbd Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 19 Dec 2017 14:47:37 -0500 Subject: [PATCH 226/272] Update block and menu icons for pen and music extensions --- src/extensions/scratch3_music/index.js | 12 ++++++++++-- src/extensions/scratch3_pen/index.js | 4 ++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index 6d661bd24..0e14a2150 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -10,7 +10,14 @@ const Timer = require('../../util/timer'); * @type {string} */ // eslint-disable-next-line max-len -const iconURI = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+PHRpdGxlPm11c2ljLWJsb2NrLWljb248L3RpdGxlPjxkZWZzPjxwYXRoIGQ9Ik0zMi4xOCAyNS44NzRDMzIuNjM2IDI4LjE1NyAzMC41MTIgMzAgMjcuNDMzIDMwYy0zLjA3IDAtNS45MjMtMS44NDMtNi4zNzItNC4xMjYtLjQ1OC0yLjI4NSAxLjY2NS00LjEzNiA0Ljc0My00LjEzNi42NDcgMCAxLjI4My4wODQgMS44OS4yMzQuMzM4LjA4Ni42MzcuMTguOTM4LjMwMi44Ny0uMDItLjEwNC0yLjI5NC0xLjgzNS0xMi4yMy0yLjEzNC0xMi4zMDIgMy4wNi0xLjg3IDguNzY4LTIuNzUyIDUuNzA4LS44ODUuMDc2IDQuODItMy42NSAzLjg0NC0zLjcyNC0uOTg3LTQuNjUtNy4xNTMuMjYzIDE0LjczOHptLTE2Ljk5OCA1Ljk5QzE1LjYzIDM0LjE0OCAxMy41MDcgMzYgMTAuNDQgMzZjLTMuMDcgMC01LjkyMi0xLjg1Mi02LjM4LTQuMTM2LS40NDgtMi4yODQgMS42NzQtNC4xMzUgNC43NS00LjEzNSAxLjAwMyAwIDEuOTc1LjE5NiAyLjg1NS41NDMuODIyLS4wNTUtLjE1LTIuMzc3LTEuODYyLTEyLjIyOC0yLjEzMy0xMi4zMDMgMy4wNi0xLjg3IDguNzY0LTIuNzUzIDUuNzA2LS44OTQuMDc2IDQuODItMy42NDggMy44MzQtMy43MjQtLjk4Ny00LjY1LTcuMTUyLjI2MiAxNC43Mzh6IiBpZD0iYSIvPjwvZGVmcz48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjx1c2UgZmlsbD0iI0ZGRiIgeGxpbms6aHJlZj0iI2EiLz48cGF0aCBzdHJva2Utb3BhY2l0eT0iLjEiIHN0cm9rZT0iIzAwMCIgZD0iTTI4LjQ1NiAyMS42NzVjLS4wMS0uMzEyLS4wODctLjgyNS0uMjU2LTEuNzAyLS4wOTYtLjQ5NS0uNjEyLTMuMDIyLS43NTMtMy43My0uMzk1LTEuOTgtLjc2LTMuOTItMS4xNDItNi4xMTMtLjczMi00LjIyMy0uNjkzLTYuMDUuMzQ0LTYuNTI3LjUtLjIzIDEuMDYtLjA4IDEuODQuMzUuNDE0LjIyNyAyLjE4MiAxLjM2NSAyLjA3IDEuMjk2IDEuOTk0IDEuMjQyIDMuNDY0IDEuNzc0IDQuOTMgMS41NDggMS41MjYtLjIzNyAyLjUwNC0uMDYgMi44NzYuNjE4LjM0OC42MzUuMDE1IDEuNDE2LS43MyAyLjE4LTEuNDcyIDEuNTE2LTMuOTc1IDIuNTE0LTUuODQ4IDIuMDIzLS44MjItLjIyLTEuMjM4LS40NjUtMi4zOC0xLjI2N2wtLjA5NS0uMDY2Yy4wNDcuNTkzLjI2NCAxLjc0LjcxNyAzLjgwMy4yOTQgMS4zMzYgMi4wOCA5LjE4NyAyLjYzNyAxMS42NzRsLjAwMi4wMTJjLjUyOCAyLjYzNy0xLjg3MyA0LjcyNC01LjIzNiA0LjcyNC0zLjI5IDAtNi4zNjMtMS45ODgtNi44NjItNC41MjgtLjUzLTIuNjQgMS44NzMtNC43MzQgNS4yMzMtNC43MzQuNjcyIDAgMS4zNDcuMDg1IDIuMDE0LjI1LjIyNy4wNTcuNDM2LjExOC42MzYuMTg3em0tMTYuOTk2IDUuOTljLS4wMS0uMzE4LS4wOS0uODM4LS4yNjYtMS43MzctLjA5LS40Ni0uNTk1LTIuOTM3LS43NTMtMy43MjctLjM5LTEuOTYtLjc1LTMuODktMS4xMy02LjA3LS43MzItNC4yMjMtLjY5Mi02LjA1LjM0NC02LjUyNi41MDItLjIzIDEuMDYtLjA4MiAxLjg0LjM1LjQxNS4yMjcgMi4xODIgMS4zNjQgMi4wNyAxLjI5NSAxLjk5MyAxLjI0MiAzLjQ2MiAxLjc3NCA0LjkyNiAxLjU0OCAxLjUyNS0uMjQgMi41MDQtLjA2NCAyLjg3Ni42MTQuMzQ4LjYzNS4wMTUgMS40MTUtLjcyOCAyLjE4LTEuNDc0IDEuNTE3LTMuOTc3IDIuNTEzLTUuODQ3IDIuMDE3LS44Mi0uMjItMS4yMzYtLjQ2NC0yLjM3OC0xLjI2N2wtLjA5NS0uMDY1Yy4wNDcuNTkzLjI2NCAxLjc0LjcxNyAzLjgwMi4yOTQgMS4zMzcgMi4wNzggOS4xOSAyLjYzNiAxMS42NzVsLjAwMy4wMTNjLjUxNyAyLjYzOC0xLjg4NCA0LjczMi01LjIzNCA0LjczMi0zLjI4NyAwLTYuMzYtMS45OTMtNi44Ny00LjU0LS41Mi0yLjY0IDEuODg0LTQuNzMgNS4yNC00LjczLjkwNSAwIDEuODAzLjE1IDIuNjUuNDM2eiIvPjwvZz48L3N2Zz4='; +const blockIconURI = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+PHRpdGxlPm11c2ljLWJsb2NrLWljb248L3RpdGxlPjxkZWZzPjxwYXRoIGQ9Ik0zMi4xOCAyNS44NzRDMzIuNjM2IDI4LjE1NyAzMC41MTIgMzAgMjcuNDMzIDMwYy0zLjA3IDAtNS45MjMtMS44NDMtNi4zNzItNC4xMjYtLjQ1OC0yLjI4NSAxLjY2NS00LjEzNiA0Ljc0My00LjEzNi42NDcgMCAxLjI4My4wODQgMS44OS4yMzQuMzM4LjA4Ni42MzcuMTguOTM4LjMwMi44Ny0uMDItLjEwNC0yLjI5NC0xLjgzNS0xMi4yMy0yLjEzNC0xMi4zMDIgMy4wNi0xLjg3IDguNzY4LTIuNzUyIDUuNzA4LS44ODUuMDc2IDQuODItMy42NSAzLjg0NC0zLjcyNC0uOTg3LTQuNjUtNy4xNTMuMjYzIDE0LjczOHptLTE2Ljk5OCA1Ljk5QzE1LjYzIDM0LjE0OCAxMy41MDcgMzYgMTAuNDQgMzZjLTMuMDcgMC01LjkyMi0xLjg1Mi02LjM4LTQuMTM2LS40NDgtMi4yODQgMS42NzQtNC4xMzUgNC43NS00LjEzNSAxLjAwMyAwIDEuOTc1LjE5NiAyLjg1NS41NDMuODIyLS4wNTUtLjE1LTIuMzc3LTEuODYyLTEyLjIyOC0yLjEzMy0xMi4zMDMgMy4wNi0xLjg3IDguNzY0LTIuNzUzIDUuNzA2LS44OTQuMDc2IDQuODItMy42NDggMy44MzQtMy43MjQtLjk4Ny00LjY1LTcuMTUyLjI2MiAxNC43Mzh6IiBpZD0iYSIvPjwvZGVmcz48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjx1c2UgZmlsbD0iI0ZGRiIgeGxpbms6aHJlZj0iI2EiLz48cGF0aCBzdHJva2Utb3BhY2l0eT0iLjEiIHN0cm9rZT0iIzAwMCIgZD0iTTI4LjQ1NiAyMS42NzVjLS4wMS0uMzEyLS4wODctLjgyNS0uMjU2LTEuNzAyLS4wOTYtLjQ5NS0uNjEyLTMuMDIyLS43NTMtMy43My0uMzk1LTEuOTgtLjc2LTMuOTItMS4xNDItNi4xMTMtLjczMi00LjIyMy0uNjkzLTYuMDUuMzQ0LTYuNTI3LjUtLjIzIDEuMDYtLjA4IDEuODQuMzUuNDE0LjIyNyAyLjE4MiAxLjM2NSAyLjA3IDEuMjk2IDEuOTk0IDEuMjQyIDMuNDY0IDEuNzc0IDQuOTMgMS41NDggMS41MjYtLjIzNyAyLjUwNC0uMDYgMi44NzYuNjE4LjM0OC42MzUuMDE1IDEuNDE2LS43MyAyLjE4LTEuNDcyIDEuNTE2LTMuOTc1IDIuNTE0LTUuODQ4IDIuMDIzLS44MjItLjIyLTEuMjM4LS40NjUtMi4zOC0xLjI2N2wtLjA5NS0uMDY2Yy4wNDcuNTkzLjI2NCAxLjc0LjcxNyAzLjgwMy4yOTQgMS4zMzYgMi4wOCA5LjE4NyAyLjYzNyAxMS42NzRsLjAwMi4wMTJjLjUyOCAyLjYzNy0xLjg3MyA0LjcyNC01LjIzNiA0LjcyNC0zLjI5IDAtNi4zNjMtMS45ODgtNi44NjItNC41MjgtLjUzLTIuNjQgMS44NzMtNC43MzQgNS4yMzMtNC43MzQuNjcyIDAgMS4zNDcuMDg1IDIuMDE0LjI1LjIyNy4wNTcuNDM2LjExOC42MzYuMTg3em0tMTYuOTk2IDUuOTljLS4wMS0uMzE4LS4wOS0uODM4LS4yNjYtMS43MzctLjA5LS40Ni0uNTk1LTIuOTM3LS43NTMtMy43MjctLjM5LTEuOTYtLjc1LTMuODktMS4xMy02LjA3LS43MzItNC4yMjMtLjY5Mi02LjA1LjM0NC02LjUyNi41MDItLjIzIDEuMDYtLjA4MiAxLjg0LjM1LjQxNS4yMjcgMi4xODIgMS4zNjQgMi4wNyAxLjI5NSAxLjk5MyAxLjI0MiAzLjQ2MiAxLjc3NCA0LjkyNiAxLjU0OCAxLjUyNS0uMjQgMi41MDQtLjA2NCAyLjg3Ni42MTQuMzQ4LjYzNS4wMTUgMS40MTUtLjcyOCAyLjE4LTEuNDc0IDEuNTE3LTMuOTc3IDIuNTEzLTUuODQ3IDIuMDE3LS44Mi0uMjItMS4yMzYtLjQ2NC0yLjM3OC0xLjI2N2wtLjA5NS0uMDY1Yy4wNDcuNTkzLjI2NCAxLjc0LjcxNyAzLjgwMi4yOTQgMS4zMzcgMi4wNzggOS4xOSAyLjYzNiAxMS42NzVsLjAwMy4wMTNjLjUxNyAyLjYzOC0xLjg4NCA0LjczMi01LjIzNCA0LjczMi0zLjI4NyAwLTYuMzYtMS45OTMtNi44Ny00LjU0LS41Mi0yLjY0IDEuODg0LTQuNzMgNS4yNC00LjczLjkwNSAwIDEuODAzLjE1IDIuNjUuNDM2eiIvPjwvZz48L3N2Zz4='; + +/** + * Icon svg to be displayed in the category menu, encoded as a data URI. + * @type {string} + */ +// eslint-disable-next-line max-len +const menuIconURI = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTE2LjA5IDEyLjkzN2MuMjI4IDEuMTQxLS44MzMgMi4wNjMtMi4zNzMgMi4wNjMtMS41MzUgMC0yLjk2Mi0uOTIyLTMuMTg2LTIuMDYzLS4yMy0xLjE0Mi44MzMtMi4wNjggMi4zNzItMi4wNjguMzIzIDAgLjY0MS4wNDIuOTQ1LjExN2EzLjUgMy41IDAgMCAxIC40NjguMTUxYy40MzUtLjAxLS4wNTItMS4xNDctLjkxNy02LjExNC0xLjA2Ny02LjE1MiAxLjUzLS45MzUgNC4zODQtMS4zNzcgMi44NTQtLjQ0Mi4wMzggMi40MS0xLjgyNSAxLjkyMi0xLjg2Mi0uNDkzLTIuMzI1LTMuNTc3LjEzMiA3LjM3ek03LjQ2IDguNTYzYy0xLjg2Mi0uNDkzLTIuMzI1LTMuNTc2LjEzIDcuMzdDNy44MTYgMTcuMDczIDYuNzU0IDE4IDUuMjIgMThjLTEuNTM1IDAtMi45NjEtLjkyNi0zLjE5LTIuMDY4LS4yMjQtMS4xNDIuODM3LTIuMDY3IDIuMzc1LTIuMDY3LjUwMSAwIC45ODcuMDk4IDEuNDI3LjI3Mi40MTItLjAyOC0uMDc0LTEuMTg5LS45My02LjExNEMzLjgzNCAxLjg3IDYuNDMgNy4wODcgOS4yODIgNi42NDZjMi44NTQtLjQ0Ny4wMzggMi40MS0xLjgyMyAxLjkxN3oiIGZpbGw9IiM1NzVFNzUiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg=='; /** * Class for the music-related blocks in Scratch 3.0 @@ -402,7 +409,8 @@ class Scratch3MusicBlocks { return { id: 'music', name: 'Music', - iconURI: iconURI, + menuIconURI: menuIconURI, + blockIconURI: blockIconURI, blocks: [ { opcode: 'playDrumForBeats', diff --git a/src/extensions/scratch3_pen/index.js b/src/extensions/scratch3_pen/index.js index e194a1d50..b3a8818d3 100644 --- a/src/extensions/scratch3_pen/index.js +++ b/src/extensions/scratch3_pen/index.js @@ -13,7 +13,7 @@ const log = require('../../util/log'); * @type {string} */ // eslint-disable-next-line max-len -const iconURI = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+cGVuLWljb248L3RpdGxlPjxnIHN0cm9rZT0iIzU3NUU3NSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwYXRoIGQ9Ik04Ljc1MyAzNC42MDJsLTQuMjUgMS43OCAxLjc4My00LjIzN2MxLjIxOC0yLjg5MiAyLjkwNy01LjQyMyA1LjAzLTcuNTM4TDMxLjA2NiA0LjkzYy44NDYtLjg0MiAyLjY1LS40MSA0LjAzMi45NjcgMS4zOCAxLjM3NSAxLjgxNiAzLjE3My45NyA0LjAxNUwxNi4zMTggMjkuNTljLTIuMTIzIDIuMTE2LTQuNjY0IDMuOC03LjU2NSA1LjAxMiIgZmlsbD0iI0ZGRiIvPjxwYXRoIGQ9Ik0yOS40MSA2LjExcy00LjQ1LTIuMzc4LTguMjAyIDUuNzcyYy0xLjczNCAzLjc2Ni00LjM1IDEuNTQ2LTQuMzUgMS41NDYiLz48cGF0aCBkPSJNMzYuNDIgOC44MjVjMCAuNDYzLS4xNC44NzMtLjQzMiAxLjE2NGwtOS4zMzUgOS4zYy4yODItLjI5LjQxLS42NjguNDEtMS4xMiAwLS44NzQtLjUwNy0xLjk2My0xLjQwNi0yLjg2OC0xLjM2Mi0xLjM1OC0zLjE0Ny0xLjgtNC4wMDItLjk5TDMwLjk5IDUuMDFjLjg0NC0uODQgMi42NS0uNDEgNC4wMzUuOTYuODk4LjkwNCAxLjM5NiAxLjk4MiAxLjM5NiAyLjg1NU0xMC41MTUgMzMuNzc0Yy0uNTczLjMwMi0xLjE1Ny41Ny0xLjc2NC44M0w0LjUgMzYuMzgybDEuNzg2LTQuMjM1Yy4yNTgtLjYwNC41My0xLjE4Ni44MzMtMS43NTcuNjkuMTgzIDEuNDQ4LjYyNSAyLjEwOCAxLjI4Mi42Ni42NTggMS4xMDIgMS40MTIgMS4yODcgMi4xMDIiIGZpbGw9IiM0Qzk3RkYiLz48cGF0aCBkPSJNMzYuNDk4IDguNzQ4YzAgLjQ2NC0uMTQuODc0LS40MzMgMS4xNjVsLTE5Ljc0MiAxOS42OGMtMi4xMyAyLjExLTQuNjczIDMuNzkzLTcuNTcyIDUuMDFMNC41IDM2LjM4bC45NzQtMi4zMTYgMS45MjUtLjgwOGMyLjg5OC0xLjIxOCA1LjQ0LTIuOSA3LjU3LTUuMDFsMTkuNzQzLTE5LjY4Yy4yOTItLjI5Mi40MzItLjcwMi40MzItMS4xNjUgMC0uNjQ2LS4yNy0xLjQtLjc4LTIuMTIyLjI1LjE3Mi41LjM3Ny43MzcuNjE0Ljg5OC45MDUgMS4zOTYgMS45ODMgMS4zOTYgMi44NTYiIGZpbGw9IiM1NzVFNzUiIG9wYWNpdHk9Ii4xNSIvPjxwYXRoIGQ9Ik0xOC40NSAxMi44M2MwIC41LS40MDQuOTA1LS45MDQuOTA1cy0uOTA1LS40MDUtLjkwNS0uOTA0YzAtLjUuNDA3LS45MDMuOTA2LS45MDMuNSAwIC45MDQuNDA0LjkwNC45MDR6IiBmaWxsPSIjNTc1RTc1Ii8+PC9nPjwvc3ZnPg=='; +const blockIconURI = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+cGVuLWljb248L3RpdGxlPjxnIHN0cm9rZT0iIzU3NUU3NSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwYXRoIGQ9Ik04Ljc1MyAzNC42MDJsLTQuMjUgMS43OCAxLjc4My00LjIzN2MxLjIxOC0yLjg5MiAyLjkwNy01LjQyMyA1LjAzLTcuNTM4TDMxLjA2NiA0LjkzYy44NDYtLjg0MiAyLjY1LS40MSA0LjAzMi45NjcgMS4zOCAxLjM3NSAxLjgxNiAzLjE3My45NyA0LjAxNUwxNi4zMTggMjkuNTljLTIuMTIzIDIuMTE2LTQuNjY0IDMuOC03LjU2NSA1LjAxMiIgZmlsbD0iI0ZGRiIvPjxwYXRoIGQ9Ik0yOS40MSA2LjExcy00LjQ1LTIuMzc4LTguMjAyIDUuNzcyYy0xLjczNCAzLjc2Ni00LjM1IDEuNTQ2LTQuMzUgMS41NDYiLz48cGF0aCBkPSJNMzYuNDIgOC44MjVjMCAuNDYzLS4xNC44NzMtLjQzMiAxLjE2NGwtOS4zMzUgOS4zYy4yODItLjI5LjQxLS42NjguNDEtMS4xMiAwLS44NzQtLjUwNy0xLjk2My0xLjQwNi0yLjg2OC0xLjM2Mi0xLjM1OC0zLjE0Ny0xLjgtNC4wMDItLjk5TDMwLjk5IDUuMDFjLjg0NC0uODQgMi42NS0uNDEgNC4wMzUuOTYuODk4LjkwNCAxLjM5NiAxLjk4MiAxLjM5NiAyLjg1NU0xMC41MTUgMzMuNzc0Yy0uNTczLjMwMi0xLjE1Ny41Ny0xLjc2NC44M0w0LjUgMzYuMzgybDEuNzg2LTQuMjM1Yy4yNTgtLjYwNC41My0xLjE4Ni44MzMtMS43NTcuNjkuMTgzIDEuNDQ4LjYyNSAyLjEwOCAxLjI4Mi42Ni42NTggMS4xMDIgMS40MTIgMS4yODcgMi4xMDIiIGZpbGw9IiM0Qzk3RkYiLz48cGF0aCBkPSJNMzYuNDk4IDguNzQ4YzAgLjQ2NC0uMTQuODc0LS40MzMgMS4xNjVsLTE5Ljc0MiAxOS42OGMtMi4xMyAyLjExLTQuNjczIDMuNzkzLTcuNTcyIDUuMDFMNC41IDM2LjM4bC45NzQtMi4zMTYgMS45MjUtLjgwOGMyLjg5OC0xLjIxOCA1LjQ0LTIuOSA3LjU3LTUuMDFsMTkuNzQzLTE5LjY4Yy4yOTItLjI5Mi40MzItLjcwMi40MzItMS4xNjUgMC0uNjQ2LS4yNy0xLjQtLjc4LTIuMTIyLjI1LjE3Mi41LjM3Ny43MzcuNjE0Ljg5OC45MDUgMS4zOTYgMS45ODMgMS4zOTYgMi44NTYiIGZpbGw9IiM1NzVFNzUiIG9wYWNpdHk9Ii4xNSIvPjxwYXRoIGQ9Ik0xOC40NSAxMi44M2MwIC41LS40MDQuOTA1LS45MDQuOTA1cy0uOTA1LS40MDUtLjkwNS0uOTA0YzAtLjUuNDA3LS45MDMuOTA2LS45MDMuNSAwIC45MDQuNDA0LjkwNC45MDR6IiBmaWxsPSIjNTc1RTc1Ii8+PC9nPjwvc3ZnPg=='; /** * Enum for pen color parameter values. @@ -286,7 +286,7 @@ class Scratch3PenBlocks { return { id: 'pen', name: 'Pen', - iconURI: iconURI, + blockIconURI: blockIconURI, blocks: [ { opcode: 'clear', From a81b81251bb29eb8027abb3893e5375beedefc5d Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Tue, 19 Dec 2017 15:54:45 -0500 Subject: [PATCH 227/272] Remove current instrument from sound state --- src/blocks/scratch3_sound.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/blocks/scratch3_sound.js b/src/blocks/scratch3_sound.js index be78ec7e2..9a2eb357c 100644 --- a/src/blocks/scratch3_sound.js +++ b/src/blocks/scratch3_sound.js @@ -26,7 +26,6 @@ class Scratch3SoundBlocks { static get DEFAULT_SOUND_STATE () { return { volume: 100, - currentInstrument: 0, effects: { pitch: 0, pan: 0 From 9f6cd92d9385b679bc762b927f637d87bde4a91c Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Wed, 20 Dec 2017 10:38:16 -0500 Subject: [PATCH 228/272] Clear sound effects for all targets on GF and stop --- src/blocks/scratch3_sound.js | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/blocks/scratch3_sound.js b/src/blocks/scratch3_sound.js index 9a2eb357c..7aa2c8ad4 100644 --- a/src/blocks/scratch3_sound.js +++ b/src/blocks/scratch3_sound.js @@ -9,6 +9,11 @@ class Scratch3SoundBlocks { * @type {Runtime} */ this.runtime = runtime; + + // Clear sound effects on green flag and stop button events. + this._clearEffectsForAllTargets = this._clearEffectsForAllTargets.bind(this); + this.runtime.on('PROJECT_STOP_ALL', this._clearEffectsForAllTargets); + this.runtime.on('PROJECT_START', this._clearEffectsForAllTargets); } /** @@ -194,13 +199,24 @@ class Scratch3SoundBlocks { } clearEffects (args, util) { - const soundState = this._getSoundState(util.target); + this._clearEffectsForTarget(util.target); + } + + _clearEffectsForTarget (target) { + const soundState = this._getSoundState(target); for (const effect in soundState.effects) { if (!soundState.effects.hasOwnProperty(effect)) continue; soundState.effects[effect] = 0; } - if (util.target.audioPlayer === null) return; - util.target.audioPlayer.clearEffects(); + if (target.audioPlayer === null) return; + target.audioPlayer.clearEffects(); + } + + _clearEffectsForAllTargets () { + const allTargets = this.runtime.targets; + for (let i = 0; i < allTargets.length; i++) { + this._clearEffectsForTarget(allTargets[i]); + } } setVolume (args, util) { From 8e554245c8c18e2a9115319523bdd2a45e96f11c Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Wed, 20 Dec 2017 10:56:44 -0500 Subject: [PATCH 229/272] Check for runtime --- src/blocks/scratch3_sound.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/blocks/scratch3_sound.js b/src/blocks/scratch3_sound.js index 7aa2c8ad4..29b0de06f 100644 --- a/src/blocks/scratch3_sound.js +++ b/src/blocks/scratch3_sound.js @@ -12,8 +12,10 @@ class Scratch3SoundBlocks { // Clear sound effects on green flag and stop button events. this._clearEffectsForAllTargets = this._clearEffectsForAllTargets.bind(this); - this.runtime.on('PROJECT_STOP_ALL', this._clearEffectsForAllTargets); - this.runtime.on('PROJECT_START', this._clearEffectsForAllTargets); + if (this.runtime) { + this.runtime.on('PROJECT_STOP_ALL', this._clearEffectsForAllTargets); + this.runtime.on('PROJECT_START', this._clearEffectsForAllTargets); + } } /** @@ -213,6 +215,7 @@ class Scratch3SoundBlocks { } _clearEffectsForAllTargets () { + if (this.runtime.targets === null) return; const allTargets = this.runtime.targets; for (let i = 0; i < allTargets.length; i++) { this._clearEffectsForTarget(allTargets[i]); From 05a1a668b3d909094a931a6feddf5c5df69dee65 Mon Sep 17 00:00:00 2001 From: Andrew Sliwinski Date: Wed, 20 Dec 2017 11:49:40 -0500 Subject: [PATCH 230/272] Accept both objects and strings for 'loadProject'. Resolves GH-733 --- src/virtual-machine.js | 12 +++---- test/integration/import-sb2-from-object.js | 38 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 test/integration/import-sb2-from-object.js diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 0881af2cf..e0bb9961b 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -217,16 +217,14 @@ class VirtualMachine extends EventEmitter { this.clear(); // Validate & parse - if (typeof json !== 'string') { - log.error('Failed to parse project. Non-string supplied to fromJSON.'); - return; - } - json = JSON.parse(json); - if (typeof json !== 'object') { - log.error('Failed to parse project. JSON supplied to fromJSON is not an object.'); + if (typeof json !== 'string' && typeof json !== 'object') { + log.error('Failed to parse project. Invalid type supplied to fromJSON.'); return; } + // Attempt to parse JSON if string is supplied + if (typeof json === 'string') json = JSON.parse(json); + // Establish version, deserialize, and load into runtime // @todo Support Scratch 1.4 // @todo This is an extremely naĂŻve / dangerous way of determining version. diff --git a/test/integration/import-sb2-from-object.js b/test/integration/import-sb2-from-object.js new file mode 100644 index 000000000..c53234f16 --- /dev/null +++ b/test/integration/import-sb2-from-object.js @@ -0,0 +1,38 @@ +const path = require('path'); +const test = require('tap').test; +const makeTestStorage = require('../fixtures/make-test-storage'); +const extract = require('../fixtures/extract'); +const VirtualMachine = require('../../src/index'); + +const uri = path.resolve(__dirname, '../fixtures/default.sb2'); +const project = JSON.parse(extract(uri)); + +test('default', t => { + const vm = new VirtualMachine(); + vm.attachStorage(makeTestStorage()); + + // Evaluate playground data and exit + vm.on('playgroundData', e => { + const threads = JSON.parse(e.threads); + t.ok(threads.length === 0); + t.end(); + process.nextTick(process.exit); + }); + + // Start VM, load project, and run + t.doesNotThrow(() => { + vm.start(); + vm.clear(); + vm.setCompatibilityMode(false); + vm.setTurboMode(false); + vm.loadProject(project).then(() => { + vm.greenFlag(); + + // After two seconds, get playground data and stop + setTimeout(() => { + vm.getPlaygroundData(); + vm.stopAll(); + }, 2000); + }); + }); +}); From a6d17fcba322d9cda089087cd1dbdd35b0eea09a Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Wed, 20 Dec 2017 14:00:23 -0500 Subject: [PATCH 231/272] Stop all sounds for all targets --- src/blocks/scratch3_sound.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/blocks/scratch3_sound.js b/src/blocks/scratch3_sound.js index 29b0de06f..ea8c5e865 100644 --- a/src/blocks/scratch3_sound.js +++ b/src/blocks/scratch3_sound.js @@ -167,9 +167,17 @@ class Scratch3SoundBlocks { return -1; } - stopAllSounds (args, util) { - if (util.target.audioPlayer === null) return; - util.target.audioPlayer.stopAllSounds(); + stopAllSounds () { + if (this.runtime.targets === null) return; + const allTargets = this.runtime.targets; + for (let i = 0; i < allTargets.length; i++) { + this._stopAllSoundsForTarget(allTargets[i]); + } + } + + _stopAllSoundsForTarget (target) { + if (target.audioPlayer === null) return; + target.audioPlayer.stopAllSounds(); } setEffect (args, util) { From cd66eb7f961776862efb11bf661f5063982cd77a Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 20 Dec 2017 15:25:14 -0500 Subject: [PATCH 232/272] Allow size to be set through postSpriteInfo, and emit updates when it is Required to allow size to be added to sprite info panel in the GUI. --- src/sprites/rendered-target.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sprites/rendered-target.js b/src/sprites/rendered-target.js index 9e181b957..c41b967a3 100644 --- a/src/sprites/rendered-target.js +++ b/src/sprites/rendered-target.js @@ -329,6 +329,7 @@ class RenderedTarget extends Target { this.runtime.requestRedraw(); } } + this.runtime.requestTargetsUpdate(this); } /** @@ -862,6 +863,9 @@ class RenderedTarget extends Target { if (data.hasOwnProperty('visible')) { this.setVisible(data.visible); } + if (data.hasOwnProperty('size')) { + this.setSize(data.size); + } } /** From 413d113dda2c8ba738ab850be316f64be6123b96 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Fri, 8 Dec 2017 12:19:11 -0500 Subject: [PATCH 233/272] Adding support for blocks to be plugged into the input of broadcast blocks. SB2 Import to come. --- src/blocks/scratch3_event.js | 25 +++++++++++++++++++++---- src/engine/execute.js | 29 ++++++++++++++++++++++++++++- src/engine/target.js | 19 ++++++++++++++++++- 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/src/blocks/scratch3_event.js b/src/blocks/scratch3_event.js index 5ee2fab1d..3b4050b62 100644 --- a/src/blocks/scratch3_event.js +++ b/src/blocks/scratch3_event.js @@ -55,9 +55,27 @@ class Scratch3EventBlocks { return false; } + /** + * Helper function to process broadcast block input (whether it's + * input from the dropdown menu or from a plugged in input block) + * @param {object} args The given arguments for the broadcast blocks + * @param {object} util The utility associated with this block. + * @return {?Variable} The broadcast message variable that matches + * the provided input. + */ + processBroadcastInput_ (args, util) { + let broadcastInput; + if (args.BROADCAST_OPTION) { + broadcastInput = util.runtime.getTargetForStage().lookupBroadcastMsg( + args.BROADCAST_OPTION.id, args.BROADCAST_OPTION.name); + } else { + broadcastInput = util.runtime.getTargetForStage().lookupBroadcastByInputValue(args.BROADCAST_INPUT.name); + } + return broadcastInput; + } + broadcast (args, util) { - const broadcastVar = util.runtime.getTargetForStage().lookupBroadcastMsg( - args.BROADCAST_OPTION.id, args.BROADCAST_OPTION.name); + const broadcastVar = this.processBroadcastInput_(args, util); if (broadcastVar) { const broadcastOption = broadcastVar.name; util.startHats('event_whenbroadcastreceived', { @@ -67,8 +85,7 @@ class Scratch3EventBlocks { } broadcastAndWait (args, util) { - const broadcastVar = util.runtime.getTargetForStage().lookupBroadcastMsg( - args.BROADCAST_OPTION.id, args.BROADCAST_OPTION.name); + const broadcastVar = this.processBroadcastInput_(args, util); if (broadcastVar) { const broadcastOption = broadcastVar.name; // Have we run before, starting threads? diff --git a/src/engine/execute.js b/src/engine/execute.js index 7dcf80d84..a4b9404d8 100644 --- a/src/engine/execute.js +++ b/src/engine/execute.js @@ -2,6 +2,7 @@ const BlockUtility = require('./block-utility'); const log = require('../util/log'); const Thread = require('./thread'); const {Map} = require('immutable'); +const cast = require('../util/cast'); /** * Single BlockUtility instance reused by execute for every pritimive ran. @@ -211,7 +212,33 @@ const execute = function (sequencer, thread) { currentStackFrame.waitingReporter = null; thread.popStack(); } - argValues[inputName] = currentStackFrame.reported[inputName]; + const inputValue = currentStackFrame.reported[inputName]; + if (inputName === 'BROADCAST_INPUT') { + const broadcastInput = inputs[inputName]; + // Check if something is plugged into the broadcast block, or + // if the shadow dropdown menu is being used. + // Differentiate between these two cases by giving argValues + // a 'BROADCAST_INPUT' field or a 'BROADCAST_OPTION' field + // respectively. + if (broadcastInput.block === broadcastInput.shadow) { + // Shadow dropdown menu is being used. + // Get the appropriate information out of it. + const shadow = blockContainer.getBlock(broadcastInput.shadow); + const broadcastField = shadow.fields.BROADCAST_OPTION; + argValues.BROADCAST_OPTION = { + id: broadcastField.id, + name: broadcastField.value + }; + } else { + // Something is plugged into the broadcast input. + // Cast it to a string. We don't need an id here. + argValues.BROADCAST_INPUT = { + name: cast.toString(inputValue) + }; + } + } else { + argValues[inputName] = inputValue; + } } // Add any mutation to args (e.g., for procedures). diff --git a/src/engine/target.js b/src/engine/target.js index 4e574177e..480b1e83c 100644 --- a/src/engine/target.js +++ b/src/engine/target.js @@ -115,6 +115,23 @@ class Target extends EventEmitter { } } + /** + * Look up a broadcast message with the given name and return the variable + * if it exists. Does not create a new broadcast message variable if + * it doesn't exist. + * @param {string} name Name of the variable. + * @return {?Variable} Variable object. + */ + lookupBroadcastByInputValue (name) { + const vars = this.variables; + for (const propName in vars) { + if ((vars[propName].type === Variable.BROADCAST_MESSAGE_TYPE) && + (vars[propName].name.toLowerCase() === name.toLowerCase())) { + return vars[propName]; + } + } + } + /** * Look up a variable object. * Search begins for local variables; then look for globals. @@ -141,7 +158,7 @@ class Target extends EventEmitter { * Search begins for local lists; then look for globals. * @param {!string} id Id of the list. * @param {!string} name Name of the list. - * @return {!List} List object. + * @return {!Varible} Variable object representing the found/created list. */ lookupOrCreateList (id, name) { const list = this.lookupVariableById(id); From c0e4ae455c42c49927d6a66d2fcb1213cc4eefe5 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Wed, 13 Dec 2017 13:41:22 -0500 Subject: [PATCH 234/272] Streamlining broadcast block execution. When arg information is provided to execute function, corresponding broadcast message is looked up by id, if provided, or if not, then name. If neither id nor name is provided, we can't look up the broadcast message and something is wrong, so an error is logged. We no longer need to differentiate between the shadow menu vs. plugged in input cases via the argValue name (e.g. 'BROADCAST_OPTION' vs. 'BROADCAST_INPUT'). This refactor also helps with sb2 import, coming in the next commit. --- src/blocks/scratch3_event.js | 25 ++++--------------------- src/engine/execute.js | 5 +---- src/engine/target.js | 13 ++++++++++--- 3 files changed, 15 insertions(+), 28 deletions(-) diff --git a/src/blocks/scratch3_event.js b/src/blocks/scratch3_event.js index 3b4050b62..5ee2fab1d 100644 --- a/src/blocks/scratch3_event.js +++ b/src/blocks/scratch3_event.js @@ -55,27 +55,9 @@ class Scratch3EventBlocks { return false; } - /** - * Helper function to process broadcast block input (whether it's - * input from the dropdown menu or from a plugged in input block) - * @param {object} args The given arguments for the broadcast blocks - * @param {object} util The utility associated with this block. - * @return {?Variable} The broadcast message variable that matches - * the provided input. - */ - processBroadcastInput_ (args, util) { - let broadcastInput; - if (args.BROADCAST_OPTION) { - broadcastInput = util.runtime.getTargetForStage().lookupBroadcastMsg( - args.BROADCAST_OPTION.id, args.BROADCAST_OPTION.name); - } else { - broadcastInput = util.runtime.getTargetForStage().lookupBroadcastByInputValue(args.BROADCAST_INPUT.name); - } - return broadcastInput; - } - broadcast (args, util) { - const broadcastVar = this.processBroadcastInput_(args, util); + const broadcastVar = util.runtime.getTargetForStage().lookupBroadcastMsg( + args.BROADCAST_OPTION.id, args.BROADCAST_OPTION.name); if (broadcastVar) { const broadcastOption = broadcastVar.name; util.startHats('event_whenbroadcastreceived', { @@ -85,7 +67,8 @@ class Scratch3EventBlocks { } broadcastAndWait (args, util) { - const broadcastVar = this.processBroadcastInput_(args, util); + const broadcastVar = util.runtime.getTargetForStage().lookupBroadcastMsg( + args.BROADCAST_OPTION.id, args.BROADCAST_OPTION.name); if (broadcastVar) { const broadcastOption = broadcastVar.name; // Have we run before, starting threads? diff --git a/src/engine/execute.js b/src/engine/execute.js index a4b9404d8..13742ec76 100644 --- a/src/engine/execute.js +++ b/src/engine/execute.js @@ -217,9 +217,6 @@ const execute = function (sequencer, thread) { const broadcastInput = inputs[inputName]; // Check if something is plugged into the broadcast block, or // if the shadow dropdown menu is being used. - // Differentiate between these two cases by giving argValues - // a 'BROADCAST_INPUT' field or a 'BROADCAST_OPTION' field - // respectively. if (broadcastInput.block === broadcastInput.shadow) { // Shadow dropdown menu is being used. // Get the appropriate information out of it. @@ -232,7 +229,7 @@ const execute = function (sequencer, thread) { } else { // Something is plugged into the broadcast input. // Cast it to a string. We don't need an id here. - argValues.BROADCAST_INPUT = { + argValues.BROADCAST_OPTION = { name: cast.toString(inputValue) }; } diff --git a/src/engine/target.js b/src/engine/target.js index 480b1e83c..9861c455d 100644 --- a/src/engine/target.js +++ b/src/engine/target.js @@ -98,12 +98,19 @@ class Target extends EventEmitter { * if it exists. * @param {string} id Id of the variable. * @param {string} name Name of the variable. - * @return {!Variable} Variable object. + * @return {?Variable} Variable object. */ lookupBroadcastMsg (id, name) { - const broadcastMsg = this.lookupVariableById(id); + let broadcastMsg; + if (id) { + broadcastMsg = this.lookupVariableById(id); + } else if (name) { + broadcastMsg = this.lookupBroadcastByInputValue(name); + } else { + log.error('Cannot find broadcast message if neither id nor name are provided.'); + } if (broadcastMsg) { - if (broadcastMsg.name !== name) { + if (name && (broadcastMsg.name.toLowerCase() !== name.toLowerCase())) { log.error(`Found broadcast message with id: ${id}, but` + `its name, ${broadcastMsg.name} did not match expected name ${name}.`); } From 154987fbb064f64c99067d8ca2046b25c15f50ad Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Wed, 13 Dec 2017 17:15:18 -0500 Subject: [PATCH 235/272] SB2 Import functionality for broadcast blocks with pluggable inputs. --- src/serialization/sb2.js | 37 +++++++++++++++++++++++++++----- src/serialization/sb2_specmap.js | 10 +++++---- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js index d19175dca..a8b750b3d 100644 --- a/src/serialization/sb2.js +++ b/src/serialization/sb2.js @@ -170,12 +170,17 @@ const generateVariableIdGetter = (function () { const globalBroadcastMsgStateGenerator = (function () { let broadcastMsgNameMap = {}; + const emptyStringName = uid(); return function (topLevel) { if (topLevel) broadcastMsgNameMap = {}; return { broadcastMsgMapUpdater: function (name) { + name = name.toLowerCase(); + if (name === '') { + name = emptyStringName; + } broadcastMsgNameMap[name] = `broadcastMsgId-${name}`; - return broadcastMsgNameMap[name]; + return {name: name, id: broadcastMsgNameMap[name]}; }, globalBroadcastMsgs: broadcastMsgNameMap }; @@ -494,15 +499,33 @@ const parseBlock = function (sb2block, addBroadcastMsg, getVariableId, extension if (shadowObscured) { fieldValue = '#990000'; } + } else if (expectedArg.inputOp === 'event_broadcast_menu') { + fieldName = 'BROADCAST_OPTION'; + if (shadowObscured) { + fieldValue = ''; + } } else if (shadowObscured) { // Filled drop-down menu. fieldValue = ''; } const fields = {}; fields[fieldName] = { - name: fieldName, - value: fieldValue + name: fieldName }; + // event_broadcast_menus have some extra properties to add to the + // field and a different value than the rest + if (expectedArg.inputOp === 'event_broadcast_menu') { + if (!shadowObscured) { + const broadcastInfo = addBroadcastMsg(fieldValue); + fields[fieldName].id = broadcastInfo.id; + // Re-assign the value, because the name could have changed + // if the scratch2 message was an empty string + fields[fieldName].value = broadcastInfo.name; + } + fields[fieldName].variableType = expectedArg.variableType; + } else { + fields[fieldName].value = fieldValue; + } activeBlock.children.push({ id: inputUid, opcode: expectedArg.inputOp, @@ -530,8 +553,12 @@ const parseBlock = function (sb2block, addBroadcastMsg, getVariableId, extension activeBlock.fields[expectedArg.fieldName].id = getVariableId(providedArg); } else if (expectedArg.fieldName === 'BROADCAST_OPTION') { // add the name in this field to the broadcast msg name map - const broadcastId = addBroadcastMsg(providedArg); - activeBlock.fields[expectedArg.fieldName].id = broadcastId; + const broadcastInfo = addBroadcastMsg(providedArg); + activeBlock.fields[expectedArg.fieldName].id = broadcastInfo.id; + // Need to reassign field value using the sb3 name from broadcastInfo + // because the sb2 message name (e.g. providedArg) could have changed + // if the original (providedArg) was an empty string + activeBlock.fields[expectedArg.fieldName].value = broadcastInfo.name; } const varType = expectedArg.variableType; if (typeof varType === 'string') { diff --git a/src/serialization/sb2_specmap.js b/src/serialization/sb2_specmap.js index cc0a56964..b829fc174 100644 --- a/src/serialization/sb2_specmap.js +++ b/src/serialization/sb2_specmap.js @@ -665,8 +665,9 @@ const specMap = { opcode: 'event_broadcast', argMap: [ { - type: 'field', - fieldName: 'BROADCAST_OPTION', + type: 'input', + inputOp: 'event_broadcast_menu', + inputName: 'BROADCAST_INPUT', variableType: Variable.BROADCAST_MESSAGE_TYPE } ] @@ -675,8 +676,9 @@ const specMap = { opcode: 'event_broadcastandwait', argMap: [ { - type: 'field', - fieldName: 'BROADCAST_OPTION', + type: 'input', + inputOp: 'event_broadcast_menu', + inputName: 'BROADCAST_INPUT', variableType: Variable.BROADCAST_MESSAGE_TYPE } ] From bcbe91064370bbe52f21cc0a66b165d3cf72b7f2 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Fri, 15 Dec 2017 11:02:26 -0500 Subject: [PATCH 236/272] Translating empty string messages from sb2 into messageN, where N is an integer >= n such that messageN is a fresh name. --- src/serialization/sb2.js | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js index a8b750b3d..313768dc2 100644 --- a/src/serialization/sb2.js +++ b/src/serialization/sb2.js @@ -170,19 +170,23 @@ const generateVariableIdGetter = (function () { const globalBroadcastMsgStateGenerator = (function () { let broadcastMsgNameMap = {}; + const allBroadcastInputsAndFields = []; const emptyStringName = uid(); return function (topLevel) { if (topLevel) broadcastMsgNameMap = {}; return { - broadcastMsgMapUpdater: function (name) { + broadcastMsgMapUpdater: function (name, block) { name = name.toLowerCase(); if (name === '') { name = emptyStringName; } broadcastMsgNameMap[name] = `broadcastMsgId-${name}`; + allBroadcastInputsAndFields.push(block); return {name: name, id: broadcastMsgNameMap[name]}; }, - globalBroadcastMsgs: broadcastMsgNameMap + globalBroadcastMsgs: broadcastMsgNameMap, + allBroadcastInputsAndFields: allBroadcastInputsAndFields, + emptyMsgName: emptyStringName }; }; }()); @@ -345,6 +349,23 @@ const parseScratchObject = function (object, runtime, extensions, topLevel) { // all other targets have finished processing. if (target.isStage) { const allBroadcastMsgs = globalBroadcastMsgObj.globalBroadcastMsgs; + const allBroadcastMsgInputsAndFields = globalBroadcastMsgObj.allBroadcastInputsAndFields; + const emptyName = globalBroadcastMsgObj.emptyMsgName; + if (allBroadcastMsgs[emptyName]) { + // look through allBroadcastMsgs to see if 'messageN' is used + let currIndex = 1; + while (allBroadcastMsgs[`message${currIndex}`]) { + currIndex += 1; + } + const newEmptyMsgName = `message${currIndex}`; + allBroadcastMsgs[newEmptyMsgName] = allBroadcastMsgs[emptyName]; + delete allBroadcastMsgs[emptyName]; + for (let i = 0; i < allBroadcastMsgInputsAndFields.length; i++) { + if (allBroadcastMsgInputsAndFields[i].value === emptyName) { + allBroadcastMsgInputsAndFields[i].value = newEmptyMsgName; + } + } + } for (const msgName in allBroadcastMsgs) { const msgId = allBroadcastMsgs[msgName]; const newMsg = new Variable( @@ -516,7 +537,7 @@ const parseBlock = function (sb2block, addBroadcastMsg, getVariableId, extension // field and a different value than the rest if (expectedArg.inputOp === 'event_broadcast_menu') { if (!shadowObscured) { - const broadcastInfo = addBroadcastMsg(fieldValue); + const broadcastInfo = addBroadcastMsg(fieldValue, fields[fieldName]); fields[fieldName].id = broadcastInfo.id; // Re-assign the value, because the name could have changed // if the scratch2 message was an empty string @@ -553,7 +574,7 @@ const parseBlock = function (sb2block, addBroadcastMsg, getVariableId, extension activeBlock.fields[expectedArg.fieldName].id = getVariableId(providedArg); } else if (expectedArg.fieldName === 'BROADCAST_OPTION') { // add the name in this field to the broadcast msg name map - const broadcastInfo = addBroadcastMsg(providedArg); + const broadcastInfo = addBroadcastMsg(providedArg, activeBlock.fields[expectedArg.fieldName]); activeBlock.fields[expectedArg.fieldName].id = broadcastInfo.id; // Need to reassign field value using the sb3 name from broadcastInfo // because the sb2 message name (e.g. providedArg) could have changed From 720c22db0e8dacf717f7c916bc58162a13428247 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Fri, 15 Dec 2017 14:00:53 -0500 Subject: [PATCH 237/272] Cleanup/refactoring. --- src/serialization/sb2.js | 72 ++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 29 deletions(-) diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js index 313768dc2..40304ce2d 100644 --- a/src/serialization/sb2.js +++ b/src/serialization/sb2.js @@ -170,22 +170,22 @@ const generateVariableIdGetter = (function () { const globalBroadcastMsgStateGenerator = (function () { let broadcastMsgNameMap = {}; - const allBroadcastInputsAndFields = []; + const allBroadcastFields = []; const emptyStringName = uid(); return function (topLevel) { if (topLevel) broadcastMsgNameMap = {}; return { - broadcastMsgMapUpdater: function (name, block) { + broadcastMsgMapUpdater: function (name, field) { name = name.toLowerCase(); if (name === '') { name = emptyStringName; } broadcastMsgNameMap[name] = `broadcastMsgId-${name}`; - allBroadcastInputsAndFields.push(block); - return {name: name, id: broadcastMsgNameMap[name]}; + allBroadcastFields.push(field); + return broadcastMsgNameMap[name]; }, globalBroadcastMsgs: broadcastMsgNameMap, - allBroadcastInputsAndFields: allBroadcastInputsAndFields, + allBroadcastFields: allBroadcastFields, emptyMsgName: emptyStringName }; }; @@ -349,23 +349,31 @@ const parseScratchObject = function (object, runtime, extensions, topLevel) { // all other targets have finished processing. if (target.isStage) { const allBroadcastMsgs = globalBroadcastMsgObj.globalBroadcastMsgs; - const allBroadcastMsgInputsAndFields = globalBroadcastMsgObj.allBroadcastInputsAndFields; - const emptyName = globalBroadcastMsgObj.emptyMsgName; - if (allBroadcastMsgs[emptyName]) { - // look through allBroadcastMsgs to see if 'messageN' is used + const allBroadcastMsgFields = globalBroadcastMsgObj.allBroadcastFields; + const oldEmptyMsgName = globalBroadcastMsgObj.emptyMsgName; + if (allBroadcastMsgs[oldEmptyMsgName]) { + // Find a fresh 'messageN' let currIndex = 1; while (allBroadcastMsgs[`message${currIndex}`]) { currIndex += 1; } const newEmptyMsgName = `message${currIndex}`; - allBroadcastMsgs[newEmptyMsgName] = allBroadcastMsgs[emptyName]; - delete allBroadcastMsgs[emptyName]; - for (let i = 0; i < allBroadcastMsgInputsAndFields.length; i++) { - if (allBroadcastMsgInputsAndFields[i].value === emptyName) { - allBroadcastMsgInputsAndFields[i].value = newEmptyMsgName; + // Add the new empty message name to the broadcast message + // name map, and assign it the old id. + // Then, delete the old entry in map. + allBroadcastMsgs[newEmptyMsgName] = allBroadcastMsgs[oldEmptyMsgName]; + delete allBroadcastMsgs[oldEmptyMsgName]; + // Now update all the broadcast message fields with + // the new empty message name. + for (let i = 0; i < allBroadcastMsgFields.length; i++) { + if (allBroadcastMsgFields[i].value === '') { + allBroadcastMsgFields[i].value = newEmptyMsgName; } } } + // Traverse the broadcast message name map and create + // broadcast messages as variables on the stage (which is this + // target). for (const msgName in allBroadcastMsgs) { const msgId = allBroadcastMsgs[msgName]; const newMsg = new Variable( @@ -531,21 +539,25 @@ const parseBlock = function (sb2block, addBroadcastMsg, getVariableId, extension } const fields = {}; fields[fieldName] = { - name: fieldName + name: fieldName, + value: fieldValue }; // event_broadcast_menus have some extra properties to add to the // field and a different value than the rest if (expectedArg.inputOp === 'event_broadcast_menu') { if (!shadowObscured) { - const broadcastInfo = addBroadcastMsg(fieldValue, fields[fieldName]); - fields[fieldName].id = broadcastInfo.id; - // Re-assign the value, because the name could have changed - // if the scratch2 message was an empty string - fields[fieldName].value = broadcastInfo.name; + // Need to update the broadcast message name map with + // the value of this field. + // Also need to provide the fields[fieldName] object, + // so that we can later update its value property, e.g. + // if sb2 message name is empty string, we will later + // replace this field's value with messageN + // once we can traverse through all the existing message names + // and come up with a fresh messageN. + const broadcastId = addBroadcastMsg(fieldValue, fields[fieldName]); + fields[fieldName].id = broadcastId; } fields[fieldName].variableType = expectedArg.variableType; - } else { - fields[fieldName].value = fieldValue; } activeBlock.children.push({ id: inputUid, @@ -573,13 +585,15 @@ const parseBlock = function (sb2block, addBroadcastMsg, getVariableId, extension // Add `id` property to variable fields activeBlock.fields[expectedArg.fieldName].id = getVariableId(providedArg); } else if (expectedArg.fieldName === 'BROADCAST_OPTION') { - // add the name in this field to the broadcast msg name map - const broadcastInfo = addBroadcastMsg(providedArg, activeBlock.fields[expectedArg.fieldName]); - activeBlock.fields[expectedArg.fieldName].id = broadcastInfo.id; - // Need to reassign field value using the sb3 name from broadcastInfo - // because the sb2 message name (e.g. providedArg) could have changed - // if the original (providedArg) was an empty string - activeBlock.fields[expectedArg.fieldName].value = broadcastInfo.name; + // Add the name in this field to the broadcast msg name map. + // Also need to provide the fields[fieldName] object, + // so that we can later update its value property, e.g. + // if sb2 message name is empty string, we will later + // replace this field's value with messageN + // once we can traverse through all the existing message names + // and come up with a fresh messageN. + const broadcastId = addBroadcastMsg(providedArg, activeBlock.fields[expectedArg.fieldName]); + activeBlock.fields[expectedArg.fieldName].id = broadcastId; } const varType = expectedArg.variableType; if (typeof varType === 'string') { From 6fc554daa5a2600f96b78f9233724d2401ac5615 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Thu, 21 Dec 2017 18:34:19 -0500 Subject: [PATCH 238/272] Implicit deletion behavior for broadcast blocks. --- src/virtual-machine.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index e0bb9961b..7b997dbdd 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -8,6 +8,7 @@ const sb2 = require('./serialization/sb2'); const sb3 = require('./serialization/sb3'); const StringUtil = require('./util/string-util'); const formatMessage = require('format-message'); +const Variable = require('./engine/variable'); const {loadCostume} = require('./import/load-costume.js'); const {loadSound} = require('./import/load-sound.js'); @@ -677,6 +678,35 @@ class VirtualMachine extends EventEmitter { * of the current editing target's blocks. */ emitWorkspaceUpdate () { + // Create a list of broadcast message Ids according to the stage variables + const stageVariables = this.runtime.getTargetForStage().variables; + let messageIds = []; + for (const varId in stageVariables) { + if (stageVariables[varId].type === Variable.BROADCAST_MESSAGE_TYPE) { + messageIds.push(varId); + } + } + // Go through all blocks on all targets, removing referenced + // broadcast ids from the list. + for (let i = 0; i < this.runtime.targets.length; i++) { + const currTarget = this.runtime.targets[i]; + const currBlocks = currTarget.blocks._blocks; + for (const blockId in currBlocks) { + if (currBlocks[blockId].fields.BROADCAST_OPTION) { + const id = currBlocks[blockId].fields.BROADCAST_OPTION.id; + const index = messageIds.indexOf(id); + if (index !== -1) { + messageIds = messageIds.slice(0, index) + .concat(messageIds.slice(index + 1)); + } + } + } + } + // Anything left in messageIds is not referenced by a block, so delete it. + for (let i = 0; i < messageIds.length; i++) { + const id = messageIds[i]; + delete this.runtime.getTargetForStage().variables[id]; + } const variableMap = Object.assign({}, this.runtime.getTargetForStage().variables, this.editingTarget.variables From 29c08c3583985bd1b9af6f867bdf179a17ca0ced Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Thu, 21 Dec 2017 18:44:29 -0500 Subject: [PATCH 239/272] Fixing unit test. --- test/unit/virtual-machine.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/unit/virtual-machine.js b/test/unit/virtual-machine.js index 40bd6bb54..8dd283cf6 100644 --- a/test/unit/virtual-machine.js +++ b/test/unit/virtual-machine.js @@ -287,12 +287,18 @@ test('emitWorkspaceUpdate', t => { global: { toXML: () => 'global' } + }, + blocks: { + toXML: () => 'blocks' } }, { variables: { unused: { toXML: () => 'unused' } + }, + blocks: { + toXML: () => 'blocks' } }, { variables: { From 5dbffe67ac55d7cddd4fe6a0234721e3066d1eb9 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Fri, 22 Dec 2017 10:47:11 -0800 Subject: [PATCH 240/272] Fix legacy `setPenHueToNumber` and `changePenHueBy` These two blocks were not doing the same shade-oriented math as `setPenShadeToNumber`: effectively these blocks were using the new color model instead of Scratch 2.0's hue-shade model. This change pulls the hue-shade color update logic into a separate function, now called by all the legacy pen blocks. --- src/extensions/scratch3_pen/index.js | 44 ++++++++++++++++++---------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/src/extensions/scratch3_pen/index.js b/src/extensions/scratch3_pen/index.js index b3a8818d3..e4a0ea843 100644 --- a/src/extensions/scratch3_pen/index.js +++ b/src/extensions/scratch3_pen/index.js @@ -673,6 +673,8 @@ class Scratch3PenBlocks { const hueValue = Cast.toNumber(args.HUE); const colorValue = hueValue / 2; this._setOrChangeColorParam(ColorParam.COLOR, colorValue, penState, false); + + this._legacyUpdatePenColor(penState); } /** @@ -686,6 +688,8 @@ class Scratch3PenBlocks { const hueChange = Cast.toNumber(args.HUE); const colorChange = hueChange / 2; this._setOrChangeColorParam(ColorParam.COLOR, colorChange, penState, true); + + this._legacyUpdatePenColor(penState); } /** @@ -705,25 +709,10 @@ class Scratch3PenBlocks { newShade = newShade % 200; if (newShade < 0) newShade += 200; - // Create the new color in RGB using the scratch 2 "shade" model - let rgb = Color.hsvToRgb({h: penState.color * 360 / 100, s: 1, v: 1}); - const shade = (newShade > 100) ? 200 - newShade : newShade; - if (shade < 50) { - rgb = Color.mixRgb(Color.RGB_BLACK, rgb, (10 + shade) / 60); - } else { - rgb = Color.mixRgb(rgb, Color.RGB_WHITE, (shade - 50) / 60); - } - - // Update the pen state according to new color - const hsv = Color.rgbToHsv(rgb); - penState.color = 100 * hsv.h / 360; - penState.saturation = 100 * hsv.s; - penState.brightness = 100 * hsv.v; - // And store the shade that was used to compute this new color for later use. penState._shade = newShade; - this._updatePenColor(penState); + this._legacyUpdatePenColor(penState); } /** @@ -739,6 +728,29 @@ class Scratch3PenBlocks { this.setPenShadeToNumber({SHADE: penState._shade + shadeChange}, util); } + /** + * Update the pen state's color from its hue & shade values, Scratch 2.0 style. + * @param {object} penState - update the HSV & RGB values in this pen state from its hue & shade values. + * @private + */ + _legacyUpdatePenColor (penState) { + // Create the new color in RGB using the scratch 2 "shade" model + let rgb = Color.hsvToRgb({h: penState.color * 360 / 100, s: 1, v: 1}); + const shade = (penState._shade > 100) ? 200 - penState._shade : penState._shade; + if (shade < 50) { + rgb = Color.mixRgb(Color.RGB_BLACK, rgb, (10 + shade) / 60); + } else { + rgb = Color.mixRgb(rgb, Color.RGB_WHITE, (shade - 50) / 60); + } + + // Update the pen state according to new color + const hsv = Color.rgbToHsv(rgb); + penState.color = 100 * hsv.h / 360; + penState.saturation = 100 * hsv.s; + penState.brightness = 100 * hsv.v; + + this._updatePenColor(penState); + } } module.exports = Scratch3PenBlocks; From ed1fc5f35300364e8f7902e7ef2e6d0e2dd0df0a Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Fri, 22 Dec 2017 11:08:05 -0800 Subject: [PATCH 241/272] Use Scratch 2.0 block labels for legacy blocks --- src/extensions/scratch3_pen/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/extensions/scratch3_pen/index.js b/src/extensions/scratch3_pen/index.js index e4a0ea843..abd46db12 100644 --- a/src/extensions/scratch3_pen/index.js +++ b/src/extensions/scratch3_pen/index.js @@ -446,7 +446,7 @@ class Scratch3PenBlocks { blockType: BlockType.COMMAND, text: formatMessage({ id: 'pen.setHue', - default: 'set pen hue to [HUE]', + default: 'set pen color to [HUE]', description: 'legacy pen blocks - set pen color to number' }), arguments: { @@ -462,7 +462,7 @@ class Scratch3PenBlocks { blockType: BlockType.COMMAND, text: formatMessage({ id: 'pen.changeHue', - default: 'change pen hue by [HUE]', + default: 'change pen color by [HUE]', description: 'legacy pen blocks - change pen color' }), arguments: { From d001a855719147316ec0133fd027c073de731887 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 28 Dec 2017 12:31:23 -0500 Subject: [PATCH 242/272] Add setDragMode primitive and unit test --- src/blocks/scratch3_sensing.js | 5 +++++ test/unit/blocks_sensing.js | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/blocks/scratch3_sensing.js b/src/blocks/scratch3_sensing.js index 75ee571c7..0ee1286eb 100644 --- a/src/blocks/scratch3_sensing.js +++ b/src/blocks/scratch3_sensing.js @@ -40,6 +40,7 @@ class Scratch3SensingBlocks { sensing_of: this.getAttributeOf, sensing_mousex: this.getMouseX, sensing_mousey: this.getMouseY, + sensing_setdragmode: this.setDragMode, sensing_mousedown: this.getMouseDown, sensing_keypressed: this.getKeyPressed, sensing_current: this.current, @@ -162,6 +163,10 @@ class Scratch3SensingBlocks { return Math.sqrt((dx * dx) + (dy * dy)); } + setDragMode (args, util) { + util.target.draggable = args.DRAG_MODE === 'draggable'; + } + getTimer (args, util) { return util.ioQuery('clock', 'projectTimer'); } diff --git a/test/unit/blocks_sensing.js b/test/unit/blocks_sensing.js index 5c2b927a8..221742b99 100644 --- a/test/unit/blocks_sensing.js +++ b/test/unit/blocks_sensing.js @@ -65,3 +65,17 @@ test('ask and answer with a visible target', t => { s.askAndWait({QUESTION: expectedQuestion}, util); }); + +test('set drag mode', t => { + const rt = new Runtime(); + const s = new Sensing(rt); + const util = {target: {draggable: true}}; + + s.setDragMode({DRAG_MODE: 'not draggable'}, util); + t.strictEqual(util.target.draggable, false); + + s.setDragMode({DRAG_MODE: 'draggable'}, util); + t.strictEqual(util.target.draggable, true); + + t.end(); +}); From fe51bd645080449310b814e328d678b8ebdda130 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 28 Dec 2017 13:14:00 -0500 Subject: [PATCH 243/272] Update layering blocks --- src/blocks/scratch3_looks.js | 22 ++++++++++++++++------ src/sprites/rendered-target.js | 25 ++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index 1429b6dd7..c694fb38e 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -233,8 +233,8 @@ class Scratch3LooksBlocks { looks_cleargraphiceffects: this.clearEffects, looks_changesizeby: this.changeSize, looks_setsizeto: this.setSize, - looks_gotofront: this.goToFront, - looks_gobacklayers: this.goBackLayers, + looks_gotofrontback: this.goToFrontBack, + looks_goforwardbackwardlayers: this.goForwardBackwardLayers, looks_size: this.getSize, looks_costumeorder: this.getCostumeIndex, looks_backdroporder: this.getBackdropIndex, @@ -409,14 +409,24 @@ class Scratch3LooksBlocks { util.target.setSize(size); } - goToFront (args, util) { + goToFrontBack (args, util) { if (!util.target.isStage) { - util.target.goToFront(); + if (args.FRONT_BACK === 'front') { + util.target.goToFront(); + } else { + util.target.goToBack(); + } } } - goBackLayers (args, util) { - util.target.goBackLayers(args.NUM); + goForwardBackwardLayers (args, util) { + if (!util.target.isStage) { + if (args.FORWARD_BACKWARD === 'forward') { + util.target.goForwardLayers(Cast.toNumber(args.NUM)); + } else { + util.target.goBackwardLayers(Cast.toNumber(args.NUM)); + } + } } getSize (args, util) { diff --git a/src/sprites/rendered-target.js b/src/sprites/rendered-target.js index c41b967a3..85c1d5365 100644 --- a/src/sprites/rendered-target.js +++ b/src/sprites/rendered-target.js @@ -699,10 +699,29 @@ class RenderedTarget extends Target { } /** - * Move back a number of layers. - * @param {number} nLayers How many layers to go back. + * Move to the back layer. */ - goBackLayers (nLayers) { + goToBack () { + if (this.renderer) { + this.renderer.setDrawableOrder(this.drawableID, -Infinity, false, 1); + } + } + + /** + * Move forward a number of layers. + * @param {number} nLayers How many layers to go forward. + */ + goForwardLayers (nLayers) { + if (this.renderer) { + this.renderer.setDrawableOrder(this.drawableID, nLayers, true, 1); + } + } + + /** + * Move backward a number of layers. + * @param {number} nLayers How many layers to go backward. + */ + goBackwardLayers (nLayers) { if (this.renderer) { this.renderer.setDrawableOrder(this.drawableID, -nLayers, true, 1); } From 477ef531ba8982c4048d0728938eefd491cf31b1 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 28 Dec 2017 14:52:06 -0500 Subject: [PATCH 244/272] Update specmap and sb2 import to add new fields to layering blocks. --- src/serialization/sb2.js | 14 ++++++++++++++ src/serialization/sb2_specmap.js | 4 ++-- test/unit/sprites_rendered-target.js | 6 +++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js index 40304ce2d..85f55910a 100644 --- a/src/serialization/sb2.js +++ b/src/serialization/sb2.js @@ -601,6 +601,20 @@ const parseBlock = function (sb2block, addBroadcastMsg, getVariableId, extension } } } + + // Updated layering blocks + if (oldOpcode === 'comeToFront') { + activeBlock.fields.FRONT_BACK = { + name: 'FRONT_BACK', + value: 'front' + }; + } else if (oldOpcode === 'goBackByLayers:') { + activeBlock.fields.FORWARD_BACKWARD = { + name: 'FORWARD_BACKWARD', + value: 'backward' + }; + } + // Special cases to generate mutations. if (oldOpcode === 'stopScripts') { // Mutation for stop block: if the argument is 'other scripts', diff --git a/src/serialization/sb2_specmap.js b/src/serialization/sb2_specmap.js index b829fc174..a8ca43540 100644 --- a/src/serialization/sb2_specmap.js +++ b/src/serialization/sb2_specmap.js @@ -345,12 +345,12 @@ const specMap = { ] }, 'comeToFront': { - opcode: 'looks_gotofront', + opcode: 'looks_gotofrontback', argMap: [ ] }, 'goBackByLayers:': { - opcode: 'looks_gobacklayers', + opcode: 'looks_goforwardbackwardlayers', argMap: [ { type: 'input', diff --git a/test/unit/sprites_rendered-target.js b/test/unit/sprites_rendered-target.js index 1592c357f..332a78111 100644 --- a/test/unit/sprites_rendered-target.js +++ b/test/unit/sprites_rendered-target.js @@ -293,8 +293,12 @@ test('layers', t => { a.renderer = renderer; a.goToFront(); t.equals(a.renderer.order, 5); - a.goBackLayers(2); + a.goBackwardLayers(2); t.equals(a.renderer.order, 3); + a.goToBack(); + t.equals(a.renderer.order, 1); + a.goForwardLayers(1); + t.equals(a.renderer.order, 2); o.drawableID = 999; a.goBehindOther(o); t.equals(a.renderer.order, 1); From b726c4c18dc5032cd2827409cc21ee4f94636a01 Mon Sep 17 00:00:00 2001 From: sjhuang26 Date: Fri, 29 Dec 2017 08:31:59 -0500 Subject: [PATCH 245/272] Changed postSpriteInfo logic --- src/sprites/rendered-target.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/sprites/rendered-target.js b/src/sprites/rendered-target.js index c41b967a3..13f9bd325 100644 --- a/src/sprites/rendered-target.js +++ b/src/sprites/rendered-target.js @@ -845,11 +845,10 @@ class RenderedTarget extends Target { */ postSpriteInfo (data) { const force = data.hasOwnProperty('force') ? data.force : null; - if (data.hasOwnProperty('x')) { - this.setXY(data.x, this.y, force); - } - if (data.hasOwnProperty('y')) { - this.setXY(this.x, data.y, force); + let isXChanged = data.hasOwnProperty('x'); + let isYChanged = data.hasOwnProperty('y'); + if (isXChanged || isYChanged) { + this.setXY(isXChanged ? data.x : this.x, isYChanged ? data.y : this.y, force); } if (data.hasOwnProperty('direction')) { this.setDirection(data.direction); From f7d80459c7cb693cbc442d99cb38f0e70f6f4ffa Mon Sep 17 00:00:00 2001 From: sjhuang26 Date: Fri, 29 Dec 2017 09:01:30 -0500 Subject: [PATCH 246/272] Fixed pen behavior when dragging --- src/extensions/scratch3_pen/index.js | 16 ++++++++++------ src/sprites/rendered-target.js | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/extensions/scratch3_pen/index.js b/src/extensions/scratch3_pen/index.js index abd46db12..c65400163 100644 --- a/src/extensions/scratch3_pen/index.js +++ b/src/extensions/scratch3_pen/index.js @@ -181,14 +181,18 @@ class Scratch3PenBlocks { * @param {RenderedTarget} target - the target which has moved. * @param {number} oldX - the previous X position. * @param {number} oldY - the previous Y position. + * @param {boolean} isForce - whether the movement was forced. * @private */ - _onTargetMoved (target, oldX, oldY) { - const penSkinId = this._getPenLayerID(); - if (penSkinId >= 0) { - const penState = this._getPenState(target); - this.runtime.renderer.penLine(penSkinId, penState.penAttributes, oldX, oldY, target.x, target.y); - this.runtime.requestRedraw(); + _onTargetMoved (target, oldX, oldY, isForce) { + // Only move the pen if the movement isn't forced (ie. dragged). + if (!isForce) { + const penSkinId = this._getPenLayerID(); + if (penSkinId >= 0) { + const penState = this._getPenState(target); + this.runtime.renderer.penLine(penSkinId, penState.penAttributes, oldX, oldY, target.x, target.y); + this.runtime.requestRedraw(); + } } } diff --git a/src/sprites/rendered-target.js b/src/sprites/rendered-target.js index 13f9bd325..fe9ede298 100644 --- a/src/sprites/rendered-target.js +++ b/src/sprites/rendered-target.js @@ -203,7 +203,7 @@ class RenderedTarget extends Target { this.x = x; this.y = y; } - this.emit(RenderedTarget.EVENT_TARGET_MOVED, this, oldX, oldY); + this.emit(RenderedTarget.EVENT_TARGET_MOVED, this, oldX, oldY, force); this.runtime.requestTargetsUpdate(this); } From 72dee72148d56d65d4d209b236638d8aa2f9a306 Mon Sep 17 00:00:00 2001 From: sjhuang26 Date: Fri, 29 Dec 2017 09:13:18 -0500 Subject: [PATCH 247/272] Change let to const --- src/sprites/rendered-target.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sprites/rendered-target.js b/src/sprites/rendered-target.js index fe9ede298..ee1109b5d 100644 --- a/src/sprites/rendered-target.js +++ b/src/sprites/rendered-target.js @@ -845,8 +845,8 @@ class RenderedTarget extends Target { */ postSpriteInfo (data) { const force = data.hasOwnProperty('force') ? data.force : null; - let isXChanged = data.hasOwnProperty('x'); - let isYChanged = data.hasOwnProperty('y'); + const isXChanged = data.hasOwnProperty('x'); + const isYChanged = data.hasOwnProperty('y'); if (isXChanged || isYChanged) { this.setXY(isXChanged ? data.x : this.x, isYChanged ? data.y : this.y, force); } From 6d90a34ff14019c9997b29a40a2aed45902c3e85 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 28 Dec 2017 12:31:23 -0500 Subject: [PATCH 248/272] Add setDragMode primitive and unit test --- src/blocks/scratch3_sensing.js | 2 +- test/unit/blocks_sensing.js | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/blocks/scratch3_sensing.js b/src/blocks/scratch3_sensing.js index 0ee1286eb..4f977a612 100644 --- a/src/blocks/scratch3_sensing.js +++ b/src/blocks/scratch3_sensing.js @@ -164,7 +164,7 @@ class Scratch3SensingBlocks { } setDragMode (args, util) { - util.target.draggable = args.DRAG_MODE === 'draggable'; + util.target.setDraggable(args.DRAG_MODE === 'draggable'); } getTimer (args, util) { diff --git a/test/unit/blocks_sensing.js b/test/unit/blocks_sensing.js index 221742b99..33b484466 100644 --- a/test/unit/blocks_sensing.js +++ b/test/unit/blocks_sensing.js @@ -1,6 +1,8 @@ const test = require('tap').test; const Sensing = require('../../src/blocks/scratch3_sensing'); const Runtime = require('../../src/engine/runtime'); +const Sprite = require('../../src/sprites/sprite'); +const RenderedTarget = require('../../src/sprites/rendered-target'); test('getPrimitives', t => { const rt = new Runtime(); @@ -67,15 +69,17 @@ test('ask and answer with a visible target', t => { }); test('set drag mode', t => { - const rt = new Runtime(); - const s = new Sensing(rt); - const util = {target: {draggable: true}}; + const runtime = new Runtime(); + runtime.requestTargetsUpdate = () => {}; // noop for testing + const sensing = new Sensing(runtime); + const s = new Sprite(); + const rt = new RenderedTarget(s, runtime); - s.setDragMode({DRAG_MODE: 'not draggable'}, util); - t.strictEqual(util.target.draggable, false); + sensing.setDragMode({DRAG_MODE: 'not draggable'}, {target: rt}); + t.strictEqual(rt.draggable, false); - s.setDragMode({DRAG_MODE: 'draggable'}, util); - t.strictEqual(util.target.draggable, true); + sensing.setDragMode({DRAG_MODE: 'draggable'}, {target: rt}); + t.strictEqual(rt.draggable, true); t.end(); }); From d6f1c48c086c40518ab383a3d95d33ae5615550a Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 4 Jan 2018 10:04:54 -0500 Subject: [PATCH 249/272] Add opcodes for new looks reporters with menu for costume number/name --- src/blocks/scratch3_looks.js | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index c694fb38e..546f594df 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -236,9 +236,8 @@ class Scratch3LooksBlocks { looks_gotofrontback: this.goToFrontBack, looks_goforwardbackwardlayers: this.goForwardBackwardLayers, looks_size: this.getSize, - looks_costumeorder: this.getCostumeIndex, - looks_backdroporder: this.getBackdropIndex, - looks_backdropname: this.getBackdropName + looks_costumenumbername: this.getCostumeNumberName, + looks_backdropnumbername: this.getBackdropNumberName }; } @@ -433,18 +432,21 @@ class Scratch3LooksBlocks { return Math.round(util.target.size); } - getBackdropIndex () { - const stage = this.runtime.getTargetForStage(); - return stage.currentCostume + 1; - } - - getBackdropName () { + getBackdropNumberName (args) { const stage = this.runtime.getTargetForStage(); + if (args.NUMBER_NAME === 'number') { + return stage.currentCostume + 1; + } + // Else return name return stage.sprite.costumes[stage.currentCostume].name; } - getCostumeIndex (args, util) { - return util.target.currentCostume + 1; + getCostumeNumberName (args, util) { + if (args.NUMBER_NAME === 'number') { + return util.target.currentCostume + 1; + } + // Else return name + return util.target.sprite.costumes[util.target.currentCostume].name; } } From 63be5bc48780cc0fe94a6b7544742a446ab0c3bc Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 4 Jan 2018 10:24:13 -0500 Subject: [PATCH 250/272] Transform sb2 looks reporters to new menu blocks --- src/serialization/sb2.js | 27 ++++++++++++++++++++++++--- src/serialization/sb2_specmap.js | 6 +++--- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js index 85f55910a..1102c005e 100644 --- a/src/serialization/sb2.js +++ b/src/serialization/sb2.js @@ -602,17 +602,38 @@ const parseBlock = function (sb2block, addBroadcastMsg, getVariableId, extension } } - // Updated layering blocks - if (oldOpcode === 'comeToFront') { + // Updates for blocks that have new menus (e.g. in Looks) + switch (oldOpcode) { + case 'comeToFront': activeBlock.fields.FRONT_BACK = { name: 'FRONT_BACK', value: 'front' }; - } else if (oldOpcode === 'goBackByLayers:') { + break; + case 'goBackByLayers:': activeBlock.fields.FORWARD_BACKWARD = { name: 'FORWARD_BACKWARD', value: 'backward' }; + break; + case 'backgroundIndex': + activeBlock.fields.NUMBER_NAME = { + name: 'NUMBER_NAME', + value: 'number' + }; + break; + case 'sceneName': + activeBlock.fields.NUMBER_NAME = { + name: 'NUMBER_NAME', + value: 'name' + }; + break; + case 'costumeIndex': + activeBlock.fields.NUMBER_NAME = { + name: 'NUMBER_NAME', + value: 'number' + }; + break; } // Special cases to generate mutations. diff --git a/src/serialization/sb2_specmap.js b/src/serialization/sb2_specmap.js index a8ca43540..bf386a15e 100644 --- a/src/serialization/sb2_specmap.js +++ b/src/serialization/sb2_specmap.js @@ -360,12 +360,12 @@ const specMap = { ] }, 'costumeIndex': { - opcode: 'looks_costumeorder', + opcode: 'looks_costumenumbername', argMap: [ ] }, 'sceneName': { - opcode: 'looks_backdropname', + opcode: 'looks_backdropnumbername', argMap: [ ] }, @@ -390,7 +390,7 @@ const specMap = { ] }, 'backgroundIndex': { - opcode: 'looks_backdroporder', + opcode: 'looks_backdropnumbername', argMap: [ ] }, From 3afe709cb07447c4a89a26cfa06ac9314ca298dd Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 4 Jan 2018 10:42:29 -0500 Subject: [PATCH 251/272] Add unit tests for new reporter blocks in looks --- test/unit/blocks_looks.js | 52 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 test/unit/blocks_looks.js diff --git a/test/unit/blocks_looks.js b/test/unit/blocks_looks.js new file mode 100644 index 000000000..1506d7f84 --- /dev/null +++ b/test/unit/blocks_looks.js @@ -0,0 +1,52 @@ +const test = require('tap').test; +const Looks = require('../../src/blocks/scratch3_looks'); +const util = { + target: { + currentCostume: 0, // Internally, current costume is 0 indexed + sprite: { + costumes: [ + {name: 'first name'}, + {name: 'second name'}, + {name: 'third name'} + ] + } + } +}; + +const fakeRuntime = { + getTargetForStage: () => util.target, // Just return the dummy target above. + on: () => {} // Stub out listener methods used in constructor. +}; +const blocks = new Looks(fakeRuntime); + +test('getCostumeNumberName returns 1-indexed costume number', t => { + util.target.currentCostume = 0; // This is 0-indexed. + const args = {NUMBER_NAME: 'number'}; + const number = blocks.getCostumeNumberName(args, util); + t.strictEqual(number, 1); + t.end(); +}); + +test('getCostumeNumberName can return costume name', t => { + util.target.currentCostume = 0; // This is 0-indexed. + const args = {NUMBER_NAME: 'name'}; + const number = blocks.getCostumeNumberName(args, util); + t.strictEqual(number, 'first name'); + t.end(); +}); + +test('getBackdropNumberName returns 1-indexed costume number', t => { + util.target.currentCostume = 2; // This is 0-indexed. + const args = {NUMBER_NAME: 'number'}; + const number = blocks.getBackdropNumberName(args, util); + t.strictEqual(number, 3); + t.end(); +}); + +test('getBackdropNumberName can return costume name', t => { + util.target.currentCostume = 2; // This is 0-indexed. + const args = {NUMBER_NAME: 'name'}; + const number = blocks.getBackdropNumberName(args, util); + t.strictEqual(number, 'third name'); + t.end(); +}); From 0b6d7adf3e69e296662169fa3b53a9f7a95de4e5 Mon Sep 17 00:00:00 2001 From: DD Liu Date: Mon, 8 Jan 2018 20:22:18 -0500 Subject: [PATCH 252/272] Update monitor on dropdown change --- src/engine/blocks.js | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 920128dc6..487115d13 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -3,6 +3,7 @@ const mutationAdapter = require('./mutation-adapter'); const xmlEscape = require('../util/xml-escape'); const MonitorRecord = require('./monitor-record'); const Clone = require('../util/clone'); +const {Map} = require('immutable'); /** * @fileoverview @@ -382,7 +383,20 @@ class Blocks { block.fields[args.name].id = args.value; } } else { + // Changing the value in a dropdown block.fields[args.name].value = args.value; + + if (!optRuntime || !block.parent){ + break; + } + + const parent = this._blocks[block.parent]; + if (parent.isMonitored) { + optRuntime.requestUpdateMonitor(Map({ + id: parent.id, + params: this._getBlockParams(parent) + })); + } } break; case 'mutation': @@ -390,14 +404,17 @@ class Blocks { break; case 'checkbox': block.isMonitored = args.value; - if (optRuntime) { - const isSpriteSpecific = optRuntime.monitorBlockInfo.hasOwnProperty(block.opcode) && - optRuntime.monitorBlockInfo[block.opcode].isSpriteSpecific; - block.targetId = isSpriteSpecific ? optRuntime.getEditingTarget().id : null; + if (!optRuntime) { + break; } - if (optRuntime && wasMonitored && !block.isMonitored) { + + const isSpriteSpecific = optRuntime.monitorBlockInfo.hasOwnProperty(block.opcode) && + optRuntime.monitorBlockInfo[block.opcode].isSpriteSpecific; + block.targetId = isSpriteSpecific ? optRuntime.getEditingTarget().id : null; + + if (wasMonitored && !block.isMonitored) { optRuntime.requestRemoveMonitor(block.id); - } else if (optRuntime && !wasMonitored && block.isMonitored) { + } else if (!wasMonitored && block.isMonitored) { optRuntime.requestAddMonitor(MonitorRecord({ // @todo(vm#564) this will collide if multiple sprites use same block id: block.id, From bbcb6bd5b72c0cc7d9497fb6ae8929874dddf29d Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Tue, 9 Jan 2018 09:39:52 -0500 Subject: [PATCH 253/272] Differentiate clamped from non clamped mouse io data (GUI#179) --- src/blocks/scratch3_motion.js | 10 +++++----- src/blocks/scratch3_sensing.js | 8 ++++---- src/io/mouse.js | 22 +++++++++++++++++++--- test/unit/io_mouse.js | 14 ++++++++++---- 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/blocks/scratch3_motion.js b/src/blocks/scratch3_motion.js index 0b206975b..69919c93a 100644 --- a/src/blocks/scratch3_motion.js +++ b/src/blocks/scratch3_motion.js @@ -64,8 +64,8 @@ class Scratch3MotionBlocks { let targetX = 0; let targetY = 0; if (targetName === '_mouse_') { - targetX = util.ioQuery('mouse', 'getX'); - targetY = util.ioQuery('mouse', 'getY'); + targetX = util.ioQuery('mouse', 'getClampedX'); + targetY = util.ioQuery('mouse', 'getClampedY'); } else if (targetName === '_random_') { const stageWidth = this.runtime.constructor.STAGE_WIDTH; const stageHeight = this.runtime.constructor.STAGE_HEIGHT; @@ -106,8 +106,8 @@ class Scratch3MotionBlocks { let targetX = 0; let targetY = 0; if (args.TOWARDS === '_mouse_') { - targetX = util.ioQuery('mouse', 'getX'); - targetY = util.ioQuery('mouse', 'getY'); + targetX = util.ioQuery('mouse', 'getClampedX'); + targetY = util.ioQuery('mouse', 'getClampedY'); } else { const pointTarget = this.runtime.getSpriteTargetByName(args.TOWARDS); if (!pointTarget) return; @@ -155,7 +155,7 @@ class Scratch3MotionBlocks { util.yield(); } } - + glideTo (args, util) { const targetXY = this.getTargetXY(args.TO, util); if (targetXY) { diff --git a/src/blocks/scratch3_sensing.js b/src/blocks/scratch3_sensing.js index 4f977a612..d8829f221 100644 --- a/src/blocks/scratch3_sensing.js +++ b/src/blocks/scratch3_sensing.js @@ -147,8 +147,8 @@ class Scratch3SensingBlocks { let targetX = 0; let targetY = 0; if (args.DISTANCETOMENU === '_mouse_') { - targetX = util.ioQuery('mouse', 'getX'); - targetY = util.ioQuery('mouse', 'getY'); + targetX = util.ioQuery('mouse', 'getClampedX'); + targetY = util.ioQuery('mouse', 'getClampedY'); } else { const distTarget = this.runtime.getSpriteTargetByName( args.DISTANCETOMENU @@ -176,11 +176,11 @@ class Scratch3SensingBlocks { } getMouseX (args, util) { - return util.ioQuery('mouse', 'getX'); + return util.ioQuery('mouse', 'getClampedX'); } getMouseY (args, util) { - return util.ioQuery('mouse', 'getY'); + return util.ioQuery('mouse', 'getClampedY'); } getMouseDown (args, util) { diff --git a/src/io/mouse.js b/src/io/mouse.js index fb4f299ae..ca16f7cf2 100644 --- a/src/io/mouse.js +++ b/src/io/mouse.js @@ -55,17 +55,33 @@ class Mouse { /** * Get the X position of the mouse. - * @return {number} Clamped X position of the mouse cursor. + * @return {number} Non-clamped X position of the mouse cursor. */ getX () { - return MathUtil.clamp(this._x, -240, 240); + return this._x; } /** * Get the Y position of the mouse. - * @return {number} Clamped Y position of the mouse cursor. + * @return {number} Non-clamped Y position of the mouse cursor. */ getY () { + return -this._y; + } + + /** + * Get the stage-clamped X position of the mouse. + * @return {number} Clamped X position of the mouse cursor. + */ + getClampedX () { + return MathUtil.clamp(this._x, -240, 240); + } + + /** + * Get the stage-clamped Y position of the mouse. + * @return {number} Clamped Y position of the mouse cursor. + */ + getClampedY () { return MathUtil.clamp(-this._y, -180, 180); } diff --git a/test/unit/io_mouse.js b/test/unit/io_mouse.js index 919786663..fc537e181 100644 --- a/test/unit/io_mouse.js +++ b/test/unit/io_mouse.js @@ -10,6 +10,8 @@ test('spec', t => { t.type(m.postData, 'function'); t.type(m.getX, 'function'); t.type(m.getY, 'function'); + t.type(m.getClampedX, 'function'); + t.type(m.getClampedY, 'function'); t.type(m.getIsDown, 'function'); t.end(); }); @@ -19,14 +21,16 @@ test('mouseUp', t => { const m = new Mouse(rt); m.postData({ - x: 1, + x: -20, y: 10, isDown: false, canvasWidth: 480, canvasHeight: 360 }); - t.strictEquals(m.getX(), -239); + t.strictEquals(m.getX(), -260); t.strictEquals(m.getY(), 170); + t.strictEquals(m.getClampedX(), -240); + t.strictEquals(m.getClampedY(), 170); t.strictEquals(m.getIsDown(), false); t.end(); }); @@ -37,13 +41,15 @@ test('mouseDown', t => { m.postData({ x: 10, - y: 100, + y: 400, isDown: true, canvasWidth: 480, canvasHeight: 360 }); t.strictEquals(m.getX(), -230); - t.strictEquals(m.getY(), 80); + t.strictEquals(m.getY(), -220); + t.strictEquals(m.getClampedX(), -230); + t.strictEquals(m.getClampedY(), -180); t.strictEquals(m.getIsDown(), true); t.end(); }); From 327d1179d9eafbecba57a7c097a9890c5f5ae1a5 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Tue, 9 Jan 2018 10:36:03 -0500 Subject: [PATCH 254/272] Update the mouse io to give scratch coordinates and client coordinates Fixes GUI #642 https://github.com/LLK/scratch-gui/issues/642 Fixes GUI #179 https://github.com/LLK/scratch-gui/issues/179 --- src/blocks/scratch3_motion.js | 8 +++---- src/blocks/scratch3_sensing.js | 12 +++++----- src/io/mouse.js | 38 +++++++++++++++++++------------ src/sprites/rendered-target.js | 3 +-- test/unit/io_mouse.js | 41 ++++++++++++++++++++++++---------- 5 files changed, 64 insertions(+), 38 deletions(-) diff --git a/src/blocks/scratch3_motion.js b/src/blocks/scratch3_motion.js index 69919c93a..524eab24a 100644 --- a/src/blocks/scratch3_motion.js +++ b/src/blocks/scratch3_motion.js @@ -64,8 +64,8 @@ class Scratch3MotionBlocks { let targetX = 0; let targetY = 0; if (targetName === '_mouse_') { - targetX = util.ioQuery('mouse', 'getClampedX'); - targetY = util.ioQuery('mouse', 'getClampedY'); + targetX = util.ioQuery('mouse', 'getScratchX'); + targetY = util.ioQuery('mouse', 'getScratchY'); } else if (targetName === '_random_') { const stageWidth = this.runtime.constructor.STAGE_WIDTH; const stageHeight = this.runtime.constructor.STAGE_HEIGHT; @@ -106,8 +106,8 @@ class Scratch3MotionBlocks { let targetX = 0; let targetY = 0; if (args.TOWARDS === '_mouse_') { - targetX = util.ioQuery('mouse', 'getClampedX'); - targetY = util.ioQuery('mouse', 'getClampedY'); + targetX = util.ioQuery('mouse', 'getScratchX'); + targetY = util.ioQuery('mouse', 'getScratchY'); } else { const pointTarget = this.runtime.getSpriteTargetByName(args.TOWARDS); if (!pointTarget) return; diff --git a/src/blocks/scratch3_sensing.js b/src/blocks/scratch3_sensing.js index d8829f221..d1f7ae51a 100644 --- a/src/blocks/scratch3_sensing.js +++ b/src/blocks/scratch3_sensing.js @@ -120,8 +120,8 @@ class Scratch3SensingBlocks { touchingObject (args, util) { const requestedObject = args.TOUCHINGOBJECTMENU; if (requestedObject === '_mouse_') { - const mouseX = util.ioQuery('mouse', 'getX'); - const mouseY = util.ioQuery('mouse', 'getY'); + const mouseX = util.ioQuery('mouse', 'getClientX'); + const mouseY = util.ioQuery('mouse', 'getClientY'); return util.target.isTouchingPoint(mouseX, mouseY); } else if (requestedObject === '_edge_') { return util.target.isTouchingEdge(); @@ -147,8 +147,8 @@ class Scratch3SensingBlocks { let targetX = 0; let targetY = 0; if (args.DISTANCETOMENU === '_mouse_') { - targetX = util.ioQuery('mouse', 'getClampedX'); - targetY = util.ioQuery('mouse', 'getClampedY'); + targetX = util.ioQuery('mouse', 'getScratchX'); + targetY = util.ioQuery('mouse', 'getScratchY'); } else { const distTarget = this.runtime.getSpriteTargetByName( args.DISTANCETOMENU @@ -176,11 +176,11 @@ class Scratch3SensingBlocks { } getMouseX (args, util) { - return util.ioQuery('mouse', 'getClampedX'); + return util.ioQuery('mouse', 'getScratchX'); } getMouseY (args, util) { - return util.ioQuery('mouse', 'getClampedY'); + return util.ioQuery('mouse', 'getScratchY'); } getMouseDown (args, util) { diff --git a/src/io/mouse.js b/src/io/mouse.js index ca16f7cf2..ecff2db10 100644 --- a/src/io/mouse.js +++ b/src/io/mouse.js @@ -40,10 +40,20 @@ class Mouse { */ postData (data) { if (data.x) { - this._x = data.x - (data.canvasWidth / 2); + this._clientX = data.x; + this._scratchX = MathUtil.clamp( + 480 * ((data.x / data.canvasWidth) - 0.5), + -240, + 240 + ); } if (data.y) { - this._y = data.y - (data.canvasHeight / 2); + this._clientY = data.y; + this._scratchY = MathUtil.clamp( + -360 * ((data.y / data.canvasHeight) - 0.5), + -180, + 180 + ); } if (typeof data.isDown !== 'undefined') { this._isDown = data.isDown; @@ -54,35 +64,35 @@ class Mouse { } /** - * Get the X position of the mouse. + * Get the X position of the mouse in client coordinates. * @return {number} Non-clamped X position of the mouse cursor. */ - getX () { - return this._x; + getClientX () { + return this._clientX; } /** - * Get the Y position of the mouse. + * Get the Y position of the mouse in client coordinates. * @return {number} Non-clamped Y position of the mouse cursor. */ - getY () { - return -this._y; + getClientY () { + return this._clientY; } /** - * Get the stage-clamped X position of the mouse. + * Get the X position of the mouse in scratch coordinates. * @return {number} Clamped X position of the mouse cursor. */ - getClampedX () { - return MathUtil.clamp(this._x, -240, 240); + getScratchX () { + return this._scratchX; } /** - * Get the stage-clamped Y position of the mouse. + * Get the Y position of the mouse in scratch coordinates. * @return {number} Clamped Y position of the mouse cursor. */ - getClampedY () { - return MathUtil.clamp(-this._y, -180, 180); + getScratchY () { + return this._scratchY; } /** diff --git a/src/sprites/rendered-target.js b/src/sprites/rendered-target.js index 1288240da..b6edd06ce 100644 --- a/src/sprites/rendered-target.js +++ b/src/sprites/rendered-target.js @@ -616,8 +616,7 @@ class RenderedTarget extends Target { // Limits test to this Drawable, so this will return true // even if the clone is obscured by another Drawable. const pickResult = this.runtime.renderer.pick( - x + (this.runtime.constructor.STAGE_WIDTH / 2), - -y + (this.runtime.constructor.STAGE_HEIGHT / 2), + x, y, null, null, [this.drawableID] ); diff --git a/test/unit/io_mouse.js b/test/unit/io_mouse.js index fc537e181..48613fdb2 100644 --- a/test/unit/io_mouse.js +++ b/test/unit/io_mouse.js @@ -8,10 +8,10 @@ test('spec', t => { t.type(m, 'object'); t.type(m.postData, 'function'); - t.type(m.getX, 'function'); - t.type(m.getY, 'function'); - t.type(m.getClampedX, 'function'); - t.type(m.getClampedY, 'function'); + t.type(m.getClientX, 'function'); + t.type(m.getClientY, 'function'); + t.type(m.getScratchX, 'function'); + t.type(m.getScratchY, 'function'); t.type(m.getIsDown, 'function'); t.end(); }); @@ -27,10 +27,10 @@ test('mouseUp', t => { canvasWidth: 480, canvasHeight: 360 }); - t.strictEquals(m.getX(), -260); - t.strictEquals(m.getY(), 170); - t.strictEquals(m.getClampedX(), -240); - t.strictEquals(m.getClampedY(), 170); + t.strictEquals(m.getClientX(), -20); + t.strictEquals(m.getClientY(), 10); + t.strictEquals(m.getScratchX(), -240); + t.strictEquals(m.getScratchY(), 170); t.strictEquals(m.getIsDown(), false); t.end(); }); @@ -46,10 +46,27 @@ test('mouseDown', t => { canvasWidth: 480, canvasHeight: 360 }); - t.strictEquals(m.getX(), -230); - t.strictEquals(m.getY(), -220); - t.strictEquals(m.getClampedX(), -230); - t.strictEquals(m.getClampedY(), -180); + t.strictEquals(m.getClientX(), 10); + t.strictEquals(m.getClientY(), 400); + t.strictEquals(m.getScratchX(), -230); + t.strictEquals(m.getScratchY(), -180); t.strictEquals(m.getIsDown(), true); t.end(); }); + +test('at zoomed scale', t => { + const rt = new Runtime(); + const m = new Mouse(rt); + + m.postData({ + x: 240, + y: 540, + canvasWidth: 960, + canvasHeight: 720 + }); + t.strictEquals(m.getClientX(), 240); + t.strictEquals(m.getClientY(), 540); + t.strictEquals(m.getScratchX(), -120); + t.strictEquals(m.getScratchY(), -90); + t.end(); +}); From db662b8584e2eb2de1ac3793f2f54ffba074f840 Mon Sep 17 00:00:00 2001 From: DD Date: Tue, 9 Jan 2018 14:55:46 -0500 Subject: [PATCH 255/272] fix lint --- src/engine/blocks.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 487115d13..d5e734ceb 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -402,7 +402,7 @@ class Blocks { case 'mutation': block.mutation = mutationAdapter(args.value); break; - case 'checkbox': + case 'checkbox': { block.isMonitored = args.value; if (!optRuntime) { break; @@ -428,6 +428,7 @@ class Blocks { } break; } + } this.resetCache(); } From fce83dc2c3ebb633568c7b9183e16ed87209dc1e Mon Sep 17 00:00:00 2001 From: DD Date: Wed, 10 Jan 2018 17:50:48 -0500 Subject: [PATCH 256/272] make it work for non-droppable inputs --- src/engine/blocks.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/engine/blocks.js b/src/engine/blocks.js index d5e734ceb..b889f2010 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -386,15 +386,15 @@ class Blocks { // Changing the value in a dropdown block.fields[args.name].value = args.value; - if (!optRuntime || !block.parent){ + if (!optRuntime){ break; } - const parent = this._blocks[block.parent]; - if (parent.isMonitored) { + const flyoutBlock = block.shadow && block.parent ? this._blocks[block.parent] : block; + if (flyoutBlock.isMonitored) { optRuntime.requestUpdateMonitor(Map({ - id: parent.id, - params: this._getBlockParams(parent) + id: flyoutBlock.id, + params: this._getBlockParams(flyoutBlock) })); } } From 323aafd165cd870d6ec4d3ca0453c389f55a284c Mon Sep 17 00:00:00 2001 From: DD Date: Wed, 10 Jan 2018 17:57:04 -0500 Subject: [PATCH 257/272] Update VM's model of monitored blocks --- src/blocks/scratch3_looks.js | 5 ++--- src/blocks/scratch3_sensing.js | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index 546f594df..e173ca04d 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -244,9 +244,8 @@ class Scratch3LooksBlocks { getMonitored () { return { looks_size: {isSpriteSpecific: true}, - looks_costumeorder: {isSpriteSpecific: true}, - looks_backdroporder: {}, - looks_backdropname: {} + looks_costumenumbername: {isSpriteSpecific: true}, + looks_backdropnumbername: {} }; } diff --git a/src/blocks/scratch3_sensing.js b/src/blocks/scratch3_sensing.js index 4f977a612..0cd4dde6d 100644 --- a/src/blocks/scratch3_sensing.js +++ b/src/blocks/scratch3_sensing.js @@ -56,7 +56,6 @@ class Scratch3SensingBlocks { sensing_answer: {}, sensing_loudness: {}, sensing_timer: {}, - sensing_of: {}, sensing_current: {} }; } From bc64e6ed3e7f950c8b4825bfa7063936252812a7 Mon Sep 17 00:00:00 2001 From: DD Date: Thu, 11 Jan 2018 11:28:21 -0500 Subject: [PATCH 258/272] Unique sprite and backdrop names --- src/virtual-machine.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 7b997dbdd..d1d8c2a14 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -268,6 +268,8 @@ class VirtualMachine extends EventEmitter { targets.forEach(target => { this.runtime.targets.push(target); (/** @type RenderedTarget */ target).updateAllDrawableProperties(); + // Ensure unique sprite name + if (target.isSprite()) this.renameSprite(target.id, target.getName()); }); // Select the first target for editing, e.g., the first sprite. if (wholeProject && (targets.length > 1)) { @@ -448,7 +450,7 @@ class VirtualMachine extends EventEmitter { addBackdrop (md5ext, backdropObject) { return loadCostume(md5ext, backdropObject, this.runtime).then(() => { const stage = this.runtime.getTargetForStage(); - stage.sprite.costumes.push(backdropObject); + stage.addCostume(backdropObject); stage.setCostume(stage.sprite.costumes.length - 1); }); } From 7ed58da1cff4517f8917ee5f3dd1817c59265236 Mon Sep 17 00:00:00 2001 From: DD Date: Thu, 11 Jan 2018 16:43:18 -0500 Subject: [PATCH 259/272] fix set editing target function --- src/virtual-machine.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index d1d8c2a14..61b61e518 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -631,7 +631,7 @@ class VirtualMachine extends EventEmitter { */ setEditingTarget (targetId) { // Has the target id changed? If not, exit. - if (targetId === this.editingTarget.id) { + if (this.editingTarget && targetId === this.editingTarget.id) { return; } const target = this.runtime.getTargetById(targetId); From 223575f8505a10050bb5b427ab66953171c4e89c Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 12 Jan 2018 11:20:17 -0500 Subject: [PATCH 260/272] Remove extra call to initDrawable that was erasing existing drawable. initDrawable is called in createClone previously, where the new costumes are installed. Calling this again here erases those loaded skins and causes an error when trying to calculate the uniforms when a drag starts. --- src/sprites/rendered-target.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sprites/rendered-target.js b/src/sprites/rendered-target.js index 1288240da..fbd6b4bc8 100644 --- a/src/sprites/rendered-target.js +++ b/src/sprites/rendered-target.js @@ -831,7 +831,6 @@ class RenderedTarget extends Target { newTarget.effects = JSON.parse(JSON.stringify(this.effects)); newTarget.variables = JSON.parse(JSON.stringify(this.variables)); newTarget.lists = JSON.parse(JSON.stringify(this.lists)); - newTarget.initDrawable(); newTarget.updateAllDrawableProperties(); newTarget.goBehindOther(this); return newTarget; From 57f3d43f4f2e4bcf15e0daae5b91ddbcedc59a9d Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Sat, 13 Jan 2018 13:23:33 -0500 Subject: [PATCH 261/272] Update specmap for sensing blocks that are now fixed menus. --- src/serialization/sb2_specmap.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/serialization/sb2_specmap.js b/src/serialization/sb2_specmap.js index bf386a15e..e9b56b9d0 100644 --- a/src/serialization/sb2_specmap.js +++ b/src/serialization/sb2_specmap.js @@ -861,9 +861,8 @@ const specMap = { opcode: 'sensing_keypressed', argMap: [ { - type: 'input', - inputOp: 'sensing_keyoptions', - inputName: 'KEY_OPTION' + type: 'field', + fieldName: 'KEY_OPTION' } ] }, @@ -936,9 +935,8 @@ const specMap = { opcode: 'sensing_of', argMap: [ { - type: 'input', - inputOp: 'sensing_of_property_menu', - inputName: 'PROPERTY' + type: 'field', + fieldName: 'PROPERTY' }, { type: 'input', From 2c1412dda42f32c2cd67c39aa91c09d20e09f5bd Mon Sep 17 00:00:00 2001 From: DD Date: Tue, 16 Jan 2018 17:41:18 -0500 Subject: [PATCH 262/272] Use text-encoding library for text encoder --- package.json | 1 + src/virtual-machine.js | 1 + 2 files changed, 2 insertions(+) diff --git a/package.json b/package.json index 02caa814e..e1a5af558 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "socket.io-client": "2.0.4", "stats.js": "^0.17.0", "tap": "^10.2.0", + "text-encoding": "0.6.4", "tiny-worker": "^2.1.1", "webpack": "^3.10.0", "webpack-dev-server": "^2.4.1", diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 61b61e518..5cacafee5 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -1,3 +1,4 @@ +import {TextEncoder} from 'text-encoding'; const EventEmitter = require('events'); const centralDispatch = require('./dispatch/central-dispatch'); From c0db708986f7f3d511122e8459c531370e75fb33 Mon Sep 17 00:00:00 2001 From: Ray Schamp Date: Wed, 17 Jan 2018 09:47:01 -0500 Subject: [PATCH 263/272] Fix import syntax --- src/virtual-machine.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 5cacafee5..0612261a9 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -1,4 +1,4 @@ -import {TextEncoder} from 'text-encoding'; +const TextEncoder = require('text-encoding'); const EventEmitter = require('events'); const centralDispatch = require('./dispatch/central-dispatch'); From e83141e81068f68b6cc8b3960ffc8ae836c7813e Mon Sep 17 00:00:00 2001 From: Ray Schamp Date: Wed, 17 Jan 2018 10:59:28 -0500 Subject: [PATCH 264/272] Revert "Use text-encoding library for text encoder" --- package.json | 1 - src/virtual-machine.js | 1 - 2 files changed, 2 deletions(-) diff --git a/package.json b/package.json index e1a5af558..02caa814e 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,6 @@ "socket.io-client": "2.0.4", "stats.js": "^0.17.0", "tap": "^10.2.0", - "text-encoding": "0.6.4", "tiny-worker": "^2.1.1", "webpack": "^3.10.0", "webpack-dev-server": "^2.4.1", diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 0612261a9..61b61e518 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -1,4 +1,3 @@ -const TextEncoder = require('text-encoding'); const EventEmitter = require('events'); const centralDispatch = require('./dispatch/central-dispatch'); From d649b2555b09c4fae3f1fa2d469b67923848ae0d Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 17 Jan 2018 11:31:44 -0500 Subject: [PATCH 265/272] Require TextEncoder correctly --- package.json | 1 + src/virtual-machine.js | 1 + 2 files changed, 2 insertions(+) diff --git a/package.json b/package.json index 02caa814e..e1a5af558 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "socket.io-client": "2.0.4", "stats.js": "^0.17.0", "tap": "^10.2.0", + "text-encoding": "0.6.4", "tiny-worker": "^2.1.1", "webpack": "^3.10.0", "webpack-dev-server": "^2.4.1", diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 61b61e518..cab409085 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -1,3 +1,4 @@ +const TextEncoder = require('text-encoding').TextEncoder; const EventEmitter = require('events'); const centralDispatch = require('./dispatch/central-dispatch'); From b02d7e8cd84a633fc1897be5eb4e7464b6babdbf Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Mon, 8 Jan 2018 15:34:58 -0500 Subject: [PATCH 266/272] Read benchmark warm up time and recording time from uri --- src/playground/benchmark.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/playground/benchmark.js b/src/playground/benchmark.js index 3fd1bc2a2..843ffca63 100644 --- a/src/playground/benchmark.js +++ b/src/playground/benchmark.js @@ -14,7 +14,7 @@ document.querySelector('.run') }, false); const loadProject = function () { - let id = location.hash.substring(1); + let id = location.hash.substring(1).split(',')[0]; if (id.length < 1 || !isFinite(id)) { id = projectInput.value; } @@ -310,7 +310,7 @@ class ProfilerRun { dom: document.getElementsByClassName('profile-count-group')[0], runningStats, - maxRecordedTime: 6000 + maxRecordedTime }); const frames = this.frames = new Frames(profiler); @@ -388,10 +388,21 @@ window.onload = function () { .innerText = progress.complete; }).on(storage); + let warmUpTime = 4000; + let maxRecordedTime = 6000; + + if (location.hash) { + const split = location.hash.substring(1).split(','); + if (split[1] && split[1].length > 0) { + warmUpTime = Number(split[1]); + } + maxRecordedTime = Number(split[2] || '0') || 6000; + } + new ProfilerRun({ vm, - warmUpTime: 4000, - maxRecordedTime: 6000 + warmUpTime, + maxRecordedTime }).run(); // Instantiate the renderer and connect it to the VM. From c6f4d89371815627ef846b836d19dd7f0cf5a0b6 Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Mon, 8 Jan 2018 15:35:43 -0500 Subject: [PATCH 267/272] Add benchmark suite, run and report on multiple benchmark projects --- src/playground/benchmark.js | 16 ++ src/playground/suite.css | 45 +++++ src/playground/suite.html | 23 +++ src/playground/suite.js | 385 ++++++++++++++++++++++++++++++++++++ 4 files changed, 469 insertions(+) create mode 100644 src/playground/suite.css create mode 100644 src/playground/suite.html create mode 100644 src/playground/suite.js diff --git a/src/playground/benchmark.js b/src/playground/benchmark.js index 843ffca63..bca3e0532 100644 --- a/src/playground/benchmark.js +++ b/src/playground/benchmark.js @@ -348,11 +348,21 @@ class ProfilerRun { run () { loadProject(); + window.parent.postMessage({ + type: 'BENCH_MESSAGE_LOADING' + }, '*'); + this.vm.on('workspaceUpdate', () => { setTimeout(() => { + window.parent.postMessage({ + type: 'BENCH_MESSAGE_WARMING_UP' + }, '*'); this.vm.greenFlag(); }, 100); setTimeout(() => { + window.parent.postMessage({ + type: 'BENCH_MESSAGE_ACTIVE' + }, '*'); this.vm.runtime.profiler = this.profiler; }, 100 + this.warmUpTime); setTimeout(() => { @@ -362,6 +372,12 @@ class ProfilerRun { this.frameTable.render(); this.opcodeTable.render(); + + window.parent.postMessage({ + type: 'BENCH_MESSAGE_COMPLETE', + frames: this.frames.frames, + opcodes: this.opcodes.opcodes + }, '*'); }, 100 + this.warmUpTime + this.maxRecordedTime); }); } diff --git a/src/playground/suite.css b/src/playground/suite.css new file mode 100644 index 000000000..08eb5d61e --- /dev/null +++ b/src/playground/suite.css @@ -0,0 +1,45 @@ +html, body { + width: 100%; + height: 100%; + margin: 0; + overflow: hidden; +} + +.runner-controls { + position: absolute; + width: 30em; + height: 100%; + left: 0; + right: 30em; + top: 0; + bottom: 0; + overflow: scroll; + padding: 1em; + box-sizing: border-box; +} + +.bench-frame-owner { + position: absolute; + width: calc(100% - 30em); + height: 100%; + left: 30em; + right: 100%; + top: 0; + bottom: 0; +} + +.fixture-project { + display: inline-block; +} + +.fixture-warm-up { + display: inline-block; +} + +.fixture-recording { + display: inline-block; +} + +.result-status { + float: right; +} diff --git a/src/playground/suite.html b/src/playground/suite.html new file mode 100644 index 000000000..8acd7ca65 --- /dev/null +++ b/src/playground/suite.html @@ -0,0 +1,23 @@ + + + + + + Scratch VM Benchmark Suite + + + +
+

Scratch VM Benchmark Suite

+
+ +
+
+
+ +
+ + + + + diff --git a/src/playground/suite.js b/src/playground/suite.js new file mode 100644 index 000000000..114828124 --- /dev/null +++ b/src/playground/suite.js @@ -0,0 +1,385 @@ +const soon = (() => { + let _soon; + return () => { + if (!_soon) { + _soon = Promise.resolve() + .then(() => { + _soon = null; + }); + } + return _soon; + }; +})(); + +class Emitter { + constructor () { + Object.defineProperty(this, '_listeners', { + value: {}, + enumerable: false + }); + } + on (name, listener, context) { + if (!this._listeners[name]) { + this._listeners[name] = []; + } + + this._listeners[name].push(listener, context); + } + off (name, listener, context) { + if (this._listeners[name]) { + if (listener) { + for (let i = 0; i < this._listeners[name].length; i += 2) { + if ( + this._listeners[name][i] === listener && + this._listeners[name][i + 1] === context) { + this._listeners[name].splice(i, 2); + i -= 2; + } + } + } else { + for (let i = 0; i < this._listeners[name].length; i += 2) { + if (this._listeners[name][i + 1] === context) { + this._listeners[name].splice(i, 2); + i -= 2; + } + } + } + } + } + emit (name, ...args) { + if (this._listeners[name]) { + for (let i = 0; i < this._listeners[name].length; i += 2) { + this._listeners[name][i].call(this._listeners[name][i + 1] || this, ...args); + } + } + } +} + +class BenchFrameStream extends Emitter { + constructor (frame) { + super(); + + this.frame = frame; + window.addEventListener('message', message => { + this.emit('message', message.data); + }); + } + + send (message) { + this.frame.send(message); + } +} + +const BENCH_MESSAGE_TYPE = { + LOAD: 'BENCH_MESSAGE_LOAD', + LOADING: 'BENCH_MESSAGE_LOADING', + WARMING_UP: 'BENCH_MESSAGE_WARMING_UP', + ACTIVE: 'BENCH_MESSAGE_ACTIVE', + COMPLETE: 'BENCH_MESSAGE_COMPLETE' +}; + +class BenchUtil { + constructor (frame) { + this.frame = frame; + this.benchStream = new BenchFrameStream(frame); + } + + startBench (args) { + Promise.resolve() + .then(() => new Promise(resolve => setTimeout(resolve, 100))) + .then(() => { + this.frame.contentWindow.location.assign('about:blank'); + }) + .then(() => new Promise(resolve => setTimeout(resolve, 100))) + .then(() => { + this.frame.contentWindow.location.assign( + `/benchmark/#${args.projectId},${args.warmUpTime},${args.recordingTime}`); + }); + } +} + +const BENCH_STATUS = { + INACTIVE: 'BENCH_STATUS_INACTIVE', + STARTING: 'BENCH_STATUS_STARTING', + LOADING: 'BENCH_STATUS_LOADING', + WARMING_UP: 'BENCH_STATUS_WARMING_UP', + ACTIVE: 'BENCH_STATUS_ACTIVE', + COMPLETE: 'BENCH_STATUS_COMPLETE' +}; + +class BenchResult { + constructor ({fixture, status = BENCH_STATUS.INACTIVE, frames = null, opcodes = null}) { + this.fixture = fixture; + this.status = status; + this.frames = frames; + this.opcodes = opcodes; + } +} + +class BenchFixture extends Emitter { + constructor ({ + projectId, + warmUpTime = 4000, + recordingTime = 6000 + }) { + super(); + + this.projectId = projectId; + this.warmUpTime = warmUpTime; + this.recordingTime = recordingTime; + } + + get id () { + return `${this.projectId}-${this.warmUpTime}-${this.recordingTime}`; + } + + run (util) { + return new Promise(resolve => { + util.benchStream.on('message', message => { + const result = { + fixture: this, + status: BENCH_STATUS.STARTING, + frames: null, + opcodes: null + }; + if (message.type === BENCH_MESSAGE_TYPE.LOADING) { + result.status = BENCH_STATUS.LOADING; + } else if (message.type === BENCH_MESSAGE_TYPE.WARMING_UP) { + result.status = BENCH_STATUS.WARMING_UP; + } else if (message.type === BENCH_MESSAGE_TYPE.ACTIVE) { + result.status = BENCH_STATUS.ACTIVE; + } else if (message.type === BENCH_MESSAGE_TYPE.COMPLETE) { + result.status = BENCH_STATUS.COMPLETE; + result.frames = message.frames; + result.opcodes = message.opcodes; + resolve(new BenchResult(result)); + util.benchStream.off('message', null, this); + } + this.emit('result', new BenchResult(result)); + }, this); + util.startBench(this); + }); + } +} + +class BenchSuiteResult extends Emitter { + constructor ({suite, results = []}) { + super(); + + this.suite = suite; + this.results = results; + + if (suite) { + suite.on('result', result => { + if (result.status === BENCH_STATUS.COMPLETE) { + this.results.push(results); + this.emit('add', this); + } + }); + } + } +} + +class BenchSuite extends Emitter { + constructor (fixtures = []) { + super(); + + this.fixtures = fixtures; + } + + add (fixture) { + this.fixtures.push(fixture); + } + + run (util) { + return new Promise(resolve => { + const fixtures = this.fixtures.slice(); + const results = []; + const push = result => { + result.fixture.off('result', null, this); + results.push(result); + }; + const emitResult = this.emit.bind(this, 'result'); + const pop = () => { + const fixture = fixtures.shift(); + if (fixture) { + fixture.on('result', emitResult, this); + fixture.run(util) + .then(push) + .then(pop); + } else { + resolve(new BenchSuiteResult({suite: this, results})); + } + }; + pop(); + }); + } +} + +class BenchRunner extends Emitter { + constructor ({frame, suite}) { + super(); + + this.frame = frame; + this.suite = suite; + this.util = new BenchUtil(frame); + } + + run () { + return this.suite.run(this.util); + } +} + +const viewNames = { + [BENCH_STATUS.INACTIVE]: 'Inactive', + [BENCH_STATUS.STARTING]: 'Starting', + [BENCH_STATUS.LOADING]: 'Loading', + [BENCH_STATUS.WARMING_UP]: 'Warming Up', + [BENCH_STATUS.ACTIVE]: 'Active', + [BENCH_STATUS.COMPLETE]: 'Complete' +}; + +class BenchResultView { + constructor ({result}) { + this.result = result; + this.dom = document.createElement('div'); + } + + update (result) { + soon().then(() => this.render(result)); + } + + render (newResult = this.result) { + const blockFunctionFrame = (newResult.frames ? newResult.frames : []) + .find(frame => frame.name === 'blockFunction'); + const stepThreadsInnerFrame = (newResult.frames ? newResult.frames : []) + .find(frame => frame.name === 'Sequencer.stepThreads#inner'); + + const blocksPerSecond = blockFunctionFrame ? + (blockFunctionFrame.executions / (stepThreadsInnerFrame.totalTime / 1000)) | 0 : + 0; + + this.dom.innerHTML = ` + + (${newResult.fixture.warmUpTime / 1000}s + ${newResult.fixture.recordingTime / 1000}s) +
+ ${blockFunctionFrame ? `${blocksPerSecond} blocks/s` : viewNames[newResult.status]} +
+ `; + + this.result = newResult; + return this; + } +} + +class BenchSuiteResultView { + constructor ({runner}) { + this.runner = runner; + this.suite = runner.suite; + this.views = {}; + this.dom = document.createElement('div'); + + const {suite} = runner; + for (const fixture of suite.fixtures) { + this.views[fixture.id] = new BenchResultView({result: new BenchResult({fixture})}); + this.dom.appendChild(this.views[fixture.id].render().dom); + } + + suite.on('result', result => { + this.views[result.fixture.id].update(result); + }); + } + + render () { + return this; + } +} + +window.onload = function () { + const suite = new BenchSuite(); + + suite.add(new BenchFixture({ + projectId: 130041250, + warmUpTime: 0, + recordingTime: 2000 + })); + + suite.add(new BenchFixture({ + projectId: 130041250, + warmUpTime: 4000, + recordingTime: 6000 + })); + + suite.add(new BenchFixture({ + projectId: 14844969, + warmUpTime: 0, + recordingTime: 2000 + })); + + suite.add(new BenchFixture({ + projectId: 14844969, + warmUpTime: 1000, + recordingTime: 6000 + })); + + suite.add(new BenchFixture({ + projectId: 173918262, + warmUpTime: 0, + recordingTime: 5000 + })); + + suite.add(new BenchFixture({ + projectId: 173918262, + warmUpTime: 5000, + recordingTime: 5000 + })); + + suite.add(new BenchFixture({ + projectId: 155128646, + warmUpTime: 0, + recordingTime: 5000 + })); + + suite.add(new BenchFixture({ + projectId: 155128646, + warmUpTime: 5000, + recordingTime: 5000 + })); + + suite.add(new BenchFixture({ + projectId: 89811578, + warmUpTime: 0, + recordingTime: 5000 + })); + + suite.add(new BenchFixture({ + projectId: 89811578, + warmUpTime: 5000, + recordingTime: 5000 + })); + + suite.add(new BenchFixture({ + projectId: 139193539, + warmUpTime: 0, + recordingTime: 5000 + })); + + suite.add(new BenchFixture({ + projectId: 139193539, + warmUpTime: 5000, + recordingTime: 5000 + })); + + const frame = document.getElementsByTagName('iframe')[0]; + const runner = new BenchRunner({frame, suite}); + const resultsView = new BenchSuiteResultView({runner}); + + document.getElementsByClassName('suite-results')[0].appendChild(resultsView.dom); + + runner.run(); +}; From 479f1ba163c1baf56da7cbf5df58a3eee903e23e Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Tue, 16 Jan 2018 18:20:26 -0500 Subject: [PATCH 268/272] Produce a benchmark share link storing the report in the url --- src/playground/benchmark.css | 26 +++++++++++ src/playground/benchmark.js | 89 ++++++++++++++++++++++++++++++++---- src/playground/index.html | 20 ++++++-- 3 files changed, 122 insertions(+), 13 deletions(-) diff --git a/src/playground/benchmark.css b/src/playground/benchmark.css index 07068f59b..746c173a8 100644 --- a/src/playground/benchmark.css +++ b/src/playground/benchmark.css @@ -11,16 +11,42 @@ p { left: 450px; } } +.share { + display: none; +} +.share label { + cursor: pointer; +} +.share[href] { + display: inline; +} + +.render .profile-tables { + position: static; + left: 0; +} +.render .description { + display: none; +} +.render .run-push { + display: none; +} #scratch-stage { border: 5px solid black; display: block; width: 400px; height: 300px; } +.render #scratch-stage { + display: none; +} .loading label, .profile-count label{ width: 15em; display: inline-block; } +.render .loading { + display: none; +} .profile-tables table { margin: 30px 0 30px 0px; } diff --git a/src/playground/benchmark.js b/src/playground/benchmark.js index bca3e0532..3c2963979 100644 --- a/src/playground/benchmark.js +++ b/src/playground/benchmark.js @@ -13,12 +13,20 @@ document.querySelector('.run') location.reload(); }, false); +const setShareLink = function (json) { + document.querySelector('.share') + .href = `#view/${btoa(JSON.stringify(json))}`; + document.querySelectorAll('.share')[1] + .href = `suite.html`; +}; + const loadProject = function () { let id = location.hash.substring(1).split(',')[0]; if (id.length < 1 || !isFinite(id)) { id = projectInput.value; } Scratch.vm.downloadProjectId(id); + return id; }; /** @@ -221,6 +229,13 @@ const frameOrder = [ 'Runtime._step' ]; +const trackSlowFrames = [ + 'Sequencer.stepThreads', + 'Sequencer.stepThreads#inner', + 'Sequencer.stepThread', + 'execute' +]; + class FramesTable extends StatTable { constructor (options) { super(options); @@ -241,12 +256,7 @@ class FramesTable extends StatTable { } isSlow (key, frame) { - return ([ - 'Sequencer.stepThreads', - 'Sequencer.stepThreads#inner', - 'Sequencer.stepThread', - 'execute' - ].indexOf(key) > 0 && + return (trackSlowFrames.indexOf(key) > 0 && frame.selfTime / frame.totalTime > SLOW); } } @@ -346,7 +356,7 @@ class ProfilerRun { } run () { - loadProject(); + this.projectId = loadProject(); window.parent.postMessage({ type: 'BENCH_MESSAGE_LOADING' @@ -378,12 +388,49 @@ class ProfilerRun { frames: this.frames.frames, opcodes: this.opcodes.opcodes }, '*'); + + setShareLink({ + fixture: { + projectId: this.projectId, + warmUpTime: this.warmUpTime, + recordingTime: this.maxRecordedTime + }, + frames: this.frames.frames, + opcodes: this.opcodes.opcodes + }); }, 100 + this.warmUpTime + this.maxRecordedTime); }); } + + render (json) { + const {fixture} = json; + document.querySelector('[type=text]').value = [ + fixture.projectId, + fixture.warmUpTime, + fixture.recordingTime + ].join(','); + + this.frames.frames = json.frames.map( + frame => Object.assign(new StatView(), frame, { + name: this.profiler.nameById(this.profiler.idByName(frame.name)) + }) + ); + + this.opcodes.opcodes = {}; + Object.entries(json.opcodes).forEach(([opcode, data]) => { + this.opcodes.opcodes[opcode] = Object.assign(new StatView(), data); + }); + + this.frameTable.render(); + this.opcodeTable.render(); + } } -window.onload = function () { +/** + * Run the benchmark with given parameters in the location's hash field or + * using defaults. + */ +const runBenchmark = function () { // Lots of global variables to make debugging easier // Instantiate the VM. const vm = new window.VirtualMachine(); @@ -493,3 +540,29 @@ window.onload = function () { // Run threads vm.start(); }; + +/** + * Render previously run benchmark data. + * @param {object} json data from a previous benchmark run. + */ +const renderBenchmarkData = function (json) { + const vm = new window.VirtualMachine(); + new ProfilerRun({vm}).render(json); + setShareLink(json); +}; + +window.onload = function () { + if (location.hash.substring(1).startsWith('view')) { + document.body.className = 'render'; + const data = location.hash.substring(6); + const frozen = atob(data); + const json = JSON.parse(frozen); + renderBenchmarkData(json); + } else { + runBenchmark(); + } +}; + +window.onhashchange = function () { + location.reload(); +}; diff --git a/src/playground/index.html b/src/playground/index.html index 81ba4f577..9a0fcfbe7 100644 --- a/src/playground/index.html +++ b/src/playground/index.html @@ -8,19 +8,21 @@

Scratch VM Benchmark

-

+

Welcome to the scratch-vm benchmark. This tool helps you profile a scratch project. When you load the page, it: -

    +
    1. loads the default project and enables turbo mode
    2. runs the project for 4 seconds to warm up
    3. profiles for 6 seconds
    4. stops and reports

    - - -

    +

    + + +
    +

    Try a different project, like `130041250`

    @@ -43,6 +45,14 @@ ...
+ +
From 775d38d8d5b59f3a35835db22643e4dae6cd603e Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Tue, 16 Jan 2018 18:32:19 -0500 Subject: [PATCH 269/272] Truncate benchmark selfTime and totalTime values --- src/playground/benchmark.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/playground/benchmark.js b/src/playground/benchmark.js index 3c2963979..4e6d383bd 100644 --- a/src/playground/benchmark.js +++ b/src/playground/benchmark.js @@ -134,10 +134,16 @@ class StatView { } cell = document.createElement('td'); + // Truncate selfTime. Value past the microsecond are floating point + // noise. + this.selfTime = Math.floor(this.selfTime * 1000) / 1000; cell.innerText = (this.selfTime / 1000).toPrecision(3); row.appendChild(cell); cell = document.createElement('td'); + // Truncate totalTime. Value past the microsecond are floating point + // noise. + this.totalTime = Math.floor(this.totalTime * 1000) / 1000; cell.innerText = (this.totalTime / 1000).toPrecision(3); row.appendChild(cell); From 4d4966cba94904fd3be901b107e425c3085b9f69 Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Tue, 16 Jan 2018 18:33:35 -0500 Subject: [PATCH 270/272] Save and compare results, show individual results in iframe --- src/playground/suite.css | 33 +++++ src/playground/suite.html | 6 +- src/playground/suite.js | 267 ++++++++++++++++++++++++++++++++++---- 3 files changed, 278 insertions(+), 28 deletions(-) diff --git a/src/playground/suite.css b/src/playground/suite.css index 08eb5d61e..06df9a3fc 100644 --- a/src/playground/suite.css +++ b/src/playground/suite.css @@ -5,6 +5,10 @@ html, body { overflow: hidden; } +iframe { + border: none; +} + .runner-controls { position: absolute; width: 30em; @@ -15,6 +19,7 @@ html, body { bottom: 0; overflow: scroll; padding: 1em; + padding-top: 0; box-sizing: border-box; } @@ -28,8 +33,24 @@ html, body { bottom: 0; } +.controls { + margin-bottom: 1em; +} + +.legend { + margin: 1em 0; +} + +.result-view { + border-bottom: 1px solid #ccc; + border-spacing: 0; + border-collapse: collapse; + padding: 5px; +} + .fixture-project { display: inline-block; + clear: both; } .fixture-warm-up { @@ -40,6 +61,18 @@ html, body { display: inline-block; } +.result-view.resume { + cursor: pointer; +} + .result-status { float: right; + text-align: right; + margin-left: 0.3em; +} + +.compare-file { + cursor: pointer; + visibility: hidden; + width: 0; } diff --git a/src/playground/suite.html b/src/playground/suite.html index 8acd7ca65..4100ddd82 100644 --- a/src/playground/suite.html +++ b/src/playground/suite.html @@ -10,11 +10,13 @@

Scratch VM Benchmark Suite

- +
+
- +
diff --git a/src/playground/suite.js b/src/playground/suite.js index 114828124..8ab0d492f 100644 --- a/src/playground/suite.js +++ b/src/playground/suite.js @@ -70,7 +70,16 @@ class BenchFrameStream extends Emitter { } } +const benchmarkUrlArgs = args => ( + [ + args.projectId, + args.warmUpTime, + args.recordingTime + ].join(',') +); + const BENCH_MESSAGE_TYPE = { + INACTIVE: 'BENCH_MESSAGE_INACTIVE', LOAD: 'BENCH_MESSAGE_LOAD', LOADING: 'BENCH_MESSAGE_LOADING', WARMING_UP: 'BENCH_MESSAGE_WARMING_UP', @@ -84,22 +93,38 @@ class BenchUtil { this.benchStream = new BenchFrameStream(frame); } + setFrameLocation (url) { + this.frame.contentWindow.location.assign(url); + } + startBench (args) { - Promise.resolve() - .then(() => new Promise(resolve => setTimeout(resolve, 100))) + this.benchArgs = args; + this.setFrameLocation(`index.html#${benchmarkUrlArgs(args)}`); + } + + pauseBench () { + new Promise(resolve => setTimeout(resolve, 1000)) .then(() => { - this.frame.contentWindow.location.assign('about:blank'); - }) - .then(() => new Promise(resolve => setTimeout(resolve, 100))) - .then(() => { - this.frame.contentWindow.location.assign( - `/benchmark/#${args.projectId},${args.warmUpTime},${args.recordingTime}`); + this.benchStream.emit('message', { + type: BENCH_MESSAGE_TYPE.INACTIVE + }); }); } + + resumeBench () { + this.startBench(this.benchArgs); + } + + renderResults (results) { + this.setFrameLocation( + `index.html#view/${btoa(JSON.stringify(results))}` + ); + } } const BENCH_STATUS = { INACTIVE: 'BENCH_STATUS_INACTIVE', + RESUME: 'BENCH_STATUS_RESUME', STARTING: 'BENCH_STATUS_STARTING', LOADING: 'BENCH_STATUS_LOADING', WARMING_UP: 'BENCH_STATUS_WARMING_UP', @@ -142,7 +167,9 @@ class BenchFixture extends Emitter { frames: null, opcodes: null }; - if (message.type === BENCH_MESSAGE_TYPE.LOADING) { + if (message.type === BENCH_MESSAGE_TYPE.INACTIVE) { + result.status = BENCH_STATUS.RESUME; + } else if (message.type === BENCH_MESSAGE_TYPE.LOADING) { result.status = BENCH_STATUS.LOADING; } else if (message.type === BENCH_MESSAGE_TYPE.WARMING_UP) { result.status = BENCH_STATUS.WARMING_UP; @@ -232,6 +259,7 @@ class BenchRunner extends Emitter { const viewNames = { [BENCH_STATUS.INACTIVE]: 'Inactive', + [BENCH_STATUS.RESUME]: 'Resume', [BENCH_STATUS.STARTING]: 'Starting', [BENCH_STATUS.LOADING]: 'Loading', [BENCH_STATUS.WARMING_UP]: 'Warming Up', @@ -240,8 +268,10 @@ const viewNames = { }; class BenchResultView { - constructor ({result}) { + constructor ({result, benchUtil}) { this.result = result; + this.compare = null; + this.benchUtil = benchUtil; this.dom = document.createElement('div'); } @@ -249,26 +279,114 @@ class BenchResultView { soon().then(() => this.render(result)); } - render (newResult = this.result) { - const blockFunctionFrame = (newResult.frames ? newResult.frames : []) + resume () { + this.benchUtil.resumeBench(); + } + + setFrameLocation (loc) { + this.benchUtil.pauseBench(); + this.benchUtil.setFrameLocation(loc); + } + + act (ev) { + if ( + ev.type === 'click' && + ev.button === 0 && + !(ev.altKey || ev.ctrlKey || ev.shiftKey || ev.metaKey) + ) { + let target = ev.target; + while (target && target.tagName.toLowerCase() !== 'a') { + target = target.parentElement; + } + if (target && target.tagName.toLowerCase() === 'a') { + if (target.href) { + this.setFrameLocation(target.href); + ev.preventDefault(); + } + } else if (ev.currentTarget.classList.contains('resume')) { + this.resume(); + } + } + } + + render (newResult = this.result, compareResult = this.compare) { + const newResultFrames = (newResult.frames ? newResult.frames : []); + const blockFunctionFrame = newResultFrames .find(frame => frame.name === 'blockFunction'); - const stepThreadsInnerFrame = (newResult.frames ? newResult.frames : []) + const stepThreadsInnerFrame = newResultFrames .find(frame => frame.name === 'Sequencer.stepThreads#inner'); const blocksPerSecond = blockFunctionFrame ? - (blockFunctionFrame.executions / (stepThreadsInnerFrame.totalTime / 1000)) | 0 : + (blockFunctionFrame.executions / + (stepThreadsInnerFrame.totalTime / 1000)) | 0 : + 0; + const stepsPerSecond = stepThreadsInnerFrame ? + (stepThreadsInnerFrame.executions / + (stepThreadsInnerFrame.totalTime / 1000)) | 0 : 0; + const compareResultFrames = ( + compareResult && compareResult.frames ? + compareResult.frames : + [] + ); + const blockFunctionCompareFrame = compareResultFrames + .find(frame => frame.name === 'blockFunction'); + const stepThreadsInnerCompareFrame = compareResultFrames + .find(frame => frame.name === 'Sequencer.stepThreads#inner'); + + const compareBlocksPerSecond = blockFunctionCompareFrame ? + (blockFunctionCompareFrame.executions / + (stepThreadsInnerCompareFrame.totalTime / 1000)) | 0 : + 0; + const compareStepsPerSecond = stepThreadsInnerCompareFrame ? + (stepThreadsInnerCompareFrame.executions / + (stepThreadsInnerCompareFrame.totalTime / 1000)) | 0 : + 0; + + const statusName = viewNames[newResult.status]; + + this.dom.className = `result-view ${ + viewNames[newResult.status].toLowerCase() + }`; + this.dom.onclick = this.act.bind(this); + let url = `index.html#${benchmarkUrlArgs(newResult.fixture)}`; + if (newResult.status === BENCH_STATUS.COMPLETE) { + url = `index.html#view/${btoa(JSON.stringify(newResult))}`; + } + let compareUrl = url; + if (compareResult && compareResult) { + compareUrl = + `index.html#view/${btoa(JSON.stringify(compareResult))}`; + } + let compareHTML = ''; + if (stepThreadsInnerFrame && stepThreadsInnerCompareFrame) { + compareHTML = ` +
+
${compareStepsPerSecond}
+
${compareBlocksPerSecond}
+
+
`; + } this.dom.innerHTML = ` - (${newResult.fixture.warmUpTime / 1000}s - ${newResult.fixture.recordingTime / 1000}s)
- ${blockFunctionFrame ? `${blocksPerSecond} blocks/s` : viewNames[newResult.status]} +
${stepThreadsInnerFrame ? `steps/s` : ''}
+
${blockFunctionFrame ? `blocks/s` : statusName}
+
+ +
+
${stepThreadsInnerFrame ? `${stepsPerSecond}` : ''}
+
${blockFunctionFrame ? `${blocksPerSecond}` : ''}
+
+
+ ${compareHTML} +
+ Run for ${newResult.fixture.recordingTime / 1000} seconds after + ${newResult.fixture.warmUpTime / 1000} seconds
`; @@ -279,15 +397,18 @@ class BenchResultView { class BenchSuiteResultView { constructor ({runner}) { + const {suite, util} = runner; + this.runner = runner; - this.suite = runner.suite; + this.suite = suite; this.views = {}; this.dom = document.createElement('div'); - const {suite} = runner; for (const fixture of suite.fixtures) { - this.views[fixture.id] = new BenchResultView({result: new BenchResult({fixture})}); - this.dom.appendChild(this.views[fixture.id].render().dom); + this.views[fixture.id] = new BenchResultView({ + result: new BenchResult({fixture}), + benchUtil: util + }); } suite.on('result', result => { @@ -296,12 +417,93 @@ class BenchSuiteResultView { } render () { + this.dom.innerHTML = `
+ Project ID +
+
steps per second
+
blocks per second
+
+
Description
+
+ + `; + + for (const fixture of this.suite.fixtures) { + this.dom.appendChild(this.views[fixture.id].render().dom); + } + return this; } } +let suite; +let suiteView; + +window.upload = function (_this) { + if (!_this.files.length) { + return; + } + const reader = new FileReader(); + reader.onload = function () { + const report = JSON.parse(reader.result); + Object.values(suiteView.views) + .forEach(view => { + const sameFixture = report.results.find(result => ( + result.fixture.projectId === + view.result.fixture.projectId && + result.fixture.warmUpTime === + view.result.fixture.warmUpTime && + result.fixture.recordingTime === + view.result.fixture.recordingTime + )); + + if (sameFixture) { + if ( + view.result && view.result.frames && + view.result.frames.length > 0 + ) { + view.render(view.result, sameFixture); + } else { + view.compare = sameFixture; + } + } + }); + }; + reader.readAsText(_this.files[0]); +}; + +window.download = function (_this) { + const blob = new Blob([JSON.stringify({ + meta: { + source: 'Scratch VM Benchmark Suite', + version: 1 + }, + results: Object.values(suiteView.views) + .map(view => view.result) + .filter(view => view.status === BENCH_STATUS.COMPLETE) + })], {type: 'application/json'}); + + _this.download = 'scratch-vm-benchmark.json'; + _this.href = URL.createObjectURL(blob); +}; + window.onload = function () { - const suite = new BenchSuite(); + suite = new BenchSuite(); suite.add(new BenchFixture({ projectId: 130041250, @@ -375,11 +577,24 @@ window.onload = function () { recordingTime: 5000 })); + suite.add(new BenchFixture({ + projectId: 187694931, + warmUpTime: 0, + recordingTime: 5000 + })); + + suite.add(new BenchFixture({ + projectId: 187694931, + warmUpTime: 5000, + recordingTime: 5000 + })); + const frame = document.getElementsByTagName('iframe')[0]; const runner = new BenchRunner({frame, suite}); - const resultsView = new BenchSuiteResultView({runner}); + const resultsView = suiteView = new BenchSuiteResultView({runner}).render(); - document.getElementsByClassName('suite-results')[0].appendChild(resultsView.dom); + document.getElementsByClassName('suite-results')[0] + .appendChild(resultsView.dom); runner.run(); }; From 4778ab8d4f00c2dc439c5c7980261bd237e247ec Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Mon, 22 Jan 2018 10:15:41 -0500 Subject: [PATCH 271/272] Fix music extension asset loading on safari --- src/extensions/scratch3_music/index.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index 0e14a2150..bbec66a47 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -97,10 +97,23 @@ class Scratch3MusicBlocks { _loadSound (fileName, index, bufferArray) { if (!this.runtime.storage) return; if (!this.runtime.audioEngine) return; + if (!this.runtime.audioEngine.audioContext) return; return this.runtime.storage.load(this.runtime.storage.AssetType.Sound, fileName, 'mp3') - .then(soundAsset => - this.runtime.audioEngine.audioContext.decodeAudioData(soundAsset.data.buffer) - ) + .then(soundAsset => { + const context = this.runtime.audioEngine.audioContext; + // Check for newer promise-based API + if (context.decodeAudioData.length === 1) { + return context.decodeAudioData(soundAsset.data.buffer); + } else { // eslint-disable no-else-return + // Fall back to callback API + return new Promise((resolve, reject) => + context.decodeAudioData(soundAsset.data.buffer, + buffer => resolve(buffer), + error => reject(error) + ) + ); + } + }) .then(buffer => { bufferArray[index] = buffer; }); From 9eaf67b50411bb7c895e714226bb943e01e08164 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Mon, 22 Jan 2018 10:27:16 -0500 Subject: [PATCH 272/272] Fix eslint-disable-line --- src/extensions/scratch3_music/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index bbec66a47..6202b2ceb 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -104,7 +104,7 @@ class Scratch3MusicBlocks { // Check for newer promise-based API if (context.decodeAudioData.length === 1) { return context.decodeAudioData(soundAsset.data.buffer); - } else { // eslint-disable no-else-return + } else { // eslint-disable-line no-else-return // Fall back to callback API return new Promise((resolve, reject) => context.decodeAudioData(soundAsset.data.buffer,