#! c:\orant\ows\cartx\common\perl\bin\perl
#
############################################################################
# Copyright (c) 1996 by Oracle Corporation */
#
#   NAME
#     parse.pl -- Oracle Forms Performance Collector Parsing routine
#
#   DESCRIPTION
#
#   PUBLIC FUNCTION(S)
#
#   PRIVATE FUNCTION(S)
#
#   RETURNS
#
#   NOTES
#
#   VERSION
#     $Id: f60parse.pl,v 1.16 2000/06/03 02:36:45 vasokkum Exp $
#
#   MODIFIED    (MM/DD/YY)
#     vasokkum   06/02/00 -  Modify the Frontpage and more changes to Relative
#                         -  time;
#     vasokkum   05/31/00 -  Print the Handshake parameter correctly
#     vasokkum   05/30/00 -  Add description in the beginning 
#     vasokkum   05/26/00 -  Include Client Time also in processing
#     vasokkum   04/04/00 -  Comment the debug info 
#     vasokkum   01/31/00 -  A better string indicating user action 
#     vasokkum   01/25/00 -  A better feel for UI
#     vasokkum   12/28/99 -  Print Help info and Generate HTML outputs
#     vasokkum   12/28/99 -  Modify for the changes in Timestamp event renaming
#     vasokkum   12/05/99 -  Accept null activities in the log fine
#     vasokkum   12/03/99 -  Command Line arguments accepted
#     vasokkum   11/15/99 -  Make Eventfile as optional input
#     vasokkum   06/30/99 -  Commandline Parameters added
#     vasokkum   06/12/99 -  Creation
############################################################################
#
# This PERL script analyses the time stamps collected by the Performance
# collection option set during runform execution. The option to be set to
# enable performance collector is "record=collect" or "record=all".i
# This file takes care of user defined events and generates
# the corresponding data accordingly 
############################################################################
#use Getopt::Long;             # to take care of command line options 

#########################################################################
# Global variables
#########################################################################
$TIMESTKEY = 'TSE';    # timestamp info starts with this key
$CACHEKEY = 'CAC';     # cached info starts with this key
$ERRORKEY = 'ERROR';
$EVENTKEY = 'EVENT_PT:';       # event info starts with this key
$ACTIONKEY = '#####';  # Indicates the start of user action


#########################################################################
# Available options
#########################################################################  

GetOptions( "input=s" => \$input,
            "eventf=s" => \$eventf,
            "output=s" => \$output );
#########################################################################
# Processing Starts from here 
#########################################################################  

    $Tempfptr = 0;    # temporary variable to store the file pointer 
    $Orgfptr = 0;     # File pointer where the actual data starts   
    $Stuseract = 0;   # First Useraction named as Start
    $TSEventcnt = 0;  # Number of time stamp events
    $Ceventcnt = 0;   # Number of cache events.
    $Curline = "";    # Line to read data from inputfile
    $Actioncnt = 0;   # Number of User actions
    $Totalcnt = 0;
    $Totaltime = 0;
    $Mintime = 100000;
    $Maxtime = 0;
    $Linecnt = 0;         # Count the number of lines already processed.
    ##
    ##Parse the command line and get the Parameters 
    ##
    ($Infile, $Eventfile, $Outfile) = GetParams($input, $eventf, $output);
    PrintHelp();
    print "\n Please specify the OS on which the data was collected ";
    print "\n Press (N) for NT and (U) for all Unix Systems :";
    $os_type = <STDIN>;
    while (defined ($os_type) ) 
    {
        chomp($os_type);
        $uos_type = uc($os_type);
        if (($uos_type eq "N") )
        {
            $div_factor = 1;
            last;
        }
        if ( ($uos_type eq "U"))
        {
            $div_factor = 1000000;
            last;
        }
	print "\n Please specify the OS on which the data was collected ";
	print "\n Press (N) for NT and (U) for all Unix Systems :";
	$os_type = <STDIN>;
    }
    $output = 1;
    ##
    ##Open the input file
    ##
    if (! -r $Infile )
    {   
        die "Hey, I'm not able to read your file $Infile";
    }
    if (! -f $Infile )
    {
        die "Your Input $Infile is not a plain file \n";
    }
    open(INPUT, "$Infile") ||
        die "Not able to open Input file $Infile $!";
    
        ##
    ##Skip the header information in the Input file
    ##
    SkipHeader();

    ProcessData();
    PrintIntro();
    ##
    ##Open the output file
    ##
    $sumoutput = "summary.html";
    $lvl1out   = "detailed.html";
    $lvl2out   = "detailed2.html";
    print "Output files are $sumoutput $lvl1out and $lvl2out";
    ##
    ##Prepare the event list by reading the event file
    ##
    print "\n Processing Event File $Eventfile .....";
    GetEvents($Eventfile);
    print " Done"; # $test = <STDIN>;
    ##
    ##Generate the list of event intervals
    ##
    open(INPUT, "perf.out") ||
        die "Not able to open Input file $Infile $!";
    $Orgfptr = 0;

    print "\n Creating Event Intervals .....";
    CreateTSEventIntervals();
    print " Done    "; 

    print "\n Creating Time Stamp Events .....";    
    CreateTSEventList();
    print " Done";

    print "\n Creating User Defined Intervals .....";
    #CreateUserEventList();
    print " Done";
    if ( $Outfile ne "" )
    {
        open (OUTPUT, "> $Outfile") ||
            die "Not able to open Output file $Outfile $!";
    }

    select (OUTPUT);
    PrintSummary();
    PrintDetails($Actioncnt);
    PrintSummaryXML();
    PrintDetailsXML();
    

#########################################################################
#   Subroutine : GetParams()
#   This routine gets the arguments from the user when used in the
#   interactive mode
#########################################################################

sub GetParams()
{
    my ($Infile, $Eventfile, $Outfile) = @_;

    print "input file is $input \n";
    $Infile = $input;
    while ( $Infile eq "" )
    {
        print "\n Specify the Input File Name : "; 
        chomp ($Infile = <STDIN> );
    }
    $Eventfile = $eventf;
    if ( $Eventfile eq "" )
    {
        print "\n Event file is not specified. ";
        print "\n Using the Default events";
    }
    else
    {
        print "Event file is $eventf \n";
    }
    $Outfile = $output; 
    if ( $Outfile eq "" )
    {
        print "\n Output file not specified. ";
        print "\n Generating only the HTML output in index.html ";
        print "\n Specify the Output File : ";
        chomp ($Outfile = <STDIN> );
    }
    else
    {
        print "\n Output file is $output \n";

    } 
    if ( $Outfile )
    {
        $output = 1;
    }
    return ($Infile, $Eventfile, $Outfile);
}        

#########################################################################
#  Subroutine : SkipHeader ()
#  This routine reads the input file and skips the header partof it.
#########################################################################

sub SkipHeader( )
{
    my ($Action, $Event, $Val, $Curfptr);

    open(RUNDET, "> runtime.html") ||
           die "Not able to open the Runtime details file $!";
    select (RUNDET);
    print "<HTML> <HEAD>";
    print "<center> <H2>Runtime Details </H2> </center></HEAD> <BODY>";
    $Action = "";

    while ( $TIMESTKEY ne $Action )
    {
         print "<h4>$Curline</h4>";
         $Curfptr = tell(INPUT);
         chomp($Curline = <INPUT> );
         $Linecnt++;
         ($Action, $Event) = split(' ', $Curline, 2);
    }
    print "</BODY> </HTML>";
    close(RUNDET);
    select(STDOUT);

    @array1 = split(' ', $Curline);
    $StartUpTime = $array1[4];
    chomp($Curline = <INPUT> );

   @array1 = split(' ', $Curline);
    $HandShake = $array1[4];

    $Resevent = "Handshake"." ".$HandShake;
    $Linecnt += 2;

}

#########################################################################
#  Subroutine : ProcessData ()
#  This routine reads the input file processes the data and generates
#  the intermediate file. 
#########################################################################

