Merge branch 'master' into new_mail_on_comments
This commit is contained in:
@ -704,9 +704,15 @@ $(function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var renderScore = function() {
|
var renderScore = function() {
|
||||||
var score = $('#score').data('score');
|
var score = parseFloat($('#score').data('score'));
|
||||||
var maxium_score = $('#score').data('maximum-score');
|
var maxium_score = parseFloat($('#score').data('maximum-score'));
|
||||||
$('.score').html((score || '?') + ' / ' + maxium_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);
|
renderProgressBar(score, maxium_score);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,6 +9,9 @@ $(function() {
|
|||||||
|
|
||||||
submissionsScoreAndTimeAssess = [[0,0]];
|
submissionsScoreAndTimeAssess = [[0,0]];
|
||||||
submissionsScoreAndTimeSubmits = [[0,0]];
|
submissionsScoreAndTimeSubmits = [[0,0]];
|
||||||
|
submissionsScoreAndTimeRuns = [];
|
||||||
|
submissionsSaves = [];
|
||||||
|
submissionsAutosaves = [];
|
||||||
var maximumValue = 0;
|
var maximumValue = 0;
|
||||||
|
|
||||||
var wtimes = $('#wtimes').data('working_times'); //.hidden#wtimes data-working_times=ActiveSupport::JSON.encode(working_times_until)
|
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++){
|
for (var i = 0;i<submissions_length;i++){
|
||||||
var submission = submissions[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"){
|
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);
|
submissionsScoreAndTimeAssess.push(submissionArray);
|
||||||
} else if(submission.cause == "submit"){
|
} 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);
|
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(submissionsScoreAndTimeAssess.length);
|
||||||
// console.log(submissionsScoreAndTimeSubmits);
|
// console.log(submissionsScoreAndTimeSubmits);
|
||||||
|
// console.log(submissionsScoreAndTimeRuns);
|
||||||
|
|
||||||
function get_minutes (time_stamp) {
|
function get_minutes (time_stamp) {
|
||||||
try {
|
try {
|
||||||
hours = time_stamp.split(":")[0];
|
hours = time_stamp.split(":")[0];
|
||||||
minutes = time_stamp.split(":")[1];
|
minutes = time_stamp.split(":")[1];
|
||||||
seconds = time_stamp.split(":")[2];
|
seconds = time_stamp.split(":")[2];
|
||||||
|
seconds /= 60;
|
||||||
minutes = parseFloat(hours * 60) + parseInt(minutes);
|
minutes = parseFloat(hours * 60) + parseInt(minutes) + seconds;
|
||||||
if (minutes > 0){
|
if (minutes > 0){
|
||||||
return minutes;
|
return minutes;
|
||||||
} else{
|
} else{
|
||||||
@ -82,6 +84,9 @@ $(function() {
|
|||||||
function graph_assesses() {
|
function graph_assesses() {
|
||||||
// MAKE THE GRAPH
|
// MAKE THE GRAPH
|
||||||
var width_ratio = .8;
|
var width_ratio = .8;
|
||||||
|
if (getWidth()*width_ratio > 1000){
|
||||||
|
width_ratio = 1000/getWidth();
|
||||||
|
}
|
||||||
var height_ratio = .7; // percent of height
|
var height_ratio = .7; // percent of height
|
||||||
|
|
||||||
var margin = {top: 100, right: 20, bottom: 70, left: 70},//30,50
|
var margin = {top: 100, right: 20, bottom: 70, left: 70},//30,50
|
||||||
@ -131,15 +136,45 @@ $(function() {
|
|||||||
.append("g")
|
.append("g")
|
||||||
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
||||||
|
|
||||||
|
var largestSubmittedTimeStamp = submissions[submissions_length-1];
|
||||||
|
var largestArrayForRange;
|
||||||
|
|
||||||
x.domain(d3.extent(submissionsScoreAndTimeAssess, function (d) {
|
if(largestSubmittedTimeStamp.cause == "assess"){
|
||||||
// console.log(d[1]);
|
largestArrayForRange = submissionsScoreAndTimeAssess;
|
||||||
return (d[1]);
|
indexForTime = 1;
|
||||||
}));
|
} else if(largestSubmittedTimeStamp.cause == "submit"){
|
||||||
y.domain(d3.extent(submissionsScoreAndTimeAssess, function (d) {
|
largestArrayForRange = submissionsScoreAndTimeSubmits;
|
||||||
|
indexForTime = 1;
|
||||||
|
} else if(largestSubmittedTimeStamp.cause == "run"){
|
||||||
|
largestArrayForRange = submissionsScoreAndTimeRuns;
|
||||||
|
indexForTime = 0;
|
||||||
|
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][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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// x.domain(d3.extent(largestArrayForRange, function (d) {
|
||||||
|
// // console.log(d[1]);
|
||||||
|
// return (d[indexForTime]);
|
||||||
|
// }));
|
||||||
|
|
||||||
|
// take maximum value between assesses and submits
|
||||||
|
var yDomain = submissionsScoreAndTimeAssess.concat(submissionsScoreAndTimeSubmits);
|
||||||
|
y.domain(d3.extent(yDomain, function (d) {
|
||||||
// console.log(d[0]);
|
// console.log(d[0]);
|
||||||
return (d[0]);
|
return (d[0]);
|
||||||
}));
|
}));
|
||||||
|
// y.domain([0,2]).clamp(true);
|
||||||
|
|
||||||
svg.append("g") //x axis
|
svg.append("g") //x axis
|
||||||
.attr("class", "x axis")
|
.attr("class", "x axis")
|
||||||
@ -221,10 +256,21 @@ $(function() {
|
|||||||
.attr("cx", function(d) { return x(d[1]); })
|
.attr("cx", function(d) { return x(d[1]); })
|
||||||
.attr("cy", function(d) { return y(d[0]); });
|
.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"],
|
var color_hash = { 0 : ["Submissions", "blue"],
|
||||||
1 : ["Assesses", "orange"]
|
1 : ["Assesses", "orange"],
|
||||||
}
|
2 : ["Runs", "red"]
|
||||||
|
};
|
||||||
|
|
||||||
// add legend
|
// add legend
|
||||||
var legend = svg.append("g")
|
var legend = svg.append("g")
|
||||||
@ -234,7 +280,8 @@ $(function() {
|
|||||||
.attr("height", 100)
|
.attr("height", 100)
|
||||||
.attr("width", 100);
|
.attr("width", 100);
|
||||||
|
|
||||||
var dataset = [submissionsScoreAndTimeSubmits,submissionsScoreAndTimeAssess];
|
var dataset = [submissionsScoreAndTimeSubmits,submissionsScoreAndTimeAssess, submissionsScoreAndTimeRuns];
|
||||||
|
var yOffset = -70;
|
||||||
|
|
||||||
legend.selectAll('g').data(dataset)
|
legend.selectAll('g').data(dataset)
|
||||||
.enter()
|
.enter()
|
||||||
@ -243,14 +290,14 @@ $(function() {
|
|||||||
var g = d3.select(this);
|
var g = d3.select(this);
|
||||||
g.append("rect")
|
g.append("rect")
|
||||||
.attr("x", 20)
|
.attr("x", 20)
|
||||||
.attr("y", i*25 + 8)
|
.attr("y", i*25 + yOffset)// + 8
|
||||||
.attr("width", 10)
|
.attr("width", 10)
|
||||||
.attr("height", 10)
|
.attr("height", 10)
|
||||||
.style("fill", color_hash[String(i)][1]);
|
.style("fill", color_hash[String(i)][1]);
|
||||||
|
|
||||||
g.append("text")
|
g.append("text")
|
||||||
.attr("x", 40)
|
.attr("x", 40)
|
||||||
.attr("y", i * 25 + 18)
|
.attr("y", i * 25 + yOffset + 10)// + 18
|
||||||
.attr("height",30)
|
.attr("height",30)
|
||||||
.attr("width",100)
|
.attr("width",100)
|
||||||
.style("fill", color_hash[String(i)][1])
|
.style("fill", color_hash[String(i)][1])
|
||||||
@ -273,7 +320,7 @@ $(function() {
|
|||||||
try{
|
try{
|
||||||
graph_assesses();
|
graph_assesses();
|
||||||
} catch(err){
|
} catch(err){
|
||||||
// not enough data
|
alert("could not draw the graph");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -41,8 +41,7 @@ Turtle.prototype.update = function () {
|
|||||||
var i, k, canvas, ctx, dx, dy, item, c, length;
|
var i, k, canvas, ctx, dx, dy, item, c, length;
|
||||||
canvas = this.canvas[0];
|
canvas = this.canvas[0];
|
||||||
ctx = canvas.getContext('2d');
|
ctx = canvas.getContext('2d');
|
||||||
ctx.fillStyle = '#fff';
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
||||||
length = this.items.length;
|
length = this.items.length;
|
||||||
dx = canvas.width / 2;
|
dx = canvas.width / 2;
|
||||||
dy = canvas.height / 2;
|
dy = canvas.height / 2;
|
||||||
@ -56,8 +55,8 @@ Turtle.prototype.update = function () {
|
|||||||
for (k = 2; k < c.length; k += 2) {
|
for (k = 2; k < c.length; k += 2) {
|
||||||
ctx.lineTo(c[k] + dx, c[k + 1] + dy);
|
ctx.lineTo(c[k] + dx, c[k + 1] + dy);
|
||||||
}
|
}
|
||||||
if (this.fill) {
|
if (item.fill) {
|
||||||
ctx.strokeStyle = this.fill;
|
ctx.strokeStyle = item.fill;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
|
@ -4,7 +4,7 @@ $(function() {
|
|||||||
|
|
||||||
if ($.isController('exercises') && $('.graph-functions').isPresent()) {
|
if ($.isController('exercises') && $('.graph-functions').isPresent()) {
|
||||||
var working_times = $('#data').data('working-time');
|
var working_times = $('#data').data('working-time');
|
||||||
|
|
||||||
function get_minutes (time_stamp){
|
function get_minutes (time_stamp){
|
||||||
try{
|
try{
|
||||||
hours = time_stamp.split(":")[0];
|
hours = time_stamp.split(":")[0];
|
||||||
@ -67,6 +67,9 @@ $(function() {
|
|||||||
// DRAW THE LINE GRAPH ------------------------------------------------------------------------------
|
// DRAW THE LINE GRAPH ------------------------------------------------------------------------------
|
||||||
function draw_line_graph() {
|
function draw_line_graph() {
|
||||||
var width_ratio = .8;
|
var width_ratio = .8;
|
||||||
|
if (getWidth()*width_ratio > 1000){
|
||||||
|
width_ratio = 1000/getWidth();
|
||||||
|
}
|
||||||
var height_ratio = .7; // percent of height
|
var height_ratio = .7; // percent of height
|
||||||
|
|
||||||
// currently sets as percentage of window width, however, unfortunately
|
// currently sets as percentage of window width, however, unfortunately
|
||||||
|
@ -38,4 +38,4 @@
|
|||||||
= t('exercises.editor.test')
|
= t('exercises.editor.test')
|
||||||
= render('editor_button', data: {:'data-placement' => 'top', :'data-tooltip' => true}, icon: 'fa fa-trophy', id: 'assess', label: t('exercises.editor.score'), title: t('shared.tooltips.shortcut', shortcut: 'ALT + s'))
|
= render('editor_button', data: {:'data-placement' => 'top', :'data-tooltip' => true}, icon: 'fa fa-trophy', id: 'assess', label: t('exercises.editor.score'), title: t('shared.tooltips.shortcut', shortcut: 'ALT + s'))
|
||||||
|
|
||||||
= render('shared/modal', id: 'comment-modal', title: t('exercises.implement.comment.request'), template: 'exercises/_request_comment_dialogcontent')
|
= render('shared/modal', id: 'comment-modal', title: t('exercises.implement.comment.request'), template: 'exercises/_request_comment_dialogcontent')
|
||||||
|
@ -78,6 +78,9 @@
|
|||||||
br
|
br
|
||||||
- if session[:lti_parameters].try(:has_key?, 'lis_outcome_service_url')
|
- if session[:lti_parameters].try(:has_key?, 'lis_outcome_service_url')
|
||||||
p.text-center = render('editor_button', classes: 'btn-lg btn-success', data: {:'data-url' => submit_exercise_path(@exercise)}, icon: 'fa fa-send', id: 'submit', label: t('exercises.editor.submit'))
|
p.text-center = render('editor_button', classes: 'btn-lg btn-success', data: {:'data-url' => submit_exercise_path(@exercise)}, icon: 'fa fa-send', id: 'submit', label: t('exercises.editor.submit'))
|
||||||
|
- else
|
||||||
|
p.text-center = render('editor_button', classes: 'btn-lg btn-warning-outline', data: {:'data-placement' => 'bottom', :'data-tooltip' => true} , icon: 'fa fa-clock-o', id: 'submit_outdated', label: t('exercises.editor.exercise_deadline_passed'), title: t('exercises.editor.tooltips.exercise_deadline_passed'))
|
||||||
|
|
||||||
- if qa_url
|
- if qa_url
|
||||||
#questions-column
|
#questions-column
|
||||||
#questions-holder data-url="#{qa_url}/qa/index/#{@exercise.id}/#{@user_id}"
|
#questions-holder data-url="#{qa_url}/qa/index/#{@exercise.id}/#{@user_id}"
|
||||||
|
@ -27,7 +27,7 @@ h1 = Exercise.model_name.human(count: 2)
|
|||||||
- @exercises.each do |exercise|
|
- @exercises.each do |exercise|
|
||||||
tr data-id=exercise.id
|
tr data-id=exercise.id
|
||||||
td = exercise.title
|
td = exercise.title
|
||||||
td = link_to_if(policy(exercise.author).show?, exercise.author, exercise.author)
|
td = link_to_if(exercise.author && policy(exercise.author).show?, exercise.author, exercise.author)
|
||||||
td = link_to_if(exercise.execution_environment && policy(exercise.execution_environment).show?, exercise.execution_environment, exercise.execution_environment)
|
td = link_to_if(exercise.execution_environment && policy(exercise.execution_environment).show?, exercise.execution_environment, exercise.execution_environment)
|
||||||
td = exercise.files.teacher_defined_tests.count
|
td = exercise.files.teacher_defined_tests.count
|
||||||
td = exercise.maximum_score
|
td = exercise.maximum_score
|
||||||
|
@ -209,8 +209,10 @@ de:
|
|||||||
submit: Code zur Bewertung abgeben
|
submit: Code zur Bewertung abgeben
|
||||||
test: Testen
|
test: Testen
|
||||||
timeout: 'Ausführung gestoppt. Ihr Code hat die erlaubte Ausführungszeit von %{permitted_execution_time} Sekunden überschritten.'
|
timeout: 'Ausführung gestoppt. Ihr Code hat die erlaubte Ausführungszeit von %{permitted_execution_time} Sekunden überschritten.'
|
||||||
|
exercise_deadline_passed: 'Die Abgabefrist für diese Aufgabe ist bereits abgelaufen.'
|
||||||
tooltips:
|
tooltips:
|
||||||
save: Ihr Code wird automatisch gespeichert, wann immer Sie eine Datei herunterladen, ausführen oder testen. Explizites Speichern ist also selten notwendig.
|
save: Ihr Code wird automatisch gespeichert, wann immer Sie eine Datei herunterladen, ausführen oder testen. Explizites Speichern ist also selten notwendig.
|
||||||
|
exercise_deadline_passed: 'Die hier erzielten Punkte können nur bis zum Ablauf der Abgabefrist an die E-Learning-Plattform übertragen werden.'
|
||||||
request_for_comments_sent: "Kommentaranfrage gesendet."
|
request_for_comments_sent: "Kommentaranfrage gesendet."
|
||||||
editor_file_tree:
|
editor_file_tree:
|
||||||
file_root: Dateien
|
file_root: Dateien
|
||||||
|
@ -209,8 +209,10 @@ en:
|
|||||||
submit: Submit Code For Assessment
|
submit: Submit Code For Assessment
|
||||||
test: Test
|
test: Test
|
||||||
timeout: 'Execution stopped. Your code exceeded the permitted execution time of %{permitted_execution_time} seconds.'
|
timeout: 'Execution stopped. Your code exceeded the permitted execution time of %{permitted_execution_time} seconds.'
|
||||||
|
exercise_deadline_passed: 'The deadline for this exercise has already passed'
|
||||||
tooltips:
|
tooltips:
|
||||||
save: Your code is automatically saved whenever you download, run, or test it. Therefore, explicitly saving is rarely necessary.
|
save: Your code is automatically saved whenever you download, run, or test it. Therefore, explicitly saving is rarely necessary.
|
||||||
|
exercise_deadline_passed: 'The results for this exercise can only be submitted to the e-learning platform before the deadline has passed.'
|
||||||
request_for_comments_sent: "Request for comments sent."
|
request_for_comments_sent: "Request for comments sent."
|
||||||
editor_file_tree:
|
editor_file_tree:
|
||||||
file_root: Files
|
file_root: Files
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
class PyUnitAdapter < TestingFrameworkAdapter
|
class PyUnitAdapter < TestingFrameworkAdapter
|
||||||
COUNT_REGEXP = /Ran (\d+) test/
|
COUNT_REGEXP = /Ran (\d+) test/
|
||||||
FAILURES_REGEXP = /FAILED \(failures=(\d+)\)/
|
FAILURES_REGEXP = /FAILED \(.*failures=(\d+).*\)/
|
||||||
|
ERRORS_REGEXP = /FAILED \(.*errors=(\d+).*\)/
|
||||||
ASSERTION_ERROR_REGEXP = /AssertionError:\s(.*)/
|
ASSERTION_ERROR_REGEXP = /AssertionError:\s(.*)/
|
||||||
|
|
||||||
def self.framework_name
|
def self.framework_name
|
||||||
@ -9,9 +10,11 @@ class PyUnitAdapter < TestingFrameworkAdapter
|
|||||||
|
|
||||||
def parse_output(output)
|
def parse_output(output)
|
||||||
count = COUNT_REGEXP.match(output[:stderr]).captures.first.to_i
|
count = COUNT_REGEXP.match(output[:stderr]).captures.first.to_i
|
||||||
matches = FAILURES_REGEXP.match(output[:stderr])
|
failures_matches = FAILURES_REGEXP.match(output[:stderr])
|
||||||
failed = matches ? matches.captures.try(:first).to_i : 0
|
failed = failures_matches ? failures_matches.captures.try(:first).to_i : 0
|
||||||
error_matches = ASSERTION_ERROR_REGEXP.match(output[:stderr]).try(:captures) || []
|
error_matches = ERRORS_REGEXP.match(output[:stderr])
|
||||||
{count: count, failed: failed, error_messages: error_matches}
|
errors = error_matches ? error_matches.captures.try(:first).to_i : 0
|
||||||
|
assertion_error_matches = ASSERTION_ERROR_REGEXP.match(output[:stderr]).try(:captures) || []
|
||||||
|
{count: count, failed: failed + errors, error_messages: assertion_error_matches}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Reference in New Issue
Block a user