The file_filter
program can enforce that a given assignment (likely 0) be completely submitted and have all components passing before submissions of any other assignments are accepted. A sample filter which would go in /u/csXXX/bin/file_filter and be designed to be called indirectly from the ISG file_filter
is:
#!/usr/bin/env perl -w use strict; # The required assignment and the current term. use constant LOGGED_ASSIGN => '00'; use constant TERM => '1095'; # The rejection error code, and corresponding filter message. use constant ERRCODE => 51; use constant REJMSG => 'Assignment ' . LOGGED_ASSIGN . ' has not been fully successfully submitted yet.'; # The course name, assignment and student id; guaranteed safe so untaint them. $ARGV[0] =~ /^(.*)$/; my $course = $1; $ARGV[1] =~ /^(.*)$/; my $assign = $1; $ARGV[2] =~ /^(.*)$/; my $student = substr($1, 0, 8); # Constants that technically depend on .submitrc settings; # should read .submitrc directly, but we aren't for simplicity. my $pubtestlog = "/u/$course/course/publictests/" . TERM . '/' . LOGGED_ASSIGN . '.completedrun.log'; # If this assignment is not the one that's required first, check if we need # to do filtering. unless ($assign eq LOGGED_ASSIGN) { my $passed = 0; if ( -e $pubtestlog ) { open( PTL, $pubtestlog ) or print "Cannot open log: $!\n" and exit ERRCODE; while(my $pubtestline = <PTL>) { # If this student has a perfect mark recorded, then the requirement # has been met; terminate the loop # NOTE: As we know the value of $student will not change for the # lifetime of this program, we set this regex to compile only once. if ($pubtestline =~ /^\s*\d+\s*${student}\s*\S*\s*([0-9.]+)\s*\/\s*([0-9.]+)\s*$/o) { if ($1 == $2) { $passed = 1; last; } } } close( PTL ); } # Unless the student passed the required assignment, reject all # submission attempts. unless ($passed) { print REJMSG . "\n"; exit ERRCODE; } } # Now re-call the main ISG filter; this environment variable was set by the # calling program, and again is known to be safe as a result. $ENV{'ISG_FILTER'} =~ /^(.*)$/; my $filter = $1; $ENV{'PATH'} =~ /^(.*)$/; $ENV{'PATH'} = $1; for my $arg (@ARGV) { $arg =~ /^(.*)$/; $arg = $1; } exec $filter, $ARGV[0], $ARGV[1], $ARGV[2], $ARGV[3], $ARGV[4];
This filter relies on marks being written to the mark list in the form $student:$mark/$total
, which is created by calls of the form writeToMarkList "$mark/$total"
inside of an RST suite's computeMarks script. This is done automatically for users of BitterSuite.