#!/usr/local/bin/perl -- -*-perl-*- use CGI; $query = new CGI; $title = "hidden";#change this for real applications print $query->header; print $query->start_html($title); srand; if ( $title eq "Prototype CATutils"){print "<font color=red ><h1>Change the title</h1></font>";} else{ print "<h1>$title</h1>"; }These first few lines of code are common to most applications. We first make CGI.pm available, then we print a header, and get the title up. Since we have cloned this from a prototype, we include the ``if'' statement, to make us super aware that we have or have not altered the title from the title included in the prototype.
$rate1 = int(90*$q1->rno(2)+4); $rate2 = int(90*$q1->rno(2)+4); $rate3 = int(90*$q1->rno(2)+4); print $query->start_form;Having generated the random numbers, we begin a question.
print "<font color=red>"; print "(IN MAIN)the random number generator generated rate1 = $rate1."; print "Since this one is being saved, this new value will be lost, and the old one will be restored upon submission."; print "</font>"; print "<font color=yellow>"; print "<br> (IN MAIN)the random number generator generated rate2 = $rate2 ."; print "Since this one is being saved, this new value will be lost, and the old one will be restored upon submission."; print "</font>"; print "<font color=green>"; print "<br> (IN MAIN)the random number generator generated rate3 = $rate3"; print "</font>";The above code has been adjusted to color code the kinds of saves which are being used. Red implies a traditional save, yellow denotes a subroutine based save, and green implies no save what so ever. What we mean is that the last rate, rate3, will change as the student attempts to answer the question, i.e., enters a number and pressing the Submit button. The other two variables, rate1 and rate2, will be preserved each time the student presses the return key. This does not mean that the student will get the same random variables if s/he returns some other time to this question. It is important to realize that the scheme presented here preserves the random number values only during the current session.
#------------------------------------------------------beginning of traditional saves if($query->param('rate1') eq ""){ $query->param('rate1',$rate1);}The first line of the traditional save executes fully only if the variable, in this case the CGI.pm variable 'rate1' is NULL. Then, and only then, the CGI.pm variable 'rate1' is initialized with the value $rate1. Since this is the value generated by the random number generator, this is the value the student will be stuck with for the duration of his/her session. The assignment of a CGI.pm variable's value is achieved solely using the statement:
print $query->hidden('rate1',$rate1);This statement (above) is the second part of save sequence, hiding this particular variable.
#------------------------------------------------------end of traditional saves $rate1 = $query->param('rate1'); #------------------------------------------------------end of traditional restoresThis last statement restores the variable $rate1 to its CGI.pm value. The second time this script is called, upon submission of an answer, the $rate1 value will be reassigned to a new random number, and this assignment statement restores the save CGI.pm value, which was the first value ever generated.
#------------------------------------------------------beginning of subroutine based saves $r2 = \$rate2;This first line of code is part of the ``pointer'' approach which Perl shares with several other computer languages. $r2 is assigned not the value of $rate2, but the address where this is stored. This address is called a pointer.
%list = ('rate2',$r2);This second line of code assigns a list, the first element of which is a string, 'rate2', and the second is the pointer to where this Perl variable of similar name is stored.
&save_variables(%list);Here we call a subroutine, whose argument list is the list mentioned above. Note that we could have used
#------------------------------------------------------end of traditional restores print "<br> enter a number"; print $query->textfield('number','',30,50);The question which is to be posed to the student is now inserted here. Our example is just plain silly, but who cares?
print "<br><font color=blue>Here is a dump, showing the variables CGI.pm is using:</font>"; print $query->dump;Here we dump the CGI.pm variables so you can see that there are three of them, rate1, rate2, and number. rate3 is a Perl variable, but not a CGI.pm variable.
print <<EOF; <br> (IN MAIN) <br> <font color=red> rate1 is being changed at every invocation and being saved in the normal manner. Therefore, it is having the same value at each invocation: $rate1 </font> <font color=yellow> <br>Here is rate2, using the save SUBROUTINE which should have the same value at each invocation: $rate2 </font> <font color=green> <br>Meanwhile, the third random number (rate3), not being hidden and saved, was $rate3 </font> EOFThe above code is meant to illustrate how the numbers are being saved, so that if you exercise this code, you will see, in one color, the rate1 information, in another the rate2 information, and finally in a third color, the rate3 information.
#=========start print "<br>",$query->submit; print $query->end_form; $number = $query->param('number'); $ans = $number*$rate2; print "<br>answer = number * <font color=yellow>rate2</font> = $number* <font color=yellow>$rate2</font> = $ans";As usual, once the form has ended, we get the student's response(s) and do something with those responses.
print $query->end_html; #--------------------------------------------- sub save_variables{ my $var_string = $_[0]; my $pointer_to_var_string = $_[1];The variables, which are local to the subroutine, are brought into the subroutine via these two lines. This is standard Perl.
my $debug = "false"; $var_string = "'".$var_string."'";#adjust for future use in CGI.pmHere, we adjust rate1, the string which is in $var-string, to look like 'rate1', i.e., bracket the string with apostrophes. This is because we need that form to pass to CGI.pm
if($debug eq "true"){ print "<br> (IN SUBROUTINE)var-string = ",$var_string; print "<br> (IN SUBROUTINE) qw{$query->param($var_string)}"; print "<br> (IN SUBROUTINE)", $query->param($var_string); print " <br> and \ (second variable)= ",$pointer_to_var_string; } $a = $$pointer_to_var_string;#variable passed by pointer $_[1]Here, we recoved the value of $rate1 which was not passed to the subroutine. Rather, the pointer to the $rate1 variable was passed, so we have to look there for the value, i.e., where the pointer is pointing.
if($debug eq "true"){ print "<br>(IN SUBROUTINE)called value \(loc= ",$pointer_to_var_string,") = ",$a; } if($query->param($var_string) eq '') { $query->param($var_string,$$pointer_to_var_string);#if first time, setHere we have the first part of the save sequence. If the CGI.pm variable is unassigned, assign it.
if($debug eq "true"){ print "<br>(IN SUBROUTINE) param was blank"; } }#save it print $query->hidden($var_string,$$pointer_to_var);Here we have the second part of the save sequence, where we hide the variable.
if($debug eq "true"){ print "<br>(IN SUBROUTINE) restored value(from query->param) ", $query->param($var_string); } $$pointer_to_var_string = $query->param($var_string);#update value pointed at by $_[1]Finally, here we restore the Perl variable to the value of the CGI.pm variable.
print "<br><br>====="; }Do we need (or want) this last line?
To try this script Use this Pointer
#!/usr/local/bin/perl -- -*-perl-*- use CGI; $query = new CGI; use CATutils; $q1 = new CATutils; $title = "hidden";#change this for real applications print $query->header; print $query->start_html($title); require "count.pl"; srand; if ( $title eq "Prototype CATutils"){print "<font color=red ><h1>Change the title</h1></font>";} else{ print "<h1>$title</h1>"; } $rate1 = int(90*$q1->rno(2)+4); $rate2 = int(90*$q1->rno(2)+4); $rate3 = int(90*$q1->rno(2)+4); print $query->start_form; print "<font color=red>"; print "(IN MAIN)the random number generator generated rate1 = $rate1."; print "Since this one is being saved, this new value will be lost, and the old one will be restored upon submission."; print "</font>"; print "<font color=yellow>"; print "<br> (IN MAIN)the random number generator generated rate2 = $rate2 ."; print "Since this one is being saved, this new value will be lost, and the old one will be restored upon submission."; print "</font>"; print "<font color=green>"; print "<br> (IN MAIN)the random number generator generated rate3 = $rate3"; print "</font>"; #------------------------------------------------------beginning of traditional saves if($query->param('rate1') eq ""){ $query->param('rate1',$rate1);} print $query->hidden('rate1',$rate1); #------------------------------------------------------end of traditional saves $rate1 = $query->param('rate1'); #------------------------------------------------------end of traditional restores #------------------------------------------------------beginning of subroutine based saves $r1 = \$rate1; $r2 = \$rate2; %list = ('rate2',$r2); &save_variables(%list); #------------------------------------------------------end of traditional restores print "<br> enter a number"; print $query->textfield('number','',30,50); print "<br><font color=blue>Here is a dump, showing the variables CGI.pm is using:</font>"; print $query->dump; print <<EOF; <br> (IN MAIN) <br> <font color=red> rate1 is being changed at every invocation and being saved in the normal manner. Therefore, it is having the same value at each invocation: $rate1 </font> <font color=yellow> <br>Here is rate2, using the save SUBROUTINE which should have the same value at each invocation: $rate2 </font> <font color=green> <br>Meanwhile, the third random number (rate3), not being hidden and saved, was $rate3 </font> EOF #=========start print "<br>",$query->submit; print $query->end_form; $number = $query->param('number'); $ans = $number*$rate2; print "<br>answer = number * <font color=yellow>rate2</font> = $number* <font color=yellow>$rate2</font> = $ans"; print $query->end_html; #--------------------------------------------- sub save_variables{ my $var_string = $_[0]; my $pointer_to_var_string = $_[1]; my $debug = "false"; $var_string = "'".$var_string."'";#adjust for future use in CGI.pm if($debug eq "true"){ print "<br> (IN SUBROUTINE)var-string = ",$var_string; print "<br> (IN SUBROUTINE) qw{$query->param($var_string)}"; print "<br> (IN SUBROUTINE)", $query->param($var_string); print " <br> and \ (second variable)= ",$pointer_to_var_string; } $a = $$pointer_to_var_string;#variable passed by pointer $_[1] if($debug eq "true"){ print "<br>(IN SUBROUTINE)called value \(loc= ",$pointer_to_var_string,") = ",$a; } if($query->param($var_string) eq '') { $query->param($var_string,$$pointer_to_var_string);#if first time, set if($debug eq "true"){ print "<br>(IN SUBROUTINE) param was blank"; } }#save it print $query->hidden($var_string,$$pointer_to_var); if($debug eq "true"){ print "<br>(IN SUBROUTINE) restored value(from query->param) ", $query->param($var_string); } $$pointer_to_var_string = $query->param($var_string);#update value pointed at by $_[1] print "<br><br>====="; }