#!/usr/bin/perl5
# Create an HTML quiz. There are two output files-- the quiz and the
# result files-- and one input file. The input file has these tags:
# >>QUIZ-TITLE
the titles of the output files
# >>QUIZ-NAME names the form and output files (name.html and
# name_result.html
# >>QUIZ-HEAD
# + the leading text in the quiz
# >>QUIZ-FOOT
# + the trailing text in the quiz
# >>QUIZ-RHEAD
# + the leading text in the result
# >>QUIZ-RFOOT
# + the trailing text in the result
# >>QUIZ-QUEST quiz question
# Q + text of question
# [CR][WR]+ column or row, wrong or right response
# R + text to print for correct answer
# W + text to print for wrong answer
# B + text to print for either answer
$state = 'start';
$fields = 0;
while(<>) {
if(/^>>QUIZ-([A-Z]+)\W/) {
if($1 eq 'TITLE') {
m/^>>QUIZ-TITLE\s+(\w.+)$/;
$title = $1;
}elsif($1 eq 'NAME') {
m/^>>QUIZ-NAME\s+(\w.+)$/;
$name = $1;
}elsif($1 eq 'HEAD') {
$state = 'head';
}elsif($1 eq 'FOOT') {
$state = 'foot';
}elsif($1 eq 'RHEAD') {
$state = 'rhead';
}elsif($1 eq 'RFOOT') {
$state = 'rfoot';
}elsif($1 eq 'QUEST') {
$state = 'quest';
$quest = (defined $quest) ? $quest+1 : 0;
$row = 0;
$col = 0;
$ans= 0;
}
}
elsif($state eq 'head') {
$head[++$#head] = $_;
}
elsif($state eq 'rhead') {
$rhead[++$#rhead] = $_;
}
elsif($state eq 'foot') {
$foot[++$#foot] = $_;
}
elsif($state eq 'rfoot') {
$rfoot[++$#rfoot] = $_;
}
elsif($state eq 'quest') {
# A quiz question, which consists of:
# the text of the query, tagged by a leading Q
# the answers, tagged by a leading [RC][RW]:
# R means start a new row of answers
# C means start a new column of answers
# R means this answer is correct
# W means this answer is wrong
# text of the question grading, tagged by [RWB]
# The order in which the questions and the answers to each question
# are encountered in the input stream is the order in which they
# appear in the output.
# The data is stored thusly:
# $quest is the question number, 0-based
# $ans is the answer number, 0-based
# $questText[$quest] is question text
# $questAns[$quest][$ans]
# $questIndex[$quest] is the index of the correct answer
# $quest{Row,Col}[$quest][$ans] is the {row,column} of the answer
if(/^Q\s+(\S.*)$/) {
$questText[$quest] .= $1 . " ";
}
elsif(/^([RWB])\s+(\S.*)$/) {
# gradeText[][0] is printed for a correct answer.
# gradeText[][1] is printed for a wrong answer.
# gradeText[][2] is printed for both, afterwards.
$gradeText[$quest][($1 eq 'R') ? 0 : (($1 eq 'W') ? 1 : 2)] .=
$2 . " ";
}
else {
m/^(.)(.)\s+(\S.*)$/;
$questAns[$quest][$ans] = $3;
$questIndex[$quest] = $ans if($2 eq 'R');
$questRow[$quest][$ans] = $row;
$questCol[$quest][$ans] = $col;
$fields++ if($col > $fields);
if($1 eq 'C') {
$col++;
} else {
$row++;
$col = 0;
}
$ans++;
}
} # state eq 'quest'
} # loop on input lines
# Validate.
for($quest = 0; defined $questText[$quest]; $quest++) {
die "No correct answer for question $quest ($questText[$quest]).\n"
if(!defined $questIndex[$quest]);
}
$title = 'Quiz' if(!defined $title);
$name = 'quiz' if(!defined $name);
open(QUIZ, ">${name}.html") || die "Can't open ${name}.html for write.\n";
open(R, ">${name}_result.html") ||
die "Can't open ${name}_result.html for write.\n";
# Emit the code.
# Header.
print QUIZ <<"HTML";
$title
$title
HTML
print QUIZ @head;
print QUIZ <<"HTML";
HTML
print QUIZ @foot;
print QUIZ "\n\n";
close(QUIZ);
# Emit the results.
# Header.
print R <<"HTML";
$title Results
$title Results
HTML
print R @rhead;
print R <<"HTML";
\n";
# Trailer.
print R @rfoot;
print R "\n\n";
close(R);