As with the earlier versions, this script is designed to check my students’ typing assignments against a key. I had to download all submitted assignments in moodle, placing them in a folder on my linux box, placing the key in .txt format, and running the script. This would output a fairly long filename that had the grade in it. I would then have to go ahead and manually enter in students’ grades in moodle and manually upload each response file. It was a big improvement, but still a tedious process. This new script automates the entire process.
The usage for the script is simply
./autograde lesson#
After that, it downloads all assignments, grades them, posts the grades to moodle, and uploads a response file.
There were some challenges for me in this one, most of which involved learning the intricacies of moodle. If you’re interested in adapting this for your own purposes, you should know that each assignment has a different number. One is related to the submissions.php file which displays the assignments in the browser, the other is related to the moodledata folder where the submissions for each student are actually stored.
In order to make this work, I had to be able to query the mysql database to find the userid number for each student. Each submission file begins with the student’s username, so I had to find a way to truncate the file so that it would return the username only and then use that to query the mysql database to return the userid. I found a great php script here and ended up using it twice in my setup – once to obtain the username in order to find the userid, and again later to obtain a consistent, and simpler filename. The second instance probably could have been done in bash instead of php, but I was already taking up too much time to write this script as it was. At some point, I may tinker with it and see if I can make it more efficient, but since it works, I’m not really inclined to fix it.
If you have any comments or suggestions on how to improve it in any way, I welcome your comments.
Dependencies:
docx2txt
dwdiff
curl
Chirp Internet’s php text truncation script
ftp access to your moodledata directory
First, here’s the main script. If you’re going to use it, be sure to change the URL’s and replace the username and password with your correct information. Also, you’ll need to do a search and replace to replace the < and > with the proper angle brackets.
#!/bin/bash # first check if there is one argument1: if [ "$#" -ne 1 ]; then echo "usage: $0 <lesson#>" exit fi WORKDIR=$HOME/autograde/$1 KEYFILE=$HOME/autograde/keys/$1key.txt if [ "$1" == lesson1 ]; then ASSIGNMENT=125 UPLOADDIR=93 else if [ "$1" == lesson2 ]; then ASSIGNMENT=126 UPLOADDIR=94 else if [ "$1" == lesson3 ]; then ASSIGNMENT=127 UPLOADDIR=95 else if [ "$1" == lesson4 ]; then ASSIGNMENT=17 UPLOADDIR=11 else if [ "$1" == lesson5 ]; then ASSIGNMENT=15 UPLOADDIR=10 else if [ "$1" == lesson6 ]; then ASSIGNMENT=33 UPLOADDIR=22 else if [ "$1" == lesson7 ]; then ASSIGNMENT=54 UPLOADDIR=35 else if [ "$1" == lesson8 ]; then ASSIGNMENT=74 UPLOADDIR=50 else if [ "$1" == lesson9 ]; then ASSIGNMENT=94 UPLOADDIR=67 else if [ "$1" == lesson10 ]; then ASSIGNMENT=128 UPLOADDIR=96 else if [ "$1" == lesson11 ]; then ASSIGNMENT=129 UPLOADDIR=97 else if [ "$1" == lesson12 ]; then ASSIGNMENT=98 UPLOADDIR=71 else if [ "$1" == lesson13 ]; then ASSIGNMENT=130 UPLOADDIR=98 else if [ "$1" == lesson14 ] ; then ASSIGNMENT=131 UPLOADDIR=99 else if [ "$1" == lesson15 ] ; then ASSIGNMENT=132 UPLOADDIR=100 else if [ "$1" == lesson16 ] ; then ASSIGNMENT=133 UPLOADDIR=101 else echo "Please input the lesson you which to grade as \"lesson#\", using only lower case, no spaces, and of course, no quotes." fi fi fi fi fi fi fi fi fi fi fi fi fi fi fi fi echo "Moodle assignment number is" $ASSIGNMENT echo "Working directory is" $WORKDIR echo "The key for this exercise is" $KEYFILE #visit the home page to get current session cookie echo "Visiting the home page to get current session cookie" wget --spider --save-cookies cookies.txt --keep-session-cookies https://yourwebsite.com/moodle/login/index.php #log in to moodle echo "logging into moodle" wget --load-cookies cookies.txt --save-cookies cookies.txt --keep-session-cookies --post-data "username=username&password=password&testcookie=1" -O- https://yourwebsite.com/moodle/login/index.php #download all files for assignment echo "downloading zip file containing assignments for" $1 wget --load-cookies cookies.txt --save-cookies cookies.txt --keep-session-cookies --post-data "download=zip" -O "$WORKDIR/assignments.zip" https://yourwebsite.com/moodle/mod/assignment/submissions.php?id=$ASSIGNMENT #unzip assignments to appropriate location unzip $WORKDIR/assignments.zip -d $WORKDIR #delete previously uploaded feedback files rm $WORKDIR/*response* GRADEDDIR=$WORKDIR/graded #checks to see if $GRADEDDIR exists and creates it if it does not if [ ! -d "$GRADEDDIR" ]; then mkdir -p "$GRADEDDIR" fi #converts MS Word format to plain text for UNGRADED in $WORKDIR/*.docx; do docx2txt.sh $UNGRADED; done #compares text files against key and outputs to .GRADED.txt file for GRADED in $WORKDIR/*.txt; do /usr/bin/dwdiff -s $KEYFILE $GRADED > "$WORKDIR/$(basename $GRADED .txt).GRADED" done #renames .GRADED file with information dwdiff writes to end of file for RENAMED in $WORKDIR/*.GRADED; do mv $RENAMED "$WORKDIR/$(basename $RENAMED .GRADED).$(grep "old:" $RENAMED).RENAMED" done #moves graded files to graded directory for MOVED in $WORKDIR/*.RENAMED; do mv "$MOVED" $GRADEDDIR/ done #begin converting .RENAMED to .html for COLORIZED in $GRADEDDIR/*.RENAMED; do cat "$COLORIZED" | sed -e 's/\[-/<span style=\"background-color:red\">/g' -e 's/-\]/<\/span>/g' -e 's/{+/<span style=\"background-color:yellow\">/g' -e 's/+}/<\/span>/g' -e '1i<html>\n<body>\n<pre>' -e 's/old:/Answer Key:/' -e 's/new:/Your Document:/' > "$COLORIZED.html" done #finish converting .txt to .html for HTMLEND in $GRADEDDIR/*.html; do echo "</pre> </body> </html>" >> '$HTMLEND' done #clean up the filenames a bit rename 's/.old: /\-/' $GRADEDDIR/*.html rename 's/.RENAMED././' $GRADEDDIR/*.html #removes .txt files from $WORKDIR rm $WORKDIR/*.txt #remove last line of .RENAMED file and rename to .TRUNCATED for TRUNCATED in $GRADEDDIR/*.RENAMED; do sed -e '$d' "$TRUNCATED" > "$TRUNCATED".TRUNCATED done #remove spaces from .TRUNCATED filenames rename 's/ /_/g' $GRADEDDIR/*.TRUNCATED #remove spaces from .html filenames rename 's/ /_/g' $GRADEDDIR/*.html #remove % sign and replace with word 'percent' in html filenames rename 's/%/percent/g' $GRADEDDIR/*.html #remove all .RENAMED files from $GRADEDDIR to clean up a bit rm $GRADEDDIR/*.RENAMED #define userid and grade variables and post the grades and a generic comment to moodle for POSTED in $GRADEDDIR/*.TRUNCATED; do USERID=$(curl -s -d "filename=$(basename $POSTED)" http://yourwebsite.com/getuserid.php) POSTEDGRADE=$(grep -o '[[:digit:]]*% common' $POSTED | grep -o '[[:digit:]]*') wget --load-cookies cookies.txt --save-cookies cookies.txt --keep-session-cookies --post-data "offset=1&userid=$USERID&id=$ASSIGNMENT&mode=grade&menuindex=10&saveuserid=-1&grade=$POSTEDGRADE&submissioncomment=Please+ask+me+if+you+have+any+questions.+&format=1&mailinfo=0&submit=Save+changes" -O- https://yourwebsite.com/moodle/mod/assignment/submissions.php done echo "Now renaming files into an easier to read format. This may take a while." for RESPONSEFILES in $GRADEDDIR/*.html; do GETUSERID=$(curl -s -d "filename=$(basename $RESPONSEFILES)" http://yourwebsite.com/getuserid.php | sed 's/ //g') GETSHORTNAME=$(curl -s -d "filename=$(basename $RESPONSEFILES)" "http://yourwebsite.com/getusername.php" | sed 's/ //g') mv $RESPONSEFILES $GRADEDDIR/$GETSHORTNAME done rename 's/Chapter/_Chapter/' $GRADEDDIR/*.html for SHORTNAMERESPONSE in $GRADEDDIR/*.html ; do GETUSERID=$(curl -s -d "filename=$(basename $SHORTNAMERESPONSE)" http://yourwebsite.com/getuserid.php | sed 's/ //g') curl -T $SHORTNAMERESPONSE ftp://yourwebsite.com/moodledata/2/moddata/assignment/$UPLOADDIR/$GETUSERID/responses/ --user username:password --ftp-create-dirs done #clean up a bit more rm $WORKDIR/assignments.zip rm $GRADEDDIR/*.TRUNCATED rm $WORKDIR/*.docx rm $GRADEDDIR/*.html
Next is the getuserid.php script:
<?php // Original PHP code by Chirp Internet: www.chirp.com.au // Please acknowledge use of this code by including this header. function myTruncate($string, $limit, $break=".", $pad="...") { // return with no change if string is shorter than $limit if(strlen($string) <= $limit) return $string; // is $break present between $limit and the end of the string? if(false !== ($breakpoint = strpos($string, $break, $limit))) { if($breakpoint < strlen($string) - 1) { $string = substr($string, 0, $breakpoint); } } return $string; } $con = mysql_connect("localhost",databasename","password"); if (!$con) { die('Could not connect: ' . mysql_error()); } mysql_select_db("databasename", $con); $testpost = $_POST['filename']; $testtruncate = myTruncate($testpost, 1, "_"); $result = mysql_query("SELECT id FROM mdl_user WHERE username LIKE '$testtruncate'") or die(mysql_error()); while($row = mysql_fetch_array($result)) { echo $row["id"]; } mysql_close($con); ?>
Last is the getusername.php script, which really probably could be done entirely in bash, I just haven’t put my head to it yet:
<?php $filename = $_POST['filename']; $pieces = explode("_", $filename); echo $pieces[0] . $pieces[1] . $pieces[2] . "feedback.html"; ?>
And that’s it. Again, any comments or suggestions you have are most welcome.