├── tutorials
├── 1.md
└── 2.md
├── media
├── 1x1.gif
├── click.mp3
├── click.ogg
├── click.wav
├── save.png
├── delete.mp3
├── delete.ogg
├── delete.png
├── delete.wav
├── pilcrow.png
├── quote0.png
├── quote1.png
├── sprites.png
├── upload.png
├── disconnect.mp3
├── disconnect.ogg
├── disconnect.wav
├── download.png
├── handclosed.cur
├── handdelete.cur
├── handopen.cur
├── paia-logo.icns
├── paia-logo.ico
├── paia-logo.png
├── dropdown-arrow.svg
├── sprites.svg
└── pingpong.svg
├── .gitmodules
├── .gitignore
├── requirements.txt
├── js
├── externs
│ ├── goog-externs.js
│ ├── generator-externs.js
│ └── block-externs.js
├── msg
│ └── json
│ │ ├── constants.json
│ │ └── synonyms.json
├── core
│ ├── interfaces
│ │ ├── i_registrable.js
│ │ ├── i_movable.js
│ │ ├── i_deletable.js
│ │ ├── i_deletearea.js
│ │ ├── i_bounded_element.js
│ │ ├── i_styleable.js
│ │ ├── i_copyable.js
│ │ ├── i_selectable.js
│ │ ├── i_accessibility.js
│ │ └── i_toolbox.js
│ ├── blocks.js
│ ├── keyboard_nav
│ │ ├── action.js
│ │ ├── tab_navigate_cursor.js
│ │ ├── flyout_cursor.js
│ │ └── marker.js
│ ├── msg.js
│ ├── utils
│ │ ├── global.js
│ │ ├── idgenerator.js
│ │ ├── size.js
│ │ ├── rect.js
│ │ ├── math.js
│ │ ├── object.js
│ │ ├── xml.js
│ │ ├── metrics.js
│ │ └── coordinate.js
│ ├── theme
│ │ ├── dark.js
│ │ ├── classic.js
│ │ ├── tritanopia.js
│ │ ├── zelos.js
│ │ ├── deuteranopia.js
│ │ ├── modern.js
│ │ └── highcontrast.js
│ ├── renderers
│ │ ├── minimalist
│ │ │ ├── constants.js
│ │ │ ├── drawer.js
│ │ │ ├── info.js
│ │ │ └── renderer.js
│ │ ├── measurables
│ │ │ └── base.js
│ │ ├── zelos
│ │ │ └── measurables
│ │ │ │ ├── row_elements.js
│ │ │ │ ├── inputs.js
│ │ │ │ └── rows.js
│ │ ├── thrasos
│ │ │ └── renderer.js
│ │ ├── geras
│ │ │ ├── constants.js
│ │ │ └── measurables
│ │ │ │ └── inputs.js
│ │ └── common
│ │ │ └── block_rendering.js
│ ├── workspace_events.js
│ ├── ui_events.js
│ ├── field_registry.js
│ ├── flyout_dragger.js
│ ├── field_label_serializable.js
│ ├── events_abstract.js
│ ├── workspace_dragger.js
│ ├── variable_model.js
│ └── requires.js
├── generators
│ ├── lua
│ │ ├── variables_dynamic.js
│ │ ├── variables.js
│ │ └── colour.js
│ ├── php
│ │ ├── variables_dynamic.js
│ │ ├── variables.js
│ │ └── colour.js
│ ├── dart
│ │ ├── variables_dynamic.js
│ │ └── variables.js
│ ├── python
│ │ ├── variables_dynamic.js
│ │ ├── plot.js
│ │ ├── variables.js
│ │ ├── ndarrays.js
│ │ ├── dicts.js
│ │ ├── file.js
│ │ └── colour.js
│ └── javascript
│ │ ├── variables_dynamic.js
│ │ └── variables.js
├── game_msg
│ ├── template.js
│ ├── easy_game.js
│ ├── arkanoid.js
│ ├── maze_car.js
│ ├── racingcar.js
│ └── pingpong.js
├── ui_msg
│ ├── zh-hant.js
│ └── en.js
├── mlgame
│ ├── easy_game.json
│ ├── arkanoid.json
│ ├── maze_car.json
│ ├── racingcar.json
│ └── pingpong.json
├── blocks
│ ├── plot.js
│ ├── file.js
│ └── colour.js
└── i18n
│ ├── tests.py
│ └── dedup_json.py
├── xml
└── blocks
│ ├── arkanoid.xml
│ ├── easy_game.xml
│ ├── racingcar.xml
│ ├── pingpong.xml
│ └── maze_car.xml
├── preload.js
├── python
├── interpreter.py
└── examples
│ ├── arkanoid
│ ├── 3. model_training.py
│ ├── 4. model_playing.py
│ ├── 1. start.py
│ └── 2. manual.py
│ ├── maze_car
│ ├── 3. model_training.py
│ ├── 4. model_playing.py
│ ├── 1. start.py
│ └── 2. manual.py
│ ├── pingpong
│ ├── 3. model_training.py
│ ├── 4. model_playing.py
│ ├── 1. start.py
│ └── 2. manual.py
│ ├── racingcar
│ ├── 3. model_training.py
│ ├── 4. model_playing.py
│ ├── 1. start.py
│ └── 2. manual.py
│ └── easy_game
│ └── 1. start.py
├── README.md
├── renderer.js
├── main.js
└── package.json
/tutorials/1.md:
--------------------------------------------------------------------------------
1 | # Tutorial 1
2 |
3 | ## Step 1
4 |
5 | ## Step 2
--------------------------------------------------------------------------------
/tutorials/2.md:
--------------------------------------------------------------------------------
1 | # Tutorial 2
2 |
3 | ## Step 1
4 |
5 | ## Step 2
--------------------------------------------------------------------------------
/media/1x1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/1x1.gif
--------------------------------------------------------------------------------
/media/click.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/click.mp3
--------------------------------------------------------------------------------
/media/click.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/click.ogg
--------------------------------------------------------------------------------
/media/click.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/click.wav
--------------------------------------------------------------------------------
/media/save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/save.png
--------------------------------------------------------------------------------
/media/delete.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/delete.mp3
--------------------------------------------------------------------------------
/media/delete.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/delete.ogg
--------------------------------------------------------------------------------
/media/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/delete.png
--------------------------------------------------------------------------------
/media/delete.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/delete.wav
--------------------------------------------------------------------------------
/media/pilcrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/pilcrow.png
--------------------------------------------------------------------------------
/media/quote0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/quote0.png
--------------------------------------------------------------------------------
/media/quote1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/quote1.png
--------------------------------------------------------------------------------
/media/sprites.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/sprites.png
--------------------------------------------------------------------------------
/media/upload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/upload.png
--------------------------------------------------------------------------------
/media/disconnect.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/disconnect.mp3
--------------------------------------------------------------------------------
/media/disconnect.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/disconnect.ogg
--------------------------------------------------------------------------------
/media/disconnect.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/disconnect.wav
--------------------------------------------------------------------------------
/media/download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/download.png
--------------------------------------------------------------------------------
/media/handclosed.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/handclosed.cur
--------------------------------------------------------------------------------
/media/handdelete.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/handdelete.cur
--------------------------------------------------------------------------------
/media/handopen.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/handopen.cur
--------------------------------------------------------------------------------
/media/paia-logo.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/paia-logo.icns
--------------------------------------------------------------------------------
/media/paia-logo.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/paia-logo.ico
--------------------------------------------------------------------------------
/media/paia-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jason53415/blockly-app/HEAD/media/paia-logo.png
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "MLGame"]
2 | path = MLGame
3 | url = https://github.com/jason53415/MLGame.git
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules/
2 | /out/
3 | __pycache__/
4 | /python/build/
5 | /python/dist/
6 | /python/*.spec
7 | /venv/
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | box2d-py==2.3.8
2 | pygame==2.0.1
3 | pyinstaller==4.2
4 | scikit-learn==0.24.1
5 | matplotlib==3.3.4
6 | pynput==1.7.3
7 |
--------------------------------------------------------------------------------
/js/externs/goog-externs.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Externs for goog.
9 | * @externs
10 | */
11 |
12 | /**
13 | * @type {!Object}
14 | */
15 | var goog = {};
16 |
--------------------------------------------------------------------------------
/xml/blocks/arkanoid.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/xml/blocks/easy_game.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/xml/blocks/racingcar.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/xml/blocks/pingpong.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/js/externs/generator-externs.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2020 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Externs for Blockly generators.
9 | * @externs
10 | */
11 |
12 | goog.provide('Blockly');
13 | goog.provide('Blockly.Generator');
14 | goog.provide('Blockly.utils.global');
15 | goog.provide('Blockly.utils.string');
16 |
17 | var Blockly;
18 |
--------------------------------------------------------------------------------
/js/msg/json/constants.json:
--------------------------------------------------------------------------------
1 | {
2 | "LOGIC_HUE": "100",
3 | "LOOPS_HUE": "140",
4 | "MATH_HUE": "170",
5 | "TEXTS_HUE": "190",
6 | "LISTS_HUE": "210",
7 | "DICTS_HUE": "230",
8 | "NDARRAY_HUE": "250",
9 | "MODEL_HUE": "270",
10 | "COLOUR_HUE": "20",
11 | "VARIABLES_HUE": "290",
12 | "VARIABLES_DYNAMIC_HUE": "300",
13 | "PROCEDURES_HUE": "310",
14 | "PLOT_HUE": "335",
15 | "FILE_HUE": "360",
16 | "MLGAME_HUE": "20"
17 | }
--------------------------------------------------------------------------------
/preload.js:
--------------------------------------------------------------------------------
1 | // All of the Node.js APIs are available in the preload process.
2 | // It has the same sandbox as a Chrome extension.
3 | window.addEventListener('DOMContentLoaded', () => {
4 | const replaceText = (selector, text) => {
5 | const element = document.getElementById(selector)
6 | if (element) element.innerText = text
7 | }
8 |
9 | for (const type of ['chrome', 'node', 'electron']) {
10 | replaceText(`${type}-version`, process.versions[type])
11 | }
12 | })
13 |
--------------------------------------------------------------------------------
/python/interpreter.py:
--------------------------------------------------------------------------------
1 | import multiprocessing
2 | import sys
3 | import os
4 | import io
5 |
6 | if __name__ == '__main__':
7 | multiprocessing.freeze_support()
8 | script = sys.argv[1]
9 | wd = os.path.dirname(script)
10 | sys.path.append(wd)
11 | sys.argv.pop(0)
12 | sys.stdout = io.TextIOWrapper(open(sys.stdout.fileno(), 'wb', 0), encoding='utf-8', write_through=True)
13 | os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "1"
14 | exec(open(script, "r", encoding='utf-8').read(), globals(), locals())
15 |
--------------------------------------------------------------------------------
/python/examples/arkanoid/3. model_training.py:
--------------------------------------------------------------------------------
1 | import pickle
2 | import os
3 | from sklearn import neighbors
4 |
5 | with open(os.path.join(os.path.dirname(__file__), 'feature.pickle'), 'rb') as f:
6 | positions = pickle.load(f)
7 | with open(os.path.join(os.path.dirname(__file__), 'target.pickle'), 'rb') as f:
8 | actions = pickle.load(f)
9 | model = neighbors.KNeighborsRegressor(5, weights='uniform')
10 | model.fit(positions, actions)
11 | with open(os.path.join(os.path.dirname(__file__), 'model.pickle'), 'wb') as f:
12 | pickle.dump(model, f)
--------------------------------------------------------------------------------
/python/examples/maze_car/3. model_training.py:
--------------------------------------------------------------------------------
1 | import pickle
2 | import os
3 | from sklearn import neighbors
4 |
5 | with open(os.path.join(os.path.dirname(__file__), 'feature.pickle'), 'rb') as f:
6 | sensor_values = pickle.load(f)
7 | with open(os.path.join(os.path.dirname(__file__), 'target.pickle'), 'rb') as f:
8 | PWMs = pickle.load(f)
9 | model = neighbors.KNeighborsRegressor(5, weights='uniform')
10 | model.fit(sensor_values, PWMs)
11 | with open(os.path.join(os.path.dirname(__file__), 'model.pickle'), 'wb') as f:
12 | pickle.dump(model, f)
--------------------------------------------------------------------------------
/python/examples/pingpong/3. model_training.py:
--------------------------------------------------------------------------------
1 | import pickle
2 | import os
3 | from sklearn import tree
4 |
5 | with open(os.path.join(os.path.dirname(__file__), 'feature.pickle'), 'rb') as f:
6 | ball_position = pickle.load(f)
7 | with open(os.path.join(os.path.dirname(__file__), 'target.pickle'), 'rb') as f:
8 | action = pickle.load(f)
9 | model = tree.DecisionTreeRegressor(max_depth=5, min_samples_split=2)
10 | model.fit(ball_position, action)
11 | with open(os.path.join(os.path.dirname(__file__), 'model.pickle'), 'wb') as f:
12 | pickle.dump(model, f)
--------------------------------------------------------------------------------
/js/core/interfaces/i_registrable.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2020 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview The interface for a Blockly component that can be registered.
9 | * (Ex. Toolbox, Fields, Renderers)
10 | * @author aschmiedt@google.com (Abby Schmiedt)
11 | */
12 |
13 | 'use strict';
14 |
15 | goog.provide('Blockly.IRegistrable');
16 |
17 |
18 | /**
19 | * The interface for a Blockly component that can be registered.
20 | * @interface
21 | * */
22 | Blockly.IRegistrable = function() {};
23 |
--------------------------------------------------------------------------------
/media/dropdown-arrow.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/python/examples/racingcar/3. model_training.py:
--------------------------------------------------------------------------------
1 | import pickle
2 | import os
3 | from sklearn import neighbors
4 |
5 | with open(os.path.join(os.path.dirname(__file__), 'feature.pickle'), 'rb') as f:
6 | player_car_position = pickle.load(f)
7 | with open(os.path.join(os.path.dirname(__file__), 'target.pickle'), 'rb') as f:
8 | action = pickle.load(f)
9 | model = neighbors.KNeighborsRegressor(5, weights='uniform')
10 | model.fit(player_car_position, action)
11 | with open(os.path.join(os.path.dirname(__file__), 'model.pickle'), 'wb') as f:
12 | pickle.dump(model, f)
--------------------------------------------------------------------------------
/xml/blocks/maze_car.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 100
9 |
10 |
11 |
12 |
13 | 100
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/js/core/blocks.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2013 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview A mapping of block type names to block prototype objects.
9 | * @author spertus@google.com (Ellen Spertus)
10 | */
11 | 'use strict';
12 |
13 | /**
14 | * A mapping of block type names to block prototype objects.
15 | * @name Blockly.Blocks
16 | */
17 | goog.provide('Blockly.Blocks');
18 |
19 | /**
20 | * A mapping of block type names to block prototype objects.
21 | * @type {!Object.}
22 | */
23 | Blockly.Blocks = Object.create(null);
24 |
--------------------------------------------------------------------------------
/js/core/interfaces/i_movable.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview The interface for an object that is movable.
9 | * @author samelh@google.com (Sam El-Husseini)
10 | */
11 |
12 | 'use strict';
13 |
14 | goog.provide('Blockly.IMovable');
15 |
16 |
17 | /**
18 | * The interface for an object that is movable.
19 | * @interface
20 | */
21 | Blockly.IMovable = function() {};
22 |
23 | /**
24 | * Get whether this is movable or not.
25 | * @return {boolean} True if movable.
26 | */
27 | Blockly.IMovable.prototype.isMovable;
28 |
--------------------------------------------------------------------------------
/js/generators/lua/variables_dynamic.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2018 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Generating Lua for dynamic variable blocks.
9 | * @author fenichel@google.com (Rachel Fenichel)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.Lua.variablesDynamic');
14 |
15 | goog.require('Blockly.Lua');
16 | goog.require('Blockly.Lua.variables');
17 |
18 |
19 | // Lua is dynamically typed.
20 | Blockly.Lua['variables_get_dynamic'] = Blockly.Lua['variables_get'];
21 | Blockly.Lua['variables_set_dynamic'] = Blockly.Lua['variables_set'];
22 |
--------------------------------------------------------------------------------
/js/generators/php/variables_dynamic.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2018 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Generating PHP for dynamic variable blocks.
9 | * @author fenichel@google.com (Rachel Fenichel)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.PHP.variablesDynamic');
14 |
15 | goog.require('Blockly.PHP');
16 | goog.require('Blockly.PHP.variables');
17 |
18 |
19 | // PHP is dynamically typed.
20 | Blockly.PHP['variables_get_dynamic'] = Blockly.PHP['variables_get'];
21 | Blockly.PHP['variables_set_dynamic'] = Blockly.PHP['variables_set'];
22 |
--------------------------------------------------------------------------------
/js/game_msg/template.js:
--------------------------------------------------------------------------------
1 | Blockly.Msg["MLPLAY_GAME_STATUS_OPTIONS"] = [
2 | ["%{BKY_TEMPLATE_GAME_STATUS_1}", "STATUS_1"],
3 | ["%{BKY_TEMPLATE_GAME_STATUS_2}", "STATUS_2"]
4 | ];
5 | Blockly.Msg["MLPLAY_GET_INFO_OPTIONS"] = [
6 | ["%{BKY_TEMPLATE_SCENE_INFO_1}", "INFO_1"],
7 | ["%{BKY_TEMPLATE_SCENE_INFO_2}", "INFO_2"]
8 | ];
9 | Blockly.Msg["MLPLAY_GET_CONSTANT_OPTIONS"] = [
10 | ["%{BKY_TEMPLATE_CONSTANT_1}", "1/0"],
11 | ["%{BKY_TEMPLATE_CONSTANT_2}", "2/100"]
12 | ];
13 | Blockly.Msg["MLPLAY_RETURN_ACTION_OPTIONS"] = [
14 | ["%{BKY_TEMPLATE_ACTION_1}", "ACTION_1"],
15 | ["%{BKY_TEMPLATE_ACTION_2}", "ACTION_2"]
16 | ];
17 |
--------------------------------------------------------------------------------
/python/examples/easy_game/1. start.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 |
4 | class MLPlay:
5 | def __init__(self):
6 | print("Initial ml script")
7 |
8 | def update(self, scene_info: dict):
9 | """
10 | Generate the command according to the received scene information
11 | """
12 | # print("AI received data from game :", scene_info)
13 |
14 | actions = ["UP", "DOWN", "LEFT", "RIGHT", "NONE"]
15 |
16 | return random.sample(actions, 1)
17 |
18 | def reset(self):
19 | """
20 | Reset the status
21 | """
22 | print("reset ml script")
23 | pass
24 |
--------------------------------------------------------------------------------
/js/generators/dart/variables_dynamic.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2018 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Generating Dart for dynamic variable blocks.
9 | * @author fenichel@google.com (Rachel Fenichel)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.Dart.variablesDynamic');
14 |
15 | goog.require('Blockly.Dart');
16 | goog.require('Blockly.Dart.variables');
17 |
18 |
19 | // Dart is dynamically typed.
20 | Blockly.Dart['variables_get_dynamic'] = Blockly.Dart['variables_get'];
21 | Blockly.Dart['variables_set_dynamic'] = Blockly.Dart['variables_set'];
22 |
--------------------------------------------------------------------------------
/js/core/interfaces/i_deletable.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview The interface for an object that is deletable.
9 | * @author samelh@google.com (Sam El-Husseini)
10 | */
11 |
12 | 'use strict';
13 |
14 | goog.provide('Blockly.IDeletable');
15 |
16 |
17 | /**
18 | * The interface for an object that can be deleted.
19 | * @interface
20 | */
21 | Blockly.IDeletable = function() {};
22 |
23 | /**
24 | * Get whether this object is deletable or not.
25 | * @return {boolean} True if deletable.
26 | */
27 | Blockly.IDeletable.prototype.isDeletable;
28 |
--------------------------------------------------------------------------------
/js/generators/python/variables_dynamic.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2018 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Generating Python for dynamic variable blocks.
9 | * @author fenichel@google.com (Rachel Fenichel)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.Python.variablesDynamic');
14 |
15 | goog.require('Blockly.Python');
16 | goog.require('Blockly.Python.variables');
17 |
18 |
19 | // Python is dynamically typed.
20 | Blockly.Python['variables_get_dynamic'] = Blockly.Python['variables_get'];
21 | Blockly.Python['variables_set_dynamic'] = Blockly.Python['variables_set'];
22 |
--------------------------------------------------------------------------------
/js/core/keyboard_nav/action.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview The class representing an action.
9 | * Used primarily for keyboard navigation.
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.Action');
14 |
15 |
16 | /**
17 | * Class for a single action.
18 | * An action describes user intent. (ex go to next or go to previous)
19 | * @param {string} name The name of the action.
20 | * @param {string} desc The description of the action.
21 | * @constructor
22 | */
23 | Blockly.Action = function(name, desc) {
24 | this.name = name;
25 | this.desc = desc;
26 | };
27 |
--------------------------------------------------------------------------------
/js/generators/javascript/variables_dynamic.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2018 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Generating JavaScript for dynamic variable blocks.
9 | * @author fenichel@google.com (Rachel Fenichel)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.JavaScript.variablesDynamic');
14 |
15 | goog.require('Blockly.JavaScript');
16 | goog.require('Blockly.JavaScript.variables');
17 |
18 |
19 | // JavaScript is dynamically typed.
20 | Blockly.JavaScript['variables_get_dynamic'] =
21 | Blockly.JavaScript['variables_get'];
22 | Blockly.JavaScript['variables_set_dynamic'] =
23 | Blockly.JavaScript['variables_set'];
24 |
--------------------------------------------------------------------------------
/js/core/interfaces/i_deletearea.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2020 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview The interface for a component that can delete a block that is
9 | * dropped on top of it.
10 | * @author aschmiedt@google.com (Abby Schmiedt)
11 | */
12 |
13 | 'use strict';
14 |
15 | goog.provide('Blockly.IDeleteArea');
16 |
17 |
18 | /**
19 | * Interface for a component that can delete a block that is dropped on top of it.
20 | * @interface
21 | */
22 | Blockly.IDeleteArea = function() {};
23 |
24 | /**
25 | * Return the deletion rectangle.
26 | * @return {Blockly.utils.Rect} Rectangle in which to delete.
27 | */
28 | Blockly.IDeleteArea.prototype.getClientRect;
29 |
--------------------------------------------------------------------------------
/js/generators/python/plot.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.provide('Blockly.Python.plot');
4 |
5 | goog.require('Blockly.Python');
6 |
7 | Blockly.Python['plot_plot'] = function(block) {
8 | // Plot.
9 | Blockly.Python.definitions_['import_plt'] = 'import matplotlib.pyplot as plt';
10 | var x = Blockly.Python.valueToCode(block, 'X',
11 | Blockly.Python.ORDER_NONE) || '[]';
12 | var y = Blockly.Python.valueToCode(block, 'Y',
13 | Blockly.Python.ORDER_NONE) || '[]';
14 | var marker = block.getFieldValue('MARKER');
15 | var line = block.getFieldValue('LINE');
16 | var color = block.getFieldValue('COLOR');
17 | var code = 'plt.plot(' + x + ', ' + y + ', "' + marker + line + '", color="' + color + '")\n' +
18 | 'plt.show()\n';
19 | return code;
20 | };
--------------------------------------------------------------------------------
/js/externs/block-externs.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2020 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Externs for Blockly blocks.
9 | * @externs
10 | */
11 |
12 | goog.provide('Blockly');
13 | goog.provide('Blockly.Blocks');
14 | goog.provide('Blockly.Comment');
15 | goog.provide('Blockly.FieldCheckbox');
16 | goog.provide('Blockly.FieldColour');
17 | goog.provide('Blockly.FieldDropdown');
18 | goog.provide('Blockly.FieldImage');
19 | goog.provide('Blockly.FieldLabel');
20 | goog.provide('Blockly.FieldMultilineInput');
21 | goog.provide('Blockly.FieldNumber');
22 | goog.provide('Blockly.FieldTextInput');
23 | goog.provide('Blockly.FieldVariable');
24 | goog.provide('Blockly.Mutator');
25 | goog.provide('Blockly.Warning');
26 |
27 | var Blockly;
--------------------------------------------------------------------------------
/js/core/interfaces/i_bounded_element.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2020 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview The interface for a bounded element.
9 | * @author samelh@google.com (Sam El-Husseini)
10 | */
11 |
12 | 'use strict';
13 |
14 | goog.provide('Blockly.IBoundedElement');
15 |
16 | goog.requireType('Blockly.utils.Rect');
17 |
18 |
19 | /**
20 | * A bounded element interface.
21 | * @interface
22 | */
23 | Blockly.IBoundedElement = function() {};
24 |
25 | /**
26 | * Returns the coordinates of a bounded element describing the dimensions of the
27 | * element.
28 | * Coordinate system: workspace coordinates.
29 | * @return {!Blockly.utils.Rect} Object with coordinates of the bounded element.
30 | */
31 | Blockly.IBoundedElement.prototype.getBoundingRectangle;
32 |
--------------------------------------------------------------------------------
/js/core/msg.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2013 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Empty name space for the Message singleton.
9 | * @author scr@google.com (Sheridan Rawlins)
10 | */
11 | 'use strict';
12 |
13 | /**
14 | * Name space for the Msg singleton.
15 | * Msg gets populated in the message files.
16 | */
17 | goog.provide('Blockly.Msg');
18 |
19 | goog.require('Blockly.utils.global');
20 |
21 |
22 | /**
23 | * Exported so that if Blockly is compiled with ADVANCED_COMPILATION,
24 | * the Blockly.Msg object exists for message files included in script tags.
25 | */
26 | if (!Blockly.utils.global['Blockly']) {
27 | Blockly.utils.global['Blockly'] = {};
28 | }
29 | if (!Blockly.utils.global['Blockly']['Msg']) {
30 | Blockly.utils.global['Blockly']['Msg'] = Blockly.Msg;
31 | }
32 |
--------------------------------------------------------------------------------
/python/examples/racingcar/4. model_playing.py:
--------------------------------------------------------------------------------
1 | import pickle
2 | import os
3 |
4 | class MLPlay:
5 | def __init__(self, player):
6 | self.player = player
7 | self.other_cars_position = []
8 | with open(os.path.join(os.path.dirname(__file__), 'model.pickle'), 'rb') as f:
9 | self.model = pickle.load(f)
10 | def update(self, scene_info):
11 | if scene_info['status'] == "RUNNING":
12 | self.action = self.model.predict([[scene_info['x'], scene_info['y']]])
13 | if self.action == 1:
14 | return ['SPEED']
15 | elif self.action == 2:
16 | return ['BRAKE']
17 | elif self.action == 3:
18 | return ['MOVE_LEFT']
19 | elif self.action == 4:
20 | return ['MOVE_RIGHT']
21 | def reset(self):
22 | pass
--------------------------------------------------------------------------------
/python/examples/pingpong/4. model_playing.py:
--------------------------------------------------------------------------------
1 | import pickle
2 | import os
3 |
4 | class MLPlay:
5 | def __init__(self, side):
6 | self.ball_served = False
7 | self.side = side
8 | with open(os.path.join(os.path.dirname(__file__), 'model.pickle'), 'rb') as f:
9 | self.model = pickle.load(f)
10 | def update(self, scene_info):
11 | if scene_info['status'] != "GAME_ALIVE":
12 | return "RESET"
13 | if not self.ball_served:
14 | self.ball_served = True
15 | return "SERVE_TO_LEFT"
16 | else:
17 | self.action = self.model.predict([[scene_info['ball'][0], scene_info['ball'][1]]])
18 | if self.action == 1:
19 | return "MOVE_LEFT"
20 | else:
21 | return "SERVE_TO_RIGHT"
22 | def reset(self):
23 | self.ball_served = False
--------------------------------------------------------------------------------
/python/examples/arkanoid/4. model_playing.py:
--------------------------------------------------------------------------------
1 | import pickle
2 | import os
3 |
4 | class MLPlay:
5 | def __init__(self):
6 | self.ball_served = False
7 | with open(os.path.join(os.path.dirname(__file__), 'model.pickle'), 'rb') as f:
8 | self.model = pickle.load(f)
9 | def update(self, scene_info):
10 | if scene_info['status'] == "GAME_PASS" or scene_info['status'] == "GAME_OVER":
11 | return "RESET"
12 | if not self.ball_served:
13 | self.ball_served = True
14 | return "SERVE_TO_LEFT"
15 | else:
16 | self.action = self.model.predict([[scene_info['ball'][0], scene_info['ball'][1]]])
17 |
18 | if self.action == 1:
19 | return "MOVE_LEFT"
20 | else:
21 | return "MOVE_RIGHT"
22 | def reset(self):
23 | self.ball_served = False
--------------------------------------------------------------------------------
/js/core/utils/global.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Provides a reference to the global object.
9 | * @author samelh@google.com (Sam El-Husseini)
10 | */
11 | 'use strict';
12 |
13 | /**
14 | * @name Blockly.utils.global
15 | * @namespace
16 | */
17 | goog.provide('Blockly.utils.global');
18 |
19 |
20 | /**
21 | * Reference to the global object.
22 | *
23 | * More info on this implementation here:
24 | * https://docs.google.com/document/d/1NAeW4Wk7I7FV0Y2tcUFvQdGMc89k2vdgSXInw8_nvCI/edit
25 | */
26 | Blockly.utils.global = function() {
27 | if (typeof self === 'object') {
28 | return self;
29 | }
30 | if (typeof window === 'object') {
31 | return window;
32 | }
33 | if (typeof global === 'object') {
34 | return global;
35 | }
36 | return this;
37 | }();
38 |
--------------------------------------------------------------------------------
/js/core/interfaces/i_styleable.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2020 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview The interface for an object that a style can be added to.
9 | * @author aschmiedt@google.com (Abby Schmiedt)
10 | */
11 |
12 | 'use strict';
13 |
14 | goog.provide('Blockly.IStyleable');
15 |
16 |
17 | /**
18 | * Interface for an object that a style can be added to.
19 | * @interface
20 | */
21 | Blockly.IStyleable = function() {};
22 |
23 | /**
24 | * Adds a style on the toolbox. Usually used to change the cursor.
25 | * @param {string} style The name of the class to add.
26 | */
27 | Blockly.IStyleable.prototype.addStyle;
28 |
29 | /**
30 | * Removes a style from the toolbox. Usually used to change the cursor.
31 | * @param {string} style The name of the class to remove.
32 | */
33 | Blockly.IStyleable.prototype.removeStyle;
34 |
--------------------------------------------------------------------------------
/js/core/theme/dark.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Dark theme.
9 | * @author samelh@google.com (Sam El-Husseini)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.Themes.Dark');
14 |
15 | goog.require('Blockly.Theme');
16 |
17 | Blockly.Themes.Dark = Blockly.Theme.defineTheme('dark', {
18 | 'base': Blockly.Themes.Classic,
19 | 'componentStyles': {
20 | 'workspaceBackgroundColour': '#1e1e1e',
21 | 'toolboxBackgroundColour': '#333',
22 | 'toolboxForegroundColour': '#fff',
23 | 'flyoutBackgroundColour': '#252526',
24 | 'flyoutForegroundColour': '#ccc',
25 | 'flyoutOpacity': 1,
26 | 'scrollbarColour': '#797979',
27 | 'insertionMarkerColour': '#fff',
28 | 'insertionMarkerOpacity': 0.3,
29 | 'scrollbarOpacity': 0.4,
30 | 'cursorColour': '#d0d0d0'
31 | }
32 | });
33 |
--------------------------------------------------------------------------------
/js/core/renderers/minimalist/constants.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview An object that provides constants for rendering blocks in the
9 | * minimalist renderer.
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.minimalist.ConstantProvider');
14 |
15 | goog.require('Blockly.blockRendering.ConstantProvider');
16 | goog.require('Blockly.utils.object');
17 |
18 |
19 | /**
20 | * An object that provides constants for rendering blocks in the sample.
21 | * @constructor
22 | * @package
23 | * @extends {Blockly.blockRendering.ConstantProvider}
24 | */
25 | Blockly.minimalist.ConstantProvider = function() {
26 | Blockly.minimalist.ConstantProvider.superClass_.constructor.call(this);
27 | };
28 | Blockly.utils.object.inherits(Blockly.minimalist.ConstantProvider,
29 | Blockly.blockRendering.ConstantProvider);
30 |
--------------------------------------------------------------------------------
/js/core/interfaces/i_copyable.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview The interface for an object that is copyable.
9 | * @author samelh@google.com (Sam El-Husseini)
10 | */
11 |
12 | 'use strict';
13 |
14 | goog.provide('Blockly.ICopyable');
15 |
16 | goog.requireType('Blockly.ISelectable');
17 | goog.requireType('Blockly.WorkspaceSvg');
18 |
19 |
20 | /**
21 | * @extends {Blockly.ISelectable}
22 | * @interface
23 | */
24 | Blockly.ICopyable = function() {};
25 |
26 | /**
27 | * Encode for copying.
28 | * @return {!Blockly.ICopyable.CopyData} Copy metadata.
29 | */
30 | Blockly.ICopyable.prototype.toCopyData;
31 |
32 | /**
33 | * Copy Metadata.
34 | * @typedef {{
35 | * xml:!Element,
36 | * source:Blockly.WorkspaceSvg,
37 | * typeCounts:?Object
38 | * }}
39 | */
40 | Blockly.ICopyable.CopyData;
41 |
--------------------------------------------------------------------------------
/python/examples/arkanoid/1. start.py:
--------------------------------------------------------------------------------
1 | """
2 | The template of the main script of the machine learning process
3 | """
4 |
5 | class MLPlay:
6 | def __init__(self):
7 | """
8 | Constructor
9 | """
10 | self.ball_served = False
11 |
12 | def update(self, scene_info):
13 | """
14 | Generate the command according to the received `scene_info`.
15 | """
16 | # Make the caller to invoke `reset()` for the next round.
17 | if (scene_info["status"] == "GAME_OVER" or
18 | scene_info["status"] == "GAME_PASS"):
19 | return "RESET"
20 |
21 | if not self.ball_served:
22 | self.ball_served = True
23 | command = "SERVE_TO_LEFT"
24 | else:
25 | command = "MOVE_LEFT"
26 |
27 | return command
28 |
29 | def reset(self):
30 | """
31 | Reset the status
32 | """
33 | self.ball_served = False
--------------------------------------------------------------------------------
/js/core/utils/idgenerator.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Generator for unique element IDs.
9 | * For UUIDs use Blockly.utils.genUid. The ID generator should primarily be
10 | * used for IDs that end up in the DOM.
11 | * @author samelh@google.com (Sam El-Husseini)
12 | */
13 | 'use strict';
14 |
15 | goog.provide('Blockly.utils.IdGenerator');
16 |
17 |
18 | /**
19 | * Next unique ID to use.
20 | * @type {number}
21 | * @private
22 | */
23 | Blockly.utils.IdGenerator.nextId_ = 0;
24 |
25 | /**
26 | * Gets the next unique ID.
27 | * IDs are compatible with the HTML4 id attribute restrictions:
28 | * Use only ASCII letters, digits, '_', '-' and '.'
29 | * @return {string} The next unique identifier.
30 | */
31 | Blockly.utils.IdGenerator.getNextUniqueId = function() {
32 | return 'blockly-' + (Blockly.utils.IdGenerator.nextId_++).toString(36);
33 | };
34 |
--------------------------------------------------------------------------------
/python/examples/pingpong/1. start.py:
--------------------------------------------------------------------------------
1 | """
2 | The template of the script for the machine learning process in game pingpong
3 | """
4 |
5 | class MLPlay:
6 | def __init__(self, side):
7 | """
8 | Constructor
9 |
10 | @param side A string "1P" or "2P" indicates that the `MLPlay` is used by
11 | which side.
12 | """
13 | self.ball_served = False
14 | self.side = side
15 |
16 | def update(self, scene_info):
17 | """
18 | Generate the command according to the received scene information
19 | """
20 | if scene_info["status"] != "GAME_ALIVE":
21 | return "RESET"
22 |
23 | if not self.ball_served:
24 | self.ball_served = True
25 | return "SERVE_TO_LEFT"
26 | else:
27 | return "MOVE_LEFT"
28 |
29 | def reset(self):
30 | """
31 | Reset the status
32 | """
33 | self.ball_served = False
34 |
--------------------------------------------------------------------------------
/js/generators/lua/variables.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2016 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Generating Lua for variable blocks.
9 | * @author rodrigoq@google.com (Rodrigo Queiro)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.Lua.variables');
14 |
15 | goog.require('Blockly.Lua');
16 |
17 |
18 | Blockly.Lua['variables_get'] = function(block) {
19 | // Variable getter.
20 | var code = Blockly.Lua.variableDB_.getName(block.getFieldValue('VAR'),
21 | Blockly.VARIABLE_CATEGORY_NAME);
22 | return [code, Blockly.Lua.ORDER_ATOMIC];
23 | };
24 |
25 | Blockly.Lua['variables_set'] = function(block) {
26 | // Variable setter.
27 | var argument0 = Blockly.Lua.valueToCode(block, 'VALUE',
28 | Blockly.Lua.ORDER_NONE) || '0';
29 | var varName = Blockly.Lua.variableDB_.getName(
30 | block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME);
31 | return varName + ' = ' + argument0 + '\n';
32 | };
33 |
--------------------------------------------------------------------------------
/js/core/interfaces/i_selectable.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview The interface for an object that is selectable.
9 | * @author samelh@google.com (Sam El-Husseini)
10 | */
11 |
12 | 'use strict';
13 |
14 | goog.provide('Blockly.ISelectable');
15 |
16 | goog.requireType('Blockly.IDeletable');
17 | goog.requireType('Blockly.IMovable');
18 |
19 |
20 | /**
21 | * The interface for an object that is selectable.
22 | * @extends {Blockly.IDeletable}
23 | * @extends {Blockly.IMovable}
24 | * @interface
25 | */
26 | Blockly.ISelectable = function() {};
27 |
28 | /**
29 | * @type {string}
30 | */
31 | Blockly.ISelectable.prototype.id;
32 |
33 | /**
34 | * Select this. Highlight it visually.
35 | * @return {void}
36 | */
37 | Blockly.ISelectable.prototype.select;
38 |
39 | /**
40 | * Unselect this. Unhighlight it visually.
41 | * @return {void}
42 | */
43 | Blockly.ISelectable.prototype.unselect;
44 |
--------------------------------------------------------------------------------
/js/generators/dart/variables.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2014 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Generating Dart for variable blocks.
9 | * @author fraser@google.com (Neil Fraser)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.Dart.variables');
14 |
15 | goog.require('Blockly.Dart');
16 |
17 |
18 | Blockly.Dart['variables_get'] = function(block) {
19 | // Variable getter.
20 | var code = Blockly.Dart.variableDB_.getName(block.getFieldValue('VAR'),
21 | Blockly.VARIABLE_CATEGORY_NAME);
22 | return [code, Blockly.Dart.ORDER_ATOMIC];
23 | };
24 |
25 | Blockly.Dart['variables_set'] = function(block) {
26 | // Variable setter.
27 | var argument0 = Blockly.Dart.valueToCode(block, 'VALUE',
28 | Blockly.Dart.ORDER_ASSIGNMENT) || '0';
29 | var varName = Blockly.Dart.variableDB_.getName(block.getFieldValue('VAR'),
30 | Blockly.VARIABLE_CATEGORY_NAME);
31 | return varName + ' = ' + argument0 + ';\n';
32 | };
33 |
--------------------------------------------------------------------------------
/js/generators/php/variables.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2015 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Generating PHP for variable blocks.
9 | * @author daarond@gmail.com (Daaron Dwyer)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.PHP.variables');
14 |
15 | goog.require('Blockly.PHP');
16 |
17 |
18 | Blockly.PHP['variables_get'] = function(block) {
19 | // Variable getter.
20 | var code = Blockly.PHP.variableDB_.getName(block.getFieldValue('VAR'),
21 | Blockly.VARIABLE_CATEGORY_NAME);
22 | return [code, Blockly.PHP.ORDER_ATOMIC];
23 | };
24 |
25 | Blockly.PHP['variables_set'] = function(block) {
26 | // Variable setter.
27 | var argument0 = Blockly.PHP.valueToCode(block, 'VALUE',
28 | Blockly.PHP.ORDER_ASSIGNMENT) || '0';
29 | var varName = Blockly.PHP.variableDB_.getName(
30 | block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME);
31 | return varName + ' = ' + argument0 + ';\n';
32 | };
33 |
--------------------------------------------------------------------------------
/js/generators/python/variables.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2012 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Generating Python for variable blocks.
9 | * @author q.neutron@gmail.com (Quynh Neutron)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.Python.variables');
14 |
15 | goog.require('Blockly.Python');
16 |
17 |
18 | Blockly.Python['variables_get'] = function(block) {
19 | // Variable getter.
20 | var code = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'),
21 | Blockly.VARIABLE_CATEGORY_NAME);
22 | return [code, Blockly.Python.ORDER_ATOMIC];
23 | };
24 |
25 | Blockly.Python['variables_set'] = function(block) {
26 | // Variable setter.
27 | var argument0 = Blockly.Python.valueToCode(block, 'VALUE',
28 | Blockly.Python.ORDER_NONE) || '0';
29 | var varName = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'),
30 | Blockly.VARIABLE_CATEGORY_NAME);
31 | return varName + ' = ' + argument0 + '\n';
32 | };
33 |
--------------------------------------------------------------------------------
/js/core/renderers/minimalist/drawer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Minimalist rendering drawer.
9 | */
10 | 'use strict';
11 |
12 | goog.provide('Blockly.minimalist.Drawer');
13 |
14 | goog.require('Blockly.blockRendering.Drawer');
15 | goog.require('Blockly.utils.object');
16 | goog.require('Blockly.minimalist.RenderInfo');
17 |
18 |
19 | /**
20 | * An object that draws a block based on the given rendering information.
21 | * @param {!Blockly.BlockSvg} block The block to render.
22 | * @param {!Blockly.minimalist.RenderInfo} info An object containing all
23 | * information needed to render this block.
24 | * @package
25 | * @constructor
26 | * @extends {Blockly.blockRendering.Drawer}
27 | */
28 | Blockly.minimalist.Drawer = function(block, info) {
29 | Blockly.minimalist.Drawer.superClass_.constructor.call(this, block, info);
30 | };
31 | Blockly.utils.object.inherits(Blockly.minimalist.Drawer,
32 | Blockly.blockRendering.Drawer);
33 |
--------------------------------------------------------------------------------
/python/examples/maze_car/4. model_playing.py:
--------------------------------------------------------------------------------
1 | import pickle
2 | import os
3 |
4 | class MLPlay:
5 | def __init__(self, player):
6 | self.f_sensor_value = 0
7 | self.r_sensor_value = 0
8 | self.l_sensor_value = 0
9 | self.left_PWM = 0
10 | self.right_PWM = 0
11 | self.sensor_values = []
12 | self.PWMs = []
13 | with open(os.path.join(os.path.dirname(__file__), 'model.pickle'), 'rb') as f:
14 | self.model = pickle.load(f)
15 | def update(self, scene_info):
16 | self.f_sensor_value = scene_info['F_sensor']
17 | self.l_sensor_value = scene_info['L_sensor']
18 | self.r_sensor_value = scene_info['R_sensor']
19 | self.sensor_values = [[self.f_sensor_value, self.l_sensor_value, self.r_sensor_value]]
20 | self.PWMs = self.model.predict(self.sensor_values)
21 |
22 | self.left_PWM = self.PWMs[0][0]
23 | self.right_PWM = self.PWMs[0][1]
24 | return [{'left_PWM': self.left_PWM, 'right_PWM': self.right_PWM}]
25 | def reset(self):
26 | pass
--------------------------------------------------------------------------------
/js/generators/javascript/variables.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2012 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Generating JavaScript for variable blocks.
9 | * @author fraser@google.com (Neil Fraser)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.JavaScript.variables');
14 |
15 | goog.require('Blockly.JavaScript');
16 |
17 |
18 | Blockly.JavaScript['variables_get'] = function(block) {
19 | // Variable getter.
20 | var code = Blockly.JavaScript.variableDB_.getName(block.getFieldValue('VAR'),
21 | Blockly.VARIABLE_CATEGORY_NAME);
22 | return [code, Blockly.JavaScript.ORDER_ATOMIC];
23 | };
24 |
25 | Blockly.JavaScript['variables_set'] = function(block) {
26 | // Variable setter.
27 | var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE',
28 | Blockly.JavaScript.ORDER_ASSIGNMENT) || '0';
29 | var varName = Blockly.JavaScript.variableDB_.getName(
30 | block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME);
31 | return varName + ' = ' + argument0 + ';\n';
32 | };
33 |
--------------------------------------------------------------------------------
/js/msg/json/synonyms.json:
--------------------------------------------------------------------------------
1 | {"CONTROLS_WHILEUNTIL_INPUT_DO": "CONTROLS_REPEAT_INPUT_DO", "CONTROLS_FOR_INPUT_DO": "CONTROLS_REPEAT_INPUT_DO", "CONTROLS_FOREACH_INPUT_DO": "CONTROLS_REPEAT_INPUT_DO", "CONTROLS_IF_MSG_THEN": "CONTROLS_REPEAT_INPUT_DO", "CONTROLS_IF_IF_TITLE_IF": "CONTROLS_IF_MSG_IF", "CONTROLS_IF_ELSEIF_TITLE_ELSEIF": "CONTROLS_IF_MSG_ELSEIF", "CONTROLS_IF_ELSE_TITLE_ELSE": "CONTROLS_IF_MSG_ELSE", "MATH_CHANGE_TITLE_ITEM": "VARIABLES_DEFAULT_NAME", "TEXT_CREATE_JOIN_ITEM_TITLE_ITEM": "VARIABLES_DEFAULT_NAME", "TEXT_APPEND_VARIABLE": "VARIABLES_DEFAULT_NAME", "LISTS_CREATE_WITH_ITEM_TITLE": "VARIABLES_DEFAULT_NAME", "LISTS_INDEX_OF_INPUT_IN_LIST": "LISTS_INLIST", "LISTS_GET_INDEX_HELPURL": "LISTS_INDEX_OF_HELPURL", "LISTS_GET_INDEX_INPUT_IN_LIST": "LISTS_INLIST", "LISTS_SET_INDEX_INPUT_IN_LIST": "LISTS_INLIST", "LISTS_GET_SUBLIST_INPUT_IN_LIST": "LISTS_INLIST", "PROCEDURES_DEFRETURN_TITLE": "PROCEDURES_DEFNORETURN_TITLE", "PROCEDURES_DEFRETURN_PROCEDURE": "PROCEDURES_DEFNORETURN_PROCEDURE", "PROCEDURES_DEFRETURN_DO": "PROCEDURES_DEFNORETURN_DO", "PROCEDURES_DEFRETURN_COMMENT": "PROCEDURES_DEFNORETURN_COMMENT"}
--------------------------------------------------------------------------------
/python/examples/racingcar/1. start.py:
--------------------------------------------------------------------------------
1 | class MLPlay:
2 | def __init__(self, player):
3 | self.player = player
4 | if self.player == "player1":
5 | self.player_no = 0
6 | elif self.player == "player2":
7 | self.player_no = 1
8 | elif self.player == "player3":
9 | self.player_no = 2
10 | elif self.player == "player4":
11 | self.player_no = 3
12 | self.other_cars_position = []
13 | self.coins_pos = []
14 | print("Initial ml script")
15 |
16 | def update(self, scene_info: dict):
17 | """
18 | Generate the command according to the received scene information
19 | """
20 | if scene_info["status"] == "RUNNING":
21 | self.car_pos = (scene_info["x"], scene_info["y"])
22 |
23 | self.other_cars_position = scene_info["cars_pos"]
24 | if scene_info.__contains__("coin"):
25 | self.coin_pos = scene_info["coin"]
26 |
27 | return ["SPEED"]
28 |
29 | def reset(self):
30 | """
31 | Reset the status
32 | """
33 | print("reset ml script")
34 | pass
35 |
--------------------------------------------------------------------------------
/js/core/renderers/measurables/base.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Methods for graphically rendering a block as SVG.
9 | * @author fenichel@google.com (Rachel Fenichel)
10 | */
11 |
12 | 'use strict';
13 |
14 | goog.provide('Blockly.blockRendering.Measurable');
15 |
16 | goog.require('Blockly.blockRendering.Types');
17 |
18 |
19 | /**
20 | * The base class to represent a part of a block that takes up space during
21 | * rendering. The constructor for each non-spacer Measurable records the size
22 | * of the block element (e.g. field, statement input).
23 | * @param {!Blockly.blockRendering.ConstantProvider} constants The rendering
24 | * constants provider.
25 | * @package
26 | * @constructor
27 | */
28 | Blockly.blockRendering.Measurable = function(constants) {
29 | this.width = 0;
30 | this.height = 0;
31 | this.type = Blockly.blockRendering.Types.NONE;
32 |
33 | this.xPos = 0;
34 | this.centerline = 0;
35 |
36 | /**
37 | * The renderer's constant provider.
38 | * @type {!Blockly.blockRendering.ConstantProvider}
39 | * @protected
40 | */
41 | this.constants_ = constants;
42 |
43 | this.notchOffset = this.constants_.NOTCH_OFFSET_LEFT;
44 | };
45 |
--------------------------------------------------------------------------------
/js/core/renderers/zelos/measurables/row_elements.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Zelos specific objects representing elements in a row of a
9 | * rendered block.
10 | * @author samelh@google.com (Sam El-Husseini)
11 | */
12 |
13 | goog.provide('Blockly.zelos.RightConnectionShape');
14 |
15 | goog.require('Blockly.blockRendering.Measurable');
16 | goog.require('Blockly.blockRendering.Types');
17 | goog.require('Blockly.utils.object');
18 |
19 |
20 | /**
21 | * An object containing information about the space a right connection shape
22 | * takes up during rendering.
23 | * @param {!Blockly.blockRendering.ConstantProvider} constants The rendering
24 | * constants provider.
25 | * @package
26 | * @constructor
27 | * @extends {Blockly.blockRendering.Measurable}
28 | */
29 | Blockly.zelos.RightConnectionShape = function(constants) {
30 | Blockly.zelos.RightConnectionShape.superClass_.constructor.call(this, constants);
31 | this.type |= Blockly.blockRendering.Types.getType('RIGHT_CONNECTION');
32 | // Size is dynamic
33 | this.height = 0;
34 | this.width = 0;
35 | };
36 | Blockly.utils.object.inherits(Blockly.zelos.RightConnectionShape,
37 | Blockly.blockRendering.Measurable);
38 |
--------------------------------------------------------------------------------
/python/examples/maze_car/1. start.py:
--------------------------------------------------------------------------------
1 | class MLPlay:
2 | def __init__(self, player):
3 | self.player_no = player[6]
4 | self.r_sensor_value = 0
5 | self.l_sensor_value = 0
6 | self.f_sensor_value = 0
7 | self.control_list = [{"left_PWM" : 0, "right_PWM" : 0}]
8 | print("Initial ml script")
9 |
10 | def update(self, scene_info: dict):
11 | """
12 | Generate the command according to the received scene information
13 | """
14 | self.r_sensor_value = scene_info["R_sensor"]
15 | self.l_sensor_value = scene_info["L_sensor"]
16 | self.f_sensor_value = scene_info["F_sensor"]
17 | if self.f_sensor_value >30:
18 | self.control_list[0]["left_PWM"] = 50
19 | self.control_list[0]["right_PWM"] = 50
20 | if self.r_sensor_value >30:
21 | self.control_list[0]["left_PWM"] = 100
22 | if self.l_sensor_value >30:
23 | self.control_list[0]["right_PWM"] = 100
24 | if self.f_sensor_value <10:
25 | self.control_list[0]["left_PWM"] = -50
26 | self.control_list[0]["right_PWM"] = -50
27 | return self.control_list
28 |
29 | def reset(self):
30 | """
31 | Reset the status
32 | """
33 | print("reset ml script")
34 | pass
35 |
--------------------------------------------------------------------------------
/js/ui_msg/zh-hant.js:
--------------------------------------------------------------------------------
1 | var MSG = {
2 | title: "積木程式",
3 | blocks: "積木",
4 | examples: "範例程式",
5 | lang: "語言",
6 | options: "選項",
7 | linkTooltip: "儲存積木組並提供連結。",
8 | runTooltip: "於工作區中執行積木組所定義的程式。",
9 | badCode: "程式錯誤:\n%1",
10 | timeout: "超過最大執行數。",
11 | discard: "捨棄所有積木",
12 | download: "儲存 Python 檔",
13 | runMLGame: "玩遊戲",
14 | runPython: "執行 Python 檔",
15 | openXml: "開啟 XML 檔",
16 | openPython: "開啟 Python 檔",
17 | downloadXml: "儲存 XML 檔",
18 | en: "英文",
19 | zh_hant: "中文",
20 | catLogic: "邏輯",
21 | catLoops: "迴圈",
22 | catMath: "數學式",
23 | catText: "文字",
24 | catLists: "清單",
25 | catDicts: "字典",
26 | catNdarrays: "多維陣列",
27 | catColour: "顏色",
28 | catFile: "檔案",
29 | catPlot: "繪圖",
30 | catModel: "模型",
31 | catVariables: "變數",
32 | catFunctions: "函式",
33 | listVariable: "清單",
34 | ndarrayVariable: "多維陣列",
35 | textVariable: "文字",
36 | dictVariable: "字典",
37 | modelVariable: "模型",
38 | objVariable: "物件",
39 | filename: "檔案名稱",
40 | trainData: "訓練資料",
41 | testData: "測試資料",
42 | trainTarget: "訓練目標",
43 | testTarget: "測試目標",
44 | httpRequestError: "命令出現錯誤。",
45 | linkAlert: "透過此連結分享您的積木組:\n\n%1",
46 | hashError: "對不起,「%1」並未對應任何已保存的程式。",
47 | xmlError: "未能載入您保存的檔案。或許它是由其他版本的Blockly創建?",
48 | badXml: "解析 XML 時出現錯誤:\n%1\n\n選擇'確定'以放棄您的更改,或選擇'取消'以進一步編輯 XML。"
49 | };
50 |
--------------------------------------------------------------------------------
/js/mlgame/easy_game.json:
--------------------------------------------------------------------------------
1 | {
2 | "GAME_STATUS": [
3 | ["GAME_ALIVE", "alive", "存活"],
4 | ["GAME_PASS", "pass", "通關"],
5 | ["GAME_OVER", "over", "失敗"]
6 | ],
7 | "SCENE_INFO": [
8 | ["scene_info['frame']", "# frame", "# 幀數"],
9 | ["scene_info['status']", "game status", "遊戲狀態"],
10 | ["scene_info['ball_x']", "x coordinate of ball", "球的 x 座標"],
11 | ["scene_info['ball_y']", "y coordinate of ball", "球的 y 座標"],
12 | ["scene_info['score']", "x coordinate of platform", "平台的 x 座標"],
13 | ["scene_info['foods']", "list of foods positions", "點點的位置清單"],
14 | ["scene_info", "dictionary of all information", "包含所有資訊的字典"]
15 | ],
16 | "CONSTANT": [
17 | [0, "left boundary", "左邊界"],
18 | [800, "right boundary", "右邊界"],
19 | [0, "top boundary", "上邊界"],
20 | [600, "bottom boundary", "下邊界"],
21 | [50, "ball width", "球身的寬度"],
22 | [50, "ball height", "球身的高度"],
23 | [8, "food width", "食物的寬度"],
24 | [8, "food height", "食物的高度"]
25 | ],
26 | "ACTION": [
27 | ["['UP']", "moving up", "向上移動"],
28 | ["['DOWN']", "moving down", "向下移動"],
29 | ["['LEFT']", "moving left", "向左移動"],
30 | ["['RIGHT']", "moving right", "向右移動"],
31 | ["['NONE']", "doing nothing", "不動作"]
32 |
33 | ]
34 | }
--------------------------------------------------------------------------------
/js/core/renderers/thrasos/renderer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Thrasos renderer.
9 | * @author fenichel@google.com (Rachel Fenichel)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.thrasos.Renderer');
14 |
15 | goog.require('Blockly.blockRendering');
16 | goog.require('Blockly.blockRendering.Renderer');
17 | goog.require('Blockly.thrasos.RenderInfo');
18 | goog.require('Blockly.utils.object');
19 |
20 | /**
21 | * The thrasos renderer.
22 | * @param {string} name The renderer name.
23 | * @package
24 | * @constructor
25 | * @extends {Blockly.blockRendering.Renderer}
26 | */
27 | Blockly.thrasos.Renderer = function(name) {
28 | Blockly.thrasos.Renderer.superClass_.constructor.call(this, name);
29 | };
30 | Blockly.utils.object.inherits(Blockly.thrasos.Renderer,
31 | Blockly.blockRendering.Renderer);
32 |
33 | /**
34 | * Create a new instance of the renderer's render info object.
35 | * @param {!Blockly.BlockSvg} block The block to measure.
36 | * @return {!Blockly.thrasos.RenderInfo} The render info object.
37 | * @protected
38 | * @override
39 | */
40 | Blockly.thrasos.Renderer.prototype.makeRenderInfo_ = function(block) {
41 | return new Blockly.thrasos.RenderInfo(this, block);
42 | };
43 |
44 |
45 | Blockly.blockRendering.register('thrasos', Blockly.thrasos.Renderer);
46 |
--------------------------------------------------------------------------------
/js/core/utils/size.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Utility methods for size calculation.
9 | * These methods are not specific to Blockly, and could be factored out into
10 | * a JavaScript framework such as Closure.
11 | * @author samelh@google.com (Sam El-Husseini)
12 | */
13 | 'use strict';
14 |
15 | /**
16 | * @name Blockly.utils.Size
17 | * @namespace
18 | */
19 | goog.provide('Blockly.utils.Size');
20 |
21 |
22 | /**
23 | * Class for representing sizes consisting of a width and height.
24 | * @param {number} width Width.
25 | * @param {number} height Height.
26 | * @struct
27 | * @constructor
28 | */
29 | Blockly.utils.Size = function(width, height) {
30 | /**
31 | * Width
32 | * @type {number}
33 | */
34 | this.width = width;
35 |
36 | /**
37 | * Height
38 | * @type {number}
39 | */
40 | this.height = height;
41 | };
42 |
43 | /**
44 | * Compares sizes for equality.
45 | * @param {Blockly.utils.Size} a A Size.
46 | * @param {Blockly.utils.Size} b A Size.
47 | * @return {boolean} True iff the sizes have equal widths and equal
48 | * heights, or if both are null.
49 | */
50 | Blockly.utils.Size.equals = function(a, b) {
51 | if (a == b) {
52 | return true;
53 | }
54 | if (!a || !b) {
55 | return false;
56 | }
57 | return a.width == b.width && a.height == b.height;
58 | };
59 |
--------------------------------------------------------------------------------
/js/game_msg/easy_game.js:
--------------------------------------------------------------------------------
1 | Blockly.Msg["MLPLAY_GAME_STATUS_OPTIONS"] = [
2 | ["%{BKY_EASY_GAME_GAME_STATUS_1}", "GAME_ALIVE"],
3 | ["%{BKY_EASY_GAME_GAME_STATUS_2}", "GAME_PASS"],
4 | ["%{BKY_EASY_GAME_GAME_STATUS_3}", "GAME_OVER"]
5 | ];
6 | Blockly.Msg["MLPLAY_GET_INFO_OPTIONS"] = [
7 | ["%{BKY_EASY_GAME_SCENE_INFO_1}", "scene_info['frame']"],
8 | ["%{BKY_EASY_GAME_SCENE_INFO_2}", "scene_info['status']"],
9 | ["%{BKY_EASY_GAME_SCENE_INFO_3}", "scene_info['ball_x']"],
10 | ["%{BKY_EASY_GAME_SCENE_INFO_4}", "scene_info['ball_y']"],
11 | ["%{BKY_EASY_GAME_SCENE_INFO_5}", "scene_info['score']"],
12 | ["%{BKY_EASY_GAME_SCENE_INFO_6}", "scene_info['foods']"],
13 | ["%{BKY_EASY_GAME_SCENE_INFO_7}", "scene_info"]
14 | ];
15 | Blockly.Msg["MLPLAY_GET_CONSTANT_OPTIONS"] = [
16 | ["%{BKY_EASY_GAME_CONSTANT_1}", "1/0"],
17 | ["%{BKY_EASY_GAME_CONSTANT_2}", "2/800"],
18 | ["%{BKY_EASY_GAME_CONSTANT_3}", "3/0"],
19 | ["%{BKY_EASY_GAME_CONSTANT_4}", "4/600"],
20 | ["%{BKY_EASY_GAME_CONSTANT_5}", "5/50"],
21 | ["%{BKY_EASY_GAME_CONSTANT_6}", "6/50"],
22 | ["%{BKY_EASY_GAME_CONSTANT_7}", "7/8"],
23 | ["%{BKY_EASY_GAME_CONSTANT_8}", "8/8"]
24 | ];
25 | Blockly.Msg["MLPLAY_RETURN_ACTION_OPTIONS"] = [
26 | ["%{BKY_EASY_GAME_ACTION_1}", "['UP']"],
27 | ["%{BKY_EASY_GAME_ACTION_2}", "['DOWN']"],
28 | ["%{BKY_EASY_GAME_ACTION_3}", "['LEFT']"],
29 | ["%{BKY_EASY_GAME_ACTION_4}", "['RIGHT']"],
30 | ["%{BKY_EASY_GAME_ACTION_5}", "['NONE']"]
31 | ];
32 |
--------------------------------------------------------------------------------
/js/core/renderers/minimalist/info.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Minimalist render info object.
9 | */
10 | 'use strict';
11 |
12 | goog.provide('Blockly.minimalist');
13 | goog.provide('Blockly.minimalist.RenderInfo');
14 |
15 | goog.require('Blockly.utils.object');
16 |
17 |
18 | /**
19 | * An object containing all sizing information needed to draw this block.
20 | *
21 | * This measure pass does not propagate changes to the block (although fields
22 | * may choose to rerender when getSize() is called). However, calling it
23 | * repeatedly may be expensive.
24 | *
25 | * @param {!Blockly.minimalist.Renderer} renderer The renderer in use.
26 | * @param {!Blockly.BlockSvg} block The block to measure.
27 | * @constructor
28 | * @package
29 | * @extends {Blockly.blockRendering.RenderInfo}
30 | */
31 | Blockly.minimalist.RenderInfo = function(renderer, block) {
32 | Blockly.minimalist.RenderInfo.superClass_.constructor.call(this, renderer, block);
33 |
34 | };
35 | Blockly.utils.object.inherits(Blockly.minimalist.RenderInfo,
36 | Blockly.blockRendering.RenderInfo);
37 |
38 | /**
39 | * Get the block renderer in use.
40 | * @return {!Blockly.minimalist.Renderer} The block renderer in use.
41 | * @package
42 | */
43 | Blockly.minimalist.RenderInfo.prototype.getRenderer = function() {
44 | return /** @type {!Blockly.minimalist.Renderer} */ (this.renderer_);
45 | };
46 |
--------------------------------------------------------------------------------
/js/core/utils/rect.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Utility methods for rectangle manipulation.
9 | * These methods are not specific to Blockly, and could be factored out into
10 | * a JavaScript framework such as Closure.
11 | * @author fraser@google.com (Neil Fraser)
12 | */
13 | 'use strict';
14 |
15 | /**
16 | * @name Blockly.utils.Rect
17 | * @namespace
18 | */
19 | goog.provide('Blockly.utils.Rect');
20 |
21 |
22 | /**
23 | * Class for representing rectangular regions.
24 | * @param {number} top Top.
25 | * @param {number} bottom Bottom.
26 | * @param {number} left Left.
27 | * @param {number} right Right.
28 | * @struct
29 | * @constructor
30 | */
31 | Blockly.utils.Rect = function(top, bottom, left, right) {
32 | /** @type {number} */
33 | this.top = top;
34 |
35 | /** @type {number} */
36 | this.bottom = bottom;
37 |
38 | /** @type {number} */
39 | this.left = left;
40 |
41 | /** @type {number} */
42 | this.right = right;
43 | };
44 |
45 | /**
46 | * Tests whether this rectangle contains a x/y coordinate.
47 | *
48 | * @param {number} x The x coordinate to test for containment.
49 | * @param {number} y The y coordinate to test for containment.
50 | * @return {boolean} Whether this rectangle contains given coordinate.
51 | */
52 | Blockly.utils.Rect.prototype.contains = function(x, y) {
53 | return x >= this.left && x <= this.right && y >= this.top && y <= this.bottom;
54 | };
55 |
--------------------------------------------------------------------------------
/js/core/keyboard_nav/tab_navigate_cursor.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview The class representing a cursor that is used to navigate
9 | * between tab navigable fields.
10 | * @author samelh@google.com (Sam El-Husseini)
11 | */
12 | 'use strict';
13 |
14 | goog.provide('Blockly.TabNavigateCursor');
15 |
16 | goog.require('Blockly.ASTNode');
17 | goog.require('Blockly.BasicCursor');
18 | goog.require('Blockly.utils.object');
19 |
20 |
21 | /**
22 | * A cursor for navigating between tab navigable fields.
23 | * @constructor
24 | * @extends {Blockly.BasicCursor}
25 | */
26 | Blockly.TabNavigateCursor = function() {
27 | Blockly.TabNavigateCursor.superClass_.constructor.call(this);
28 | };
29 | Blockly.utils.object.inherits(Blockly.TabNavigateCursor, Blockly.BasicCursor);
30 |
31 | /**
32 | * Skip all nodes except for tab navigable fields.
33 | * @param {Blockly.ASTNode} node The AST node to check whether it is valid.
34 | * @return {boolean} True if the node should be visited, false otherwise.
35 | * @override
36 | */
37 | Blockly.TabNavigateCursor.prototype.validNode_ = function(node) {
38 | var isValid = false;
39 | var type = node && node.getType();
40 | if (node) {
41 | var location = /** @type {Blockly.Field} */ (node.getLocation());
42 | if (type == Blockly.ASTNode.types.FIELD &&
43 | location && location.isTabNavigable() && location.isClickable()) {
44 | isValid = true;
45 | }
46 | }
47 | return isValid;
48 | };
49 |
--------------------------------------------------------------------------------
/js/mlgame/arkanoid.json:
--------------------------------------------------------------------------------
1 | {
2 | "GAME_STATUS": [
3 | ["GAME_ALIVE", "alive", "存活"],
4 | ["GAME_PASS", "pass", "通關"],
5 | ["GAME_OVER", "over", "失敗"]
6 | ],
7 | "SCENE_INFO": [
8 | ["scene_info['frame']", "# frame", "# 幀數"],
9 | ["scene_info['status']", "game status", "遊戲狀態"],
10 | ["scene_info['ball'][0]", "x coordinate of ball", "球的 x 座標"],
11 | ["scene_info['ball'][1]", "y coordinate of ball", "球的 y 座標"],
12 | ["scene_info['platform'][0]", "x coordinate of platform", "平台的 x 座標"],
13 | ["scene_info['platform'][1]", "y coordinate of platform", "平台的 y 座標"],
14 | ["scene_info['bricks']", "list of brick positions", "磚塊的位置清單"],
15 | ["scene_info['hard_bricks']", "list of hard brick positions", "堅硬磚塊的位置清單"],
16 | ["scene_info", "dictionary of all information", "包含所有資訊的字典"]
17 | ],
18 | "CONSTANT": [
19 | [0, "left boundary", "左邊界"],
20 | [200, "right boundary", "右邊界"],
21 | [0, "top boundary", "上邊界"],
22 | [500, "bottom boundary", "下邊界"],
23 | [40, "platform width", "平台寬度"],
24 | [5, "platform height", "平台高度"],
25 | [25, "brick width", "磚塊寬度"],
26 | [10, "brick height", "磚塊高度"]
27 | ],
28 | "ACTION": [
29 | ["SERVE_TO_LEFT", "serving left", "向左發球"],
30 | ["SERVE_TO_RIGHT", "serving right", "向右發球"],
31 | ["MOVE_LEFT", "moving left", "向左移動"],
32 | ["MOVE_RIGHT", "moving right", "向右移動"],
33 | ["NONE", "doing nothing", "不動作"],
34 | ["RESET", "reset", "重置"]
35 | ]
36 | }
--------------------------------------------------------------------------------
/js/mlgame/maze_car.json:
--------------------------------------------------------------------------------
1 | {
2 | "INIT_INFO": [
3 | ["player", "player number", "玩家編號"]
4 | ],
5 | "PLAYER_STATUS": [
6 | ["player1", "1P", "1P"],
7 | ["player2", "2P", "2P"],
8 | ["player3", "3P", "3P"],
9 | ["player4", "4P", "4P"],
10 | ["player5", "5P", "5P"],
11 | ["player6", "6P", "6P"]
12 | ],
13 | "GAME_STATUS": [
14 | ["GAME_ALIVE", "alive", "存活"],
15 | ["GAME_PASS", "pass", "通關"],
16 | ["GAME_OVER", "over", "失敗"]
17 | ],
18 | "SCENE_INFO": [
19 | ["scene_info['frame']", "# frame", "# 幀數"],
20 | ["scene_info['status']", "game status", "遊戲狀態"],
21 | ["scene_info['x']", "x position of the car", "車子的 x 座標"],
22 | ["scene_info['y']", "y position of the car", "車子的 y 座標"],
23 | ["scene_info['angle']", "angle of the car", "車子的角度"],
24 | ["scene_info['end']", "end position", "終點位置"],
25 | ["scene_info['R_sensor']", "right sensor value", "右超聲波值"],
26 | ["scene_info['F_sensor']", "front sensor value", "前超聲波值"],
27 | ["scene_info['L_sensor']", "left sensor value", "左超聲波值"],
28 | ["scene_info['R_T_sensor']", "right front sensor value", "右前超聲波值"],
29 | ["scene_info['L_T_sensor']", "left front sensor value", "左前超聲波值"]
30 | ],
31 | "CONSTANT": [
32 | [0, "left boundary", "左邊界"],
33 | [820, "right boundary", "右邊界"],
34 | [0, "top boundary", "上邊界"],
35 | [520, "bottom boundary", "下邊界"]
36 | ],
37 | "ACTION": [
38 | ["RESET", "reset", "重置"]
39 | ]
40 | }
41 |
--------------------------------------------------------------------------------
/js/core/renderers/zelos/measurables/inputs.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2020 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Zelos specific objects representing inputs with connections on
9 | * a rendered block.
10 | * @author samelh@google.com (Sam El-Husseini)
11 | */
12 |
13 | goog.provide('Blockly.zelos.StatementInput');
14 |
15 | goog.require('Blockly.blockRendering.StatementInput');
16 | goog.require('Blockly.utils.object');
17 |
18 |
19 | /**
20 | * An object containing information about the space a statement input takes up
21 | * during rendering
22 | * @param {!Blockly.blockRendering.ConstantProvider} constants The rendering
23 | * constants provider.
24 | * @param {!Blockly.Input} input The statement input to measure and store
25 | * information for.
26 | * @package
27 | * @constructor
28 | * @extends {Blockly.blockRendering.StatementInput}
29 | */
30 | Blockly.zelos.StatementInput = function(constants, input) {
31 | Blockly.zelos.StatementInput.superClass_.constructor.call(this,
32 | constants, input);
33 |
34 | if (this.connectedBlock) {
35 | // Find the bottom-most connected block in the stack.
36 | var block = this.connectedBlock;
37 | while (block.getNextBlock()) {
38 | block = block.getNextBlock();
39 | }
40 | if (!block.nextConnection) {
41 | this.height = this.connectedBlockHeight;
42 | this.connectedBottomNextConnection = true;
43 | }
44 | }
45 | };
46 | Blockly.utils.object.inherits(Blockly.zelos.StatementInput,
47 | Blockly.blockRendering.StatementInput);
48 |
--------------------------------------------------------------------------------
/js/generators/python/ndarrays.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.provide('Blockly.Python.ndarrays');
4 |
5 | goog.require('Blockly.Python');
6 |
7 | Blockly.Python['ndarrays_create_with'] = function(block) {
8 | // Create an ndarray of any shape filled with a specific element.
9 | Blockly.Python.definitions_['import_np'] = 'import numpy as np';
10 | var shape = new Array(block.dimCount_);
11 | for (var i = 0; i < block.dimCount_; i++) {
12 | shape[i] = Blockly.Python.valueToCode(block, 'DIM' + i,
13 | Blockly.Python.ORDER_NONE) || '0';
14 | }
15 | var fill = Blockly.Python.valueToCode(block, 'FILL',
16 | Blockly.Python.ORDER_NONE) || '0';
17 | var code = 'np.full((' + shape.join(', ') + '), ' + fill + ')';
18 | return [code, Blockly.Python.ORDER_ATOMIC];
19 | };
20 |
21 | Blockly.Python['ndarrays_create_with_list'] = function(block) {
22 | // Create an ndarray of any shape filled with a specific element.
23 | Blockly.Python.definitions_['import_np'] = 'import numpy as np';
24 | var list = Blockly.Python.valueToCode(block, 'LIST',
25 | Blockly.Python.ORDER_NONE) || '0';
26 | var code = 'np.array(' + list + ')';
27 | return [code, Blockly.Python.ORDER_ATOMIC];
28 | };
29 |
30 | Blockly.Python['ndarrays_to_list'] = function(block) {
31 | // Create an ndarray of any shape filled with a specific element.
32 | Blockly.Python.definitions_['import_np'] = 'import numpy as np';
33 | var array = Blockly.Python.valueToCode(block, 'ARRAY',
34 | Blockly.Python.ORDER_NONE) || '0';
35 | var code = array + '.tolist()';
36 | return [code, Blockly.Python.ORDER_ATOMIC];
37 | };
--------------------------------------------------------------------------------
/js/game_msg/arkanoid.js:
--------------------------------------------------------------------------------
1 | Blockly.Msg["MLPLAY_GAME_STATUS_OPTIONS"] = [
2 | ["%{BKY_ARKANOID_GAME_STATUS_1}", "GAME_ALIVE"],
3 | ["%{BKY_ARKANOID_GAME_STATUS_2}", "GAME_PASS"],
4 | ["%{BKY_ARKANOID_GAME_STATUS_3}", "GAME_OVER"]
5 | ];
6 | Blockly.Msg["MLPLAY_GET_INFO_OPTIONS"] = [
7 | ["%{BKY_ARKANOID_SCENE_INFO_1}", "scene_info['frame']"],
8 | ["%{BKY_ARKANOID_SCENE_INFO_2}", "scene_info['status']"],
9 | ["%{BKY_ARKANOID_SCENE_INFO_3}", "scene_info['ball'][0]"],
10 | ["%{BKY_ARKANOID_SCENE_INFO_4}", "scene_info['ball'][1]"],
11 | ["%{BKY_ARKANOID_SCENE_INFO_5}", "scene_info['platform'][0]"],
12 | ["%{BKY_ARKANOID_SCENE_INFO_6}", "scene_info['platform'][1]"],
13 | ["%{BKY_ARKANOID_SCENE_INFO_7}", "scene_info['bricks']"],
14 | ["%{BKY_ARKANOID_SCENE_INFO_8}", "scene_info['hard_bricks']"],
15 | ["%{BKY_ARKANOID_SCENE_INFO_9}", "scene_info"]
16 | ];
17 | Blockly.Msg["MLPLAY_GET_CONSTANT_OPTIONS"] = [
18 | ["%{BKY_ARKANOID_CONSTANT_1}", "1/0"],
19 | ["%{BKY_ARKANOID_CONSTANT_2}", "2/200"],
20 | ["%{BKY_ARKANOID_CONSTANT_3}", "3/0"],
21 | ["%{BKY_ARKANOID_CONSTANT_4}", "4/500"],
22 | ["%{BKY_ARKANOID_CONSTANT_5}", "5/40"],
23 | ["%{BKY_ARKANOID_CONSTANT_6}", "6/5"],
24 | ["%{BKY_ARKANOID_CONSTANT_7}", "7/25"],
25 | ["%{BKY_ARKANOID_CONSTANT_8}", "8/10"]
26 | ];
27 | Blockly.Msg["MLPLAY_RETURN_ACTION_OPTIONS"] = [
28 | ["%{BKY_ARKANOID_ACTION_1}", "SERVE_TO_LEFT"],
29 | ["%{BKY_ARKANOID_ACTION_2}", "SERVE_TO_RIGHT"],
30 | ["%{BKY_ARKANOID_ACTION_3}", "MOVE_LEFT"],
31 | ["%{BKY_ARKANOID_ACTION_4}", "MOVE_RIGHT"],
32 | ["%{BKY_ARKANOID_ACTION_5}", "NONE"],
33 | ["%{BKY_ARKANOID_ACTION_6}", "RESET"]
34 | ];
35 |
--------------------------------------------------------------------------------
/js/blocks/plot.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.require('Blockly');
4 | goog.require('Blockly.Blocks');
5 | goog.require('Blockly.FieldDropdown');
6 | goog.require('Blockly.FieldLabel');
7 | goog.require('Blockly.FieldColour');
8 |
9 | Blockly.defineBlocksWithJsonArray([
10 | // Train a model.
11 | {
12 | "type": "plot_plot",
13 | "message0": "%{BKY_PLOT_PLOT}",
14 | "args0": [
15 | {
16 | "type": "input_value",
17 | "name": "X"
18 | },
19 | {
20 | "type": "input_value",
21 | "name": "Y"
22 | },
23 | {
24 | "type": "field_dropdown",
25 | "name": "MARKER",
26 | "options": [
27 | ["None", ""],
28 | ["\u{25CF}", "."],
29 | ["\u{25B2}", "^"],
30 | ["\u{2605}", "*"]
31 | ]
32 | },
33 | {
34 | "type": "field_dropdown",
35 | "name": "LINE",
36 | "options": [
37 | ["None", ""],
38 | ["\u{23AF}\u{23AF}\u{23AF}", "-"],
39 | ["\u{207B}\u{207B}\u{207B}", "--"],
40 | ["\u{2027}\u{2027}\u{2027}\u{2027}\u{2027}", ":"],
41 | ["\u{2012}\u{2027}\u{2012}", "-."]
42 | ]
43 | },
44 | {
45 | "type": "field_colour",
46 | "name": "COLOR",
47 | "colour": "#1f77b4",
48 | "colourOptions":
49 | ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd',
50 | '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf'],
51 | "columns": 5
52 | }
53 | ],
54 | "inputsInline": true,
55 | "previousStatement": null,
56 | "nextStatement": null,
57 | "style": "plot_blocks",
58 | "tooltip": "%{BKY_PLOT_PLOT_TOOLTIP}"
59 | }
60 | ]);
--------------------------------------------------------------------------------
/js/core/utils/math.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Utility methods for math.
9 | * These methods are not specific to Blockly, and could be factored out into
10 | * a JavaScript framework such as Closure.
11 | * @author fraser@google.com (Neil Fraser)
12 | */
13 | 'use strict';
14 |
15 | /**
16 | * @name Blockly.utils.math
17 | * @namespace
18 | */
19 | goog.provide('Blockly.utils.math');
20 |
21 |
22 | /**
23 | * Converts degrees to radians.
24 | * Copied from Closure's goog.math.toRadians.
25 | * @param {number} angleDegrees Angle in degrees.
26 | * @return {number} Angle in radians.
27 | */
28 | Blockly.utils.math.toRadians = function(angleDegrees) {
29 | return angleDegrees * Math.PI / 180;
30 | };
31 |
32 | /**
33 | * Converts radians to degrees.
34 | * Copied from Closure's goog.math.toDegrees.
35 | * @param {number} angleRadians Angle in radians.
36 | * @return {number} Angle in degrees.
37 | */
38 | Blockly.utils.math.toDegrees = function(angleRadians) {
39 | return angleRadians * 180 / Math.PI;
40 | };
41 |
42 | /**
43 | * Clamp the provided number between the lower bound and the upper bound.
44 | * @param {number} lowerBound The desired lower bound.
45 | * @param {number} number The number to clamp.
46 | * @param {number} upperBound The desired upper bound.
47 | * @return {number} The clamped number.
48 | */
49 | Blockly.utils.math.clamp = function(lowerBound, number, upperBound) {
50 | if (upperBound < lowerBound) {
51 | var temp = upperBound;
52 | upperBound = lowerBound;
53 | lowerBound = temp;
54 | }
55 | return Math.max(lowerBound, Math.min(number, upperBound));
56 | };
57 |
--------------------------------------------------------------------------------
/js/ui_msg/en.js:
--------------------------------------------------------------------------------
1 | var MSG = {
2 | title: "Blockly",
3 | blocks: "Blocks",
4 | examples: "Examples",
5 | lang: "Language",
6 | options: "Options",
7 | linkTooltip: "Save and link to blocks.",
8 | runTooltip: "Run the program defined by the blocks in the workspace.",
9 | badCode: "Program error:\n%1",
10 | timeout: "Maximum execution iterations exceeded.",
11 | discard: "Discard all blocks",
12 | download: "Save Python file",
13 | runMLGame: "Play game",
14 | runPython: "Run Python file",
15 | openXml: "Open XML file",
16 | openPython: "Open Python file",
17 | downloadXml: "Save XML file",
18 | en: "English",
19 | zh_hant: "Chinese",
20 | catLogic: "Logic",
21 | catLoops: "Loops",
22 | catMath: "Math",
23 | catText: "Text",
24 | catLists: "Lists",
25 | catDicts: "Dictionaries",
26 | catNdarrays: "Ndarrays",
27 | catColour: "Colour",
28 | catVariables: "Variables",
29 | catFunctions: "Functions",
30 | catFile: "File",
31 | catPlot: "Plot",
32 | catModel: "Model",
33 | listVariable: "list",
34 | ndarrayVariable: "ndarray",
35 | textVariable: "text",
36 | dictVariable: "dictionary",
37 | modelVariable: "model",
38 | objVariable: "object",
39 | filename: "filename",
40 | trainData: "train data",
41 | testData: "test data",
42 | trainTarget: "train target",
43 | testTarget: "test target",
44 | httpRequestError: "There was a problem with the request.",
45 | linkAlert: "Share your blocks with this link:\n\n%1",
46 | hashError: "Sorry, '%1' doesn't correspond with any saved program.",
47 | xmlError: "Could not load your saved file. Perhaps it was created with a different version of Blockly?",
48 | badXml: "Error parsing XML:\n%1\n\nSelect 'OK' to abandon your changes or 'Cancel' to further edit the XML."
49 | };
50 |
--------------------------------------------------------------------------------
/js/game_msg/maze_car.js:
--------------------------------------------------------------------------------
1 | Blockly.Msg["MLPLAY_INIT_INFO_OPTIONS"] = [
2 | ["%{BKY_MAZE_CAR_INIT_INFO_1}", "player"]
3 | ];
4 | Blockly.Msg["MLPLAY_PLAYER_STATUS_OPTIONS"] = [
5 | ["%{BKY_MAZE_CAR_PLAYER_STATUS_1}", "player1"],
6 | ["%{BKY_MAZE_CAR_PLAYER_STATUS_2}", "player2"],
7 | ["%{BKY_MAZE_CAR_PLAYER_STATUS_3}", "player3"],
8 | ["%{BKY_MAZE_CAR_PLAYER_STATUS_4}", "player4"],
9 | ["%{BKY_MAZE_CAR_PLAYER_STATUS_5}", "player5"],
10 | ["%{BKY_MAZE_CAR_PLAYER_STATUS_6}", "player6"]
11 | ];
12 | Blockly.Msg["MLPLAY_GAME_STATUS_OPTIONS"] = [
13 | ["%{BKY_MAZE_CAR_GAME_STATUS_1}", "GAME_ALIVE"],
14 | ["%{BKY_MAZE_CAR_GAME_STATUS_2}", "GAME_PASS"],
15 | ["%{BKY_MAZE_CAR_GAME_STATUS_3}", "GAME_OVER"]
16 | ];
17 | Blockly.Msg["MLPLAY_GET_INFO_OPTIONS"] = [
18 | ["%{BKY_MAZE_CAR_SCENE_INFO_1}", "scene_info['frame']"],
19 | ["%{BKY_MAZE_CAR_SCENE_INFO_2}", "scene_info['status']"],
20 | ["%{BKY_MAZE_CAR_SCENE_INFO_3}", "scene_info['x']"],
21 | ["%{BKY_MAZE_CAR_SCENE_INFO_4}", "scene_info['y']"],
22 | ["%{BKY_MAZE_CAR_SCENE_INFO_5}", "scene_info['angle']"],
23 | ["%{BKY_MAZE_CAR_SCENE_INFO_6}", "scene_info['end']"],
24 | ["%{BKY_MAZE_CAR_SCENE_INFO_7}", "scene_info['R_sensor']"],
25 | ["%{BKY_MAZE_CAR_SCENE_INFO_8}", "scene_info['F_sensor']"],
26 | ["%{BKY_MAZE_CAR_SCENE_INFO_9}", "scene_info['L_sensor']"],
27 | ["%{BKY_MAZE_CAR_SCENE_INFO_10}", "scene_info['R_T_sensor']"],
28 | ["%{BKY_MAZE_CAR_SCENE_INFO_11}", "scene_info['L_T_sensor']"]
29 | ];
30 | Blockly.Msg["MLPLAY_GET_CONSTANT_OPTIONS"] = [
31 | ["%{BKY_MAZE_CAR_CONSTANT_1}", "1/0"],
32 | ["%{BKY_MAZE_CAR_CONSTANT_2}", "2/820"],
33 | ["%{BKY_MAZE_CAR_CONSTANT_3}", "3/0"],
34 | ["%{BKY_MAZE_CAR_CONSTANT_4}", "4/520"]
35 | ];
36 | Blockly.Msg["MLPLAY_RETURN_ACTION_OPTIONS"] = [
37 | ["%{BKY_MAZE_CAR_ACTION_1}", "RESET"]
38 | ];
39 |
--------------------------------------------------------------------------------
/js/mlgame/racingcar.json:
--------------------------------------------------------------------------------
1 | {
2 | "GAME_STATUS": [
3 | ["GAME_ALIVE", "alive", "存活"],
4 | ["GAME_PASS", "pass", "通關"],
5 | ["GAME_OVER", "over", "失敗"]
6 | ],
7 | "SCENE_INFO": [
8 | ["scene_info['frame']", "# frame", "# 幀數"],
9 | ["scene_info['status']", "game status", "遊戲狀態"],
10 | ["scene_info['id']", "player id", "玩家編號"],
11 | ["scene_info['x']", "x position of player", "玩家的 x 座標"],
12 | ["scene_info['y']", "y position of player", "玩家的 y 座標"],
13 | ["scene_info['distance']", "advanced distance of player", "玩家前進的距離"],
14 | ["scene_info['velocity']", "velocity", "玩家的速度"],
15 | ["scene_info['all_cars_pos']", "positions of all cars", "所有車子的位置"],
16 | ["scene_info['coin']", "positions of coins", "金幣的位置"],
17 | ["scene_info['coin_num']", "number of coins obtained", "獲得的金幣數量"]
18 | ],
19 | "CONSTANT": [
20 | [0, "left boundary", "左邊界"],
21 | [1000, "right boundary", "右邊界"],
22 | [0, "top boundary", "上邊界"],
23 | [700, "bottom boundary", "下邊界"],
24 | [60, "car length", "車子長度"],
25 | [30, "car width", "車子寬度"],
26 | [30, "coin length", "金幣長度"],
27 | [31, "coin width", "金幣寬度"]
28 | ],
29 | "ACTION": [
30 | ["['SPEED']", "speed up", "加速"],
31 | ["['BRAKE']", "brake", "減速"],
32 | ["['MOVE_LEFT']", "move left", "向左移動"],
33 | ["['MOVE_RIGHT']", "move left", "向右移動"],
34 | ["['SPEED', 'MOVE_LEFT']", "speed up and move left", "加速並向左移動"],
35 | ["['SPEED', 'MOVE_RIGHT']", "speed up and move right", "加速並向右移動"],
36 | ["['BRAKE', 'MOVE_LEFT']", "brake and move left", "減速並向左移動"],
37 | ["['BRAKE', 'MOVE_RIGHT']", "brake and move right", "減速並向右移動"],
38 | ["RESET", "reset", "重置遊戲"],
39 | ["[]", "do nothing", "不動作"]
40 | ]
41 | }
--------------------------------------------------------------------------------
/js/i18n/tests.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: utf-8 -*-
3 |
4 | # Tests of i18n scripts.
5 | #
6 | # Copyright 2013 Google LLC
7 | #
8 | # Licensed under the Apache License, Version 2.0 (the "License");
9 | # you may not use this file except in compliance with the License.
10 | # You may obtain a copy of the License at
11 | #
12 | # http://www.apache.org/licenses/LICENSE-2.0
13 | #
14 | # Unless required by applicable law or agreed to in writing, software
15 | # distributed under the License is distributed on an "AS IS" BASIS,
16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | # See the License for the specific language governing permissions and
18 | # limitations under the License.
19 |
20 | import common
21 | import re
22 | import unittest
23 |
24 | class TestSequenceFunctions(unittest.TestCase):
25 | def test_insert_breaks(self):
26 | spaces = re.compile(r'\s+|\\n')
27 | def contains_all_chars(orig, result):
28 | return re.sub(spaces, '', orig) == re.sub(spaces, '', result)
29 |
30 | sentences = [u'Quay Pegman qua bên trái hoặc bên phải 90 độ.',
31 | u'Foo bar baz this is english that is okay bye.',
32 | u'If there is a path in the specified direction, \nthen ' +
33 | u'do some actions.',
34 | u'If there is a path in the specified direction, then do ' +
35 | u'the first block of actions. Otherwise, do the second ' +
36 | u'block of actions.']
37 | for sentence in sentences:
38 | output = common.insert_breaks(sentence, 30, 50)
39 | self.assertTrue(contains_all_chars(sentence, output),
40 | u'Mismatch between:\n{0}\n{1}'.format(
41 | re.sub(spaces, '', sentence),
42 | re.sub(spaces, '', output)))
43 |
44 |
45 | if __name__ == '__main__':
46 | unittest.main()
47 |
--------------------------------------------------------------------------------
/js/generators/python/dicts.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.provide('Blockly.Python.dicts');
4 |
5 | goog.require('Blockly.Python');
6 |
7 | Blockly.Python['dicts_get_keys'] = function(block) {
8 | // Get dict keys.
9 | var list = Blockly.Python.valueToCode(block, 'DICT',
10 | Blockly.Python.ORDER_NONE) || '{}';
11 | return [list + '.keys()', Blockly.Python.ORDER_ATOMIC];
12 | };
13 |
14 |
15 | Blockly.Python['dicts_create_with'] = function(block) {
16 | if (block.itemCount_ == 0) {
17 | return ['{}', Blockly.Python.ORDER_ATOMIC];
18 | }
19 |
20 | var code = new Array(block.itemCount_);
21 |
22 | for (var n = 0; n < block.itemCount_; n++) {
23 | var key = Blockly.Python.valueToCode(block, 'KEY' + n,
24 | Blockly.Python.ORDER_NONE) || 'None';
25 | var value = Blockly.Python.valueToCode(block, 'VALUE' + n,
26 | Blockly.Python.ORDER_NONE) || 'None';
27 | code[n] = key +": "+ value;
28 | }
29 | code = '{\n' + Blockly.Python.INDENT + code.join(',\n' + Blockly.Python.INDENT) + '\n}';
30 | return [code, Blockly.Python.ORDER_ATOMIC];
31 | };
32 |
33 | Blockly.Python['dicts_get_value'] = function(block) {
34 | var dict = Blockly.Python.valueToCode(block, 'DICT',
35 | Blockly.Python.ORDER_MEMBER) || '{}';
36 | var key = Blockly.Python.valueToCode(block, 'KEY',
37 | Blockly.Python.ORDER_NONE) || 'None';
38 | var code = dict + '[' + key + ']';
39 | return [code, Blockly.Python.ORDER_ATOMIC];
40 | };
41 |
42 | Blockly.Python['dicts_set_value'] = function(block) {
43 | var dict = Blockly.Python.valueToCode(block, 'DICT',
44 | Blockly.Python.ORDER_MEMBER) || '{}';
45 | var key = Blockly.Python.valueToCode(block, 'KEY',
46 | Blockly.Python.ORDER_NONE) || 'None';
47 | var value = Blockly.Python.valueToCode(block, 'VALUE',
48 | Blockly.Python.ORDER_NONE) || 'None';
49 | var code = dict + '[' + key + '] = ' + value + '\n';
50 | return code;
51 | };
52 |
--------------------------------------------------------------------------------
/js/game_msg/racingcar.js:
--------------------------------------------------------------------------------
1 | Blockly.Msg["MLPLAY_GAME_STATUS_OPTIONS"] = [
2 | ["%{BKY_RACINGCAR_GAME_STATUS_1}", "GAME_ALIVE"],
3 | ["%{BKY_RACINGCAR_GAME_STATUS_2}", "GAME_PASS"],
4 | ["%{BKY_RACINGCAR_GAME_STATUS_3}", "GAME_OVER"]
5 | ];
6 | Blockly.Msg["MLPLAY_GET_INFO_OPTIONS"] = [
7 | ["%{BKY_RACINGCAR_SCENE_INFO_1}", "scene_info['frame']"],
8 | ["%{BKY_RACINGCAR_SCENE_INFO_2}", "scene_info['status']"],
9 | ["%{BKY_RACINGCAR_SCENE_INFO_3}", "scene_info['id']"],
10 | ["%{BKY_RACINGCAR_SCENE_INFO_4}", "scene_info['x']"],
11 | ["%{BKY_RACINGCAR_SCENE_INFO_5}", "scene_info['y']"],
12 | ["%{BKY_RACINGCAR_SCENE_INFO_6}", "scene_info['distance']"],
13 | ["%{BKY_RACINGCAR_SCENE_INFO_7}", "scene_info['velocity']"],
14 | ["%{BKY_RACINGCAR_SCENE_INFO_8}", "scene_info['all_cars_pos']"],
15 | ["%{BKY_RACINGCAR_SCENE_INFO_9}", "scene_info['coin']"],
16 | ["%{BKY_RACINGCAR_SCENE_INFO_10}", "scene_info['coin_num']"]
17 | ];
18 | Blockly.Msg["MLPLAY_GET_CONSTANT_OPTIONS"] = [
19 | ["%{BKY_RACINGCAR_CONSTANT_1}", "1/0"],
20 | ["%{BKY_RACINGCAR_CONSTANT_2}", "2/1000"],
21 | ["%{BKY_RACINGCAR_CONSTANT_3}", "3/0"],
22 | ["%{BKY_RACINGCAR_CONSTANT_4}", "4/700"],
23 | ["%{BKY_RACINGCAR_CONSTANT_5}", "5/60"],
24 | ["%{BKY_RACINGCAR_CONSTANT_6}", "6/30"],
25 | ["%{BKY_RACINGCAR_CONSTANT_7}", "7/30"],
26 | ["%{BKY_RACINGCAR_CONSTANT_8}", "8/31"]
27 | ];
28 | Blockly.Msg["MLPLAY_RETURN_ACTION_OPTIONS"] = [
29 | ["%{BKY_RACINGCAR_ACTION_1}", "['SPEED']"],
30 | ["%{BKY_RACINGCAR_ACTION_2}", "['BRAKE']"],
31 | ["%{BKY_RACINGCAR_ACTION_3}", "['MOVE_LEFT']"],
32 | ["%{BKY_RACINGCAR_ACTION_4}", "['MOVE_RIGHT']"],
33 | ["%{BKY_RACINGCAR_ACTION_5}", "['SPEED', 'MOVE_LEFT']"],
34 | ["%{BKY_RACINGCAR_ACTION_6}", "['SPEED', 'MOVE_RIGHT']"],
35 | ["%{BKY_RACINGCAR_ACTION_7}", "['BRAKE', 'MOVE_LEFT']"],
36 | ["%{BKY_RACINGCAR_ACTION_8}", "['BRAKE', 'MOVE_RIGHT']"],
37 | ["%{BKY_RACINGCAR_ACTION_9}", "RESET"],
38 | ["%{BKY_RACINGCAR_ACTION_10}", "[]"]
39 | ];
40 |
--------------------------------------------------------------------------------
/js/core/renderers/geras/constants.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview An object that provides constants for rendering blocks in Geras
9 | * mode.
10 | * @author kozbial@google.com (Monica Kozbial)
11 | */
12 | 'use strict';
13 |
14 | goog.provide('Blockly.geras.ConstantProvider');
15 |
16 | goog.require('Blockly.blockRendering.ConstantProvider');
17 | goog.require('Blockly.utils.object');
18 |
19 |
20 | /**
21 | * An object that provides constants for rendering blocks in Geras mode.
22 | * @constructor
23 | * @package
24 | * @extends {Blockly.blockRendering.ConstantProvider}
25 | */
26 | Blockly.geras.ConstantProvider = function() {
27 | Blockly.geras.ConstantProvider.superClass_.constructor.call(this);
28 |
29 | /**
30 | * @override
31 | */
32 | this.FIELD_TEXT_BASELINE_CENTER = false;
33 |
34 | // The dark/shadow path in classic rendering is the same as the normal block
35 | // path, but translated down one and right one.
36 | this.DARK_PATH_OFFSET = 1;
37 |
38 | /**
39 | * The maximum width of a bottom row that follows a statement input and has
40 | * inputs inline.
41 | * @type {number}
42 | */
43 | this.MAX_BOTTOM_WIDTH = 30;
44 | };
45 | Blockly.utils.object.inherits(Blockly.geras.ConstantProvider,
46 | Blockly.blockRendering.ConstantProvider);
47 |
48 |
49 | /**
50 | * @override
51 | */
52 | Blockly.geras.ConstantProvider.prototype.getCSS_ = function(selector) {
53 | return Blockly.geras.ConstantProvider.superClass_.getCSS_.call(this, selector)
54 | .concat([
55 | /* eslint-disable indent */
56 | // Insertion marker.
57 | selector + ' .blocklyInsertionMarker>.blocklyPathLight,',
58 | selector + ' .blocklyInsertionMarker>.blocklyPathDark {',
59 | 'fill-opacity: ' + this.INSERTION_MARKER_OPACITY + ';',
60 | 'stroke: none;',
61 | '}',
62 | /* eslint-enable indent */
63 | ]);
64 | };
65 |
--------------------------------------------------------------------------------
/python/examples/maze_car/2. manual.py:
--------------------------------------------------------------------------------
1 | import pickle
2 | import os
3 | from pynput import keyboard
4 | from collections import defaultdict
5 |
6 | _KEYBOARD_ON_PRESSED = None
7 |
8 | def on_press(key):
9 | _KEYBOARD_ON_PRESSED[str(key)] = True
10 |
11 | def on_release(key):
12 | _KEYBOARD_ON_PRESSED[str(key)] = False
13 |
14 | _KEYBOARD_ON_PRESSED = defaultdict(bool)
15 | listener = keyboard.Listener(
16 | on_press=on_press,
17 | on_release=on_release)
18 | listener.start()
19 |
20 |
21 | class MLPlay:
22 | def __init__(self, player):
23 | self.f_sensor_value = 0
24 | self.r_sensor_value = 0
25 | self.l_sensor_value = 0
26 | self.left_PWM = 0
27 | self.right_PWM = 0
28 | self.feature = []
29 | self.target = []
30 | def update(self, scene_info):
31 | if scene_info['status'] != "GAME_PASS":
32 | with open(os.path.join(os.path.dirname(__file__), 'feature.pickle'), 'wb') as f:
33 | pickle.dump(self.feature, f)
34 | with open(os.path.join(os.path.dirname(__file__), 'target.pickle'), 'wb') as f:
35 | pickle.dump(self.target, f)
36 | elif _KEYBOARD_ON_PRESSED["Key.up"]:
37 | self.left_PWM = 150
38 | self.right_PWM = 150
39 | elif _KEYBOARD_ON_PRESSED["Key.right"]:
40 | self.left_PWM = 100
41 | self.right_PWM = -100
42 | elif _KEYBOARD_ON_PRESSED["Key.left"]:
43 | self.left_PWM = -100
44 | self.right_PWM = 100
45 | elif _KEYBOARD_ON_PRESSED["Key.down"]:
46 | self.left_PWM = -150
47 | self.right_PWM = -150
48 | else:
49 | self.left_PWM = 0
50 | self.right_PWM = 0
51 | self.feature.append([scene_info['F_sensor'], scene_info['L_sensor'], scene_info['R_sensor']])
52 | self.target.append([self.left_PWM, self.right_PWM])
53 | return [{'left_PWM': self.left_PWM, 'right_PWM': self.right_PWM}]
54 | def reset(self):
55 | pass
--------------------------------------------------------------------------------
/python/examples/racingcar/2. manual.py:
--------------------------------------------------------------------------------
1 | from pynput import keyboard
2 | from collections import defaultdict
3 | import pickle
4 | import os
5 |
6 | _KEYBOARD_ON_PRESSED = None
7 |
8 | def on_press(key):
9 | _KEYBOARD_ON_PRESSED[str(key)] = True
10 |
11 | def on_release(key):
12 | _KEYBOARD_ON_PRESSED[str(key)] = False
13 |
14 | _KEYBOARD_ON_PRESSED = defaultdict(bool)
15 | listener = keyboard.Listener(
16 | on_press=on_press,
17 | on_release=on_release)
18 | listener.start()
19 |
20 | class MLPlay:
21 | def __init__(self, player):
22 | self.player = player
23 | self.other_cars_position = []
24 | self.player_car_position = []
25 | self.action = []
26 | def update(self, scene_info):
27 | if scene_info['status'] == "RUNNING":
28 | if _KEYBOARD_ON_PRESSED["Key.right"]:
29 | self.player_car_position.append([scene_info['x'], scene_info['y']])
30 | self.action.append(1)
31 | return ['SPEED']
32 | elif _KEYBOARD_ON_PRESSED["Key.left"]:
33 | self.player_car_position.append([scene_info['x'], scene_info['y']])
34 | self.action.append(2)
35 | return ['BRAKE']
36 | elif _KEYBOARD_ON_PRESSED["Key.up"]:
37 | self.player_car_position.append([scene_info['x'], scene_info['y']])
38 | self.action.append(3)
39 | return ['MOVE_LEFT']
40 | elif _KEYBOARD_ON_PRESSED["Key.down"]:
41 | self.player_car_position.append([scene_info['x'], scene_info['y']])
42 | self.action.append(4)
43 | return ['MOVE_RIGHT']
44 | elif scene_info['status'] == "END":
45 | with open(os.path.join(os.path.dirname(__file__), 'feature.pickle'), 'wb') as f:
46 | pickle.dump(self.player_car_position, f)
47 | with open(os.path.join(os.path.dirname(__file__), 'target.pickle'), 'wb') as f:
48 | pickle.dump(self.action, f)
49 | def reset(self):
50 | pass
--------------------------------------------------------------------------------
/python/examples/arkanoid/2. manual.py:
--------------------------------------------------------------------------------
1 | import pickle
2 | import os
3 | from pynput import keyboard
4 | from collections import defaultdict
5 |
6 | _KEYBOARD_ON_PRESSED = None
7 |
8 | def on_press(key):
9 | _KEYBOARD_ON_PRESSED[str(key)] = True
10 |
11 | def on_release(key):
12 | _KEYBOARD_ON_PRESSED[str(key)] = False
13 |
14 | _KEYBOARD_ON_PRESSED = defaultdict(bool)
15 | listener = keyboard.Listener(
16 | on_press=on_press,
17 | on_release=on_release)
18 | listener.start()
19 |
20 |
21 | class MLPlay:
22 | def __init__(self):
23 | self.ball_served = False
24 | self.actions = []
25 | self.positions = []
26 | def update(self, scene_info):
27 | if scene_info['status'] == "GAME_PASS" or scene_info['status'] == "GAME_OVER":
28 | with open(os.path.join(os.path.dirname(__file__), 'target.pickle'), 'wb') as f:
29 | pickle.dump(self.actions, f)
30 | with open(os.path.join(os.path.dirname(__file__), 'feature.pickle'), 'wb') as f:
31 | pickle.dump(self.positions, f)
32 | return "RESET"
33 | if not self.ball_served:
34 | if (_KEYBOARD_ON_PRESSED["'A'"] or _KEYBOARD_ON_PRESSED["'a'"]):
35 | self.ball_served = True
36 | return "SERVE_TO_LEFT"
37 | elif (_KEYBOARD_ON_PRESSED["'D'"] or _KEYBOARD_ON_PRESSED["'d'"]):
38 | self.ball_served = True
39 | return "SERVE_TO_RIGHT"
40 | else:
41 | if _KEYBOARD_ON_PRESSED["Key.left"]:
42 | self.ball_served = True
43 | self.positions.append([scene_info['ball'][0], scene_info['ball'][1]])
44 | self.actions.append(1)
45 | return "MOVE_LEFT"
46 | elif _KEYBOARD_ON_PRESSED["Key.right"]:
47 | self.ball_served = True
48 | self.positions.append([scene_info['ball'][0], scene_info['ball'][1]])
49 | self.actions.append(0)
50 | return "MOVE_RIGHT"
51 | def reset(self):
52 | self.ball_served = False
--------------------------------------------------------------------------------
/media/sprites.svg:
--------------------------------------------------------------------------------
1 |
2 |
75 |
--------------------------------------------------------------------------------
/js/core/interfaces/i_accessibility.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2020 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview AST Node and keyboard navigation interfaces.
9 | * @author samelh@google.com (Sam El-Husseini)
10 | */
11 |
12 | 'use strict';
13 |
14 | goog.provide('Blockly.IASTNodeLocation');
15 | goog.provide('Blockly.IASTNodeLocationSvg');
16 | goog.provide('Blockly.IASTNodeLocationWithBlock');
17 | goog.provide('Blockly.IBlocklyActionable');
18 |
19 | /**
20 | * An AST node location interface.
21 | * @interface
22 | */
23 | Blockly.IASTNodeLocation = function() {};
24 |
25 | /**
26 | * An AST node location SVG interface.
27 | * @interface
28 | * @extends {Blockly.IASTNodeLocation}
29 | */
30 | Blockly.IASTNodeLocationSvg = function() {};
31 |
32 | /**
33 | * Add the marker svg to this node's svg group.
34 | * @param {SVGElement} markerSvg The svg root of the marker to be added to the
35 | * svg group.
36 | */
37 | Blockly.IASTNodeLocationSvg.prototype.setMarkerSvg;
38 |
39 | /**
40 | * Add the cursor svg to this node's svg group.
41 | * @param {SVGElement} cursorSvg The svg root of the cursor to be added to the
42 | * svg group.
43 | */
44 | Blockly.IASTNodeLocationSvg.prototype.setCursorSvg;
45 |
46 | /**
47 | * An AST node location that has an associated block.
48 | * @interface
49 | * @extends {Blockly.IASTNodeLocation}
50 | */
51 | Blockly.IASTNodeLocationWithBlock = function() {};
52 |
53 | /**
54 | * Get the source block associated with this node.
55 | * @return {Blockly.Block} The source block.
56 | */
57 | Blockly.IASTNodeLocationWithBlock.prototype.getSourceBlock;
58 |
59 |
60 | /**
61 | * An interface for an object that handles Blockly actions when keyboard
62 | * navigation is enabled.
63 | * @interface
64 | */
65 | Blockly.IBlocklyActionable = function() {};
66 |
67 | /**
68 | * Handles the given action.
69 | * @param {!Blockly.Action} action The action to be handled.
70 | * @return {boolean} True if the action has been handled, false otherwise.
71 | */
72 | Blockly.IBlocklyActionable.prototype.onBlocklyAction;
73 |
--------------------------------------------------------------------------------
/js/mlgame/pingpong.json:
--------------------------------------------------------------------------------
1 | {
2 | "INIT_INFO": [
3 | ["side", "player number", "玩家編號"]
4 | ],
5 | "PLAYER_STATUS": [
6 | ["1P", "1P", "1P"],
7 | ["2P", "2P", "2P"]
8 | ],
9 | "GAME_STATUS": [
10 | ["GAME_ALIVE", "alive", "存活"],
11 | ["GAME_1P_WIN", "1P wins", "1P 勝利"],
12 | ["GAME_2P_WIN", "2P wins", "2P 勝利"],
13 | ["GAME_DRAW", "draw", "平手"]
14 | ],
15 | "SCENE_INFO": [
16 | ["scene_info['frame']", "# frame", "# 幀數"],
17 | ["scene_info['status']", "game status", "遊戲狀態"],
18 | ["scene_info['ball'][0]", "x coordinate of ball", "球的 x 座標"],
19 | ["scene_info['ball'][1]", "y coordinate of ball", "球的 y 座標"],
20 | ["scene_info['ball_speed'][0]", "ball velocity along x-axis", "球的 x 方向速度"],
21 | ["scene_info['ball_speed'][1]", "ball velocity along y-axis", "球的 y 方向速度"],
22 | ["scene_info['platform_1P'][0]", "x coordinate of 1P platform", "1P 平台的 x 座標"],
23 | ["scene_info['platform_1P'][1]", "y coordinate of 1P platform", "1P 平台的 y 座標"],
24 | ["scene_info['platform_2P'][0]", "x coordinate of 2P platform", "2P 平台的 x 座標"],
25 | ["scene_info['platform_2P'][1]", "y coordinate of 2P platform", "2P 平台的 y 座標"],
26 | ["scene_info['blocker'][0]", "x coordinate of blocker position", "障礙物的 x 座標"],
27 | ["scene_info['blocker'][1]", "y coordinate of blocker position", "障礙物的 y 座標"],
28 | ["scene_info", "dictionary of all information", "包含所有資訊的字典"]
29 | ],
30 | "CONSTANT": [
31 | [0, "left boundary", "左邊界"],
32 | [200, "right boundary", "右邊界"],
33 | [0, "top boundary", "上邊界"],
34 | [500, "bottom boundary", "下邊界"],
35 | [40, "platform width", "平台寬度"],
36 | [30, "platform height", "平台高度"],
37 | [30, "blocker width", "障礙物寬度"],
38 | [20, "blocker height", "障礙物高度"]
39 | ],
40 | "ACTION": [
41 | ["SERVE_TO_LEFT", "serving left", "向左發球"],
42 | ["SERVE_TO_RIGHT", "serving right", "向右發球"],
43 | ["MOVE_LEFT", "moving left", "向左移動"],
44 | ["MOVE_RIGHT", "moving right", "向右移動"],
45 | ["NONE", "doing nothing", "不動作"],
46 | ["RESET", "reset", "重置"]
47 | ]
48 | }
--------------------------------------------------------------------------------
/js/game_msg/pingpong.js:
--------------------------------------------------------------------------------
1 | Blockly.Msg["MLPLAY_INIT_INFO_OPTIONS"] = [
2 | ["%{BKY_PINGPONG_INIT_INFO_1}", "side"]
3 | ];
4 | Blockly.Msg["MLPLAY_PLAYER_STATUS_OPTIONS"] = [
5 | ["%{BKY_PINGPONG_PLAYER_STATUS_1}", "1P"],
6 | ["%{BKY_PINGPONG_PLAYER_STATUS_2}", "2P"]
7 | ];
8 | Blockly.Msg["MLPLAY_GAME_STATUS_OPTIONS"] = [
9 | ["%{BKY_PINGPONG_GAME_STATUS_1}", "GAME_ALIVE"],
10 | ["%{BKY_PINGPONG_GAME_STATUS_2}", "GAME_1P_WIN"],
11 | ["%{BKY_PINGPONG_GAME_STATUS_3}", "GAME_2P_WIN"],
12 | ["%{BKY_PINGPONG_GAME_STATUS_4}", "GAME_DRAW"]
13 | ];
14 | Blockly.Msg["MLPLAY_GET_INFO_OPTIONS"] = [
15 | ["%{BKY_PINGPONG_SCENE_INFO_1}", "scene_info['frame']"],
16 | ["%{BKY_PINGPONG_SCENE_INFO_2}", "scene_info['status']"],
17 | ["%{BKY_PINGPONG_SCENE_INFO_3}", "scene_info['ball'][0]"],
18 | ["%{BKY_PINGPONG_SCENE_INFO_4}", "scene_info['ball'][1]"],
19 | ["%{BKY_PINGPONG_SCENE_INFO_5}", "scene_info['ball_speed'][0]"],
20 | ["%{BKY_PINGPONG_SCENE_INFO_6}", "scene_info['ball_speed'][1]"],
21 | ["%{BKY_PINGPONG_SCENE_INFO_7}", "scene_info['platform_1P'][0]"],
22 | ["%{BKY_PINGPONG_SCENE_INFO_8}", "scene_info['platform_1P'][1]"],
23 | ["%{BKY_PINGPONG_SCENE_INFO_9}", "scene_info['platform_2P'][0]"],
24 | ["%{BKY_PINGPONG_SCENE_INFO_10}", "scene_info['platform_2P'][1]"],
25 | ["%{BKY_PINGPONG_SCENE_INFO_11}", "scene_info['blocker'][0]"],
26 | ["%{BKY_PINGPONG_SCENE_INFO_12}", "scene_info['blocker'][1]"],
27 | ["%{BKY_PINGPONG_SCENE_INFO_13}", "scene_info"]
28 | ];
29 | Blockly.Msg["MLPLAY_GET_CONSTANT_OPTIONS"] = [
30 | ["%{BKY_PINGPONG_CONSTANT_1}", "1/0"],
31 | ["%{BKY_PINGPONG_CONSTANT_2}", "2/200"],
32 | ["%{BKY_PINGPONG_CONSTANT_3}", "3/0"],
33 | ["%{BKY_PINGPONG_CONSTANT_4}", "4/500"],
34 | ["%{BKY_PINGPONG_CONSTANT_5}", "5/40"],
35 | ["%{BKY_PINGPONG_CONSTANT_6}", "6/30"],
36 | ["%{BKY_PINGPONG_CONSTANT_7}", "7/30"],
37 | ["%{BKY_PINGPONG_CONSTANT_8}", "8/20"]
38 | ];
39 | Blockly.Msg["MLPLAY_RETURN_ACTION_OPTIONS"] = [
40 | ["%{BKY_PINGPONG_ACTION_1}", "SERVE_TO_LEFT"],
41 | ["%{BKY_PINGPONG_ACTION_2}", "SERVE_TO_RIGHT"],
42 | ["%{BKY_PINGPONG_ACTION_3}", "MOVE_LEFT"],
43 | ["%{BKY_PINGPONG_ACTION_4}", "MOVE_RIGHT"],
44 | ["%{BKY_PINGPONG_ACTION_5}", "NONE"],
45 | ["%{BKY_PINGPONG_ACTION_6}", "RESET"]
46 | ];
47 |
--------------------------------------------------------------------------------
/js/core/utils/object.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Utility methods for objects.
9 | * @author samelh@google.com (Sam El-Husseini)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.utils.object');
14 |
15 |
16 | /**
17 | * Inherit the prototype methods from one constructor into another.
18 | *
19 | * @param {!Function} childCtor Child class.
20 | * @param {!Function} parentCtor Parent class.
21 | * @suppress {strictMissingProperties} superClass_ is not defined on Function.
22 | */
23 | Blockly.utils.object.inherits = function(childCtor, parentCtor) {
24 | childCtor.superClass_ = parentCtor.prototype;
25 | childCtor.prototype = Object.create(parentCtor.prototype);
26 | childCtor.prototype.constructor = childCtor;
27 | };
28 |
29 | /**
30 | * Copies all the members of a source object to a target object.
31 | * @param {!Object} target Target.
32 | * @param {!Object} source Source.
33 | */
34 | Blockly.utils.object.mixin = function(target, source) {
35 | for (var x in source) {
36 | target[x] = source[x];
37 | }
38 | };
39 |
40 | /**
41 | * Complete a deep merge of all members of a source object with a target object.
42 | * @param {!Object} target Target.
43 | * @param {!Object} source Source.
44 | * @return {!Object} The resulting object.
45 | */
46 | Blockly.utils.object.deepMerge = function(target, source) {
47 | for (var x in source) {
48 | if (source[x] != null && typeof source[x] === 'object') {
49 | target[x] = Blockly.utils.object.deepMerge(
50 | target[x] || Object.create(null), source[x]);
51 | } else {
52 | target[x] = source[x];
53 | }
54 | }
55 | return target;
56 | };
57 |
58 | /**
59 | * Returns an array of a given object's own enumerable property values.
60 | * @param {!Object} obj Object containing values.
61 | * @return {!Array} Array of values.
62 | */
63 | Blockly.utils.object.values = function(obj) {
64 | if (Object.values) {
65 | /* eslint-disable es5/no-es6-methods */
66 | return Object.values(obj);
67 | /* eslint-enable es5/no-es6-methods */
68 | }
69 | // Fallback for IE.
70 | return Object.keys(obj).map(function(e) {
71 | return obj[e];
72 | });
73 | };
74 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | | :warning: WARNING |
2 | | :---------------- |
3 | | Blockly-App is deprecated after version 1.2.6. The latest version will continue to be released under the name [PAIA-Desktop](https://github.com/PAIA-Playful-AI-Arena/Paia-Desktop). |
4 |
5 | # Blockly-App
6 |
7 | Blockly-App is a visual programming editor based on Blockly, and built on Electron. We designed it to make everyone can easily build AI to play games.
8 |
9 | ## Downloads
10 |
11 | Pre-built installers of latest release can be downloaded from the links below.
12 |
13 | #### Windows 64-bit
14 |
15 | [](https://github.com/jason53415/blockly-app/releases/download/v1.2.6/blockly-app-1.2.6.Setup.exe) [](https://github.com/jason53415/blockly-app/releases/download/v1.2.6/blockly-app-win32-x64-1.2.6.zip)
16 | #### macOS 64-bit
17 |
18 | [](https://github.com/jason53415/blockly-app/releases/download/v1.2.6/blockly-app-1.2.6.dmg) [](https://github.com/jason53415/blockly-app/releases/download/v1.2.6/blockly-app-darwin-x64-1.2.6.zip)
19 |
20 | #### Linux 64-bit
21 |
22 | [](https://github.com/jason53415/blockly-app/releases/download/v1.2.6/blockly-app-1.2.6.deb) [](https://github.com/jason53415/blockly-app/releases/download/v1.2.6/blockly-app-1.2.6.rpm)
23 |
24 | ## Building
25 |
26 | To build Blockly-App from source you'll need [Git](https://git-scm.com), [Python 3.6+](https://www.python.org/) and [Node.js](https://nodejs.org/en/download/) (which comes with [npm](http://npmjs.com)) installed on your computer. From your command line:
27 |
28 | ```bash
29 | # Clone this repository
30 | git clone --recursive https://github.com/jason53415/blockly-app.git
31 | # Go into the repository
32 | cd blockly-app
33 | # Install Python dependencies
34 | pip install -r requirements.txt
35 | # Install Node.js dependencies
36 | npm install
37 | # Build Python executable
38 | npm run make-py
39 | # Build Blockly-App executable
40 | npm run make
41 | ```
42 | The built executables can be found in the `out` directory.
--------------------------------------------------------------------------------
/js/core/utils/xml.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2018 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview XML element manipulation.
9 | * These methods are not specific to Blockly, and could be factored out into
10 | * a JavaScript framework such as Closure.
11 | * @author fraser@google.com (Neil Fraser)
12 | */
13 | 'use strict';
14 |
15 | /**
16 | * @name Blockly.utils.xml
17 | * @namespace
18 | */
19 | goog.provide('Blockly.utils.xml');
20 |
21 | /**
22 | * Namespace for Blockly's XML.
23 | */
24 | Blockly.utils.xml.NAME_SPACE = 'https://developers.google.com/blockly/xml';
25 |
26 | /**
27 | * Get the document object. This method is overridden in the Node.js build of
28 | * Blockly. See gulpfile.js, package-blockly-node task.
29 | * @return {!Document} The document object.
30 | * @public
31 | */
32 | Blockly.utils.xml.document = function() {
33 | return document;
34 | };
35 |
36 | /**
37 | * Create DOM element for XML.
38 | * @param {string} tagName Name of DOM element.
39 | * @return {!Element} New DOM element.
40 | * @public
41 | */
42 | Blockly.utils.xml.createElement = function(tagName) {
43 | return Blockly.utils.xml.document().createElementNS(
44 | Blockly.utils.xml.NAME_SPACE, tagName);
45 | };
46 |
47 | /**
48 | * Create text element for XML.
49 | * @param {string} text Text content.
50 | * @return {!Text} New DOM text node.
51 | * @public
52 | */
53 | Blockly.utils.xml.createTextNode = function(text) {
54 | return Blockly.utils.xml.document().createTextNode(text);
55 | };
56 |
57 | /**
58 | * Converts an XML string into a DOM tree.
59 | * @param {string} text XML string.
60 | * @return {Document} The DOM document.
61 | * @throws if XML doesn't parse.
62 | * @public
63 | */
64 | Blockly.utils.xml.textToDomDocument = function(text) {
65 | var oParser = new DOMParser();
66 | return oParser.parseFromString(text, 'text/xml');
67 | };
68 |
69 | /**
70 | * Converts a DOM structure into plain text.
71 | * Currently the text format is fairly ugly: all one line with no whitespace.
72 | * @param {!Node} dom A tree of XML nodes.
73 | * @return {string} Text representation.
74 | * @public
75 | */
76 | Blockly.utils.xml.domToText = function(dom) {
77 | var oSerializer = new XMLSerializer();
78 | return oSerializer.serializeToString(dom);
79 | };
80 |
--------------------------------------------------------------------------------
/js/core/workspace_events.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Class for a finished loading workspace event.
9 | * @author BeksOmega
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.Events.FinishedLoading');
14 |
15 | goog.require('Blockly.Events');
16 | goog.require('Blockly.Events.Ui');
17 | goog.require('Blockly.utils.object');
18 |
19 |
20 | /**
21 | * Class for a finished loading event.
22 | * Used to notify the developer when the workspace has finished loading (i.e
23 | * domToWorkspace).
24 | * Finished loading events do not record undo or redo.
25 | * @param {!Blockly.Workspace} workspace The workspace that has finished
26 | * loading.
27 | * @extends {Blockly.Events.Abstract}
28 | * @constructor
29 | */
30 | Blockly.Events.FinishedLoading = function(workspace) {
31 | /**
32 | * The workspace identifier for this event.
33 | * @type {string}
34 | */
35 | this.workspaceId = workspace.id;
36 |
37 | /**
38 | * The event group ID for the group this event belongs to. Groups define
39 | * events that should be treated as an single action from the user's
40 | * perspective, and should be undone together.
41 | * @type {string}
42 | */
43 | this.group = Blockly.Events.getGroup();
44 |
45 | // Workspace events do not undo or redo.
46 | this.recordUndo = false;
47 | };
48 | Blockly.utils.object.inherits(Blockly.Events.FinishedLoading,
49 | Blockly.Events.Ui);
50 |
51 | /**
52 | * Type of this event.
53 | * @type {string}
54 | */
55 | Blockly.Events.FinishedLoading.prototype.type = Blockly.Events.FINISHED_LOADING;
56 |
57 | /**
58 | * Encode the event as JSON.
59 | * @return {!Object} JSON representation.
60 | */
61 | Blockly.Events.FinishedLoading.prototype.toJson = function() {
62 | var json = {
63 | 'type': this.type,
64 | };
65 | if (this.group) {
66 | json['group'] = this.group;
67 | }
68 | if (this.workspaceId) {
69 | json['workspaceId'] = this.workspaceId;
70 | }
71 | return json;
72 | };
73 |
74 | /**
75 | * Decode the JSON event.
76 | * @param {!Object} json JSON representation.
77 | */
78 | Blockly.Events.FinishedLoading.prototype.fromJson = function(json) {
79 | this.workspaceId = json['workspaceId'];
80 | this.group = json['group'];
81 | };
82 |
--------------------------------------------------------------------------------
/python/examples/pingpong/2. manual.py:
--------------------------------------------------------------------------------
1 | import pickle
2 | import os
3 | from pynput import keyboard
4 | from collections import defaultdict
5 |
6 | _KEYBOARD_ON_PRESSED = None
7 |
8 | def on_press(key):
9 | _KEYBOARD_ON_PRESSED[str(key)] = True
10 |
11 | def on_release(key):
12 | _KEYBOARD_ON_PRESSED[str(key)] = False
13 |
14 | _KEYBOARD_ON_PRESSED = defaultdict(bool)
15 | listener = keyboard.Listener(
16 | on_press=on_press,
17 | on_release=on_release)
18 | listener.start()
19 |
20 | class MLPlay:
21 | def __init__(self, side):
22 | self.ball_served = False
23 | self.side = side
24 | self.action = []
25 | self.ball_position = []
26 | def update(self, scene_info):
27 | if self.side == '1P':
28 | if scene_info['status'] != "GAME_ALIVE":
29 | with open(os.path.join(os.path.dirname(__file__), 'feature.pickle'), 'wb') as f:
30 | pickle.dump(self.ball_position, f)
31 | with open(os.path.join(os.path.dirname(__file__), 'target.pickle'), 'wb') as f:
32 | pickle.dump(self.action, f)
33 | return "RESET"
34 | if not self.ball_served:
35 | self.ball_served = True
36 | return "SERVE_TO_LEFT"
37 | else:
38 | if _KEYBOARD_ON_PRESSED["Key.left"]:
39 | self.ball_position.append([scene_info['ball_speed'][0], scene_info['ball_speed'][1]])
40 | self.action.append(1)
41 | return "MOVE_LEFT"
42 | elif _KEYBOARD_ON_PRESSED["Key.right"]:
43 | self.ball_position.append([scene_info['ball_speed'][0], scene_info['ball_speed'][1]])
44 | self.action.append(0)
45 | return "MOVE_RIGHT"
46 | else:
47 | if scene_info['status'] != "GAME_ALIVE":
48 | return "RESET"
49 | if not self.ball_served:
50 | self.ball_served = True
51 | return "SERVE_TO_LEFT"
52 | else:
53 | if (_KEYBOARD_ON_PRESSED["'A'"] or _KEYBOARD_ON_PRESSED["'a'"]):
54 | return "MOVE_LEFT"
55 | elif (_KEYBOARD_ON_PRESSED["'D'"] or _KEYBOARD_ON_PRESSED["'d'"]):
56 | return "MOVE_RIGHT"
57 | def reset(self):
58 | self.ball_served = False
--------------------------------------------------------------------------------
/renderer.js:
--------------------------------------------------------------------------------
1 | // This file is required by the index.html file and will
2 | // be executed in the renderer process for that window.
3 | // No Node.js APIs are available in this process because
4 | // `nodeIntegration` is turned off. Use `preload.js` to
5 | // selectively enable features needed in the rendering
6 | // process.
7 | const { dialog, shell } = require('electron').remote;
8 | const { PythonShell } = require('python-shell');
9 | const buffer = require('buffer');
10 | const Store = require('electron-store');
11 | const store = new Store();
12 | const path = require('path');
13 | const fs = require('fs');
14 |
15 | window.pythonRun = function(options, script, tmp_file, cwd) {
16 | var old_cwd = process.cwd();
17 | process.chdir(cwd);
18 | let python = new PythonShell(script, options);
19 | python.on('message', function (message) {
20 | var full_message = document.getElementById('content_console').textContent + message + '\n';
21 | document.getElementById('content_console').textContent = full_message.slice(-5000);
22 | var e = document.getElementById('console-body');
23 | e.scrollTo(0, e.scrollHeight);
24 | });
25 | python.on('stderr', function (stderr) {
26 | document.getElementById('content_console').textContent += stderr + '\n';
27 | var e = document.getElementById('console-body');
28 | e.scrollTo(0, e.scrollHeight);
29 | });
30 | python.on('close', function () {
31 | document.getElementById('content_console').textContent += '> Python program finished\n';
32 | var e = document.getElementById('console-body');
33 | e.scrollTo(0, e.scrollHeight);
34 | fs.unlinkSync(tmp_file);
35 | process.chdir(old_cwd);
36 | });
37 | python.on('error', function () {
38 | window.alert('Error: process exited with code ' + python.exitCode);
39 | });
40 | };
41 |
42 | window.writeFile = function(file, data) {
43 | fs.writeFileSync(file, data, (err) => {
44 | if (err) window.alert(err);
45 | console.log('The file has been saved at ' + file);
46 | });
47 | };
48 |
49 | window.readFile = function(file) {
50 | return fs.readFileSync(file, 'utf8', (err, data) => {
51 | if (err) window.alert(err);
52 | return data;
53 | });
54 | };
55 |
56 | window.selectPath = function(options) {
57 | return dialog.showOpenDialogSync(options);
58 | };
59 |
60 | window.openPath = function(pathname) {
61 | shell.openPath(pathname);
62 | };
63 |
--------------------------------------------------------------------------------
/js/core/renderers/minimalist/renderer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Minimalist renderer.
9 | */
10 | 'use strict';
11 |
12 | goog.provide('Blockly.minimalist.Renderer');
13 |
14 | goog.require('Blockly.blockRendering');
15 | goog.require('Blockly.blockRendering.Renderer');
16 | goog.require('Blockly.utils.object');
17 | goog.require('Blockly.minimalist.ConstantProvider');
18 | goog.require('Blockly.minimalist.Drawer');
19 | goog.require('Blockly.minimalist.RenderInfo');
20 |
21 |
22 | /**
23 | * The minimalist renderer.
24 | * @param {string} name The renderer name.
25 | * @package
26 | * @constructor
27 | * @extends {Blockly.blockRendering.Renderer}
28 | */
29 | Blockly.minimalist.Renderer = function(name) {
30 | Blockly.minimalist.Renderer.superClass_.constructor.call(this, name);
31 | };
32 | Blockly.utils.object.inherits(Blockly.minimalist.Renderer,
33 | Blockly.blockRendering.Renderer);
34 |
35 | /**
36 | * Create a new instance of the renderer's constant provider.
37 | * @return {!Blockly.minimalist.ConstantProvider} The constant provider.
38 | * @protected
39 | * @override
40 | */
41 | Blockly.minimalist.Renderer.prototype.makeConstants_ = function() {
42 | return new Blockly.minimalist.ConstantProvider();
43 | };
44 |
45 | /**
46 | * Create a new instance of the renderer's render info object.
47 | * @param {!Blockly.BlockSvg} block The block to measure.
48 | * @return {!Blockly.minimalist.RenderInfo} The render info object.
49 | * @protected
50 | * @override
51 | */
52 | Blockly.minimalist.Renderer.prototype.makeRenderInfo_ = function(block) {
53 | return new Blockly.minimalist.RenderInfo(this, block);
54 | };
55 |
56 | /**
57 | * Create a new instance of the renderer's drawer.
58 | * @param {!Blockly.BlockSvg} block The block to render.
59 | * @param {!Blockly.blockRendering.RenderInfo} info An object containing all
60 | * information needed to render this block.
61 | * @return {!Blockly.minimalist.Drawer} The drawer.
62 | * @protected
63 | * @override
64 | */
65 | Blockly.minimalist.Renderer.prototype.makeDrawer_ = function(block, info) {
66 | return new Blockly.minimalist.Drawer(block,
67 | /** @type {!Blockly.minimalist.RenderInfo} */ (info));
68 | };
69 |
70 | Blockly.blockRendering.register('minimalist', Blockly.minimalist.Renderer);
71 |
--------------------------------------------------------------------------------
/js/core/theme/classic.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2018 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Classic theme.
9 | * Contains multi-coloured border to create shadow effect.
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.Themes.Classic');
14 |
15 | goog.require('Blockly.Theme');
16 |
17 |
18 | // Temporary holding object.
19 | Blockly.Themes.Classic = {};
20 |
21 | Blockly.Themes.Classic.defaultBlockStyles = {
22 | "colour_blocks": {
23 | "colourPrimary": "20"
24 | },
25 | "logic_blocks": {
26 | "colourPrimary": "100"
27 | },
28 | "loop_blocks": {
29 | "colourPrimary": "140"
30 | },
31 | "math_blocks": {
32 | "colourPrimary": "170"
33 | },
34 | "text_blocks": {
35 | "colourPrimary": "190"
36 | },
37 | "list_blocks": {
38 | "colourPrimary": "210"
39 | },
40 | "dict_blocks": {
41 | "colourPrimary": "230"
42 | },
43 | "ndarray_blocks": {
44 | "colourPrimary": "250"
45 | },
46 | "model_blocks": {
47 | "colourPrimary": "270"
48 | },
49 | "variable_blocks": {
50 | "colourPrimary": "290"
51 | },
52 | "variable_dynamic_blocks": {
53 | "colourPrimary": "300"
54 | },
55 | "procedure_blocks": {
56 | "colourPrimary": "310"
57 | },
58 | "plot_blocks": {
59 | "colourPrimary": "335"
60 | },
61 | "file_blocks": {
62 | "colourPrimary": "360"
63 | },
64 | "mlgame_blocks": {
65 | "colourPrimary": "20"
66 | },
67 | "hat_blocks": {
68 | "colourPrimary": "360",
69 | "hat": "cap"
70 | }
71 | };
72 |
73 | Blockly.Themes.Classic.categoryStyles = {
74 | "colour_category": {
75 | "colour": "20"
76 | },
77 | "list_category": {
78 | "colour": "260"
79 | },
80 | "logic_category": {
81 | "colour": "210"
82 | },
83 | "loop_category": {
84 | "colour": "120"
85 | },
86 | "math_category": {
87 | "colour": "230"
88 | },
89 | "procedure_category": {
90 | "colour": "290"
91 | },
92 | "text_category": {
93 | "colour": "160"
94 | },
95 | "variable_category": {
96 | "colour": "330"
97 | },
98 | "variable_dynamic_category": {
99 | "colour": "310"
100 | }
101 | };
102 |
103 | Blockly.Themes.Classic =
104 | new Blockly.Theme('classic', Blockly.Themes.Classic.defaultBlockStyles,
105 | Blockly.Themes.Classic.categoryStyles);
106 |
--------------------------------------------------------------------------------
/js/core/ui_events.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2018 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Events fired as a result of UI actions in Blockly's editor.
9 | * @author fraser@google.com (Neil Fraser)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.Events.Ui');
14 |
15 | goog.require('Blockly.Events');
16 | goog.require('Blockly.Events.Abstract');
17 | goog.require('Blockly.utils.object');
18 |
19 |
20 | /**
21 | * Class for a UI event.
22 | * UI events are events that don't need to be sent over the wire for multi-user
23 | * editing to work (e.g. scrolling the workspace, zooming, opening toolbox
24 | * categories).
25 | * UI events do not undo or redo.
26 | * @param {Blockly.Block} block The affected block.
27 | * @param {string} element One of 'selected', 'comment', 'mutatorOpen', etc.
28 | * @param {*} oldValue Previous value of element.
29 | * @param {*} newValue New value of element.
30 | * @extends {Blockly.Events.Abstract}
31 | * @constructor
32 | */
33 | Blockly.Events.Ui = function(block, element, oldValue, newValue) {
34 | Blockly.Events.Ui.superClass_.constructor.call(this);
35 | this.blockId = block ? block.id : null;
36 | this.workspaceId = block ? block.workspace.id : undefined;
37 | this.element = element;
38 | this.oldValue = oldValue;
39 | this.newValue = newValue;
40 | // UI events do not undo or redo.
41 | this.recordUndo = false;
42 | };
43 | Blockly.utils.object.inherits(Blockly.Events.Ui, Blockly.Events.Abstract);
44 |
45 | /**
46 | * Type of this event.
47 | * @type {string}
48 | */
49 | Blockly.Events.Ui.prototype.type = Blockly.Events.UI;
50 |
51 | /**
52 | * Encode the event as JSON.
53 | * @return {!Object} JSON representation.
54 | */
55 | Blockly.Events.Ui.prototype.toJson = function() {
56 | var json = Blockly.Events.Ui.superClass_.toJson.call(this);
57 | json['element'] = this.element;
58 | if (this.newValue !== undefined) {
59 | json['newValue'] = this.newValue;
60 | }
61 | if (this.blockId) {
62 | json['blockId'] = this.blockId;
63 | }
64 | return json;
65 | };
66 |
67 | /**
68 | * Decode the JSON event.
69 | * @param {!Object} json JSON representation.
70 | */
71 | Blockly.Events.Ui.prototype.fromJson = function(json) {
72 | Blockly.Events.Ui.superClass_.fromJson.call(this, json);
73 | this.element = json['element'];
74 | this.newValue = json['newValue'];
75 | this.blockId = json['blockId'];
76 | };
77 |
--------------------------------------------------------------------------------
/js/core/renderers/geras/measurables/inputs.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Objects representing inputs with connections on a rendered
9 | * block.
10 | * @author kozbial@google.com (Monica Kozbial)
11 | */
12 | 'use strict';
13 |
14 | goog.provide('Blockly.geras.InlineInput');
15 | goog.provide('Blockly.geras.StatementInput');
16 |
17 | goog.require('Blockly.utils.object');
18 |
19 |
20 | /**
21 | * An object containing information about the space an inline input takes up
22 | * during rendering
23 | * @param {!Blockly.blockRendering.ConstantProvider} constants The rendering
24 | * constants provider.
25 | * @param {!Blockly.Input} input The inline input to measure and store
26 | * information for.
27 | * @package
28 | * @constructor
29 | * @extends {Blockly.blockRendering.InlineInput}
30 | */
31 | Blockly.geras.InlineInput = function(constants, input) {
32 | Blockly.geras.InlineInput.superClass_.constructor.call(
33 | this, constants, input);
34 |
35 | if (this.connectedBlock) {
36 | // We allow the dark path to show on the parent block so that the child
37 | // block looks embossed. This takes up an extra pixel in both x and y.
38 | this.width += this.constants_.DARK_PATH_OFFSET;
39 | this.height += this.constants_.DARK_PATH_OFFSET;
40 | }
41 | };
42 | Blockly.utils.object.inherits(Blockly.geras.InlineInput,
43 | Blockly.blockRendering.InlineInput);
44 |
45 | /**
46 | * An object containing information about the space a statement input takes up
47 | * during rendering
48 | * @param {!Blockly.blockRendering.ConstantProvider} constants The rendering
49 | * constants provider.
50 | * @param {!Blockly.Input} input The statement input to measure and store
51 | * information for.
52 | * @package
53 | * @constructor
54 | * @extends {Blockly.blockRendering.StatementInput}
55 | */
56 | Blockly.geras.StatementInput = function(constants, input) {
57 | Blockly.geras.StatementInput.superClass_.constructor.call(
58 | this, constants, input);
59 |
60 | if (this.connectedBlock) {
61 | // We allow the dark path to show on the parent block so that the child
62 | // block looks embossed. This takes up an extra pixel in both x and y.
63 | this.height += this.constants_.DARK_PATH_OFFSET;
64 | }
65 | };
66 | Blockly.utils.object.inherits(Blockly.geras.StatementInput,
67 | Blockly.blockRendering.StatementInput);
68 |
--------------------------------------------------------------------------------
/js/core/renderers/common/block_rendering.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Namespace for block rendering functionality.
9 | * @author fenichel@google.com (Rachel Fenichel)
10 | */
11 | 'use strict';
12 |
13 | /**
14 | * The top level namespace for block rendering.
15 | * @namespace Blockly.blockRendering
16 | */
17 | goog.provide('Blockly.blockRendering');
18 |
19 | goog.require('Blockly.registry');
20 | goog.require('Blockly.utils.object');
21 |
22 |
23 | /**
24 | * Whether or not the debugger is turned on.
25 | * @type {boolean}
26 | * @package
27 | */
28 | Blockly.blockRendering.useDebugger = false;
29 |
30 | /**
31 | * Registers a new renderer.
32 | * @param {string} name The name of the renderer.
33 | * @param {!Function} rendererClass The new renderer class
34 | * to register.
35 | * @throws {Error} if a renderer with the same name has already been registered.
36 | */
37 | Blockly.blockRendering.register = function(name, rendererClass) {
38 | Blockly.registry.register(Blockly.registry.Type.RENDERER, name,
39 | rendererClass);
40 | };
41 |
42 | /**
43 | * Unregisters the renderer registered with the given name.
44 | * @param {string} name The name of the renderer.
45 | */
46 | Blockly.blockRendering.unregister = function(name) {
47 | Blockly.registry.unregister(Blockly.registry.Type.RENDERER, name);
48 | };
49 | /**
50 | * Turn on the blocks debugger.
51 | * @package
52 | */
53 | Blockly.blockRendering.startDebugger = function() {
54 | Blockly.blockRendering.useDebugger = true;
55 | };
56 |
57 | /**
58 | * Turn off the blocks debugger.
59 | * @package
60 | */
61 | Blockly.blockRendering.stopDebugger = function() {
62 | Blockly.blockRendering.useDebugger = false;
63 | };
64 |
65 | /**
66 | * Initialize anything needed for rendering (constants, etc).
67 | * @param {!string} name Name of the renderer to initialize.
68 | * @param {!Blockly.Theme} theme The workspace theme object.
69 | * @param {Object=} opt_rendererOverrides Rendering constant overrides.
70 | * @return {!Blockly.blockRendering.Renderer} The new instance of a renderer.
71 | * Already initialized.
72 | * @package
73 | */
74 |
75 | Blockly.blockRendering.init = function(name, theme, opt_rendererOverrides) {
76 | var rendererClass = Blockly.registry.getClass(
77 | Blockly.registry.Type.RENDERER, name);
78 | var renderer = new rendererClass(name);
79 | renderer.init(theme, opt_rendererOverrides);
80 | return renderer;
81 | };
82 |
--------------------------------------------------------------------------------
/js/core/field_registry.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Fields can be created based on a JSON definition. This file
9 | * contains methods for registering those JSON definitions, and building the
10 | * fields based on JSON.
11 | * @author bekawestberg@gmail.com (Beka Westberg)
12 | */
13 | 'use strict';
14 |
15 | goog.provide('Blockly.fieldRegistry');
16 |
17 | goog.require('Blockly.registry');
18 |
19 |
20 | /**
21 | * Registers a field type.
22 | * Blockly.fieldRegistry.fromJson uses this registry to
23 | * find the appropriate field type.
24 | * @param {string} type The field type name as used in the JSON definition.
25 | * @param {?function(new:Blockly.Field, ...?)} fieldClass The field class
26 | * containing a fromJson function that can construct an instance of the
27 | * field.
28 | * @throws {Error} if the type name is empty, the field is already
29 | * registered, or the fieldClass is not an object containing a fromJson
30 | * function.
31 | */
32 | Blockly.fieldRegistry.register = function(type, fieldClass) {
33 | Blockly.registry.register(Blockly.registry.Type.FIELD, type, fieldClass);
34 | };
35 |
36 | /**
37 | * Unregisters the field registered with the given type.
38 | * @param {string} type The field type name as used in the JSON definition.
39 | */
40 | Blockly.fieldRegistry.unregister = function(type) {
41 | Blockly.registry.unregister(Blockly.registry.Type.FIELD, type);
42 | };
43 |
44 | /**
45 | * Construct a Field from a JSON arg object.
46 | * Finds the appropriate registered field by the type name as registered using
47 | * Blockly.fieldRegistry.register.
48 | * @param {!Object} options A JSON object with a type and options specific
49 | * to the field type.
50 | * @return {Blockly.Field} The new field instance or null if a field wasn't
51 | * found with the given type name
52 | * @package
53 | */
54 | Blockly.fieldRegistry.fromJson = function(options) {
55 | var fieldClass = /** @type {{fromJson:function(!Object):!Blockly.Field}} */ (
56 | Blockly.registry.getClass(Blockly.registry.Type.FIELD, options['type']));
57 | if (!fieldClass) {
58 | console.warn('Blockly could not create a field of type ' + options['type'] +
59 | '. The field is probably not being registered. This could be because' +
60 | ' the file is not loaded, the field does not register itself (Issue' +
61 | ' #1584), or the registration is not being reached.');
62 | return null;
63 | }
64 | return fieldClass.fromJson(options);
65 | };
66 |
--------------------------------------------------------------------------------
/js/core/interfaces/i_toolbox.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2020 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview The interface for a toolbox.
9 | * @author aschmiedt@google.com (Abby Schmiedt)
10 | */
11 |
12 | 'use strict';
13 |
14 | goog.provide('Blockly.IToolbox');
15 |
16 | goog.requireType('Blockly.IRegistrable');
17 |
18 |
19 | /**
20 | * Interface for a toolbox.
21 | * @extends {Blockly.IRegistrable}
22 | * @interface
23 | */
24 | Blockly.IToolbox = function() {};
25 |
26 | /**
27 | * Initializes the toolbox.
28 | * @return {void}
29 | */
30 | Blockly.IToolbox.prototype.init;
31 |
32 | /**
33 | * Fill the toolbox with categories and blocks.
34 | * @param {Array.} toolboxDef Array holding objects
35 | * containing information on the contents of the toolbox.
36 | */
37 | Blockly.IToolbox.prototype.render;
38 |
39 | /**
40 | * Dispose of this toolbox.
41 | * @return {void}
42 | */
43 | Blockly.IToolbox.prototype.dispose;
44 |
45 | /**
46 | * Get the width of the toolbox.
47 | * @return {number} The width of the toolbox.
48 | */
49 | Blockly.IToolbox.prototype.getWidth;
50 |
51 | /**
52 | * Get the height of the toolbox.
53 | * @return {number} The width of the toolbox.
54 | */
55 | Blockly.IToolbox.prototype.getHeight;
56 |
57 | /**
58 | * Get the toolbox flyout.
59 | * @return {Blockly.Flyout} The toolbox flyout.
60 | */
61 | Blockly.IToolbox.prototype.getFlyout;
62 |
63 | /**
64 | * Move the toolbox to the edge.
65 | * @return {void}
66 | */
67 | Blockly.IToolbox.prototype.position;
68 |
69 | /**
70 | * Unhighlight any previously specified option.
71 | * @return {void}
72 | */
73 | Blockly.IToolbox.prototype.clearSelection;
74 |
75 | /**
76 | * Updates the category colours and background colour of selected categories.
77 | * @return {void}
78 | */
79 | Blockly.IToolbox.prototype.refreshTheme;
80 |
81 | /**
82 | * Update the flyout's contents without closing it. Should be used in response
83 | * to a change in one of the dynamic categories, such as variables or
84 | * procedures.
85 | * @return {void}
86 | */
87 | Blockly.IToolbox.prototype.refreshSelection;
88 |
89 | /**
90 | * Toggles the visibility of the toolbox.
91 | * @param {boolean} isVisible True if the toolbox should be visible.
92 | */
93 | Blockly.IToolbox.prototype.setVisible;
94 |
95 | /**
96 | * Select the first toolbox category if no category is selected.
97 | * @return {void}
98 | */
99 | Blockly.IToolbox.prototype.selectFirstCategory;
100 |
--------------------------------------------------------------------------------
/js/core/flyout_dragger.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2017 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Methods for dragging a flyout visually.
9 | * @author fenichel@google.com (Rachel Fenichel)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.FlyoutDragger');
14 |
15 | goog.require('Blockly.utils.object');
16 | goog.require('Blockly.WorkspaceDragger');
17 |
18 |
19 | /**
20 | * Class for a flyout dragger. It moves a flyout workspace around when it is
21 | * being dragged by a mouse or touch.
22 | * Note that the workspace itself manages whether or not it has a drag surface
23 | * and how to do translations based on that. This simply passes the right
24 | * commands based on events.
25 | * @param {!Blockly.Flyout} flyout The flyout to drag.
26 | * @extends {Blockly.WorkspaceDragger}
27 | * @constructor
28 | */
29 | Blockly.FlyoutDragger = function(flyout) {
30 | Blockly.FlyoutDragger.superClass_.constructor.call(this,
31 | flyout.getWorkspace());
32 |
33 | /**
34 | * The scrollbar to update to move the flyout.
35 | * Unlike the main workspace, the flyout has only one scrollbar, in either the
36 | * horizontal or the vertical direction.
37 | * @type {!Blockly.Scrollbar}
38 | * @private
39 | */
40 | this.scrollbar_ = flyout.scrollbar;
41 |
42 | /**
43 | * Whether the flyout scrolls horizontally. If false, the flyout scrolls
44 | * vertically.
45 | * @type {boolean}
46 | * @private
47 | */
48 | this.horizontalLayout_ = flyout.horizontalLayout;
49 | };
50 | Blockly.utils.object.inherits(Blockly.FlyoutDragger, Blockly.WorkspaceDragger);
51 |
52 | /**
53 | * Move the flyout based on the most recent mouse movements.
54 | * @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has
55 | * moved from the position at the start of the drag, in pixel coordinates.
56 | * @package
57 | */
58 | Blockly.FlyoutDragger.prototype.drag = function(currentDragDeltaXY) {
59 | // startScrollXY_ is assigned by the superclass.
60 | var newXY = Blockly.utils.Coordinate.sum(this.startScrollXY_,
61 | currentDragDeltaXY);
62 |
63 | // We can't call workspace.scroll because the flyout's workspace doesn't own
64 | // it's own scrollbars. This is because (as of 2.20190722.1) the
65 | // workspace's scrollbar property must be a scrollbar pair, rather than a
66 | // single scrollbar.
67 | // Instead we'll just expect setting the scrollbar to update the scroll of
68 | // the workspace as well.
69 | if (this.horizontalLayout_) {
70 | this.scrollbar_.set(-newXY.x);
71 | } else {
72 | this.scrollbar_.set(-newXY.y);
73 | }
74 | };
75 |
--------------------------------------------------------------------------------
/js/i18n/dedup_json.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | # Consolidates duplicate key-value pairs in a JSON file.
4 | # If the same key is used with different values, no warning is given,
5 | # and there is no guarantee about which key-value pair will be output.
6 | # There is also no guarantee as to the order of the key-value pairs
7 | # output.
8 | #
9 | # Copyright 2013 Google LLC
10 | #
11 | # Licensed under the Apache License, Version 2.0 (the "License");
12 | # you may not use this file except in compliance with the License.
13 | # You may obtain a copy of the License at
14 | #
15 | # http://www.apache.org/licenses/LICENSE-2.0
16 | #
17 | # Unless required by applicable law or agreed to in writing, software
18 | # distributed under the License is distributed on an "AS IS" BASIS,
19 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 | # See the License for the specific language governing permissions and
21 | # limitations under the License.
22 |
23 | import argparse
24 | import codecs
25 | import json
26 | from common import InputError
27 |
28 |
29 | def main():
30 | """Parses arguments and iterates over files.
31 |
32 | Raises:
33 | IOError: An I/O error occurred with an input or output file.
34 | InputError: Input JSON could not be parsed.
35 | """
36 |
37 | # Set up argument parser.
38 | parser = argparse.ArgumentParser(
39 | description='Removes duplicate key-value pairs from JSON files.')
40 | parser.add_argument('--suffix', default='',
41 | help='optional suffix for output files; '
42 | 'if empty, files will be changed in place')
43 | parser.add_argument('files', nargs='+', help='input files')
44 | args = parser.parse_args()
45 |
46 | # Iterate over files.
47 | for filename in args.files:
48 | # Read in json using Python libraries. This eliminates duplicates.
49 | print('Processing ' + filename + '...')
50 | try:
51 | with codecs.open(filename, 'r', 'utf-8') as infile:
52 | j = json.load(infile)
53 | except ValueError as e:
54 | print('Error reading ' + filename)
55 | raise InputError(filename, str(e))
56 |
57 | # Built up output strings as an array to make output of delimiters easier.
58 | output = []
59 | for key in j:
60 | if key != '@metadata':
61 | output.append('\t"' + key + '": "' +
62 | j[key].replace('\n', '\\n') + '"')
63 |
64 | # Output results.
65 | with codecs.open(filename + args.suffix, 'w', 'utf-8') as outfile:
66 | outfile.write('{\n')
67 | outfile.write(',\n'.join(output))
68 | outfile.write('\n}\n')
69 |
70 |
71 | if __name__ == '__main__':
72 | main()
73 |
--------------------------------------------------------------------------------
/js/core/field_label_serializable.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Non-editable, serializable text field. Behaves like a
9 | * normal label but is serialized to XML. It may only be
10 | * edited programmatically.
11 | */
12 | 'use strict';
13 |
14 | goog.provide('Blockly.FieldLabelSerializable');
15 |
16 | goog.require('Blockly.FieldLabel');
17 | goog.require('Blockly.fieldRegistry');
18 | goog.require('Blockly.utils');
19 | goog.require('Blockly.utils.object');
20 |
21 |
22 | /**
23 | * Class for a non-editable, serializable text field.
24 | * @param {*} opt_value The initial value of the field. Should cast to a
25 | * string. Defaults to an empty string if null or undefined.
26 | * @param {string=} opt_class Optional CSS class for the field's text.
27 | * @param {Object=} opt_config A map of options used to configure the field.
28 | * See the [field creation documentation]{@link https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/label-serializable#creation}
29 | * for a list of properties this parameter supports.
30 | * @extends {Blockly.FieldLabel}
31 | * @constructor
32 | *
33 | */
34 | Blockly.FieldLabelSerializable = function(opt_value, opt_class, opt_config) {
35 | Blockly.FieldLabelSerializable.superClass_.constructor.call(
36 | this, opt_value, opt_class, opt_config);
37 | };
38 | Blockly.utils.object.inherits(Blockly.FieldLabelSerializable,
39 | Blockly.FieldLabel);
40 |
41 | /**
42 | * Construct a FieldLabelSerializable from a JSON arg object,
43 | * dereferencing any string table references.
44 | * @param {!Object} options A JSON object with options (text, and class).
45 | * @return {!Blockly.FieldLabelSerializable} The new field instance.
46 | * @package
47 | * @nocollapse
48 | */
49 | Blockly.FieldLabelSerializable.fromJson = function(options) {
50 | var text = Blockly.utils.replaceMessageReferences(options['text']);
51 | return new Blockly.FieldLabelSerializable(text, undefined, options);
52 | };
53 |
54 | /**
55 | * Editable fields usually show some sort of UI indicating they are
56 | * editable. This field should not.
57 | * @type {boolean}
58 | */
59 | Blockly.FieldLabelSerializable.prototype.EDITABLE = false;
60 |
61 | /**
62 | * Serializable fields are saved by the XML renderer, non-serializable fields
63 | * are not. This field should be serialized, but only edited programmatically.
64 | * @type {boolean}
65 | */
66 | Blockly.FieldLabelSerializable.prototype.SERIALIZABLE = true;
67 |
68 | Blockly.fieldRegistry.register(
69 | 'field_label_serializable', Blockly.FieldLabelSerializable);
70 |
--------------------------------------------------------------------------------
/js/core/events_abstract.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2018 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Abstract class for events fired as a result of actions in
9 | * Blockly's editor.
10 | * @author fraser@google.com (Neil Fraser)
11 | */
12 | 'use strict';
13 |
14 | goog.provide('Blockly.Events.Abstract');
15 |
16 | goog.require('Blockly.Events');
17 |
18 |
19 | /**
20 | * Abstract class for an event.
21 | * @constructor
22 | */
23 | Blockly.Events.Abstract = function() {
24 | /**
25 | * The workspace identifier for this event.
26 | * @type {string|undefined}
27 | */
28 | this.workspaceId = undefined;
29 |
30 | /**
31 | * The event group id for the group this event belongs to. Groups define
32 | * events that should be treated as an single action from the user's
33 | * perspective, and should be undone together.
34 | * @type {string}
35 | */
36 | this.group = Blockly.Events.getGroup();
37 |
38 | /**
39 | * Sets whether the event should be added to the undo stack.
40 | * @type {boolean}
41 | */
42 | this.recordUndo = Blockly.Events.recordUndo;
43 | };
44 |
45 | /**
46 | * Encode the event as JSON.
47 | * @return {!Object} JSON representation.
48 | */
49 | Blockly.Events.Abstract.prototype.toJson = function() {
50 | var json = {
51 | 'type': this.type
52 | };
53 | if (this.group) {
54 | json['group'] = this.group;
55 | }
56 | return json;
57 | };
58 |
59 | /**
60 | * Decode the JSON event.
61 | * @param {!Object} json JSON representation.
62 | */
63 | Blockly.Events.Abstract.prototype.fromJson = function(json) {
64 | this.group = json['group'];
65 | };
66 |
67 | /**
68 | * Does this event record any change of state?
69 | * @return {boolean} True if null, false if something changed.
70 | */
71 | Blockly.Events.Abstract.prototype.isNull = function() {
72 | return false;
73 | };
74 |
75 | /**
76 | * Run an event.
77 | * @param {boolean} _forward True if run forward, false if run backward (undo).
78 | */
79 | Blockly.Events.Abstract.prototype.run = function(_forward) {
80 | // Defined by subclasses.
81 | };
82 |
83 | /**
84 | * Get workspace the event belongs to.
85 | * @return {!Blockly.Workspace} The workspace the event belongs to.
86 | * @throws {Error} if workspace is null.
87 | * @protected
88 | */
89 | Blockly.Events.Abstract.prototype.getEventWorkspace_ = function() {
90 | if (this.workspaceId) {
91 | var workspace = Blockly.Workspace.getById(this.workspaceId);
92 | }
93 | if (!workspace) {
94 | throw Error('Workspace is null. Event must have been generated from real' +
95 | ' Blockly events.');
96 | }
97 | return workspace;
98 | };
99 |
--------------------------------------------------------------------------------
/js/core/workspace_dragger.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2017 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Methods for dragging a workspace visually.
9 | * @author fenichel@google.com (Rachel Fenichel)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.WorkspaceDragger');
14 |
15 | goog.require('Blockly.utils.Coordinate');
16 |
17 |
18 | /**
19 | * Class for a workspace dragger. It moves the workspace around when it is
20 | * being dragged by a mouse or touch.
21 | * Note that the workspace itself manages whether or not it has a drag surface
22 | * and how to do translations based on that. This simply passes the right
23 | * commands based on events.
24 | * @param {!Blockly.WorkspaceSvg} workspace The workspace to drag.
25 | * @constructor
26 | */
27 | Blockly.WorkspaceDragger = function(workspace) {
28 | /**
29 | * @type {!Blockly.WorkspaceSvg}
30 | * @private
31 | */
32 | this.workspace_ = workspace;
33 |
34 | /**
35 | * The scroll position of the workspace at the beginning of the drag.
36 | * Coordinate system: pixel coordinates.
37 | * @type {!Blockly.utils.Coordinate}
38 | * @protected
39 | */
40 | this.startScrollXY_ = new Blockly.utils.Coordinate(
41 | workspace.scrollX, workspace.scrollY);
42 | };
43 |
44 | /**
45 | * Sever all links from this object.
46 | * @package
47 | * @suppress {checkTypes}
48 | */
49 | Blockly.WorkspaceDragger.prototype.dispose = function() {
50 | this.workspace_ = null;
51 | };
52 |
53 | /**
54 | * Start dragging the workspace.
55 | * @package
56 | */
57 | Blockly.WorkspaceDragger.prototype.startDrag = function() {
58 | if (Blockly.selected) {
59 | Blockly.selected.unselect();
60 | }
61 | this.workspace_.setupDragSurface();
62 | };
63 |
64 | /**
65 | * Finish dragging the workspace and put everything back where it belongs.
66 | * @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has
67 | * moved from the position at the start of the drag, in pixel coordinates.
68 | * @package
69 | */
70 | Blockly.WorkspaceDragger.prototype.endDrag = function(currentDragDeltaXY) {
71 | // Make sure everything is up to date.
72 | this.drag(currentDragDeltaXY);
73 | this.workspace_.resetDragSurface();
74 | };
75 |
76 | /**
77 | * Move the workspace based on the most recent mouse movements.
78 | * @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has
79 | * moved from the position at the start of the drag, in pixel coordinates.
80 | * @package
81 | */
82 | Blockly.WorkspaceDragger.prototype.drag = function(currentDragDeltaXY) {
83 | var newXY = Blockly.utils.Coordinate.sum(this.startScrollXY_, currentDragDeltaXY);
84 | this.workspace_.scroll(newXY.x, newXY.y);
85 | };
86 |
--------------------------------------------------------------------------------
/js/core/theme/tritanopia.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Tritanopia theme.
9 | * A color palette for people that have tritanopia (the inability to perceive
10 | * blue light).
11 | */
12 | 'use strict';
13 |
14 | goog.provide('Blockly.Themes.Tritanopia');
15 |
16 | goog.require('Blockly.Theme');
17 |
18 |
19 | // Temporary holding object.
20 | Blockly.Themes.Tritanopia = {};
21 |
22 | Blockly.Themes.Tritanopia.defaultBlockStyles = {
23 | "colour_blocks": {
24 | "colourPrimary": "#05427f",
25 | "colourSecondary": "#2974c0",
26 | "colourTertiary": "#2d74bb"
27 | },
28 | "list_blocks": {
29 | "colourPrimary": "#b69ce8",
30 | "colourSecondary": "#ccbaef",
31 | "colourTertiary": "#9176c5"
32 | },
33 | "logic_blocks": {
34 | "colourPrimary": "#9fd2f1",
35 | "colourSecondary": "#c0e0f4",
36 | "colourTertiary": "#74bae5"
37 | },
38 | "loop_blocks": {
39 | "colourPrimary": "#aa1846",
40 | "colourSecondary": "#d36185",
41 | "colourTertiary": "#7c1636"
42 | },
43 | "math_blocks": {
44 | "colourPrimary": "#e6da39",
45 | "colourSecondary": "#f3ec8e",
46 | "colourTertiary": "#f2eeb7"
47 | },
48 | "procedure_blocks": {
49 | "colourPrimary": "#590721",
50 | "colourSecondary": "#8c475d",
51 | "colourTertiary": "#885464"
52 | },
53 | "text_blocks": {
54 | "colourPrimary": "#058863",
55 | "colourSecondary": "#5ecfaf",
56 | "colourTertiary": "#04684c"
57 | },
58 | "variable_blocks": {
59 | "colourPrimary": "#4b2d84",
60 | "colourSecondary": "#816ea7",
61 | "colourTertiary": "#83759e"
62 | },
63 | "variable_dynamic_blocks": {
64 | "colourPrimary": "#4b2d84",
65 | "colourSecondary": "#816ea7",
66 | "colourTertiary": "#83759e"
67 | }
68 | };
69 |
70 | Blockly.Themes.Tritanopia.categoryStyles = {
71 | "colour_category": {
72 | "colour": "#05427f"
73 | },
74 | "list_category": {
75 | "colour": "#b69ce8"
76 | },
77 | "logic_category": {
78 | "colour": "#9fd2f1"
79 | },
80 | "loop_category": {
81 | "colour": "#aa1846"
82 | },
83 | "math_category": {
84 | "colour": "#e6da39"
85 | },
86 | "procedure_category": {
87 | "colour": "#590721"
88 | },
89 | "text_category": {
90 | "colour": "#058863"
91 | },
92 | "variable_category": {
93 | "colour": "#4b2d84"
94 | },
95 | "variable_dynamic_category": {
96 | "colour": "#4b2d84"
97 | }
98 | };
99 |
100 | Blockly.Themes.Tritanopia =
101 | new Blockly.Theme('tritanopia',
102 | Blockly.Themes.Tritanopia.defaultBlockStyles,
103 | Blockly.Themes.Tritanopia.categoryStyles);
104 |
--------------------------------------------------------------------------------
/js/core/theme/zelos.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2018 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Zelos theme.
9 | */
10 | 'use strict';
11 |
12 | goog.provide('Blockly.Themes.Zelos');
13 |
14 | goog.require('Blockly.Theme');
15 |
16 |
17 | // Temporary holding object.
18 | Blockly.Themes.Zelos = {};
19 |
20 | Blockly.Themes.Zelos.defaultBlockStyles = {
21 | "colour_blocks": {
22 | "colourPrimary": "#CF63CF",
23 | "colourSecondary": "#C94FC9",
24 | "colourTertiary": "#BD42BD"
25 | },
26 | "list_blocks": {
27 | "colourPrimary": "#9966FF",
28 | "colourSecondary": "#855CD6",
29 | "colourTertiary": "#774DCB"
30 | },
31 | "logic_blocks": {
32 | "colourPrimary": "#4C97FF",
33 | "colourSecondary": "#4280D7",
34 | "colourTertiary": "#3373CC"
35 | },
36 | "loop_blocks": {
37 | "colourPrimary": "#0fBD8C",
38 | "colourSecondary": "#0DA57A",
39 | "colourTertiary": "#0B8E69"
40 | },
41 | "math_blocks": {
42 | "colourPrimary": "#59C059",
43 | "colourSecondary": "#46B946",
44 | "colourTertiary": "#389438"
45 | },
46 | "procedure_blocks": {
47 | "colourPrimary": "#FF6680",
48 | "colourSecondary": "#FF4D6A",
49 | "colourTertiary": "#FF3355"
50 | },
51 | "text_blocks": {
52 | "colourPrimary": "#FFBF00",
53 | "colourSecondary": "#E6AC00",
54 | "colourTertiary": "#CC9900"
55 | },
56 | "variable_blocks": {
57 | "colourPrimary": "#FF8C1A",
58 | "colourSecondary": "#FF8000",
59 | "colourTertiary": "#DB6E00"
60 | },
61 | "variable_dynamic_blocks": {
62 | "colourPrimary": "#FF8C1A",
63 | "colourSecondary": "#FF8000",
64 | "colourTertiary": "#DB6E00"
65 | },
66 | "hat_blocks": {
67 | "colourPrimary": "#4C97FF",
68 | "colourSecondary": "#4280D7",
69 | "colourTertiary": "#3373CC",
70 | "hat": "cap"
71 | }
72 | };
73 |
74 | Blockly.Themes.Zelos.categoryStyles = {
75 | "colour_category": {
76 | "colour": "#CF63CF"
77 | },
78 | "list_category": {
79 | "colour": "#9966FF"
80 | },
81 | "logic_category": {
82 | "colour": "#4C97FF"
83 | },
84 | "loop_category": {
85 | "colour": "#0fBD8C"
86 | },
87 | "math_category": {
88 | "colour": "#59C059"
89 | },
90 | "procedure_category": {
91 | "colour": "#FF6680"
92 | },
93 | "text_category": {
94 | "colour": "#FFBF00"
95 | },
96 | "variable_category": {
97 | "colour": "#FF8C1A"
98 | },
99 | "variable_dynamic_category": {
100 | "colour": "#FF8C1A"
101 | }
102 | };
103 |
104 | Blockly.Themes.Zelos =
105 | new Blockly.Theme('zelos', Blockly.Themes.Zelos.defaultBlockStyles,
106 | Blockly.Themes.Zelos.categoryStyles);
107 |
--------------------------------------------------------------------------------
/js/core/theme/deuteranopia.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Deuteranopia theme.
9 | * A colour palette for people that have deuteranopia (the inability to perceive
10 | * green light). This can also be used for people that have protanopia (the
11 | * inability to perceive red light).
12 | */
13 | 'use strict';
14 |
15 | goog.provide('Blockly.Themes.Deuteranopia');
16 |
17 | goog.require('Blockly.Theme');
18 |
19 |
20 | // Temporary holding object.
21 | Blockly.Themes.Deuteranopia = {};
22 |
23 | Blockly.Themes.Deuteranopia.defaultBlockStyles = {
24 | "colour_blocks": {
25 | "colourPrimary": "#f2a72c",
26 | "colourSecondary": "#f1c172",
27 | "colourTertiary": "#da921c"
28 | },
29 | "list_blocks": {
30 | "colourPrimary": "#7d65ab",
31 | "colourSecondary": "#a88be0",
32 | "colourTertiary": "#66518e"
33 | },
34 | "logic_blocks": {
35 | "colourPrimary": "#9fd2f1",
36 | "colourSecondary": "#c0e0f4",
37 | "colourTertiary": "#74bae5"
38 | },
39 | "loop_blocks": {
40 | "colourPrimary": "#795a07",
41 | "colourSecondary": "#ac8726",
42 | "colourTertiary": "#c4a03f"
43 | },
44 | "math_blocks": {
45 | "colourPrimary": "#e6da39",
46 | "colourSecondary": "#f3ec8e",
47 | "colourTertiary": "#f2eeb7"
48 | },
49 | "procedure_blocks": {
50 | "colourPrimary": "#590721",
51 | "colourSecondary": "#8c475d",
52 | "colourTertiary": "#885464"
53 | },
54 | "text_blocks": {
55 | "colourPrimary": "#058863",
56 | "colourSecondary": "#5ecfaf",
57 | "colourTertiary": "#04684c"
58 | },
59 | "variable_blocks": {
60 | "colourPrimary": "#47025a",
61 | "colourSecondary": "#820fa1",
62 | "colourTertiary": "#8e579d"
63 | },
64 | "variable_dynamic_blocks": {
65 | "colourPrimary": "#47025a",
66 | "colourSecondary": "#820fa1",
67 | "colourTertiary": "#8e579d"
68 | }
69 | };
70 |
71 | Blockly.Themes.Deuteranopia.categoryStyles = {
72 | "colour_category": {
73 | "colour": "#f2a72c"
74 | },
75 | "list_category": {
76 | "colour": "#7d65ab"
77 | },
78 | "logic_category": {
79 | "colour": "#9fd2f1"
80 | },
81 | "loop_category": {
82 | "colour": "#795a07"
83 | },
84 | "math_category": {
85 | "colour": "#e6da39"
86 | },
87 | "procedure_category": {
88 | "colour": "#590721"
89 | },
90 | "text_category": {
91 | "colour": "#058863"
92 | },
93 | "variable_category": {
94 | "colour": "#47025a"
95 | },
96 | "variable_dynamic_category": {
97 | "colour": "#47025a"
98 | }
99 | };
100 |
101 | Blockly.Themes.Deuteranopia =
102 | new Blockly.Theme('deuteranopia',
103 | Blockly.Themes.Deuteranopia.defaultBlockStyles,
104 | Blockly.Themes.Deuteranopia.categoryStyles);
105 |
--------------------------------------------------------------------------------
/js/core/theme/modern.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2018 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Modern theme.
9 | * Same colours as classic, but single coloured border.
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.Themes.Modern');
14 |
15 | goog.require('Blockly.Theme');
16 |
17 |
18 | // Temporary holding object.
19 | Blockly.Themes.Modern = {};
20 |
21 | Blockly.Themes.Modern.defaultBlockStyles = {
22 | "colour_blocks": {
23 | "colourPrimary": "#a5745b",
24 | "colourSecondary": "#dbc7bd",
25 | "colourTertiary": "#845d49"
26 | },
27 | "list_blocks": {
28 | "colourPrimary": "#745ba5",
29 | "colourSecondary": "#c7bddb",
30 | "colourTertiary": "#5d4984"
31 | },
32 | "logic_blocks": {
33 | "colourPrimary": "#5b80a5",
34 | "colourSecondary": "#bdccdb",
35 | "colourTertiary": "#496684"
36 | },
37 | "loop_blocks": {
38 | "colourPrimary": "#5ba55b",
39 | "colourSecondary": "#bddbbd",
40 | "colourTertiary": "#498449"
41 | },
42 | "math_blocks": {
43 | "colourPrimary": "#5b67a5",
44 | "colourSecondary": "#bdc2db",
45 | "colourTertiary": "#495284"
46 | },
47 | "procedure_blocks": {
48 | "colourPrimary": "#995ba5",
49 | "colourSecondary": "#d6bddb",
50 | "colourTertiary": "#7a4984"
51 | },
52 | "text_blocks": {
53 | "colourPrimary": "#5ba58c",
54 | "colourSecondary": "#bddbd1",
55 | "colourTertiary": "#498470"
56 | },
57 | "variable_blocks": {
58 | "colourPrimary": "#a55b99",
59 | "colourSecondary": "#dbbdd6",
60 | "colourTertiary": "#84497a"
61 | },
62 | "variable_dynamic_blocks": {
63 | "colourPrimary": "#a55b99",
64 | "colourSecondary": "#dbbdd6",
65 | "colourTertiary": "#84497a"
66 | },
67 | "hat_blocks": {
68 | "colourPrimary": "#a55b99",
69 | "colourSecondary": "#dbbdd6",
70 | "colourTertiary": "#84497a",
71 | "hat": "cap"
72 | }
73 | };
74 |
75 | Blockly.Themes.Modern.categoryStyles = {
76 | "colour_category": {
77 | "colour": "#a5745b"
78 | },
79 | "list_category": {
80 | "colour": "#745ba5"
81 | },
82 | "logic_category": {
83 | "colour": "#5b80a5"
84 | },
85 | "loop_category": {
86 | "colour": "#5ba55b"
87 | },
88 | "math_category": {
89 | "colour": "#5b67a5"
90 | },
91 | "procedure_category": {
92 | "colour": "#995ba5"
93 | },
94 | "text_category": {
95 | "colour": "#5ba58c"
96 | },
97 | "variable_category": {
98 | "colour": "#a55b99"
99 | },
100 | "variable_dynamic_category": {
101 | "colour": "#a55b99"
102 | }
103 | };
104 |
105 | // This style is still being fleshed out and may change.
106 | Blockly.Themes.Modern =
107 | new Blockly.Theme('modern', Blockly.Themes.Modern.defaultBlockStyles,
108 | Blockly.Themes.Modern.categoryStyles);
109 |
--------------------------------------------------------------------------------
/js/core/keyboard_nav/flyout_cursor.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview The class representing a cursor used to navigate the flyout.
9 | * Used primarily for keyboard navigation.
10 | * @author aschmiedt@google.com (Abby Schmiedt)
11 | */
12 | 'use strict';
13 |
14 | goog.provide('Blockly.FlyoutCursor');
15 |
16 | goog.require('Blockly.Cursor');
17 | goog.require('Blockly.navigation');
18 | goog.require('Blockly.utils.object');
19 |
20 |
21 | /**
22 | * Class for a flyout cursor.
23 | * This controls how a user navigates blocks in the flyout.
24 | * @constructor
25 | * @extends {Blockly.Cursor}
26 | */
27 | Blockly.FlyoutCursor = function() {
28 | Blockly.FlyoutCursor.superClass_.constructor.call(this);
29 | };
30 | Blockly.utils.object.inherits(Blockly.FlyoutCursor, Blockly.Cursor);
31 |
32 | /**
33 | * Handles the given action.
34 | * This is only triggered when keyboard navigation is enabled.
35 | * @param {!Blockly.Action} action The action to be handled.
36 | * @return {boolean} True if the action has been handled, false otherwise.
37 | * @override
38 | */
39 | Blockly.FlyoutCursor.prototype.onBlocklyAction = function(action) {
40 | switch (action.name) {
41 | case Blockly.navigation.actionNames.PREVIOUS:
42 | this.prev();
43 | return true;
44 | case Blockly.navigation.actionNames.NEXT:
45 | this.next();
46 | return true;
47 | default:
48 | return false;
49 | }
50 | };
51 |
52 | /**
53 | * Find the next connection, field, or block.
54 | * @return {Blockly.ASTNode} The next element, or null if the current node is
55 | * not set or there is no next value.
56 | * @override
57 | */
58 | Blockly.FlyoutCursor.prototype.next = function() {
59 | var curNode = this.getCurNode();
60 | if (!curNode) {
61 | return null;
62 | }
63 | var newNode = curNode.next();
64 |
65 | if (newNode) {
66 | this.setCurNode(newNode);
67 | }
68 | return newNode;
69 | };
70 |
71 | /**
72 | * This is a no-op since a flyout cursor can not go in.
73 | * @return {null} Always null.
74 | * @override
75 | */
76 | Blockly.FlyoutCursor.prototype.in = function() {
77 | return null;
78 | };
79 |
80 | /**
81 | * Find the previous connection, field, or block.
82 | * @return {Blockly.ASTNode} The previous element, or null if the current node
83 | * is not set or there is no previous value.
84 | * @override
85 | */
86 | Blockly.FlyoutCursor.prototype.prev = function() {
87 | var curNode = this.getCurNode();
88 | if (!curNode) {
89 | return null;
90 | }
91 | var newNode = curNode.prev();
92 |
93 | if (newNode) {
94 | this.setCurNode(newNode);
95 | }
96 | return newNode;
97 | };
98 |
99 | /**
100 | * This is a no-op since a flyout cursor can not go out.
101 | * @return {null} Always null.
102 | * @override
103 | */
104 | Blockly.FlyoutCursor.prototype.out = function() {
105 | return null;
106 | };
107 |
--------------------------------------------------------------------------------
/js/generators/python/file.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.provide('Blockly.Python.file');
4 |
5 | goog.require('Blockly.Python');
6 |
7 | Blockly.Python['file_save'] = function(block) {
8 | // Save an object as a pickle file.
9 | Blockly.Python.definitions_['import_pickle'] = 'import pickle';
10 | Blockly.Python.definitions_['import_os'] = 'import os';
11 | var obj = Blockly.Python.valueToCode(block, 'OBJECT',
12 | Blockly.Python.ORDER_NONE) || 'None';
13 | var name = Blockly.Python.valueToCode(block, 'FILENAME',
14 | Blockly.Python.ORDER_NONE) || ("'save_" + new Date().getTime() + "'");
15 | var code = "with open(os.path.join(os.path.dirname(__file__), " + name + " + '.pickle'), 'wb') as f:\n" +
16 | Blockly.Python.prefixLines("pickle.dump(" + obj + ", f)\n", Blockly.Python.INDENT);
17 | return code;
18 | };
19 |
20 | Blockly.Python['file_load'] = function(block) {
21 | // Load an object from a pickle file.
22 | Blockly.Python.definitions_['import_pickle'] = 'import pickle';
23 | Blockly.Python.definitions_['import_os'] = 'import os';
24 | var obj = Blockly.Python.valueToCode(block, 'OBJECT',
25 | Blockly.Python.ORDER_NONE) || '_';
26 | var name = Blockly.Python.valueToCode(block, 'FILENAME',
27 | Blockly.Python.ORDER_NONE) || "''";
28 | var code = "with open(os.path.join(os.path.dirname(__file__), " + name + " + '.pickle'), 'rb') as f:\n" +
29 | Blockly.Python.prefixLines(obj + " = pickle.load(f)\n", Blockly.Python.INDENT);
30 | return code;
31 | };
32 |
33 | Blockly.Python['file_csv_save'] = function(block) {
34 | // Save an object as a csv file.
35 | Blockly.Python.definitions_['import_csv'] = 'import csv';
36 | Blockly.Python.definitions_['import_os'] = 'import os';
37 | var obj = Blockly.Python.valueToCode(block, 'OBJECT',
38 | Blockly.Python.ORDER_NONE) || 'None';
39 | var name = Blockly.Python.valueToCode(block, 'FILENAME',
40 | Blockly.Python.ORDER_NONE) || ("'save_" + new Date().getTime() + "'");
41 | var delimiter = block.getFieldValue('DELIMITER');
42 | var code = "with open(os.path.join(os.path.dirname(__file__), " + name + " + '.csv'), 'w', newline='') as f:\n" +
43 | Blockly.Python.prefixLines("csv.writer(f, delimiter='" + delimiter + "').writerows(" + obj + ")\n", Blockly.Python.INDENT);
44 | return code;
45 | };
46 |
47 | Blockly.Python['file_csv_load'] = function(block) {
48 | // Load an object from a csv file.
49 | Blockly.Python.definitions_['import_csv'] = 'import csv';
50 | Blockly.Python.definitions_['import_os'] = 'import os';
51 | var obj = Blockly.Python.valueToCode(block, 'OBJECT',
52 | Blockly.Python.ORDER_NONE) || '_';
53 | var name = Blockly.Python.valueToCode(block, 'FILENAME',
54 | Blockly.Python.ORDER_NONE) || "''";
55 | var delimiter = block.getFieldValue('DELIMITER');
56 | var code = "with open(os.path.join(os.path.dirname(__file__), " + name + " + '.csv'), 'r', newline='') as f:\n" +
57 | Blockly.Python.prefixLines(obj + " = [row for row in csv.reader(f, delimiter='" + delimiter + "')]\n", Blockly.Python.INDENT);
58 | return code;
59 | };
60 |
--------------------------------------------------------------------------------
/js/core/variable_model.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2017 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Components for the variable model.
9 | * @author marisaleung@google.com (Marisa Leung)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.VariableModel');
14 |
15 | goog.require('Blockly.Events');
16 | goog.require('Blockly.Events.VarCreate');
17 | goog.require('Blockly.utils');
18 |
19 |
20 | /**
21 | * Class for a variable model.
22 | * Holds information for the variable including name, ID, and type.
23 | * @param {!Blockly.Workspace} workspace The variable's workspace.
24 | * @param {string} name The name of the variable. This must be unique across
25 | * variables and procedures.
26 | * @param {string=} opt_type The type of the variable like 'int' or 'string'.
27 | * Does not need to be unique. Field_variable can filter variables based on
28 | * their type. This will default to '' which is a specific type.
29 | * @param {string=} opt_id The unique ID of the variable. This will default to
30 | * a UUID.
31 | * @see {Blockly.FieldVariable}
32 | * @constructor
33 | */
34 | Blockly.VariableModel = function(workspace, name, opt_type, opt_id) {
35 | /**
36 | * The workspace the variable is in.
37 | * @type {!Blockly.Workspace}
38 | */
39 | this.workspace = workspace;
40 |
41 | /**
42 | * The name of the variable, typically defined by the user. It must be
43 | * unique across all names used for procedures and variables. It may be
44 | * changed by the user.
45 | * @type {string}
46 | */
47 | this.name = name;
48 |
49 | /**
50 | * The type of the variable, such as 'int' or 'sound_effect'. This may be
51 | * used to build a list of variables of a specific type. By default this is
52 | * the empty string '', which is a specific type.
53 | * @see {Blockly.FieldVariable}
54 | * @type {string}
55 | */
56 | this.type = opt_type || '';
57 |
58 | /**
59 | * A unique id for the variable. This should be defined at creation and
60 | * not change, even if the name changes. In most cases this should be a
61 | * UUID.
62 | * @type {string}
63 | * @private
64 | */
65 | this.id_ = opt_id || Blockly.utils.genUid();
66 |
67 | Blockly.Events.fire(new Blockly.Events.VarCreate(this));
68 | };
69 |
70 | /**
71 | * @return {string} The ID for the variable.
72 | */
73 | Blockly.VariableModel.prototype.getId = function() {
74 | return this.id_;
75 | };
76 |
77 | /**
78 | * A custom compare function for the VariableModel objects.
79 | * @param {Blockly.VariableModel} var1 First variable to compare.
80 | * @param {Blockly.VariableModel} var2 Second variable to compare.
81 | * @return {number} -1 if name of var1 is less than name of var2, 0 if equal,
82 | * and 1 if greater.
83 | * @package
84 | */
85 | Blockly.VariableModel.compareByName = function(var1, var2) {
86 | var name1 = var1.name.toLowerCase();
87 | var name2 = var2.name.toLowerCase();
88 | if (name1 < name2) {
89 | return -1;
90 | } else if (name1 == name2) {
91 | return 0;
92 | } else {
93 | return 1;
94 | }
95 | };
96 |
--------------------------------------------------------------------------------
/js/generators/python/colour.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2012 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Generating Python for colour blocks.
9 | * @author fraser@google.com (Neil Fraser)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.Python.colour');
14 |
15 | goog.require('Blockly.Python');
16 |
17 |
18 | Blockly.Python['colour_picker'] = function(block) {
19 | // Colour picker.
20 | var code = Blockly.Python.quote_(block.getFieldValue('COLOUR'));
21 | return [code, Blockly.Python.ORDER_ATOMIC];
22 | };
23 |
24 | Blockly.Python['colour_random'] = function(block) {
25 | // Generate a random colour.
26 | Blockly.Python.definitions_['import_random'] = 'import random';
27 | var code = '\'#%06x\' % random.randint(0, 2**24 - 1)';
28 | return [code, Blockly.Python.ORDER_FUNCTION_CALL];
29 | };
30 |
31 | Blockly.Python['colour_rgb'] = function(block) {
32 | // Compose a colour from RGB components expressed as percentages.
33 | var functionName = Blockly.Python.provideFunction_(
34 | 'colour_rgb',
35 | ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(r, g, b):',
36 | ' r = round(min(100, max(0, r)) * 2.55)',
37 | ' g = round(min(100, max(0, g)) * 2.55)',
38 | ' b = round(min(100, max(0, b)) * 2.55)',
39 | ' return \'#%02x%02x%02x\' % (r, g, b)']);
40 | var r = Blockly.Python.valueToCode(block, 'RED',
41 | Blockly.Python.ORDER_NONE) || 0;
42 | var g = Blockly.Python.valueToCode(block, 'GREEN',
43 | Blockly.Python.ORDER_NONE) || 0;
44 | var b = Blockly.Python.valueToCode(block, 'BLUE',
45 | Blockly.Python.ORDER_NONE) || 0;
46 | var code = functionName + '(' + r + ', ' + g + ', ' + b + ')';
47 | return [code, Blockly.Python.ORDER_FUNCTION_CALL];
48 | };
49 |
50 | Blockly.Python['colour_blend'] = function(block) {
51 | // Blend two colours together.
52 | var functionName = Blockly.Python.provideFunction_(
53 | 'colour_blend',
54 | ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ +
55 | '(colour1, colour2, ratio):',
56 | ' r1, r2 = int(colour1[1:3], 16), int(colour2[1:3], 16)',
57 | ' g1, g2 = int(colour1[3:5], 16), int(colour2[3:5], 16)',
58 | ' b1, b2 = int(colour1[5:7], 16), int(colour2[5:7], 16)',
59 | ' ratio = min(1, max(0, ratio))',
60 | ' r = round(r1 * (1 - ratio) + r2 * ratio)',
61 | ' g = round(g1 * (1 - ratio) + g2 * ratio)',
62 | ' b = round(b1 * (1 - ratio) + b2 * ratio)',
63 | ' return \'#%02x%02x%02x\' % (r, g, b)']);
64 | var colour1 = Blockly.Python.valueToCode(block, 'COLOUR1',
65 | Blockly.Python.ORDER_NONE) || '\'#000000\'';
66 | var colour2 = Blockly.Python.valueToCode(block, 'COLOUR2',
67 | Blockly.Python.ORDER_NONE) || '\'#000000\'';
68 | var ratio = Blockly.Python.valueToCode(block, 'RATIO',
69 | Blockly.Python.ORDER_NONE) || 0;
70 | var code = functionName + '(' + colour1 + ', ' + colour2 + ', ' + ratio + ')';
71 | return [code, Blockly.Python.ORDER_FUNCTION_CALL];
72 | };
73 |
--------------------------------------------------------------------------------
/js/blocks/file.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.require('Blockly');
4 | goog.require('Blockly.Blocks');
5 | goog.require('Blockly.FieldTextInput');
6 | goog.require('Blockly.FieldDropdown');
7 | goog.require('Blockly.FieldLabel');
8 |
9 | Blockly.defineBlocksWithJsonArray([
10 | // Block for saving an object as a pickle file.
11 | {
12 | "type": "file_save",
13 | "message0": "%{BKY_FILE_SAVE}",
14 | "args0": [
15 | {
16 | "type": "input_value",
17 | "name": "OBJECT"
18 | },
19 | {
20 | "type": "input_value",
21 | "name": "FILENAME",
22 | "check": "String"
23 | }
24 | ],
25 | "inputsInline": true,
26 | "previousStatement": null,
27 | "nextStatement": null,
28 | "style": "file_blocks",
29 | "tooltip": "%{BKY_FILE_SAVE_TOOLTIP}"
30 | },
31 | // Block for loading an object from a pickle file.
32 | {
33 | "type": "file_load",
34 | "message0": "%{BKY_FILE_LOAD}",
35 | "args0": [
36 | {
37 | "type": "input_value",
38 | "name": "OBJECT"
39 | },
40 | {
41 | "type": "input_value",
42 | "name": "FILENAME",
43 | "check": "String"
44 | }
45 | ],
46 | "inputsInline": true,
47 | "previousStatement": null,
48 | "nextStatement": null,
49 | "style": "file_blocks",
50 | "tooltip": "%{BKY_FILE_LOAD_TOOLTIP}"
51 | },
52 | // Block for saving an object as a csv file.
53 | {
54 | "type": "file_csv_save",
55 | "message0": "%{BKY_FILE_CSV_SAVE}",
56 | "args0": [
57 | {
58 | "type": "input_value",
59 | "name": "OBJECT"
60 | },
61 | {
62 | "type": "input_value",
63 | "name": "FILENAME",
64 | "check": "String"
65 | },
66 | {
67 | "type": "field_dropdown",
68 | "name": "DELIMITER",
69 | "options": [
70 | [",", ","],
71 | [":", ":"],
72 | [";", ";"],
73 | ["|", "|"],
74 | ["SPACE", " "],
75 | ["TAB", "\\t"]
76 | ]
77 | }
78 | ],
79 | "inputsInline": true,
80 | "previousStatement": null,
81 | "nextStatement": null,
82 | "style": "file_blocks",
83 | "tooltip": "%{BKY_FILE_SAVE_TOOLTIP}"
84 | },
85 | // Block for loading an object from a csv file.
86 | {
87 | "type": "file_csv_load",
88 | "message0": "%{BKY_FILE_CSV_LOAD}",
89 | "args0": [
90 | {
91 | "type": "input_value",
92 | "name": "OBJECT"
93 | },
94 | {
95 | "type": "input_value",
96 | "name": "FILENAME",
97 | "check": "String"
98 | },
99 | {
100 | "type": "field_dropdown",
101 | "name": "DELIMITER",
102 | "options": [
103 | [",", ","],
104 | [":", ":"],
105 | [";", ";"],
106 | ["|", "|"],
107 | ["SPACE", " "],
108 | ["TAB", "\\t"]
109 | ]
110 | }
111 | ],
112 | "inputsInline": true,
113 | "previousStatement": null,
114 | "nextStatement": null,
115 | "style": "file_blocks",
116 | "tooltip": "%{BKY_FILE_LOAD_TOOLTIP}"
117 | }
118 | ]);
119 |
--------------------------------------------------------------------------------
/js/generators/lua/colour.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2016 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Generating Lua for colour blocks.
9 | * @author rodrigoq@google.com (Rodrigo Queiro)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.Lua.colour');
14 |
15 | goog.require('Blockly.Lua');
16 |
17 |
18 | Blockly.Lua['colour_picker'] = function(block) {
19 | // Colour picker.
20 | var code = Blockly.Lua.quote_(block.getFieldValue('COLOUR'));
21 | return [code, Blockly.Lua.ORDER_ATOMIC];
22 | };
23 |
24 | Blockly.Lua['colour_random'] = function(block) {
25 | // Generate a random colour.
26 | var code = 'string.format("#%06x", math.random(0, 2^24 - 1))';
27 | return [code, Blockly.Lua.ORDER_HIGH];
28 | };
29 |
30 | Blockly.Lua['colour_rgb'] = function(block) {
31 | // Compose a colour from RGB components expressed as percentages.
32 | var functionName = Blockly.Lua.provideFunction_(
33 | 'colour_rgb',
34 | ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(r, g, b)',
35 | ' r = math.floor(math.min(100, math.max(0, r)) * 2.55 + .5)',
36 | ' g = math.floor(math.min(100, math.max(0, g)) * 2.55 + .5)',
37 | ' b = math.floor(math.min(100, math.max(0, b)) * 2.55 + .5)',
38 | ' return string.format("#%02x%02x%02x", r, g, b)',
39 | 'end']);
40 | var r = Blockly.Lua.valueToCode(block, 'RED',
41 | Blockly.Lua.ORDER_NONE) || 0;
42 | var g = Blockly.Lua.valueToCode(block, 'GREEN',
43 | Blockly.Lua.ORDER_NONE) || 0;
44 | var b = Blockly.Lua.valueToCode(block, 'BLUE',
45 | Blockly.Lua.ORDER_NONE) || 0;
46 | var code = functionName + '(' + r + ', ' + g + ', ' + b + ')';
47 | return [code, Blockly.Lua.ORDER_HIGH];
48 | };
49 |
50 | Blockly.Lua['colour_blend'] = function(block) {
51 | // Blend two colours together.
52 | var functionName = Blockly.Lua.provideFunction_(
53 | 'colour_blend',
54 | ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ +
55 | '(colour1, colour2, ratio)',
56 | ' local r1 = tonumber(string.sub(colour1, 2, 3), 16)',
57 | ' local r2 = tonumber(string.sub(colour2, 2, 3), 16)',
58 | ' local g1 = tonumber(string.sub(colour1, 4, 5), 16)',
59 | ' local g2 = tonumber(string.sub(colour2, 4, 5), 16)',
60 | ' local b1 = tonumber(string.sub(colour1, 6, 7), 16)',
61 | ' local b2 = tonumber(string.sub(colour2, 6, 7), 16)',
62 | ' local ratio = math.min(1, math.max(0, ratio))',
63 | ' local r = math.floor(r1 * (1 - ratio) + r2 * ratio + .5)',
64 | ' local g = math.floor(g1 * (1 - ratio) + g2 * ratio + .5)',
65 | ' local b = math.floor(b1 * (1 - ratio) + b2 * ratio + .5)',
66 | ' return string.format("#%02x%02x%02x", r, g, b)',
67 | 'end']);
68 | var colour1 = Blockly.Lua.valueToCode(block, 'COLOUR1',
69 | Blockly.Lua.ORDER_NONE) || '\'#000000\'';
70 | var colour2 = Blockly.Lua.valueToCode(block, 'COLOUR2',
71 | Blockly.Lua.ORDER_NONE) || '\'#000000\'';
72 | var ratio = Blockly.Lua.valueToCode(block, 'RATIO',
73 | Blockly.Lua.ORDER_NONE) || 0;
74 | var code = functionName + '(' + colour1 + ', ' + colour2 + ', ' + ratio + ')';
75 | return [code, Blockly.Lua.ORDER_HIGH];
76 | };
77 |
--------------------------------------------------------------------------------
/js/core/keyboard_nav/marker.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview The class representing a marker.
9 | * Used primarily for keyboard navigation to show a marked location.
10 | * @author aschmiedt@google.com (Abby Schmiedt)
11 | */
12 | 'use strict';
13 |
14 | goog.provide('Blockly.Marker');
15 |
16 | goog.require('Blockly.ASTNode');
17 | goog.require('Blockly.navigation');
18 |
19 |
20 | /**
21 | * Class for a marker.
22 | * This is used in keyboard navigation to save a location in the Blockly AST.
23 | * @constructor
24 | */
25 | Blockly.Marker = function() {
26 | /**
27 | * The colour of the marker.
28 | * @type {?string}
29 | */
30 | this.colour = null;
31 |
32 | /**
33 | * The current location of the marker.
34 | * @type {Blockly.ASTNode}
35 | * @private
36 | */
37 | this.curNode_ = null;
38 |
39 | /**
40 | * The object in charge of drawing the visual representation of the current node.
41 | * @type {Blockly.blockRendering.MarkerSvg}
42 | * @private
43 | */
44 | this.drawer_ = null;
45 |
46 | /**
47 | * The type of the marker.
48 | * @type {string}
49 | */
50 | this.type = 'marker';
51 | };
52 |
53 | /**
54 | * Sets the object in charge of drawing the marker.
55 | * @param {Blockly.blockRendering.MarkerSvg} drawer The object in charge of
56 | * drawing the marker.
57 | */
58 | Blockly.Marker.prototype.setDrawer = function(drawer) {
59 | this.drawer_ = drawer;
60 | };
61 |
62 | /**
63 | * Get the current drawer for the marker.
64 | * @return {Blockly.blockRendering.MarkerSvg} The object in charge of drawing
65 | * the marker.
66 | */
67 | Blockly.Marker.prototype.getDrawer = function() {
68 | return this.drawer_;
69 | };
70 |
71 | /**
72 | * Gets the current location of the marker.
73 | * @return {Blockly.ASTNode} The current field, connection, or block the marker
74 | * is on.
75 | */
76 | Blockly.Marker.prototype.getCurNode = function() {
77 | return this.curNode_;
78 | };
79 |
80 | /**
81 | * Set the location of the marker and call the update method.
82 | * Setting isStack to true will only work if the newLocation is the top most
83 | * output or previous connection on a stack.
84 | * @param {Blockly.ASTNode} newNode The new location of the marker.
85 | */
86 | Blockly.Marker.prototype.setCurNode = function(newNode) {
87 | var oldNode = this.curNode_;
88 | this.curNode_ = newNode;
89 | if (this.drawer_) {
90 | this.drawer_.draw(oldNode, this.curNode_);
91 | }
92 | };
93 |
94 | /**
95 | * Redraw the current marker.
96 | * @package
97 | */
98 | Blockly.Marker.prototype.draw = function() {
99 | if (this.drawer_) {
100 | this.drawer_.draw(this.curNode_, this.curNode_);
101 | }
102 | };
103 |
104 | /**
105 | * Hide the marker SVG.
106 | */
107 | Blockly.Marker.prototype.hide = function() {
108 | if (this.drawer_) {
109 | this.drawer_.hide();
110 | }
111 | };
112 |
113 | /**
114 | * Dispose of this marker.
115 | */
116 | Blockly.Marker.prototype.dispose = function() {
117 | if (this.getDrawer()) {
118 | this.getDrawer().dispose();
119 | }
120 | };
121 |
--------------------------------------------------------------------------------
/js/core/utils/metrics.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2020 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Workspace metrics definitions.
9 | * @author samelh@google.com (Sam El-Husseini)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.utils.Metrics');
14 |
15 |
16 | /**
17 | * @record
18 | */
19 | Blockly.utils.Metrics = function() {};
20 |
21 | /**
22 | * Height of the visible portion of the workspace.
23 | * @type {number}
24 | */
25 | Blockly.utils.Metrics.prototype.viewHeight;
26 |
27 | /**
28 | * Width of the visible portion of the workspace.
29 | * @type {number}
30 | */
31 | Blockly.utils.Metrics.prototype.viewWidth;
32 |
33 | /**
34 | * Height of the content.
35 | * @type {number}
36 | */
37 | Blockly.utils.Metrics.prototype.contentHeight;
38 |
39 | /**
40 | * Width of the content.
41 | * @type {number}
42 | */
43 | Blockly.utils.Metrics.prototype.contentWidth;
44 |
45 | /**
46 | * Top-edge of the visible portion of the workspace, relative to the workspace
47 | * origin.
48 | * @type {number}
49 | */
50 | Blockly.utils.Metrics.prototype.viewTop;
51 |
52 | /**
53 | * Left-edge of the visible portion of the workspace, relative to the workspace
54 | * origin.
55 | * @type {number}
56 | */
57 | Blockly.utils.Metrics.prototype.viewLeft;
58 |
59 | /**
60 | * Top-edge of the content, relative to the workspace origin.
61 | * @type {number}
62 | */
63 | Blockly.utils.Metrics.prototype.contentTop;
64 |
65 | /**
66 | * Left-edge of the content relative to the workspace origin.
67 | * @type {number}
68 | */
69 | Blockly.utils.Metrics.prototype.contentLeft;
70 |
71 | /**
72 | * Top-edge of the visible portion of the workspace, relative to the blocklyDiv.
73 | * @type {number}
74 | */
75 | Blockly.utils.Metrics.prototype.absoluteTop;
76 |
77 | /**
78 | * Left-edge of the visible portion of the workspace, relative to the
79 | * blocklyDiv.
80 | * @type {number}
81 | */
82 | Blockly.utils.Metrics.prototype.absoluteLeft;
83 |
84 | /**
85 | * Height of the Blockly div (the view + the toolbox, simple of otherwise).
86 | * @type {number|undefined}
87 | */
88 | Blockly.utils.Metrics.prototype.svgHeight;
89 |
90 | /**
91 | * Width of the Blockly div (the view + the toolbox, simple or otherwise).
92 | * @type {number|undefined}
93 | */
94 | Blockly.utils.Metrics.prototype.svgWidth;
95 |
96 | /**
97 | * Width of the toolbox, if it exists. Otherwise zero.
98 | * @type {number|undefined}
99 | */
100 | Blockly.utils.Metrics.prototype.toolboxWidth;
101 |
102 | /**
103 | * Height of the toolbox, if it exists. Otherwise zero.
104 | * @type {number|undefined}
105 | */
106 | Blockly.utils.Metrics.prototype.toolboxHeight;
107 |
108 | /**
109 | * Top, bottom, left or right. Use TOOLBOX_AT constants to compare.
110 | * @type {number|undefined}
111 | */
112 | Blockly.utils.Metrics.prototype.toolboxPosition;
113 |
114 | /**
115 | * Width of the flyout if it is always open. Otherwise zero.
116 | * @type {number|undefined}
117 | */
118 | Blockly.utils.Metrics.prototype.flyoutWidth;
119 |
120 | /**
121 | * Height of the flyout if it is always open. Otherwise zero.
122 | * @type {number|undefined}
123 | */
124 | Blockly.utils.Metrics.prototype.flyoutHeight;
125 |
--------------------------------------------------------------------------------
/js/core/theme/highcontrast.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2018 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview High contrast theme.
9 | * Darker colours to contrast the white font.
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.Themes.HighContrast');
14 |
15 | goog.require('Blockly.Theme');
16 |
17 |
18 | // Temporary holding object.
19 | Blockly.Themes.HighContrast = {};
20 |
21 | Blockly.Themes.HighContrast.defaultBlockStyles = {
22 | "colour_blocks": {
23 | "colourPrimary": "#a52714",
24 | "colourSecondary": "#FB9B8C",
25 | "colourTertiary": "#FBE1DD"
26 | },
27 | "list_blocks": {
28 | "colourPrimary": "#4a148c",
29 | "colourSecondary": "#AD7BE9",
30 | "colourTertiary": "#CDB6E9"
31 | },
32 | "logic_blocks": {
33 | "colourPrimary": "#01579b",
34 | "colourSecondary": "#64C7FF",
35 | "colourTertiary": "#C5EAFF"
36 | },
37 | "loop_blocks": {
38 | "colourPrimary": "#33691e",
39 | "colourSecondary": "#9AFF78",
40 | "colourTertiary": "#E1FFD7"
41 | },
42 | "math_blocks": {
43 | "colourPrimary": "#1a237e",
44 | "colourSecondary": "#8A9EFF",
45 | "colourTertiary": "#DCE2FF"
46 | },
47 | "procedure_blocks": {
48 | "colourPrimary": "#006064",
49 | "colourSecondary": "#77E6EE",
50 | "colourTertiary": "#CFECEE"
51 | },
52 | "text_blocks": {
53 | "colourPrimary": "#004d40",
54 | "colourSecondary": "#5ae27c",
55 | "colourTertiary": "#D2FFDD"
56 | },
57 | "variable_blocks": {
58 | "colourPrimary": "#880e4f",
59 | "colourSecondary": "#FF73BE",
60 | "colourTertiary": "#FFD4EB"
61 | },
62 | "variable_dynamic_blocks": {
63 | "colourPrimary": "#880e4f",
64 | "colourSecondary": "#FF73BE",
65 | "colourTertiary": "#FFD4EB"
66 | },
67 | "hat_blocks": {
68 | "colourPrimary": "#880e4f",
69 | "colourSecondary": "#FF73BE",
70 | "colourTertiary": "#FFD4EB",
71 | "hat": "cap"
72 | }
73 | };
74 |
75 | Blockly.Themes.HighContrast.categoryStyles = {
76 | "colour_category": {
77 | "colour": "#a52714"
78 | },
79 | "list_category": {
80 | "colour": "#4a148c"
81 | },
82 | "logic_category": {
83 | "colour": "#01579b"
84 | },
85 | "loop_category": {
86 | "colour": "#33691e"
87 | },
88 | "math_category": {
89 | "colour": "#1a237e"
90 | },
91 | "procedure_category": {
92 | "colour": "#006064"
93 | },
94 | "text_category": {
95 | "colour": "#004d40"
96 | },
97 | "variable_category": {
98 | "colour": "#880e4f"
99 | },
100 | "variable_dynamic_category": {
101 | "colour": "#880e4f"
102 | }
103 | };
104 |
105 | // This style is still being fleshed out and may change.
106 | Blockly.Themes.HighContrast =
107 | new Blockly.Theme('highcontrast',
108 | Blockly.Themes.HighContrast.defaultBlockStyles,
109 | Blockly.Themes.HighContrast.categoryStyles);
110 |
111 | Blockly.Themes.HighContrast.setComponentStyle('selectedGlowColour', '#000000');
112 | Blockly.Themes.HighContrast.setComponentStyle('selectedGlowSize', 1);
113 | Blockly.Themes.HighContrast.setComponentStyle('replacementGlowColour', '#000000');
114 |
115 | Blockly.Themes.HighContrast.setFontStyle({
116 | 'family': null, // Use default font-family
117 | 'weight': null, // Use default font-weight
118 | 'size': 16
119 | });
120 |
--------------------------------------------------------------------------------
/js/core/requires.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Default Blockly entry point. Use this to pick and choose which
9 | * fields and renderers to include in your Blockly bundle.
10 | * @author samelh@google.com (Sam El-Husseini)
11 | */
12 | 'use strict';
13 |
14 | goog.provide('Blockly.requires');
15 |
16 | // Blockly Core (absolutely mandatory).
17 | goog.require('Blockly');
18 |
19 |
20 | // If block comments aren't required, then Blockly.inject's "comments"
21 | // configuration must be false, and no blocks may be loaded from XML which
22 | // define comments.
23 | goog.require('Blockly.Comment');
24 | // One of these two will almost certainly be needed (usually VerticalFlyout).
25 | goog.require('Blockly.HorizontalFlyout');
26 | goog.require('Blockly.VerticalFlyout');
27 | // Flyout buttons are needed by the variable category,
28 | // and by any custom toolbox that has a button or a label.
29 | goog.require('Blockly.FlyoutButton');
30 | // If there is code generation into any language, then the generator is needed.
31 | // Should not be required when using advanced compilation since
32 | // individual generator files should already have this require.
33 | goog.require('Blockly.Generator');
34 | // If the toolbox does not have categories and only has a simple flyout, then
35 | // 'Blockly.Toolbox' is not needed.
36 | goog.require('Blockly.Toolbox');
37 | // If a trashcan on the workspace isn't required, then Blockly.inject's
38 | // "trashcan" configuration must be false.
39 | goog.require('Blockly.Trashcan');
40 | // Only needed if one is using the 'VARIABLE_DYNAMIC' typed variables category.
41 | goog.require('Blockly.VariablesDynamic');
42 | // Only need to require these two if you're using workspace comments.
43 | // goog.require('Blockly.WorkspaceCommentSvg');
44 | // goog.require('Blockly.WorkspaceCommentSvg.render');
45 | // If zoom controls aren't required, then Blockly.inject's
46 | // "zoom"/"controls" configuration must be false.
47 | goog.require('Blockly.ZoomControls');
48 |
49 |
50 | // Block dependencies.
51 | // None of these should be required when using advanced compilation since
52 | // individual block files should include the requirements they depend on.
53 | goog.require('Blockly.Mutator');
54 | goog.require('Blockly.Warning');
55 | goog.require('Blockly.FieldAngle');
56 | goog.require('Blockly.FieldCheckbox');
57 | goog.require('Blockly.FieldColour');
58 | goog.require('Blockly.FieldDropdown');
59 | goog.require('Blockly.FieldLabelSerializable');
60 | goog.require('Blockly.FieldImage');
61 | goog.require('Blockly.FieldTextInput');
62 | goog.require('Blockly.FieldMultilineInput');
63 | goog.require('Blockly.FieldNumber');
64 | goog.require('Blockly.FieldVariable');
65 |
66 |
67 | // Blockly Renderers.
68 | // At least one renderer is mandatory. Geras is the default one.
69 | // Others may be chosen using Blockly.inject's "renderer" configuration.
70 | goog.require('Blockly.geras.Renderer');
71 | goog.require('Blockly.thrasos.Renderer');
72 | goog.require('Blockly.zelos.Renderer');
73 | // The debug renderer, which shows simplified versions of the blocks for
74 | // developer use.
75 | // goog.require('Blockly.blockRendering.Debug');
76 |
77 | // Blockly Themes.
78 | // Classic is the default theme.
79 | goog.require('Blockly.Themes.Classic');
80 | goog.require('Blockly.Themes.Dark');
81 | goog.require('Blockly.Themes.Deuteranopia');
82 | goog.require('Blockly.Themes.HighContrast');
83 | goog.require('Blockly.Themes.Tritanopia');
84 | // goog.require('Blockly.Themes.Modern');
85 |
--------------------------------------------------------------------------------
/main.js:
--------------------------------------------------------------------------------
1 | // Modules to control application life and create native browser window
2 | const {app, BrowserWindow, shell, Menu, ipcMain} = require('electron')
3 | const path = require('path')
4 | const openAboutWindow = require('about-window').default
5 |
6 | function createWindow () {
7 | // Create the browser window.
8 | const mainWindow = new BrowserWindow({
9 | width: 800,
10 | height: 600,
11 | webPreferences: {
12 | preload: path.join(__dirname, 'preload.js'),
13 | nodeIntegration: true,
14 | enableRemoteModule: true,
15 | }
16 | })
17 |
18 | // The menubar template.
19 | const template = [
20 | {
21 | label: 'File',
22 | submenu: [
23 | {
24 | label: 'Exit',
25 | click() {
26 | mainWindow.close();
27 | }
28 | }
29 | ]
30 | },
31 | {
32 | label: 'View',
33 | submenu: [
34 | {
35 | label: 'Reload',
36 | accelerator: 'CmdOrCtrl+R',
37 | click() {
38 | mainWindow.webContents.reload();
39 | }
40 | },
41 | {
42 | label: 'Toggle Developer Tools',
43 | accelerator: 'F12',
44 | click() {
45 | mainWindow.webContents.openDevTools();
46 | }
47 | }
48 | ]
49 | },
50 | {
51 | label: 'Help',
52 | submenu: [
53 | {
54 | label: 'About',
55 | click() {
56 | openAboutWindow({
57 | icon_path: path.join(__dirname, 'media', 'paia-logo.png'),
58 | package_json_dir: __dirname,
59 | win_options: {
60 | parent: mainWindow,
61 | modal: true
62 | },
63 | bug_report_url: 'https://github.com/jason53415/blockly-app/issues'
64 | });
65 | }
66 | }
67 | ]
68 | }
69 | ];
70 |
71 | Menu.setApplicationMenu(Menu.buildFromTemplate(template));
72 |
73 | // and load the index.html of the app.
74 | mainWindow.loadFile('index.html')
75 | // mainWindow.setMenuBarVisibility(false)
76 |
77 | // Open the DevTools.
78 | // mainWindow.webContents.openDevTools()
79 | var handleRedirect = (e, url) => {
80 | if(url.startsWith('http')) {
81 | e.preventDefault()
82 | shell.openExternal(url)
83 | }
84 | }
85 |
86 | mainWindow.webContents.on('will-navigate', handleRedirect)
87 | }
88 |
89 | // Make sure not launching multiple times during install on Windows.
90 | if (require('electron-squirrel-startup')) return app.quit();
91 |
92 | // This method will be called when Electron has finished
93 | // initialization and is ready to create browser windows.
94 | // Some APIs can only be used after this event occurs.
95 | app.whenReady().then(() => {
96 | createWindow()
97 |
98 | app.on('activate', function () {
99 | // On macOS it's common to re-create a window in the app when the
100 | // dock icon is clicked and there are no other windows open.
101 | if (BrowserWindow.getAllWindows().length === 0) createWindow()
102 | })
103 | })
104 |
105 | // Quit when all windows are closed, except on macOS. There, it's common
106 | // for applications and their menu bar to stay active until the user quits
107 | // explicitly with Cmd + Q.
108 | app.on('window-all-closed', function () {
109 | if (process.platform !== 'darwin') app.quit()
110 | })
111 |
112 | // In this file you can include the rest of your app's specific main process
113 | // code. You can also put them in separate files and require them here.
114 |
--------------------------------------------------------------------------------
/js/core/renderers/zelos/measurables/rows.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview An object representing a single row on a rendered block and all
9 | * of its subcomponents.
10 | * @author samelh@google.com (Sam El-Husseini)
11 | */
12 | 'use strict';
13 |
14 | goog.provide('Blockly.zelos.BottomRow');
15 | goog.provide('Blockly.zelos.TopRow');
16 |
17 | goog.require('Blockly.blockRendering.BottomRow');
18 | goog.require('Blockly.blockRendering.TopRow');
19 | goog.require('Blockly.blockRendering.SpacerRow');
20 | goog.require('Blockly.utils.object');
21 |
22 |
23 | /**
24 | * An object containing information about what elements are in the top row of a
25 | * block as well as sizing information for the top row.
26 | * Elements in a top row can consist of corners, hats, spacers, and previous
27 | * connections.
28 | * After this constructor is called, the row will contain all non-spacer
29 | * elements it needs.
30 | * @param {!Blockly.blockRendering.ConstantProvider} constants The rendering
31 | * constants provider.
32 | * @package
33 | * @constructor
34 | * @extends {Blockly.blockRendering.TopRow}
35 | */
36 | Blockly.zelos.TopRow = function(constants) {
37 | Blockly.zelos.TopRow.superClass_.constructor.call(this, constants);
38 | };
39 | Blockly.utils.object.inherits(Blockly.zelos.TopRow,
40 | Blockly.blockRendering.TopRow);
41 |
42 | /**
43 | * @override
44 | */
45 | Blockly.zelos.TopRow.prototype.endsWithElemSpacer = function() {
46 | return false;
47 | };
48 |
49 | /**
50 | * Render a round corner unless the block has an output connection.
51 | * @override
52 | */
53 | Blockly.zelos.TopRow.prototype.hasLeftSquareCorner = function(block) {
54 | var hasHat = (block.hat ?
55 | block.hat === 'cap' : this.constants_.ADD_START_HATS) &&
56 | !block.outputConnection && !block.previousConnection;
57 | return !!block.outputConnection || hasHat;
58 | };
59 |
60 | /**
61 | * Render a round corner unless the block has an output connection.
62 | * @override
63 | */
64 | Blockly.zelos.TopRow.prototype.hasRightSquareCorner = function(block) {
65 | return !!block.outputConnection && !block.statementInputCount &&
66 | !block.nextConnection;
67 | };
68 |
69 | /**
70 | * An object containing information about what elements are in the bottom row of
71 | * a block as well as spacing information for the top row.
72 | * Elements in a bottom row can consist of corners, spacers and next
73 | * connections.
74 | * @param {!Blockly.blockRendering.ConstantProvider} constants The rendering
75 | * constants provider.
76 | * @package
77 | * @constructor
78 | * @extends {Blockly.blockRendering.BottomRow}
79 | */
80 | Blockly.zelos.BottomRow = function(constants) {
81 | Blockly.zelos.BottomRow.superClass_.constructor.call(this, constants);
82 | };
83 | Blockly.utils.object.inherits(Blockly.zelos.BottomRow,
84 | Blockly.blockRendering.BottomRow);
85 |
86 | /**
87 | * @override
88 | */
89 | Blockly.zelos.BottomRow.prototype.endsWithElemSpacer = function() {
90 | return false;
91 | };
92 |
93 | /**
94 | * Render a round corner unless the block has an output connection.
95 | * @override
96 | */
97 | Blockly.zelos.BottomRow.prototype.hasLeftSquareCorner = function(block) {
98 | return !!block.outputConnection;
99 | };
100 |
101 | /**
102 | * Render a round corner unless the block has an output connection.
103 | * @override
104 | */
105 | Blockly.zelos.BottomRow.prototype.hasRightSquareCorner = function(block) {
106 | return !!block.outputConnection && !block.statementInputCount &&
107 | !block.nextConnection;
108 | };
109 |
--------------------------------------------------------------------------------
/js/generators/php/colour.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2015 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Generating PHP for colour blocks.
9 | * @author daarond@gmail.com (Daaron Dwyer)
10 | */
11 | 'use strict';
12 |
13 | goog.provide('Blockly.PHP.colour');
14 |
15 | goog.require('Blockly.PHP');
16 |
17 |
18 | Blockly.PHP['colour_picker'] = function(block) {
19 | // Colour picker.
20 | var code = Blockly.PHP.quote_(block.getFieldValue('COLOUR'));
21 | return [code, Blockly.PHP.ORDER_ATOMIC];
22 | };
23 |
24 | Blockly.PHP['colour_random'] = function(block) {
25 | // Generate a random colour.
26 | var functionName = Blockly.PHP.provideFunction_(
27 | 'colour_random',
28 | ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + '() {',
29 | ' return \'#\' . str_pad(dechex(mt_rand(0, 0xFFFFFF)), ' +
30 | '6, \'0\', STR_PAD_LEFT);',
31 | '}']);
32 | var code = functionName + '()';
33 | return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
34 | };
35 |
36 | Blockly.PHP['colour_rgb'] = function(block) {
37 | // Compose a colour from RGB components expressed as percentages.
38 | var red = Blockly.PHP.valueToCode(block, 'RED',
39 | Blockly.PHP.ORDER_COMMA) || 0;
40 | var green = Blockly.PHP.valueToCode(block, 'GREEN',
41 | Blockly.PHP.ORDER_COMMA) || 0;
42 | var blue = Blockly.PHP.valueToCode(block, 'BLUE',
43 | Blockly.PHP.ORDER_COMMA) || 0;
44 | var functionName = Blockly.PHP.provideFunction_(
45 | 'colour_rgb',
46 | ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
47 | '($r, $g, $b) {',
48 | ' $r = round(max(min($r, 100), 0) * 2.55);',
49 | ' $g = round(max(min($g, 100), 0) * 2.55);',
50 | ' $b = round(max(min($b, 100), 0) * 2.55);',
51 | ' $hex = \'#\';',
52 | ' $hex .= str_pad(dechex($r), 2, \'0\', STR_PAD_LEFT);',
53 | ' $hex .= str_pad(dechex($g), 2, \'0\', STR_PAD_LEFT);',
54 | ' $hex .= str_pad(dechex($b), 2, \'0\', STR_PAD_LEFT);',
55 | ' return $hex;',
56 | '}']);
57 | var code = functionName + '(' + red + ', ' + green + ', ' + blue + ')';
58 | return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
59 | };
60 |
61 | Blockly.PHP['colour_blend'] = function(block) {
62 | // Blend two colours together.
63 | var c1 = Blockly.PHP.valueToCode(block, 'COLOUR1',
64 | Blockly.PHP.ORDER_COMMA) || '\'#000000\'';
65 | var c2 = Blockly.PHP.valueToCode(block, 'COLOUR2',
66 | Blockly.PHP.ORDER_COMMA) || '\'#000000\'';
67 | var ratio = Blockly.PHP.valueToCode(block, 'RATIO',
68 | Blockly.PHP.ORDER_COMMA) || 0.5;
69 | var functionName = Blockly.PHP.provideFunction_(
70 | 'colour_blend',
71 | ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
72 | '($c1, $c2, $ratio) {',
73 | ' $ratio = max(min($ratio, 1), 0);',
74 | ' $r1 = hexdec(substr($c1, 1, 2));',
75 | ' $g1 = hexdec(substr($c1, 3, 2));',
76 | ' $b1 = hexdec(substr($c1, 5, 2));',
77 | ' $r2 = hexdec(substr($c2, 1, 2));',
78 | ' $g2 = hexdec(substr($c2, 3, 2));',
79 | ' $b2 = hexdec(substr($c2, 5, 2));',
80 | ' $r = round($r1 * (1 - $ratio) + $r2 * $ratio);',
81 | ' $g = round($g1 * (1 - $ratio) + $g2 * $ratio);',
82 | ' $b = round($b1 * (1 - $ratio) + $b2 * $ratio);',
83 | ' $hex = \'#\';',
84 | ' $hex .= str_pad(dechex($r), 2, \'0\', STR_PAD_LEFT);',
85 | ' $hex .= str_pad(dechex($g), 2, \'0\', STR_PAD_LEFT);',
86 | ' $hex .= str_pad(dechex($b), 2, \'0\', STR_PAD_LEFT);',
87 | ' return $hex;',
88 | '}']);
89 | var code = functionName + '(' + c1 + ', ' + c2 + ', ' + ratio + ')';
90 | return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
91 | };
92 |
--------------------------------------------------------------------------------
/js/blocks/colour.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2012 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Colour blocks for Blockly.
9 | *
10 | * This file is scraped to extract a .json file of block definitions. The array
11 | * passed to defineBlocksWithJsonArray(..) must be strict JSON: double quotes
12 | * only, no outside references, no functions, no trailing commas, etc. The one
13 | * exception is end-of-line comments, which the scraper will remove.
14 | * @author fraser@google.com (Neil Fraser)
15 | */
16 | 'use strict';
17 |
18 | goog.provide('Blockly.Blocks.colour'); // Deprecated
19 | goog.provide('Blockly.Constants.Colour');
20 |
21 | goog.require('Blockly');
22 | goog.require('Blockly.Blocks');
23 | goog.require('Blockly.FieldColour');
24 | goog.require('Blockly.FieldLabel');
25 |
26 |
27 | /**
28 | * Unused constant for the common HSV hue for all blocks in this category.
29 | * @deprecated Use Blockly.Msg['COLOUR_HUE']. (2018 April 5)
30 | */
31 | Blockly.Constants.Colour.HUE = 20;
32 |
33 | Blockly.defineBlocksWithJsonArray([ // BEGIN JSON EXTRACT
34 | // Block for colour picker.
35 | {
36 | "type": "colour_picker",
37 | "message0": "%1",
38 | "args0": [
39 | {
40 | "type": "field_colour",
41 | "name": "COLOUR",
42 | "colour": "#ff0000"
43 | }
44 | ],
45 | "output": "Colour",
46 | "helpUrl": "%{BKY_COLOUR_PICKER_HELPURL}",
47 | "style": "colour_blocks",
48 | "tooltip": "%{BKY_COLOUR_PICKER_TOOLTIP}",
49 | "extensions": ["parent_tooltip_when_inline"]
50 | },
51 |
52 | // Block for random colour.
53 | {
54 | "type": "colour_random",
55 | "message0": "%{BKY_COLOUR_RANDOM_TITLE}",
56 | "output": "Colour",
57 | "helpUrl": "%{BKY_COLOUR_RANDOM_HELPURL}",
58 | "style": "colour_blocks",
59 | "tooltip": "%{BKY_COLOUR_RANDOM_TOOLTIP}"
60 | },
61 |
62 | // Block for composing a colour from RGB components.
63 | {
64 | "type": "colour_rgb",
65 | "message0": "%{BKY_COLOUR_RGB_TITLE} %{BKY_COLOUR_RGB_RED} %1 %{BKY_COLOUR_RGB_GREEN} %2 %{BKY_COLOUR_RGB_BLUE} %3",
66 | "args0": [
67 | {
68 | "type": "input_value",
69 | "name": "RED",
70 | "check": "Number",
71 | "align": "RIGHT"
72 | },
73 | {
74 | "type": "input_value",
75 | "name": "GREEN",
76 | "check": "Number",
77 | "align": "RIGHT"
78 | },
79 | {
80 | "type": "input_value",
81 | "name": "BLUE",
82 | "check": "Number",
83 | "align": "RIGHT"
84 | }
85 | ],
86 | "output": "Colour",
87 | "helpUrl": "%{BKY_COLOUR_RGB_HELPURL}",
88 | "style": "colour_blocks",
89 | "tooltip": "%{BKY_COLOUR_RGB_TOOLTIP}"
90 | },
91 |
92 | // Block for blending two colours together.
93 | {
94 | "type": "colour_blend",
95 | "message0": "%{BKY_COLOUR_BLEND_TITLE} %{BKY_COLOUR_BLEND_COLOUR1} " +
96 | "%1 %{BKY_COLOUR_BLEND_COLOUR2} %2 %{BKY_COLOUR_BLEND_RATIO} %3",
97 | "args0": [
98 | {
99 | "type": "input_value",
100 | "name": "COLOUR1",
101 | "check": "Colour",
102 | "align": "RIGHT"
103 | },
104 | {
105 | "type": "input_value",
106 | "name": "COLOUR2",
107 | "check": "Colour",
108 | "align": "RIGHT"
109 | },
110 | {
111 | "type": "input_value",
112 | "name": "RATIO",
113 | "check": "Number",
114 | "align": "RIGHT"
115 | }
116 | ],
117 | "output": "Colour",
118 | "helpUrl": "%{BKY_COLOUR_BLEND_HELPURL}",
119 | "style": "colour_blocks",
120 | "tooltip": "%{BKY_COLOUR_BLEND_TOOLTIP}"
121 | }
122 | ]); // END JSON EXTRACT (Do not delete this comment.)
123 |
--------------------------------------------------------------------------------
/media/pingpong.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "blockly-app",
3 | "version": "1.2.6",
4 | "description": "A blockly application that can build AI to play games.",
5 | "main": "main.js",
6 | "scripts": {
7 | "start": "electron-forge start",
8 | "package": "electron-forge package",
9 | "make": "electron-forge make",
10 | "make-py": "cd ./python && pyinstaller -y --hidden-import=csv --hidden-import=pathlib --hidden-import=matplotlib.pyplot --hidden-import=pynput.keyboard._win32 --hidden-import=pynput.mouse._win32 --hidden-import=pynput.keyboard._darwin --hidden-import=pynput.mouse._darwin --hidden-import=pynput.keyboard._xorg --hidden-import=pynput.mouse._xorg --hidden-import=queue --hidden-import=pygame --hidden-import=multiprocessing --hidden-import=pickle --hidden-import=Box2D --hidden-import=sklearn.neighbors --hidden-import=sklearn.tree --hidden-import=sklearn.svm --hidden-import=sklearn.ensemble --hidden-import=sklearn.neural_network --hidden-import=sklearn.linear_model --hidden-import=sklearn.metrics --hidden-import=sklearn.model_selection --hidden-import=sklearn.utils._weight_vector --hidden-import=scipy.special.cython_special interpreter.py"
11 | },
12 | "repository": "https://github.com/jason53415/blockly-app",
13 | "keywords": [
14 | "Blockly",
15 | "Python",
16 | "MLGame",
17 | "AI"
18 | ],
19 | "author": "PAIA",
20 | "license": "CC0-1.0",
21 | "devDependencies": {
22 | "@electron-forge/cli": "^6.0.0-beta.54",
23 | "@electron-forge/maker-deb": "^6.0.0-beta.54",
24 | "@electron-forge/maker-dmg": "^6.0.0-beta.54",
25 | "@electron-forge/maker-rpm": "^6.0.0-beta.54",
26 | "@electron-forge/maker-squirrel": "^6.0.0-beta.54",
27 | "@electron-forge/maker-zip": "^6.0.0-beta.54",
28 | "electron": "^11.1.1"
29 | },
30 | "dependencies": {
31 | "@paia-arena/blockly": "^0.0.3",
32 | "about-window": "^1.15.1",
33 | "bootstrap": "^4.1.3",
34 | "bootstrap-icons": "^1.5.0",
35 | "codemirror": "^5.61.1",
36 | "download-git-repo": "^3.0.2",
37 | "electron-installer-dmg": "^3.0.0",
38 | "electron-squirrel-startup": "^1.0.0",
39 | "electron-store": "^6.0.1",
40 | "github-markdown-css": "^4.0.0",
41 | "jquery": "^3.3.1",
42 | "popper.js": "^1.14.4",
43 | "python-shell": "^2.0.3",
44 | "showdown": "^1.9.1",
45 | "vex-js": "^4.1.0"
46 | },
47 | "config": {
48 | "forge": {
49 | "packagerConfig": {
50 | "icon": "media/paia-logo",
51 | "ignore": [
52 | "/.gitignore",
53 | "/.gitmodules",
54 | "/.vscode",
55 | "/requirements.txt",
56 | "/js/blocks",
57 | "/js/generators",
58 | "/js/i18n",
59 | "/js/mlgame",
60 | "/js/msg",
61 | "/js/build.py",
62 | "(.*)__pycache__",
63 | "/python/build",
64 | "/python/interpreter.spec",
65 | "/python/interpreter.py"
66 | ]
67 | },
68 | "makers": [
69 | {
70 | "name": "@electron-forge/maker-squirrel",
71 | "config": {}
72 | },
73 | {
74 | "name": "@electron-forge/maker-zip",
75 | "platforms": [
76 | "darwin",
77 | "win32"
78 | ]
79 | },
80 | {
81 | "name": "@electron-forge/maker-dmg",
82 | "platforms": [
83 | "darwin"
84 | ]
85 | },
86 | {
87 | "name": "@electron-forge/maker-deb",
88 | "config": {
89 | "options": {
90 | "icon": "media/paia-logo.png"
91 | }
92 | }
93 | },
94 | {
95 | "name": "@electron-forge/maker-rpm",
96 | "config": {
97 | "options": {
98 | "icon": "media/paia-logo.png"
99 | }
100 | }
101 | }
102 | ]
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/js/core/utils/coordinate.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright 2019 Google LLC
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Utility methods for coordinate manipulation.
9 | * These methods are not specific to Blockly, and could be factored out into
10 | * a JavaScript framework such as Closure.
11 | * @author fraser@google.com (Neil Fraser)
12 | */
13 | 'use strict';
14 |
15 | /**
16 | * @name Blockly.utils.Coordinate
17 | * @namespace
18 | */
19 | goog.provide('Blockly.utils.Coordinate');
20 |
21 |
22 | /**
23 | * Class for representing coordinates and positions.
24 | * @param {number} x Left.
25 | * @param {number} y Top.
26 | * @struct
27 | * @constructor
28 | */
29 | Blockly.utils.Coordinate = function(x, y) {
30 | /**
31 | * X-value
32 | * @type {number}
33 | */
34 | this.x = x;
35 |
36 | /**
37 | * Y-value
38 | * @type {number}
39 | */
40 | this.y = y;
41 | };
42 |
43 | /**
44 | * Compares coordinates for equality.
45 | * @param {Blockly.utils.Coordinate} a A Coordinate.
46 | * @param {Blockly.utils.Coordinate} b A Coordinate.
47 | * @return {boolean} True iff the coordinates are equal, or if both are null.
48 | */
49 | Blockly.utils.Coordinate.equals = function(a, b) {
50 | if (a == b) {
51 | return true;
52 | }
53 | if (!a || !b) {
54 | return false;
55 | }
56 | return a.x == b.x && a.y == b.y;
57 | };
58 |
59 | /**
60 | * Returns the distance between two coordinates.
61 | * @param {!Blockly.utils.Coordinate} a A Coordinate.
62 | * @param {!Blockly.utils.Coordinate} b A Coordinate.
63 | * @return {number} The distance between `a` and `b`.
64 | */
65 | Blockly.utils.Coordinate.distance = function(a, b) {
66 | var dx = a.x - b.x;
67 | var dy = a.y - b.y;
68 | return Math.sqrt(dx * dx + dy * dy);
69 | };
70 |
71 | /**
72 | * Returns the magnitude of a coordinate.
73 | * @param {!Blockly.utils.Coordinate} a A Coordinate.
74 | * @return {number} The distance between the origin and `a`.
75 | */
76 | Blockly.utils.Coordinate.magnitude = function(a) {
77 | return Math.sqrt(a.x * a.x + a.y * a.y);
78 | };
79 |
80 | /**
81 | * Returns the difference between two coordinates as a new
82 | * Blockly.utils.Coordinate.
83 | * @param {!Blockly.utils.Coordinate|!SVGPoint} a An x/y coordinate.
84 | * @param {!Blockly.utils.Coordinate|!SVGPoint} b An x/y coordinate.
85 | * @return {!Blockly.utils.Coordinate} A Coordinate representing the difference
86 | * between `a` and `b`.
87 | */
88 | Blockly.utils.Coordinate.difference = function(a, b) {
89 | return new Blockly.utils.Coordinate(a.x - b.x, a.y - b.y);
90 | };
91 |
92 | /**
93 | * Returns the sum of two coordinates as a new Blockly.utils.Coordinate.
94 | * @param {!Blockly.utils.Coordinate|!SVGPoint} a An x/y coordinate.
95 | * @param {!Blockly.utils.Coordinate|!SVGPoint} b An x/y coordinate.
96 | * @return {!Blockly.utils.Coordinate} A Coordinate representing the sum of
97 | * the two coordinates.
98 | */
99 | Blockly.utils.Coordinate.sum = function(a, b) {
100 | return new Blockly.utils.Coordinate(a.x + b.x, a.y + b.y);
101 | };
102 |
103 | /**
104 | * Scales this coordinate by the given scale factor.
105 | * @param {number} s The scale factor to use for both x and y dimensions.
106 | * @return {!Blockly.utils.Coordinate} This coordinate after scaling.
107 | */
108 | Blockly.utils.Coordinate.prototype.scale = function(s) {
109 | this.x *= s;
110 | this.y *= s;
111 | return this;
112 | };
113 |
114 | /**
115 | * Translates this coordinate by the given offsets.
116 | * respectively.
117 | * @param {number} tx The value to translate x by.
118 | * @param {number} ty The value to translate y by.
119 | * @return {!Blockly.utils.Coordinate} This coordinate after translating.
120 | */
121 | Blockly.utils.Coordinate.prototype.translate = function(tx, ty) {
122 | this.x += tx;
123 | this.y += ty;
124 | return this;
125 | };
126 |
--------------------------------------------------------------------------------