Skip to content
This repository was archived by the owner on Jan 7, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 59 additions & 26 deletions app/controllers/assessments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class AssessmentsController < ApplicationController
# this is inherited from ApplicationController
before_action :set_assessment, except: [:index, :new, :create, :installAssessment,
:importAsmtFromTar, :importAssessment,
:log_submit, :local_submit, :autograde_done]
:log_submit, :local_submit, :autograde_done, :multiImport]
before_action :set_submission, only: [:viewFeedback]

# We have to do this here, because the modules don't inherit ApplicationController.
Expand Down Expand Up @@ -113,31 +113,45 @@ def importAsmtFromTar
tarFile = File.new(tarFile.open, "rb")
tar_extract = Gem::Package::TarReader.new(tarFile)
tar_extract.rewind
is_valid_tar, asmt_name = valid_asmt_tar(tar_extract)
tar_extract.close
unless is_valid_tar
flash[:error] = "Invalid tarball. Please verify the existence of configuration files."
redirect_to(action: "installAssessment")
return
end
rescue StandardError => e
flash[:error] = "Error while reading the tarball -- #{e.message}."
redirect_to(action: "installAssessment")
return
end

# Check if the assessment already exists.
unless @course.assessments.find_by(name: asmt_name).nil?
flash[:error] = "An assessment with the same name already exists for the course. Please use a different name."
redirect_to(action: "installAssessment") && return
assessmentNames = []
tar_extract.each do |entry|
if entry.directory? && entry.full_name.chomp!("/").count("/") == 0
assessmentNames.push(entry.full_name)
end
end

assessmentNames.each do |asmt_name|
unless @course.assessments.find_by(name: asmt_name).nil?
flash[:error] = "An assessment with the same name #{asmt_name} already exists for the course. Please use a different name."
redirect_to(action: "installAssessment") && return
end

tar_extract.rewind
is_valid_tar, current = valid_asmt_tar(tar_extract,asmt_name)

unless is_valid_tar
flash[:error] = "Invalid assessment. Please verify the existence of configuration files. in the #{current} folder"
redirect_to(action: "installAssessment") && return
end





# If all requirements are satisfied, extract assessment files.
begin
course_root = Rails.root.join("courses", @course.name)
tar_extract.rewind
tar_extract.each do |entry|
relative_pathname = entry.full_name
# abort relative_pathname.inspect
next unless entry.full_name.split("/")[0] == asmt_name
if entry.directory?
FileUtils.mkdir_p(File.join(course_root, relative_pathname),
mode: entry.header.mode, verbose: false)
Expand All @@ -154,13 +168,29 @@ def importAsmtFromTar
end
end
tar_extract.close

File.open(File.join(course_root, asmt_name, asmt_name + ".rb"), "wb") do |f|
f.write "require \"AssessmentBase.rb\"

module #{asmt_name.capitalize}
include AssessmentBase