sub ProcessData()
{
    my ($i); $first=0;

    #$Val = seek(INPUT, $Orgfptr, 0);
    $FilePtr[0] = tell(INPUT); # $Orgfptr;
   
    open(OUTPUT, "> perf.out") ||
         die "Not able to open output file $Outfile";
    select(STDOUT);
    while( <INPUT> )
    {
        chomp($Curline = $_);
       
        $Linecnt++;
        ($Temp, $Event) = split(' ', $Curline, 2);
        if ( $Temp eq $ACTIONKEY )
        {
            $Val =  tell(INPUT);
            $FilePtr[$i++] = tell(INPUT);
        }
        if ( $Temp eq '#')        {
            chomp($Curline = <INPUT>);
            if ( $first == 1 )
            {
		$FilePtr[$i++] = tell(INPUT);
	    } 
	    if ( $ActionList[$i-1] eq "")
            {
		$ActionList[$i-1] = $Curline;	     
		$first++;
	    }
	    else
	    {                
		#print "Actionlist is $ActionList[$i] for value $i";
	    }
        }
        
    }
    print "Processed $Linecnt lines"; 
    $FilePtr[$i] = tell(INPUT);
  
    $Eventcnt = $i;
    #for ( $i = 0; $i < $Eventcnt; $i++ )
    #{
	#print "\n $i is Actionlist is $ActionList[$i] ";
    #}
    select(OUTPUT);
    $cnt = 0;
    for ( $i = 0;$i < $Eventcnt; $i++ )
    {
        $Val = seek(INPUT, $FilePtr[$i], 0);
        if ( $ActionList[$i] ne '')
        {
            print "\n EVENT_PT: $cnt $ActionList[$i]";
            $cnt++;	   
        }      
        while ( $Val < $FilePtr[$i+1] )
        {
            chomp($Curline = <INPUT>);
            ($Temp , $Event) = split(' ', $Curline, 2);
            if ( $Temp eq $TIMESTKEY )
            {
		print "\n $Curline";
            }
	    $Val = tell(INPUT);
	}
    }
    close (INPUT);
    close (OUTPUT);
} 
       


#########################################################################
#  Subroutine : GetEvents()
#  This routine opens and reads the event file.
#  Creates two hash lists for storing the details
#  EventHash has the EventStart and ends and the nick names
#  GroupHash has the name of the group to which it belongs to.
#  The grouphash is used to maintain multiple levels of data
#  for the end user. 
#########################################################################
sub GetEvents( )
{
    my ($Efile) = @_;
    my ($nick, $Pgroup, $Stactual, $Endactual, $Actual, $count, $ival, $failed);
    $evfile = "event.html";
    open (EVENTDEF, ">$evfile ") || 
            die "Not able to create Event Definition File event.html $!";

    
    $failed = 0;
    $count = 12; 
    ##
    ##Open the event file 
    ##
    if (! -r $Efile )
    {   
         print "Not able to read event file $Efile";
         $failed = 1;
    }
    if (! -f $Efile )
    {
        print "Input file $Efile is not a plain file \n";
        $failed = 1;
    }
   
    open( EVENT, "$Efile") ;

    if ( !EVENT )
    {
         print "Not able to open Event file $Efile $!";
         $failed = 1;
    }
    if ( $failed == 1 )
    {
        #print "\n Assuming Default Events as below";
        $tempevt[0] ="Net  Net    FSERVER_END    FSERVER_START";
        $tempevt[1] ="DBLOGON  DBLogon        DBLOGON_START  DBLOGON_END";
        $tempevt[2] ="FServer  FSPostLogon     DBLOGON_END    FSERVER_END";
        $tempevt[3] ="DBPROC   DBPROC        DB_START       DB_END";
        $tempevt[4] ="FServer  FSMidDB       DB_END         DB_START";
        $tempevt[5] ="FServer  FSPostDB     DB_END         FSERVER_END";
        $tempevt[6] ="FServer  FSPreLogoff    FSERVER_START   DBLOGOFF_START";
        $tempevt[7] ="DBLOGOFF DBLogoff       DBLOGOFF_START DBLOGOFF_END"; 
        $tempevt[8] ="FServer  FSPreLogon       FSERVER_START DBLOGON_START"; 
        $tempevt[9] ="FServer  FSPreDB       FSERVER_START DB_START"; 
        $tempevt[10] ="FServer  FSPostLogoff  DBLOGOFF_END DB_START"; 
        $tempevt[11] ="ClientTime  ClientTime  temp1           temp1        "; 
        #$tempevt[10] ="Client+Net2    FServer  FSERVER_END  FSERVER_END";
        for ( $ival = 0; $ival < $count; $ival++ )
        { 
            ($Pgroup, $nick, $Stactual, $Endactual) = split ' ',$tempevt[$ival];
            $Actual = $Stactual.'-'.$Endactual;
            $EventHash{$Actual} = $nick;
            $GroupHash{$Actual} = $Pgroup;
        }
        
    }
    else 
    {
        $ival = 0;
        while ( <EVENT> )
        {
            $tempevt[$ival] = $_;
            ($Pgroup, $nick, $Stactual, $Endactual) = split ' ', $_ ;
            $Actual = $Stactual.'-'.$Endactual;
            #print "Event is $Actual"; $test = <STDIN>;
            $EventHash{$Actual} = $nick;
            $GroupHash{$Actual} = $Pgroup;
            $ival++;   
        }
        $count = $ival-1; 
    }
    select(EVENTDEF);
    print "\n <html> \n <head>";
    print "\n<title>Forms Performance Analysis - Event Definitions</title>";
    print "\n<\/head> \n    <body>";
    print "\n <h2> <center> Event Definition View</center> </h2>";
    print"\n <a name=\"event\"> <\/a>";
    print("\n<table width=100% border=1> <thead>");
    print "\n  <th>GroupEvent (Details Level1)<\/th>";
    print "\n  <th>Event (Details Level2)<\/th>";
    print "\n  <th>Duration<\/th>";
    print "\n <\/thead> <tbody>";

    for ( $ival = 0; $ival < $count; $ival++ )
    { 
        ($Pgroup, $nick, $Stactual, $Endactual) = split ' ',$tempevt[$ival];
        $Actual = $Stactual.'-'.$Endactual;
        print "<tr> <td>$Pgroup <\/td> <td>$nick<\/td><td>$Actual<\/td><\/tr>";
    } 
    print "<\/tbody> <\/table>";
    print "<h2> Event : <\/h2> <p>Event is a generic terminology used to name the interval between the two significant time stamping points. Events in the given data collection are given in Table <\/p>" ; 
    print "<h2> Group Event : <\/h2> <p> Events are divided into 6 different groups.
 This classification is based on which part of the 3-tier architecture the timing event relates to.<\/p>";
    print "Group Events are : <br>";
    print "DBLOGON <br>";
    print " DBLOGOFF <br>";
    print " DBPROC <br>";
    print " FServer <br>";
    print "Client <br>";
    print " Net <br>";

    print "<\/body><\/html>  ";       

    ##
    ## Add temporary values to take care of other events
    ##
    $EventHash{"temp"} = "FServer";
    $GroupHash{"temp"} = "FServer";
    #while ( ($k, $v) = each %EventHash) 
    #{
    #     print "$k => $v \n";
    #}
    select(STDOUT); 
    return (EventHash);
}   

#########################################################################
#  Subroutine : GroupInit()
#  This routine initialises the Hash to store group details.
#  The grouphash is used to maintain multiple levels of data
#  for the end user. 
#########################################################################
sub GroupInit ( )
{
    my (@Gvalue,$Gstr);

    my ($Str, $Total, $Min, $Max) = ( "", 0, 100000, 0);
    $Str = join ',', $Total, $Min, $Max;

    @Gvalue = values % GroupHash;
    foreach $Gstr ( @Gvalue ) 
    {
        $GdataHash{$Gstr} = $Str;
    }
    # print "GroupInit called now ................."; $test = <STDIN>;
    #@Gvalue = keys % GdataHash;
}
#########################################################################
#  Subroutine : ClientInit()        
#  This routine initialises the ClientTime variables
#########################################################################
sub ClientandNetInit( )
{
    $Clientcnt = 0;
    $CMintime = 0;
    $CMaxtime = 0;
    $Clienttime = 0;
    $Netcnt    = 0;
    $NMintime = 0;
    $NMaxtime = 0;
    $Nettime = 0;
}

