Last active
July 6, 2019 08:55
-
-
Save chaidhat/47e72152c248570bb61da72c093a0234 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const ArgumentType = require('../../extension-support/argument-type'); | |
const BlockType = require('../../extension-support/block-type'); | |
const Cast = require('../../util/cast'); | |
const log = require('../../util/log'); | |
const nets = require('nets'); | |
const languageNames = require('scratch-translate-extension-languages'); | |
const formatMessage = require('format-message'); | |
/** | |
* Icon svg to be displayed in the blocks category menu, encoded as a data URI. | |
* @type {string} | |
*/ | |
// eslint-disable-next-line max-len | |
const menuIconURI = 'data:image/png;base64,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'; | |
/** | |
* 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 blockIconURI = 'data:image/png;base64,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'; | |
const blockIconURI = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHN0eWxlPi5zdDJ7ZmlsbDpyZWR9LnN0M3tmaWxsOiNlMGUwZTB9LnN0NHtmaWxsOm5vbmU7c3Ryb2tlOiM2NjY7c3Ryb2tlLXdpZHRoOi41O3N0cm9rZS1taXRlcmxpbWl0OjEwfTwvc3R5bGU+PHBhdGggZD0iTTM1IDI4SDVhMSAxIDAgMCAxLTEtMVYxMmMwLS42LjQtMSAxLTFoMzBjLjUgMCAxIC40IDEgMXYxNWMwIC41LS41IDEtMSAxeiIgZmlsbD0iI2ZmZiIgaWQ9IkxheWVyXzYiLz48ZyBpZD0iTGF5ZXJfNCI+PHBhdGggY2xhc3M9InN0MiIgZD0iTTQgMjVoMzJ2Mi43SDR6TTEzIDI0aC0yLjJhMSAxIDAgMCAxLTEtMXYtOS43YzAtLjYuNC0xIDEtMUgxM2MuNiAwIDEgLjQgMSAxVjIzYzAgLjYtLjUgMS0xIDF6Ii8+PHBhdGggY2xhc3M9InN0MiIgZD0iTTYuMSAxOS4zdi0yLjJjMC0uNS40LTEgMS0xaDkuN2MuNSAwIDEgLjUgMSAxdjIuMmMwIC41LS41IDEtMSAxSDcuMWExIDEgMCAwIDEtMS0xeiIvPjxjaXJjbGUgY2xhc3M9InN0MiIgY3g9IjIyLjgiIGN5PSIxOC4yIiByPSIzLjQiLz48Y2lyY2xlIGNsYXNzPSJzdDIiIGN4PSIzMC42IiBjeT0iMTguMiIgcj0iMy40Ii8+PHBhdGggY2xhc3M9InN0MiIgZD0iTTQuMiAyN2gzMS45di43SDQuMnoiLz48L2c+PGcgaWQ9IkxheWVyXzUiPjxjaXJjbGUgY2xhc3M9InN0MyIgY3g9IjIyLjgiIGN5PSIxOC4yIiByPSIyLjMiLz48Y2lyY2xlIGNsYXNzPSJzdDMiIGN4PSIzMC42IiBjeT0iMTguMiIgcj0iMi4zIi8+PHBhdGggY2xhc3M9InN0MyIgZD0iTTEyLjUgMjIuOWgtMS4yYy0uMyAwLS41LS4yLS41LS41VjE0YzAtLjMuMi0uNS41LS41aDEuMmMuMyAwIC41LjIuNS41djguNGMwIC4zLS4yLjUtLjUuNXoiLz48cGF0aCBjbGFzcz0ic3QzIiBkPSJNNy4yIDE4Ljd2LTEuMmMwLS4zLjItLjUuNS0uNWg4LjRjLjMgMCAuNS4yLjUuNXYxLjJjMCAuMy0uMi41LS41LjVINy43Yy0uMyAwLS41LS4yLS41LS41ek00IDI2aDMydjJINHoiLz48L2c+PGcgaWQ9IkxheWVyXzMiPjxwYXRoIGNsYXNzPSJzdDQiIGQ9Ik0zNS4yIDI3LjlINC44YTEgMSAwIDAgMS0xLTFWMTIuMWMwLS42LjUtMSAxLTFoMzAuNWMuNSAwIDEgLjQgMSAxVjI3YTEgMSAwIDAgMS0xLjEuOXoiLz48cGF0aCBjbGFzcz0ic3Q0IiBkPSJNMzUuMiAyNy45SDQuOGExIDEgMCAwIDEtMS0xVjEyLjFjMC0uNi41LTEgMS0xaDMwLjVjLjUgMCAxIC40IDEgMVYyN2ExIDEgMCAwIDEtMS4xLjl6Ii8+PC9nPjwvc3ZnPg=='; | |
//const docsURI: 'https://translate-service.scratch.mit.edu/'; | |
/** | |
* The url of the translate server. | |
* @type {string} | |
*/ | |
const serverURL = 'https://translate-service.scratch.mit.edu/'; | |
/** | |
* How long to wait in ms before timing out requests to translate server. | |
* @type {int} | |
*/ | |
const serverTimeoutMs = 10000; // 10 seconds (chosen arbitrarily). | |
/** | |
* Class for the translate block in Scratch 3.0. | |
* @constructor | |
*/ | |
class Scratch3SOOP { | |
constructor (runtime, util) { | |
this.runtime = runtime; | |
this.util = util; | |
this._a = 0; | |
this._funcs = {}; | |
this._funcsparam = {}; | |
this.debug = "all good"; | |
this.debugerrorc = 0; | |
//[function_expecting, return value] | |
this._retFunctionExpecting = {}; | |
this._retFunctionExpectingNum = 0; | |
this._retValue = "null"; | |
this._structure = {}; | |
this._giveDir = false; | |
this._altFunc = {}; | |
this._testFunc = false; | |
this._scope = ""; | |
this._tempscope = {}; | |
this._tempscopenum = 0; | |
this._funcscope = ""; | |
this._tempfuncscope = {}; | |
this._tempfuncscopenum = 0; | |
} | |
/** | |
* The key to load & store a target's translate state. | |
* @return {string} The key. | |
*/ | |
static get STATE_KEY () { | |
return 'Scratch.translate'; | |
} | |
/** | |
* @returns {object} metadata for this extension and its blocks. | |
*/ | |
getInfo () { | |
this._supportedLanguages = this._getSupportedLanguages(this.getViewerLanguageCode()); | |
this._randomLanguageCode = this._supportedLanguages[ | |
Math.floor(Math.random() * this._supportedLanguages.length)].value; | |
return { | |
id: 'translate', | |
name: formatMessage({ | |
id: 'translate.categoryName', | |
default: 'OOP', | |
description: 'Name of extension that adds translate blocks' | |
}), | |
color1: '#8B4200', | |
color2: '#7B3200', | |
color3: '#CCCCCC', | |
docsURI: 'https://translate-service.scratch.mit.edu/', | |
//blockIconURI: blockIconURI, | |
//menuIconURI: menuIconURI, | |
blocks: [ | |
{ | |
opcode: 'clas', | |
text: formatMessage({ | |
id: 'translate.clas', | |
default: 'class [CLASSNAME]', | |
description: 'the languge of the project viewer' | |
}), | |
blockType: BlockType.REPORTER, | |
arguments: { | |
CLASSNAME: { | |
type: ArgumentType.STRING, | |
defaultValue: formatMessage({ | |
id: 'translate.clas.name', | |
default: "Fruit", | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
}, | |
}, | |
{ | |
opcode: 'clasConstructor', | |
text: formatMessage({ | |
id: 'translate.clasConstructor', | |
default: 'class [CLASSNAME]. [VALUE]', | |
description: 'the languge of the project viewer' | |
}), | |
blockType: BlockType.REPORTER, | |
arguments: { | |
CLASSNAME: { | |
type: ArgumentType.STRING, | |
defaultValue: formatMessage({ | |
id: 'translate.clasConstructor.name', | |
default: "Fruit", | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
VALUE: { | |
//type: ArgumentType.STRING, | |
defaultValue: formatMessage({ | |
id: 'translate.clasConstructor.value', | |
default: 1, | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
}, | |
}, | |
{ | |
opcode: 'prop', | |
text: formatMessage({ | |
id: 'translate.scopeableVar', | |
default: 'property [PROPNAME]', | |
description: 'the languge of the project viewer' | |
}), | |
blockType: BlockType.REPORTER, | |
arguments: { | |
PROPNAME: { | |
type: ArgumentType.STRING, | |
defaultValue: formatMessage({ | |
id: 'translate.prop.name', | |
default: "apple", | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
}, | |
}, | |
'---', | |
{ | |
opcode: 'set', | |
text: formatMessage({ | |
id: 'translate.set', | |
default: 'set object [NAME] to [VALUE]', | |
description: 'the languge of the project viewer' | |
}), | |
blockType: BlockType.COMMAND, | |
arguments: { | |
NAME: { | |
//type: ArgumentType.STRING, | |
defaultValue: formatMessage({ | |
id: 'translate.set.name', | |
default: 1, | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
VALUE: { | |
type: ArgumentType.STRING, | |
defaultValue: formatMessage({ | |
id: 'translate.set.value', | |
default: 1, | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
}, | |
}, | |
'---', | |
{ | |
opcode: 'funcref', | |
text: formatMessage({ | |
id: 'translate.funcref', | |
default: 'function [FUNCNAME]', | |
description: 'the languge of the project viewer' | |
}), | |
blockType: BlockType.REPORTER, | |
arguments: { | |
FUNCNAME: { | |
type: ArgumentType.STRING, | |
defaultValue: formatMessage({ | |
id: 'translate.funcref.name', | |
default: "foo", | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
}, | |
}, | |
{ | |
opcode: 'callfunc', | |
text: formatMessage({ | |
id: 'translate.callfunc', | |
default: 'call [NAME] <-- [PARAM]', | |
description: 'the languge of the project viewer' | |
}), | |
blockType: BlockType.REPORTER, | |
arguments: { | |
NAME: { | |
//type: ArgumentType.STRING, | |
defaultValue: formatMessage({ | |
id: 'translate.callfunc.name', | |
default: "foo", | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
PARAM: { | |
//type: ArgumentType.STRING, | |
defaultValue: formatMessage({ | |
id: 'translate.callfunc.param', | |
default: 1, | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
}, | |
}, | |
'---', | |
{ | |
opcode: 'func', | |
text: formatMessage({ | |
id: 'translate.func', | |
default: '[SCOPE] :: function [NAME] <-- [PARAM]', | |
description: 'the languge of the project viewer' | |
}), | |
blockType: BlockType.HAT, | |
arguments: { | |
SCOPE: { | |
//type: ArgumentType.STRING, | |
defaultValue: formatMessage({ | |
id: 'translate.func.scope', | |
default: 1, | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
NAME: { | |
type: ArgumentType.STRING, | |
defaultValue: formatMessage({ | |
id: 'translate.func.name', | |
default: "foo", | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
PARAM: { | |
//type: ArgumentType.STRING, | |
defaultValue: formatMessage({ | |
id: 'translate.func.param', | |
default: 1, | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
}, | |
}, | |
{ | |
opcode: 'thi', | |
text: formatMessage({ | |
id: 'translate.thi', | |
default: 'this class . [PARAM]', | |
description: 'the languge of the project viewer' | |
}), | |
blockType: BlockType.REPORTER, | |
arguments: { | |
PARAM: { | |
//type: ArgumentType.STRING, | |
defaultValue: formatMessage({ | |
id: 'translate.thi.param', | |
default: 1, | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
}, | |
}, | |
{ | |
opcode: 'ret', | |
text: formatMessage({ | |
id: 'translate.ret', | |
default: 'function return [VALUE]-->', | |
description: 'the languge of the project viewer' | |
}), | |
isTerminal: true, | |
blockType: BlockType.COMMAND, | |
arguments: { | |
VALUE: { | |
type: ArgumentType.STRING, | |
defaultValue: formatMessage({ | |
id: 'translate.ret.value', | |
default: "bar", | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
}, | |
}, | |
'---', | |
{ | |
opcode: 'tuple', | |
text: formatMessage({ | |
id: 'translate.tuple', | |
default: '[VALUE1] , [VALUE2]', | |
description: 'the languge of the project viewer' | |
}), | |
blockType: BlockType.REPORTER, | |
arguments: { | |
VALUE1: { | |
type: ArgumentType.STRING, | |
defaultValue: formatMessage({ | |
id: 'translate.tuple.value1', | |
default: "", | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
VALUE2: { | |
type: ArgumentType.STRING, | |
defaultValue: formatMessage({ | |
id: 'translate.tuple.value2', | |
default: "", | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
}, | |
}, | |
{ | |
opcode: 'gettuple', | |
text: formatMessage({ | |
id: 'translate.gettuple', | |
default: 'get item [NUMBER] of tuple [TUPLE]', | |
description: 'the languge of the project viewer' | |
}), | |
blockType: BlockType.REPORTER, | |
arguments: { | |
NUMBER: { | |
type: ArgumentType.NUMBER, | |
defaultValue: formatMessage({ | |
id: 'translate.gettuple.number', | |
default: 1, | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
TUPLE: { | |
//type: ArgumentType.STRING, | |
defaultValue: formatMessage({ | |
id: 'translate.gettuple.tuple', | |
default: 1, | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
}, | |
}, | |
'---', | |
{ | |
opcode: 'scop', | |
text: formatMessage({ | |
id: 'translate.scop', | |
default: 'using class [CLASSNAME]', | |
description: 'the languge of the project viewer' | |
}), | |
blockType: BlockType.CONDITIONAL, | |
arguments: { | |
CLASSNAME: { | |
defaultValue: formatMessage({ | |
id: 'translate.scop.classname', | |
default: 1, | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
}, | |
}, | |
'---', | |
{ | |
opcode: 'c', | |
text: formatMessage({ | |
id: 'translate.c', | |
default: 'debug.reset func [NAME]', | |
description: 'the languge of the project viewer' | |
}), | |
blockType: BlockType.COMMAND, | |
arguments: { | |
NAME: { | |
type: ArgumentType.STRING, | |
defaultValue: formatMessage({ | |
id: 'translate.debug.name', | |
default: 1, | |
description: 'hello: the default text to translate' | |
}) | |
}, | |
}, | |
}, | |
{ | |
opcode: 'dl', | |
text: formatMessage({ | |
id: 'translate.dl', | |
default: 'debug.log', | |
description: 'the languge of the project viewer' | |
}), | |
blockType: BlockType.REPORTER, | |
arguments: { | |
}, | |
}, | |
{ | |
opcode: 'de', | |
text: formatMessage({ | |
id: 'translate.de', | |
default: 'debug.error?', | |
description: 'the languge of the project viewer' | |
}), | |
blockType: BlockType.BOOLEAN, | |
arguments: { | |
}, | |
}, | |
], | |
menus: { | |
languages: { | |
acceptReporters: true, | |
items: this._supportedLanguages | |
} | |
} | |
}; | |
} | |
func({SCOPE,NAME,PARAM}) | |
{ | |
if (SCOPE) | |
NAME = SCOPE.substring(0,SCOPE.length - 1) + "," + NAME; | |
if (this._funcs[NAME] === "true") | |
{ | |
this._tempscope[this._tempscopenum] = this._scope; | |
this._tempscopenum++; | |
this._tempfuncscope[this._tempfuncscopenum] = this._funcscope; | |
this._tempfuncscopenum++; | |
this._scope = "funcclass " + NAME + ","; | |
if (SCOPE) | |
this._funcscope = SCOPE.substring(0,SCOPE.length - 1) + ","; | |
this._funcs[NAME] = "standtrue"; | |
if (this._testFunc) | |
{ | |
return false; | |
} | |
return true; | |
} | |
else | |
{ | |
if (this._funcs[NAME] === "standfalse") | |
{ | |
this._funcs[NAME] = "false"; | |
} | |
return false; | |
} | |
} | |
callfunc(args,util) | |
{ | |
var a = args.NAME.substring(args.NAME.length - 1, args.NAME.length); | |
if (!(a === "]")) | |
{ | |
this.debug = "ERROR NO" + this.debugerrorc +": in function " + args.NAME + ", " + "Code: 1. not a function! Proper usage: (call ( (function (FOO)) ) <-- ( )). Put only (function ( )) block into it!"; | |
return this.debug; | |
} | |
else | |
{ | |
args.NAME = args.NAME.substring(0, args.NAME.length - 1); | |
} | |
if (this._retFunctionExpectingNum < -10) | |
{ | |
this.debug = "ERROR NO" + this.debugerrorc +": in function " + args.NAME + ", " + "Code: 2. this._retFunctionExpectingNum < 10, please reset errors."; | |
return this.debug; | |
} | |
if (util.stackTimerNeedsInit()) { | |
var j = 0; | |
for (var i = -10; i < this._retFunctionExpectingNum; i++) | |
{ | |
if (this._retFunctionExpecting[i] === args.NAME) | |
{ | |
j++; | |
} | |
} | |
if (j > 0) | |
{ | |
this.debug = "ERROR NO" + this.debugerrorc + ": in function " + args.NAME + ", " + "Code: 3. no recursion allowed. I'm sorry."; | |
return this.debug; | |
} | |
if (this._funcs[args.NAME] != "true" && this._funcs[args.NAME] != "standfalse" && this._funcs[args.NAME] != "standtrue") | |
{ | |
/* | |
/ 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; | |
} | |
} | |
// We've */ | |
const efen = this._retFunctionExpectingNum; | |
this._funcs[args.NAME] = "true"; | |
this._funcsparam[args.NAME] = args.PARAM; | |
this._retFunctionExpectingNum++; | |
this._retFunctionExpecting[efen] = args.NAME; | |
util.a = efen; | |
util.time = 0; | |
util.startStackTimer(100); | |
/*let efen = this._retFunctionExpectingNum; | |
this._retFunctionExpectingNum++; | |
for (var i = 0; i < 10; i++) | |
{ | |
if (this._retFunctionExpectingNum === efen) | |
{ | |
return this._retValue; | |
} | |
}*/ | |
this.runtime.requestRedraw(); | |
util.yield(); | |
} | |
else | |
{ | |
util.yield(); | |
} | |
} | |
else | |
{ | |
if (this._retFunctionExpectingNum === util.a) { | |
this._retFunctionExpecting[util.a] = ""; | |
this._funcs[args.NAME] = "standfalse"; | |
return this._retValue; | |
} else { | |
util.time++; | |
if (!(this._funcs[args.NAME] === "standtrue") && util.stackTimerFinished()) | |
{ | |
this._funcs[args.NAME] = "false"; | |
this._retFunctionExpectingNum--; | |
this.debug = "ERROR NO" + this.debugerrorc + ": in function " + args.NAME + ", " + "Code: 4. Is there actually a function hat declaring this function?"; | |
return this.debug; | |
} | |
util.yield(); | |
} | |
} | |
} | |
ret({VALUE}) | |
{ | |
this._retValue = VALUE; | |
this._retFunctionExpectingNum--; | |
this._tempscopenum--; | |
this._scope = this._tempscope[this._tempscopenum]; | |
return; | |
} | |
c(args,util) | |
{ | |
for (var i = -10; i < this._retFunctionExpectingNum + 1; i++) | |
{ | |
this._retFunctionExpecting[i] = ""; | |
} | |
this._retFunctionExpectingNum = 0; | |
this._tempscopenum = 0; | |
this._funcs[args.NAME] = "false"; | |
this._scope = ""; | |
this.debug = "all good"; | |
} | |
clas(args, util) | |
{ | |
this._giveDir = ">" + args.CLASSNAME + "["; | |
//this.debug = (this._scope + this._giveDir); | |
return ">" + args.CLASSNAME + "["; | |
} | |
clasConstructor(args, util) | |
{ | |
if (args.VALUE) | |
{ | |
} | |
else | |
{ | |
this._giveDir = ">" + args.CLASSNAME + "["; | |
//this.debug = (this._scope + this._giveDir); | |
return ">" + args.CLASSNAME + "["; | |
} | |
this._giveDir = ">" + args.CLASSNAME + "," + this._giveDir; | |
//this.debug = (this._scope + this._giveDir); | |
var a = (this._scope + this._giveDir).substring((this._scope + this._giveDir).length - 1, (this._scope + this._giveDir).length); | |
if (a === "[" || a === "]") | |
{ | |
// class | |
return (this._scope + this._giveDir); | |
} | |
if (this._structure[(this._scope + this._giveDir)]) | |
{ | |
// property | |
if (this._structure[(this._scope + this._giveDir)].substring(0,1) === "*") | |
{ | |
return this._structure[(this._scope + this._giveDir)].substring(1,this._structure[(this._scope + this._giveDir)].length); | |
} | |
else | |
{ | |
return this._structure[(this._scope + this._giveDir)]; | |
} | |
} | |
else | |
{ | |
// nullptr | |
return "null"; | |
} | |
} | |
prop(args, util) | |
{ | |
this._giveDir = args.PROPNAME; | |
//this.debug = (this._scope + this._giveDir); | |
if (this._structure[(this._scope + this._giveDir)]) | |
{ | |
// property | |
if (this._structure[(this._scope + this._giveDir)].substring(0,1) === "*") | |
{ | |
return this._structure[(this._scope + this._giveDir)].substring(1,this._structure[(this._scope + this._giveDir)].length); | |
} | |
else | |
{ | |
return this._structure[(this._scope + this._giveDir)]; | |
} | |
} | |
else | |
{ | |
// nullptr | |
return "null"; | |
} | |
} | |
thi(args) | |
{ | |
if (args.VALUE) | |
{ | |
} | |
else | |
{ | |
this._giveDir = ">" + args.CLASSNAME + "["; | |
//this.debug = (this._scope + this._giveDir); | |
return ">" + args.CLASSNAME + "["; | |
} | |
this._giveDir = ">" + args.CLASSNAME + "," + this._giveDir; | |
//this.debug = (this._scope + this._giveDir); | |
var a = (this._scope + this._giveDir).substring((this._funcscope + this._giveDir).length - 1, (this._scope + this._giveDir).length); | |
if (a === "[" || a === "]") | |
{ | |
// class | |
return (this._funcscope + this._giveDir); | |
} | |
if (this._structure[(this._funcscope + this._giveDir)]) | |
{ | |
// property | |
if (this._structure[(this._funcscope + this._giveDir)].substring(0,1) === "*") | |
{ | |
return this._structure[(this._funcscope + this._giveDir)].substring(1,this._structure[(this._funcscope + this._giveDir)].length); | |
} | |
else | |
{ | |
return this._structure[(this._funcscope + this._giveDir)]; | |
} | |
} | |
else | |
{ | |
// nullptr | |
return "null"; | |
} | |
} | |
funcref(args, util) | |
{ | |
this._giveDir = args.FUNCNAME + "]"; | |
this.debug = (this._scope + this._giveDir); | |
return (this._scope + this._giveDir); | |
} | |
dl() | |
{ | |
return this._funcscope; | |
} | |
de() | |
{ | |
if (this.debug === "all good") | |
{ | |
return false; | |
} | |
else | |
{ | |
return true; | |
} | |
} | |
set(args, util) | |
{ | |
//this.debug = "set " + (this._scope + this._giveDir) + ", "; | |
var de = "" | |
var a = getBranch((this._scope + this._giveDir), false); | |
var b = getBranch((this._scope + this._giveDir), true); | |
var c = a[b-1]; | |
if (!this._structure[(this._scope + this._giveDir)]) | |
{ | |
//this.debug = "a"; | |
for (var j = 1; j < b; j++) | |
{ | |
var d = a[0]; | |
for (var i = 1; i < j; i++) | |
{ | |
d = d + "," + a[i]; | |
} | |
var prefix = ""; | |
// d is the indexer | |
if (j < b - 1) | |
{ | |
//prefix = ">"; | |
} | |
if (!this._structure[d]) | |
{ | |
this._structure[d] = prefix + a[j]; | |
} | |
else | |
{ | |
this._structure[d] = this._structure[d] + "," + prefix + a[j]; | |
} | |
de = de + "::" + d + " to " + this._structure[d]; | |
} | |
} | |
if ((this._scope + this._giveDir).substring((this._scope + this._giveDir).length - 1, (this._scope + this._giveDir).length) === "[") | |
{ | |
// to make sure it exists, we add "*" to the beginning of it | |
//this._structure[(this._scope + this._giveDir)] = "*" + args.VALUE; | |
var name = args.NAME.substring(0,args.NAME.length - 1); | |
var val = args.VALUE.substring(0,args.VALUE.length - 1); | |
if (val) | |
{ | |
// notice val and name are swapped in the CORRECT order | |
this.debug = val; | |
this._structure = dupeBranch(this._structure, val, name); | |
} | |
else | |
{ | |
this.debug = "ERROR NO" + this.debugerrorc +": Code: 3. Value to be copied is missing."; | |
} | |
} | |
else if ((this._scope + this._giveDir).substring((this._scope + this._giveDir).length - 1, (this._scope + this._giveDir).length) === "]") | |
{ | |
this._structure[(this._scope + this._giveDir)] | |
} | |
else | |
{ | |
// to make sure it exists, we add "*" to the beginning of it | |
this._structure[(this._scope + this._giveDir)] = "*" + args.VALUE; | |
this.debug = de; | |
} | |
} | |
tuple(args) | |
{ | |
return args.VALUE1 + "," + args.VALUE2; | |
} | |
gettuple(args) | |
{ | |
var a = getBranch(args.TUPLE, false); | |
return a[args.NUMBER - 1]; | |
} | |
scop(args, util) | |
{ | |
if (typeof util.stackFrame.loopCounter === 'undefined') { | |
util.stackFrame.loopCounter = 1; | |
} | |
if (util.stackFrame.loopCounter > 0) { | |
if ((this._scope + this._giveDir).substring((this._scope + this._giveDir).length - 1, (this._scope + this._giveDir).length) === "[") | |
{ | |
if (this._scope === "") | |
{ | |
this._scope = args.CLASSNAME.substring(0,args.CLASSNAME.length - 1) + ","; | |
} | |
else | |
{ | |
this._scope = this._scope + args.CLASSNAME.substring(0,args.CLASSNAME.length - 1) + ","; | |
} | |
util.stackFrame.loopCounter--; | |
util.startBranch(1, true); | |
} | |
else | |
{ | |
this.debug = "ERROR NO" + this.debugerrorc +": Code: 4. Input must be a class."; | |
} | |
} | |
else | |
{ | |
this._scope = this._scope.substring(0, this._scope.length - args.CLASSNAME.length) | |
; | |
} | |
} | |
/** | |
* Computes a list of language code and name pairs for the given language. | |
* @param {string} code The language code to get the list of language pairs | |
* @return {Array.<object.<string, string>>} An array of languge name and | |
* language code pairs. | |
* @private | |
*/ | |
_getSupportedLanguages (code) { | |
return languageNames.menuMap[code].map(entry => { | |
const obj = {text: entry.name, value: entry.code}; | |
return obj; | |
}); | |
} | |
/** | |
* Get the human readable language value for the reporter block. | |
* @return {string} the language name of the project viewer. | |
*/ | |
getViewerLanguage () { | |
this._viewerLanguageCode = this.getViewerLanguageCode(); | |
const names = languageNames.menuMap[this._viewerLanguageCode]; | |
let langNameObj = names.find(obj => obj.code === this._viewerLanguageCode); | |
// If we don't have a name entry yet, try looking it up via the Google langauge | |
// code instead of Scratch's (e.g. for es-419 we look up es to get espanol) | |
if (!langNameObj && languageNames.scratchToGoogleMap[this._viewerLanguageCode]) { | |
const lookupCode = languageNames.scratchToGoogleMap[this._viewerLanguageCode]; | |
langNameObj = names.find(obj => obj.code === lookupCode); | |
} | |
let langName = this._viewerLanguageCode; | |
if (langNameObj) { | |
langName = langNameObj.name; | |
} | |
return langName; | |
} | |
/** | |
* Get the viewer's language code. | |
* @return {string} the language code. | |
*/ | |
getViewerLanguageCode () { | |
const locale = formatMessage.setup().locale; | |
const viewerLanguages = [locale].concat(navigator.languages); | |
const languageKeys = Object.keys(languageNames.menuMap); | |
// Return the first entry in viewerLanguages that matches | |
// one of the available language keys. | |
const languageCode = viewerLanguages.reduce((acc, lang) => { | |
if (acc) { | |
return acc; | |
} | |
if (languageKeys.indexOf(lang.toLowerCase()) > -1) { | |
return lang; | |
} | |
return acc; | |
}, '') || 'en'; | |
return languageCode.toLowerCase(); | |
} | |
} | |
//structure = dupeBranch(structure); | |
function getBranch (dir, getB) | |
{ | |
var c = dir; | |
var a = {}; | |
var b = 0; | |
var m = 0; | |
for (var i = 0; i < c.length - 1; i++) | |
{ | |
if (c.substring(i,i+1) === ",") | |
{ | |
a[b] = c.substring(m, i); | |
b++; | |
m = i + 1; | |
} | |
} | |
a[b] = c.substring(m, i + 1); | |
b++; | |
if (getB) | |
{ | |
return b; | |
} | |
return a; | |
} | |
function dupeBranch (structure, dupeDir, newDir) | |
{ | |
var a = getBranch(structure[dupeDir], false); | |
var b = getBranch(structure[dupeDir], true); | |
for (var i = 0; i < b; i++){ | |
if (a[i].substring(0, 1) === ">") | |
{ | |
structure = dupeBranch (structure, dupeDir + "," + a[i], newDir + "," + a[i]) | |
} | |
if (i < 1) | |
{ | |
d = a[i]; | |
} | |
else | |
{ | |
d = d + "," + a[i]; | |
} | |
structure[newDir + "," + a[i]] = structure[dupeDir + "," + a[i]]; | |
} | |
structure[newDir] = d; | |
/* var s = structure; | |
var c = s[dupeDir] = "iads:yewuio:cxcv"; | |
var a = {}; | |
var b = 0; | |
var s = 0; | |
for (var i = 0; i < c.length - 1; i++) | |
{ | |
if (c.substring(i,i+1) === ",") | |
{ | |
a[b] = c.substring(s, i); | |
b++; | |
s = i + 1; | |
} | |
} | |
a[b] = c.substring(s, i + 1); | |
b++; | |
structure[newDir] = c; | |
for (var i = 0; i < b; b++) | |
{ | |
structure[newDir + "," + a[b]] = s[dupeDir + "," + a[b]]; | |
}*/ | |
/*this._structure["Fruit/apple/ripeness"] = 0; | |
this._structure["Fruit/apple/count"] = 0; | |
this._structure["Fruit/apple"] = "ripeness:count";*/ | |
return structure; | |
} | |
module.exports = Scratch3SOOP; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment