PASS — Preparing Programming Assignments for Submission System

This application was written for the School of Computing Sciences, UEA to help prepare programming assignments for submission according to the school requirements. Source code is now available on GitHub.

Requirements

Variants

The following applications all use the same passlib.jar backend:

PASS GUI
the original application with a GUI frontend.
PASS CLI
a command line alternative for devices that don’t support a graphical user interface.
Server PASS
a variation of PASS CLI used in a Docker image running on a server for student’s studying remotely.
PASS Editor
provides a primitive text editor interface for use by students sitting a practical exam in the lab. Unlike common IDEs, this doesn’t provide any hints or autofilling. (So it’s like switching off the spellchecker and grammar checker for students who are allowed to use a word processor when sitting an English exam.)

Basic editing functions (undo/redo, copy, cut, paste, go to line, and search) are provided. There is a basic project file navigation panel with the ability to create additional files. Required files are created automatically and assignment resource files are fetched. The editor panel doesn’t allow the resource files to be edited. However it is possible for the student to use another installed text editor to modify them.

There is a function for compiling and running the code in the project directory for testing purposes. As with other PASS applications, this obeys the compile, run and build attributes. However, this function doesn’t refresh the project resource files from the original remote location as it’s designed for quick testing.

There is another function that runs the PASS backend which copies the project files to PASS’s working directory and will fetch the project resource files from their remote location. So if the student does use another editor to modify their local copy of the resource files those modifications won’t make it into the version used by the backend.

Additionally, there is a staff-only command line application that can be used to verify the submitted PDF files to check for signs that the file may have been altered after it was created by PASS. (PASS adds some custom encrypted PDF metadata that can be double-checked against information provided in the unencrypted areas. Any inconsistencies will be flagged.)

Resource Files (Courses)

The local and remote resource XML files have the same syntax. Note that the URL must be the exact address. Redirects aren’t permitted (including any redirects from http: to https:). SSL/TCP requires a valid certificate in Java’s cacerts file. The same applies for URL references in other elements described below. There’s a dummy course available for testing in the referenced dummy-resources.xml file:

 <resource name="CMP-123XY"
  href="http://www.dickimaw-books.com/software/pass/dummy-assignments.xml">
 Dummy Course for Testing
 </resource>
You can use this as a template for new courses but I recommend a better naming scheme. For example, CMP-123XY.xml. Remember to use one <resource> tag per course.

You may omit the remote resource file and just have all the courses defined within the local lib/resources.xml file. The disadvantage with this is that if you need to add a new course you will need to update the local lib/resources.xml file for each installed version of PASS (for all variants). This is particularly awkward for Server PASS as it would require rebuilding the Docker image.

Each course that uses PASS for student submissions needs to have an assignment XML file that the lecturer can edit to add the assignment data. These XML files need to be placed somewhere on the university’s site in a location that can be accessed by the PASS application. For each course, a corresponding resource block must be added to the local lib/resources.xml file or remote resource file (as described earlier), with the name element set to the course code ("CMP-123XY" in the above example) and the href element set to the URL of the assignment database. The content of the resource block ("Dummy Course for Testing" in the above example) is the course title. You may additionally add debug="true" or debug="on" if you only want the course available when PASS is running in debug mode.

The PASS application will search for the compiler on the OS path. If the compiler isn’t on the system path, you can specify the location in the lib/resources.xml file using the application tag with the name element set to the application identifier (e.g. javac) and the uri element set to the URI of the application’s path. For example:

 <application
   name="javac"
   uri="file:///usr/java/latest/bin/javac"
 />
You can have multiple application tags. One for each application. Currently supported applications: javac, java, g++, gcc, perl, lua.

Whilst you can have <application> in a remote resource XML file, it’s more appropriate to put it in the local resource file as the paths are likely to be different for different installations of PASS.

Note that pdflatex or lualatex is also required to build the PDF file. (The attachfile package doesn’t work with xelatex.)

Testing

