#!/usr/bin/env perl use strict; use warnings; use Data::Dumper; # utility functions sub urldecode { my ($a) = @_; $a =~ s/\+/ /g; $a =~ s/%([A-Fa-f\d]{2})/chr hex $1/eg; return $a; } sub urlencode { my ($a) = @_; $a =~ s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg; return $a; } sub parse_post() { my $POST_STRING = <>; my @POST = split(/[&=]/, $POST_STRING); my %POST_PARAMETERS = (); for (my $i = 0; $i < $#POST; $i += 2) { if (!defined $POST_PARAMETERS{$POST[$i]}) { $POST_PARAMETERS{$POST[$i]} = $POST[$i+1]; } else { $POST_PARAMETERS{$POST[$i]} = $POST_PARAMETERS{$POST[$i]} . "," . urldecode ($POST[$i+1]); } } return \%POST_PARAMETERS; } sub check_equivalence { my ($string1,$string2) = @_; $string1 = (urldecode $string1) =~ s/^\s+|\s+$//rg; $string2 = (urldecode $string2) =~ s/^\s+|\s+$//rg; return $string1 =~ /^\s*$string2\s*$/i } print "Content-Type: text/html\n\n"; print ""; print ""; print < Amino Acid Practice EOF print "

Amino Acids

"; print "
"; our @amino = ( ["Phenylalanine", "Phe", "F", "F.png", "Nonpolar" ], ["Leucine", "Leu", "L", "L.png", "Nonpolar" ], ["Isoleucine", "Ile", "I", "I.png", "Nonpolar" ], ["Methionine", "Met", "M", "M.png", "Nonpolar" ], ["Valine", "Val", "V", "V.png", "Nonpolar" ], ["Proline", "Pro", "P", "P.png", "Nonpolar" ], ["Alanine", "Ala", "A", "A.png", "Nonpolar" ], ["Tryptophan", "Trp", "W", "W.png", "Nonpolar" ], ["Glycine", "Gly", "G", "G.png", "Nonpolar" ], ["Serine", "Ser", "S", "S.png", "Polar" ], ["Threonine", "Thr", "T", "T.png", "Polar" ], ["Tyrosine", "Tyr", "Y", "Y.png", "Polar" ], ["Glutamine", "Gln", "Q", "Q.png", "Polar" ], ["Asparagine", "Asn", "N", "N.png", "Polar" ], ["Cysteine", "Cys", "C", "C.png", "Polar" ], ["Aspartate", "Asp", "D", "D.png", "Acidic" ], ["Glutamate", "Glu", "E", "E.png", "Acidic" ], ["Histidine", "His", "H", "H.png", "Basic" ], ["Lysine", "Lys", "K", "K.png", "Basic" ], ["Arginine", "Arg", "R", "R.png", "Basic" ] ); our @abbreviations = ("full name", "3-letter abbreviation", "1-letter abbreviation", "image"); our @properties = ("Polar", "Nonpolar", "Acidic", "Basic"); sub answer_choices { my %found = (); for(0..($#amino-1)) {$found{$_} = 1;}; my @res; for((1..5)) { my $choice; do { $choice = int(rand $#amino); } while ($found{$choice} == 0); $found{$choice} = 0; push @res, $choice; } my $correct = $res[int(rand $#res)]; return \@res, $correct; } sub to_image { my ($query) = @_; return $query =~ s/([^\s]*?).png//r; } sub decode_question { my ($choices_idx, $correct_idx) = answer_choices(); # generate a question type my %type_hash = (0 => 1, 1 => 1, 2 => 1, 3 => 1); my @types = (); for (1..2) {my $cur; do {$cur = int(rand 4);} while($type_hash{$cur} == 0); push @types, $cur; $type_hash{$cur} = 0;}; my $question = "What is the " . $abbreviations[$types[1]] . " for " . $amino[$correct_idx]->[$types[0]] . "?"; my $answer = $amino[$correct_idx]->[$types[1]]; my @options = (); for(@$choices_idx) { push @options, $amino[$_]->[$types[1]] } if (rand() < 0.3 && $types[1] != 3) { return $question, $answer, []; } return $question, $answer, \@options; } sub properties_question { my ($choices_idx, $correct_idx) = answer_choices(); my $question = "Property of the amino acid " . $amino[$correct_idx]->[int(rand 4)]; return $question, $amino[$correct_idx]->[4], \@properties; } sub construct_form { my ($question, $answer, $options) = @_; $answer = $answer; $question = urldecode $question; my $question_label = to_image $question; print "
"; print "
"; print ""; if (scalar @$options) { print "
"; for (my $i = 0; $i < scalar @$options; $i++) { my $opt = $options->[$i]; my $lbl = to_image($options->[$i]); print ""; print ""; print ""; print "
"; } print "
"; } else { print ""; } print ""; print "
"; print "
"; } if ($ENV{'REQUEST_METHOD'} =~ /POST/i) { my $parameters = parse_post(); our $response = ($parameters->{'response'} // ''); our $answer = ($parameters->{'answer'} // 'wrong'); our $question = ($parameters->{'question'} // ''); our @options = split(',', $parameters->{'options'} // ''); # answer and response should have the same elements. our $correct = check_equivalence $answer, $response; construct_form($question, $answer, \@options); if ($correct) { print "

Correct!

"; } else { print "

Incorrect!

"; } } else { if (int(rand(2)) == 0) { construct_form(properties_question()); } else { construct_form(decode_question()); } } print "
"; print ""; print "
"; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(); $year += 1900; print "

© Juni Kim 2022-$year

"; print"";