#! /usr/bin/perl #-w
#damian knopp
#cosc 336 database prog
#This program reads in profiles from a file,then creates a hashtable with the 
#info.In case of hashfunction collision linear probing is used.
#An inverted directory is also created. The program then  
#reports the whole direct file and inverted file organization.
#Next it implements secondary key retrival. Finally it preforms update
#operations on the inverted file
#########################################################################
@students=();
@hashtable=();
@student=();

open (TD,"short2.dat") || die "Cannot open file: $! \n";
 for ($i=0;<TD>;$i++){
   chomp;
   ($key,$name,$last,$age,$salary,$dept)=split (/ +/,$_);
   $student=store($key,$name,$last,$age,$salary,$dept);
   $students[$i]=$student;
 } #end for loop
close TD; 
for (my $i=0;$i<$#students+1;$i++){
  #print"$students[$i]->{NAME} has dept $students[$i]->{DEPT}\n";
  $href=hashfunc($students[$i]->{KEY},$i);
       if(defined $hashtable[$href->{HASH}]){
          until (! defined $hashtable[$href->{HASH}]){
               #print"collision searching for next avaliable space.\n";
               $href->{LINK}++; 
               $href->{HASH}=$href->{HASH}+1;}}
       if(! defined $hashtable[$href->{HASH}]){  
           #print"space is avaliable!\n"; 
           $hashtable[$href->{HASH}]=$href;}
 } #end for loop
$seckey[0]=dir_age(\@students); #store inverted file
$seckey[1]=dir_dept(\@students);
$seckey[2]=dir_salary(\@students);

for (my $i=0; $i<$#hashtable+1;$i++){ #report hashtable
    if(defined $hashtable[$i]){
    $j=$i; 
     write;
    }
} 

$^ = "STD2_TOP";
$~ = "STDOUT2";
for (my $j=0; $j<$#students+1;$j++){ #report students
    $salary=$students[$j]->{SALARY};
    $name= $students[$j]->{NAME};
    $age=$students[$j]->{AGE};
    $dept=$students[$j]->{DEPT};
    $key=$students[$j]->{KEY};  
    $i=$j; 
    write;
}
print"These people are in the COSC dept.\n";
foreach  $index(@{ $dir_dept{COSC}{LIST} }){
   if (defined $index){ 
   #sleep 1;
   print"-----------------------------------\n";
   print "NAME:  $students[$index]->{NAME} \n";
   print "AGE:   $students[$index]->{AGE} \n";
   print "SALARY:$students[$index]->{SALARY} \n";
   print"-----------------------------------\n"; 
}
}
print"These people make less than 30000 and are in the MATH or COSC dept\n";
foreach $index(@{ $dir_sal{20}{LIST} }, @{ $dir_sal{29}{LIST} }){
 if (defined $index){
  if($students[$index]->{DEPT} eq "COSC" || $students[$index]->{DEPT} eq"MATH"){
     #sleep 1; 
     print "-------------------------------\n";
     print "NAME:$students[$index]->{NAME} \n";
     print "DEPT:$students[$index]->{DEPT} \n";
     print "AGE:$students[$index]->{AGE}   \n";
     print "SALARY:$students[$index]->{SALARY} \n";
     print "-------------------------------\n";
     }
   }
}
print"These people are in the COSC dept and are between ages 21 and 24\n";
for $index(@{ $dir_dept{COSC}{LIST} }){
   if (defined $index){
    if($students[$index]->{AGE} >= 21 && $students[$index]->{AGE} <= 24){
     print "----------------------------------\n";
     print "NAME:$students[$index]->{NAME}\n";
     print "DEPT:$students[$index]->{DEPT}\n";
     print "AGE:$students[$index]->{AGE}\n ";
     print "SALARY:$students[$index]->{SALARY}\n";
     print "----------------------------------\n";
     }
   }}
open (MD,"modify.dat") || die "Cannot open file $!\n";
for($i=$i;<MD>;$i++){
    if($_ =~ /^INSERT/){
       sleep 1;
       $h=$_;
       for($i=$i;<MD>;$i++){
         if($_ =~ /^$$/){
            $h=$_;
            next;}
         else{ 
          chomp;
          ($key,$name,$last,$age,$salary,$dept)=split(/ +/,$_);
          $student=store($key,$name,$last,$age,$salary,$dept);
          $students[$i]=$student;
       }} 
     }
   #if($_ =~ /^DELETE/){
   #  sleep 1;
   #  $h=$_;
   #  for($i=$i;<MD>;$i++){
   #   if($_ !~ /W/){
}