#########################################################################
#   Subroutine : CreateTSEventIntervals()
#   This routine prepares a list of Time Stamp Events from the input file
#########################################################################
sub CreateTSEventIntervals()
{
    my ($Stevent, $Endevent,$Stendevent);

    $Val = seek(INPUT, $Orgfptr, 0);
    $Actioncnt = 0;  
    $tempfptr = $Orgfptr;
    while ( <INPUT> )
    {
        @array1 = split ' ',$_;
        if ( $array1[0] ne "" )   # Skip the empty lines
        {
            while ( ($array1[0] ne $EVENTKEY) && ($array1[0] ne $ERRORKEY) ) 
            {
	        if ( ($array1[0] eq $TIMESTKEY) )
                {
                    $Curline = $_;
                    $tempfile = tell(INPUT);
                   
                    if ( $Stevent ne $array1[1] )
                    {
                        $Stendevent = $Stevent.'-'.$array1[1];
                        $Stevent = $array1[1];
                        $TSEventcnt = $#TSEventlist + 1;
                        for ( $i= 0; $i < $TSEventcnt; $i++ )
                        {
                           if ( $TSEventlist[$i] eq $Stendevent )
                           {
                               last;
                           }
                        }
                        # 
                        # it is a new event. So, insert into array
                        #
                        if ( $i == $TSEventcnt )
                        {
                             $TSEventlist[$i] = $Stendevent;
                             $TSEventcnt ++;
                             last;
		        }
                    }
                    else   # Someother event, so skip that
		    {
                       last;
	            }
                }
                else  # skip the lines which do not have a 
                  # TIMESTKEy or EVENTKEy 
                {
                     last;
                }
            }
            #
            # This is where the time stamp of the actual user events
            # get stored. 
            #
            if ( $array1[0] eq $EVENTKEY )
            {
               
                $Resstr = $array1[2]."_".$array1[4].",".$array1[5];
                $ActionList[$Actioncnt] = $Resstr;
                #print "The Resstr here is $Resstr .... "; $test = <STDIN>;
                $FPList[$Actioncnt] = tell(INPUT); 
                chomp($Curline = <INPUT>);
              
	        @array1 = split ' ',$Curline;
	        if ( $array1[0] eq $TIMESTKEY )
	        {
	            $Stevent = $array1[1];
		    $CTimeList[$Actioncnt] = $array1[3];
		    $TimeList[$Actioncnt++] = $array1[4];
	        }
                else
                {
                    print "Invalid sequence in the intermediate file";
		    $test = <STDIN>;
                }
            }
            $EndTimeList[$Actioncnt] = $array1[4];
       }
       $tempfptr = tell(INPUT);
   }
   $FPList[$Actioncnt] = $tempfile;
    $EndTimeList[0] = $TimeList[0];

    
}
#########################################################################
#   Subroutine : CreateTSEventList()
#   This routine prepares a list of Time Stamp Events from the input file
#   This routine reads the list of events between any two user actions as
#   shown by the FPList and estimates the duration of different events.
#   
#   FPList  is the list of file pointers pointing to the User action point
#           in the logged information
#   TSEventList is the list of TimeStamp events that are available
#   
#   ActionList  is the list of User actions, i.e. names 
#   ThinkList   list of think times
#   
#########################################################################
sub CreateTSEventList()
{

    for $i ( 0 .. $#FPList )
    {
         #print "Entering CreateTSeventlist for $i in $#FPList"; $test=<STDIN>;
         $Actendtime = 0;
         $Enduseract = $ActionList[$i];
         GroupInit();
         $Stfptr = $FPList[$i];
         $Endfptr = $FPList[$i+1];

         for ( $j = 0; $j < @TSEventlist; $j++ )
         {

             $Totalcnt = 0;
             $Totaltime = 0;
             $Mintime = 100000;
             $Maxtime = 0;
             seek(INPUT, $Stfptr, 0);
             $Curfptr = tell(INPUT);
             ($Stevent, $Endevent) = split('-', $TSEventlist[$j]);
             while( ($Endfptr > $Curfptr) )
             {
                 $Curline = GetNewLine ($Stevent, $Endfptr);
                 $filepos = tell(INPUT);
                 if ( $Curline )
                 {
                     ($Event1, $Bytes1, $Cstime, $Sttime) 
			 = split ' ',$Curline;
		     chomp($Newline = <INPUT>);
                     $filepos = tell(INPUT);
                     ($Readval, $Str) = split(' ', $Newline, 2);
                     if ( $Readval ne $TIMESTKEY )
		     {
			 $Curfptr = tell (INPUT);
		     }
		     ($Actstr, $Evstr) = split  ' ', $Str;
		     if ($Actstr eq $Endevent)
		     {
			 #print "Finding a match for $Actstr with $Endevent"; 
			 #$test=<STDIN>;
			 ($Action, $Bytes2, $Cetime, $Endtime) 
			     = split ' ',$Str;
			 if ($Actendtime < $Endtime )
			 {
			     $Actendtime = $Endtime;
			     $Lastevent = $Str;
			 }
			 #print "\n Endtime $Endtime and Starttime $Sttime"; 
			 $Time = ($Endtime - $Sttime) /$div_factor;
			 if ( ($Stevent eq 'FSERVER_END' ) &&
			     ($Endevent eq 'FSERVER_START') )
			 {
			     $CTime = ($Cetime - $Cstime);
			     if ( $CTime > $Time )
			     {
				 $CTime = $Time;
			     }
			     #print "\n Diff is $Time $CTime"; $test=<STDIN>;
			     UpdateClientTotal($CTime);
			     UpdateNetTotal($Time - $CTime);
			     UpdateGTotal("Net", $Time - $CTime);
			 } 
			 else
			 {
			     #print "\n Diff is $Time"; $test=<STDIN>;
			     UpdateTotal($Time);
			 }
		     }
		 }
		 $Curfptr = tell (INPUT);
	     }
  
	     $Curaction = $Stevent.'-'.$Endevent;
	     if ( exists ($EventHash{$Curaction}) )
	     {
		 $Resevent = $EventHash{$Curaction};
		 $Resstr = join(' ', $Resevent, $Totalcnt,
				$Totaltime, $Mintime, $Maxtime);
		 #print "Resstr here is $Resstr Action cnt $Actioncnt"; 
		 #$test = <STDIN>;
	     }
	     else
	     {
		 $Curaction = "temp";
		 $Resevent = $EventHash{$Curaction};
		 $Resstr = join(' ', $Resevent, $Totalcnt,
				$Totaltime, $Mintime, $Maxtime);
	     }

	     #
	     ##If the group name exists for the action in the
	     ##current list, add to that grouplist. Otherwise,
	     ##add to the group with name Groupname list  
	     ##Otherwise assume the groupname as FServer and
	     ##update in that.
	     if ( exists ($GroupHash{$Curaction}) )
	     {
		 $Pgroup = $GroupHash{$Curaction};
		 #print "\n Getting the gname $Pgroup for $Curaction"; 
		 #$test=<STDIN>;
		 UpdateGTotal($Pgroup, $Totaltime);
             }
          
             if ( $Totalcnt > 0 )
             {
                 if ( $Resstr )
                 {
                     push(@ResList, $Resstr);
                 }
             }  
	 }
	 
	 if ( $i > 0 )
	 {
	     $temp =  ($TimeList[$i] - $EndTimeList[$i])/$div_factor;
	     $ctime = $CTimeList[$i];
	     if ( $ctime > $temp )
	     {
		 $ctime = $temp ;
	     }               
	     UpdateNetTotal($temp - $ctime);
	     UpdateGTotal("Net", $temp - $ctime);
	     UpdateClientTotal($ctime);
	 }
	 if ( $Clientcnt > 0 )
	 {
	     
	     $Resevent = "Net";
	     $Resstr = join(' ', $Resevent, $Netcnt, 
			   $Nettime, $NMintime, $NMaxtime);
	    
	     push(@ResList, $Resstr); 
	     $Resstr = join(' ', "ClientTime", $Clientcnt,
			    $Clienttime, $CMintime , $CMaxtime);
	     
	     push(@ResList, $Resstr);
	     if ( exists ($GroupHash{"temp1-temp1"}))
	     {
		 $Pgroup = $GroupHash{"temp1-temp1"};
		 UpdateGTotal($Pgroup, $Clienttime);
	     }
	     ClientandNetInit();
	     
	 }
        if ( $#ResList >= 0)
        {
            push @ActResults, [@ResList];
           
            push @GroupResults, [%GdataHash];
            #while ( ($k, $v) = each %GdataHash) 
            #{
            #     print "$k => $v \n";
            #}
            #$test = <STDIN>;
            ResetGTotal("Net");
            ResetGTotal("temp1-temp1");
            $#ResList = -1;
        }
        else
        {
            #print "Trying to push empty here ????????"; $test=<STDIN>; 
            push @ActResults, "Here comes the nulvalues";
            push @GroupResults, "Here comes emptty group";
            $#ResList = -1;
        }
    }
    $EndTimeList[$Actioncnt] = $Endtime;
    for ( $k = 0; $k <= $Actioncnt  ;$k++ )
    {
         #print "EndTimelist is $EndTimeList[$k] ?????"; $test=<STDIN>;
    }
}

#########################################################################
sub CreateUserEventList()
{
    my (@UserEventlist);

    @UserEventlist = keys %EventHash;

    for $i ( 0 .. $#FPList )
    {
         # Read from the Actionlist
         $Actendtime = 0;
         $Enduseract = $ActionList[$i];
         $Stfptr = $FPList[$i];
         $Endfptr = $FPList[$i+1];
         
         foreach $UserEvent (@UserEventlist) 
         {
             $Totalcnt = 0;
             $Totaltime = 0;
             $Mintime = 100000;
             $Maxtime = 0;
             seek(INPUT, $Stfptr, 0);
             $Curfptr = tell(INPUT);
             ($Stevent, $Endevent) = split('-', $UserEvent);
             #print "Looking for event $UserEvent "; $test = <STDIN>;
 
             while( ($Endfptr > $Curfptr) )
             {
                 $Curline = GetNewLine ($Stevent, $Endfptr);
                 #print "Coming here current line  $Curline"; $test=<STDIN>;
                 if ( $Curline )
                 {
                     ($Event1, $Bytes1, $Stctime, $Sttime)
			 = split ' ',$Curline;
                      $Newline = GetNewLine($Endevent, $Endfptr);
                      #print "Reading new line $Newline"; $test=<STDIN>;
                      ($Action, $Bytes2, $Endetime, $Endtime) 
			  = split ' ',$Newline;
                      if ($Action eq $Endevent)
                      {
                          #print "Finding a match"; $test=<STDIN>;
                          if ($Actendtime < $Endtime )
                          {
                              $Actendtime = $Endtime;
                              $Lastevent = $Actstr;
                          }
                          #print "Endtime $Endtime and sttime $Sttime\n";
                          $Time = ($Endtime - $Sttime) /$div_factor;
                          #print "Updating time $Time"; $test=<STDIN>;
			  $CTime = ($Endctime - $Stctime);
                          UpdateTotal($Time);
                       }
                   }
                   $Curfptr = tell (INPUT);
              }
              $Resevent = $EventHash{$UserEvent};
              #print "UserEventlist is $UserEvent";
              $Resstr = join(' ', $Resevent, $Totalcnt,
                                 $Totaltime, $Mintime, $Maxtime);
              #print "\n Resstr here is $Resstr Action cnt $Actioncnt"; 
              #$test = <STDIN>;
              if ( $Resstr )
              {
                  #print "pushing now..."; $test=<STDIN>;
                  push(@UserList, $Resstr);
              }
          }
          if ( $#UserList > 0 )
          {
              #print "User list here is @UserList\n"; $test=<STDIN>;
              push @TUserList, [@UserList];
              $#UserList = -1;
          }
    }
}
#########################################################################
#  Subroutine : GetNewLine()
#  This routine reads the input file and returns the next valid line for
#  processing. 
#  Input : Event of interst
#  Output : Line containing the event of interest
#########################################################################

sub GetNewLine {
    my ($EndAction) = $_[0];

    my ($Test, $Readval, $Str, $Actstr, $Evstr, $Tval, $lptr, $tptr );

    $Tval = $Action;
    $lptr = tell(INPUT);
    while ( $lptr < $Endfptr )
    {
        if ( !eof(INPUT) )
        {
             chomp ($_ = <INPUT>);
             ($Readval, $Str) = split (' ', $_, 2);
             $lptr = tell (INPUT);
             if ( $Readval eq $TIMESTKEY )
             {
                 ($Actstr, $Evstr) = split ' ', $Str;
                 if ( $Actstr eq $EndAction )
                 {
                     return ($Str);
                 }
             }
             else
             {
                 $Str = "";
                 return $Str;
             }
        }
        else
        {
             $Endfptr = $lptr; 
        }
    }
    return "";
}
#########################################################################
#  Subroutine : UpdateTotal()
#  This routine updates the global variables $Mintime, $Maxtime
#  $Totalcnt and $Totaltime for an event
#  Input : Time value to be used for updating the global variables 
#  Output : NULL
#########################################################################
sub UpdateTotal( )
{
    my $ttime = $_[0];

    $Totalcnt++;
    $Totaltime += $ttime;
    if ( $ttime < $Mintime )
    {
        $Mintime = $ttime;
    }
    else
    {
        if ( $Totalcnt == 1 )
        {
            $Mintime = $ttime;
        }
    }
    if ( $ttime > $Maxtime )
    {
        $Maxtime = $ttime;
    }
} 
#########################################################################
#  Subroutine : UpdateTotal()
#  This routine updates the global variables $Mintime, $Maxtime
#  $Totalcnt and $Totaltime for an event
#  Input : Time value to be used for updating the global variables 
#  Output : NULL
#########################################################################

sub UpdateClientTotal( )
{
    my $ttime = $_[0];

    $Clientcnt++;
    $Clienttime += $ttime;
    if ( $ttime < $CMintime )
    {
        $CMintime = $ttime;
    }
    else
    {
        if ( $Clientcnt == 1 )
        {
            $CMintime = $ttime;
        }
    }
    if ( $ttime > $CMaxtime )
    {
        $CMaxtime = $ttime;
    }  
} 
sub UpdateNetTotal()    
{
    my $ttime = $_[0];

    $Netcnt++;    
    if ( $ttime < 0 )
    {
        $ttime = 0;
    }
    $Nettime += $ttime;
    if ( $ttime < $NMintime )
    {
        $NMintime = $ttime;
    }
    else
    {
        if ( $Netcnt == 1 )
        {
            $NMintime = $ttime;
        }
    }
    if ( $ttime > $NMaxtime )
    {
        $NMaxtime = $ttime;
    }
   
} 
#########################################################################
#  Subroutine : UpdateGTotal()
#  This routine updates the global variables $Minval, $Maxval and
#  TotalTime for a group of events 
#  Creates the Event list and returns to the calling routine
#  Input : Groupname, Time to be addeded to the group
#  Output : NULL, Adds in the global % and returns 
#########################################################################

sub UpdateGTotal( )
{
    my ($groupname, $ttime) = @_;

    my ($Outstr, $TotalTime) = ("", 0);
    my ($Minval, $Maxval) = (100000, 0);
    
    $Outstr = $GdataHash{$groupname};
    ($TotalTime, $Minval, $Maxval) = split (',',$Outstr,3);
    $TotalTime += $ttime;
    if ( $ttime < $Minval )
    {
        $Minval = $ttime;
    }
    if ( $ttime > $Maxval )
    {
        $Maxval = $ttime;
    }
    $Outstr = $TotalTime.','.$Minval.','.$Maxval;
    $GdataHash{$groupname} = $Outstr;
}
#########################################################################
#  Subroutine : UpdateGTotal()
#  This routine updates the global variables $Minval, $Maxval and
#  TotalTime for a group of events 
#  Creates the Event list and returns to the calling routine
#  Input : Groupname, Time to be addeded to the group
#  Output : NULL, Adds in the global % and returns 
#########################################################################

sub ResetGTotal(  )
{
    my ($groupname)  = @_;

    my ($Outstr, $TotalTime) = ("", 0);
    my ($Minval, $Maxval) = (100000, 0);
    
    $Outstr = $GdataHash{$groupname};

    $Outstr = $TotalTime.','.$Minval.','.$Maxval;
    $GdataHash{$groupname} = $Outstr;
}        

#########################################################################
#  Subroutine : PrintSummary
#  This routine Prints the Summary list. This mainly concentrats on the
#  user think time.
#  
#########################################################################

sub PrintSummary( )
{
    my ($i, $Sttime, $Tmptime, $Oldtime, $Duration, $Diff);
    
	
    print "\n",'-' x 80, "\n";
    print " , , ,Summary \n";
    print "\n";
    print "No, Action, , Time of , , Client+ \n";
    print ", , , Occurance,  , Net Time\n";
    print " , , ,Absolute,Relative \n";
    print " , , ,(msec),(msec),(msec) \n";
    print '-' x 80, "\n";

    $Sttime = 0;
    $Oldtime = $TimeList[0];
    #$Actioncnt--;
    for $i ( 0 .. $Actioncnt-1)
    {
        $Tmptime = $TimeList[$i];
        $Duration = ($Tmptime)/$div_factor;
        $Diff = ($Tmptime - $Oldtime)/$div_factor;
        printf ("%4d,%25s,%20f,%10.3f \n",
                         $i+1,$ActionList[$i],
                         $Duration, $Diff);
                        
    }
    print "\n \n \n"; 

}

sub PrintSummaryXML( )
{
    my ($i, $Sttime, $Tmptime, $Oldtime, $Duration, $Diff);

    open (SUMOUTPUT, "> $sumoutput") || 
            die "Not able to open Output file $Outfile $!";

    select(SUMOUTPUT);

    print "\n <html> \n <head>";
    print "\n<title>Forms Performance Analysis - Summary</title>";
    print "\n<\/head> \n    <body>";
    print "\n<center><h2>Summary View<\/h2></center>";
    print "\n<a href=\"runtime.html\"><center><h3>Runtime Details</h3></center></a>";
    print "\n<table width=100% border=1><thead>";
    print "\n <tr> <th rowspan=2>#<\/th> ";
    print "\n<th rowspan=2>Action<\/th> ";
    print "\n <th COLSPAN=2>Time of Occurrence <sup>*<sup><\/th> ";
    ### Not required for now.##
    #print "\n  <th rowspan=2>User + Client + Net Time (msec)<\/th>";
    print "\n  <\/tr>";

    print "\n  <th>Absolute Time (msec)<\/th>";
    print "\n  <th>Relative Time (msec)<\/th>";
    print "\n <\/thead>";
    $Sttime = 0;
    $Oldtime =$StartUpTime ;
 printf (" <\/tr> ");
    printf("\n<td><\/td>");
    printf("\n<td>STARTUP<\/td>");
    printf("\n<td>%20f<\/td>", $StartUpTime/$div_factor);
      printf (" <\/tr> ");

    printf("\n<td><\/td>");
    printf("\n<td> HandShake Duration<\/td>");
    printf("\n<td>%20f<\/td>", ($HandShake)/$div_factor);
    printf ("<td> %10.3f </\td>  ",($HandShake- $StartUpTime)/$div_factor);
    printf (" <\/tr> <tr> ");
    printf ("\n<td>0 <\/td> \n <td> <a href=\"%s#0\" <\/a> ", $lvl1out);
    printf (" %25s <\/td>  ", $ActionList[0]);
    printf ("<td> %20f </td>  ",($TimeList[0])/$div_factor);
    printf ("<td> %10.3f </\td> </tr>  ",
	    ($TimeList[0] - $HandShake)/$div_factor);
    #$Actioncnt--; $cnt = 0;
    for $i ( 1 .. $Actioncnt-1 )
    {
        printf ("<tr>");
        #$Tmptime = $TimeList[$i];
        $Duration = ($EndTimeList[$i] - $Sttime)/$div_factor;
        #$Diff = ($Tmptime - $Oldtime)/$div_factor;
        $Diff = ($EndTimeList[$i] - $EndTimeList[$i-1])/$div_factor;
	printf ("\n<td> %4d <\/td>  ", $i);
        printf ("\n<td> <a href=\"%s#%d\" <\/a> ", $lvl1out, $i);
        printf (" %25s <\/td>  ", $ActionList[$i]);
        printf ("<td> %20f </td>  ",$Duration);
        printf ("<td> %10.3f </\td>  ",$Diff);
        # 
        # This part gives the Client + User + Net time. Since it may not
        # be correct always, this has been removed.
        #if ( $i > 0 )
        #{
        #    printf ("<td>%10.3f </\td> ",
	#	    ($TimeList[$i]-$EndTimeList[$i])/$div_factor);
        #}
        $Oldtime = $Tmptime;
        printf (" <\/tr> \n\n");
    }
   # print '-'x80, "\n";
    print("\n<\/table>");
    print("\n<\/tbody>");
    print("\n<\/table>");
    print("<br><br>");
    print("<b>Note:</b> A User Action starts when the previous User Action ");
    print("Ends");  
    print("\n<\/body>");
    print("\n<\/html>");    print "\n \n \n";
}
#########################################################################
#  Subroutine : PrintDetails
#  This routine Prints the Details of the events between user actions.
#########################################################################

sub PrintDetails()
{
    my ($i, $Tmpst, $Tmpend, $Ans, $Oldtime, $Duration, $Diff);
    $Stno = 0;
    $Endno = $Actioncnt;

    PrintQuery();
    #PrintUserEvents();
    PrintActions();
}


sub PrintDetailsXML()
{
    my ($i, $Tmpst, $Tmpend, $Ans, $Oldtime, $Duration, $Diff);
    $Stno = 0;
    $Endno = $Actioncnt;

    PrintActionsXML();
    PrintCollectHTML();
#   PrintActionsAllXML();
}

sub PrintQuery()
{
    my ($i, $Tmpst, $Tmpend, $Ans, $Oldtime, $Duration, $Diff);

    if ( !$output )
    {
        until ($Ans eq "y" || $Ans eq "n" || $Ans eq "Y" || $Ans eq "N")
        {
            print "Do you want to see the detailed results? [Y]/[N] \n";
            chomp($Ans = <STDIN>);
        }
	    if ( $ans eq 'n' || $ans eq 'N' )
        {
            exit;
        }
        print "The Detailed results can be displayed between any two \n";
        print "User Actions listed above. Enter the Starting and Ending\n";
        print "action numbers\n";
		print '-' x 80, "\n";
        print "Enter the Starting Action Number default[0]";
        chomp($Stno = <STDIN>);
        if ( !$Stno ) 
        {
            $Stno = 0;
        }
        print "Enter the Ending Action Number default[$Actioncnt]";
        chomp($Endno = <STDIN>);
        if ( !$Endno )
        {
            $Endno = $Actioncnt;
        }
        print "Start no $Stno   End No $Endno\n "; $test=<STDIN>;
    }
   #print '-'x100,"\n";
    print ", , Detailed  Results \n";
    print " ,           BETWEEN ACTION $ActionList[$Stno] and     $ActionList[$Endno] \n,";
}

sub PrintUserEvents()
{
    print "UserAction, , Event, Count, Total,Total,Min,Max,Avg\n";
    print " , , , , , Time,Time,Time,Time,Time\n";
    print" , , , , , (msec),(%),(msec),(msec),(msec)\n";
   # print "\n into Userlist print $Stno    $Endno"; $test=<STDIN>;
    
    for $i ( $Stno+1 .. $Endno-1 )
    {
        print "\n,$ActionList[$i-1],"; 
        $temptotal = 0;
        $tempper = 0;
        $tempval = $TimeList[$i] - $TimeList[$i-1];
        for ( $j = 0; $j <=  $#{$TUserList[$i]} ; $j+=1 )
        {
             $UEvent = $TUserList[$i][$j];
             ($Prevent, $Prcnt, $Prttime, $Prmintime, $Prmaxtime)
                               = split (' ', $UEvent);
             if ( $Prcnt > 0 )
             {
                 $Pravtime = $Prttime/($Prcnt);
             
             printf "%15s,%8d,%11.3f,%11.3f,%10.3f,%11.3f,%11.3f\n, , ,",
                     $Prevent, $Prcnt, $Prttime,$Prttime*100/$tempval,$Prmintime, 
                     $Prmaxtime, $Pravtime;
             }
        }
   }        
   print "\n \n \n,";
        
}

sub PrintActions()
{
    print "UserAction, , Event, Total,Total,Min,Max\n";
    print ", , , ,Time,Time,Time,Time\n";
    print" , , , ,(msec),(%),(msec),(msec)\n";
    for $i ( $Stno .. $Endno-1 )
    {
        print ",$ActionList[$i],";
        $temptotal = 0;
        $tempper = 0;
        #print "GroupResults is $#{$GroupResults[$i]}"; $test= <STDIN>;
        if($#{$GroupResults[$i]}) 
        {
            $Tempoff = 1;
            if (($TimeList[$i+$tempoff] == $TimeList[$i]) )
            {
                 $tempoff ++;
            }
            $tempval = ($EndTimeList[$i+$tempoff]-$EndTimeList[$i])/$div_factor;
            #print "Tempoval for $i value is $tempval"; $stdin = <STDIN>; 
        }
        for ( $j = 0; $j <  $#{$GroupResults[$i]} ; $j++ )
        {
            $Ghash = $GroupResults[$i][$j];
            @Times = split (',', $GroupResults[$i][$j+1]);
            if ( $Times[0] != "0" ) 
            {
                if ( $tempval != 0 )
                {
                    printf("%15s,%10.3f,%10.3f, %10.3f, %10.3f \n,,,", 
                                   $GroupResults[$i][$j], 
                                   $Times[0], $Times[0]*100/$tempval,
                                   $Times[1], $Times[2]);
                $temptotal += $Times[0];
                $tempper += ($Times[0]*100/$tempval);
                }
            }
        }
        printf ("GrandTotal, %10.3f, %10.3f", $temptotal, $tempper);
        print "\n \n \n";
    }  
    print "\n\n\n,";
    print "UserAction, , Event,Count,Total,Total,Min,Max,Average\n";
    print " , , ,, ,Time,Time, Time,Time,Time \n";
    print" , , , , ,(msec),(%),(msec),(msec),(msec)\n";

    for $i ( $Stno .. $Endno-1 )
    {
        print ",$ActionList[$i]\n";
        print ", ,RegularEvents,";

        $temptotal = 0;
        $tempper = 0;
        $tempval = ($EndTimeList[$i+1]-$EndTimeList[$i])/$div_factor;
        for $j ( 0 .. $#{$ActResults[$i]} )
        {
            ($Prevent, $Prcnt, $Prttime, $Prmintime, $Prmaxtime)
                               = split (' ', $ActResults[$i][$j]);
             $Pravtime = $Prttime/($Prcnt);
             if ( $tempval > 0 )
             {
                  printf "%15s,%8d,%11.3f,%11.3f,%10.3f,%11.3f,%11.3f\n ,, ,",
		  $Prevent, $Prcnt,                                           
                   $Prttime,$Prttime*100/$tempval,$Prmintime, 
                     $Prmaxtime, $Pravtime;
             
             $temptotal += $Prttime;
             $tempper += ($Prttime*100/$tempval);
             }
        }
        printf "GrandTotal, ,%10.3f, %10.3f,,\n ", $temptotal, $tempper;
    }
    #print "The action count is $Actioncnt \n"; $test = <STDIN>;
    for ( $i = 0; $i < $#Actresults ; $i++ )
    {
        $Aref = $Actresults[$i];
        print "\n Aref is $Aref with count $#Aref";
        for $j ( 0..$#{Aref} )
        {
            print "element $i $j is $Aref->[$j]\n";
            $test = <STDIN>;
        }
    }
}


sub PrintActionsXML()
{
   
    open (LVL1OUTPUT, "> $lvl1out") || 
            die "Not able to open Output file $lvl1out $!";

#    select(STDOUT);
    select(LVL1OUTPUT);
    print "\n <html> \n <head>";
    print "\n<title>Forms Performance Analysis - Details</title>";
    print "\n<\/head> \n    <body>";
    print "\n<center><h2>Detailed View<\/h2></center>";
    $Stno = 0;
    for $i ( $Stno .. $Endno-1  )
    {
    printf("\n <a name=%d>", $i);
   # print "\n<center><h2> $i $ActionList[$i]<\/h2></center> <\/a>";
    printf("\n<td> <a href=\"%s#%d\" > ", $lvl2out, $i);
    print "<center><h4>Action $i: $ActionList[$i]<\/h4></center><\/a><\/a>", ;
    printf("\n <\/a> ", $lvl2out, $i);
    print "\n<table width=100% border=1><thead>";
    print "\n  <th colspan=5>Details Level 1 <\/th>";
    print "\n  <\/tr>";
    print "\n  <th><a href=\"event.html\">GroupEvent  <\/a><\/th>";
    print "\n  <th>Total Time (msec)<\/th>";
    print "\n  <th>Total Time (%)<\/th>";
    print "\n  <th>Min Time(msec)<\/th>";
    print "\n  <th>Max Time(msec)<\/th>";
    print "\n <\/thead>";
    print "\n <tr>";
        PrintNextLevel($i);
    print "\n</\tr>  <tr>";
    print("\n<\/table>");

    
    print "\n<table width=100% border=1><thead>";
  
    print "\n  <th colspan=7>Details Level 2<\/th>";
    print "\n  <\/tr>";
    print "\n  <th><a href=\"event.html\">FSEvent <a> <\/th>";
    print "\n  <th>count  <\/th>";
    print "\n  <th>Total Time (msec)<\/th>";
    print "\n  <th>Total Time (%)<\/th>";
    print "\n  <th>Min Time(msec)<\/th>";
    print "\n  <th>Max Time(msec)<\/th>";
    print "\n  <th>Avg Time(msec)<\/th>";
    print "\n <\/thead>";
    print "\n <tr>";
         PrintNextDetailedLevel($i);
         print "\n</\tr>  <tr>";
    print("\n<\/table>");

    }
    print("\n<\/body>");
    print("\n<\/html>");    print "\n \n \n";

}

sub PrintNextLevel()
{
     my($i) = @_;

       
#     printf("\n<td> <a href=\"%s#%d\" <\/a> ", $lvl2out, $i);
#     print "\n $ActionList[$i] </\td>";
        
     $temptotal = 0;
     $tempper = 0;
     #print "GroupResults is $#{$GroupResults[$i]}"; $test= <STDIN>;
     if($#{$GroupResults[$i]} > 0) 
     {
         $Tempoff = 1;
         if (($TimeList[$i+$tempoff] == $TimeList[$i]) )
         {
              $tempoff ++;
         }
         $tempval = ($EndTimeList[$i+1]-$EndTimeList[$i])/$div_factor;
         #print "Tempoval for $i value is $tempval"; $test = <STDIN>; 
         for ( $j = 0; $j <  $#{$GroupResults[$i]} ; $j++ )
         {
             $Ghash = $GroupResults[$i][$j];
             @Times = split (',', $GroupResults[$i][$j+1]);
            if ( $Times[0] != "0" ) 
            {
                #print "for Groupresult $GroupResults[$i][$j+1]";$test = <STDIN>;
                if ( $tempval != 0 )
                {
                      printf("\n<td><a href=\"event.html\"> %15s </\td></\a>",                                 $GroupResults[$i][$j]);
                      printf("\n<td> %10.3f </\td>", $Times[0]);
                      printf("\n<td> %10.3f </\td>", $Times[0]*100/$tempval);           
                      printf("\n<td> %10.3f </\td>", $Times[1]);           
                      printf("\n<td> %10.3f </\td>\n", $Times[2]);                                  			
                      $temptotal += $Times[0];
                      $tempper += ($Times[0]*100/$tempval);
                      print "\n </\tr> <tr>  ";         
		  }
             
            }

           }
           print "\n<\/tr> <tr>   ";         
       }
         
       printf ("\n<td>GrandTotal</\td><td> %10.3f</\td><td> %10.3f</\td>", 
                 $temptotal, $tempper);
       print "</\tr>";         

}

sub PrintActionsAllXML()
{

    open (LVL2OUTPUT, "> $lvl2out") || 
            die "Not able to open Output file $lvl1out $!";
    
    select(LVL2OUTPUT);
    print("<?xml version=\"1.0\" ?>\n");
    print("<?xml-stylesheet type=\"text/xsl\" href=\"detail2.xsl\" ?>\n");
    print("<detail2>");
    print "<item>";
    for $i ( $Stno .. $Endno-1 )
    {
    }
}

sub PrintNextDetailedLevel()
{

     my($i) = @_;

        $temptotal = 0;
        $tempper = 0;
        $tempval = ($EndTimeList[$i+1]-$EndTimeList[$i])/$div_factor;

        for $j ( 0 .. $#{$ActResults[$i]} )
        {
            ($Prevent, $Prcnt, $Prttime, $Prmintime, $Prmaxtime)
                               = split (' ', $ActResults[$i][$j]);
             $Pravtime = $Prttime/($Prcnt);
             if ( $tempval > 0 )
             {
                      printf("\n<td><a href=\"event.html\"> %15s </\a></\td>",
                                   $Prevent );
                      printf("\n<td> %8d </\td>",$Prcnt );
                      printf("\n<td> %10.3f </\td>", $Prttime);
                      printf("\n<td> %10.3f </\td>", $Prttime*100/$tempval);           
                      printf("\n<td> %10.3f </\td>", $Prmintime);           
                      printf("\n<td> %10.3f </\td>\n", $Prmaxtime);
                      printf("\n<td> %10.3f </\td>\n", $Pravtime);                         
                          
                     $temptotal += $Prttime;
                     $tempper += ($Prttime*100/$tempval);
             }
           
             print "</\tr>  <tr>";         
             
        }
        printf "\n<td>GrandTotal</\td> <td> </\td> \n <td>%10.3f</\td>\n<td>%10.3f</\td>\n ",
                        $temptotal, $tempper;
        print "\n</\tr>";   
 }

sub GetOptions {

    my @optionlist = @_;    # local copy of the option descriptions
    my $argend = '--';      # option list terminator
    my %opctl;          # table of arg.specs
    my %aliases;        # alias table
    my @ret = ();       # accum for non-options
    my %linkage;        # linkage
    my $userlinkage;        # user supplied HASH
    $error = 0;
    $genprefix = "(--|-|\\+)";


    # Verify correctness of optionlist.
    %opctl = ();
    while ( @optionlist > 0 ) 
    {
        my $opt = shift (@optionlist);

        # Strip leading prefix so people can specify "-foo=i" if they like.
        $opt = $' if $opt =~ /^($genprefix)+/;


        if ( $opt !~ /^(\w+[-\w|]*)?(!|[=:][infse]@?)?$/ ) 
        {
            warn ("Error in option spec: \"", $opt, "\"\n");
            $error++;
            next;
        }
        my ($o, $c, $a) = ($1, $2);

        if ( ! defined $o ) 
        {
            # empty -> '-' option
            $opctl{$o = ''} = defined $c ? $c : '';
        }
        else 
        {
            # Handle alias names
            my @o =  split (/\|/, $o);
            $o = $o[0];
            foreach ( @o ) 
            {
                if ( defined $c && $c eq '!' ) 
                {
                    $opctl{"no$_"} = $c;
                    $c = '';
                }
                $opctl{$_} = defined $c ? $c : '';
                if ( defined $a ) 
                {
                    # Note alias.
                    $aliases{$_} = $a;
                }
                else 
                {
                    # Set primary name.
                    $a = $_;
                }
            }
        }

        # Copy the linkage. If omitted, link to global variable.
        if ( @optionlist > 0 && ref($optionlist[0]) ) 
        {
            print STDERR ("=> link \"$o\" to $optionlist[0]\n")
            if $debug;
            if ( ref($optionlist[0]) eq 'SCALAR') 
            {
                $linkage{$o} = shift (@optionlist);
            }
            else 
            {
                warn ("Invalid option linkage for \"", $opt, "\"\n");
                $error++;
            }
        }
    }

    # Bail out if errors found.
    return 0 if $error;

    # Show if debugging.
    if ( $debug ) 
    {
        my ($arrow, $k, $v);
        $arrow = "=> ";
        while ( ($k,$v) = each(%opctl) ) 
        {
            print STDERR ($arrow, "\$opctl{\"$k\"} = \"$v\"\n");
            $arrow = "   ";
        }
    }

    my $opt;            # current option
    my $arg;            # current option value
    my $array;          # current option is array typed

    # Process argument list
    while ( @ARGV > 0 ) 
    {
        # >>> See also the continue block <<<

        #### Get next argument ####

        $opt = shift (@ARGV);
        $arg = undef;
        my $optarg = undef;
        $array = 0;
        print STDERR ("=> option \"", $opt, "\"\n") if $debug;

        #### Determine what we have ####

        # Double dash is option list terminator.
        if ( $opt eq $argend ) 
        {
            # Finish. Push back accumulated arguments and return.
            unshift (@ARGV, @ret)
        }

        if ( $opt =~ /^$genprefix/ ) 
        {
            ($temp, $optarg) = split ('=',$opt,2);
            #oks like an option.
            $opt = $';      # option name (w/o prefix)
        }

        # ...otherwise, terminate.
        else 
        {
            # Push this one back and exit.
            unshift (@ARGV, $opt);
            return ($error == 0);
        }

        #### Look it up ###
        ($temp, $optarg) = split('=',$opt, 2);
        $opt = $temp;
        $tryopt = $opt;
        my $type;
        unless  ( defined ( $type = $opctl{$tryopt} ) ) 
        {
            print STDERR ("Unknown option: ", $opt, "\n");
            $error++;
            next;
        }

        $opt = $tryopt;
        print STDERR ("=> found \"$type\" for ", $opt, "\n") if $debug;

        #### Determine argument status ####

        # Get mandatory status and type info.
        my $mand;
        ($mand, $type, $array) = $type =~ /^(.)(.)(@?)$/;
        # Check if there is an option argument available.
        if ( defined $optarg ? ($optarg eq '') : (@ARGV <= 0) ) 
        {
            # Complain if this option needs an argument.
            if ( $mand eq "=" ) 
            {
                print STDERR ("Option ", $opt, " requires an argument\n");
                $error++;
            }
            next;
        }

        # Get (possibly optional) argument.
        $arg = defined $optarg ? $optarg : shift (@ARGV);
        #print "\n Latest arg value comes here ...2 $arg"; $value = <STDIN>;

        #### Check if the argument is valid for this option ####

        if ( $type eq "s" ) 
        {   
            # string
            # A mandatory string takes anything.
            next if $mand eq "=";
            # An optional string takes almost anything.
            next if defined $optarg;
            next if $arg eq "-";

            # Check for option or option list terminator.
            if ($arg eq $argend || $arg =~ /^$genprefix.+/) 
            {
                # Push back.
                unshift (@ARGV, $arg);
                # Supply empty value.
                $arg = '';
            }
            next;
         }

        die ("Internal error (Can't happen)\n");
    }

    continue 
    {
        if ( defined $arg ) 
        {
            $opt = $aliases{$opt} if defined $aliases{$opt};
            if ( defined $linkage{$opt} ) 
            {
                print STDERR ("=> ref(\$L{$opt}) -> ",
                  ref($linkage{$opt}), "\n") if $debug;

                if ( ref($linkage{$opt}) eq 'SCALAR' ) 
                {
                    print STDERR ("=> \$\$L{$opt} = \"$arg\"\n") if $debug;
                    #print "assigning $arg for $opt"; $value = <STDIN>;
                    ${$linkage{$opt}} = $arg;
                }
            }
            # No entry in linkage means entry in userlinkage.
            else 
            {
                print STDERR ("=>\$L{$opt} = \"$arg\"\n") if $debug;
                $userlinkage->{$opt} = $arg;
             }
         }
    }

    # Finish.
    if ( $error == 0)
    {
        #  Push back accumulated arguments
        unshift (@ARGV, @ret) if @ret > 0;
    }

    return ($error);
}


sub PrintHelp {

    print"\n################################################################";
    print"\n##              FORMS PERFORMANCE DATA PARSER                 ##";
    print"\n#################################################################";
    print "\n##                                                            ## ";
    print "\n##     InputFile : Data collected using 'record = performance'## ";
    print "\n##                 in the command line                        ## ";
    print "\n##     EventFile : Lists the events of interest to the user.  ## ";
    print "\n##                 <Optional> If not defined default events   ## ";
    print "\n##                 will be taken                              ## ";
    print "\n##     OutputFile : The file to store the result in xls format## ";
    print "\n##                                                            ## ";
    print"\n#################################################################";
    print "\n \n \n";
    print "\n                  !!!!!!!!!!!!!!!!!!!!!!!!!";
    print "\n                     New Additions         ";
    print "\n                     HTML OUTPUT           ";
    print "\n                  !!!!!!!!!!!!!!!!!!!!!!!!!";
    print "\n  The data presented in spreadsheet output is also  written in ";
    print "\n  the HTML format. Look for the  index.html and drill down further";
    print "\n \n \n";
}


sub PrintCollectHTML {

    open (LVL2OUTPUT, "> $lvl2out") || 
            die "Not able to open Output file $Outfile $!";

    select(LVL2OUTPUT);
    #select(STDOUT);
    $Actioncnt++;
    $eventfound = 0; 
    print "\n <html> \n <head>";
    print "\n<title>Forms Performance Analysis - Extracted View</title>";
    print "\n<\/head> \n    <body> ";
    print "\n<center><h2>Extracted View<\/h2></center> <table>";
    seek(INPUT, $Orgfptr, 0);
    printf("\n <a name=%d>", $i); print "<\/a>";
    printf("\n<center><h3>Action ", $i);
        
    chomp($Curline = <INPUT>);
    chomp($Curline = <INPUT>);
    ($temp, $optarg) = split(' ',$Curline, 2);
    print "$optarg <\/h3></center>";
    print("\n<table width=100% border=1> <thead>");
    print "\n  <th>TimeStamp Point<\/th>";
    print "\n  <th>CTime<\/th>";
    print "\n  <th>TimeStamp <\/th>";
    print "\n <\/thead> <tbody>";

    while (<INPUT>)
    {
            chomp($Curline = $_);
            #print "Current line read $Curline and i is $i"; $test = <STDIN>;
 
            if ( $Curline ne "" )
            {
		($temp, $optarg) = split(' ',$Curline, 2);
                if ( ($temp eq $EVENTKEY) ) 
                {
		     print "<\/tbody> <\/table>";
				    $i++;
		    printf("\n <a name=%d>", $i); print "<\/a>";
		    printf("\n<center><h3>Action  ", $i);
		  
		    print "$optarg <\/h3></center>";
		    print("\n<table width=100% border=1> <thead>");
		    print "\n  <th>Event<\/th>";
		    print "\n  <th>ClientTime<\/th>";
		    print "\n  <th>TimeStamp<\/th>";
		    print "\n <\/thead> <tbody>";
		    next;
		}
		else
		{
		    #print "Reading teh Timestkey "; $test=<STDIN>;
		    ($temp, $no, $ctime, $time) = split(' ',$optarg, 4);
		    print "<tr> <td> $temp <\/td> \n  <td>$ctime <\/td> <td>$time <\/td> <\/tr>"; 
		}
            }
            else
            {
		#print "The current line is empty"; $test=<STDIN>;
            }
	}
    $eventfound = 0;
    print "<\/tbody> <\/table>";
    print "\n </body> </html>";
}       
 

sub PrintIntro()
{
           
    open (INTRO, "> index.html") || 
            die "Not able to open Output file intro.html $!";
    select(INTRO);
print "<html><head><title>Forms Runtime Performance Data Parser ";
print "</title> </head> <body>";
print "<center><h1> FORMS PERFORMANCE DATA PARSER</h1></center>";
print "<center> <h3> ANALYSIS RESULTS</h3></center>";
print "<table BORDER=0 WIDTH=\"100%\"> <tr> <td>Input</td>";
print "<td>$Infile</td></tr>";
print "<tr><td>Output</td>";
print "<td>Comma Separated Variable Output for SpreadSheet";
if ( $Outfile eq "" )
{
     print "<br> File name not specified by the user </td> </tr></table> ";
}
else
{
     print "$Outfile </td> </tr></table>";
}
print "<center><h3>";
print "<hr WIDTH=\"100%\">HTML VIEWS</h3></center>";
print "<center>&nbsp;<a href=\"summary.html\">Summary View</a>";
print "<br>&nbsp;<a href=\"detailed.html#0\">Detailed View</a>";
print "<br>&nbsp;<a href=\"detailed2.html#0\">Extracted View</a>";
print "<br>&nbsp;<a href=\"event.html\">Event Definitions</a></center>";

print "<p><br><center> <h3>HELP ON USING THE VIEWS</h3></center>";
print "<b>Summary View:</b>";
print "<blockquote>This view provides a summary  of all User Actions with ";
print "related timing details.";
print "<br> The 'Time of Occurrence' of a User Action represents the start time ";
print "of the Action. The timestamp for a UserAction starts at the end of ";
print "previous UserAction. Thus, the Absolute time  of start of a User ";
print "Action is the instant at which the previous action ends.";
print "<br>The Relative Time is the duration between the successive User ";
print "Actions.";
print "<br>Startup is the Instant at which Client gets connected to the  ";
print "Forms Server.";
print "<br>Handshake duration shows the time taken to complete the handshake ";
print "between the Client and the Forms Server.</blockquote>";
print "<b>Detailed View :</b>";
print "<blockquote>&nbsp;&nbsp;&nbsp; 3-Tier view of the User Action execution";
print " time. This presents 2 levels of details.<br>";
print "<br><u>Detailed Level1:</u>";
print "&nbsp &nbsp &nbsp &nbsp <br> <br>";
print "Presents a detailed view of the total time spent at the DB Server, ";
print "the Forms Server, the Client and the Network during the execution ";
print "of a User Action.<br> ";
print "<br><u>Detailed Level2:</u><br>";
print "&nbsp<br>";
print "Presents a detailed view of the time spent at the Forms Server as ";
print "different Segments of time, by identifying the duration between the ";
print "different timestamping points. ";
print "The ClientTime and DB Server Time components ";
print "are the same as presented in Detailed View 1.</blockquote>";
print "<b>Extracted View:</b>";
print "&nbsp";
print "<blockquote> This is a view of the relevant data extracted from the ";
print "Raw Input file. The data is presented in 3 columns :";
print "<li> </blockquote>";
print "<b>Event Definition View</b>";
print "&nbsp";
print "<blockquote>&nbsp;Presents the description of the events as the duration";
print "between successive timestamping points.</blockquote>";

print"<center><h3><b>ACCURACY OF THE RESULTS</b></h3></center>";
print"<ul><li>The accuracy of the results depend on the accuracy ";
print "of the data supported by the underlying Operating System.</li>";
print "<li>The 'ClientTime'&nbsp; factor includes the Client CPU time and ";
print "the User Think Time.</li>";

print "<li>";
print "The 'ClientTime' is the factor determined  at the Java client UI ";
print "and thus depends on the accuracy with which the JVM provides the ";
print "timestamp values. Our experiments with clients of reasonable speed  ";
print "&nbsp (450MHz PIII, 128 MB RAM) ( show a deviation of 10-20msec, ";
print "during random user actions. ";
print "<li>";
print "The 'Net' factor is derived using the 'ClientTime' and the  ";
print "Forms Server TimeStamp instants. ";
print "Thus, the accuracy of value presented in 'Net' depends on the ";
print "accuracy of the ClientTime.</li>";
print "</ul>";
print "<br>";
print"</body></html>";
    close (INTRO);
}
