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.

86 lignes
2.2 KiB

  1. require 'ruby-progressbar'
  2. module KGrader
  3. class Task
  4. def initialize(filesystem, course, semester, assignment, students = nil)
  5. @fs = filesystem
  6. @course = course
  7. @semester = semester
  8. @assignment = @course.assignment assignment
  9. @submissions = get_submissions students
  10. end
  11. def grade(options = {})
  12. due = options.fetch(:due, Time.now)
  13. fetch = options.fetch(:fetch, true)
  14. regrade = options.fetch(:regrade, false)
  15. superscore = options.fetch(:superscore, false)
  16. if options.include?(:due) && !fetch
  17. raise TaskError, "can't set a new due date without fetching"
  18. end
  19. if regrade && superscore
  20. raise TaskError, "can't regrade and superscore at the same time"
  21. end
  22. prepare
  23. subtask 'setup' do |sub|
  24. sub.create unless sub.exists?
  25. end
  26. if fetch
  27. subtask 'fetch' do |sub|
  28. sub.fetch due
  29. end
  30. end
  31. subtask 'grade' do |sub|
  32. if sub.status == :init || sub.status == :fetching
  33. next 'skip (need to fetch first)'
  34. elsif sub.status == :graded && !regrade && !superscore
  35. next
  36. else
  37. sub.grade superscore
  38. end
  39. end
  40. end
  41. def commit
  42. prepare
  43. subtask 'commit', &:commit
  44. end
  45. private
  46. def get_submissions(students)
  47. roster = @course.roster(@semester).students
  48. students.nil? ? (students = roster) : (students &= roster)
  49. students.map do |student|
  50. Submission.new @fs, @course, @semester, @assignment, student
  51. end
  52. end
  53. def student_len
  54. @student_len ||= @submissions.map { |sub| sub.student.length }.max
  55. end
  56. def prepare
  57. @course.backend.prepare @semester, @assignment
  58. end
  59. def subtask(name)
  60. progress = ProgressBar.create title: name, total: @submissions.size,
  61. throttle_rate: 0, format: '%t [%b>%i] %j%% %e '
  62. @submissions.each.with_index do |sub, i|
  63. job = "#{name} [#{sub.student.ljust student_len}]"
  64. progress.title = "#{job}:"
  65. result = yield sub
  66. progress.title = name if i == @submissions.size - 1
  67. progress.log "#{job}#{': ' if result}#{result}" if result
  68. progress.increment
  69. end
  70. end
  71. end
  72. end