$^=STDOUT_TOP;
$~=STDOUT;
for (my $i=0; $i<$#hashtable+1;$i++){ #report hashtable
    if(defined $hashtable[$i]){
    $j=$i; 
     write;
    }
}
$^ = "STD2_TOP";
$~ = "STDOUT2";
for (my $j=0; $j<$#students+1;$j++){ #report students
    $salary=$students[$j]->{SALARY};
    $name= $students[$j]->{NAME};
    $age=$students[$j]->{AGE};
    $dept=$students[$j]->{DEPT};
    $key=$students[$j]->{KEY};  
    $i=$j; 
    write;
}
#############################
#creates new student record
#############################
sub store{
my($key,$first,$last,$age,$salary,$dept)=@_;
$name=$first." " .$last;
$student_rec = {
       KEY  => $key,
       NAME => $name,
       DEPT => $dept,
       AGE  => $age,
       SALARY => $salary,
};	
#print "$student_rec->{NAME} $student_rec->{SALARY} ";
#print "$student_rec->{AGE} $student_rec->{DEPT}\n";
return $student_rec;
}
##############################################
#function to create a key for the hash table(mod 11)
###############################################
sub hashfunc{
my ($key,$i)=@_;
my $sum=0;
my $mod=0;
my $seg1=0;
my $seg2=0;
my $seg3=0;

$seg1=substr($key,0,3);
$seg2=substr($key,3,3);
$seg3=substr($key,6,3);
$sum=$seg1+$seg2+$seg3;
$mod=$sum % 307;
$hash_rec = {
  KEY     => $key,  #full key before mod
  ADDRESS => $i,    #index in student table
  HASH    => $mod,  #index in hash table
  LINK    => 0, #link to know if there has been a collision
};
#print "key=$key, sum=$sum, hashkey=$mod,studentindex=$i\n";
return $hash_rec;
}

#####################################
#inverted directry of students salary a list of recs
#####################################
sub dir_salary{
my ($student)=@_;

%dir_sal = (
  20 => {
    COUNT => 0,
    LIST  => [undef],
  }, 
  29 => {
    COUNT => 0,
    LIST  => [undef],
  },
  39 => {
    COUNT => 0,
    LIST  => [undef],
  }, 
  50 => {
    COUNT => 0,
    LIST  => [undef],
  }, 
  51 => {
    COUNT => 0,
    LIST  => [undef],
  }, 
);

for (my $i=0; $i < @$student; $i++){
 if ($student->[$i]->{SALARY} <= 20000){
      push  @{ $dir_sal{20}{LIST} },$i;     
      $dir_sal{20}{COUNT}++;
 }
 elsif($student->[$i]->{SALARY} > 20000 && $student->[$i]->{SALARY} < 30000){
      push @{ $dir_sal{29}{LIST} },$i; 
      $dir_sal{29}{COUNT}++; 
 } 
 elsif ($student->[$i]->{SALARY} >= 30000 && $student->[$i]->{SALARY} < 40000){ 
      push @{ $dir_sal{39}{LIST} },$i;
      $dir_sal{39}{COUNT}++;
 }  
 elsif ($student->[$i]->{SALARY} >= 40000 && $student->[$i]->{SALARY} <= 50000){
      push @{ $dir_sal{50}{LIST} },$i;
      $dir_sal{50}{COUNT}++;
 } 
 elsif ($student->[$i]->{SALARY} > 50000){
      push @{ $dir_sal{51}{LIST} },$i;
      $dir_sal{51}{COUNT}++;
 }

}#end for
return %dir_sal;
}

