A code autograder for student homework submissions
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

123 lignes
2.6 KiB

  1. module KGrader
  2. class Submission
  3. attr_reader :course, :semester, :assignment, :student
  4. def initialize(filesystem, course, semester, assignment, student)
  5. @fs = filesystem
  6. @course = course
  7. @semester = semester
  8. @assignment = assignment
  9. @student = student
  10. @root = @fs.submission @course.name, @semester, @assignment.name, student
  11. @status = nil
  12. end
  13. def status
  14. @status ||= @fs.load(statusfile).to_sym
  15. end
  16. def status=(new_status)
  17. File.write statusfile, new_status
  18. @status = new_status
  19. end
  20. def exists?
  21. File.exists? statusfile
  22. end
  23. def create
  24. FileUtils.mkdir_p @root
  25. self.status = :init
  26. nil
  27. end
  28. def fetch(due)
  29. if status == :init
  30. @course.backend.clone repo, @semester, @assignment.id, @student
  31. rewind due
  32. self.status = :ungraded
  33. else
  34. oldrev = revision if status == :graded
  35. self.status = :fetching
  36. @course.backend.update repo
  37. newrev = rewind due
  38. self.status = newrev == oldrev ? :graded : :ungraded
  39. end
  40. nil
  41. end
  42. def grade
  43. # TODO:
  44. # self.status = :ungraded
  45. stage
  46. # [grade the stuff]
  47. # [save report to gradefile]
  48. # @fs.jail.reset
  49. # FileUtils.touch pendingfile
  50. # self.status = :graded
  51. # return grade summary string
  52. sleep rand / 2
  53. '100%'
  54. end
  55. def commit
  56. # TODO:
  57. # if status == :graded && File.exists? pendingfile
  58. # [copy gradefile to repo]
  59. # @course.backend.commit repo, <message>, <gradefile path>
  60. # FileUtils.rm pendingfile
  61. # end
  62. sleep rand / 2
  63. nil
  64. end
  65. private
  66. def repo
  67. File.join @root, 'repo'
  68. end
  69. def statusfile
  70. File.join @root, 'status.txt'
  71. end
  72. def gradefile
  73. File.join @root, 'grade.txt'
  74. end
  75. def pendingfile
  76. File.join @root, 'pending'
  77. end
  78. def revision
  79. @course.backend.revision repo
  80. end
  81. def rewind(date)
  82. log = @course.backend.log repo
  83. target = log.find { |commit| commit[:date] <= date }
  84. if target.nil?
  85. raise SubmissionError, "no commits before due date: #{student}"
  86. end
  87. rev = target[:rev]
  88. @course.backend.update repo, rev
  89. rev
  90. end
  91. def stage
  92. @fs.jail.reset
  93. @fs.jail.init
  94. @assignment.manifest[:provided].each do |entry|
  95. @fs.jail.stage entry[:path], entry[:name]
  96. end
  97. @assignment.manifest[:graded].each do |entry|
  98. @fs.jail.stage File.join(repo, entry[:name]), entry[:name]
  99. end
  100. end
  101. end
  102. end