Browse Source

More SVN fetch code, grading.

master
Ben Kurtovic 8 years ago
parent
commit
ca45c8e105
6 changed files with 144 additions and 32 deletions
  1. +1
    -0
      lib/kgrader.rb
  2. +28
    -6
      lib/kgrader/backend/svn.rb
  3. +1
    -1
      lib/kgrader/course.rb
  4. +10
    -1
      lib/kgrader/filesystem.rb
  5. +70
    -0
      lib/kgrader/submission.rb
  6. +34
    -24
      lib/kgrader/task.rb

+ 1
- 0
lib/kgrader.rb View File

@@ -5,5 +5,6 @@ require_relative 'kgrader/course'
require_relative 'kgrader/errors'
require_relative 'kgrader/filesystem'
require_relative 'kgrader/roster'
require_relative 'kgrader/submission'
require_relative 'kgrader/task'
require_relative 'kgrader/util'

+ 28
- 6
lib/kgrader/backend/svn.rb View File

@@ -1,17 +1,39 @@
require 'open3'

module KGrader::Backend
class SVN

def initialize(filesystem, config)
def initialize(filesystem, course, config)
@fs = filesystem
@course = course
@config = config
end

def fetch(semester, assignment, student)
url = @config['url'] % {
:semester => semester, :assignment => assignment, :student => student }

def revision(repo)
# TODO
puts "[fetching #{student}: #{url}]"
-1
end

def clone(repo, semester, assignment, student)
url = get_url semester, assignment, student
run 'checkout', '--ignore-externals', url, repo
end

def update(repo)
run 'update', '--ignore-externals', '--accept', 'tf', repo
end

private
def run(*cmd)
Open3.capture2e('svn', *cmd)
end

def get_url(semester, assignment, student)
@config['url'] % {
:semester => semester,
:assignment => assignment,
:student => student
}
end
end
end

+ 1
- 1
lib/kgrader/course.rb View File

@@ -8,7 +8,7 @@ module KGrader

@config = @fs.load @fs.course_config(@name)
type = @config['backend']
@backend = KGrader::backend(type).new self, @config[type]
@backend = KGrader::backend(type).new @fs, self, @config[type]
@rosters = {}
@assignments = {}
rescue FilesystemError


+ 10
- 1
lib/kgrader/filesystem.rb View File

@@ -1,3 +1,4 @@
require 'json'
require 'yaml'

module KGrader
@@ -37,6 +38,10 @@ module KGrader
File.join desk, courseid, semester, '_roster.csv'
end

def submission(courseid, semester, assignment, student)
File.join desk, courseid, semester, assignment, student
end

# -------------------------------------------------------------------------

def courses
@@ -44,7 +49,7 @@ module KGrader
end

def assignments(courseid)
Dir[assignment courseid '*'].map! { |fn| File.basename File.dirname fn }
Dir[assignment courseid, '*'].map! { |fn| File.basename File.dirname fn }
end

def semesters(courseid)
@@ -55,6 +60,10 @@ module KGrader

def load(path)
case File.extname path
when '.txt'
File.read path
when '.json'
JSON.parse File.read(path)
when '.yml', '.yaml'
YAML.load File.read(path)
when '.csv'


+ 70
- 0
lib/kgrader/submission.rb View File

@@ -0,0 +1,70 @@
module KGrader
class Submission
attr_reader :course, :semester, :assignment, :student

def initialize(filesystem, course, semester, assignment, student)
@fs = filesystem
@course = course
@semester = semester
@assignment = assignment
@student = student

@root = @fs.submission @course.name, @semester, @assignment.name, student
@status = nil
end

def status
@status ||= @fs.load(statusfile).to_sym
end

def status=(new_status)
File.write statusfile, new_status
@status = new_status
end

def exists?
File.exists? statusfile
end

def create
FileUtils.mkdir_p @root
self.status = :init
end

def fetch(due)
if status == :init
@course.backend.clone repo, @semester, @assignment.id, @student
rewind due
self.status = :ungraded
else
oldrev = revision if status == :graded
self.status = :fetching
@course.backend.update repo
rewind due
self.status = revision == oldrev ? :graded : :ungraded
end
end

def grade
# TODO
# self.status = :graded
end

private
def statusfile
File.join @root, "status.txt"
end

def repo
File.join @root, "repo"
end

def revision
@course.backend.revision repo
end

def rewind(date)
# TODO
end
end
end

+ 34
- 24
lib/kgrader/task.rb View File

@@ -2,52 +2,62 @@ module KGrader
class Task

def initialize(filesystem, course, semester, assignment)
@fs = filesystem
@course = course
@semester = semester
@fs = filesystem
@course = course
@semester = semester

@assignment = @course.assignment assignment
@students = @course.roster(@semester).students
@students = @course.roster(@semester).students
end

def grade(options = {})
students = @students
students &= options[:students] unless options[:students].nil?

submissions = get_submissions options[:students]
due = options.fetch(:due, Time.now)
fetch = options.fetch(:fetch, true)
regrade = options.fetch(:regrade, false)

# TODO
puts "[grading]"
puts "course => #{@course.name}"
puts "semester => #{@semester}"
puts "assignment => #{@assignment.name}"
puts "students => #{students.join ', '}"
puts "due => #{due}"
puts "fetch => #{fetch}"
puts "regrade => #{regrade}"
puts
count = submissions.count
puts "[grading #{count} student#{'s' if count != 1}]"

fetch_students students if fetch
submissions.each do |sub|
unless sub.exists?
puts "[init #{sub.student}]"
sub.create
end
end

if fetch
submissions.each do |sub|
puts "[fetch #{sub.student}]"
sub.fetch due
end
end

submissions.each do |sub|
sub.status = :ungraded if regrade
if sub.status == :ungraded
puts "[grade #{sub.student}]"
sub.grade
end
end
end

def commit(options = {})
students = @students
students &= options[:students] unless options[:students].nil?
submissions = get_submissions options[:students]

# TODO
puts "[committing]"
puts "course => #{@course.name}"
puts "semester => #{@semester}"
puts "assignment => #{@assignment.name}"
puts "students => #{students.join ', '}"
puts "students => #{submissions.map { |sub| sub.student }.join ', '}"
end

private
def fetch_students(students)
students.each do |student|
@course.backend.fetch @semester, @assignment.id, student
def get_submissions(students)
students.nil? ? (students = @students) : (students &= @students)
students.map do |student|
Submission.new @fs, @course, @semester, @assignment, student
end
end
end


Loading…
Cancel
Save