Merge remote-tracking branch 'origin/master' into statistics

This commit is contained in:
Maximilian Grundke
2015-10-29 10:24:30 +01:00
17 changed files with 65 additions and 4531 deletions

View File

@@ -30,7 +30,7 @@ $(function() {
numMessages = 0,
turtlecanvas = $('#turtlecanvas'),
prompt = $('#prompt'),
commands = ['input', 'write', 'turtle', 'turtlebatch', 'exit', 'status'],
commands = ['input', 'write', 'turtle', 'turtlebatch', 'exit', 'timeout', 'status'],
streams = ['stdin', 'stdout', 'stderr'];
var ENTER_KEY_CODE = 13;
@@ -686,8 +686,8 @@ $(function() {
};
var isBrowserSupported = function() {
// todo event streams are no longer required with websockets
return window.EventSource !== undefined;
// eventsource tests for server send events (used for scoring), websockets is used for run
return Modernizr.eventsource && Modernizr.websockets;
};
var populatePanel = function(panel, result, index) {
@@ -1004,7 +1004,7 @@ $(function() {
};
var showTimeoutMessage = function() {
$.flash.danger({
$.flash.info({
icon: ['fa', 'fa-clock-o'],
text: $('#editor').data('message-timeout')
});
@@ -1059,14 +1059,6 @@ $(function() {
running = false;
toggleButtonStates();
hidePrompt();
flashKillMessage();
}
var flashKillMessage = function() {
$.flash.info({
icon: ['fa', 'fa-clock-o'],
text: "Your program was stopped." // todo get data attribute
});
}
// todo set this from websocket command, required to e.g. stop container
@@ -1125,7 +1117,7 @@ $(function() {
};
var initWebsocketConnection = function(url) {
websocket = new WebSocket('ws://' + window.location.hostname + ':' + window.location.port + url);
websocket = new WebSocket('wss://' + window.location.hostname + ':' + window.location.port + url);
websocket.onopen = function(evt) { resetOutputTab(); }; // todo show some kind of indicator for established connection
websocket.onclose = function(evt) { /* expected at some point */ };
websocket.onmessage = function(evt) { parseCanvasMessage(evt.data, true); };
@@ -1160,7 +1152,7 @@ $(function() {
}
switch(msg.cmd) {
case 'input':
showPrompt();
showPrompt(msg);
break;
case 'write':
printWebsocketOutput(msg);
@@ -1176,6 +1168,10 @@ $(function() {
case 'exit':
killWebsocketAndContainer();
break;
case 'timeout':
// just show the timeout message here. Another exit command is sent by the rails backend when the socket to the docker container closes.
showTimeoutMessage();
break;
case 'status':
showStatus(msg)
break;
@@ -1249,11 +1245,13 @@ $(function() {
executeWebsocketCommand(msg);
};
var showPrompt = function() {
if (prompt.isPresent() && prompt.hasClass('hidden')) {
var showPrompt = function(msg) {
var label = $('#prompt .input-group-addon');
label.text(msg.data || label.data('prompt'));
if (prompt.isPresent() && prompt.hasClass('hidden')) {
prompt.removeClass('hidden');
}
prompt.focus();
$('#prompt input').focus();
}
var hidePrompt = function() {

View File

@@ -0,0 +1,3 @@
/*! modernizr 3.1.0 (Custom Build) | MIT *
* http://modernizr.com/download/?-eventsource-websockets !*/
!function(e,n,s){function o(e,n){return typeof e===n}function a(e){var n=l.className,s=Modernizr._config.classPrefix||"";if(f&&(n=n.baseVal),Modernizr._config.enableJSClass){var o=new RegExp("(^|\\s)"+s+"no-js(\\s|$)");n=n.replace(o,"$1"+s+"js$2")}Modernizr._config.enableClasses&&(n+=" "+s+e.join(" "+s),f?l.className.baseVal=n:l.className=n)}function t(){var e,n,s,a,t,l,f;for(var r in c){if(e=[],n=c[r],n.name&&(e.push(n.name.toLowerCase()),n.options&&n.options.aliases&&n.options.aliases.length))for(s=0;s<n.options.aliases.length;s++)e.push(n.options.aliases[s].toLowerCase());for(a=o(n.fn,"function")?n.fn():n.fn,t=0;t<e.length;t++)l=e[t],f=l.split("."),1===f.length?Modernizr[f[0]]=a:(!Modernizr[f[0]]||Modernizr[f[0]]instanceof Boolean||(Modernizr[f[0]]=new Boolean(Modernizr[f[0]])),Modernizr[f[0]][f[1]]=a),i.push((a?"":"no-")+f.join("-"))}}var i=[],l=n.documentElement,f="svg"===l.nodeName.toLowerCase(),c=[],r={_version:"3.1.0",_config:{classPrefix:"",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,n){var s=this;setTimeout(function(){n(s[e])},0)},addTest:function(e,n,s){c.push({name:e,fn:n,options:s})},addAsyncTest:function(e){c.push({name:null,fn:e})}},Modernizr=function(){};Modernizr.prototype=r,Modernizr=new Modernizr,Modernizr.addTest("websockets","WebSocket"in e&&2===e.WebSocket.CLOSING),Modernizr.addTest("eventsource","EventSource"in e),t(),a(i),delete r.addTest,delete r.addAsyncTest;for(var u=0;u<Modernizr._q.length;u++)Modernizr._q[u]();e.Modernizr=Modernizr}(window,document);

View File

@@ -90,6 +90,12 @@ class SubmissionsController < ApplicationController
hijack do |tubesock|
Thread.new { EventMachine.run } unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive?
# socket is the socket into the container, tubesock is the socket to the client
# give the docker_client the tubesock object, so that it can send messages (timeout)
@docker_client.tubesock = tubesock
result = @docker_client.execute_run_command(@submission, params[:filename])
tubesock.send_data JSON.dump({'cmd' => 'status', 'status' => result[:status]})

View File

@@ -3,6 +3,6 @@ class Comment < ActiveRecord::Base
include Creation
attr_accessor :username
belongs_to :file, class: CodeOcean::File
belongs_to :file, class_name: 'CodeOcean::File'
belongs_to :user, polymorphic: true
end

View File

@@ -2,7 +2,7 @@ module Context
extend ActiveSupport::Concern
included do
has_many :files, as: :context, class: CodeOcean::File
has_many :files, as: :context, class_name: 'CodeOcean::File'
accepts_nested_attributes_for :files
end

View File

@@ -1,6 +1,6 @@
class RequestForComment < ActiveRecord::Base
belongs_to :exercise
belongs_to :file, class: CodeOcean::File
belongs_to :file, class_name: 'CodeOcean::File'
belongs_to :user, polymorphic: true
before_create :set_requested_timestamp

View File

@@ -39,7 +39,7 @@
#output-col1
// todo set to full width if turtle isnt used
#prompt.input-group.hidden
span.input-group-addon = t('exercises.editor.input')
span.input-group-addon data-prompt=t('exercises.editor.input') = t('exercises.editor.input')
input#prompt-input.form-control type='text'
span.input-group-btn
button#prompt-submit.btn.btn-primary type="button" = t('exercises.editor.send')