#!/usr/bin/perl -w
###############################################
## Name: QuizTaker ##
## Version: 1.08 ##
## Author: Thomas Stanley ##
###############################################
use strict;
use File::Slurp;
use Text::Wrap;
my $A=0;
my $Choice;
while($A == 0){
system('clear');
print"\n";
print"\t\t ******************************* \n";
print"\t\t *** QuizTaker.pl *** \n";
print"\t\t *** Version 1.08 *** \n";
print"\t\t *** by Thomas Stanley *** \n";
print"\t\t ******************************* \n";
print"\n"x4;
print"\t\t\t\t1) Take a test\n";
print"\t\t\t\t2) Exit\n";
print"\n\n";
print"\t\t\t\tYour choice: ";
$Choice = <STDIN>;
chomp($Choice);
my $B = 0;
while($B == 0){
if($Choice == 1){
&Choose();
$B=1;
}elsif($Choice == 2){
print"\n\n\t\t\t\tThanks for playing!\n";
$A = 1;
}
$B = 1;
}
}
##############################
sub Choose{
system('clear');
my %File_Lengths=();
my %NumberOfTests=();
my $Choice;
my $MaxQuestions;
my $Length;
my $File;
my $C;
my $D = 1;
my $H = 0;
my $I = 0;
my $refFile_lengths = GetFileLengths(\%File_Lengths);
foreach $C(keys %File_Lengths){
$C=~s/\.\w{3}//;
$NumberOfTests{$D} = $C;
$D++;
}
print"\n";
foreach $C(keys %NumberOfTests){
print"\t\t\t$C) $NumberOfTests{$C}\n";
}
while($H == 0){
print"\n\t\t\tEnter the test number: ";
my $number = <STDIN>;
chomp $number;
$Choice = "$NumberOfTests{$number}.psv";
if(exists $NumberOfTests{$number}){
while($I == 0){
print"\n\t\tHow many questions do you wish to answer (Max = $F
+ile_Lengths{$Choice}): ";
my $MaxQuestions = <STDIN>;
chomp $MaxQuestions;
if(($MaxQuestions<1)||($MaxQuestions>$File_Lengths{$Choice})){
print"\n\n\t\tPlease re-enter the number of questions.";
sleep(2);
}else{
$Length = $File_Lengths{$Choice};
&Randomize($Choice,$Length,$MaxQuestions);
$I = 1;
}
}
}else{
print"\n\t\tPlease choose again!!\n\n";
sleep(2);
}
$H = 1;
}
return;
}
##################################
sub GetFileLengths{
my $File_Lengths = shift;
my $Directory = "./Questions";
my $File;
my @Files = read_dir($Directory);
my $Check;
my $path;
foreach $File(@Files){
if($File=~/\.psv/){
$path = $Directory."/".$File;
$Check = Check($path);
if($Check<1){}else{
$$File_Lengths{$File} = $Check;
}
}
}
my $number = keys %$File_Lengths;
if($number == 0){
die"No files available\n";
}
return $File_Lengths;
}
#############################
sub Check{
my $file=shift;
my $lines;
if(-e $file){
$lines =`wc -l < $file`;
}else{
die"Can't find $file!\n";
}
return $lines;
}
#############################
sub Randomize{
my $File = shift;
my $FileLength = shift;
my $Max = shift;
my $Directory = "./Questions";
my %Randoms = ();
my %Data=();
my %TestQuestions=();
my %TestAnswers=();
srand();
my $Path = $Directory."/".$File;
my $ref=Loader(\%Data,$Path);
for(1..$Max){
my $question_number = int(rand($FileLength)+1);
redo if exists ($Randoms{$question_number});
$Randoms{$question_number} = 1;
}
my @Randoms = keys %Randoms;
my $ref2=shuffle(\@Randoms);
for(my $a=0;$a<$Max;$a++){
$TestAnswers{$Randoms[$a]} = pop@{$Data{$Randoms[$a]}};
$TestQuestions{$Randoms[$a]} = $Data{$Randoms[$a]};
}
my %QuestionLength = ();
my $b;
foreach my $key (keys %TestQuestions){
$b = @{$TestQuestions{$key}};
$QuestionLength{$key} = $b;
}
&Tester(\%TestQuestions,\%TestAnswers,\@Randoms,\%QuestionLength,$Ma
+x);
return;
}
######################
sub Loader{
my $Data=shift;
my $file=shift;
my $question_number;
my $length;
my $f;
my @Sorter=();
open(FH,"$file")||die"Can't open $file: $!\n";
while(<FH>){
@Sorter=split /\|/;
$question_number=shift @Sorter;
$length=@Sorter;
for($f=0;$f<$length;$f++){
$$Data{$question_number}[$f]=$Sorter[$f];
}
}
close FH;
return $Data;
}
##########################
sub Tester{
my $Questions=shift;
my $Answers=shift;
my $Randoms=shift;
my $question_length=shift;
my $Max=shift;
my $length;
my $question_number=1;
my $question_answer="";
my $answer;
my $number_correct=0;
my $key;
my $g;
system('clear');
print"\n";
while($question_number<=$Max){
$key=shift @$Randoms;
$length=$$question_length{$key};
print"Question Number $question_number\n";
for($g=0;$g<$length;$g++){
print wrap("","","$$Questions{$key}[$g]\n");
}
print"\nYour answer: ";
$answer=<STDIN>;
chomp $answer;
$answer=uc $answer;
$question_answer=$$Answers{$key};
chomp $question_answer;
$question_answer = uc $question_answer;
if($answer eq $question_answer){
print"That is correct!!\n\n";
$question_number+=1;
$number_correct+=1;
}else{
print"That is incorrect!\n";
print"The correct answer is $question_answer.\n\n";
$question_number+=1;
}
}
&Final_Score($number_correct, $Max);
return;
}
###########################
sub Final_Score{
my $Correct=shift;
my $Max=shift;
my $Percentage=($Correct/$Max)*100;
print"You answered $Correct out of $Max correctly.\n";
printf"For a final score of %.2f%%\n",$Percentage;
sleep(4);
return;
}
#
# Fisher-Yates Shuffle
#
sub shuffle {
my $array = shift;
my $i;
for ($i = @$array; --$i; ) {
my $j = int rand ($i+1);
next if $i == $j;
@$array[$i,$j] = @$array[$j,$i];
}
}
__END__;
=pod
=head1 QuizTaker.pl Version 1.08
This program will allow you to take simple tests,
based upon a file of questions and answers that you
create. A sample file of questions have been included
with this distribution, so you can see how its done.
The values are stored within the file, with the pipe
character "|" as a separator. Please ensure that you
have an extension of .psv on the end of your question/answer
files.
To run this program, type the following at the command prompt in
the directory where you have installed QuizTaker:
./QuizTaker.pl
This program also requires the File::Slurp module which can be
found on your nearest CPAN mirror.
=head2 Improvements
=over 4
=item 1
Now includes this section of POD
=item 2
Now uses the Text::Wrap module found in the core distribution
of Perl, to wrap the lines of long questions
=item 3
Now has a menu based interface, and allows you to choose
which test you would like to take.
=item 4
Cleaned up some syntax within the functions to make them
look better
=item 5
Fixed a bug where if the letter in the answer file
is in lowercase, it would break in the Test subroutine.
=item 6
Implemented the Fisher-Yates shuffling algorithm to provide for
a more random sequence in the array of questions
=back
=head2 To Do List
=over 4
=item 1
Make a graphical user interface using the Tk module
=back
=head2 Questions/Comments
If you have any questions or comments about this program
please email me at Thomas_J_Stanley@msn.com . I am always
striving to make this program better.
=cut
|