From e2f4991e5450891dc61f9b4d7e47f702a7035226 Mon Sep 17 00:00:00 2001 From: yqbk Date: Thu, 12 May 2016 17:09:13 +0200 Subject: [PATCH 01/30] change collapsing style --- app/views/exercises/_file_form.html.slim | 2 +- app/views/exercises/show.html.slim | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/exercises/_file_form.html.slim b/app/views/exercises/_file_form.html.slim index c737f068..5cdfdc98 100644 --- a/app/views/exercises/_file_form.html.slim +++ b/app/views/exercises/_file_form.html.slim @@ -4,7 +4,7 @@ li.panel.panel-default div.clearfix role="button" span = f.object.name a.pull-right data-toggle="collapse" data-parent="#files" href="#collapse#{id}" collapse - .panel-collapse.collapse.in id="collapse#{id}" role="tabpanel" + .panel-collapse.collapse id="collapse#{id}" role="tabpanel" .panel-body .clearfix = link_to(t('shared.destroy'), '#', class:'btn btn-warning btn-sm discard-file pull-right') .form-group diff --git a/app/views/exercises/show.html.slim b/app/views/exercises/show.html.slim index fc28272a..ceab96a7 100644 --- a/app/views/exercises/show.html.slim +++ b/app/views/exercises/show.html.slim @@ -29,7 +29,7 @@ ul.list-unstyled.panel-group#files div.clearfix role="button" span.panel-title = file.name_with_extension a.pull-right data-toggle="collapse" data-parent="#files" href="#collapse#{file.id}" collapse - .panel-collapse.collapse.in id="collapse#{file.id}" role="tabpanel" + .panel-collapse.collapse id="collapse#{file.id}" role="tabpanel" .panel-body - if policy(file).destroy? .clearfix = link_to(t('shared.destroy'), file, class:'btn btn-warning btn-sm pull-right', data: {confirm: t('shared.confirm_destroy')}, method: :delete) From a16eb4b15b9ae9846cb258c1ec775f888c0d829a Mon Sep 17 00:00:00 2001 From: yqbk Date: Thu, 12 May 2016 17:13:30 +0200 Subject: [PATCH 02/30] sorting files alphabetically --- app/views/exercises/_editor.html.slim | 4 ++-- app/views/exercises/show.html.slim | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/exercises/_editor.html.slim b/app/views/exercises/_editor.html.slim index 42b12e42..3340d6ac 100644 --- a/app/views/exercises/_editor.html.slim +++ b/app/views/exercises/_editor.html.slim @@ -1,7 +1,7 @@ #editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id div class=(@exercise.hide_file_tree ? 'hidden col-sm-3' : 'col-sm-3') = render('editor_file_tree', files: @files) div id='frames' class=(@exercise.hide_file_tree ? 'col-sm-12' : 'col-sm-9') - - @files.each do |file| + - @files.sort{ |a,b| a[:group][:name] <=> b[:group][:name] }.each do |file| = render('editor_frame', exercise: exercise, file: file) #autosave-label = t('exercises.editor.lastsaved') @@ -38,4 +38,4 @@ = 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('shared/modal', id: 'comment-modal', title: t('exercises.implement.comment.request'), template: 'exercises/_request_comment_dialogcontent') \ No newline at end of file += render('shared/modal', id: 'comment-modal', title: t('exercises.implement.comment.request'), template: 'exercises/_request_comment_dialogcontent') diff --git a/app/views/exercises/show.html.slim b/app/views/exercises/show.html.slim index ceab96a7..85fb09cb 100644 --- a/app/views/exercises/show.html.slim +++ b/app/views/exercises/show.html.slim @@ -23,7 +23,7 @@ h1 h2 = t('activerecord.attributes.exercise.files') ul.list-unstyled.panel-group#files - - @exercise.files.each do |file| + - @exercise.files.order('name').each do |file| li.panel.panel-default .panel-heading role="tab" id="heading" div.clearfix role="button" From 10e68915d82d8db4b39aaea790c3beea1848f905 Mon Sep 17 00:00:00 2001 From: yqbk Date: Thu, 12 May 2016 17:34:30 +0200 Subject: [PATCH 03/30] add key exercise_deadline_passed --- config/locales/de.yml | 2 ++ config/locales/en.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/config/locales/de.yml b/config/locales/de.yml index e7d78943..30f4f7ef 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -209,8 +209,10 @@ de: submit: Code zur Bewertung abgeben test: Testen 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: 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 Punkten können nur bis zum Ablauf der Abgabefrist an die E-Learning-Plattform übertragen werden.' request_for_comments_sent: "Kommentaranfrage gesendet." editor_file_tree: file_root: Dateien diff --git a/config/locales/en.yml b/config/locales/en.yml index f2470fc8..6cc9dcaf 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -209,8 +209,10 @@ en: submit: Submit Code For Assessment test: Test 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: 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." editor_file_tree: file_root: Files From e838f5a1b129c32ff94b73778abd84a4bcffec57 Mon Sep 17 00:00:00 2001 From: yqbk Date: Thu, 12 May 2016 17:35:09 +0200 Subject: [PATCH 04/30] fix submit-button when not active --- app/views/exercises/implement.html.slim | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/views/exercises/implement.html.slim b/app/views/exercises/implement.html.slim index 728492b6..0c5e109b 100644 --- a/app/views/exercises/implement.html.slim +++ b/app/views/exercises/implement.html.slim @@ -78,6 +78,9 @@ br - 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')) + - 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 #questions-column #questions-holder data-url="#{qa_url}/qa/index/#{@exercise.id}/#{@user_id}" From 5c9a9b8a476a8a1b7fe8d9d1b0e60acb6454d12b Mon Sep 17 00:00:00 2001 From: yqbk Date: Thu, 12 May 2016 17:53:21 +0200 Subject: [PATCH 05/30] add alert on submit-button click --- app/assets/javascripts/editor.js.erb | 8 ++++++++ app/views/exercises/_editor.html.slim | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb index c69551bb..3d9bb5cb 100644 --- a/app/assets/javascripts/editor.js.erb +++ b/app/assets/javascripts/editor.js.erb @@ -465,6 +465,7 @@ $(function() { $('#start').on('click', showWorkspaceTab); //$('#submit').on('click', confirmSubmission); $('#submit').on('click', submitCode); + $('#submit_outdated').on('click', submitOutdated); }; var initializeWorkspaceButtons = function() { @@ -751,6 +752,13 @@ $(function() { }); }; + var submitOutdated = function(event) { + $.flash.danger({ + icon: ['fa', 'fa-clock-o'], + text: $('#editor').data('message-deadline') + }); + }; + var sendError = function(message, submission_id) { showSpinner($('#render')); var jqxhr = ajax({ diff --git a/app/views/exercises/_editor.html.slim b/app/views/exercises/_editor.html.slim index 3340d6ac..39ef3bd1 100644 --- a/app/views/exercises/_editor.html.slim +++ b/app/views/exercises/_editor.html.slim @@ -1,4 +1,4 @@ -#editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id +#editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-deadline=t('exercises.editor.deadline_alert') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id div class=(@exercise.hide_file_tree ? 'hidden col-sm-3' : 'col-sm-3') = render('editor_file_tree', files: @files) div id='frames' class=(@exercise.hide_file_tree ? 'col-sm-12' : 'col-sm-9') - @files.sort{ |a,b| a[:group][:name] <=> b[:group][:name] }.each do |file| From 3189f615353309148ee9a56637ae25e2b635dc0c Mon Sep 17 00:00:00 2001 From: yqbk Date: Thu, 12 May 2016 18:03:33 +0200 Subject: [PATCH 06/30] no alert on outdated button --- app/assets/javascripts/editor.js.erb | 8 -------- app/views/exercises/_editor.html.slim | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb index 3d9bb5cb..c69551bb 100644 --- a/app/assets/javascripts/editor.js.erb +++ b/app/assets/javascripts/editor.js.erb @@ -465,7 +465,6 @@ $(function() { $('#start').on('click', showWorkspaceTab); //$('#submit').on('click', confirmSubmission); $('#submit').on('click', submitCode); - $('#submit_outdated').on('click', submitOutdated); }; var initializeWorkspaceButtons = function() { @@ -752,13 +751,6 @@ $(function() { }); }; - var submitOutdated = function(event) { - $.flash.danger({ - icon: ['fa', 'fa-clock-o'], - text: $('#editor').data('message-deadline') - }); - }; - var sendError = function(message, submission_id) { showSpinner($('#render')); var jqxhr = ajax({ diff --git a/app/views/exercises/_editor.html.slim b/app/views/exercises/_editor.html.slim index 39ef3bd1..b9c41863 100644 --- a/app/views/exercises/_editor.html.slim +++ b/app/views/exercises/_editor.html.slim @@ -1,4 +1,4 @@ -#editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-deadline=t('exercises.editor.deadline_alert') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id +#editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id div class=(@exercise.hide_file_tree ? 'hidden col-sm-3' : 'col-sm-3') = render('editor_file_tree', files: @files) div id='frames' class=(@exercise.hide_file_tree ? 'col-sm-12' : 'col-sm-9') - @files.sort{ |a,b| a[:group][:name] <=> b[:group][:name] }.each do |file| From d54d1dd3e8b5b8d2b8f1119523f07d046ee85c02 Mon Sep 17 00:00:00 2001 From: yqbk Date: Thu, 12 May 2016 18:22:17 +0200 Subject: [PATCH 07/30] Score given in percentage --- app/assets/javascripts/editor.js.erb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb index c69551bb..b40b93ec 100644 --- a/app/assets/javascripts/editor.js.erb +++ b/app/assets/javascripts/editor.js.erb @@ -706,7 +706,8 @@ $(function() { var renderScore = function() { var score = $('#score').data('score'); var maxium_score = $('#score').data('maximum-score'); - $('.score').html((score || '?') + ' / ' + maxium_score); + var percentage_score = score / maxium_score * 100 + $('.score').html((percentage_score || 0) + ' % '); renderProgressBar(score, maxium_score); }; From d05ceac7a346bff9f7864a6491efbff6a5e3cab1 Mon Sep 17 00:00:00 2001 From: yqbk Date: Thu, 12 May 2016 18:30:50 +0200 Subject: [PATCH 08/30] check if score is valid --- app/assets/javascripts/editor.js.erb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb index b40b93ec..1d84361b 100644 --- a/app/assets/javascripts/editor.js.erb +++ b/app/assets/javascripts/editor.js.erb @@ -706,8 +706,13 @@ $(function() { var renderScore = function() { var score = $('#score').data('score'); var maxium_score = $('#score').data('maximum-score'); - var percentage_score = score / maxium_score * 100 - $('.score').html((percentage_score || 0) + ' % '); + if (score >= 0 && score <= maxium_score && maxium_score >0 ) { + var percentage_score = score / maxium_score * 100 + $('.score').html(percentage_score + '%'); + } + else { + $('.score').html( 0 + ' % '); + } renderProgressBar(score, maxium_score); }; From e5b3d33228599f6bf902a260b05eeed5d4404794 Mon Sep 17 00:00:00 2001 From: yqbk Date: Thu, 12 May 2016 18:34:16 +0200 Subject: [PATCH 09/30] delete spaces --- app/assets/javascripts/editor.js.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb index 1d84361b..0bb22853 100644 --- a/app/assets/javascripts/editor.js.erb +++ b/app/assets/javascripts/editor.js.erb @@ -711,7 +711,7 @@ $(function() { $('.score').html(percentage_score + '%'); } else { - $('.score').html( 0 + ' % '); + $('.score').html( 0 + '%'); } renderProgressBar(score, maxium_score); }; From a2e1b08730daa61476d0c4cd426446cfe9d83e4f Mon Sep 17 00:00:00 2001 From: yqbk Date: Thu, 12 May 2016 18:40:42 +0200 Subject: [PATCH 10/30] delete duplicate depleted --- app/views/exercises/_editor.html.slim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/exercises/_editor.html.slim b/app/views/exercises/_editor.html.slim index b9c41863..3340d6ac 100644 --- a/app/views/exercises/_editor.html.slim +++ b/app/views/exercises/_editor.html.slim @@ -1,4 +1,4 @@ -#editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id +#editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id div class=(@exercise.hide_file_tree ? 'hidden col-sm-3' : 'col-sm-3') = render('editor_file_tree', files: @files) div id='frames' class=(@exercise.hide_file_tree ? 'col-sm-12' : 'col-sm-9') - @files.sort{ |a,b| a[:group][:name] <=> b[:group][:name] }.each do |file| From d26d859df1e532fd8519020a1dd08ed6a689c52b Mon Sep 17 00:00:00 2001 From: yqbk Date: Thu, 12 May 2016 18:45:14 +0200 Subject: [PATCH 11/30] resolve confilts --- app/views/exercises/_editor.html.slim | 2 +- app/views/exercises/_file_form.html.slim | 2 +- app/views/exercises/show.html.slim | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/exercises/_editor.html.slim b/app/views/exercises/_editor.html.slim index 3340d6ac..0ce5b73f 100644 --- a/app/views/exercises/_editor.html.slim +++ b/app/views/exercises/_editor.html.slim @@ -1,7 +1,7 @@ #editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id div class=(@exercise.hide_file_tree ? 'hidden col-sm-3' : 'col-sm-3') = render('editor_file_tree', files: @files) div id='frames' class=(@exercise.hide_file_tree ? 'col-sm-12' : 'col-sm-9') - - @files.sort{ |a,b| a[:group][:name] <=> b[:group][:name] }.each do |file| + - @files.each do |file| = render('editor_frame', exercise: exercise, file: file) #autosave-label = t('exercises.editor.lastsaved') diff --git a/app/views/exercises/_file_form.html.slim b/app/views/exercises/_file_form.html.slim index 5cdfdc98..c737f068 100644 --- a/app/views/exercises/_file_form.html.slim +++ b/app/views/exercises/_file_form.html.slim @@ -4,7 +4,7 @@ li.panel.panel-default div.clearfix role="button" span = f.object.name a.pull-right data-toggle="collapse" data-parent="#files" href="#collapse#{id}" collapse - .panel-collapse.collapse id="collapse#{id}" role="tabpanel" + .panel-collapse.collapse.in id="collapse#{id}" role="tabpanel" .panel-body .clearfix = link_to(t('shared.destroy'), '#', class:'btn btn-warning btn-sm discard-file pull-right') .form-group diff --git a/app/views/exercises/show.html.slim b/app/views/exercises/show.html.slim index 85fb09cb..fc28272a 100644 --- a/app/views/exercises/show.html.slim +++ b/app/views/exercises/show.html.slim @@ -23,13 +23,13 @@ h1 h2 = t('activerecord.attributes.exercise.files') ul.list-unstyled.panel-group#files - - @exercise.files.order('name').each do |file| + - @exercise.files.each do |file| li.panel.panel-default .panel-heading role="tab" id="heading" div.clearfix role="button" span.panel-title = file.name_with_extension a.pull-right data-toggle="collapse" data-parent="#files" href="#collapse#{file.id}" collapse - .panel-collapse.collapse id="collapse#{file.id}" role="tabpanel" + .panel-collapse.collapse.in id="collapse#{file.id}" role="tabpanel" .panel-body - if policy(file).destroy? .clearfix = link_to(t('shared.destroy'), file, class:'btn btn-warning btn-sm pull-right', data: {confirm: t('shared.confirm_destroy')}, method: :delete) From f5aa3cef3ce69f453fbf1fecd9c6ebe6599feb1c Mon Sep 17 00:00:00 2001 From: yqbk Date: Thu, 12 May 2016 19:03:17 +0200 Subject: [PATCH 12/30] Problem when no files solved --- app/views/exercises/_editor.html.slim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/exercises/_editor.html.slim b/app/views/exercises/_editor.html.slim index 3340d6ac..0ce5b73f 100644 --- a/app/views/exercises/_editor.html.slim +++ b/app/views/exercises/_editor.html.slim @@ -1,7 +1,7 @@ #editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id div class=(@exercise.hide_file_tree ? 'hidden col-sm-3' : 'col-sm-3') = render('editor_file_tree', files: @files) div id='frames' class=(@exercise.hide_file_tree ? 'col-sm-12' : 'col-sm-9') - - @files.sort{ |a,b| a[:group][:name] <=> b[:group][:name] }.each do |file| + - @files.each do |file| = render('editor_frame', exercise: exercise, file: file) #autosave-label = t('exercises.editor.lastsaved') From 34c9d791f43c83a4b75a7d9ecba28139b0560c29 Mon Sep 17 00:00:00 2001 From: John Geiger Date: Sun, 29 May 2016 17:30:49 +0200 Subject: [PATCH 13/30] Finishing up graphs. Formatting and adding "Runs" lines. --- Gemfile | 2 +- app/assets/javascripts/exercise_graphs.js | 65 ++--- app/assets/javascripts/working_time_graphs.js | 5 +- db/schema.rb | 225 ------------------ 4 files changed, 43 insertions(+), 254 deletions(-) delete mode 100644 db/schema.rb diff --git a/Gemfile b/Gemfile index 540b11b2..bf089d6c 100644 --- a/Gemfile +++ b/Gemfile @@ -37,7 +37,7 @@ gem 'tubesock' gem 'faye-websocket' gem 'nokogiri' gem 'd3-rails' -gem 'rest-client’ +gem 'rest-client' group :development do gem 'better_errors', platform: :ruby diff --git a/app/assets/javascripts/exercise_graphs.js b/app/assets/javascripts/exercise_graphs.js index 2d3588c6..f0a9f0fc 100644 --- a/app/assets/javascripts/exercise_graphs.js +++ b/app/assets/javascripts/exercise_graphs.js @@ -9,6 +9,7 @@ $(function() { submissionsScoreAndTimeAssess = [[0,0]]; submissionsScoreAndTimeSubmits = [[0,0]]; + submissionsScoreAndTimeRuns = []; var maximumValue = 0; var wtimes = $('#wtimes').data('working_times'); //.hidden#wtimes data-working_times=ActiveSupport::JSON.encode(working_times_until) @@ -18,43 +19,38 @@ $(function() { for (var i = 0;i 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]); } } // 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 +78,9 @@ $(function() { function graph_assesses() { // MAKE THE GRAPH var width_ratio = .8; + if (width_ratio > 1000){ + width_ratio = 1000; + } var height_ratio = .7; // percent of height var margin = {top: 100, right: 20, bottom: 70, left: 70},//30,50 @@ -221,10 +220,21 @@ $(function() { .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 +244,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 +254,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]) diff --git a/app/assets/javascripts/working_time_graphs.js b/app/assets/javascripts/working_time_graphs.js index 315d2c09..4b6db432 100644 --- a/app/assets/javascripts/working_time_graphs.js +++ b/app/assets/javascripts/working_time_graphs.js @@ -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 (width_ratio > 1000){ + width_ratio = 1000; + } var height_ratio = .7; // percent of height // currently sets as percentage of window width, however, unfortunately diff --git a/db/schema.rb b/db/schema.rb deleted file mode 100644 index bcf1a675..00000000 --- a/db/schema.rb +++ /dev/null @@ -1,225 +0,0 @@ -# encoding: UTF-8 -# This file is auto-generated from the current state of the database. Instead -# of editing this file, please use the migrations feature of Active Record to -# incrementally modify your database, and then regenerate this schema definition. -# -# Note that this schema.rb definition is the authoritative source for your -# database schema. If you need to create the application database on another -# system, you should be using db:schema:load, not running all the migrations -# from scratch. The latter is a flawed and unsustainable approach (the more migrations -# you'll amass, the slower it'll run and the greater likelihood for issues). -# -# It's strongly recommended that you check this file into your version control system. - -ActiveRecord::Schema.define(version: 20160510145341) do - - # These are extensions that must be enabled in order to support this database - enable_extension "plpgsql" - - create_table "code_harbor_links", force: true do |t| - t.string "oauth2token" - t.datetime "created_at" - t.datetime "updated_at" - t.integer "user_id" - end - - add_index "code_harbor_links", ["user_id"], name: "index_code_harbor_links_on_user_id", using: :btree - - create_table "comments", force: true do |t| - t.integer "user_id" - t.integer "file_id" - t.string "user_type" - t.integer "row" - t.integer "column" - t.string "text" - t.datetime "created_at" - t.datetime "updated_at" - end - - add_index "comments", ["file_id"], name: "index_comments_on_file_id", using: :btree - add_index "comments", ["user_id"], name: "index_comments_on_user_id", using: :btree - - create_table "consumers", force: true do |t| - t.string "name" - t.datetime "created_at" - t.datetime "updated_at" - t.string "oauth_key" - t.string "oauth_secret" - end - - create_table "errors", force: true do |t| - t.integer "execution_environment_id" - t.text "message" - t.datetime "created_at" - t.datetime "updated_at" - t.integer "submission_id" - end - - add_index "errors", ["submission_id"], name: "index_errors_on_submission_id", using: :btree - - create_table "execution_environments", force: true do |t| - t.string "docker_image" - t.string "name" - t.datetime "created_at" - t.datetime "updated_at" - t.string "run_command" - t.string "test_command" - t.string "testing_framework" - t.text "help" - t.string "exposed_ports" - t.integer "permitted_execution_time" - t.integer "user_id" - t.string "user_type" - t.integer "pool_size" - t.integer "file_type_id" - t.integer "memory_limit" - t.boolean "network_enabled" - end - - create_table "exercises", force: true do |t| - t.text "description" - t.integer "execution_environment_id" - t.string "title" - t.datetime "created_at" - t.datetime "updated_at" - t.integer "user_id" - t.text "instructions" - t.boolean "public" - t.string "user_type" - t.string "token" - t.integer "team_id" - t.boolean "hide_file_tree" - t.boolean "allow_file_creation" - end - - add_index "exercises", ["execution_environment_id"], name: "test3", using: :btree - - create_table "external_users", force: true do |t| - t.integer "consumer_id" - t.string "email" - t.string "external_id" - t.string "name" - t.datetime "created_at" - t.datetime "updated_at" - end - - create_table "file_types", force: true do |t| - t.string "editor_mode" - t.string "file_extension" - t.integer "indent_size" - t.string "name" - t.integer "user_id" - t.datetime "created_at" - t.datetime "updated_at" - t.boolean "executable" - t.boolean "renderable" - t.string "user_type" - t.boolean "binary" - end - - create_table "files", force: true do |t| - t.text "content" - t.integer "context_id" - t.string "context_type" - t.integer "file_id" - t.integer "file_type_id" - t.boolean "hidden" - t.string "name" - t.boolean "read_only" - t.datetime "created_at" - t.datetime "updated_at" - t.string "native_file" - t.string "role" - t.string "hashed_content" - t.string "feedback_message" - t.float "weight" - t.string "path" - end - - add_index "files", ["context_id", "context_type"], name: "index_files_on_context_id_and_context_type", using: :btree - - create_table "hints", force: true do |t| - t.integer "execution_environment_id" - t.string "locale" - t.text "message" - t.string "name" - t.string "regular_expression" - t.datetime "created_at" - t.datetime "updated_at" - end - - create_table "internal_users", force: true do |t| - t.integer "consumer_id" - t.string "email" - t.string "name" - t.string "role" - t.datetime "created_at" - t.datetime "updated_at" - t.string "crypted_password" - t.string "salt" - t.integer "failed_logins_count", default: 0 - t.datetime "lock_expires_at" - t.string "unlock_token" - t.string "remember_me_token" - t.datetime "remember_me_token_expires_at" - t.string "reset_password_token" - t.datetime "reset_password_token_expires_at" - t.datetime "reset_password_email_sent_at" - t.string "activation_state" - t.string "activation_token" - t.datetime "activation_token_expires_at" - end - - add_index "internal_users", ["activation_token"], name: "index_internal_users_on_activation_token", using: :btree - add_index "internal_users", ["email"], name: "index_internal_users_on_email", unique: true, using: :btree - add_index "internal_users", ["remember_me_token"], name: "index_internal_users_on_remember_me_token", using: :btree - add_index "internal_users", ["reset_password_token"], name: "index_internal_users_on_reset_password_token", using: :btree - - create_table "internal_users_teams", force: true do |t| - t.integer "internal_user_id" - t.integer "team_id" - end - - add_index "internal_users_teams", ["internal_user_id"], name: "index_internal_users_teams_on_internal_user_id", using: :btree - add_index "internal_users_teams", ["team_id"], name: "index_internal_users_teams_on_team_id", using: :btree - - create_table "request_for_comments", force: true do |t| - t.integer "user_id", null: false - t.integer "exercise_id", null: false - t.integer "file_id", null: false - t.datetime "requested_at" - t.datetime "created_at" - t.datetime "updated_at" - t.string "user_type" - t.text "question" - end - - create_table "submissions", force: true do |t| - t.integer "exercise_id" - t.float "score" - t.integer "user_id" - t.datetime "created_at" - t.datetime "updated_at" - t.string "cause" - t.string "user_type" - end - - add_index "submissions", ["exercise_id"], name: "test1", where: "((user_type)::text = 'ExternalUser'::text)", using: :btree - add_index "submissions", ["exercise_id"], name: "test2", using: :btree - - create_table "teams", force: true do |t| - t.string "name" - t.datetime "created_at" - t.datetime "updated_at" - end - - create_table "testruns", force: true do |t| - t.boolean "passed" - t.text "output" - t.integer "file_id" - t.integer "submission_id" - t.datetime "created_at" - t.datetime "updated_at" - end - -end From 2ff04cf59df90dd0c3432268b8de784a6ee5d50c Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Thu, 2 Jun 2016 15:27:36 +0200 Subject: [PATCH 14/30] fixed scaling of graphs --- app/assets/javascripts/exercise_graphs.js | 4 ++-- app/assets/javascripts/working_time_graphs.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/exercise_graphs.js b/app/assets/javascripts/exercise_graphs.js index f0a9f0fc..8b11f668 100644 --- a/app/assets/javascripts/exercise_graphs.js +++ b/app/assets/javascripts/exercise_graphs.js @@ -78,8 +78,8 @@ $(function() { function graph_assesses() { // MAKE THE GRAPH var width_ratio = .8; - if (width_ratio > 1000){ - width_ratio = 1000; + if (getWidth()*width_ratio > 1000){ + width_ratio = 1000/getWidth(); } var height_ratio = .7; // percent of height diff --git a/app/assets/javascripts/working_time_graphs.js b/app/assets/javascripts/working_time_graphs.js index 4b6db432..181b3799 100644 --- a/app/assets/javascripts/working_time_graphs.js +++ b/app/assets/javascripts/working_time_graphs.js @@ -67,8 +67,8 @@ $(function() { // DRAW THE LINE GRAPH ------------------------------------------------------------------------------ function draw_line_graph() { var width_ratio = .8; - if (width_ratio > 1000){ - width_ratio = 1000; + if (getWidth()*width_ratio > 1000){ + width_ratio = 1000/getWidth(); } var height_ratio = .7; // percent of height From 5ba980b31612c092afa8ac98d7470e57705a7636 Mon Sep 17 00:00:00 2001 From: John Geiger Date: Thu, 2 Jun 2016 15:30:18 +0200 Subject: [PATCH 15/30] Fix x-axis domain problem --- app/assets/javascripts/exercise_graphs.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/exercise_graphs.js b/app/assets/javascripts/exercise_graphs.js index 8b11f668..efde486d 100644 --- a/app/assets/javascripts/exercise_graphs.js +++ b/app/assets/javascripts/exercise_graphs.js @@ -130,8 +130,17 @@ $(function() { .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); + var largestSubmittedTimeStamp = submissions[submissions_length-1]; + var largestArrayForRange; + if(largestSubmittedTimeStamp.cause == "assess"){ + largestArrayForRange = submissionsScoreAndTimeAssess; + } else if(largestSubmittedTimeStamp.cause == "submit"){ + largestArrayForRange = submissionsScoreAndTimeSubmits; + } else if(largestSubmittedTimeStamp.cause == "run"){ + largestArrayForRange = submissionsScoreAndTimeRuns; + } - x.domain(d3.extent(submissionsScoreAndTimeAssess, function (d) { + x.domain(d3.extent(largestArrayForRange, function (d) { // console.log(d[1]); return (d[1]); })); From 3c8bd90e2b03fec1d904ccefb3e0ce89346f13e2 Mon Sep 17 00:00:00 2001 From: John Geiger Date: Thu, 2 Jun 2016 15:40:18 +0200 Subject: [PATCH 16/30] fix indexing for x axis --- app/assets/javascripts/exercise_graphs.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/exercise_graphs.js b/app/assets/javascripts/exercise_graphs.js index efde486d..8e6263bf 100644 --- a/app/assets/javascripts/exercise_graphs.js +++ b/app/assets/javascripts/exercise_graphs.js @@ -131,18 +131,23 @@ $(function() { .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var largestSubmittedTimeStamp = submissions[submissions_length-1]; + var indexForTime; var largestArrayForRange; if(largestSubmittedTimeStamp.cause == "assess"){ - largestArrayForRange = submissionsScoreAndTimeAssess; + largestArrayForRange = submissionsScoreAndTimeAssess[1]; + indexForTime = 1; } else if(largestSubmittedTimeStamp.cause == "submit"){ - largestArrayForRange = submissionsScoreAndTimeSubmits; + largestArrayForRange = submissionsScoreAndTimeSubmits[1]; + indexForTime = 1; } else if(largestSubmittedTimeStamp.cause == "run"){ - largestArrayForRange = submissionsScoreAndTimeRuns; + largestArrayForRange = submissionsScoreAndTimeRuns[0]; + indexForTime = 0; + } x.domain(d3.extent(largestArrayForRange, function (d) { // console.log(d[1]); - return (d[1]); + return (d[indexForTime]); })); y.domain(d3.extent(submissionsScoreAndTimeAssess, function (d) { // console.log(d[0]); From cd005483ab4814be176f53791f326853c0ee224e Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Thu, 2 Jun 2016 16:34:13 +0200 Subject: [PATCH 17/30] removed incorrect array accesses. --- app/assets/javascripts/exercise_graphs.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/exercise_graphs.js b/app/assets/javascripts/exercise_graphs.js index 8e6263bf..8e8e15db 100644 --- a/app/assets/javascripts/exercise_graphs.js +++ b/app/assets/javascripts/exercise_graphs.js @@ -134,13 +134,13 @@ $(function() { var indexForTime; var largestArrayForRange; if(largestSubmittedTimeStamp.cause == "assess"){ - largestArrayForRange = submissionsScoreAndTimeAssess[1]; + largestArrayForRange = submissionsScoreAndTimeAssess; indexForTime = 1; } else if(largestSubmittedTimeStamp.cause == "submit"){ - largestArrayForRange = submissionsScoreAndTimeSubmits[1]; + largestArrayForRange = submissionsScoreAndTimeSubmits; indexForTime = 1; } else if(largestSubmittedTimeStamp.cause == "run"){ - largestArrayForRange = submissionsScoreAndTimeRuns[0]; + largestArrayForRange = submissionsScoreAndTimeRuns; indexForTime = 0; } From a75227c8f7ffcaab447ca5c4b69aaae887a6eafe Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Wed, 8 Jun 2016 11:49:34 +0200 Subject: [PATCH 18/30] Don't call author policy if author is missing --- app/views/exercises/index.html.slim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/exercises/index.html.slim b/app/views/exercises/index.html.slim index 97847f1f..ae018e82 100644 --- a/app/views/exercises/index.html.slim +++ b/app/views/exercises/index.html.slim @@ -27,7 +27,7 @@ h1 = Exercise.model_name.human(count: 2) - @exercises.each do |exercise| tr data-id=exercise.id 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 = exercise.files.teacher_defined_tests.count td = exercise.maximum_score From 52ba35d0e4d20f4a41ad7d64a7efde1dcdee770c Mon Sep 17 00:00:00 2001 From: John Geiger Date: Wed, 8 Jun 2016 13:55:09 +0200 Subject: [PATCH 19/30] fixed graph sizing --- app/assets/javascripts/exercise_graphs.js | 38 ++++++++++++++++++----- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/exercise_graphs.js b/app/assets/javascripts/exercise_graphs.js index 8e8e15db..f5640788 100644 --- a/app/assets/javascripts/exercise_graphs.js +++ b/app/assets/javascripts/exercise_graphs.js @@ -10,6 +10,8 @@ $(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) @@ -38,6 +40,10 @@ $(function() { 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); @@ -131,8 +137,8 @@ $(function() { .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var largestSubmittedTimeStamp = submissions[submissions_length-1]; - var indexForTime; var largestArrayForRange; + if(largestSubmittedTimeStamp.cause == "assess"){ largestArrayForRange = submissionsScoreAndTimeAssess; indexForTime = 1; @@ -142,17 +148,33 @@ $(function() { } 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]); - })); - y.domain(d3.extent(submissionsScoreAndTimeAssess, function (d) { + // 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]); return (d[0]); })); + // y.domain([0,2]).clamp(true); svg.append("g") //x axis .attr("class", "x axis") @@ -298,7 +320,7 @@ $(function() { try{ graph_assesses(); } catch(err){ - // not enough data + alert("could not draw the graph"); } } From 9e5297c1de6b0bc08b9e1d1f4507f69c5ac693a9 Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Wed, 8 Jun 2016 14:05:13 +0200 Subject: [PATCH 20/30] re-add schema.rb --- db/schema.rb | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 db/schema.rb diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 00000000..f519dfe1 --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,220 @@ +# encoding: UTF-8 +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema.define(version: 20160512131539) do + + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + + create_table "code_harbor_links", force: true do |t| + t.string "oauth2token" + t.datetime "created_at" + t.datetime "updated_at" + t.integer "user_id" + end + + add_index "code_harbor_links", ["user_id"], name: "index_code_harbor_links_on_user_id", using: :btree + + create_table "comments", force: true do |t| + t.integer "user_id" + t.integer "file_id" + t.string "user_type" + t.integer "row" + t.integer "column" + t.text "text" + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "comments", ["file_id"], name: "index_comments_on_file_id", using: :btree + add_index "comments", ["user_id"], name: "index_comments_on_user_id", using: :btree + + create_table "consumers", force: true do |t| + t.string "name" + t.datetime "created_at" + t.datetime "updated_at" + t.string "oauth_key" + t.string "oauth_secret" + end + + create_table "errors", force: true do |t| + t.integer "execution_environment_id" + t.text "message" + t.datetime "created_at" + t.datetime "updated_at" + t.integer "submission_id" + end + + add_index "errors", ["submission_id"], name: "index_errors_on_submission_id", using: :btree + + create_table "execution_environments", force: true do |t| + t.string "docker_image" + t.string "name" + t.datetime "created_at" + t.datetime "updated_at" + t.string "run_command" + t.string "test_command" + t.string "testing_framework" + t.text "help" + t.string "exposed_ports" + t.integer "permitted_execution_time" + t.integer "user_id" + t.string "user_type" + t.integer "pool_size" + t.integer "file_type_id" + t.integer "memory_limit" + t.boolean "network_enabled" + end + + create_table "exercises", force: true do |t| + t.text "description" + t.integer "execution_environment_id" + t.string "title" + t.datetime "created_at" + t.datetime "updated_at" + t.integer "user_id" + t.text "instructions" + t.boolean "public" + t.string "user_type" + t.string "token" + t.integer "team_id" + t.boolean "hide_file_tree" + t.boolean "allow_file_creation" + end + + create_table "external_users", force: true do |t| + t.integer "consumer_id" + t.string "email" + t.string "external_id" + t.string "name" + t.datetime "created_at" + t.datetime "updated_at" + end + + create_table "file_types", force: true do |t| + t.string "editor_mode" + t.string "file_extension" + t.integer "indent_size" + t.string "name" + t.integer "user_id" + t.datetime "created_at" + t.datetime "updated_at" + t.boolean "executable" + t.boolean "renderable" + t.string "user_type" + t.boolean "binary" + end + + create_table "files", force: true do |t| + t.text "content" + t.integer "context_id" + t.string "context_type" + t.integer "file_id" + t.integer "file_type_id" + t.boolean "hidden" + t.string "name" + t.boolean "read_only" + t.datetime "created_at" + t.datetime "updated_at" + t.string "native_file" + t.string "role" + t.string "hashed_content" + t.string "feedback_message" + t.float "weight" + t.string "path" + end + + add_index "files", ["context_id", "context_type"], name: "index_files_on_context_id_and_context_type", using: :btree + + create_table "hints", force: true do |t| + t.integer "execution_environment_id" + t.string "locale" + t.text "message" + t.string "name" + t.string "regular_expression" + t.datetime "created_at" + t.datetime "updated_at" + end + + create_table "internal_users", force: true do |t| + t.integer "consumer_id" + t.string "email" + t.string "name" + t.string "role" + t.datetime "created_at" + t.datetime "updated_at" + t.string "crypted_password" + t.string "salt" + t.integer "failed_logins_count", default: 0 + t.datetime "lock_expires_at" + t.string "unlock_token" + t.string "remember_me_token" + t.datetime "remember_me_token_expires_at" + t.string "reset_password_token" + t.datetime "reset_password_token_expires_at" + t.datetime "reset_password_email_sent_at" + t.string "activation_state" + t.string "activation_token" + t.datetime "activation_token_expires_at" + end + + add_index "internal_users", ["activation_token"], name: "index_internal_users_on_activation_token", using: :btree + add_index "internal_users", ["email"], name: "index_internal_users_on_email", unique: true, using: :btree + add_index "internal_users", ["remember_me_token"], name: "index_internal_users_on_remember_me_token", using: :btree + add_index "internal_users", ["reset_password_token"], name: "index_internal_users_on_reset_password_token", using: :btree + + create_table "internal_users_teams", force: true do |t| + t.integer "internal_user_id" + t.integer "team_id" + end + + add_index "internal_users_teams", ["internal_user_id"], name: "index_internal_users_teams_on_internal_user_id", using: :btree + add_index "internal_users_teams", ["team_id"], name: "index_internal_users_teams_on_team_id", using: :btree + + create_table "request_for_comments", force: true do |t| + t.integer "user_id", null: false + t.integer "exercise_id", null: false + t.integer "file_id", null: false + t.datetime "requested_at" + t.datetime "created_at" + t.datetime "updated_at" + t.string "user_type" + t.text "question" + end + + create_table "submissions", force: true do |t| + t.integer "exercise_id" + t.float "score" + t.integer "user_id" + t.datetime "created_at" + t.datetime "updated_at" + t.string "cause" + t.string "user_type" + end + + create_table "teams", force: true do |t| + t.string "name" + t.datetime "created_at" + t.datetime "updated_at" + end + + create_table "testruns", force: true do |t| + t.boolean "passed" + t.text "output" + t.integer "file_id" + t.integer "submission_id" + t.datetime "created_at" + t.datetime "updated_at" + end + +end \ No newline at end of file From 81fe1f1f14a5c2e00ce45968c2e4c4f920d92cc2 Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Wed, 8 Jun 2016 14:07:34 +0200 Subject: [PATCH 21/30] fix end-line of schema.rb --- db/schema.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/schema.rb b/db/schema.rb index f519dfe1..104a1469 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -217,4 +217,4 @@ ActiveRecord::Schema.define(version: 20160512131539) do t.datetime "updated_at" end -end \ No newline at end of file +end From 1e4ab7cabe2ea052d4c1251a7c6c7549559b4057 Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Fri, 10 Jun 2016 11:54:11 +0200 Subject: [PATCH 22/30] py_unit_adapter now also counts errors, not just failures --- lib/py_unit_adapter.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/py_unit_adapter.rb b/lib/py_unit_adapter.rb index f7f98dae..23b86ae9 100644 --- a/lib/py_unit_adapter.rb +++ b/lib/py_unit_adapter.rb @@ -1,6 +1,6 @@ class PyUnitAdapter < TestingFrameworkAdapter COUNT_REGEXP = /Ran (\d+) test/ - FAILURES_REGEXP = /FAILED \(failures=(\d+)\)/ + FAILURES_REGEXP = /FAILED \((failures)|(errors)=(\d+)\)/ ASSERTION_ERROR_REGEXP = /AssertionError:\s(.*)/ def self.framework_name @@ -10,7 +10,7 @@ class PyUnitAdapter < TestingFrameworkAdapter def parse_output(output) count = COUNT_REGEXP.match(output[:stderr]).captures.first.to_i matches = FAILURES_REGEXP.match(output[:stderr]) - failed = matches ? matches.captures.try(:first).to_i : 0 + failed = matches ? matches.captures.try(:third).to_i : 0 error_matches = ASSERTION_ERROR_REGEXP.match(output[:stderr]).try(:captures) || [] {count: count, failed: failed, error_messages: error_matches} end From 74b33492cb58a25c2efca4fff1f4a9c52c14dd4c Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Tue, 14 Jun 2016 10:42:15 +0200 Subject: [PATCH 23/30] fixed python failure regex. --- lib/py_unit_adapter.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/py_unit_adapter.rb b/lib/py_unit_adapter.rb index 23b86ae9..11b8cb09 100644 --- a/lib/py_unit_adapter.rb +++ b/lib/py_unit_adapter.rb @@ -1,6 +1,6 @@ class PyUnitAdapter < TestingFrameworkAdapter COUNT_REGEXP = /Ran (\d+) test/ - FAILURES_REGEXP = /FAILED \((failures)|(errors)=(\d+)\)/ + FAILURES_REGEXP = /FAILED \((failures|errors)=(\d+)\)/ ASSERTION_ERROR_REGEXP = /AssertionError:\s(.*)/ def self.framework_name @@ -10,7 +10,7 @@ class PyUnitAdapter < TestingFrameworkAdapter def parse_output(output) count = COUNT_REGEXP.match(output[:stderr]).captures.first.to_i matches = FAILURES_REGEXP.match(output[:stderr]) - failed = matches ? matches.captures.try(:third).to_i : 0 + failed = matches ? matches.captures.try(:second).to_i : 0 error_matches = ASSERTION_ERROR_REGEXP.match(output[:stderr]).try(:captures) || [] {count: count, failed: failed, error_messages: error_matches} end From f2e2c232e48b42e5c3e7c70299c1e41466ddfc35 Mon Sep 17 00:00:00 2001 From: yqbk Date: Tue, 14 Jun 2016 17:01:50 +0200 Subject: [PATCH 24/30] round result to fixed 2 digits --- app/assets/javascripts/editor.js.erb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb index 0bb22853..10123521 100644 --- a/app/assets/javascripts/editor.js.erb +++ b/app/assets/javascripts/editor.js.erb @@ -707,7 +707,8 @@ $(function() { var score = $('#score').data('score'); var maxium_score = $('#score').data('maximum-score'); if (score >= 0 && score <= maxium_score && maxium_score >0 ) { - var percentage_score = score / maxium_score * 100 + var rounded_number = (score / maxium_score ).toFixed(2); + var percentage_score = rounded_number * 100 $('.score').html(percentage_score + '%'); } else { From d5b78c29da39c15df6a61e7de1da83cf2b3f1e63 Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Tue, 14 Jun 2016 17:19:52 +0200 Subject: [PATCH 25/30] Fixed rounding issue caused by JavaScript and the conversion to String. --- app/assets/javascripts/editor.js.erb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb index 10123521..50217b1f 100644 --- a/app/assets/javascripts/editor.js.erb +++ b/app/assets/javascripts/editor.js.erb @@ -707,8 +707,7 @@ $(function() { var score = $('#score').data('score'); var maxium_score = $('#score').data('maximum-score'); if (score >= 0 && score <= maxium_score && maxium_score >0 ) { - var rounded_number = (score / maxium_score ).toFixed(2); - var percentage_score = rounded_number * 100 + var percentage_score = (score / maxium_score * 100 ).toFixed(2); $('.score').html(percentage_score + '%'); } else { From a1ead9658e22f413eadd719a1c251bfbb49c9bce Mon Sep 17 00:00:00 2001 From: tstaubitz Date: Tue, 14 Jun 2016 17:27:15 +0200 Subject: [PATCH 26/30] Update de.yml --- config/locales/de.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/de.yml b/config/locales/de.yml index 30f4f7ef..ae7fb930 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -212,7 +212,7 @@ de: exercise_deadline_passed: 'Die Abgabefrist für diese Aufgabe ist bereits abgelaufen.' tooltips: 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 Punkten können nur bis zum Ablauf der Abgabefrist an die E-Learning-Plattform übertragen werden.' + 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." editor_file_tree: file_root: Dateien From 8ddf1e158e02410874fe4354ae6eb3067f2cdc2e Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Tue, 14 Jun 2016 17:53:54 +0200 Subject: [PATCH 27/30] Fixed background and pen coloring on client side (javascript). See: https://github.com/openHPI/codeocean/issues/59 Kudos to waywwaard. --- app/assets/javascripts/turtle.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/turtle.js b/app/assets/javascripts/turtle.js index f2fa184b..ddbb27eb 100644 --- a/app/assets/javascripts/turtle.js +++ b/app/assets/javascripts/turtle.js @@ -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(); From 894f8abda233fd00dd0efe6bcb2b2cd704592f63 Mon Sep 17 00:00:00 2001 From: yqbk Date: Wed, 15 Jun 2016 12:03:34 +0200 Subject: [PATCH 28/30] round result to fixed 0 digits in percentage output --- app/assets/javascripts/editor.js.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb index 50217b1f..f000a23a 100644 --- a/app/assets/javascripts/editor.js.erb +++ b/app/assets/javascripts/editor.js.erb @@ -707,7 +707,7 @@ $(function() { var score = $('#score').data('score'); var maxium_score = $('#score').data('maximum-score'); if (score >= 0 && score <= maxium_score && maxium_score >0 ) { - var percentage_score = (score / maxium_score * 100 ).toFixed(2); + var percentage_score = (score / maxium_score * 100 ).toFixed(0); $('.score').html(percentage_score + '%'); } else { From fbb83e3057ddb4fe01c77badb8d637bc8df4e618 Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Thu, 16 Jun 2016 11:38:16 +0200 Subject: [PATCH 29/30] fix comparison problem caused by javascript comparisons based on Strings. ("1.00" <= "1.0" --> false) --- app/assets/javascripts/editor.js.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb index f000a23a..1e64195e 100644 --- a/app/assets/javascripts/editor.js.erb +++ b/app/assets/javascripts/editor.js.erb @@ -704,8 +704,8 @@ $(function() { }; var renderScore = function() { - var score = $('#score').data('score'); - var maxium_score = $('#score').data('maximum-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 + '%'); From 9e644563e3eae71b48b990323c3d9fd545628cf9 Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Thu, 16 Jun 2016 11:39:13 +0200 Subject: [PATCH 30/30] adapt regex for py_unit_adapter once more... hopefully we got all cases now. --- lib/py_unit_adapter.rb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/py_unit_adapter.rb b/lib/py_unit_adapter.rb index 11b8cb09..1ff5cd98 100644 --- a/lib/py_unit_adapter.rb +++ b/lib/py_unit_adapter.rb @@ -1,6 +1,7 @@ class PyUnitAdapter < TestingFrameworkAdapter COUNT_REGEXP = /Ran (\d+) test/ - FAILURES_REGEXP = /FAILED \((failures|errors)=(\d+)\)/ + FAILURES_REGEXP = /FAILED \(.*failures=(\d+).*\)/ + ERRORS_REGEXP = /FAILED \(.*errors=(\d+).*\)/ ASSERTION_ERROR_REGEXP = /AssertionError:\s(.*)/ def self.framework_name @@ -9,9 +10,11 @@ class PyUnitAdapter < TestingFrameworkAdapter def parse_output(output) count = COUNT_REGEXP.match(output[:stderr]).captures.first.to_i - matches = FAILURES_REGEXP.match(output[:stderr]) - failed = matches ? matches.captures.try(:second).to_i : 0 - error_matches = ASSERTION_ERROR_REGEXP.match(output[:stderr]).try(:captures) || [] - {count: count, failed: failed, error_messages: error_matches} + failures_matches = FAILURES_REGEXP.match(output[:stderr]) + failed = failures_matches ? failures_matches.captures.try(:first).to_i : 0 + error_matches = ERRORS_REGEXP.match(output[:stderr]) + 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