sumorobot-web/assets/js/main.js

262 lines
9.3 KiB
JavaScript
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// The local/remote server URL
//var ROBOT_SERVER = '192.168.2.1:80';
//var ROBOT_SERVER = '165.227.140.64:80';
var ROBOT_SERVER = 'sumo.koodur.com:80';
//var ROBOT_SERVER = '192.168.1.1:80';
//var ROBOT_SERVER = '192.168.1.1:80';
// The sumorobot object
var sumorobot;
// Disable / enable coding mode
var codingEnabled = false;
// Disable / enable live stream
var liveStreamVisible = false;
window.addEventListener('load', function() {
// Set the robot ID from the localstorage
$('#robot-id').val(getLocalStorageItem('sumorobot.robotId'));
// 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
if (sumorobot.moving) {
$('.btn-stop').addClass('hover');
$('.btn-stop').click();
} else {
$('.btn-start').addClass('hover');
$('.btn-start').click();
}
break;
case 37: // left
sumorobot.send('left');
break;
case 38: // up
sumorobot.send('forward');
break;
case 39: // right
sumorobot.send('right');
break;
case 40: // down
sumorobot.send('backward');
break;
case 67: // c
$('#panel').toggle();
break;
case 76: // l
// No live stream if cookies are disabled
if (!cookiesEnabled) {
// TODO: Open the cookie consent popup
return;
}
// 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>');
}
$('#stream').toggle();
// Toggle live steam visible
liveStreamVisible = !liveStreamVisible;
// If not in coding mode
if (codingEnabled == false) {
$('#readOnlyBlocklyCode').toggle();
}
break;
case 80: // p
$('#blocklyDiv').toggle();
$('#blocklyArea').toggle();
$('#blocklyCode').toggle();
// When live stream is not active
if (liveStreamVisible == false) {
// Toggle Blockly Python code
$('#readOnlyBlocklyCode').toggle();
}
// 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
$('.btn-stop').addClass('hover');
$('.btn-stop').click();
break;
case 84: // t
sumorobot.send('calibrate_line');
break;
case 87: // w
$('.btn-start').addClass('hover');
$('.btn-start').click();
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) {
sumorobot.send('stop');
}
});
function stopProcessCode() {
// Stop highlighting blocks and lines
lines = [];
workspace.highlightBlock('');
if (range_id) {
readOnlyCodingEditor.session.removeMarker(range_id);
}
}
var range_id;
var lines = [];
var foundTrue = false;
// Function to process code and highlight blocks and lines
function processCode(index) {
if(sumorobot.disconnected || !sumorobot.codeExecute) {
//$('.btn-stop').click();
stopProcessCode();
return;
}
// 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'] < 2500);
} else if (/RIGHT/.test(code)) {
foundTrue = (sumorobot.sensors['line_right'] < 2500);
} else if (/MIDDLE/.test(code)) {
foundTrue = (sumorobot.sensors['line_middle'] < 2500);
} else {
foundTrue = true;
}
}
// Some lines don't correspond to any block
if (temp[1] && index != -1 && ((!isCondition && foundTrue) || isCondition || !/if/.test(lines[0]))) {
// When sleep function, we get the timeout value from the function
if (/\d/.test(code)) {
timeout = parseInt(code.replace(/[a-z\.()]/g, ''));
}
if (range_id) {
readOnlyCodingEditor.session.removeMarker(range_id);
}
var range = new Range(index, 0, index, 1);
range_id = readOnlyCodingEditor.session.addMarker(range, "highlight", "fullLine");
// 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);
}
$('.btn-upload').click(function() {
if(codingEnabled) {
parsedCode = codingEditor.getValue();
} else {
parsedCode = Blockly.Python.workspaceToCode(workspace).replace(/;;.{20}/g, '');
}
sumorobot.send('code', parsedCode.replace(/"/g, '\\"').replace(/\n/g, ';;'));
lines = Blockly.Python.workspaceToCode(workspace).split('\n').filter(Boolean);
});
// Start button listener
$('.btn-start').click(function() {
// When we are in Python coding mode
if (codingEnabled) {
// Get the Python code
parsedCode = codingEditor.getValue();
// Otherwise when we are in Blockly mode
} else {
// Get the code from the blocks
parsedCode = Blockly.Python.workspaceToCode(workspace).replace(/;;.{20}/g, '');
}
// Escape the qoutes, replace new lines and send the code
sumorobot.send('start', parsedCode.replace(/"/g, '\\"').replace(/\n/g, ';;'));
// Split into lines of code and filter empty lines
lines = Blockly.Python.workspaceToCode(workspace).split('\n').filter(Boolean);
// Process the code starting from the first line
//processCode(0);
});
// Stop button listener
$('.btn-stop').click(function() {
sumorobot.send('stop');
stopProcessCode();
});
// Enter (return) keypress listener on robot ID field
$('#robot-id').keypress(function(e) {
if (e.which == 13) {
// Simulate robot GO button click
$('.btn-robot-go').click();
}
});
// Robot GO button listener
$('.btn-robot-go').click(function() {
// Get and validate the selected robot ID
var robotId = $('#robot-id').val().trim().toLowerCase().split("-").reverse()[0];
if (robotId === '' || /^([a-zA-Z0-9]{6})$/.test(robotId) == false) {
$('#robot-id, #robot-label').addClass('has-error');
return;
} else {
$('#robot-id, #robot-label').removeClass('has-error');
}
// Update robot ID in local storage
setLocalStorageItem('sumorobot.robotId', robotId);
// When a connection was already opened
if (sumorobot) {
// Close the connection
sumorobot.close();
}
// Connect to the selected robots WebSocket
sumorobot = new Sumorobot(`ws://${ROBOT_SERVER}/p2p/browser/sumo-${robotId}/`, robotId);
$(sumorobot).on('start',function(){
//console.log("START");
lines = Blockly.Python.workspaceToCode(workspace).split('\n').filter(Boolean);
processCode(0);
});
// Hide the configuration panel
$('#panel').hide();
});
});