The PASS application can be tested using the dummy course. If there’s only one resource tag in the local or remote resource XML file, that course will automatically be selected on startup. If there are multiple courses, the application will present a list from which you can select the required course. The dummy course comes with a number of different assignments allowing you to test each supported programming language. The PASS GUI application will automatically select the assignment closest to its due date. You can use the drop-down menu to select a different assignment. The dummy assignments are listed below. These only require the creation of a single file containing the assignment code. In practice, assignments are likely to require multiple files, but the same instructions apply. It’s also possible for students to add additional source files if they have created more than the required set.

Hello World C

This assignment requires a C program that prints “Hello World!” to STDOUT. The code must be supplied in a single file called helloworld.c. To test PASS with this dummy assignment, create a file called helloworld.c that contains the following:

#include <stdio.h>

int main()
{
   printf("Hello World!");

   return 0;
}
Start up PASS GUI and select "Hello World C" from the assignment list. Click on "Next" to move to the next panel. Select the directory containing the helloworld.c file and click "Next". Hopefully, the full path to helloworld.c should be listed. If the file is simply listed as helloworld.c without the full path, then the file wasn’t found. You can use the file selector button to find it or go back to the previous panel and check that you selected the correct directory. (If the student wasn’t able to complete the assignment, they can continue with the submission process even if some of the required files are missing.)

Once the file has been found, click on "Next" and PASS will process the assignment. If successful, it will open a save dialogue window allowing you to save the PDF. (If you click "Cancel", a "Save As..." button will appear at the bottom of the PASS window.) After the PDF file has been saved an "Open PDF" button will appear at the bottom of the PASS window, which should launch your default PDF viewer and open the PDF file in it.

Hello World C++

This assignment is much the same as the previous except that it requires C++ instead of C. The assignment must be supplied in the file helloworld.cpp. If you want to test it, the file contents are:

#include <iostream>
using namespace std;

int main()
{
   cout << "Hello World!\n";
   return 0;
}
Follow the same instructions as above.

Hello World Java

This assignment is much the same as the previous two except that it requires Java. The assignment must be supplied in the file HelloWorld.java. If you want to test it, the file contents are:

package helloworld;

public class HelloWorld
{
   public static void main(String[] args)
   {
      System.out.println("Hello World!");
   }
}
Follow the same instructions as above.

Test Read File Java

This dummy assignment requires a Java application that reads the file dummy.txt and writes the contents to STDOUT with the line number prefixed. The file dummy.txt is available at http://www.dickimaw-books.com/software/pass/dummy.txt. The assignment resource file indicates this with the following element:

  <resourcefile src="http://www.dickimaw-books.com/software/pass/dummy.txt" />
PASS will fetch it from that location when it tries to compile and run the code. To test this example, create a file called TestReadFile.java that contains the following:
package testreadfile;

import java.io.*;

public class TestReadFile
{
   public static void main(String[] args)
   {
      try
      {
         File file = new File("dummy.txt");

         BufferedReader in = new BufferedReader(new FileReader(file));

         String line;
         int lineNum=0;

         while ((line = in.readLine()) != null)
         {
            lineNum++;
            System.out.println(String.format("%d. %s", lineNum, line));
         }

         in.close();
      }
      catch (Exception e)
      {
         e.printStackTrace();
      }
   }
}

Make a PNG Image Java

This is a dummy Java assignment that must create an image file called image.png and a text file called output.txt. This is indicated with:
   <resultfile type="image/png" name="image.png" />
   <resultfile type="text/plain" name="output.txt"/>
The code must be supplied in the file MakeImage.java. The file contents are shown below:
package makeimage;

import java.io.*;
import java.awt.image.*;
import java.awt.*;
import javax.imageio.ImageIO;

public class MakeImage
{
   private static void test() throws IOException
   {
      BufferedImage image = new BufferedImage(100, 100,
       BufferedImage.TYPE_INT_ARGB);

      Graphics2D g2 = image.createGraphics();

      if (g2 != null)
      {
         g2.setComposite(AlphaComposite.Src);

         g2.setColor(Color.YELLOW);
         g2.fillRect(0, 0, 100, 100);

         g2.setColor(Color.BLUE);

         g2.drawRect(10, 10, 80, 60);

         g2.dispose();
      }

      ImageIO.write(image, "png", new File("image.png"));

      File file = new File("output.txt");

      PrintWriter writer = new PrintWriter(file);

      writer.println("Test output.");

      writer.close();    
   }