#####################################
#
#####################################
sub dir_age{
my ($student)=@_;

%dir_age = (
 18 => {
    COUNT => 0,
    LIST  => [undef],
 },
 19 => {
    COUNT => 0,
    LIST  => [undef],
 },
 20 => {
    COUNT => 0,
    LIST  => [undef],
 }, 
 21 => {
    COUNT => 0,
    LIST  => [undef],
 },
 22 => {
    COUNT => 0,
    LIST  => [undef],
 },
 23 => {
    COUNT => 0,
    LIST  => [undef],
 },
 24 => {
    COUNT => 0,
    LIST  => [undef],
 },
 25 => {
    COUNT => 0,
    LIST  => [undef],
 },
 26 => {
    COUNT => 0,
    LIST  => [undef],
 },
);  

for (my $i=0; $i < @$student; $i++){
  if($student->[$i]->{AGE} <= 18){
     push @{ $dir_age{18}{LIST} },$i;    
     $dir_age{18}{COUNT}++;
  }
  elsif($student->[$i]->{AGE} == 19){
     push @{ $dir_age{19}{LIST} },$i;
     $dir_age{19}{COUNT}++;
  }
  elsif($student->[$i]->{AGE} == 20){
     push @{ $dir_age{20}{LIST} },$i;
     $dir_age{20}{COUNT}++;
  }
  elsif($student->[$i]->{AGE} == 21){
     push @{ $dir_age{21}{LIST} },$i;
     $dir_age{21}{COUNT}++;
  }
  elsif($student->[$i]->{AGE} == 22){
     push @{ $dir_age{22}{LIST} },$i;
     $dir_age{22}{COUNT}++;
  }
  elsif($student->[$i]->{AGE} == 23){
     push @{ $dir_age{23}{LIST} },$i;
     $dir_age{23}{COUNT}++;
  }
  elsif($student->[$i]->{AGE} == 24){
     push @{ $dir_age{24}{LIST} },$i;
     $dir_age{24}{COUNT}++;
  }
  elsif($student->[$i]->{AGE} == 25){
     push @{ $dir_age{25}{LIST} },$i;
     $dir_age{25}{COUNT}++;
  }
  elsif($student->[$i]->{AGE} >= 26){
     push  @{ $dir_age{26}{LIST} },$i;
     $dir_age{26}{COUNT}++;
  }
} 
return %dir_age;
}

##################################
#creates dept directory
##################################
sub dir_dept{
my ($student)=@_;

%dir_dept= (
   MATH => {
      COUNT=> 0,
      LIST => [undef],
   },
   COSC => {
      COUNT=> 0,
      LIST => [undef],      
   },
   BIOL => {
      COUNT=> 0,
      LIST => [undef],
   },
   CHEM => {
      COUNT=> 0,
      LIST => [undef],
   },
   PHYL => {
       COUNT=> 0,
       LIST => [undef],
   },
   ART  => {
        COUNT=> 0,
        LIST => [undef],
   },
   HIST => {
         COUNT=> 0,
         LIST => [undef],
   },
);
for (my $i=0; $i < @$student; $i++){
   if($student->[$i]->{DEPT} =~ /^MATH/){
       push @{ $dir_dept{MATH}{LIST} },$i;
       $dir_dept{MATH}{COUNT}++;
    }
    elsif($student->[$i]->{DEPT} =~/^COSC/){
        push @{ $dir_dept{COSC}{LIST} },$i;
        $dir_dept{COSC}{COUNT}++;
    }
    elsif($student->[$i]->{DEPT} =~ /^BIOL/){
        push @{ $dir_dept{BIOL}{LIST} },$i;
        $dir_dept{BIOL}{COUNT}++;
    }
    elsif($student->[$i]->{DEPT} =~ /^CHEM/){
         push @{ $dir_dept{CHEM}{LIST} },$i;
         $dir_dept{CHEM}{COUNT}++;
    }
    elsif($student->[$i]->{DEPT} =~ /^PHYL/){
         push @{ $dir_dept{PHYL}{LIST} },$i;
         $dir_dept{PHYL}{COUNT}++;
    }
    elsif($student->[$i]->{DEPT} =~ /^ART/){
          push @{ $dir_dept{ART}{LIST} },$i;
          $dir_dept{ART}{COUNT}++;
    }
    elsif($student->[$i]->{DEPT} =~ /^HIST/){
          push @{ $dir_dept{HIST}{LIST} },$i;
          $dir_dept{HIST}{COUNT}++;
    }
}#end for
return %dir_dept;
}

       
format STDOUT=
@|||    @||||||||||||  @|||||||          @||||        @||||
$j,$hashtable[$j]->{KEY},$hashtable[$j]->{ADDRESS},$j,$hashtable[$j]->{LINK}
.

format STDOUT_TOP =
Page @|| 
$%

INDEX       KEY          ADDRESS         HASH	       LINK
=======  ============ ==============   ==========   ===========
.

format STDOUT2=
@||  @||||||||   @<<<<<<<<<<<<<<<   @||  @<<<<<<<<<  @||||||||||||
$i,$salary,$name,$age,$dept,$key
.

format STD2_TOP =
Page @||
$%

INDEX	SALARY	   NAME    AGE  DEPT      KEY
====== ========== ======== ==== ====== ================
.


