2018-08-18 17:12:05 +00:00
|
|
|
// Blockly workspace
|
|
|
|
var workspace;
|
|
|
|
|
2018-11-12 20:33:26 +00:00
|
|
|
|
2018-08-12 10:37:02 +00:00
|
|
|
window.addEventListener('load', function() {
|
2018-07-08 18:52:16 +00:00
|
|
|
// To remember the control_if blockId
|
2018-08-12 10:37:02 +00:00
|
|
|
var controlBlockId = '';
|
2018-07-08 18:52:16 +00:00
|
|
|
|
|
|
|
// Change the if block to be more cheerful
|
2018-08-19 15:21:15 +00:00
|
|
|
Blockly.Msg.LOGIC_HUE = '#24c74f';
|
2018-07-08 18:52:16 +00:00
|
|
|
|
|
|
|
// Remote previous and next statement from control_if block
|
|
|
|
Blockly.defineBlocksWithJsonArray([
|
2018-11-12 20:33:26 +00:00
|
|
|
{
|
|
|
|
"type": "controls_if",
|
|
|
|
"message0": "%{BKY_CONTROLS_IF_MSG_IF} %1",
|
|
|
|
"args0": [
|
|
|
|
{
|
|
|
|
"type": "input_value",
|
|
|
|
"name": "IF0",
|
|
|
|
"check": "Boolean"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"message1": "%{BKY_CONTROLS_IF_MSG_THEN} %1",
|
|
|
|
"args1": [
|
|
|
|
{
|
|
|
|
"type": "input_statement",
|
|
|
|
"name": "DO0"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"colour": "%{BKY_LOGIC_HUE}",
|
|
|
|
"helpUrl": "%{BKY_CONTROLS_IF_HELPURL}",
|
|
|
|
"mutator": "controls_if_mutator",
|
|
|
|
"extensions": ["controls_if_tooltip"]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"type": "logic_operation",
|
|
|
|
"message0": "%1 %2 %3",
|
|
|
|
"args0": [
|
|
|
|
{
|
|
|
|
"type": "input_value",
|
|
|
|
"name": "A",
|
|
|
|
"check": "Boolean"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"type": "field_dropdown",
|
|
|
|
"name": "OP",
|
|
|
|
"options": [
|
|
|
|
["%{BKY_LOGIC_OPERATION_AND}", "AND"],
|
|
|
|
["%{BKY_LOGIC_OPERATION_OR}", "OR"]
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"type": "input_value",
|
|
|
|
"name": "B",
|
|
|
|
"check": "Boolean"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"inputsInline": true,
|
|
|
|
"output": "Boolean",
|
|
|
|
"colour": "%{BKY_LOGIC_HUE}",
|
|
|
|
"helpUrl": "%{BKY_LOGIC_OPERATION_HELPURL}",
|
|
|
|
"extensions": ["logic_op_tooltip"]
|
|
|
|
}
|
|
|
|
]);
|
2018-07-08 18:52:16 +00:00
|
|
|
|
|
|
|
// Make control_if mutator icon bigger
|
|
|
|
Blockly.Icon.prototype.renderIcon = function(cursorX) {
|
|
|
|
if (this.collapseHidden && this.block_.isCollapsed()) {
|
|
|
|
this.iconGroup_.setAttribute('display', 'none');
|
|
|
|
return cursorX;
|
|
|
|
}
|
|
|
|
this.iconGroup_.setAttribute('display', 'block');
|
|
|
|
|
|
|
|
var SIZE = 1.7;
|
|
|
|
var TOP_MARGIN = 2;
|
|
|
|
var LEFT_MARGIN = 5;
|
|
|
|
var width = this.SIZE;
|
|
|
|
if (this.block_.RTL) {
|
|
|
|
cursorX -= width;
|
|
|
|
}
|
|
|
|
this.iconGroup_.setAttribute('transform',
|
|
|
|
'translate(' + LEFT_MARGIN + ',' + TOP_MARGIN + ') scale(' + SIZE + ')');
|
|
|
|
this.computeIconLocation();
|
|
|
|
if (this.block_.RTL) {
|
|
|
|
cursorX -= Blockly.BlockSvg.SEP_SPACE_X;
|
|
|
|
} else {
|
|
|
|
cursorX += width + Blockly.BlockSvg.SEP_SPACE_X;
|
|
|
|
}
|
|
|
|
return cursorX;
|
|
|
|
};
|
|
|
|
|
|
|
|
// When mouse click occures on Blockly workspace
|
|
|
|
Blockly.utils.isRightButton = function(e) {
|
|
|
|
var target = e.target;
|
|
|
|
|
|
|
|
// When control_if block is in use
|
2018-08-12 10:37:02 +00:00
|
|
|
if (controlBlockId != '') {
|
2018-07-08 18:52:16 +00:00
|
|
|
// When the user clicks anywhere outside the mutator and not on the mutator icon
|
|
|
|
if (!$(target).is('.blocklyBubbleCanvas') && !$(target).parents().is('.blocklyBubbleCanvas')) {
|
|
|
|
if (!$(target).is('.blocklyIconGroup') && !$(target).parents().is('.blocklyIconGroup')) {
|
|
|
|
// Hide the mutator
|
|
|
|
workspace.getBlockById(controlBlockId).mutator.setVisible(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Disable right click on Blockly workspace
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
Blockly.Blocks['sumorobot_sleep'] = {
|
|
|
|
init: function() {
|
2018-08-19 15:21:15 +00:00
|
|
|
this.setColour('#e98017');
|
2018-07-08 18:52:16 +00:00
|
|
|
this.appendDummyInput()
|
2018-11-12 20:33:26 +00:00
|
|
|
.appendField(Blockly.Msg.SUMOROBOT_SLEEP)
|
2018-07-08 18:52:16 +00:00
|
|
|
.appendField(new Blockly.FieldTextInput('1000',
|
2018-11-12 20:33:26 +00:00
|
|
|
Blockly.FieldNumber.numberValidator), "SLEEP");
|
2018-07-08 18:52:16 +00:00
|
|
|
this.setPreviousStatement(true);
|
|
|
|
this.setNextStatement(true);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Blockly.Blocks['sumorobot_move'] = {
|
|
|
|
init: function() {
|
|
|
|
var OPERATORS = [
|
2018-11-12 20:33:26 +00:00
|
|
|
[Blockly.Msg.SUMOROBOT_STOP, 'STOP'],
|
|
|
|
[Blockly.Msg.SUMOROBOT_LEFT, 'LEFT'],
|
|
|
|
[Blockly.Msg.SUMOROBOT_RIGHT, 'RIGHT'],
|
|
|
|
[Blockly.Msg.SUMOROBOT_SEARCH, 'SEARCH'],
|
|
|
|
[Blockly.Msg.SUMOROBOT_FORWARD, 'FORWARD'],
|
|
|
|
[Blockly.Msg.SUMOROBOT_BACKWARD, 'BACKWARD']
|
2018-07-08 18:52:16 +00:00
|
|
|
];
|
2018-08-19 15:21:15 +00:00
|
|
|
this.setColour('#d6382d');
|
2018-07-08 18:52:16 +00:00
|
|
|
var dropdown = new Blockly.FieldDropdown(OPERATORS);
|
2018-11-12 20:33:26 +00:00
|
|
|
this.appendDummyInput().appendField(dropdown, 'Move');
|
2018-07-08 18:52:16 +00:00
|
|
|
this.setPreviousStatement(true);
|
|
|
|
this.setNextStatement(true);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Blockly.Blocks['sumorobot_opponent'] = {
|
|
|
|
init: function() {
|
2018-08-12 10:37:02 +00:00
|
|
|
this.setColour('#0099E6');
|
2018-11-12 20:33:26 +00:00
|
|
|
this.appendDummyInput().appendField(Blockly.Msg.SUMOROBOT_OPPONENT);
|
2018-07-08 18:52:16 +00:00
|
|
|
this.setOutput(true, 'Boolean');
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Blockly.Blocks['sumorobot_line'] = {
|
|
|
|
init: function() {
|
|
|
|
var OPERATORS = [
|
2018-11-12 20:33:26 +00:00
|
|
|
[Blockly.Msg.SUMOROBOT_LINE_LEFT, 'LEFT'],
|
|
|
|
[Blockly.Msg.SUMOROBOT_LINE_MIDDLE, 'MIDDLE'],
|
|
|
|
[Blockly.Msg.SUMOROBOT_LINE_RIGHT, 'RIGHT']
|
2018-07-08 18:52:16 +00:00
|
|
|
];
|
2018-08-12 10:37:02 +00:00
|
|
|
this.setColour('#E6BF00');
|
2018-07-08 18:52:16 +00:00
|
|
|
var dropdown = new Blockly.FieldDropdown(OPERATORS);
|
|
|
|
this.appendDummyInput().appendField(dropdown, 'LINE');
|
|
|
|
this.setOutput(true, 'Boolean');
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Blockly.Python['sumorobot_sleep'] = function(block) {
|
2018-11-12 20:33:26 +00:00
|
|
|
var code = 'sumorobot.sleep(' + parseFloat(block.getFieldValue("SLEEP")) + ');;' + block.id + '\n';
|
2018-07-08 18:52:16 +00:00
|
|
|
return code;
|
|
|
|
};
|
|
|
|
|
|
|
|
Blockly.Python['sumorobot_move'] = function(block) {
|
2018-11-12 20:33:26 +00:00
|
|
|
var code = 'sumorobot.move(' + block.getFieldValue('Move') + ');;' + block.id + '\n';
|
2018-07-08 18:52:16 +00:00
|
|
|
return code;
|
|
|
|
};
|
|
|
|
|
|
|
|
Blockly.Python['sumorobot_opponent'] = function(block) {
|
2018-08-15 17:53:10 +00:00
|
|
|
var code = 'sumorobot.is_opponent();;' + block.id;
|
2018-07-08 18:52:16 +00:00
|
|
|
return [code, Blockly.Python.ORDER_ATOMIC];
|
|
|
|
};
|
|
|
|
|
|
|
|
Blockly.Python['sumorobot_line'] = function(block) {
|
2018-08-15 17:53:10 +00:00
|
|
|
var code = 'sumorobot.is_line(' + block.getFieldValue('LINE') + ');;' + block.id;
|
2018-07-08 18:52:16 +00:00
|
|
|
return [code, Blockly.Python.ORDER_ATOMIC];
|
|
|
|
};
|
|
|
|
|
2018-11-12 20:33:26 +00:00
|
|
|
// Inject Blocklyresiz
|
2018-07-08 18:52:16 +00:00
|
|
|
var blocklyArea = document.getElementById('blocklyArea');
|
|
|
|
var blocklyDiv = document.getElementById('blocklyDiv');
|
2018-08-12 10:37:02 +00:00
|
|
|
workspace = Blockly.inject(blocklyDiv, {
|
2018-07-08 18:52:16 +00:00
|
|
|
media: 'assets/blockly/media/',
|
2018-11-12 20:33:26 +00:00
|
|
|
scrollbars: true,
|
2018-07-08 18:52:16 +00:00
|
|
|
trashcan: true,
|
|
|
|
sounds: true,
|
|
|
|
zoom: {
|
|
|
|
controls: true,
|
2018-11-12 20:33:26 +00:00
|
|
|
startScale: 1.0
|
2018-07-08 18:52:16 +00:00
|
|
|
},
|
|
|
|
toolbox: document.getElementById('toolbox')
|
|
|
|
});
|
|
|
|
|
|
|
|
// On Blockly resize
|
|
|
|
var onresize = function(e) {
|
|
|
|
// Compute the absolute coordinates and dimensions of blocklyArea.
|
|
|
|
var element = blocklyArea;
|
|
|
|
var x = 0;
|
|
|
|
var y = 0;
|
|
|
|
do {
|
|
|
|
x += element.offsetLeft;
|
|
|
|
y += element.offsetTop;
|
|
|
|
element = element.offsetParent;
|
|
|
|
} while (element);
|
|
|
|
// Position blocklyDiv over blocklyArea
|
|
|
|
blocklyDiv.style.left = x + 'px';
|
|
|
|
blocklyDiv.style.top = y + 'px';
|
|
|
|
blocklyDiv.style.width = blocklyArea.offsetWidth + 'px';
|
|
|
|
blocklyDiv.style.height = blocklyArea.offsetHeight + 'px';
|
2018-08-18 20:56:14 +00:00
|
|
|
// Resize the blockly svg
|
|
|
|
Blockly.svgResize(workspace);
|
2018-07-08 18:52:16 +00:00
|
|
|
};
|
|
|
|
window.addEventListener('resize', onresize, false);
|
|
|
|
onresize();
|
|
|
|
|
|
|
|
// Retrieve the blocks
|
2018-08-17 13:32:56 +00:00
|
|
|
var code = getLocalStorageItem('sumorobot.blockly');
|
|
|
|
// When there is code
|
|
|
|
if (code) {
|
|
|
|
// Convert it to XML
|
|
|
|
var xml = Blockly.Xml.textToDom(code);
|
|
|
|
// Resume the blocks from the XML
|
|
|
|
Blockly.Xml.domToWorkspace(xml, workspace);
|
|
|
|
}
|
2018-07-08 18:52:16 +00:00
|
|
|
// On Blockly code change
|
|
|
|
function onCodeChanged(event) {
|
|
|
|
// When the if condition block was created
|
2018-08-12 10:37:02 +00:00
|
|
|
if (event.type == Blockly.Events.CREATE &&
|
|
|
|
event.xml.getAttributeNode('type').nodeValue == 'controls_if') {
|
2018-07-08 18:52:16 +00:00
|
|
|
// Remember the control_if block id
|
|
|
|
controlBlockId = event.blockId;
|
|
|
|
// Get the control_if block object
|
|
|
|
var block = workspace.getBlockById(event.blockId);
|
|
|
|
// When the control_if block doesn't already have an else
|
|
|
|
if (block.elseCount_ == 0) {
|
|
|
|
// Automatically add the else statement input
|
|
|
|
block.elseCount_ = 1;
|
|
|
|
block.updateShape_();
|
|
|
|
}
|
|
|
|
// When the if condition block was removed
|
2018-08-12 10:37:02 +00:00
|
|
|
} else if (event.type == Blockly.Events.DELETE &&
|
|
|
|
event.oldXml.getAttributeNode('type').nodeValue == 'controls_if') {
|
2018-07-08 18:52:16 +00:00
|
|
|
// Remove the control_if block id
|
2018-08-12 10:37:02 +00:00
|
|
|
controlBlockId = '';
|
2018-07-08 18:52:16 +00:00
|
|
|
// Enable the if condition block
|
2018-08-12 10:37:02 +00:00
|
|
|
workspace.updateToolbox(document.getElementById('toolbox'));
|
2018-07-08 18:52:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Only process change and move commands
|
|
|
|
if (event.type != Blockly.Events.CHANGE && event.type != Blockly.Events.MOVE) return;
|
2018-08-12 10:37:02 +00:00
|
|
|
|
2018-07-08 18:52:16 +00:00
|
|
|
// Show the code in the ace editor, filter out block IDs
|
2018-08-18 17:12:05 +00:00
|
|
|
readOnlyCodingEditor.setValue(Blockly.Python.workspaceToCode(workspace).replace(/;;.{20}/g, ''));
|
2018-07-08 18:52:16 +00:00
|
|
|
readOnlyCodingEditor.clearSelection();
|
|
|
|
|
|
|
|
// Save the code to the local storage
|
|
|
|
var xml = Blockly.Xml.workspaceToDom(workspace);
|
2018-08-12 10:37:02 +00:00
|
|
|
localStorage.setItem('sumorobot.blockly', Blockly.Xml.domToText(xml));
|
2018-07-08 18:52:16 +00:00
|
|
|
|
|
|
|
// When control_if block is used
|
2018-08-12 10:37:02 +00:00
|
|
|
if (controlBlockId != '') {
|
2018-07-08 18:52:16 +00:00
|
|
|
// Disable the if condition block
|
2018-08-12 10:37:02 +00:00
|
|
|
workspace.updateToolbox(document.getElementById('toolbox_no_if'));
|
2018-07-08 18:52:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-17 13:32:56 +00:00
|
|
|
// Add the change listener to Blockly
|
2018-07-08 18:52:16 +00:00
|
|
|
workspace.addChangeListener(onCodeChanged);
|
|
|
|
|
|
|
|
// Set a click listener on the document
|
|
|
|
$(document).click(function(e) {
|
2018-08-17 13:32:56 +00:00
|
|
|
// Get the event target
|
2018-07-08 18:52:16 +00:00
|
|
|
var target = e.target;
|
|
|
|
// When control_if block is in use
|
2018-08-12 10:37:02 +00:00
|
|
|
if (controlBlockId != '') {
|
2018-07-08 18:52:16 +00:00
|
|
|
// When the user clicks anywhere outside the mutator and not on the mutator icon
|
|
|
|
if (!$(target).is('.blocklyBubbleCanvas') && !$(target).parents().is('.blocklyBubbleCanvas')) {
|
|
|
|
if (!$(target).is('.blocklyIconGroup') && !$(target).parents().is('.blocklyIconGroup')) {
|
|
|
|
// Hide the mutator
|
|
|
|
workspace.getBlockById(controlBlockId).mutator.setVisible(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|