| @@ -27,6 +27,10 @@ kgrader uses rake as its command-line interface. | |||
| ### Setup | |||
| To show all known classes, semesters, and assignments: | |||
| rake list | |||
| To load a roster for a course semester: | |||
| rake roster cs123 sp2016 myroster.csv | |||
| @@ -43,10 +47,6 @@ After verifying that everything looks good, push the grade reports with: | |||
| ### Housekeeping | |||
| To show all known classes, semesters, and assignments: | |||
| rake list | |||
| To do some basic cleanup (i.e., trash uncommitted grading attempts, or reset | |||
| messy internal state after a bad run): | |||
| @@ -63,7 +63,7 @@ but also delete checked-out student repos and roster files -- dangerous!): | |||
| To specify the semester, instead of the inferred current one: | |||
| rake grade cs123 mp1 semester=sp2016 | |||
| rake grade cs123 mp1 semester=sp16 | |||
| To set a cutoff date after which commits will be ignored: | |||
| @@ -1 +1,2 @@ | |||
| require_relative 'kgrader/cli' | |||
| require_relative 'kgrader/util' | |||
| @@ -5,6 +5,43 @@ module KGrader | |||
| @dir = dir | |||
| end | |||
| def list | |||
| # TODO | |||
| puts "[list]" | |||
| end | |||
| def roster(course, semester, rosterfile) | |||
| # TODO | |||
| puts "[installing roster: c=#{course} s=#{semester} rf=#{rosterfile}]" | |||
| end | |||
| def grade(course, semester, assignment, options = {}) | |||
| # TODO | |||
| puts "[grading c=#{course} s=#{semester} a=#{assignment}]" | |||
| puts " - [students=#{options[:students].inspect}]" | |||
| puts " - [due=#{options[:due].inspect}]" | |||
| puts " - [fetch=#{options.fetch(:fetch, true).inspect}]" | |||
| puts " - [regrade=#{options.fetch(:regrade, false).inspect}]" | |||
| end | |||
| def commit(course, semester, assignment, options = {}) | |||
| # TODO | |||
| puts "[committing c=#{course} s=#{semester} a=#{assignment}]" | |||
| puts " - [students=#{options[:students].inspect}]" | |||
| end | |||
| def clean | |||
| # TODO: also purge uncommitted grades | |||
| reset_jail | |||
| end | |||
| def clobber | |||
| # TODO: confirm | |||
| reset_jail | |||
| reset_desk | |||
| end | |||
| private | |||
| def reset_jail | |||
| jail_dir = File.join(@dir, 'jail') | |||
| FileUtils.rm_rf jail_dir | |||
| @@ -0,0 +1,32 @@ | |||
| require 'date' | |||
| module KGrader | |||
| def self.parse_args(raw, num, keywords) | |||
| args = [] | |||
| options = {} | |||
| raw.each do |arg| | |||
| if arg.include? '=' | |||
| key, val = arg.split('=', 2) | |||
| key = key.to_sym | |||
| yield "unknown keyword #{key}" unless keywords.include? key | |||
| options[key] = case keywords[key] | |||
| when :string | |||
| val | |||
| when :bool | |||
| %w(true yes 1 t y).include? val.downcase | |||
| when :array | |||
| val.split(",").map! { |x| x.strip.downcase } | |||
| when :datetime | |||
| DateTime.parse(val) | |||
| end | |||
| else | |||
| args << arg | |||
| end | |||
| end | |||
| yield "too few arguments" if args.size < num | |||
| yield "too many arguments" if args.size > num | |||
| return args, options | |||
| end | |||
| end | |||
| @@ -1,50 +1,56 @@ | |||
| require_relative 'lib/kgrader' | |||
| def get_cli | |||
| def cli | |||
| KGrader::CLI.new Rake.application.original_dir | |||
| end | |||
| task :clean do | |||
| cli = get_cli | |||
| # TODO: also purge uncommitted grades | |||
| cli.reset_jail | |||
| def parse_args(num, keywords) | |||
| args, options = KGrader::parse_args ARGV.drop(1), num, keywords do |err| | |||
| abort err | |||
| end | |||
| args.each { |arg| task arg.to_sym {} } | |||
| args + [options] | |||
| end | |||
| task :clobber do | |||
| cli = get_cli | |||
| # TODO: confirm | |||
| cli.reset_jail | |||
| cli.reset_desk | |||
| task :default => :help do ; end | |||
| task :help do | |||
| puts %{usage: | |||
| - rake list | |||
| - rake roster <course> <semester> <rosterfile> | |||
| - rake grade <course> <assignment> [semester=<...>] [students=<...>] | |||
| [due=<...>] [fetch=<yes/no>] [regrade=<yes/no>] | |||
| - rake commit <course> <assignment> [semester=<...>] [students=<...>] | |||
| - rake clean | |||
| - rake clobber} | |||
| end | |||
| task :list do | |||
| # TODO | |||
| puts '[list!]' | |||
| cli.list | |||
| end | |||
| task :roster do | |||
| # TODO: [course, assignment, rosterfile] | |||
| puts '[installing roster!]' | |||
| course, semester, rosterfile = parse_args 3 | |||
| cli.roster course, semester, rosterfile | |||
| end | |||
| task :grade do | |||
| puts ARGV.inspect | |||
| course = ARGV[1] | |||
| assignment = ARGV[2] | |||
| course, assignment, options = parse_args 2, | |||
| { :semester => :string, :students => :array, :due => :datetime, | |||
| :fetch => :bool, :regrade => :bool } | |||
| cli.grade course, options[:semester], assignment, options | |||
| end | |||
| task course.to_sym {} | |||
| task assignment.to_sym {} | |||
| task :commit do | |||
| course, assignment, options = parse_args 2, | |||
| { :semester => :string, :students => :array } | |||
| cli.commit course, options[:semester], assignment, options | |||
| end | |||
| # TODO | |||
| puts "Grading #{assignment} for #{course}..." | |||
| puts " - semester:" | |||
| puts " - due:" | |||
| puts " - fetch:" | |||
| puts " - students:" | |||
| puts " - regrade:" | |||
| task :clean do | |||
| cli.clean | |||
| end | |||
| task :commit do | |||
| # TODO: [course, assignment], semester=, students= | |||
| puts '[committing!]' | |||
| task :clobber do | |||
| cli.clobber | |||
| end | |||
| @@ -1 +1 @@ | |||
| Subproject commit a0a432cb96f38c230355e3e5b12bbf131beb04bd | |||
| Subproject commit 54398ad4a16ac3d9f7344ecf680f4dd167e05818 | |||