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[0] 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[4], 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.
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Dynamic DNS—an Object Lesson in Problem Solving | May 21, 2013 |
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
- Dynamic DNS—an Object Lesson in Problem Solving
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Using Salt Stack and Vagrant for Drupal Development
- New Products
- A Topic for Discussion - Open Source Feature-Richness?
- Drupal Is a Framework: Why Everyone Needs to Understand This
- RSS Feeds
- Validate an E-Mail Address with PHP, the Right Way
- Readers' Choice Awards
- Tech Tip: Really Simple HTTP Server with Python
Enter to Win an Adafruit Pi Cobbler Breakout Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Pi Cobbler Breakout Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- 5-21-13, Prototyping Pi Plate Kit: Philip Kirby
- Next winner announced on 5-27-13!
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?




38 min 58 sec ago
1 hour 11 min ago
3 hours 34 min ago
3 hours 38 min ago
3 hours 39 min ago
8 hours 4 min ago
9 hours 55 min ago
15 hours 8 min ago
18 hours 19 min ago
20 hours 35 min ago