2018-07-08 18:51:59 +00:00
|
|
|
|
// The local/remote server URL
|
2018-08-15 17:58:29 +00:00
|
|
|
|
//var ROBOT_SERVER = '192.168.2.1:80';
|
2018-09-12 12:12:54 +00:00
|
|
|
|
var ROBOT_SERVER = '165.227.140.64:80';
|
2018-07-08 18:51:59 +00:00
|
|
|
|
|
|
|
|
|
// The sumorobot object
|
2018-08-12 10:37:57 +00:00
|
|
|
|
var sumorobot;
|
2018-07-08 18:51:59 +00:00
|
|
|
|
// Disable / enable coding mode
|
|
|
|
|
var codingEnabled = false;
|
|
|
|
|
// Disable / enable live stream
|
|
|
|
|
var liveStreamVisible = false;
|
|
|
|
|
|
2018-08-12 10:37:57 +00:00
|
|
|
|
window.addEventListener('load', function() {
|
|
|
|
|
// Set the robot ID from the localstorage
|
|
|
|
|
$('#robot-id').val(getLocalStorageItem('sumorobot.robotId'));
|
2018-07-08 18:51:59 +00:00
|
|
|
|
|
|
|
|
|
// Key down event
|
|
|
|
|
$(document).keydown(function(e) {
|
|
|
|
|
// When the alt key is not pressed, don't process hotkeys
|
|
|
|
|
if (e.altKey == false) return;
|
|
|
|
|
|
|
|
|
|
// Prevent typing in textfields
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
|
|
// Select the hotkey
|
|
|
|
|
switch(e.which) {
|
|
|
|
|
case 32: // space bar
|
2018-08-12 10:37:57 +00:00
|
|
|
|
if (sumorobot.moving) {
|
|
|
|
|
$('.btn-stop').addClass('hover');
|
|
|
|
|
$('.btn-stop').click();
|
2018-07-08 18:51:59 +00:00
|
|
|
|
} else {
|
2018-08-12 10:37:57 +00:00
|
|
|
|
$('.btn-start').addClass('hover');
|
|
|
|
|
$('.btn-start').click();
|
2018-07-08 18:51:59 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 37: // left
|
2018-08-12 10:37:57 +00:00
|
|
|
|
sumorobot.send('left');
|
2018-07-08 18:51:59 +00:00
|
|
|
|
break;
|
|
|
|
|
case 38: // up
|
2018-08-12 10:37:57 +00:00
|
|
|
|
sumorobot.send('forward');
|
2018-07-08 18:51:59 +00:00
|
|
|
|
break;
|
|
|
|
|
case 39: // right
|
2018-08-12 10:37:57 +00:00
|
|
|
|
sumorobot.send('right');
|
2018-07-08 18:51:59 +00:00
|
|
|
|
break;
|
|
|
|
|
case 40: // down
|
2018-08-12 10:37:57 +00:00
|
|
|
|
sumorobot.send('backward');
|
2018-07-08 18:51:59 +00:00
|
|
|
|
break;
|
|
|
|
|
case 67: // c
|
2018-08-12 10:37:57 +00:00
|
|
|
|
$('#panel').toggle();
|
2018-07-08 18:51:59 +00:00
|
|
|
|
break;
|
|
|
|
|
case 76: // l
|
|
|
|
|
// No live stream if cookies are disabled
|
|
|
|
|
if (!cookiesEnabled) {
|
|
|
|
|
// TODO: Open the cookie consent popup
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-08-12 10:37:57 +00:00
|
|
|
|
// Load the Mixer stream when it is not yet loaded
|
|
|
|
|
if ($('#stream').is(':empty')) {
|
|
|
|
|
$('#stream').html('<iframe src="https://mixer.com/embed/player/14551694"></iframe>');
|
2018-07-08 18:51:59 +00:00
|
|
|
|
}
|
2018-08-12 10:37:57 +00:00
|
|
|
|
$('#stream').toggle();
|
2018-07-08 18:51:59 +00:00
|
|
|
|
// Toggle live steam visible
|
|
|
|
|
liveStreamVisible = !liveStreamVisible;
|
|
|
|
|
// If not in coding mode
|
|
|
|
|
if (codingEnabled == false) {
|
2018-08-12 10:37:57 +00:00
|
|
|
|
$('#readOnlyBlocklyCode').toggle();
|
2018-07-08 18:51:59 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 80: // p
|
2018-08-12 10:37:57 +00:00
|
|
|
|
$('#blocklyDiv').toggle();
|
|
|
|
|
$('#blocklyArea').toggle();
|
|
|
|
|
$('#blocklyCode').toggle();
|
|
|
|
|
// When live stream is not active
|
2018-07-08 18:51:59 +00:00
|
|
|
|
if (liveStreamVisible == false) {
|
2018-08-12 10:37:57 +00:00
|
|
|
|
// Toggle Blockly Python code
|
|
|
|
|
$('#readOnlyBlocklyCode').toggle();
|
2018-07-08 18:51:59 +00:00
|
|
|
|
}
|
|
|
|
|
// Toggle coding enabled
|
|
|
|
|
codingEnabled = !codingEnabled;
|
|
|
|
|
if (codingEnabled) {
|
|
|
|
|
// Resize the coding editor
|
|
|
|
|
codingEditor.resize();
|
|
|
|
|
// Focus, so the user can start coding
|
|
|
|
|
codingEditor.focus();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 82: // r
|
|
|
|
|
// Implement something
|
|
|
|
|
break;
|
|
|
|
|
case 83: // s
|
2018-08-12 10:37:57 +00:00
|
|
|
|
$('.btn-stop').addClass('hover');
|
|
|
|
|
$('.btn-stop').click();
|
2018-07-08 18:51:59 +00:00
|
|
|
|
break;
|
|
|
|
|
case 84: // t
|
2018-08-12 10:37:57 +00:00
|
|
|
|
sumorobot.send('calibrate_line');
|
2018-07-08 18:51:59 +00:00
|
|
|
|
break;
|
|
|
|
|
case 87: // w
|
2018-08-12 10:37:57 +00:00
|
|
|
|
$('.btn-start').addClass('hover');
|
|
|
|
|
$('.btn-start').click();
|
2018-07-08 18:51:59 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Key up event
|
|
|
|
|
$(document).keyup(function(e) {
|
|
|
|
|
// When the alt key is not pressed, don't process hotkeys
|
|
|
|
|
if (e.altKey == false) return;
|
|
|
|
|
// Remove hover from buttons
|
|
|
|
|
$('.btn').removeClass('hover');
|
|
|
|
|
// If arrow keys were pressed
|
|
|
|
|
if (e.which == 37 || e.which == 38 || e.which == 39 || e.which == 40) {
|
2018-08-12 10:37:57 +00:00
|
|
|
|
sumorobot.send('stop');
|
2018-07-08 18:51:59 +00:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2018-08-18 17:12:05 +00:00
|
|
|
|
var range_id;
|
2018-08-15 17:58:29 +00:00
|
|
|
|
var lines = [];
|
|
|
|
|
var foundTrue = false;
|
|
|
|
|
// Function to process code and highlight blocks and lines
|
2018-08-15 18:44:52 +00:00
|
|
|
|
function processCode(index) {
|
2018-08-15 17:58:29 +00:00
|
|
|
|
// When all lines are already processed
|
|
|
|
|
if (lines.length == 0) return;
|
|
|
|
|
// Split into code and block ID
|
|
|
|
|
var temp = lines[index].split(';;');
|
|
|
|
|
var code = temp[0];
|
|
|
|
|
// Default timeout for processing the next line
|
|
|
|
|
var timeout = 100;
|
|
|
|
|
var isCondition = /(if|elif|else)/.test(code);
|
|
|
|
|
// When it is a condition line
|
|
|
|
|
if (isCondition) {
|
|
|
|
|
if (foundTrue) {
|
|
|
|
|
// Start processing the code from the beginning again
|
|
|
|
|
index = -1;
|
|
|
|
|
foundTrue = false;
|
|
|
|
|
} else if (/opponent/.test(code)) {
|
|
|
|
|
foundTrue = (sumorobot.sensors['opponent'] < 40.0);
|
|
|
|
|
} else if (/LEFT/.test(code)) {
|
|
|
|
|
foundTrue = (sumorobot.sensors['line_left'] > 2000);
|
|
|
|
|
} else if (/RIGHT/.test(code)) {
|
|
|
|
|
foundTrue = (sumorobot.sensors['line_right'] > 2000);
|
2018-11-02 10:50:15 +00:00
|
|
|
|
} else if (/MIDDLE/.test(code)) {
|
|
|
|
|
foundTrue = (sumorobot.sensors['line_middle'] > 2000);
|
2018-08-15 17:58:29 +00:00
|
|
|
|
} else {
|
|
|
|
|
foundTrue = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Some lines don't correspond to any block
|
2018-08-15 18:44:52 +00:00
|
|
|
|
if (temp[1] && index != -1 && ((!isCondition && foundTrue) || isCondition || !/if/.test(lines[0]))) {
|
2018-08-15 17:58:29 +00:00
|
|
|
|
// When sleep function, we get the timeout value from the function
|
|
|
|
|
if (/\d/.test(code)) {
|
|
|
|
|
timeout = parseInt(code.replace(/[a-z\.()]/g, ''));
|
|
|
|
|
}
|
2018-08-18 17:12:05 +00:00
|
|
|
|
if (range_id) {
|
|
|
|
|
readOnlyCodingEditor.session.removeMarker(range_id);
|
|
|
|
|
}
|
|
|
|
|
var range = new Range(index, 0, index, 1);
|
|
|
|
|
range_id = readOnlyCodingEditor.session.addMarker(range, "highlight", "fullLine");
|
2018-08-15 17:58:29 +00:00
|
|
|
|
// Block ID should always be 20 symbols long
|
|
|
|
|
var blockId = temp[1].substring(0, 20);
|
|
|
|
|
// Highlight the block
|
|
|
|
|
workspace.highlightBlock(blockId);
|
|
|
|
|
}
|
|
|
|
|
// Set an timeout for processing the next line
|
|
|
|
|
index = (index + 1) % lines.length
|
|
|
|
|
setTimeout(function() { processCode(index) }, timeout);
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-08 18:51:59 +00:00
|
|
|
|
// Start button listener
|
2018-08-12 10:37:57 +00:00
|
|
|
|
$('.btn-start').click(function() {
|
|
|
|
|
// When we are in Python coding mode
|
2018-07-08 18:51:59 +00:00
|
|
|
|
if (codingEnabled) {
|
2018-08-12 10:37:57 +00:00
|
|
|
|
// Get the Python code
|
|
|
|
|
parsedCode = codingEditor.getValue();
|
2018-07-08 18:51:59 +00:00
|
|
|
|
// Otherwise when we are in Blockly mode
|
|
|
|
|
} else {
|
2018-08-12 10:37:57 +00:00
|
|
|
|
// Get the code from the blocks
|
2018-08-15 18:18:56 +00:00
|
|
|
|
parsedCode = Blockly.Python.workspaceToCode(workspace).replace(/;;.{20}/g, '');
|
2018-07-08 18:51:59 +00:00
|
|
|
|
}
|
2018-08-12 10:37:57 +00:00
|
|
|
|
// Escape the qoutes, replace new lines and send the code
|
2018-08-17 17:51:10 +00:00
|
|
|
|
sumorobot.send('code', parsedCode.replace(/"/g, '\\"').replace(/\n/g, ';;'));
|
2018-08-15 17:58:29 +00:00
|
|
|
|
// Split into lines of code and filter empty lines
|
2018-08-15 18:18:56 +00:00
|
|
|
|
lines = Blockly.Python.workspaceToCode(workspace).split('\n').filter(Boolean);
|
2018-08-15 17:58:29 +00:00
|
|
|
|
// Process the code starting from the first line
|
|
|
|
|
processCode(0);
|
2018-07-08 18:51:59 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Stop button listener
|
2018-08-12 10:37:57 +00:00
|
|
|
|
$('.btn-stop').click(function() {
|
|
|
|
|
sumorobot.send('stop');
|
2018-08-15 17:58:29 +00:00
|
|
|
|
// Stop highlighting blocks and lines
|
|
|
|
|
lines = [];
|
|
|
|
|
workspace.highlightBlock('');
|
2018-08-18 17:12:05 +00:00
|
|
|
|
if (range_id) {
|
|
|
|
|
readOnlyCodingEditor.session.removeMarker(range_id);
|
|
|
|
|
}
|
2018-07-08 18:51:59 +00:00
|
|
|
|
});
|
|
|
|
|
|
2018-08-12 10:37:57 +00:00
|
|
|
|
// Enter (return) keypress listener on robot ID field
|
|
|
|
|
$('#robot-id').keypress(function(e) {
|
2018-07-08 18:51:59 +00:00
|
|
|
|
if (e.which == 13) {
|
|
|
|
|
// Simulate robot GO button click
|
2018-08-12 10:37:57 +00:00
|
|
|
|
$('.btn-robot-go').click();
|
2018-07-08 18:51:59 +00:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2018-08-12 10:37:57 +00:00
|
|
|
|
// Robot GO button listener
|
|
|
|
|
$('.btn-robot-go').click(function() {
|
2018-08-17 16:34:52 +00:00
|
|
|
|
// Get and validate the selected robot ID
|
2018-09-12 12:14:52 +00:00
|
|
|
|
var robotId = $('#robot-id').val().trim();
|
2018-09-12 12:24:04 +00:00
|
|
|
|
if (robotId === '' || /^([a-zA-Z0-9]{8})$/.test(robotId) == false) {
|
2018-08-12 10:37:57 +00:00
|
|
|
|
$('#robot-id, #robot-label').addClass('has-error');
|
2018-07-08 18:51:59 +00:00
|
|
|
|
return;
|
|
|
|
|
} else {
|
2018-08-12 10:37:57 +00:00
|
|
|
|
$('#robot-id, #robot-label').removeClass('has-error');
|
2018-07-08 18:51:59 +00:00
|
|
|
|
}
|
2018-08-12 10:37:57 +00:00
|
|
|
|
// Update robot ID in local storage
|
|
|
|
|
setLocalStorageItem('sumorobot.robotId', robotId);
|
|
|
|
|
// When a connection was already opened
|
|
|
|
|
if (sumorobot) {
|
|
|
|
|
// Close the connection
|
2018-07-08 18:51:59 +00:00
|
|
|
|
sumorobot.close();
|
|
|
|
|
}
|
|
|
|
|
// Connect to the selected robots WebSocket
|
2018-09-12 20:26:29 +00:00
|
|
|
|
sumorobot = new Sumorobot(`ws://${ROBOT_SERVER}/p2p/browser/sumo-${robotId}/`, robotId);
|
2018-07-08 18:51:59 +00:00
|
|
|
|
// Hide the configuration panel
|
2018-08-12 10:37:57 +00:00
|
|
|
|
$('#panel').hide();
|
2018-07-08 18:51:59 +00:00
|
|
|
|
});
|
|
|
|
|
});
|