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/errors'
require_relative 'kgrader/filesystem' require_relative 'kgrader/filesystem'
require_relative 'kgrader/roster' require_relative 'kgrader/roster'
require_relative 'kgrader/submission'
require_relative 'kgrader/task' require_relative 'kgrader/task'
require_relative 'kgrader/util' require_relative 'kgrader/util'

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

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

module KGrader::Backend module KGrader::Backend
class SVN class SVN


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


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

def revision(repo)
# TODO # 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 end
end end

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

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


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


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

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


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


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

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


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


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


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


def load(path) def load(path)
case File.extname path case File.extname path
when '.txt'
File.read path
when '.json'
JSON.parse File.read(path)
when '.yml', '.yaml' when '.yml', '.yaml'
YAML.load File.read(path) YAML.load File.read(path)
when '.csv' 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 class Task


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


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


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

submissions = get_submissions options[:students]
due = options.fetch(:due, Time.now) due = options.fetch(:due, Time.now)
fetch = options.fetch(:fetch, true) fetch = options.fetch(:fetch, true)
regrade = options.fetch(:regrade, false) 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 end


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


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


private 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 end
end end


Loading…
Cancel
Save