   public static void main(String[] args)
   {
      try
      {
         test();
      }
      catch (IOException e)
      {
         e.printStackTrace();
      }
   }
}

Hello Input Perl

This dummy assignment requires the creation of a Perl script called hello.pl that requires the user to input a name and a colour. The assignment resource file provides dummy input that’s used when testing the script:

   <input>Sample Name</input>
   <input>Sample Colour</input>
The required Perl code is listed below:
#!/usr/bin/perl

print "What's your name? ";

my $name = <STDIN>;

chomp $name;

print "Hello ", $name, "!\n";

print "What's your favourite colour? ";

my $colour = <STDIN>;

chomp $colour;

print "Your favourite colour is '$colour'.\n";

1;

Hello Arg Lua

This dummy assignment requires Lua code in a file called hello.lua that takes a command line argument. The assignment resource file supplies a dummy argument that’s used when testing the script:

   <arg>Sample Name</arg>
The Lua code is:
#!/usr/bin/lua

if #arg < 1
then
  error("Syntax error: argument missing")
end

print("Hello ".. arg[1] .."!\n")

Free-Form Example

This example requires at least PASS v1.06 as it doesn’t have a mainfile element. It represents an assignment that only requires the student to include a report file called reportdoc1.pdf or reportdoc1.doc or reportdoc1.docx. They may submit other files as well, but there are no required source code files. The assignment is identified as follows:

 <assignment name="freeform" compile="false" >
  <title>Free-Form</title>
  <due>2017-04-30 15:00</due>
  <report>reportdoc1</report>
 </assignment>

In this case, PASS won’t attempt to compile or run any code because there is no main file. Without the compile="false" attribute this will cause a warning in case the main file was omitted by accident.

Test Build Hello Lua

This dummy assignment requires Lua code in a file called hello.lua but unlike the earlier "Hello Lua" example, this one comes with a custom build script, which is identified with the build attribute:

build="http://www.dickimaw-books.com/software/pass/dummy-build.sh"
This automatically switches off the compile and run attributes and instead fetches the build script and uses that to perform the appropriate steps required to build and test the application. In this case, there’s no compilation required as Lua is a scripting language. The build script simply prints text to STDOUT and runs the script:
#!/usr/bin/env sh
echo "Test Build Script"
texlua hello.lua Test
The hello.lua script from the earlier "Hello Lua" example can be used for this example as well.

Test Build Hello Lua (With Output File)

This is like the above but the custom shell script runs hello.lua with STDOUT redirected to the file output.txt. This file needs to be included in the PDF generated by PASS, so it’s necessary to list it as a result file:

 <assignment name="testbuild2" build="http://www.dickimaw-books.com/software/pass/dummy-build2.sh" >
   <title>Test Build Hello Lua (With Output File)</title>
   <due>2021-01-02 15:00</due>
   <mainfile>hello.lua</mainfile>
   <resultfile type="text/plain" name="output.txt"/>
 </assignment>

Note that this example requires at least PASS GUI v1.23 or PASS CLI v1.04.

Hello World Template (Java)

This example is essentially the same as the earlier Hello World Java assignment but it’s designed for PASS Editor with a template file that contains bugs and a stub method that the students have to correct. The template is identified with the template attribute:

  <mainfile template="http://www.dickimaw-books.com/software/pass/dummy-HelloWorld.java">HelloWorld.java</mainfile>
When PASS Editor is used with this assignment, it will create a file called HelloWorld.java and add the contents of the referenced template to it. When used with the other PASS applications, the template will be ignored.

Assignment XML Files

Each course has a separate XML file that’s identified in the local lib/resource.xml file or in the remote resources XML file (identified in lib/resource.xml with the <courses> element). For example:

