Creating a Multiple Choice quiz System, Part 3
Last month, we continued looking at ways to improve the user interface of our CGI quiz engine. This engine is based on the QuizQuestions.pm Perl module and allows us to create a number of different multiple-choice quizzes. Each quiz is stored in a separate ASCII text file on the server's file system, and thanks to the abstraction layer provided by the QuizQuestions object, we are able to ignore the way in which the information is stored and focus on the quiz itself.
Or can we? As we saw last month, it is relatively easy for us to create a quiz using HTML forms and a CGI program. Indeed, we created such a program without much trouble; still, as I pointed out at the end of last month's column, our job is only half done. Using an HTML form and CGI program simplifies the process of creating quiz files and reduces the potential for error. However, of someone wants to modify a quiz that he has already created, he still has to understand our file format and make sure not to disturb it. It would be nice to have a single program which allowed users to create and modify their quizzes, saving them from having to work directly with quiz files.
Such a program would be desirable for its error-free, user-friendly quiz creation. We use text files to store information with tabs or other special characters separating fields within a given record. Fewer problems will ensue if we can provide a graphical interface that restricts the type of data that our users can input. In addition, a quiz editor would empower the designers and producers on our site—who, at an increasing number of sites, are kept separate from the technical staff responsible for creating CGI programs and keeping the network up and running. While you might be an experienced system administrator who knows the difference between tabs and spaces and doesn't flinch before editing /etc/fstab or a Makefile, most content-oriented people on a site are not experienced users. If we can provide a tool that creates and modifies quizzes without the need to learn Emacs, come to us with questions or tear their hair out in frustration, then why not?
Last month, we looked at a simple program, create-quizfile.pl, which took information from an HTML form and correctly formed it into a quiz file. This month, we take the basic idea behind that quiz creator and look at how we can write a quiz editor. That is, our new program will allow us to create quizzes, just as the previous one did, but will also let us edit quizzes by modifying the text of questions and answers or deleting existing questions from the quiz file.
From the above description it seems as though our basic unit of operation is a line of text in the quiz file that will contain a question. The easiest way to handle these data is to keep track of them in an array of strings, which we call @lines. This means $lines is the first non-comment, non-whitespace line in the quiz file—in other words, the first set of questions and answers. For example, to find the third answer to the fifth question, we call up $lines, split it across tabs using Perl's “split” operator, and read the fourth element of that array. Each line of the quiz file is of the format question answer1 answer2 answer3 answer4 correctAnswer, with each field separated from its neighbor by a tab character. Each line of the quiz file can be represented by a string containing the tabs or by a list created by splitting the string across the tab character.
Luckily, we don't have to think much about the format of the quiz file, thanks to the QuizQuestions object module we have used so far. When we create a new instance of QuizQuestions, we effectively create a new, blank quiz. To add questions to that quiz, we use the addQuestion method, which expects to receive six arguments—not surprisingly, the same arguments as appear on each line of the quiz file.
To create a brand-new quiz our program, called edit-quiz.pl, must create an HTML form containing elements into which the user can enter one or more questions and answers. To edit an old quiz file, edit-quizfile.pl has to create an instance of QuizFile corresponding to a quiz file already existing on disk. It then must read the questions from that quiz file, turning each question into a set of HTML form elements. This lets the user edit the questions and answers, delete existing questions and add new ones.
But wait a second—if edit-quizfile.pl is going to create the HTML form that the user will use for editing a quiz, which program will take the contents of this form and actually do something with it? After all, CGI programs are single operations: they receive input, perform some processing and produce output. It seems if our program produces an HTML form as output, it cannot also accept input from that form and save it to disk. The secret here is that edit-quizfile.pl can accept its own input by expecting to be invoked twice. On the first invocation, it creates the form to be used to edit quizzes, and on the second invocation, it saves the submitted data in the form of a quiz. Our program thus performs two different actions on two distinct occasions.
Why not simply write two separate programs, one to display the form and a second to process it? We certainly could have handled it in this way, but this would restrict us to a single iteration of editing. By keeping all of the quiz-editing features within a single program we can create an editing loop that allows us more than a one-shot deal. We can reuse the code for displaying the current state of the quiz file, because we always display the quiz's file state when our program is invoked. By keeping all the code within one program and simply putting the display code at the bottom of this program, everything becomes a bit easier to understand and maintain.
Free DevOps eBooks, Videos, and more!
Regardless of where you are in your DevOps process, Linux Journal can help!
We offer here the DEFINITIVE DevOps for Dummies, a mobile Application Development Primer, and advice & help from the expert sources like:
- Linux Journal
- Be a Mechanic...with Android and Linux!
- New Products
- Users, Permissions and Multitenant Sites
- Flexible Access Control with Squid Proxy
- Security in Three Ds: Detect, Decide and Deny
- High-Availability Storage with HA-LVM
- Tighten Up SSH
- Solving ODEs on Linux
- DevOps: Everything You Need to Know
- Non-Linux FOSS: MenuMeters