« get me outta code hell

begin the site! - scratchblocks-generator-3 - scratchblocks generator for projects made in 3.0
about summary refs log tree commit diff
path: root/index.js
diff options
context:
space:
mode:
authorFlorrie <towerofnix@gmail.com>2019-12-20 17:46:21 -0400
committerFlorrie <towerofnix@gmail.com>2019-12-20 17:46:21 -0400
commit6fe5b85f8ce201d618a9c7c175d7502c2ff8c395 (patch)
treeedbe264b31213d6ee2f5087507f4f1557f17864d /index.js
parent5ec73fd9d3a6018945464565fac5de9efe05466d (diff)
begin the site!
Diffstat (limited to 'index.js')
-rw-r--r--index.js445
1 files changed, 0 insertions, 445 deletions
diff --git a/index.js b/index.js
deleted file mode 100644
index b62db99..0000000
--- a/index.js
+++ /dev/null
@@ -1,445 +0,0 @@
-'use strict';
-
-const { Project } = require('./sb-edit');
-const fs = require('fs');
-const path = require('path');
-const util = require('util');
-
-const readFile = util.promisify(fs.readFile);
-
-// TODO: set prefix to \t
-function indent(string, prefix = '    ') {
-    return string.split('\n').map(l => prefix + l).join('\n');
-}
-
-function input(inp, target, flag = false) {
-    if (!inp) {
-        return '';
-    }
-    switch (inp.type) {
-        case 'number':
-        case 'angle':
-            return `(${inp.value})`;
-
-        case 'string':
-            return `[${inp.value}]`;
-
-        case 'variable':
-        case 'list':
-        case 'graphicEffect':
-        case 'rotationStyle':
-        case 'greaterThanMenu':
-        case 'stopMenu':
-        case 'dragModeMenu':
-        case 'propertyOfMenu':
-        case 'currentMenu':
-        case 'mathopMenu':
-        case 'frontBackMenu':
-        case 'forwardBackwardMenu':
-        case 'costumeNumberName':
-            return `[${inp.value} v]`;
-
-        case 'costume':
-        case 'sound':
-        case 'goToTarget':
-        case 'pointTowardsTarget':
-        case 'penColorParam':
-        case 'target':
-        case 'cloneTarget':
-        case 'touchingTarget':
-        case 'distanceToMenu':
-            return `(${inp.value} v)`;
-
-        case 'broadcast':
-        case 'backdrop':
-        case 'key':
-            if (flag) {
-                return `[${inp.value} v]`;
-            } else {
-                return `(${inp.value} v)`;
-            }
-
-        case 'color':
-            const hex = k => inp.value[k].toString(16).padStart(2, '0')
-            return `[#${hex('r') + hex('g') + hex('b')}]`;
-
-        case 'block':
-            if (flag) {
-                return '\n' + indent(blockToScratchblocks(inp.value, target)) + '\n';
-            } else {
-                return blockToScratchblocks(inp.value, target);
-            }
-
-        case 'blocks':
-            return '\n' + indent(blocksToScratchblocks(inp.value, target)) + '\n';
-
-        default:
-            return `\x1b[33m<${inp.type}>\x1b[0m`;
-    }
-}
-
-function blockToScratchblocks(block, target) {
-    if (!target) {
-        throw new Error('expected target');
-    }
-
-    const i = (key, ...args) => input(block.inputs[key], target, ...args);
-    const operator = op => `(${i('NUM1')} ${op} ${i('NUM2')})`;
-    const boolop = op => `<${i('OPERAND1')} ${op} ${i('OPERAND2')}>`;
-
-    switch (block.opcode) {
-
-            // motion ------------------------------------------------------ //
-        case 'motion_movesteps':
-            return `move ${i('STEPS')} steps`;
-        case 'motion_turnright':
-            return `turn cw ${i('DEGREES')} degrees`;
-        case 'motion_turnleft':
-            return `turn ccw ${i('DEGREES')} degrees`;
-        case 'motion_goto':
-            return `go to ${i('TO')}`;
-        case 'motion_gotoxy':
-            return `go to x: ${i('X')} y: ${i('Y')}`;
-        case `motion_glideto`:
-            return `glide ${i('SECS')} secs to ${i('TO')}`;
-        case `motion_glidesecstoxy`:
-            return `glide ${i('SECS')} secs to x: ${i('X')} y: ${i('Y')}`;
-        case 'motion_pointindirection':
-            return `point in direction ${i('DIRECTION')}`;
-        case 'motion_pointtowards':
-            return `point towards ${i('TOWARDS')}`;
-        case 'motion_changexby':
-            return `change x by ${i('DX')}`;
-        case 'motion_setx':
-            return `set x to ${i('X')}`;
-        case 'motion_changeyby':
-            return `change y by ${i('DY')}`;
-        case 'motion_sety':
-            return `set y to ${i('Y')}`;
-        case 'motion_ifonedgebounce':
-            return 'if on edge, bounce';
-        case 'motion_setrotationstyle':
-            return `set rotation style ${i('STYLE')}`;
-        case 'motion_xposition':
-            return '(x position)';
-        case 'motion_yposition':
-            return '(y position)';
-        case 'motion_direction':
-            return '(direction)';
-
-            // looks ------------------------------------------------------- //
-        case 'looks_sayforsecs':
-            return `say ${i('MESSAGE')} for ${i('SECS')} seconds`;
-        case 'looks_say':
-            return `say ${i('MESSAGE')}`;
-        case 'looks_thinkforsecs':
-            return `think ${i('MESSAGE')} for ${i('SECS')} seconds`;
-        case 'looks_think':
-            return `think ${i('MESSAGE')}`;
-        case 'looks_switchcostumeto':
-            return `switch costume to ${i('COSTUME')}`;
-        case 'looks_nextcostume':
-            return 'next costume';
-        case 'looks_switchbackdropto':
-            return `switch backdrop to ${i('BACKDROP')}`;
-        case 'looks_nextbackdrop':
-            return `next backdrop`;
-        case 'looks_changesizeby':
-            return `change size by ${i('CHANGE')}`;
-        case 'looks_setsizeto':
-            return `set size to ${i('SIZE')}%`;
-        case 'looks_changeeffectby':
-            return `change ${i('EFFECT')} effect by ${i('CHANGE')} :: looks`;
-        case 'looks_seteffectto':
-            return `set ${i('EFFECT')} effect to ${i('VALUE')} :: looks`;
-        case 'looks_cleargraphiceffects':
-            return 'clear graphic effects';
-        case 'looks_show':
-            return 'show';
-        case 'looks_hide':
-            return 'hide';
-        case 'looks_gotofrontback':
-            return `go to ${i('FRONT_BACK')} layer`;
-        case 'looks_goforwardbackwardlayers':
-            return `go ${i('FORWARD_BACKWARD')} ${i('NUM')} layers`;
-        case 'looks_costumenumbername':
-            return `(costume ${i('NUMBER_NAME')})`;
-        case 'looks_backdropnumbername':
-            return `(backdrop ${i('NUMBER_NAME')})`;
-        case 'looks_size':
-            return '(size)';
-        case 'looks_hideallsprites':
-            return 'hide all sprites :: looks';
-        case 'looks_switchbackdroptoandwait':
-            return `switch backdrop to ${i('BACKDROP')} and wait`;
-        case 'looks_changestretchby':
-            return `change stretch by ${i('CHANGE')} :: looks`;
-        case 'looks_setstretchto':
-            return `set stretch to ${i('STRETCH')} % :: looks`;
-
-            // sound ------------------------------------------------------- //
-        case 'sound_playuntildone':
-            return `play sound ${i('SOUND_MENU')} until done`;
-        case 'sound_play':
-            return `start sound ${i('SOUND_MENU')}`;
-        case 'sound_stopallsounds':
-            return 'stop all sounds';
-        case 'sound_changeeffectby':
-            return `change ${i('EFFECT')} effect by ${i('VALUE')} :: sound`;
-        case 'sound_seteffectto':
-            return `set ${i('EFFECT')} effect to ${i('VALUE')} :: sound`;
-        case 'sound_cleareffects':
-            return 'clear sound effects';
-        case 'sound_changevolumeby':
-            return `change volume by ${i('VOLUME')}`;
-        case 'sound_setvolumeto':
-            return `set volume to ${i('VOLUME')} %`;
-        case 'sound_volume':
-            return '(volume)';
-
-            // events ------------------------------------------------------ //
-        case 'event_whenflagclicked':
-            return 'when green flag clicked';
-        case 'event_whenkeypressed':
-            return `when ${i('KEY_OPTION', true)} key pressed`;
-        case 'event_whenthisspriteclicked':
-            return 'when this sprite clicked';
-        case 'event_whenbackdropswitchesto':
-            return `when backdrop switches to ${i('BACKDROP', true)}`;
-        case 'event_whengreaterthan':
-            return `when ${i('WHENGREATERTHANMENU')} > ${i('VALUE')}`;
-        case 'event_whenbroadcastreceived':
-            return `when I receive ${i('BROADCAST_OPTION', true)}`;
-        case 'event_broadcast':
-            return `broadcast ${i('BROADCAST_INPUT')}`;
-        case 'event_broadcastandwait':
-            return `broadcast ${i('BROADCAST_INPUT')} and wait`;
-
-            // control ----------------------------------------------------- //
-        case 'control_wait':
-            return `wait ${i('DURATION')} seconds`;
-        case 'control_repeat':
-            return `repeat ${i('TIMES')}` + i('SUBSTACK', true) + 'end';
-        case 'control_forever':
-            return 'forever' + i('SUBSTACK', true) + 'end';
-        case 'control_if':
-            return `if ${i('CONDITION') || '<>'} then` + i('SUBSTACK', true) + 'end';
-        case 'control_if_else':
-            return `if ${i('CONDITION') || '<>'} then` + i('SUBSTACK', true) + 'else' + i('SUBSTACK2', true) + 'end';
-        case 'control_wait_until':
-            return `wait until ${i('CONDITION') || '<>'}`;
-        case 'control_repeat_until':
-            return `repeat until ${i('CONDITION') || '<>'}` + i('SUBSTACK', true) + 'end';
-        case 'control_stop':
-            return `stop ${i('STOP_OPTION')}`;
-        case 'control_start_as_clone':
-            return 'when I start as a clone';
-        case 'control_create_clone_of':
-            return `create clone of ${i('CLONE_OPTION')}`;
-        case 'control_delete_this_clone':
-            return 'delete this clone';
-
-            // sensing ----------------------------------------------------- //
-        case 'sensing_touchingobject':
-            return `<touching ${i('TOUCHINGOBJECTMENU')} ?>`;
-        case 'sensing_touchingcolor':
-            return `<touching ${i('COLOR')} ?>`;
-        case 'sensing_coloristouchingcolor':
-            return `<${i('COLOR')} is touching ${i('COLOR2')} ?>`;
-        case 'sensing_distanceto':
-            return `(distance to ${i('DISTANCETOMENU')})`;
-        case 'sensing_askandwait':
-            return `ask ${i('QUESTION')} and wait`;
-        case 'sensing_answer':
-            return '(answer)';
-        case 'sensing_keypressed':
-            return `<key ${i('KEY_OPTION')} pressed?>`;
-        case 'sensing_mousedown':
-            return '<mouse down?>';
-        case 'sensing_mousex':
-            return '(mouse x)';
-        case 'sensing_mousey':
-            return '(mouse y)';
-        case 'sensing_setdragmode':
-            return `set drag mode ${i('DRAG_MODE')}`;
-        case 'sensing_loudness':
-            return '(loudness)';
-        case 'sensing_loud':
-            return '<loud? :: sensing>';
-        case 'sensing_timer':
-            return '(timer)';
-        case 'sensing_resettimer':
-            return 'reset timer';
-        case 'sensing_of':
-            return `(${i('PROPERTY')} of ${i('OBJECT')})`;
-        case 'sensing_current':
-            return `(current ${i('CURRENTMENU')})`;
-        case 'sensing_dayssince2000':
-            return '(days since 2000)';
-        case 'sensing_username':
-            return '(username)';
-        case 'sensing_userid':
-            return '(user id :: sensing)';
-
-            // operators --------------------------------------------------- //
-        case 'operator_add':
-            return operator('+');
-        case 'operator_subtract':
-            return operator('-');
-        case 'operator_multiply':
-            return operator('*');
-        case 'operator_divide':
-            return operator('/');
-        case 'operator_random':
-            return `(pick random ${i('FROM')} to ${i('TO')})`;
-        case 'operator_gt':
-            return boolop('>');
-        case 'operator_lt':
-            return boolop('<');
-        case 'operator_equals':
-            return boolop('=');
-        case 'operator_and':
-            return boolop('and');
-        case 'operator_or':
-            return boolop('or');
-        case 'operator_not':
-            return `<not ${i('OPERAND')}>`;
-        case 'operator_join':
-            return `(join ${i('STRING1')} ${i('STRING2')})`;
-        case 'operator_letter_of':
-            return `(letter ${i('LETTER')} of ${i('STRING')}`;
-        case 'operator_length':
-            return `(length of ${i('STRING')}`;
-        case 'operator_contains':
-            return `<${i('STRING1')} contains ${i('STRING2')} ? :: operators>`;
-        case 'operator_mod':
-            return operator('mod');
-        case 'operator_round':
-            return `(round ${i('NUM')})`;
-        case 'operator_mathop':
-            return `(${i('OPERATOR')} of ${i('NUM')})`;
-
-            // data -------------------------------------------------------- //
-        case 'data_variable':
-            return `(${block.inputs.VARIABLE.value} :: variables)`;
-        case 'data_setvariableto':
-            return `set ${i('VARIABLE')} to ${i('VALUE')}`;
-        case 'data_changevariableby':
-            return `change ${i('VARIABLE')} by ${i('VALUE')}`;
-        case 'data_showvariable':
-            return `show variable ${i('VARIABLE')}`;
-        case 'data_hidevariable':
-            return `hide variable ${i('VARIABLE')}`;
-        case 'data_listcontents':
-            return `(${block.inputs.LIST.value} :: list)`;
-        case 'data_addtolist':
-            return `add ${i('ITEM')} to ${i('LIST')}`;
-        case 'data_deleteoflist':
-            return `delete ${i('INDEX')} of ${i('LIST')}`;
-        case 'data_deletealloflist':
-            return `delete all of ${i('LIST')}`;
-        case 'data_insertatlist':
-            return `insert ${i('ITEM')} at ${i('INDEX')} of ${i('LIST')}`;
-        case 'data_replaceitemoflist':
-            return `replace item ${i('INDEX')} of ${i('LIST')} with ${i('ITEM')}`;
-        case 'data_itemoflist':
-            return `(item ${i('INDEX')} of ${i('LIST')})`;
-        case 'data_itemnumoflist':
-            return `(item # of ${i('ITEM')} in ${i('LIST')})`;
-        case 'data_lengthoflist':
-            return `(length of ${i('LIST')})`;
-        case 'data_listcontainsitem':
-            return `<${i('LIST')} contains ${i('ITEM')} ? :: list>`;
-        case 'data_showlist':
-            return `show list ${i('LIST')}`;
-        case 'data_hidelist':
-            return `hide list ${i('LIST')}`;
-
-            // custom blocks ----------------------------------------------- //
-        case 'procedures_definition':
-            const spec = block.inputs.ARGUMENTS.value.map(({ type, name }) => {
-                switch (type) {
-                    case 'label':
-                        return name.replace(/\//g, '\\/');
-                    case 'numberOrString':
-                        return `(${name})`;
-                    case 'boolean':
-                        return `<${name}>`;
-                }
-            }).join(' ');
-            return `define ${spec}` + (block.inputs.WARP.value ? ' // run without screen fresh' : '');
-        case 'procedures_call':
-            const definition = target.scripts.map(s => s.blocks[0]).find(b => b.opcode === 'procedures_definition' && b.inputs.PROCCODE.value === block.inputs.PROCCODE.value);
-            if (definition) {
-                let index = 0;
-                return definition.inputs.ARGUMENTS.value.map(({ type, name }) => {
-                    switch (type) {
-                        case 'label':
-                            return name.replace(/\//g, '\\/');
-                        default:
-                            // TODO: deal with empty boolean inputs, which can't even load yet
-                            return input(block.inputs.INPUTS.value[index++], target);
-                    }
-                }).join(' ') + ' :: custom';
-            } else {
-                return `... // missing custom block definition for ${block.inputs.PROCCODE.value}`;
-            }
-        case 'argument_reporter_string_number':
-            return `(${block.inputs.VALUE.value} :: custom-arg)`;
-        case 'argument_reporter_boolean':
-            return `<${block.inputs.VALUE.value} :: custom-arg>`;
-
-            // extension: pen ---------------------------------------------- //
-        case 'pen_clear':
-            return 'erase all';
-        case 'pen_stamp':
-            return 'stamp';
-        case 'pen_penDown':
-            return 'pen down';
-        case 'pen_penUp':
-            return 'pen up';
-        case 'pen_setPenColorToColor':
-            return `set pen color to ${i('COLOR')}`;
-        case 'pen_changePenColorParamBy':
-            return `change pen ${i('COLOR_PARAM')} by ${i('VALUE')}`;
-        case 'pen_setPenColorParamTo':
-            return `set pen ${i('COLOR_PARAM')} to ${i('VALUE')}`;
-        case 'pen_changePenSizeBy':
-            return `change pen size by ${i('SIZE')}`;
-        case 'pen_setPenSizeTo':
-            return `set pen size to ${i('SIZE')}`;
-        case 'pen_changePenShadeBy':
-            return `change pen shade by ${i('SHADE')}`;
-        case 'pen_setPenShadeToNumber':
-            return `set pen shade to ${i('SHADE')}`;
-        case 'pen_changePenHueBy':
-            return `change pen color by ${i('HUE')}`;
-        case 'pen_setPenHueTo':
-            return `set pen hue to ${i('HUE')}`;
-
-        default:
-            return `\x1b[33m${block.opcode} (${Object.keys(block.inputs).join(', ')})\x1b[0m`;
-
-    }
-}
-
-function blocksToScratchblocks(blocks, target) {
-    return blocks.map(b => blockToScratchblocks(b, target)).join('\n');
-}
-
-function scriptToScratchblocks(script, target) {
-    return blocksToScratchblocks(script.blocks, target);
-}
-
-async function main() {
-    const sb3 = process.argv[2];
-    if (!sb3) {
-        console.error('Please pass an sb3 file.');
-        process.exit(1);
-    }
-    const file = await readFile(sb3);
-    const project = await Project.fromSb3(file);
-    console.log(scriptToScratchblocks(project.sprites[1].scripts[0], project.sprites[1]));
-}
-
-main().catch(err => console.error(err));