Quizzer is an online support tool for academic writing instruction. It can be installed with a single command, requires no student IDs or passwords, and works well with classes made up of students at varying stages of language acquisition, and from diverse language backgrounds.
The basic concept is to use student writing as the basis for a flood of pattern-recognition exercises, cast as online quizzes delivered by email. By raising the pace of iteration, the aim is to help students internalize a sense of grammatical anomalies and stylistic infelicities.
While Quizzer can be used to generate multiple-choice quizzes for a variety of purposes, the workflow it was built for runs like this:
- Students submit a 400-word essay once each week on an arbitrary topic.
- The instructor selects representative errors of style and grammar from the submissions, and composes a multiple-choice question consisting of the student's own sentence, two alternatives that also contain errors, and a corrected version.
- After constructing one question from each submitted essay, students are sent personalized links to the resulting quiz.
- Students submit their responses, which are recorded on the Quizzer server. Students receive feedback immediately feedback on their incorrect responses. Neither the essays nor the quiz results are assessed.
- Class commenters (TAs, instructors, and other experienced writers) post short explanations of why the wrong answers were wrong. Where appropriate, commenters from the students' own language domain can be brought in to provide supplementary native-language guidance.
- Class commenters of the target language domain can set persistent "rules" on-the-fly to cover issues that arise frequently. These rules can then to set as comments on specific wrong answers, and they can be translated by native-language commenters, for reference by students of the same language domain.
- When students revisit their quiz links, they will find their errors attached with explanatory rule, comments, and a list of classmates who answered the question correctly.
- Students are given an assessed, paper-based, multiple-choice supplementary mid-term and final exam, consisting entirely of questions from the quizzes.
Quiz distribution, commenting, exam composition, and marking are all managed by Quizzer. Paper tests are randomized as a hedge against cheating, and marked with a barcode reader for quick assessment.
The initial inspiration for Quizzer was a small code
sample
posted by Chetan Jain. The code has been refactored and extended
considerably for this project, but I gratefully acknowledge the
starting point for this frolic. Hats off also to the developers of
node.js
, and LaTeX and, well, everything else. Quizzer was built on
short notice to fill a critical need, and it has been a real pleasure
to see how quickly it could be brought together, and how smoothly
it could be extended.
Quizzer is a node.js
module. To get the website running, the
minimum requirements are:
npm
>=1.3.xnode
>=0.10.x
In addition, the following external utilities are required for the typesetting of exams:
pandoc
>=1.11.x (preferably compiled with texmath support)- either
pdflatex
, orplatex
anddvipdfmx
(the latter pair is needed only if Japanese text must be handled)
LaTex (pLaTeX) documents created by Quizzer use the following packages:
makebarcode
marginnote
graphicx
tikz
ctable
float
hyphenat
amsmath
Quizzer must have access to a mail transfer agent (MTA). This can
either be a sendmail
instance running on the same server, or a mail
API to a service such as GMail.
With the above requirements in place, Quizzer can be run on a
workstation for initial trials, accessed via a port on localhost
(aka 127.0.0.1
). For production use, Quizzer should be placed behind
a webserver, such as lighttpd
or apache
. Instructions for setting
up the former are given below.
Install quizzer from the npm
repository:
npm install quizzer
Run the server by saving the following code to a file (say, quizServer.js
):
var qz = require('quizzer');
qz.run();
Run the script from command line like this:
node ./quizServer.js
The script will whinge on first run, asking for some essential details:
usage: quizServer.js [-h] [-v] [-H PROXY_HOSTNAME] [-Q QUIZZER_PATH]
[-p REAL_PORT] [-e EMAIL_ACCOUNT] [-s SMTP_HOST]
[-l LOCALE] [-P] [-E]
Quizzer, a quiz server
Optional arguments:
-h, --help Show this help message and exit.
-v, --version Show program's version number and exit.
-H PROXY_HOSTNAME, --proxy-hostname PROXY_HOSTNAME
Host name for external access
-Q QUIZZER_PATH, --quizzer-path QUIZZER_PATH
Server path to quizzer (default: "/quizzer/")
-p REAL_PORT, --real-port REAL_PORT
Port on which to listen for local connections
(defaults to 3498)
-e EMAIL_ACCOUNT, --email-account EMAIL_ACCOUNT
Full username of email account (e.g. [email protected])
-s SMTP_HOST, --smtp-host SMTP_HOST
SMTP host name (e.g. smtp.gmail.com)
-l LOCALE, --locale LOCALE
Language locale for admin interface ("en" or "ja")
-P, --use-platex Use platex engine + dvipdfmx for PDF generation
-E, --use-euc-jp Convert input text from UTF8 to legacy EUC-JP
encoding before LaTeX processing
ERROR: must set option proxy_hostname
ERROR: must set option email_account
To get Quizzer running, set proxy_hostname
to localhost
(or 127.0.0.1
), and
set email_account
to your mail address ([email protected]
in the example below):
node ./quizServer -H localhost -e [email protected]
Quizzer will come up with a message like the following:
Wrote config parameters to quizzer-3498.cfg
Quizzer can now be run with the single option: -p 3498
Message: no mypwd.txt file found, will use local Sendmail transport
Using local Sendmail transport
Admin URL: http://localhost:3498/?admin=179359xq
Adding admin role
Loaded class membership keys
Woke up the mail schedulers
Done. Ready to shake, rattle and roll!
The website can now be accessed at the URL reported in the fifth line.
(Note that the admin
key is automatically generated, and will differ
from that shown in the example above.)
The database and configuration files are created in the directory from
which the script is run, named after the port number. The server can
be shut down with CTRL-c
(SIGINT
), and as the startup message
says, it can be restarted with the single option -p <REAL_PORT>
A full explanation of the remaining options will be added to this README as time permits.
When PROXY_HOSTNAME
is set to a fully qualified domain name
(e.g. myschool.edu
), it will assume that it is being run behind a
reverse proxy, and adjust URLs accordingly. Quizzer itself has only
the thinnest concept of security, and should be run behind a proxy in
production (and preferably over SSL). Access to the administrator
display depends on a key set in the URL of a GET request. Rewrite
rules on the front-end web server should be used to assure that
attempts to set the key directly are rerouted through a
password-protected URL.
If lighttpd
is used as the front-end server, and Quizzer is run from
a directory quizzer
to which the server has access, configuration
settings like the following should do the trick:
url.rewrite = (
"^(?!/quizzer)(.*)\?admin=[^&]+(?:&(.*))*" => "/quizzer/admin.html$1?$2",
"^(?!/quizzer)(.*)&admin=[^&]+(?:&(.*))*" => "/quizzer/admin.html$1&$2",
"^/quizzer/admin.html$" => "/quizzer/admin.html?admin=fyvg19vx",
"^/quizzer/admin.html\?(.*)$" => "/quizzer/admin.html?admin=fyvg19vx&$1"
)
$HTTP["host"] == "faculty.of.things.edu" {
proxy.server = ( "/quizzer" => ( ( "host" => "127.0.0.1", "port" => 3498 ) ) )
}
auth.backend = "htdigest"
auth.backend.htdigest.userfile = "/etc/lighttpd/lighttpd.user"
auth.require = ( "/quizzer/admin.html" =>
(
"method" => "basic",
"realm" => "Quiz Admin",
"require" => "user=quizmaster"
)
)