#!perl -w # practice7 - QuizMaker Practice Quiz data parser VERSION 07 # Copyright 1999, Attotron Biosensor Corporation # Permission is hereby granted for non-profit use. # Please do not distribute modified copies without permission (info@attotron.com). # This program is under development - see www.attotron.com/pub/quizmaker.html # Configuration variables: my $image_path = "images/"; # relative path to images my $index_columns = 2; # number of columns for Index table my $def_delimiter = ":"; my $dictionary_text = "dictionary.txt"; # input file my $dictionary_name = "diction.htm"; # output file my $indexfile = "index.htm"; # index of practice quiz pages # globals my %dictionary; # dictionary hash print "Creating dictionary from file \"$dictionary_text\"...\n"; makeDictionary($dictionary_text); print "...dictionary created.\n"; ################################## # CREATE THE PRACTICE QUIZ FILES # # AND INDEX PAGE # ################################## @quiznames = glob("*.quiz"); open(QUIZINDEX, ">$indexfile") || die "Could not open $indexfile: $!"; print QUIZINDEX < Quiz Index

Index of Practice Quizzes

\n
    \n
      HTML foreach my $datafile (@quiznames){ print "Processing file \"$datafile\"...\n"; my $htmlfile = $datafile; $htmlfile =~ s/\.quiz/\.htm/; my $quiztitle = practiceQ($datafile,$htmlfile); print QUIZINDEX "\t
    • $quiztitle\n"; print "...file \"$htmlfile\" created.\n"; } print QUIZINDEX "
    \n
    \n\n"; close(QUIZINDEX) || die "Could not close $indexfile: $!"; print "Index file \"$indexfile\" created.\nFinished.\n\n"; ### SUBROUTINES ### sub makeDictionary{ # create the dictionary file my($dictionary_text) = @_; open(DICTDAT, $dictionary_text) || die "Could not open $dictionary_text: $!"; # read first line as title my $title_line = || die "First line of input file is not a suitable name!: $!"; $title_line = filterHTMLchars($title_line); my @title_array = split(/,/,$title_line); my $title = shift @title_array; open (DICTHTML, ">$dictionary_name") || die "Could not open $dictionary_name: $!"; # output file print DICTHTML "\n$title\n\n"; print DICTHTML "

    $title

    "; while (my $subtitle = shift @title_array){print DICTHTML "$subtitle
    \n";} print DICTHTML "
    \n
    \n"; # create dictionary hash table from text file entries while (defined(my $line = )) { if ($line=~/^\s*$/) {next;} # skip blank lines (my $term, $definition) = split($def_delimiter, $line); $dictionary{$term} = $definition; # use .= to allow multiple definitions? # terms and defs are NOT HTML filtered inside hash } # create HTML index table of dictionary terms my $colwidth = 100/$index_columns; print DICTHTML "
    \n
    Index
    \n
      \n"; my $numterms = keys(%dictionary); # in scalar context, keys() returns number of keys my $termnum = 0; foreach my $term (sort alphabetically keys %dictionary){ my $linkedterm = crossref($term,"Cest_ne_pas_une_term."," "); print DICTHTML "
    • $linkedterm\n"; if (++$termnum % (($numterms/$index_columns)+1) == 0) {print DICTHTML "
      "}; # ^increment ^modulus This line starts new column in table, based on number of entries. percent^ } print DICTHTML "
    \n
    \n
    \n
    \n"; # write cross-indexed HTML definitions from dictionary hash entries foreach my $term (sort alphabetically keys %dictionary){ my $linkedline = crossref($dictionary{$term},$term," "); unless ($linkedline) {next;} my $anchor = despace($term); print DICTHTML "

    $term

    $linkedline
    "; print DICTHTML "
    Back "; print DICTHTML "Index

    \n"; } print DICTHTML "\n

    Another dictionary by QuizMaker"; print DICTHTML "
    \n\n\n"; close(DICTHTML); } sub by_number_of_words { my @aWords = split(/\b/,$a); my @bWords = split(/\b/,$b); @bWords <=> @aWords; # using array in scalar context = length } sub alphabetically { lc($a) cmp lc($b); } sub practiceQ { my($infile,$outfile) = @_; if (!defined($infile)) { die("No quiz data file specified: $!") } open(QUIZDATA, "<$infile") || die("Could not open $infile: $!"); if (!defined($outfile)) { die("No output HTML file specified: $!") } open(QUIZHTML, ">$outfile") || die("Could not open $outfile: $!"); my $title = ; # first line will be title... # note no "Content-type: is needed for static pages print QUIZHTML < $title

    $title

    \n
      \n
      HTML my $lcounter = 0; # counts lines within each question while (defined(my $line = )){ $line = filterHTMLchars($line); $lcounter++; # count the line if ($line eq "") { # blank line - question seperator $lcounter = 0; # start counting over $line = "\t

      \n\t


      \n"; # horizontal rule } elsif ($lcounter == 1) { # question line $line = "

    1. \t$line

      \n"; } else { # answer line, followed by feedback line. ($lcounter > 1) $line = "\t$line

      \n"; my $letter = chr(63+$lcounter); # answer letter depends on the line's position; 2=A, etc. unless (defined($feedback = )) {next;} # next line must be feedback; qcounter not incremented $feedback = crossref($feedback,"Cest_ne_pas_une_term.",$dictionary_name); # filterHTMLchars for term $feedback = filterAlertBox($feedback); print QUIZHTML "\t\n"; } print QUIZHTML $line; } print QUIZHTML "\n

      Another quiz by QuizMaker
      "; print QUIZHTML "\n\n"; close(QUIZDATA) || die("Could not close $infile: $!"); close(QUIZHTML) || die("Could not close $outfile: $!"); return $title; } sub filterHTMLchars{ my($str) = @_; chomp($str); $str =~ s/([0-9])'/$1´/g;# use primes after numbers, assuming chemical structures NO POUND SIGNS! $str =~ s#([^\s]+)\.(jpe?g|giff?)#

      #gi; # tag images return $str; } sub filterAlertBox{ my($str) = @_; $str =~ s/'/'/g; # apostrophes = ' $str =~ s/"/\\"/g; # quotes = " must be double-escaped in feedback strings! return $str; } ### dictionary SUBROUTINES ### sub despace{ my($line) = @_; $line =~ s/ /_/g; return $line; } sub crossref { # note special case where a term is the same as an image name (negative lookahead) # not global replace - only link first use of each term in definition # sort by_number_of_words and negative lookahead for link close tag avoid nesting links my($def,$thisTerm,$dictfile) = @_; chomp($def); foreach $term (sort by_number_of_words keys %dictionary){ if ($term eq $thisTerm) { # don't link when a key appears in own definition - bold $def =~ s/\b(($thisTerm)(es|s)?(?!\.(jpe?g|giff?)))\b/$1<\/B>/gi; next; } my $anchor = despace($term); $def =~ s/\b(($term)(es|s)?)(?!\.(giff?|jpe?g))(?![^<]*(<\/A>|<\/B>))\b/"".&filterHTMLchars($1)."<\/A>"/ei; # evaluated backreference preserves capitalization } return $def; }