CodeOceanEditorEvaluation = { chunkBuffer: [{streamedResponse: true}], evaluateCode: function (url, onmessageFunction) { this.initWebsocketConnection(url, onmessageFunction);; }, handleScoringResponse: function (websocket_event) { var results = JSON.parse(websocket_event.data); this.printScoringResults(results); var score = _.reduce(results, function (sum, result) { return sum + result.score * result.weight; }, 0).toFixed(2); $('#score').data('score', score); this.renderScore(); this.showTab(2); }, handleTestResponse: function (websocket_event) { var result = JSON.parse(websocket_event.data); this.clearOutput(); this.printOutput(result, false, 0); if (this.qa_api) { this.qa_api.executeCommand('syncOutput', [result]); } this.showStatus(result); this.showTab(1); }, printOutput: function (output, colorize, index) { var element = this.findOrCreateOutputElement(index); if (!colorize) { if (output.stdout != undefined && output.stdout != '') { element.append(output.stdout) } if (output.stderr != undefined && output.stderr != '') { element.append('There was an error: StdErr: ' + output.stderr); } } else if (output.stderr) { element.addClass('text-warning').append(output.stderr); this.flowrOutputBuffer += output.stderr; this.QaApiOutputBuffer.stderr += output.stderr; } else if (output.stdout) { element.addClass('text-success').append(output.stdout); this.flowrOutputBuffer += output.stdout; this.QaApiOutputBuffer.stdout += output.stdout; } else { element.addClass('text-muted').text($('#output').data('message-no-output')); } }, printScoringResult: function (result, index) { $('#results').show(); var panel = $('#dummies').children().first().clone(); this.populatePanel(panel, result, index); $('#results ul').first().append(panel); }, printScoringResults: function (response) { $('#results ul').first().html(''); $('.test-count .number').html(response.length); this.clearOutput(); _.each(response, function (result, index) { this.printOutput(result, false, index); this.printScoringResult(result, index); }.bind(this)); if (_.some(response, function (result) { return result.status === 'timeout'; })) { this.showTimeoutMessage(); } if (_.some(response, function (result) { return result.status === 'container_depleted'; })) { this.showContainerDepletedMessage(); } if (this.qa_api) { // send test response to QA this.qa_api.executeCommand('syncOutput', [response]); } }, renderHint: function (object) { var hint = object.data || object.hint; if (hint) { $('#hint .panel-body').text(hint); $('#hint').fadeIn(); } }, renderScore: function () { var score = parseFloat($('#score').data('score')); var maximum_score = parseFloat($('#score').data('maximum-score')); if (score >= 0 && score <= maximum_score && maximum_score > 0) { var percentage_score = (score / maximum_score * 100 ).toFixed(0); $('.score').html(percentage_score + '%'); } else { $('.score').html(0 + '%'); } this.renderProgressBar(score, maximum_score); }, scoreCode: function (event) { event.preventDefault(); this.runmode = this.SERVER_SEND_EVENT; this.createSubmission('#assess', null, function (response) { this.showSpinner($('#assess')); var url = response.score_url; this.evaluateCode(url, this.handleScoringResponse.bind(this)); }.bind(this)); }, stopCode: function (event) { event.preventDefault(); if (this.isActiveFileStoppable()) { if (this.runmode == this.WEBSOCKET) { this.killWebsocketAndContainer(); } else if (this.runmode == this.SERVER_SEND_EVENT) { this.stopCodeServerSendEvent(event); } this.runmode = this.NONE; } }, stopCodeServerSendEvent: function (event) { var jqxhr = this.ajax({ data: { container_id: $('#stop').data('container').id }, url: $('#stop').data('url') }); jqxhr.always(function () { this.hideSpinner(); this.running = false; this.toggleButtonStates(); }); jqxhr.fail(ajaxError); }, killWebsocketAndContainer: function () { if (this.websocket.readyState != WebSocket.OPEN) { return; } this.websocket.send(JSON.stringify({cmd: 'exit'})); this.websocket.flush(); this.websocket.close(); this.hideSpinner(); this.running = false; this.toggleButtonStates(); this.hidePrompt(); }, //TODO: Move Prompt Part in own component showPrompt: function(msg) { var label = $('#prompt .input-group-addon'); label.text(msg.data || label.data('prompt')); if (this.prompt.isPresent() && this.prompt.hasClass('hidden')) { this.prompt.removeClass('hidden'); } $('#prompt input').focus(); }, hidePrompt: function() { if (this.prompt.isPresent() && !this.prompt.hasClass('hidden')) { this.prompt.addClass('hidden'); } }, initPrompt: function() { if ($('#run').isPresent()) { $('#run').bind('click', this.hidePrompt.bind(this)); } if ($('#prompt').isPresent()) { $('#prompt').on('keypress', this.handlePromptKeyPress.bind(this)); $('#prompt-submit').on('click', this.submitPromptInput.bind(this)); } }, submitPromptInput: function() { var input = $('#prompt-input'); var message = input.val(); this.websocket.send(JSON.stringify({cmd: 'result', 'data': message})); this.websocket.flush(); input.val(''); this.hidePrompt(); }, handlePromptKeyPress: function(evt) { if (evt.which === this.ENTER_KEY_CODE) { this.submitPromptInput(); } }, renderWebsocketOutput: function(msg){ var element = this.findOrCreateRenderElement(0); element.append(msg.data); }, printWebsocketOutput: function(msg) { if (!msg.data) { return; } msg.data = msg.data.replace(/(\r)/gm, "\n"); var stream = {}; stream[msg.stream] = msg.data; this.printOutput(stream, true, 0); }, clearOutput: function() { $('#output pre').remove(); } };