<?xml version="1.0"?>
<resources>
 <resource name="CMP-1234X" 
   href="http://www.example.com/pass/CMP-1234X.xml">
 Introductory Programming
 </resource>
 <resource name="CMP-1234Y"
   href="http://www.example.com/pass/CMP-1234Y.xml">
 Advanced Programming
 </resource>
</resources>

The assignment XML file for the given course is identified by the href attribute. The referenced assignment XML file should have the structure:

<assignments>
  <assignment name="label">
  assignment settings
  </assignment>
  ...
  <assignment name="label">
  assignment settings
  </assignment>
  options for all assignments
</assignments>
Within the assignments block but outside of any assignment tags (options for all assignments), you can optionally have the following elements:
listings
The listings element can be used to adjust the listings style. For example, to make the identifiers blue:
 <listings>identifierstyle=\color{blue}</listings>
(See the listings documentation for further details.) This will be applied to all the assignments for the given course. This tag is cumulative. For example:
 <listings>identifierstyle=\color{blue}</listings>
 <listings>stringstyle=\color{lightgray}</listings>
is equivalent to:
 <listings>identifierstyle=\color{blue},stringstyle=\color{lightgray}</listings>
geometry
Similarly as from v1.05 there’s now a geometry tag, which can be used to adjust the page geometry. For example:
 <geometry>margin=10mm,includeheadfoot</geometry>
See the geometry documentation for further details.
fontspec
If LuaLaTeX is used (UTF-8) then the fontspec package will be loaded. You can provide commands that should be loaded after this package with the fontspec tag. For example:
<fontspec>
\setromanfont{FreeSerif}
\setsansfont{FreeSans}
\setmonofont{FreeMono}
</fontspec>
The options attribute may be set to specify any options that should be passed to fontspec. This tag is cumulative. If omitted the default is:
<fontspec>
\usepackage{lmodern}
</fontspec>
If LuaLaTeX isn’t used this tag has no effect.
fontenc
If PDFLaTeX is used (ASCII or Latin-1) then the fontenc package will be loaded. You can provide commands that should be loaded after this package with the fontenc tag. For example:
<fontenc>
\usepackage{noto}
</fontenc>
The options attribute may be set to specify any options that should be passed to fontenc. This tag is cumulative. If omitted the default is:
<fontenc options="T1" >
\usepackage{lmodern}
</fontenc>
maxoutput
To guard against excessive chatter to STDOUT, PASS will truncate any output that exceeds maxoutput. The default value for this setting is 10240 but you may change it in the XML file with:

<maxoutput>value</maxoutput>
verbatim
Known languages are typeset using \lstinputlisting but other verbatim content (plain text files, messages to STDOUT/STDERR) is written to a temporary file (rather than using the verbatim environment) and input with \verbatiminput. The content is preprocessed by PASS to break up long lines and replace TAB characters with spaces (since this is something that’s easier to do in Java than in TeX). The default is to break up lines that exceed 80 characters and use 8 spaces for TAB characters. You can change these values with the verbatim tag, which has the attributes maxchars and tabcount to set the maximum characters per line and TAB character count, respectively. For example:
 <verbatim maxchars="85" tabcount="4" />
The assignment element may have the following attributes:
name
The name attribute should be a short label identifying the assignment. For example:
<assignment name="helloworld">
The only permitted characters within the name attribute are: a-z, A-Z, 0-9, . (dot), + (plus) and - (hyphen). Note that the name may be used to form filenames.
run
PASS will automatically try to test the application (after the code has been compiled if required). If you want to skip this test, set the run attribute to false. For example:
<assignment name="helloworld" run="false" >
compile
You can also skip the compile step if required with the compile attribute set to false. Note that this will automatically implement run="false" as well. The compile step is automatically skipped for non-compiled languages (such as Lua) but since compile="false" sets run="false", this setting will prevent non-compiled languages from being run, so only use it for compiled languages.
build
If you require a custom build, you can now (v1.19+) use the build attribute. The value should be the URL where the build script can be fetched from. This option automatically switches off the compile and run attributes. Any required compiling or execution should be performed by the build script.

