Thanks to the many TA's (particularly David Newman) who have used these tools
and provided valuable input for improving them. And thanks to Jack Applin who
provided several scripts and suggested the method for handling the symbolic
link CurrentSemester
.
Fritz Sieker -
~/bin/tools
.cd
to the directory of step 1.make -f ~cs000/public_html/tools/Makefile
$PATH
variable to include the directory from
step 1.Java
assignments, and for
testing the students' code (Java/C/LC-3 assembler to date).
There is a lot of detail following, but you might be able to tell
from the name whether it would be of interest.
newSemester
info (create directory structure)makeCurrent
info (reset symbolic link)genUsers
info (create user file for checkin)forceCheckin
info (put submission into ~/Checkin after drop dead date)java
Assignments
newAssignment
info (script to create assignment directory structure)genDoc
info (script to generate javadoc)Shell.java
info (base class for my Java assignments)AssignX.java
info (example java assignment main class)MyAssignX.java
info (what students complete for assignment)cleanup
info (remove files before regrading)genGrades
info (generate grades for assignment)genMaster
info (generate master output used in diff) genStats
info (generate statistics about this assignment)gradeAll
info (grade assignment of all students)latePolicy
info (determine number of points to deduct for late submission)releaseGrades
info (make grades visible to students)splitGrades
info (split grade list into section by section list)stdFilter
info (modify students output in standard way)adjust.PAx
(file/directory of manual changes to grade)AssignX.java
info (example java assignment main class)checkComments
info (find comments in Java code)cleanup
info (remove files before regrading)Shell.java
info (base class for my Java assignments)doxygen.config
info (config file for doxygen
)forceCheckin
info (put submission into ~/Checkin after drop dead date)genAdjust
info (generate adjustment file for each
student - for manual grading of some aspect of assignment)genDoc
info (generate javadoc)gendoxy
info (generate doc using doxygen)genGrade
info (generate grade for one student)genGrades
info(generate grades for all students) genMaster
info (generate master output used in diff) genStats
info (generate statistics about this assignment)genUsers
info (create user file for checkin)grade.ini
info (control behavior of gradeAssignment)gradeAll
info (grade assignment of all students)javaMakefile
info (Makefile for java
)gradeAssignment
info (grade assignment of one student)latePolicy
info (determine number of points to deduct for late submission)makeCurrent
info (reset symbolic link
CurrentSemester
)MyAssignX.java
info (what students complete for assignment)newAssignment
info (create assignment directory structure)newSemester
info (create directory structure)noLoop
info (monitor program likely in infinite loop)diff
)releaseGrades
info (make grades visible to students)runner
info (grade programs doing console I/O)splitGrades
info (split grade list into section by section list)stdFilter
info (modify students output in standard way)sumCol.pl
info (sum of column of numbers - possibly real)testCases
info (file of test cases to run)In talking with various faculty members, I found that it would be convenient for the faculty be able to easily browse various semesters of a course to see how it was evolving. It was also suggested that we might want to publish our historical versions to promote our department. The directory structure incorporates these suggestions. The "openness" is controlled by Linux permissions.
This directory structure is currently in place for cs160, cs161, cs200,
cs270
. It was in place for cs370
, but has been disabled.
To see the practical result of this directory structure, visit this
newSemester
) and populated with content.makeCurrent
).~csXXX/public_html
.
This has several advantages:
cs370
(for
example), but then try to access it as you (e.g.fsieker
),
you immediately see any permission problems which the students would also
see.~cs370
drwxr-xr-x 3 cs370 class 4096 Jul 19 13:09 bin/
lrwxrwxrwx 1 cs370 class 35 Jul 19 13:15 Checkin -> public_html/CurrentSemester/Checkin/
drwxr-xr-x 17 cs370 class 4096 Jul 19 14:47 public_html/
-rw-r--r-- 1 cs370 class 1307 Jul 19 14:04 README
~cs370/public_html
lrwxrwxrwx 1 cs370 class 8 Jul 19 14:46 CurrentSemester -> .Spring11/
drwxr-x--- 7 cs370 class 4096 Jul 19 13:49 .Fall09/
drwxr-x--- 7 cs370 class 4096 Jul 19 13:50 .Fall10/
drwxr-x--x 9 cs370 class 4096 Jul 19 13:57 .Fall11/
-rw-r----- 1 cs370 class 1281 Jul 19 14:19 .history.html
-r--r--r-- 1 cs370 class 62 Jul 19 13:17 index.php
-rw-r--r-- 1 cs370 class 1307 Jul 19 14:03 README
drwx--x--x 10 cs370 class 4096 Nov 19 2010 .Shared/
drwxr-x--- 7 cs370 class 4096 Aug 17 2010 .Spring09/
drwxr-x--- 8 cs370 class 4096 May 3 2010 .Spring10/
drwxr-x--x 3 cs370 class 4096 Jul 19 13:25 .Spring11/
drwx------ 3 cs370 class 4096 Feb 12 2009 .Spring09/
public_html
there is a directory per semester named
.SpringXX/.FallXX
. I used hidden directory names (beginning with .)
so that only the directories relevant to the "current" semester show up when
one does an ls
. Absolutely everything dealing with that semester lives
in this directory. Access to things not for public viewing are controlled with file
permissions.public_html/CurrentSemester
is a symbolic link to the current
semester. Thus, only this link needs to be changed from semester to
semester (see makeCurrent
script).public_html/index.php
accesses the value of
CurrentSemester
and redirects
to there. As a result, indexing services like Google will see a consistent URL
that never changes. Access in the future is controlled by directory permissions.
The code for index.php
is:
<?php header("Location: " . readlink("CurrentSemester")); ?>
public_html/.history.html
is a simple web page pointing to the
web sites of each semester. It provides a convenient mechanism to browse past semesters
listing the instructor and a link to that semester's web site. Individual semesters web
sites may be password protected at the end of the semester or left open.bin
contains the checkin
tools (I use the
department checkin process rather than RamCT). Info on the checkin process may
be found
here. Because the files are stored locally, they may be easily accessed
by tools (see section on testing). I have a
sub directory of bin
called tools
where I place all the tools I mention. The
permissions on these are normally 540
.
~/Checkin
is a symbolic link to public_html/CurrentSemester/Checkin
.
(~/Checkin
is the directory used for submitting assignments). The
checkin
program uses the directory ~/Checkin
. This
link just puts the actual directory under the directory for a particular
semester.
~/public_html/Shared
is a directory containing material that
is not expected to changed from semester to semester (GIFs, policies, ...).newSemester
facilitates the
creation of a new semester. It creates a directory named for its first
parameter.
The second parameter is an option of what to create. The options are:
drwxr-xr-x 6 cs370 class 4096 2010-06-09 13:56 assignments/ drws--S--- 2 cs370 class 4096 2010-06-09 13:56 Checkin/ drwxr-xr-x 6 cs370 class 4096 2010-06-09 13:56 lecture_codes/ drwx------ 2 cs370 class 4096 2010-06-09 13:56 private/ drwxr-xr-x 6 cs370 class 4096 2010-06-09 13:56 recitations/ lrwxrwxrwx 1 cs370 class 9 2010-08-11 10:32 Shared -> ../Shared/ drwxr-xr-x 6 cs370 class 4096 2010-06-09 13:56 slides/
assignments
contains the material for each assignment stored
in a directory for each one.Checkin
is the actual directory where assignment
submissions are stored. This can be deleted at the end of a semester, or
maintained if one wanted to be able to compare submissions semester to
semester.lecture_codes
is a repository of any code or code snippets
presented in class that the instructor wishes to make available
electronically.private
contains exams, quizzes, etc. I also maintain a
Spreadsheet of grades there. By leaving old exams, quizzes, etc in this
directory, it becomes a good source for future instructors.recitations
is a repository of any code or information
provided to students to complete recitations.Shared
is a link to the Shared directory. Thus links in an
html page can be coded as Shared/XXX
.slides
is a repository of class slides. Some instructors put
both ppt and pdf files here, but may choose to only provide links to the
pdf files.checkin
program require a users
file that defines
who is allowed to check things in. It can be opened up to general submissions,
but I prefer to actually specify the users enrolled in the class. To do this,
first use AriesWeb or RamCT to access the class list(s). Save the info as a
comma
separated list of values. If there is more than one section, save the class
list for each section. I save these files in the Checkin
directory.
Then use the script genUsers
.
This script parses the file(s), looks up the login of each student and produces
the file ~/Checkin/users
. Any errors are students that do not
currently have a cs login. This may be a result of a new student or perhaps
a name change (e.g. someone gets married). I always add myself and the TA's
to the file so that
we can run checkin just like the students do.The script also produces a number
of other files that are used to upload grades to RamCT and used to split grades
into multiple sections.
The script also produces the files allLogins logins.001 ...
. Theses files are used by the grading tools. The files
allLogins
is a sorted list of all the students in the course. This
is used to produce the users
file. The logins.00X
file(s) correspond to the logins for the students in the section(s) of the
course.
The script also produces a start for the file
~/Checkin/assignments
. This file defines the assignments and when
they can be checked it. See the comments at the beginning of the file for
details.
The script also produces a number of mapping files (*.map
,
mapCStoRamCT
) that are used to upload grades to RamCT.
NOTE: Since these tools access the file via ~/Checkin/
they
should only be run after the makeCurrent
script resets
the public_html/currentSemester
link.
~/public_html/CurrentSemester/assignments
directory.
There is one sub-directory per assignment. My convention is to use the names
PAx
for programming assignments and HWx
for written
assignments. The names of the directories are then the key in the
~/Checkin/assignments
file that defines when assignments
may be checked in. Although any key may be used, I keep them short
because they are used as file suffixes by many of the testing tools.
For every project, the assignment sub-directory contains the following:
Things to note:
-rw-r--r-- 1 cs370 class 5510 2010-04-29 15:40 PAx.html
drwx------ 2 cs370 class 4096 2010-04-22 16:15 class
drwxr-xr-x 3 cs370 class 4096 2010-04-22 16:16 doc
drwx------ 2 cs370 class 4096 2010-05-09 16:32 soln
drwxr-xr-x 2 cs370 class 4096 2010-05-09 16:00 src
drwx------ 8 cs370 class 4096 2010-08-26 11:21 test
PAx.html
is the web page for the assignment. It references
the doc
directory for the generated documentation of all provided
source code.class
contains the compiled java
files.doc
contains the javadoc
for supplied files. It may also
contain files produced by doxygen for C and other languages.soln
contains the source of a completed assignment.src
contains the provided source code. In my
assignments there are often substantial number of provided files. Some are
designed as "use only, do not modify" and some are "modifiable".test
contains tools and data for automated testing. There
is a lot of material on testing later.newAssignment
creates
this directory structure.
Once the source files have been generated,
the script genDoc
creates javadoc
for the file. This script expects to be executed from the src
directory. The script produces javadoc
including all
private
fields/methods so that students can view everything. There is
a tool gendoxy
that generates documentation for non java files
using doxygen
.
Checkin
directory after the
drop dead date of the assignment. See Java
Assignments
cs161
in Spring 2010, I reworked some Java
code I had
developed for another class. This became the basis for Java
files. Some
were provided. Others were written/modified by the students. To keep things
more obvious, all files that the students wrote or modified were named with
the pattern MyClassName
using the My
to emphasize what the students should work on.
Most of the documentation for assignments came from javadoc
of the
provided file(s). This forces the students read javadoc
to get
necessary information and to encourage them to use the online
javadoc
to learn about the many Java
classes that are
part of the java
environment.
System.out.println
for
debuggingjava
program. I believe
students can learn a lot by reading code and imitating what they
see.input
which takes commands from a file and processes
them just as if they were typed at the console. Multiple input
may
be nested to any depth and provides a nice example of recursion.It Also has an
exit
which terminates the current input stream and resumes
processing at the next outer layer. If there is no outer layer, the program
is terminated.
extends
the class Shell
, thus
illustrating inheritance. It
adds the commands that test the functionality of this assignment. This
happens in the processOneCommand()
method. This nicely illustrates
method overwriting and how the super
keyword is used. We provided
this code for many assignments, but later just provided a skeleton of the
class and had the students complete it. This structure separates the testing
of commands from the implementation of the assignment details.
If one had a series of assignments that built on one another, this could still be used by simply having each assignment extend the previous one and add some new functionality. On could even override commands in later assignments to provide additional functionality to something done earlier.
The example code is the first assignment of that semester. Its purpose was to get the students writing code and to test their ability to write loops, nested loops, to read from files, and do simple logic. This example will be used in the section on testing to illustrate test cases.
AssignX abstract
by adding the methods
(and javadoc
) that the students must implement. This introduces
a 3rd file MyAssignX.java to the assignment.
This class extends AssignX
. Using an IDE such as Eclipse, empty
implementations can be produced automatically. Now one has a compilable,
runnable program, but the methods will not function correctly. With the command
interpreter (often one command per method the student needs to implement), the
student may code and test incrementally.
Another alternative is to define the methods via an interface
that
the students code must implement
. This decouples the students
code form the interpreter hierarchy. Unfortunately, nether solution works when
you want to introduce a static
method into the assignment.
Java/C/LC3 assembly
programs, but is not
limited to those. The tools are tightly coupled to the
checkin
program in that they rely on the key
used to
check in an assignment and the location where the checkin
program
stores things. The tools have been used to grade programs submitted via RamCT.
This only requires grabbing the submissions from RanCT and putting them in the
correct stucture. Wim Boehm has written a program to do this.
Some of the goals of the work included:
checkin
but still utilize the testing framework. The tools assume that they can
look in ~/Checkin
and its subdirectories for information. The
organization is as follows:
~/Checkin
exists (often a symbolic link to somewhere else)~/Checkin
is a directory per assignment. The names
are arbitrary, but are supplied to the grading tools. The name is
also used as the suffix of several generated files, so it is convenient
to keep it short (I use PAx).tar/zip/gzip/...
file is acceptable. The framework
automatically unpacks many different formats.~/Checkin/allLogins
containing student "names".
These names correspond directly to the names of the directories under
each assignment directory. If the checkin
program is used
these are the login
of the stundents on the cs department
machines. The names are one per line. Blank lines and lines beginning with
# are ignored.diff
it against a master. Recognizing that diff
may be too "harsh", the grader may supply additional tools to either grade the
output directly or "cook" it and then diff
the result against
the "cooked" master output. And beyond this, the grader may manually review
the results and give credit as needed. The idea was to keep things as simple
as possible and only do additional work as needed.
The tests are also somewhat like unit tests in that each test case tests
one small thing. Typically there were 20+ test cases per assignment. Often
the individual test cases tested the same feature with different values to check
completeness of implementation. The test cases often supplied "bad" values
(e.g. null
) to see if students handled erroneous input.
test
directory. This directory may
be anywhere, but my convention is to make it a subdirectory of the assignment.
The following is a listing of a typical test
directory:
-rw------- 1 cs161 class 107 2010-05-10 14:03 grade.ini
drwx------ 2 cs161 class 4096 2010-08-26 11:21 grades.PAx
-rw------- 1 cs161 class 6788 2010-05-10 14:51 gradeThese
drwx------ 2 cs161 class 4096 2010-05-10 14:54 input
drwx------ 2 cs161 class 4096 2010-05-10 14:54 master
drwx------ 2 cs161 class 4096 2010-05-15 13:27 output
drwx------ 2 cs161 class 4096 2010-05-11 15:21 provided
drwx------ 2 cs161 class 4096 2010-05-11 15:21 regrade
-rw------- 1 cs161 class 290 2010-05-10 14:02 testCases.PAx
drwx------ 2 cs161 class 4096 2010-05-15 13:27 work
Several directories/files have suffixes which correspond to the assignment tag. This was done so that we could grade the original assignment (e.g. PA5) and the resubmitted assignment (e.g. PA5-R) in the same directory. The only real difference was the test cases we ran.
grade.ini
is an optional file that controls runtime
behavior of the script gradeAssignment
.
See details.
grades.PAx
contains the grades until they are released
to the students. The suffix corresponds to the "tag" used to checkin the
assignment (e.g. PA5).gradeThese
is an optional file that controls which
students submissions are graded. See details
input
contains test files. If one is using the
Shell
style assignment, these files
contain the commands to be executed for each test case.
Data files needed during
testing could be stored here. However, it is more convenient to store data
files in the provided
directory. A sample directory listing
looks like this:
-r-------- 1 cs161 class 31 2010-04-14 18:16 chooseFour
-r-------- 1 cs161 class 31 2010-04-14 18:16 chooseOne
-r-------- 1 cs161 class 34 2010-04-15 09:44 lengthFour
-r-------- 1 cs161 class 32 2010-04-14 18:15 lengthThree
-r-------- 1 cs161 class 42 2010-04-14 17:59 negativeDistance
-r-------- 1 cs161 class 34 2010-04-15 09:50 optFour
-r-------- 1 cs161 class 30 2010-04-14 18:18 optTwo
-r-------- 1 cs161 class 40 2010-04-14 17:58 positiveDistance
master
contains the results against which assignments are
compared. It is generated by running the testing script against a solution
(often by the TA, or choose a good student's submission). There is one file
per test case and they are named exactly the same as the files in
input
. If there are any "cooking" going on, there will be a file
named xxx.cooked
.output
contains the output produced by each test case. The directory is
removed and recreated before every run. The files have the same names
as the files found in master
.provided
contains any files provided as part of the assignment.
These are copied into the work
directory, overwriting any
submitted files of the same name. To handle various programming languages, the
build is based on make
.
Thus, to grade java
assignments where provided
directory contains only a simple
makefile
file and nothing else. The simple makefile
I used for java
is here.
Data files for testing may be placed here. Thus, referencing of files can
be a simple name, as the programs are executed in the work
directory.
regrade
an optional directory containing regrade
toolstesCases.PAx
is an required file that controls runtime
behavior of the script gradeAssignment
. It defines the test cases
to execute. See details
work
contains all of the students code and all provided files.
It is removed and recreated before every run.makefile
,
create one appropriate to the language of the programs being graded and store
it in the provided
directory. The build
is performed in the test
directory by executing
make -C work -s
.
The makefile
I used for java
is here .
latePolicy
script to take off points
for late submissions. See details.
stdFilter
script.
See details.
input
directory. Assign points to each test case and generate the
testCases.PAx
file.
See details.cleanup
See details.genMaster
Review the gradeAll
. See details.genGrades
to generate the final
grade file for each student. See details.releaseGrades
to make the
grades visible to the students. See details.cs161
) can manually put things in the
Checkin
directory and then run gradeAssignment
.
The reason this works is that the date is used only if the name
contains LATE_. The script forceCheckin
is used
for this.
adjust.PAx
tar
. The grade tools assume that the
submission is a single file. In the case where an assignment consists of
multiple files, they must be packaged in some fashion (tar prefered).
The tools can unpack multiple formats. In the case where students
failed to package their files, the grader may manually do this for them.
I would name the tar fritz.tar
to indicate that I did the
packaging for them.
javac
rejects. I would untar the submission, look at the
code and fix simple syntax errors. I would then retar the files and
"submit" the fixed code and place
it in the students submission directory. In the case of a tar
,
the name is unimportant. Therefore, I would name it fritz.tar
to indicate that I had manually fixed the submission. I did not
modify the original file. I preserve it for tracability.
Each of these cases is handled by providing a adjust.PAx
file.
See details.
cs161
or
any other user that has a real Checkin
directory.Checkin
directory is referenced by ~/Checkin
.tar -xvf Checkin.tar
This will
create a Checkin directory and additional files/directories below it.cd Checkin
mkdir tools
.cd tools
make -f ~fsieker/public_html/teaching/Makefile
tools
directory is in your $PATH
.cd ~/Checkin/test
. Peruse the various files and directories
you see there and refer to the documentation for details.genMaster PAx perfect
. This produces the master output files
in the master
subdirectory.gradeAll PAx
. This will grade the submissions found in the
~/Checkin/allLogins
file. This is a superset of the
actual submissions found in ~/Checkin/PAx
to illustrate
a student who did not submit anything.grades.PAx
subdirectory. There is also a file called ERRORS
there.genGrades PAx
. This will generate the final grade files in
the grades.PAx
subdirectory. Note the files now contain
a summary section at the top.genStats PAx
. This will generate statistics about the
grading in the file grades.PAx/PAx.stats
.adjust.PAx
file and regenerate
the grades.MyAssignX.java
and use
forceCheckin
to add it to the Checkin directory.cleanup PAx
, then gradeAll PAx
...gradeThese
file.~/Checkin
to clean everything up.
Reset your $PATH
. test
directory or
stored in a central location (I suggest ~/bin/tools
). Your
$PATH
shell variable must include either .
or
the directory where the tools are stored. If you invoke any of the tools
without parameters, they will print a usage message with an example.
adjust.PAx
File/Directorytest
directory.
Its purpose is to allow manual modifications to the results of the
automated grading. It is separate file so that grading may be rerun as many
times as necessary
without losing the information stored here. The information is incorporated
into the students grade file by the script genGrade
.
The file adjust.PAx
consists of multiple sections, one per student.
There need only be sections for students whose grade requires adjustment.
If there are adjustments for every student (e.g. something which
MUST be done manually), then the adjustments may be stored in individual
files in the directory adjust.PAx
. The name of the file is
the login name. For example, in one assignment, the students were expected to
include a README
file containing answers to several questions.
By creating the simple script genAdjust
and including the line in the testCases.PAx
file of the form:
adjust % 5 % ../genAdjust $assignName $login
a file was created for each student that contained the students
README
as well as a place for the grader to assign a grade.
Here
is the result for a sample user.
The format of a section/file is:
All the info for a particular user is added to the grade file when it is
generated. Lines containing the word
<BEGIN loginName1>
adjust Score: -10 // Commented out unused code that used an undeclared variable called "shortestPath" -Maggie
<END>
<BEGIN loginName2>
adjust Score: -10 // Removed '\r' from the Cities toString method -Maggie
<END>
Score:
cause the total
to be changed. All other lines are simply copied into the grade file.
Multiple score adjustments for a single login are OK.
checkComments
Scriptcleanup
Scriptgrades.PAx
directory. It is normally used before rerunning
gradeAll
script to make sure the results are fresh.
forceCheckin
Scriptscript
may be used
to place an assignment in the Checkin
directory after the drop
dead date of the assignment. For example, a student may have an official excuse
(e.g. traveling for team sport), and this allows the TA to "submit" the
assignment without it being marked as late.
genAdjust
ScriptPA2.QandA
that contained several questions about
the code the students wrote for the assignment. The students were expected to
answer the questions in the file (simple text) and turn it in as part of the
submission. This script was used to produce an adjustment file for each student.
The graders then edit the file, add a score for each questiopn and perhaps
some comments. This is then inserted into the students grade file. By providing
a file per student, multiple graders could work simultaneously. In general,
this script will be customized for each assignment.
A multi-step process was then used for grading. The example assumes that
genAdjust
is in the test
directory.
genAdjust
script was customized for this assignment. In this
case cat P2.QandA
was all that was neededtestCases.PAx
file was produced containing the single line
QandA % 10 % ../genAdjust $testName $login %
This has the effect of assignming 10 points to the questions. See
testCases for more detail.gradeAll
to produce one file per student. The files
may now be manually graded.testCases.PAx
file to add the remaining test cases and
modify the command line portion of QandA
test to be
echo ""
genMaster
. The master output for the QandA
test case will be an empty file.testCases.PAx
file and modify the command line
portion of the QandA
test to be
echo "see attached"
. This will cause the automated grading
to assign a score of 0 to this test. The points will be added back in via
the adjustment file.gendoxy
Scriptgendoxy
. Most
of the documentation is in the .h
files as normal
doxygen
comments. I put the TODO
in the
.c
files as this is what the students were expected to complete.
The tools assumes the file ~/bin/tools/doyxgen.config
exists.
This is the default file generated with doxygen -g
with the following changes:
> REPEAT_BRIEF = NO
> OPTIMIZE_OUTPUT_FOR_C = YES
> EXAMPLE_PATH = ..
> HTML_OUTPUT = ../doc
> SEARCHENGINE = NO
> GENERATE_LATEX = NO
The script assumes a directory structure as create by
newAssignment
. All source code lives in the src
directory. The description of the assignment (PAx.html
) is in the
PAx
directory. In the html
file links to the provided
files are coded with the path src/fileName
.
Finally in one of the source files (I normally choose the one containing
main()
), the following lines are added:
/** @mainpage cs270 Fall 2012 Programming Assignment 1 - Bit Fields in C
* \htmlinclude "PA1.html"
*/
To generate the documentation, in the src
directory execute
gendoxy PAx
The final documentation is accessed as
http://.../doc/index.html
genGrade
ScriptgradeAssignment
script. This script
produces a summary, assesses late penalties and includes information
(if any) from the adjust.PAx
file. The script is rarely used
directly. Rather, it is invoked by the genGrades
script.
genGrades
ScriptgenGrade
. It is
driven by a list of login names (one per line).
It uses the file gradeThese.PAX
or gradeThese
or
~/Checkin/allLogins
, whichever it finds first.
The script extracts the scores for the individual test
cases and generates an assignment total. It then regenerates the grade
file with the total as the first line of the file. The script is also
responsible for deducting late points and adding info from the
adjust.PAx
file.
As part of the run, the script produces the file
grades.PAx/SUMMARY
. This file contains the login and assignment
grade for each student. There are tools for uploading this information
to RamCT.
genMaster
Script
master
directory. It then uses gradeAssignment
to test
the submission. The output then becomes the master for all subsequent runs.
If a students submission is used to generate the master, that student should
be regraded, since in the run of this program produces a grade file with all 0's.
The script is invoked as follows
genMaster assignName login
The parameter assignName
is the name used in the
checkin
of the assignment. It is a subdirectory of the
directory ~/Checkin
.
The parameter login
is the login of the person whose code will
be used to generate the master output. This code goes through exactly the
same process as any student submission.
genStats
Scripttest/grades.PAx/PAx.stats
. A
sample file is here.
gradeAll
ScriptgradeAssignment
. It is
driven by a list of login names (one per line).
It uses the file gradeThese.PAX
or gradeThese
or
~/Checkin/allLogins
, whichever it finds first.
As it works it echoes the logins to the screen
so the tester can monitor progress. If a test hangs (typically infinite loop)
just kill the process(s). It will likely take multiple ctrl-C's to stop
everything. Then create a file gradeThese
containing
the logins of the remaining submissions and restart the script. As each
submission is graded, it produces a file grades.PAx/login.grade
.
The script also produces the file grades.PAx/ERRORS
. This contains
the list of all logins for which there was no submission or the compile failed.
It provides a quick check on the overall status of the class.
Each grade file contains multiple sections corresponding to each test case. Each section contains the name of the test case, the contents of the test case file, the output produced by the submitted program, the master output, and the grade for this test. The output of the tested program is limited to the maximum of the length of the master output or 60 lines. This was to prevent huge stack traces (infinite recursion) from filling up the file. An example grade file with the side-by-side output (the default) is here. An example grade file with linear output (configurable) is here. An example grade file containing a runtime error is here.
gradeAssignment
ScriptgradeAll
script.
It is the "meat" of the process, doing all the work for grading the
assignment for a single student. The script contains many embedded tools
that do portions of the work.
The script is invoked as follows
gradeAssignment assignName login
The parameter assignName
is the name used in the
checkin
of the assignment. It is a subdirectory of the
directory ~/Checkin
.
The parameter login
is the login of the person whose code will
be graded. The gradeAll
simply invokes this script once for
each user to be graded.
As a program executes, stdout
and stderr
are captured in
$outputFile
. See
testCases.PAx
for details.
The flow of the script is:
grade.ini
file if it can be foundwork
directorygrades.PAx/login.grade
)getSubmission()
LATE_
and rename as needed
(see embedded script chekLate()
)extractFiles()
)flatten()
)package
statements that might exist
(see embedded script fixPackage()
)provided
to work
(see embedded script addProvided()
)make
checkMakeAndRunTests()
gradeSubmission()
. Otherwise, assign grade of 0testCases.PAx
file one
at a time. Determine the name of the test and other parameters and actually
run the test. Output is captured in a temporary file.stdFilter
if it existsdiff
the output and master
. The result is
appended to the grade file in a side-by-side format so the user can
easily compare their results to the master. When viewing results, maximize the
window to accommodate very long lines.grade.ini
Filegrade.ini
is an optional file that overrides some
of the behavior of the grading script gradeAssignment
.
That script first looks in the current
directory and then in the home directory for the file. If this file is present,
it is sourced in. An example of the file is here.
gradeThese
Filetest
directory is used to
restrict the number of users processed
by gradeAll
and genGrades
. The file consists of
logins, one per line. It is commonly used when a run of gradeAll
"breaks" because a submission enters an infinite loop. The grader kills the
grading process, and produces a file of the remaining students who have not
yet been graded, then restarts the process. If the file is not present,
the list of students is taken from ~/Checkin/allLogins
.
It is also useful during resubmissions to grade only those students who
actually resubmit. The file can be produced by a simple ls
of
the resubmit directory.
latePolicy
Script
The script is used by the genGrades
script and splits out the
late policy from the rest of the work for convenient modification.
The reason that hours late is passed was to provide some "wiggle" room in the calculation of late points. For example, if the assignment is 1 hour late, perhaps only a small penalty (1 point) might be deducted. Anything beyond this might be calculated as 10 percent per day.
login.Grade
FilegradeAssignment
executes, its output is collected and placed
in the file grades.PAx/login.grade
.
Each grade file contains multiple sections corresponding to each test case. Each section contains the name of the test case, the contents of the test case file, the output produced by the submitted program, the master output, and the grade for this test. The output of the tested program is limited to the maximum of the length of the master output or 60 lines. This was to prevent huge stack traces (infinite recursion) from filling up the file. An example grade file with the side-by-side output (the default) is here. An example grade file with linear output (configurable) is here. An example grade file containing a runtime error is here.
regrade
Scriptsdiff
. The
script can function in one of two ways:
diff'ed
against the results obtained by
performing the same filtering on the master output.stdout
. The format of the line is:
testName Score: value / max
The script is stored in the regrade
directory and is executed as:
regrade/scriptName testName regradePoints originalFileName cookedFileName
Consider a simple example from a beginning Java class. The students were
instructed to write a program that prompts for several inputs, then calculates
the income tax owed. The following is a sample student output and the master
output from the .grade
file:
Your output Master output
Number of Exceptions: 2 | Number of Exemptions: 2
Gross Salary: 10000 Gross Salary: 10000
Interest Income: 500 Interest Income: 500
Capital Gains:250 | Capital Gains: 250
Charitable Contributions: 30 Charitable Contributions: 30
Total Income: $10750.00 Total Income: $10750.00
Adjusted Income: $7450.00 Adjusted Income: $7450.00
Total Tax: 0.00 | Total Tax: $0.00
Notice the "minor" errors. The diff
awards a score of 0 as there
are differences. However, with a simple regrade filter, one can easily
give back full/partial credit. The most important result was the computed
tax. Thus, the following script was used. It simply grabbed the last line
and isolated the number at the end (the tax). It is up to the grader to
decide how much the final value was worth.
#!/bin/sh
# Fritz sieker
#set -x
testName=$1
points=$2
testFile=$3
cookedFile=$4
# get the last line (should contain "total Tax: XXX.YY
# remove everthing up to :
# remove everything up to $
# remove leading/trailing whitespace
# only thing remaining should be computed number
tail -n1 $testFile | sed -e 's/^.*\://g; s/^.*\$//g; s/^[ \t]*//; s/[ \t]*$//' > $cookedFile
In another case, one might sort the output and give partial/full credit if the
sorted output matches.
One of our assignments involved a brute force traveling salesman problem. If there are N cities, there are 2N equivalent circuits (start at any city, go either clockwise or counter-clockwise). For this case we wrote a script that preserved their solution, but started at a particular city and traversed in a particular direction.
If one is using the additional filtering method, the cooked results must be written to the file specified in the fourth parameter. Here is a another example of a regrade script. The script to reorder the TSP data is here. For that assignment the original output is here while the "cooked" output (produced by the regrade script) is here.
A handy source of sed
scripts is
here.
Here is a another example regrade
script. The script splits the file into words (one per line) gets rid
of all blanks and sorts the output. In this case, the grader might choose to
give partial credit on a match.
#!/bin/sh
# Fritz Sieker
#set -x
testName=$1
points=$2
testFile=$3
cookedFile=$4
sed -s 's/ /\n/g' $testFile | sed -s 's/ //g' | sort > $cookedFile
noLoop
ScriptnoLoop
. For example
noLoop java P2 < test
If the program P2 executes more that 10 seconds (configurable in script), the
program is killed and an error printed. This is usefull in the automated testing
so that one students problems do not prevent completion of testing all of the
students programs. The runner script has this and other
capabilities.
releaseGrades
Scripttest/grades.PAx
to the directory
~/Checkin/PAx
. Once this has been done, the grades become
visible to the students using the ~/bin/grade
program.
This script may be used multiple times if regrading is performed after initial
grades are released.
runner
Script
java P2 < test1
Number of Exemptions: Gross Salary: Interest Income: Capital Gains: Charitable Contributions: Total Income: $10750.00
Adjusted Income: $7450.00
Total Tax: $0.00
If the runner
is used, the output is as follows:
runner java P2 < test1
Number of Exemptions: 2
Gross Salary: 10000
Interest Income: 500
Capital Gains: 250
Charitable Contributions: 300
Total Income: $10750.00
Adjusted Income: $7450.00
Total Tax: $0.00
runner
has other capabilites including limiting the total CPU time (detect infinite
loops) of the tested program, limiting the output, ... Talk to Jack for more info. or read the script.
stdFilter
Scripttr
to convert everything to a single case. Transformations that go
here will not need to be processed by any optional regrade tools. The
example script removes all trailing white space on lines and removes all
null characters. Filters are expected to read from stdin
and
write to stdout
. No filtering is performed if the
command which stdFilter
results in an error.
A handy source of sed
scripts is
here.
sumCol.pl
ScriptgenGrade
to sum up individual
test case scores (possibly real numbers).
testCases.PAx
File'%'
.
The hash character ('#'
) denotes the beginning of a
to-end-of-line comment. Blank lines are ignored.
Each line of this file contains seven parameters. Parameters may be blank, and parameters after the last actual parameter may be left off. The parameters are:
work
directory. There may be IO redirection and
pipes in the command line as needed. To make this field easier to generate,
there are several macros defined that one may use. They are:
$testName
- the name of this test case.$points
- the number of points for this test case.$inputDir
- the path to the input directory.$inputFile
- the value $inputDir/$testName
$outputDir
- the path to the output directory. ALL
output of the program must be stored in this directory, because this
directory becomes the master directory upon running
genMaster
..$outputFile
- the value $outputDir/$testName
.
Anything written to stdout
or stderr
is captured in
this file.$workDir
- the path to the work directory.$login
- the login of the user whose assignment is
being graded.The command line may be blank, in which case nothing is executed. This is useful in the case where a previous test case produces multiple files, each of which is to be graded individually. The first test case executes the program and grades one of the result files. Subsequent test cases leave the command line blank, and simply specify the remaining files, one per test case.
Programs prompting for console input: If you have a program prompting for input,
consider wrapping the command in the runner
script.
Programs using only command line parameters: While the tools allow
you run a program that takes all of its input from command line parameters,
the output will not show those parameters unless the program explicity print
them. Thus, it is hard for students to understand their errors.
However, this is easily fixed without modifying the tested program.
Simply put the actual command line in a file. Then in the
testCases
file the line for that test case becomes.
testName % 4 % . $inputFile % $inputFile % $outputFile
where the file testName
contains the actual command line. This
file will be printed in the resulting output, so the students can see how
the program was run.
grade
file. If the parameter is blank, no files are
copied. My convention is to name the input file the same as the
test name. This is not required, but makes developing the
test case file easier, because the name is directly available with
the macro $inputFile
An interesting use of this field is to set its value to
$outputFile
and leave the output field blank. Suppose the
command line specified executed a script which checks for comments in the
students code and generates a grade based on the comments. Since there
is really no master output to diff against, the script simply writes its
results (including a score) to stdout
. The output is captured
and copied into the grade file.
stdFilter
(if it exists), and then diff'ed
against
files with the same name in the master
directory. If no file
is specified, no diff'ing
occurs.Here is the file used to test the sample
assignment referenced in another section. Note that three of the test cases
use the regrade scripts nullToEmptyArray
, and that three of the
tests have multiple input files.