Browse Source

Add log files; more on report generation.

master
Ben Kurtovic 8 years ago
parent
commit
80ba8be05f
4 changed files with 93 additions and 15 deletions
  1. +13
    -3
      lib/kgrader/assignment.rb
  2. +2
    -1
      lib/kgrader/filesystem.rb
  3. +5
    -2
      lib/kgrader/jail.rb
  4. +73
    -9
      lib/kgrader/submission.rb

+ 13
- 3
lib/kgrader/assignment.rb View File

@@ -25,7 +25,9 @@ module KGrader
end

def tests
@config['grade']
@tests ||= @config['grade'].map do |it|
{ :name => it.keys.first, :max => it.values.first }
end
end

def report
@@ -33,12 +35,16 @@ module KGrader
end

def commit_message(student)
default = "adding grade report for #{name}: {student}"
template = @config['commit']['message'].clone || default
default = "Adding grade report for #{title}: {student}"
template = (@config['commit']['message'] || default).clone
template['{student}'] = student
template
end

def extra_comments
@config['commit']['comments'] || []
end

private
def verify_config
%w(stage build grade).each do |key|
@@ -59,5 +65,9 @@ module KGrader

{ :provided => provided, :graded => graded }
end

def title
@config['title'] || @name
end
end
end

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

@@ -77,7 +77,8 @@ module KGrader
Dir[File.join desk_dir, '*', '*', '*', '*', 'status.txt'].each do |fn|
File.write fn, "ungraded" if File.read(fn) == "graded"
end
FileUtils.rm_rf Dir[File.join desk_dir, '*', '*', '*', '*', 'pending']
FileUtils.rm_f Dir[File.join desk_dir, '*', '*', '*', '*', 'pending']
FileUtils.rm_f Dir[File.join desk_dir, '*', '*', '*', '*', '*.log']
end

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


+ 5
- 2
lib/kgrader/jail.rb View File

@@ -17,13 +17,16 @@ module KGrader
FileUtils.cp source, File.join(@root, target)
end

def exec(command)
def exec(command, logpath)
pid = Process.fork do
fp = File.open(logpath, 'w+')
Dir.chdir @root
# TODO: rlimit in exec, umask?
Process.exec command
Process.exec command, :in => :close, :out => fp, :err => fp,
:close_others => true
end
Process.waitpid pid, 0
$?.exited? && $?.exitstatus == 0
end
end
end

+ 73
- 9
lib/kgrader/submission.rb View File

@@ -48,14 +48,13 @@ module KGrader
end

def grade
self.status = :ungraded
grade_prep
stage
build
test
save
# self.status = :graded # UNCOMMENT
# @fs.jail.reset # UNCOMMENT
# TODO: return grade summary string
grade_post
@summary
end

def commit
@@ -85,6 +84,14 @@ module KGrader
File.join @root, 'pending'
end

def buildlog
File.join @root, 'build.log'
end

def testlog
File.join @root, 'test.log'
end

def revision
@course.backend.revision repo
end
@@ -101,10 +108,23 @@ module KGrader
rev
end

def stage
def grade_prep
@failure = false
@comments = []
@summary = nil
@tests = []

self.status = :ungraded
FileUtils.rm_f [buildlog, testlog]
@fs.jail.reset
@fs.jail.init

@assignment.tests.each do |test|
@tests.push({ :name => test[:name], :max => test[:max], :score => 0 })
end
end

def stage
@assignment.manifest[:provided].each do |entry|
@fs.jail.stage entry[:path], entry[:name]
end
@@ -115,19 +135,63 @@ module KGrader

def build
@assignment.build_steps.each do |command|
@fs.jail.exec command
return build_failure unless @fs.jail.exec command, buildlog
end
end

def test
@assignment.tests.each do |script|
# TODO: execute script in jail
return if @failure
@assignment.tests.each do |test|
# TODO: execute script in jail and update @test/@comments; out testlog
end
end

def save
# TODO: save gradefile
File.write gradefile, generate_report
FileUtils.touch pendingfile
end

def grade_post
# self.status = :graded # TODO: uncomment
# @fs.jail.reset # TODO: uncomment
@summary = generate_summary unless @summary
end

def build_failure
@failure = true
@comments.push "failed to compile"
@summary = "#{format_points 0, max_score}: failed to compile"
end

def generate_report
# TODO
@tests
@assignment.extra_comments
end

def generate_summary
tests = @tests.each do |test|
"#{test[:score].to_s.rjust get_span(test[:max])}/#{test[:max]}"
end.join ', '
"#{format_points score, max_score}: #{tests}"
end

def score
@tests.reduce(0) { |sum, t| sum + t[:score] }
end

def max_score
@tests.reduce(0) { |sum, t| sum + t[:max] }
end

def format_points(score, max)
percent = (score.to_f * 100 / max).round.to_s.rjust 3
span = get_span max
"#{percent}% (#{score.to_s.rjust span}/#{max.to_s.rjust span})"
end

def get_span(max)
(Math.log10(max) + 1).to_i
end
end
end

Loading…
Cancel
Save