language
The programming language that the code is written in (see below).
variant
The variant of the programming language (see below).

The contents of the assignment tag must include

<title>Assignment Title</title>
<due>Due Date</due>
<mainfile>filename</mainfile>
(As from PASS v1.06, the mainfile element is now optional. If omitted, PASS won’t attempt to compile or run any code.) The due date must be given in the format YYYY-MM-DD HH:mm. For example, a minimal assignment where the students are only required to submit the file helloworld.c:
 <assignment name="helloworld">
  <title>Hello World</title>
  <due>2016-10-02 16:30</due>
  <mainfile>helloworld.c</mainfile>
 </assignment>
Additional required files are marked up with the optional file tag. For example, if the students are required to submit Foo.java, Bar.jar and FooMain.java, where the main method is in FooMain.java:
 <assignment name="foobar">
  <title>Foo Bar</title>
  <due>2016-10-02 16:30</due>
  <file>Foo.java</file>
  <file>Bar.java</file>
  <mainfile>FooMain.java</mainfile>
 </assignment>

The order of the file and mainfile tags determines the listing order in the PDF. Both the file and mainfile tags allow the following attribute:

template
The value should be a URL to a file containing template code used by PASS Editor when initialising a project. Other PASS applications ignore the value (but the value is still parsed and so must be a well-formed URL).

There are two optional attributes to the assignment tag related to the code listings: language and variant. PASS tries to determine the appropriate language setting for the listings package when creating the PDF file by testing for known file extensions. For example, if the extension is .c then "C" is assumed. If it’s unable to determine the language from the extension, then \verbatiminput is used instead. The language tag provides a fallback to use as a default if this happens. The value must be recognised by the listings package. If you have files that don’t have file extensions (for example, bash scripts) you’ll need to set the language attribute.

The listings package also recognises some variants for various languages. This can be supplied in the variant attribute. The value must be recognised by listings.sty. For example:

 <assignment name="helloarg" language="Lua" variant="5.0">

If the project code should be compiled, additional compiler arguments can be specified using the compiler-arg tag. There should be one tag per command line argument. For example:

<compiler-arg>-encoding</compiler-arg>
<compiler-arg>UTF-8</compiler-arg>

There is an analogous tag invoker-arg for arguments that should be passed to the invoker. For example, to set the default line ending for the JVM to "\r\n":

<invoker-arg>-Dline.separator=&#x0D;&#x0A;</invoker-arg>

(Note the use of entities to specify the carriage return and line feed characters as you can’t use \r\n in this context.)

If the project needs to read any files provided by the assignment, each file should be identified using the resourcefile tag with the location of the original file given in the src attribute. For example, if the project needs to load the files foo.txt and bar.txt that the students were able to download from http://www.example.com/projects/foo.txt and http://www.example.com/projects/bar.txt:

   <resourcefile src="http://www.example.com/projects/foo.txt" />
   <resourcefile src="http://www.example.com/projects/bar.txt" />

If the project should be accompanied by PDF or Word reports, then these can be specified using the <report> tag. If the extension is omitted, PASS will try to search for the files according to the extensions ".pdf", ".doc" and ".docx". For example:

  <report>projectreport1</report>
  <report>projectreport2</report>

If the project must generate a file or files, each file name should be listed in the resultfile tag with the name attribute set to the file name and the type attribute set to the mime type for that file. For example, if the project must create an image file called image.png and a text file called output.txt, then:

   <resultfile type="image/png" name="image.png" />
   <resultfile type="text/plain" name="output.txt" />

Each file will be attached to the PDF. In addition, if the mime type starts with text the contents will be listed and if the mime type starts with image the file will be included with \includegraphics. If you want to skip the file inclusion and only have it attached, set the listing attribute to "false". For example:

   <resultfile type="text/plain" name="output.txt" listing="false"/>

If the project application requires command line arguments, use the arg tag for each argument. For example:

   <arg>Sample Name</arg>

If the project application requires reading information from STDIN, use the input tag to provide each line of test data. For example:

   <input>Sample Name</input>
   <input>Sample Address</input>