A code autograder for student homework submissions
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
2.3 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. # [grade the stuff]
  46. # [save report to gradefile]
  47. # FileUtils.touch pendingfile
  48. # self.status = :graded
  49. # return grade summary string
  50. sleep rand / 2
  51. '100%'
  52. end
  53. def commit
  54. # TODO:
  55. # if status == :graded && File.exists? pendingfile
  56. # [copy gradefile to repo]
  57. # @course.backend.commit repo, <message>, <gradefile path>
  58. # FileUtils.rm pendingfile
  59. # end
  60. sleep rand / 2
  61. nil
  62. end
  63. private
  64. def repo
  65. File.join @root, 'repo'
  66. end
  67. def statusfile
  68. File.join @root, 'status.txt'
  69. end
  70. def gradefile
  71. File.join @root, 'grade.txt'
  72. end
  73. def pendingfile
  74. File.join @root, 'pending'
  75. end
  76. def revision
  77. @course.backend.revision repo
  78. end
  79. def rewind(date)
  80. log = @course.backend.log repo
  81. target = log.find { |commit| commit[:date] <= date }
  82. if target.nil?
  83. raise SubmissionError, "no commits before due date: #{student}"
  84. end
  85. rev = target[:rev]
  86. @course.backend.update repo, rev
  87. rev
  88. end
  89. end
  90. end