def assessmentInitialize(course)
super(\"#{asmt_name}\",course)
@problems = []
end

end"
end
rescue StandardError => e
flash[:error] = "Error while extracting tarball to server -- #{e.message}."
redirect_to(action: "installAssessment") && return
end

params[:assessment_name] = asmt_name
importAssessment && return
importAssessment
end
redirect_to(@course)
end

# importAssessment - Imports an existing assessment from local file.
Expand All @@ -172,7 +202,13 @@ def importAssessment
@assessment.load_yaml # this will save the assessment
@assessment.construct_folder # make sure there's a handin folder, just in case
@assessment.load_config_file # only call this on saved assessments
redirect_to([@course, @assessment])
end

action_auth_level :multiImport, :instructor
def multiImport
if request.post?
importAsmtFromTar
end
end

# create - Creates an assessment from an assessment directory
Expand Down Expand Up @@ -352,6 +388,7 @@ def export




action_auth_level :destroy, :instructor
def destroy
for submission in @assessment.submissions do
Expand Down Expand Up @@ -784,25 +821,20 @@ def edit_assessment_params
# a valid assessment tar has a single root directory that's named after the
# assessment, containing an assessment yaml file and an assessment ruby file
#
def valid_asmt_tar(tar_extract)
asmt_name = nil
asmt_rb_exists = false
def valid_asmt_tar(tar_extract, asmt_name)
asmt_yml_exists = false
tar_extract.each do |entry|
pathname = entry.full_name
next if pathname.start_with? "."
pathname.chomp!("/") if entry.directory?
next if !entry.full_name.split("/")[0] == asmt_name
next if pathname == asmt_name

# nested directories are okay
if entry.directory? && pathname.count("/") == 0
return false if asmt_name
asmt_name = pathname
else
return false unless asmt_name
asmt_rb_exists = true if pathname == "#{asmt_name}/#{asmt_name}.rb"
asmt_yml_exists = true if pathname == "#{asmt_name}/#{asmt_name}.yml"
end
return false unless asmt_name
asmt_yml_exists = true if pathname == "#{asmt_name}/#{asmt_name}.yml"
end
[asmt_rb_exists && asmt_yml_exists && (!asmt_name.nil?), asmt_name]
[asmt_yml_exists && (!asmt_name.nil?), asmt_name]
end

# methods for sending different file packages depending on what button was clicked
Expand Down Expand Up @@ -905,3 +937,4 @@ def exportStudentFiles()
end
end
end

1 change: 1 addition & 0 deletions app/models/submission.rb
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ def save_additional_form_fields(params)
if assessment.is_section_dependant
form_hash["section"] = (assessment.lecture?) ? course_user_datum.lecture : course_user_datum.section
end
form_hash["ip"] = self.submitter_ip
self.settings = form_hash.to_json
self.save!
end
Expand Down
4 changes: 4 additions & 0 deletions app/views/assessments/installAssessment.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
<h4><li>Create from scratch</h4>
<h5>You can create a new assessment from scratch using our
<%= link_to "Assessment Builder", new_course_assessment_path %>. </h5>

<h4><li>Import Multiple Assessments</h4>
<h5>You can Multiple Assessmets Using The
<%= link_to "Assessment Importer", multiImport_course_assessments_path %>. </h5>
</div>

43 changes: 43 additions & 0 deletions app/views/assessments/multiImport.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<% @title = "Mutliple Assessment Importer" %>

<% content_for :javascripts do %>
<script type="application/javascript">
jQuery(function() {
$importTarballForm = $('#import-tarball-form');
$tarballFilenameInput = $('#tarFile-name');

/* two-way-bind newDayField with daysField */
$tarballFilenameInput.on('change', function() {
$importTarballForm.submit();
});
});
</script>
<% end %>



<div class="section">
<h4><li>Import from tarball</h4>
<h5>You can import a tarball with the assessment directory.</h5>
<%= form_tag({action: :multiImport}, multipart: true, id: "import-tarball-form") do %>
<div class="file-field input-field" style="margin: 1.5rem 0 !important">
<div class="btn">
<span>Browse</span>
<%= file_field_tag "tarFile" %>
</div>
<div class="file-path-wrapper">
<%= text_field_tag "tarFile-name", "Upload Assessment Tarball", class: "file-path validate" %>
</div>
</div>
<% end %>
</div>

<div class="section">
<h4>Guide for making the tar ball</h4>
<p>a starter tarball for this method of importing can be found <a href="https://github.com/UBAutograding/Autolab/raw/multi-assessment-import/examples/multiple%20assessment%20import%20starter.tar/">here</a></p>
<p>please do not rename the handin directory in the YAML file</p>
<p>the top level folder names must match the name of the assessment in the YAML file as well as the name of the YAML file itself</p>
<p>if the assessment does not have an autograded componet do not include autograde-Makefile or autograde.tar</p>
<p>if the assessment does have an autograded componet include autograde-Makefile and autograde.tar</p>
<p>please do not add any other files or directories than are what included in the starter</p>
</div>
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@
get "installAssessment"
post "importAssessment"
post "importAsmtFromTar"
post "multiImport"
get "multiImport"
end
end

Expand Down
4 changes: 0 additions & 4 deletions examples/README

This file was deleted.

94 changes: 94 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Examples

this directory contains examples for a few features of the autograder

## Assessments

The Hello folder and Hello.tar contain various examples of different styles of Assessments


## Importing Assessments

whether you are importing one or more assessments the procedure is the same

multiple assessment import starter.tar is the starter file for importing one or more assessments


```bash
multiple assessment import starter.tar
├── assessment1
│ ├── handin
│ ├── assessment1.yml
Comment thread
Searay-330 marked this conversation as resolved.
Outdated
│ ├── autograde.tar
│ └── autograde-Makefile
└── assessment2
├── handin
└── assessment1.yml

```

the top level must consist of folders named the same as what you will be naming the course (url name not display name)
Comment thread
Searay-330 marked this conversation as resolved.
Outdated

assessment1 is an example of an assessment with an autograding component

the handin folder while has to remain present and named the same is not currently used for anything but will be in the future for adding submissions to new assessments.

assessment1.yml
```YAML
---
general:
Comment thread
Searay-330 marked this conversation as resolved.
name: assessment1
Comment thread
Searay-330 marked this conversation as resolved.
description: ''
display_name: ASSESSMENT WITH AUTOGRADING
handin_filename: handin.zip
handin_directory: handin
max_grace_days: 0
handout: ''
writeup: ''
max_submissions: -1
disable_handins: false
max_size: 2
has_svn: false
category_name: Lab Activities
problems:
- name: Score
description: ''
max_score: 3.0
optional: false
autograder:
autograde_timeout: 180
autograde_image: autograding_image
release_score: true
```
the only hiccup on this file is that the name field must be the same as the file and top level folder name
Comment thread
Searay-330 marked this conversation as resolved.
Outdated

problems even if there is only 1 must be denoted as a list
~~~
autograde-Makefile, autograde.tar
~~~
will contain your assessment files to ship to tango and be graded with naming is standardized to avoid complications.

assessment2 is an assessment without autograding same rules apply as assessment1 the only difference being the assessment.yml file does not contain the autograder section

```YAML
---
general:
name: assessment2
description: ''
display_name: ASSESSMENT WITH OUT AUOTGRADING
handin_filename: objects.zip
handin_directory: handin
max_grace_days: 0
handout: ''
writeup: ''
max_submissions: -1
disable_handins: false
max_size: 5
has_svn: false
category_name: RecitationQuiz
problems:
- name: quiz02
description: ''
max_score: 100.0
optional: false
```
Binary file not shown.