Merge branch 'master' into feature-file-templates
Conflicts: app/views/application/_navigation.html.slim config/locales/de.yml config/locales/en.yml db/schema.rb
This commit is contained in:
@@ -19,6 +19,10 @@ $(function() {
|
||||
var SERVER_SEND_EVENT = 2;
|
||||
|
||||
var editors = [];
|
||||
var editor_for_file = new Map();
|
||||
var regex_for_language = new Map();
|
||||
var tracepositions_regex;
|
||||
|
||||
var active_file = undefined;
|
||||
var active_frame = undefined;
|
||||
var running = false;
|
||||
@@ -175,7 +179,10 @@ $(function() {
|
||||
var downloadCode = function(event) {
|
||||
event.preventDefault();
|
||||
createSubmission(this, null,function(response) {
|
||||
var url = response.download_url.replace(FILENAME_URL_PLACEHOLDER, active_file.filename);
|
||||
var url = response.download_url;
|
||||
|
||||
// to download just a single file, use the following url
|
||||
//var url = response.download_file_url.replace(FILENAME_URL_PLACEHOLDER, active_file.filename);
|
||||
window.location = url;
|
||||
});
|
||||
};
|
||||
@@ -404,12 +411,18 @@ $(function() {
|
||||
editor.setTheme(THEME);
|
||||
editor.commands.bindKey("ctrl+alt+0", null);
|
||||
editors.push(editor);
|
||||
editor_for_file.set($(element).parent().data('filename'), editor);
|
||||
var session = editor.getSession();
|
||||
session.setMode($(element).data('mode'));
|
||||
session.setTabSize($(element).data('indent-size'));
|
||||
session.setUseSoftTabs(true);
|
||||
session.setUseWrapMode(true);
|
||||
|
||||
// set regex for parsing error traces based on the mode of the main file.
|
||||
if( $(element).parent().data('role') == "main_file"){
|
||||
tracepositions_regex = regex_for_language.get($(element).data('mode'));
|
||||
}
|
||||
|
||||
var file_id = $(element).data('id');
|
||||
|
||||
/*
|
||||
@@ -457,6 +470,12 @@ $(function() {
|
||||
$('#request-for-comments').on('click', requestComments);
|
||||
};
|
||||
|
||||
|
||||
var initializeRegexes = function(){
|
||||
regex_for_language.set("ace/mode/python", /File "(.+?)", line (\d+)/g);
|
||||
regex_for_language.set("ace/mode/java", /(.*\.java):(\d+):/g);
|
||||
}
|
||||
|
||||
var initializeTooltips = function() {
|
||||
$('[data-tooltip]').tooltip();
|
||||
};
|
||||
@@ -587,7 +606,7 @@ $(function() {
|
||||
} else if (output.stdout) {
|
||||
//if (output_mode_is_streaming){
|
||||
element.addClass('text-success').append(output.stdout);
|
||||
flowrOutputBuffer += output.stdout;
|
||||
// flowrOutputBuffer += output.stdout;
|
||||
//}else{
|
||||
// element.addClass('text-success');
|
||||
// element.data('content_buffer' , element.data('content_buffer') + output.stdout);
|
||||
@@ -704,9 +723,15 @@ $(function() {
|
||||
};
|
||||
|
||||
var renderScore = function() {
|
||||
var score = $('#score').data('score');
|
||||
var maxium_score = $('#score').data('maximum-score');
|
||||
$('.score').html((score || '?') + ' / ' + maxium_score);
|
||||
var score = parseFloat($('#score').data('score'));
|
||||
var maxium_score = parseFloat($('#score').data('maximum-score'));
|
||||
if (score >= 0 && score <= maxium_score && maxium_score >0 ) {
|
||||
var percentage_score = (score / maxium_score * 100 ).toFixed(0);
|
||||
$('.score').html(percentage_score + '%');
|
||||
}
|
||||
else {
|
||||
$('.score').html( 0 + '%');
|
||||
}
|
||||
renderProgressBar(score, maxium_score);
|
||||
};
|
||||
|
||||
@@ -870,7 +895,9 @@ $(function() {
|
||||
}
|
||||
|
||||
var showWorkspaceTab = function(event) {
|
||||
event.preventDefault();
|
||||
if(event){
|
||||
event.preventDefault();
|
||||
}
|
||||
showTab(0);
|
||||
};
|
||||
|
||||
@@ -1030,6 +1057,7 @@ $(function() {
|
||||
case 'exit':
|
||||
killWebsocketAndContainer();
|
||||
handleStderrOutputForFlowr();
|
||||
augmentStacktraceInOutput();
|
||||
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.
|
||||
@@ -1041,6 +1069,41 @@ $(function() {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var jumpToSourceLine = function(event){
|
||||
var file = $(event.target).data('file');
|
||||
var line = $(event.target).data('line');
|
||||
|
||||
showWorkspaceTab(null);
|
||||
// set active file ?!?!
|
||||
|
||||
var frame = $('div.frame[data-filename="' + file + '"]');
|
||||
showFrame(frame);
|
||||
|
||||
var editor = editor_for_file.get(file);
|
||||
editor.gotoLine(line, 0);
|
||||
|
||||
};
|
||||
|
||||
var augmentStacktraceInOutput = function() {
|
||||
if(tracepositions_regex){
|
||||
var element = $('#output>pre');
|
||||
var text = element.text();
|
||||
element.on( "click", "a", jumpToSourceLine);
|
||||
|
||||
var matches;
|
||||
|
||||
while(matches = tracepositions_regex.exec(text)){
|
||||
var frame = $('div.frame[data-filename="' + matches[1] + '"]')
|
||||
|
||||
if(frame.length > 0){
|
||||
element.html(text.replace(matches[0], "<a href='#' data-file='" + matches[1] + "' data-line='" + matches[2] + "'>" + matches[0] + "</a>"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var renderWebsocketOutput = function(msg){
|
||||
var element = findOrCreateRenderElement(0);
|
||||
element.append(msg.data);
|
||||
@@ -1154,25 +1217,25 @@ $(function() {
|
||||
var file_id = $('.editor').data('id')
|
||||
var question = $('#question').val();
|
||||
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: '/request_for_comments',
|
||||
data: {
|
||||
request_for_comment: {
|
||||
exercise_id: exercise_id,
|
||||
file_id: file_id,
|
||||
question: question,
|
||||
"requested_at(1i)": 2015, // these are the timestamp values that the request handler demands
|
||||
"requested_at(2i)":3, // they could be random here, because the timestamp is updated on serverside anyway
|
||||
"requested_at(3i)":27,
|
||||
"requested_at(4i)":17,
|
||||
"requested_at(5i)":06
|
||||
var createRequestForComments = function(submission) {
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: '/request_for_comments',
|
||||
data: {
|
||||
request_for_comment: {
|
||||
exercise_id: exercise_id,
|
||||
file_id: file_id,
|
||||
submission_id: submission.id,
|
||||
question: question
|
||||
}
|
||||
}
|
||||
}
|
||||
}).done(function() {
|
||||
hideSpinner();
|
||||
$.flash.success({ text: $('#askForCommentsButton').data('message-success') })
|
||||
}).error(ajaxError);
|
||||
}).done(function() {
|
||||
hideSpinner();
|
||||
$.flash.success({ text: $('#askForCommentsButton').data('message-success') });
|
||||
}).error(ajaxError);
|
||||
}
|
||||
|
||||
createSubmission($('.requestCommentsButton'), null, createRequestForComments);
|
||||
|
||||
$('#comment-modal').modal('hide');
|
||||
var button = $('.requestCommentsButton');
|
||||
@@ -1201,6 +1264,7 @@ $(function() {
|
||||
|
||||
if ($('#editor').isPresent()) {
|
||||
if (isBrowserSupported()) {
|
||||
initializeRegexes();
|
||||
initializeCodePilot();
|
||||
$('.score, #development-environment').show();
|
||||
configureEditors();
|
||||
|
@@ -9,6 +9,9 @@ $(function() {
|
||||
|
||||
submissionsScoreAndTimeAssess = [[0,0]];
|
||||
submissionsScoreAndTimeSubmits = [[0,0]];
|
||||
submissionsScoreAndTimeRuns = [];
|
||||
submissionsSaves = [];
|
||||
submissionsAutosaves = [];
|
||||
var maximumValue = 0;
|
||||
|
||||
var wtimes = $('#wtimes').data('working_times'); //.hidden#wtimes data-working_times=ActiveSupport::JSON.encode(working_times_until)
|
||||
@@ -18,43 +21,42 @@ $(function() {
|
||||
|
||||
for (var i = 0;i<submissions_length;i++){
|
||||
var submission = submissions[i];
|
||||
var workingTime;
|
||||
var submissionArray;
|
||||
|
||||
workingTime = get_minutes(wtimes[i]);
|
||||
submissionArray = [submission.score, 0];
|
||||
|
||||
if (workingTime > 0) {
|
||||
submissionArray[1] = workingTime;
|
||||
}
|
||||
if(submission.score>maximumValue){
|
||||
maximumValue = submission.score;
|
||||
}
|
||||
|
||||
if(submission.cause == "assess"){
|
||||
var workingTime = get_minutes(wtimes[i]);
|
||||
var submissionArray = [submission.score, 0];
|
||||
|
||||
if (workingTime > 0) {
|
||||
submissionArray[1] = workingTime;
|
||||
}
|
||||
|
||||
if(submission.score>maximumValue){
|
||||
maximumValue = submission.score;
|
||||
}
|
||||
submissionsScoreAndTimeAssess.push(submissionArray);
|
||||
} else if(submission.cause == "submit"){
|
||||
var workingTime = get_minutes(wtimes[i]);
|
||||
var submissionArray = [submission.score, 0];
|
||||
|
||||
if (workingTime > 0) {
|
||||
submissionArray[1] = workingTime;
|
||||
}
|
||||
|
||||
if(submission.score>maximumValue){
|
||||
maximumValue = submission.score;
|
||||
}
|
||||
submissionsScoreAndTimeSubmits.push(submissionArray);
|
||||
} else if(submission.cause == "run"){
|
||||
submissionsScoreAndTimeRuns.push(submissionArray[1]);
|
||||
} else if(submission.cause == "autosave"){
|
||||
submissionsAutosaves.push(submissionArray[1]);
|
||||
} else if(submission.cause == "save"){
|
||||
submissionsSaves.push(submissionArray[1]);
|
||||
}
|
||||
}
|
||||
// console.log(submissionsScoreAndTimeAssess.length);
|
||||
// console.log(submissionsScoreAndTimeSubmits);
|
||||
// console.log(submissionsScoreAndTimeRuns);
|
||||
|
||||
function get_minutes (time_stamp) {
|
||||
try {
|
||||
hours = time_stamp.split(":")[0];
|
||||
minutes = time_stamp.split(":")[1];
|
||||
seconds = time_stamp.split(":")[2];
|
||||
|
||||
minutes = parseFloat(hours * 60) + parseInt(minutes);
|
||||
seconds /= 60;
|
||||
minutes = parseFloat(hours * 60) + parseInt(minutes) + seconds;
|
||||
if (minutes > 0){
|
||||
return minutes;
|
||||
} else{
|
||||
@@ -82,6 +84,9 @@ $(function() {
|
||||
function graph_assesses() {
|
||||
// MAKE THE GRAPH
|
||||
var width_ratio = .8;
|
||||
if (getWidth()*width_ratio > 1000){
|
||||
width_ratio = 1000/getWidth();
|
||||
}
|
||||
var height_ratio = .7; // percent of height
|
||||
|
||||
var margin = {top: 100, right: 20, bottom: 70, left: 70},//30,50
|
||||
@@ -131,15 +136,32 @@ $(function() {
|
||||
.append("g")
|
||||
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
||||
|
||||
var largestSubmittedTimeStamp = submissions[submissions_length-1];
|
||||
var largestArrayForRange;
|
||||
|
||||
x.domain(d3.extent(submissionsScoreAndTimeAssess, function (d) {
|
||||
// console.log(d[1]);
|
||||
return (d[1]);
|
||||
}));
|
||||
y.domain(d3.extent(submissionsScoreAndTimeAssess, function (d) {
|
||||
if(largestSubmittedTimeStamp.cause == "assess"){
|
||||
largestArrayForRange = submissionsScoreAndTimeAssess;
|
||||
x.domain([0,largestArrayForRange[largestArrayForRange.length - 1][1]]).clamp(true);
|
||||
} else if(largestSubmittedTimeStamp.cause == "submit"){
|
||||
largestArrayForRange = submissionsScoreAndTimeSubmits;
|
||||
x.domain([0,largestArrayForRange[largestArrayForRange.length - 1][1]]).clamp(true);
|
||||
} else if(largestSubmittedTimeStamp.cause == "run"){
|
||||
largestArrayForRange = submissionsScoreAndTimeRuns;
|
||||
x.domain([0,largestArrayForRange[largestArrayForRange.length - 1]]).clamp(true);
|
||||
} else if(largestSubmittedTimeStamp.cause == "autosave"){
|
||||
largestArrayForRange = submissionsAutosaves;
|
||||
x.domain([0,largestArrayForRange[largestArrayForRange.length - 1]]).clamp(true);
|
||||
} else if(largestSubmittedTimeStamp.cause == "save"){
|
||||
largestArrayForRange = submissionsSaves;
|
||||
x.domain([0,largestArrayForRange[largestArrayForRange.length - 1]]).clamp(true);
|
||||
}
|
||||
// take maximum value between assesses and submits
|
||||
var yDomain = submissionsScoreAndTimeAssess.concat(submissionsScoreAndTimeSubmits);
|
||||
y.domain(d3.extent(yDomain, function (d) {
|
||||
// console.log(d[0]);
|
||||
return (d[0]);
|
||||
}));
|
||||
// y.domain([0,2]).clamp(true);
|
||||
|
||||
svg.append("g") //x axis
|
||||
.attr("class", "x axis")
|
||||
@@ -177,15 +199,15 @@ $(function() {
|
||||
.style('font-size', 20)
|
||||
.style('text-decoration', 'underline');
|
||||
|
||||
//
|
||||
// svg.append("path")
|
||||
// //.datum()
|
||||
// .attr("class", "line")
|
||||
// .attr('id', 'myPath')// new
|
||||
// .attr("stroke", "black")
|
||||
// .attr("stroke-width", 5)
|
||||
// .attr("fill", "none")// end new
|
||||
// .attr("d", line(submissionsScoreAndTimeAssess));//---
|
||||
|
||||
svg.append("path")
|
||||
//.datum()
|
||||
.attr("class", "line")
|
||||
.attr('id', 'myPath')// new
|
||||
.attr("stroke", "black")
|
||||
.attr("stroke-width", 5)
|
||||
.attr("fill", "none")// end new
|
||||
.attr("d", line(submissionsScoreAndTimeAssess));//---
|
||||
|
||||
svg.append("path")
|
||||
.datum(submissionsScoreAndTimeAssess)
|
||||
@@ -204,27 +226,35 @@ $(function() {
|
||||
.attr("cx", function(d) { return x(d[1]); })
|
||||
.attr("cy", function(d) { return y(d[0]); });
|
||||
|
||||
|
||||
svg.append("path")
|
||||
.datum(submissionsScoreAndTimeSubmits)
|
||||
.attr("class", "line2")
|
||||
.attr('id', 'myPath')// new
|
||||
.attr("stroke", "blue")
|
||||
.attr("stroke-width", 5)
|
||||
.attr("fill", "none")// end new
|
||||
.attr("d", line);//---
|
||||
if (submissionsScoreAndTimeSubmits.length > 0){
|
||||
// get rid of the 0 element at the beginning
|
||||
submissionsScoreAndTimeSubmits.shift();
|
||||
}
|
||||
|
||||
svg.selectAll("dot") // Add dots to submits
|
||||
.data(submissionsScoreAndTimeSubmits)
|
||||
.enter().append("circle")
|
||||
.attr("r", 3.5)
|
||||
.attr("r", 6)
|
||||
.attr("stroke", "black")
|
||||
.attr("fill", "blue")
|
||||
.attr("cx", function(d) { return x(d[1]); })
|
||||
.attr("cy", function(d) { return y(d[0]); });
|
||||
|
||||
for (var i = 0; i < submissionsScoreAndTimeRuns.length; i++) {
|
||||
svg.append("line")
|
||||
.attr("stroke", "red")
|
||||
.attr("stroke-width", 1)
|
||||
.attr("fill", "none")// end new
|
||||
.attr("y1", y(0))
|
||||
.attr("y2", 0)
|
||||
.attr("x1", x(submissionsScoreAndTimeRuns[i]))
|
||||
.attr("x2", x(submissionsScoreAndTimeRuns[i]));
|
||||
}
|
||||
|
||||
var color_hash = { 0 : ["Submissions", "blue"],
|
||||
1 : ["Assesses", "orange"]
|
||||
}
|
||||
1 : ["Assesses", "orange"],
|
||||
2 : ["Runs", "red"]
|
||||
};
|
||||
|
||||
// add legend
|
||||
var legend = svg.append("g")
|
||||
@@ -234,7 +264,8 @@ $(function() {
|
||||
.attr("height", 100)
|
||||
.attr("width", 100);
|
||||
|
||||
var dataset = [submissionsScoreAndTimeSubmits,submissionsScoreAndTimeAssess];
|
||||
var dataset = [submissionsScoreAndTimeSubmits,submissionsScoreAndTimeAssess, submissionsScoreAndTimeRuns];
|
||||
var yOffset = -70;
|
||||
|
||||
legend.selectAll('g').data(dataset)
|
||||
.enter()
|
||||
@@ -243,14 +274,14 @@ $(function() {
|
||||
var g = d3.select(this);
|
||||
g.append("rect")
|
||||
.attr("x", 20)
|
||||
.attr("y", i*25 + 8)
|
||||
.attr("y", i*25 + yOffset)// + 8
|
||||
.attr("width", 10)
|
||||
.attr("height", 10)
|
||||
.style("fill", color_hash[String(i)][1]);
|
||||
|
||||
g.append("text")
|
||||
.attr("x", 40)
|
||||
.attr("y", i * 25 + 18)
|
||||
.attr("y", i * 25 + yOffset + 10)// + 18
|
||||
.attr("height",30)
|
||||
.attr("width",100)
|
||||
.style("fill", color_hash[String(i)][1])
|
||||
@@ -273,7 +304,7 @@ $(function() {
|
||||
try{
|
||||
graph_assesses();
|
||||
} catch(err){
|
||||
// not enough data
|
||||
alert("could not draw the graph");
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -12,6 +12,9 @@ $(function() {
|
||||
$('#files li:last select[name*="file_type_id"]').val(getSelectedExecutionEnvironment().file_type_id);
|
||||
$('#files li:last select').chosen(window.CodeOcean.CHOSEN_OPTIONS);
|
||||
$('body, html').scrollTo('#add-file');
|
||||
// if we collapse the file forms by default, we need to click on the new element in order to open it.
|
||||
// however, this crashes for more files (if we add several ones by clicking the add button more often), since the elements are probably not correctly added to the files list.
|
||||
//$('#files li:last>div:first>a>div').click();
|
||||
};
|
||||
|
||||
var ajaxError = function() {
|
||||
|
@@ -41,8 +41,7 @@ Turtle.prototype.update = function () {
|
||||
var i, k, canvas, ctx, dx, dy, item, c, length;
|
||||
canvas = this.canvas[0];
|
||||
ctx = canvas.getContext('2d');
|
||||
ctx.fillStyle = '#fff';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
length = this.items.length;
|
||||
dx = canvas.width / 2;
|
||||
dy = canvas.height / 2;
|
||||
@@ -56,8 +55,8 @@ Turtle.prototype.update = function () {
|
||||
for (k = 2; k < c.length; k += 2) {
|
||||
ctx.lineTo(c[k] + dx, c[k + 1] + dy);
|
||||
}
|
||||
if (this.fill) {
|
||||
ctx.strokeStyle = this.fill;
|
||||
if (item.fill) {
|
||||
ctx.strokeStyle = item.fill;
|
||||
}
|
||||
|
||||
ctx.stroke();
|
||||
|
@@ -4,7 +4,7 @@ $(function() {
|
||||
|
||||
if ($.isController('exercises') && $('.graph-functions').isPresent()) {
|
||||
var working_times = $('#data').data('working-time');
|
||||
|
||||
|
||||
function get_minutes (time_stamp){
|
||||
try{
|
||||
hours = time_stamp.split(":")[0];
|
||||
@@ -67,6 +67,9 @@ $(function() {
|
||||
// DRAW THE LINE GRAPH ------------------------------------------------------------------------------
|
||||
function draw_line_graph() {
|
||||
var width_ratio = .8;
|
||||
if (getWidth()*width_ratio > 1000){
|
||||
width_ratio = 1000/getWidth();
|
||||
}
|
||||
var height_ratio = .7; // percent of height
|
||||
|
||||
// currently sets as percentage of window width, however, unfortunately
|
||||
|
Reference in New Issue
Block a user