There are three steps to printing out assignments
TODO: Harmonize the information dealing with downloading assignments/marks with the information at LocalMarmosetSubmissionMirror
The RST hierarchy is simple. All of the assignments are put in ~/handin/<assignment #>/<student id>
. Create a directory for the assignment and download all of the zip files to this location. Copy the marmoset2rst
scripts into ~/handin/<assignment #>
and run make
. This will unpack all of the zips (e.g. unzip A1P1.zip
, unzip A1P2.zip
, ...), properly rename all of the directories (the rename
script), will remove submissions by course staff (e.g. rm -rf djshaw*
, rm -rf f2qiu
), and will automatically generate grade files (the parseGrades
script).
Now you need to run RST. Create a directory for marking in ~/marking/<assignment #>/test.<assignment #>/
and copy the marking
scripts into this folder. Run rst
with /u/isg/bin/rst <assignment #> p <assignment #> '*' print
I recommend that you spot check ps files that are generated by RST, just to make sure that your marking scheme is correct that the grades are properly calculated.
Print out the assignments with /u/isg/bin/printOut <assignment #> <assignment #> <timestamp> <# of piles> -g
The rename script has been modified to handle this procedure, so use the follow rename script if you wish to handle this case.
#!/usr/bin/env bash # first arg is suffix to remove function renameDirs { if [ `ls -d -- *-$1 2> /dev/null | wc -w` -ne 0 ]; then for i in *$1; do suffixRemoved=${i%$1} if [ -d $suffixRemoved ]; then echo " C Copying files from $i to $suffixRemoved ..." cp -- $i/* $suffixRemoved/ echo " X Removing directory $i ..." rm -rf -- $i else echo " R Renaming $i to $suffixRemoved ..." mv -- "$i" "$suffixRemoved" 2> /dev/null fi done fi } # important to do it in this order to ensure on-times get overwritten by lates echo "Renaming On-time Directories ..." renameDirs "-On-time" echo "Renaming Late Directories ..." renameDirs "-Late" echo "Done renaming."
When you unpack the zips from marmoset, each student has a directory named <userid>-On-time
. To make these directory look like an RST hierarchy, we need to remove the -On-time
. The following script rename
accomplishes this.
#!/software/.admin/bins/bin/bash for i in `ls`; do if [[ ${i:(-8)} == "-On-time" ]]; then if [ -d $i ]; then mv $i `basename $i -On-time` fi fi done
Note that this script contains hardcoded references to file names, and so will need to be edited before being used.
#!/software/.admin/bins/bin/python import csv import os def sumRow (row, start, length, student): ret = 0 for i in range(start, start + length, 1): try: ret += int(row[i]) except: print "sumRow expcetion for student " + student + " at index %i" % i ret += 0 return ret def reader (file, numPublic, numRelease, numSecret): ret = {} for row in file: if "cvsAccount" == row[0] or row[0].endswith("-canonical"): continue name = row[0] public = sumRow (row, 3, numPublic, row[0]) release = sumRow (row, 3 + numPublic, numRelease, row[0]) secret = sumRow (row, 3 + numPublic + numRelease, numSecret, row[0]) ret[name] = [public, release, secret] return ret def writer (out, key, part, filename, marks, maxpublic, maxrelease, maxsecret, maxbonus=0, human=False, humanSum=0): if marks.has_key(key): if human: out.writelines ("____/%i Part %i: %s\n\n" % ((maxpublic + maxrelease + maxsecret + humanSum), part, filename)) else: out.writelines ("%i/%i Part %i: %s\n\n" % ((marks[f][0] + marks[f][1] + marks[f][2]), (maxpublic + maxrelease + maxsecret), part, filename)) out.writelines ("\t %i/%i Public tests\n\n" % (marks[f][0], maxpublic)) if maxrelease != 0: out.writelines ("\t %i/%i Release tests\n\n" % (marks[f][1], maxrelease)) if maxsecret != 0: out.writelines ("\t %i/%i Secret tests\n\n" % (marks[f][2], maxsecret)) else: out.writelines ("0/%i Part %i: %s\n\n" % ((maxpublic + maxrelease + maxsecret + humanSum), part, filename)) out.writelines ("\t 0/%i Public tests\n\n" % maxpublic) if maxrelease != 0: out.writelines ("\t 0/%i Release tests\n\n" % maxrelease) if maxsecret != 0: out.writelines ("\t 0/%i Secret tests\n\n" % maxsecret) p1 = reader (csv.reader(open('project-A5P1-grades.csv'), dialect='excel'), 1, 2, 0) p2 = reader (csv.reader(open('project-A5P2-grades.csv'), dialect='excel'), 1, 2, 0) dirs = os.listdir (".") for f in dirs: if not os.path.isdir(f): continue if f == ".svn": continue print f + "/grades..." grades = open(f + "/grades", "w") grades.writelines ("\t\t\t\t=============================================\n") grades.writelines ("\t\t\t\t Winter 2009 CS 139 Assignment 4\n") grades.writelines ("\n") grades.writelines ("\t\t\t\t Marked By:\n") grades.writelines ("\n") grades.writelines ("\t\t\t\t TOTAL: /TODO\n") grades.writelines ("\t\t\t\t=============================================\n") grades.writelines ("\n") grades.writelines ("\n") grades.writelines ("\n") grades.writelines ("\n") writer (grades, f, 1, "a5p1.cc", p1, 4, 15, 0, 0, True, 8) grades.writelines ("\t____/1 pre/post conditions for isEmpty\n\n") grades.writelines ("\t____/1 pre/post conditions for push\n\n") grades.writelines ("\t____/1 pre/post conditions for pop\n\n") grades.writelines ("\t____/2 properly deleting node in pop\n\n") grades.writelines ("\t____/1 pre/post conditions for top\n\n") grades.writelines ("\t____/1 pre/post conditions for swap\n\n") grades.writelines ("\t____/1 pre/post conditions for size\n\n") writer (grades, f, 2, "a5p2.cc", p2, 3, 14, 0, 0, True, 10) grades.writelines ("\t____/1 pre/post conditions for isEmptyPQ\n\n") grades.writelines ("\t____/1 pre/post conditions for enterPQ\n\n") grades.writelines ("\t____/1 pre/post conditions for firstPQ\n\n") grades.writelines ("\t____/1 pre/post conditions for leavePQ\n\n") grades.writelines ("\t____/2 properly deleting node in leavePQ\n\n") grades.writelines ("\t____/2 properly deleting priority in leavePQ\n\n") grades.writelines ("\t____/1 pre/post conditions for sizePQ\n\n") grades.writelines ("\t____/1 pre/post conditions for sizeByPriority\n\n") grades.writelines ("\t____/1 pre/post conditions for numPriorities\n\n") grades.close ()
ZIP_FILES=$(wildcard p*.zip) REMOVE_USERS=pbeshai glu ctkierst jmatlee omnafees .PHONY: all unzip renameDirs parseGrades all: @$(MAKE) unzip @$(MAKE) renameDirs @$(MAKE) parseGrades parseGrades: @./parseGrades renameDirs: @./rename unzip: @for zipFile in $(ZIP_FILES); do \\ unzip -o $$zipFile; \\ /bin/bash -c "rm -rf *-canonical*/ *-student*/ $(foreach user,$(REMOVE_USERS),$(user)*/)"; \\ done clean: -/bin/bash -c "rm -rf */" remove: @rm *.zip rename Makefile parseGrades
The REMOVE_USERS variable specifies the tutor's and instructor's userids to ensure their files do not get printed. (Note that commands must begin with a tab character, not several spaces)
computeMarks is often a very simple, short script.
For a scheme assignment:
#!/bin/bash FULLPROG=`type $0 | awk '{print $3}'` # find the program's full path PROGDIR=`dirname ${FULLPROG}` # extract the directory PATH=`/bin/showpath gnu standard current` retainFile () { if [ -s "$submitdir/$1" ]; then # only keep the file if it exists "$PROGDIR/plt370mangle" "$submitdir/$1" > "$submitdir/$1.mod" # remove the compiler directive from the student's code and put it in $1.mod keepFile "$submitdir/$1.mod" 512 -f -h "$1" # tell rst to keep the first 512 lines of $1.mod fi } cat "$submitdir/grades" > "$marksheet" retainFile a1-princess.ss retainFile a1-grades.ss retainFile a1-temperature.ss
The plt370mangle script referenced above is borrowed from BitterSuite, and can be found in the appropriate subdirectory of /u/isg if it cannot be found on the course account.
For a c++ assignment (same as the scheme computeMarks, without the call to plt370mangle):
#!/bin/bash FULLPROG=`type $0 | awk '{print $3}'` # find the program's full path PROGDIR=`dirname ${FULLPROG}` # extract the directory PATH=`/bin/showpath gnu standard current` retainFile () { if [ -s "$submitdir/$1" ]; then keepFile "$submitdir/$1" 512 -f -h "$1" # tell rst to keep the first 512 lines fi } cat "$submitdir/grades" > "$marksheet" retainFile a5p1.cc retainFile a5p2.cc
REQUIRED_FILES
do not count towards the file limit specified by FILE_LIMIT
, and binary files are (hopefully) ignored.
#!/bin/bash PATH=`/bin/showpath gnu standard current` FILE_LIMIT=10 FILE_LINE_LIMIT=1000 REQUIRED_FILES="Card.cc Card.h Common.cc Common.h Parser.h Deck.h Deck.cc Makefile Name.h Name.cc Player.h Player.cc Hand.h Hand.cc Driver.cc" # use the grades file if you ran parseGrades to include Marmoset testing results cat "$submitdir/grades" > "$marksheet" #cat "$testdir/mark-scheme" > "$marksheet" ls $submitdir fileCount=0 for file in $submitdir/*; do base=`basename $file` # ensure that binary files are not printed filetype=`file $file` if [[ "$filetype" == *executable* ]]; then echo >> "$marksheet" echo "### Warning: file $base is an executable and was not printed ###" >> "$marksheet" continue fi if [ "${file##*.}" == "o" -o "${file##*.}" == "zip" ]; then echo >> "$marksheet" echo "### Warning: file $base is an executable and was not printed ###" >> "$marksheet" continue fi if [[ "$base" == *~ ]]; then echo >> "$marksheet" echo "### Warning: file $base is assumed to be a backup and was not printed ###" >> "$marksheet" fi # if this isn't a required file, increase file count if [[ "$REQUIRED_FILES" != *$base* ]]; then let fileCount=fileCount+1 fi # if we have reached the file limit, stop printing if [ "$fileCount" -gt "$FILE_LIMIT" ]; then echo >> "$marksheet" echo "### Warning: student submitted more than $FILE_LIMIT non-required files. Only $FILE_LIMIT files shown. ###" >> "$marksheet" break fi # print the file if it the marksheet if [ "$base" != "grades" ]; then printFile $base $FILE_LINE_LIMIT -f fi done