<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: server.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: server.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>/** * Object for communicating with the external servers. This includes functionality for * saving and loading files, logging events, saving completions, and retrieving history. * * @constructor * @this {BlockPyServer} * @param {Object} main - The main BlockPy instance */ function BlockPyServer(main) { this.main = main; // Add the LocalStorage connection // Presently deprecated, but we should investigate this this.storage = new LocalStorageWrapper("BLOCKPY"); this.saveTimer = {}; this.presentationTimer = null; // For managing "walks" that let us rerun stored code this.inProgressWalks = []; this.createSubscriptions(); } BlockPyServer.prototype.createSubscriptions = function() { var server = this, model = this.main.model; model.program.subscribe(function() { server.saveCode(); }); model.assignment.name.subscribe(function(e) { server.saveAssignment();}); model.assignment.introduction.subscribe(function(e) { server.saveAssignment(); }); model.assignment.parsons.subscribe(function(e) { server.saveAssignment(); }); model.assignment.importable.subscribe(function(e) { server.saveAssignment(); }); model.assignment.disable_algorithm_errors.subscribe(function(e) { server.saveAssignment(); }); model.assignment.initial_view.subscribe(function(e) { server.saveAssignment(); }); model.settings.editor.subscribe(function(newValue) { server.logEvent('editor', newValue); }); model.execution.show_trace.subscribe(function(newValue) { server.logEvent('trace', newValue); }); model.execution.trace_step.subscribe(function(newValue) { server.logEvent('trace_step', newValue); }); }; /** * * Some subscriptions have to happen after other things have been loaded. * Right now this is just after CORGIS libraries have been loaded, but maybe * we'll add more later and this will need to be refactored. * */ BlockPyServer.prototype.finalizeSubscriptions = function() { var server = this, model = this.main.model; model.assignment.modules.subscribe(function(e) { server.saveAssignment(); }); }; BlockPyServer.prototype.TIMER_DELAY = 1000; BlockPyServer.prototype.createServerData = function() { var assignment = this.main.model.assignment; var d = new Date(); var seconds = Math.round(d.getTime() / 1000); data = { 'assignment_id': assignment.assignment_id, 'course_id': assignment.course_id, 'student_id': assignment.student_id, 'version': assignment.version(), 'timestamp': seconds }; if (this.main.model.settings.log_id() != null) { data['log_id'] = this.main.model.settings.log_id(); } return data; } BlockPyServer.prototype.setStatus = function(status, server_error) { this.main.model.status.server(status); if (server_error !== undefined) { this.main.model.status.server_error(server_error); } else { this.main.model.status.server_error(''); } } BlockPyServer.prototype.defaultResponseWithoutVersioning = function(response) { if (response.success) { this.setStatus('Saved'); } else { console.error(response); this.setStatus('Error', response.message); } } BlockPyServer.prototype.defaultResponse = function(response) { /*console.log(response); if (!response.is_version_correct) { this.setStatus('Out of date'); } else */if (response.success) { this.setStatus('Saved'); } else { console.error(response); this.setStatus('Error', response.message); } } BlockPyServer.prototype.defaultFailure = function(error, textStatus) { this.setStatus('Disconnected', "Could not access server!\n"+textStatus); } BlockPyServer.prototype.logEvent = function(event_name, action, body) { var data = this.createServerData(); data['event'] = event_name; data['action'] = action; if (body === undefined) { data['body'] = ''; } else { data['body'] = body; } this.setStatus('Logging'); if (this.main.model.server_is_connected('log_event')) { $.post(this.main.model.constants.urls.log_event, data, this.defaultResponse.bind(this)) .fail(this.defaultFailure.bind(this)); } else { this.setStatus('Offline', "Server is not connected!"); } } BlockPyServer.prototype.markSuccess = function(success) { var data = this.createServerData(); var server = this, model = this.main.model; data['code'] = model.programs.__main__; data['status'] = success; this.main.components.editor.getPngFromBlocks(function(pngData, img) { data['image'] = pngData; img.remove(); server.setStatus('Saving'); if (model.server_is_connected('save_success')) { $.post(model.constants.urls.save_success, data, server.defaultResponse.bind(server)) .fail(server.defaultFailure.bind(server)); } else { server.setStatus('Offline', "Server is not connected!"); } }); }; BlockPyServer.prototype.saveAssignment = function() { var data = this.createServerData(); var model = this.main.model; data['introduction'] = model.assignment.introduction(); data['parsons'] = model.assignment.parsons(); data['initial'] = model.assignment.initial_view(); data['importable'] = model.assignment.importable(); data['disable_algorithm_errors'] = model.assignment.disable_algorithm_errors(); data['name'] = model.assignment.name(); //data['disabled'] = disabled; data['modules'] = model.assignment.modules().join(','); // TODO: hackish, broken if ',' is in name var server = this; this.setStatus('Saving'); if (this.main.model.server_is_connected('save_assignment') && this.main.model.settings.auto_upload()) { clearTimeout(this.presentationTimer); this.presentationTimer = setTimeout(function() { $.post(server.main.model.constants.urls.save_assignment, data, server.defaultResponseWithoutVersioning.bind(server)) .fail(server.defaultFailure.bind(server)); }, this.TIMER_DELAY); } else { this.setStatus('Offline', "Server is not connected!"); } } BlockPyServer.prototype.saveCode = function() { var filename = this.main.model.settings.filename(); var data = this.createServerData(); data['filename'] = filename; data['code'] = this.main.model.programs[filename](); var server = this; this.setStatus('Saving'); if (this.main.model.server_is_connected('save_code') && this.main.model.settings.auto_upload()) { if (this.saveTimer[filename]) { clearTimeout(this.saveTimer[filename]); } this.saveTimer[filename] = setTimeout(function() { $.post(server.main.model.constants.urls.save_code, data, filename == '__main__' ? server.defaultResponse.bind(server) : server.defaultResponseWithoutVersioning.bind(server)) .fail(server.defaultFailure.bind(server)); }, this.TIMER_DELAY); } else { this.setStatus('Offline', "Server is not connected!"); } } BlockPyServer.prototype.getHistory = function(callback) { var data = this.createServerData(); var model = this.main.model; var server = this; this.setStatus('Loading History'); if (model.server_is_connected('get_history')) { $.post(model.constants.urls.get_history, data, function(response) { if (response.success) { server.setStatus('Saved'); callback(response.data); } else { console.error(response); server.setStatus('Error', response.message); } }) .fail(server.defaultFailure.bind(server)); } else { this.setStatus('Offline', "Server is not connected!"); callback([]); /*callback([ {code: "=", time: "20160801-105102"}, {code: "= 0", time: "20160801-105112"}, {code: "a = 0", time: "20160801-105502"}, {code: "a = 0\nprint", time: "20160801-110003"}, {code: "a = 0\nprint(a)", time: "20160801-111102"} ])*/ } } BlockPyServer.prototype.walkOldCode = function() { var server = this, main = this.main; if (this.inProgressWalks.length > 0) { var response = this.inProgressWalks.pop(); console.log('Processing walk', response.log_id); main.setCode(response.code, '__main__'); main.setCode(response.feedback, 'give_feedback'); main.model.assignment.assignment_id = response.assignment_id; main.model.assignment.user_id = response.user_id; main.model.settings.log_id(response.log_id); main.components.engine.onExecutionEnd = function(newState) { console.log(response.log_id, newState); main.components.engine.onExecutionEnd = null; setTimeout(function() { server.walkOldCode() }, 0); }; console.log("Running"); main.components.engine.run(); } else { var data = this.createServerData(); this.setStatus('Retrieving'); if (main.model.server_is_connected('walk_old_code')) { $.post(server.main.model.constants.urls.walk_old_code, data, function (response) { if (response.success) { if (response.more_to_do) { server.inProgressWalks = response.walks; server.walkOldCode(); } } else { this.setStatus('Failure', response.message); } }) .fail( function(response) { console.error(response); setTimeout(function() { server.walkOldCode() }, 3000); } ); //server.defaultFailure.bind(server)); } else { this.setStatus('Offline', "Server is not connected!"); } } } /* BlockPyServer.prototype.load = function() { var data = { 'question_id': this.model.question.question_id, 'student_id': this.model.question.student_id, 'context_id': this.model.question.context_id }; var alertBox = this.alertBox; var server = this, blockpy = this.blockpy; if (this.model.urls.server !== false && this.model.urls.load_code !== false) { $.post(this.model.urls.load_code, data, function(response) { if (response.success) { if (server.storage.has(data.question_id)) { if (server.storage.is_new(data.question_id, response.timestamp)) { var xml = server.storage.get(data.question_id); server.model.load(xml); server.save(); } else { server.storage.remove(data.question_id); if (response.code !== null) { server.model.load(response.code); } } } else { if (response.code !== null) { server.model.load(response.code); } } if (response.completed) { blockpy.feedback.success(''); } alertBox("Loaded").delay(200).fadeOut("slow"); } else { console.error("Server Load Error", response.message); alertBox("Loading failed"); } }).fail(function() { alertBox("Loading failed"); }).always(function() { server.model.loaded = true; }); } else { server.model.loaded = true; alertBox("Loaded").delay(200).fadeOut("slow"); if (this.model.urls.load_success === true) { this.blockpy.feedback.success(''); } } }; */</code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="BlockPy.html">BlockPy</a></li><li><a href="BlockPyCorgis.html">BlockPyCorgis</a></li><li><a href="BlockPyDialog.html">BlockPyDialog</a></li><li><a href="BlockPyEditor.html">BlockPyEditor</a></li><li><a href="BlockPyEngine.html">BlockPyEngine</a></li><li><a href="BlockPyEnglish.html">BlockPyEnglish</a></li><li><a href="BlockPyFeedback.html">BlockPyFeedback</a></li><li><a href="BlockPyHistory.html">BlockPyHistory</a></li><li><a href="BlockPyPresentation.html">BlockPyPresentation</a></li><li><a href="BlockPyPrinter.html">BlockPyPrinter</a></li><li><a href="BlockPyServer.html">BlockPyServer</a></li><li><a href="BlockPyToolbar.html">BlockPyToolbar</a></li><li><a href="LocalStorageWrapper.html">LocalStorageWrapper</a></li><li><a href="PythonToBlocks.html">PythonToBlocks</a></li></ul><h3>Global</h3><ul><li><a href="global.html#BlockPyInterface">BlockPyInterface</a></li><li><a href="global.html#cloneNode">cloneNode</a></li><li><a href="global.html#encodeHTML">encodeHTML</a></li><li><a href="global.html#expandArray">expandArray</a></li><li><a href="global.html#EXTENDED_ERROR_EXPLANATION">EXTENDED_ERROR_EXPLANATION</a></li><li><a href="global.html#indent">indent</a></li><li><a href="global.html#instructor_module">instructor_module</a></li><li><a href="global.html#prettyPrintDateTime">prettyPrintDateTime</a></li><li><a href="global.html#randomInteger">randomInteger</a></li><li><a href="global.html#set_button_loaded">set_button_loaded</a></li><li><a href="global.html#timerGuard">timerGuard</a></li></ul> </nav> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Sun Mar 26 2017 09:45:03 GMT-0400 (Eastern Daylight Time) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>