#
# SctDAQWebLib.pl
#
# A library of perl subroutines for interpretation of SCTDAQ result
# files, and the composing of summary web tables
#
# Code by Dave Charlton, Bruce Gallop & Peter Phillips
#

$SctDAQWebLibVersion="0.56" ;

# Version 0.56  DGC  24/06/03    Collate XML files correctly despite non-collating filenames
# Version 0.55  DGC  24/06/03    Add TestDCS info for DCS values from each test
#                                Treat IV test defects differently, via dummy channel 9999
# Version 0.54  PWP  24/06/03    Link to gzipped longterm plot if available
# Version 0.53  DGC  04/06/03    Show LTT raw data and PS files in table, if in txt file
# Version 0.52  DGC  14/04/03    Add Hybrid_IV as a standard test sequence
# Version 0.51  DGC  04/04/03    Find first and last lines of test
# Version 0.5   DGC  14/03/03    Major rewrite of parts to read log files and write
#                                HTML index pages
# Version 0.47  PWP  04/02/03    Calculate mean deltat between thermistor temperatures
# Version 0.46  DGC  03/02/03    Copy SCTDB comments into html file; Add function
#                                to get XML files; index these on html page
# Version 0.45  DGC  31/01/03    Really fix adjacent-defects bug(!)
# Version 0.44  DGC  18/10/02    Bug fix in defect table for adjacent defective
#                                channels with different defects; Correctly index
#                                previously-compressed .ps.gz files
# Version 0.43  DGC  10/10/02    Yet another MyChomp fix; add subheadings and 
#                                links to them in test web pages; block identically
#                                defective channels together in channel defect printout
# Version 0.42  DGC  09/10/02    Bug fix for s-curve plots, also gzip them
#                                too (on linux); other minor bug fixes
# Version 0.41  DGC  09/10/02    Bug fix in MyChomp for Win line ends
# Version 0.4   DGC  06/10/02    Merge Bruce's mods; add MyChomp for better
#                                parsing of Windows files on Linux; Add T to
#                                DetModIV printout; Add comments.txt to file
# Version 0.33  DGC  11/09/02    Fix timewalk bug
# Version 0.32  DGC  01/05/02    Minor mods
# Version 0.3   DGC  22/03/02    Migrated to library from scripts
#

require "./LocalVariables.pl" || die "Cannot load local variables" ;

return 1 ;

sub InitialiseVariables {

    &InitialiseLocalVariables ;
    @KnownTests=("DetModIV","ModIVScan","HardReset","FullBypassTest","RedundancyTest","PipelineTest",
		 "StrobeDelay","ThreePointGain","Trim","ResponseCurve","NO","Timewalk",
		 "LongTermTest") ;
    @KnownSequences=("Hybrid_IV","Hybrid_Initial","Hybrid_Longterm","Hybrid_Cold",
		     "Hybrid_Completion","Hybrid_Acceptance",
		     "Module_Initial","Module_Completion","Module_Reception","Module_Longterm",
		     "Module_Acceptance") ;
    @DCSVariables=("T<sub>0</sub>","T<sub>1</sub>","V<sub>DET</sub>","I<sub>DET</sub>",
		   "V<sub>CC</sub>","I<sub>CC</sub>","V<sub>DD</sub>","I<sub>DD</sub>") ;
    @DCSUnits=("deg. C","deg. C","V","microA",
		   "V","mA","V","mA") ;

# Following variable is used to distinguish Longterm tests in StoreTestResults.pl
    $NumTestsInCharacterisation=14 ;

}

sub PassFailString {
    return ( $Pass eq "YES" ? "PASS" : "<font color=red><b>FAIL</b></font>" ) ;
}

sub DefectString {
    my $str,$def,$type,$range,$first,$last,$d ;
    my $nd=$_[0] ;
    my $firstdefect=$_[1] ;
    my $lastdefect=$_[2] ;
    if ($nd==0) {
	$str="No defects" ;
    }
    else {
	$str="<b>$nd defect" . ( $nd>1 ? "s" : "" ) . "</b>";
	if ($nd<21) {
	    $str.=" (" ;
	    for ($d=$firstdefect;$d<$lastdefect+1;$d++) {
		$def=$Defect[$d] ;
		($type,$range)=split(' ',$def) ;
		($first,$last)=split('-',$range) ;
		if ($first==$last) {
		    $str.="$first " ;
		}
		else { 
		    $str.="$range " ;
		}
	    }
	    $str=substr($str,0,-1) ;
	    $str.=")" ;
	}
	else {
	    $str.=" (see results file for details)" ;
	}
    }
    return $str ;
}

sub WriteIndexHTMLHeader {
    my $DUT=$_[0] ;
    my $SequenceType=$_[1] ;
    print HTML "<html>\n<head>\n" ;
    print HTML "<title>$SequenceType Test of $DUT</title>\n" ;
    print HTML "</head>\n<body bgcolor=white>\n" ;
    print HTML "<h1>$SequenceType Test of $DUT</h1>\n" ;
    print HTML "<a href=#DCS>DCS</A> - " ;
    print HTML "<a href=#LTT>LTT plots</a> - " if $LTT ;
    print HTML "<a href=#RESULTS>Test results</a> - " ;
    print HTML "<a href=#DEFECTS>Defects</a> - <a href=#TRIMDEFECTS>Trim defects</A> - " ;
    if ($#xmlfiles>-1) {
	print HTML "<a href=#XMLS>XML Config file(s)</A> - \n" ;
    }
    print HTML "<a href=#LOGS>Log text files</A>\n" ;
    print HTML "<p>\n" ;
    print HTML "<pre>\n" ;
    print HTML "Tests started by     : \U$Initials[0]\n" ;
    print HTML "              at     : $Location[0]\n" ;
    print HTML "              on     : \L$Host[0]\n" ;
    if ($MinimumVersion==$MaximumVersion) {
	print HTML "SCTDAQ version       : $MaximumVersion\n" ;
    }
    else {
	print HTML "SCTDAQ versions      : $MinimumVersion - $MaximumVersion\n" ;
    }
    my $sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst ;
    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
    printf HTML "Page generated on    : %4.4d/%2.2d/%2.2d\n",$year+1900,$mon+1,$mday ;
    printf HTML "               at    : %2.2d:%2.2d\n",$hour,$min ;
    print HTML "SctDAQWebLib version : $SctDAQWebLibVersion\n" ;
    print HTML "</pre>\n" ;
}

sub ProcessLogFiles {
    my $dir=$_[0] ;
    my $SequenceType=$_[1] ;

    chdir $dir ;

# Get all the DCS information from the files

    &GetDCSInfo ;

# Get basic test information from the files

    &GetAllTestsInfo ;
#    &PrintAllTestsInfo ;

    &AnalyseDefects ;
    
    return 0 ;

}

sub PrintAllTestHTML {
    my $SequenceType=$_[1] ;

# start
    if ($LTT) {
	print HTML "<h3><A NAME=LTT>Long-term test files</A></h3>\n" ;
	foreach $plot (@psfiles) { 
 	    if ($plot=~/^longterm/){
	        $plot=&GZipIt(".",$plot) ;
	        print HTML "<a href=$plot> Temperature/current/noise-occupancy history plot</a>";
	    }
	}
	foreach $f (@ldtfiles) {
	    print HTML ", <a href=$f>history log file</a>" ;
	}
    }

# Insert comments section
    if (-f "comments.txt") {
	print HTML "<H3><A NAME=COMMENTS>Comments</A></H3>\n";

	open(COMMENTS, "comments.txt");

	while (<COMMENTS>) {
	    print HTML "$_\n";
	}

	close COMMENTS;
    }

# Second Table - test results
    print HTML "<H3><A NAME=RESULTS>Test Results</A></H3>\n" ;
    print HTML "<table border=1 width=100%>\n" ;
    print HTML "<tr>\n" ;
    print HTML "<th>Test</th>\n" ;
    print HTML "<th>Date/Time</th>\n" ;
    print HTML "<th align=center>Status</th>\n" ;
    print HTML "<th>Comments</th>\n<th align=center>Raw data</th>\n";
    print HTML "<th align=center>Plots</th>\n" ;
    print HTML "</tr>\n" ;

# Now can simply loop over tests...

    $n_iv=0 ;
    $n_rc=0 ;
    $n_no=0 ;
    $n_tw=0 ;
    $n_tr=0 ;
    for($t=0;$t<$NumTests+1;$t++) {
	$tt=$TestType[$t] ;
	next if $tt eq "Trim" ; 
	print HTML "<tr>" ;
	if ($tt ne "") {
	    print HTML "<td>$tt</td>" ;
	}
	else {
	    print HTML "<td>Non-standard test</td>" ;
	}	
	my $dateform=substr($DateStamp[$t],0,4) . "/" . substr($DateStamp[$t],4,2) . "/" . substr($DateStamp[$t],6,2)  ;
	my $timeform=substr($TimeStamp[$t],0,2) . ":" . substr($TimeStamp[$t],2,2) ;
	print HTML "<td align=center>$dateform $timeform</td>\n" ;
	print HTML "<td align=center>" . ( $Pass[$t] eq "YES" ? "PASS" : "<font color=red><b>FAIL</b></font>" ) . "</td>" ;
	$dbcommstr="" ;
	if ($DBComments[$t] ne "") {
	    $dbcommstr="<br>SCT DB comments:" ;
	    my $c ;
	    @DBC=split('\n',$DBComments[$t]) ;
	    foreach $c (@DBC) {
		$dbcommstr.="<br><tt>$c</tt>" ;
	    }
	}
# Here need test-specific printout - which should use $TestData
	if ( $tt eq "ModIVScan" || $tt eq "DetModIV" ) {
	    &GetIVData($TestData[$t]) ;
	    print HTML "<td>T = $Temperature C<br>\n" ;
	    print HTML "Leakage $i150 microA at 150V<br>\n" ;
	    print HTML "Leakage $i350 microA at 350V<br>\n" ;
	    print HTML "Leakage $i500 microA at 500V<br>\n" if $i500 ;
	    print HTML &DefectString($NumDefects[$t],$FirstDefect[$t],$LastDefect[$t]) . $dbcommstr . "</td>\n" ;
	    $RawFile=(split('\n',$RawData[$t]))[0] ;
	    @Raw=split(/\\/,$RawFile) ;
	    $RawFile=$Raw[$#Raw] ;
	    print HTML "<td align=center><a href=$RawFile>IV Data</a></td>\n" ;
	    if ($URL[$t] ne "") {
		$URL1=(split('\n',$URL[$t]))[0] ;
		$plot=&StripWebKey($URL1) ;
	    }
	    else {
		@IVPlots=grep {/IVCurve/} @psfiles ;
		$plot=@IVPlots[$n_iv];
	    }
	    $plot=&GZipIt(".",$plot) ;
	    if ( $plot ne "" ) {
		print HTML "<td align=center><a href=$plot>Plots</a></td>\n" ;
	    }
	    else {
		print HTML "<td align=center>&nbsp;</td>\n" ;
	    }
	    $n_iv++;
	}
	elsif ( $tt eq "HardReset" || $tt eq "FullBypassTest" || $tt eq "RedundancyTest" || 
	     $tt eq "PipelineTest" ) {
	    print HTML "<td>" . &DefectString($NumDefects[$t],$FirstDefect[$t],$LastDefect[$t]) . $dbcommstr . "</td>\n" ;
	    print HTML "<td align=center>&nbsp;</td>\n" ;
	    print HTML "<td align=center>&nbsp;</td>\n" ;
	}
	elsif ( $tt eq "LongTermTest" ) {
	    print HTML "<td>" . &DefectString($NumDefects[$t],$FirstDefect[$t],$LastDefect[$t]) . $dbcommstr . "</td>\n" ;
	    if ($RawData[$t]) {
		$RawFile=(split('\n',$RawData[$t]))[0] ;
		@Raw=split(/\\/,$RawFile) ;
		$RawFile=$Raw[$#Raw] ;
		print HTML "<td align=center><a href=$RawFile>History data</a></td>\n" ;
	    }
	    else {
		print HTML "<td align=center>&nbsp;</td>\n" ;
	    }
	    $plot="" ;
	    if ($URL[$t] ne "") {
		$URL1=(split('\n',$URL[$t]))[0] ;
		$plot=&StripWebKey($URL1) ;
	    }
	    if ( $plot ne "" ) {
		$plot=&GZipIt(".",$plot) ;
		print HTML "<td align=center><a href=$plot>Plots</a></td>\n" ;
	    }
	    else {
		print HTML "<td align=center>&nbsp;</td>\n" ;
	    }
	}
	elsif ( $tt eq "StrobeDelay" ) {
	    &GetStrobeDelaySettings($TestData[$t]) ;
	    print HTML "<td>Strobe Delay between $mindelay and $maxdelay<br>\n" ;
	    print HTML &DefectString($NumDefects[$t],$FirstDefect[$t],$LastDefect[$t]) . $dbcommstr . "</td>\n" ;
	    print HTML "<td align=center>&nbsp;</td>\n" ;
	    print HTML "<td align=center>&nbsp;</td>\n" ;
	}
	elsif ( $tt eq "ThreePointGain" || $tt eq "ResponseCurve") {
	    &GetGainRange($TestData[$t]) ;
	    print HTML "<td>Gain between $mingain and $maxgain mV/fC<br>Noise between $minnse and $maxnse ENC<br>\n" ;
	    print HTML &DefectString($NumDefects[$t],$FirstDefect[$t],$LastDefect[$t]) . $dbcommstr . "</td>\n" ;
	    $RawFile=(split('\n',$RawData[$t]))[0] ;
	    @Raw=split(/\\/,$RawFile) ;
	    $RawFile=$Raw[$#Raw] ;
	    print HTML "<td align=center><a href=$RawFile>Gain/Offset/Noise</a></td>\n" ;
	    if ($URL[$t] ne "") {
		$URL1=(split('\n',$URL[$t]))[0] ;
		$plot=&StripWebKey($URL1) ;
	    }
	    else {
		@RCPlots=grep {/RCPlot/} @psfiles ;
		$plot=@RCPlots[$n_rc];
	    }
	    $plot=&GZipIt(".",$plot) ;
	    if ( $plot ne "" ) {
		print HTML "<td align=center><a href=$plot>Plots</a></td>\n" ;
	    }
	    else {
		print HTML "<td align=center>&nbsp;</td>\n" ;
	    }
	    $n_rc++;
	}
	elsif ($tt eq "TrimRangeScan") {
	    print HTML "<td>\n" ;
	    print HTML &DefectString($NumDefects[$t],$FirstDefect[$t],$LastDefect[$t])  . " on range -1\n" . $dbcommstr ;
# $itr is trim range for 0,1,2,3 and is 4 for range -1
# $trimt is the test number for trim range $itr
	    $TrimData="<td align=left>" ;
	    for ($itr=0;$itr<5;$itr++) {
		$trimt=$t-4+$itr ;
		$tr=$itr ;
		$tr=-1 if $itr==4 ;
		$RawFile=(split('\n',$RawData[$trimt]))[0] ;
		@Raw=split(/\\/,$RawFile) ;
		$TrimFile[$itr]=$Raw[$#Raw] ;
		$MaskFile[$itr]=$TrimFile[$itr] ;
		$MaskFile[$itr]=~s/\.trim/\.mask/g;
		if (-s "$MaskFile[$itr]" ) {
		    $NumUntrims[$itr]=&NumberOfLinesInFile("$MaskFile[$itr]") ;
		}
		else {
		    $NumUntrims[$itr]=0 ;
		}
#		print " $tr $TrimFile[$itr] $MaskFile[$itr] $NumUntrims[$itr]\n" ; 
		if ($NumUntrims[$tr]>0) {
		    print HTML "<br>$NumUntrims[$itr] channels masked on range $tr:" ;
		    open(MASKF,"$MaskFile[$itr]") ;
		    while(<MASKF>) {
#			    print ;
			my $chan=(split(' ',$_))[0] ;
			print HTML " $chan" ;
		    }
		    close MASKF ;
		}
		$TrimData.="Range $tr: <a href=$TrimFile[$itr]>trim</a>;" ;
		if ($NumUntrims[$itr]) {
		    $TrimData.=" <a href=$MaskFile[$itr]>mask</a>" ;
		}
		else {
		    $TrimData.=" mask (empty)" ;
		}
		$TrimData.="<br>" if $itr<4 ;
	    }
	    print HTML "</td>\n" ;
	    print HTML "$TrimData</td>" ;
	    if ($URL[$t]) {
		$URL1=(split('\n',$URL[$t]))[0] ;
		$plot=&StripWebKey($URL1) ;
	    }
	    else {
		@TRPlots=grep {/TrimRangePlot/} @psfiles ;	
		$plot=@TRPlots[$n_tr] ;
	    }
	    $plot=&GZipIt(".",$plot) ;
	    print HTML "<td align=center><A href=$plot>Plots</a></td>\n" ;
	    print HTML "</tr>\n" ;
	    $n_tr++ ;
	}
	elsif ($tt eq "NO") {
	    &GetNoiseRange($TestData[$t]) ;
	    print HTML "<td>Noise Occupancy at 1fC between $minno and $maxno<br>\n" ;
	    print HTML "Estimated ENC between $minenc and $maxenc<br>\n" ;
	    print HTML &DefectString($NumDefects[$t],$FirstDefect[$t],$LastDefect[$t]) . $dbcommstr . "</td>\n" ;
	    print HTML "<td align=center>&nbsp;</td>\n" ;
	    print HTML "<td align=center>" ;
	    ($URL1,$URL2)=split('\n',$URL[$t]) ;
	    $plot2="" ;
	    if ($URL1 ne "") {
		$plot=&StripWebKey($URL1) ;
	    }
	    else {
		@NOPlots=grep {/NoPlot/} @psfiles ;	
		$plot=@NOPlots[$n_no];
	    }
	    $plot=&GZipIt(".",$plot) ;
	    if ($URL2) {
		$plot_temp=$plot;
		$plot=&StripWebKey($URL2);
		$plot=&GZipIt(".",$plot) ;
		$plot2=$plot;
		$plot=$plot_temp;
	    }
	    if( $plot2 ne "" ) {
		print HTML "<a href=$plot>Plots</a>; \n" ;
		print HTML "<a href=$plot2>SCurves</a></td>\n" ;
	    } else {
		@AllScanPlots=grep {/stscrun/} @psfiles ;
		$NumSP=-1 ;
		foreach $sp (@AllScanPlots) {
		    $sp=&GZipIt(".",$sp) ;
		    ($d1r,$s,$moi,$loi)=split(/_/,(split('\.',$sp))[0]) ;
		    $sptail=substr($sp,7) ;
		    $r=substr($d1r,7) ;
		    if ($s eq "all") {
			($d1,$d2,$r,$s,$moi,$loi)=split(/_/,(split('\.',$sp))[0]) ;
		    }
		    if ($r==$RunNum[$t] && $s==$ScanNum[$t]) {
			$NumSP++ ;
			$SPdata[$NumSP]="<a href=$sp>SCurves link $loi</a>" ;
		    }
		} 
		if ( $plot ne "" ) {
		    print HTML "<a href=$plot>Plots</a>" ;
		}
		for ($i=0;$i<$NumSP+1;$i++) {
		    print HTML "; $SPdata[$i]\n" ;
		}
	    }
	    print HTML "</td>\n" ;
	    $n_no++;
	}
	elsif ( $tt eq "Timewalk" ) {
	    &GetTimewalkRange($TestData[$t]) ;
	    print HTML "<td>Timewalk between $mintwalk and $maxtwalk nS<br>\n" ;
	    print HTML &DefectString($NumDefects[$t],$FirstDefect[$t],$LastDefect[$t]) . $dbcommstr . "</td>\n" ;	
	    print HTML "<td align=center>&nbsp;</td>\n" ;
	    if ($URL[$t] ne "") {
		$URL1=(split('\n',$URL[$t]))[0] ;
		$plot=&StripWebKey($URL1) ;
	    }
	    else {
		@TWPlots=grep {/TimewalkPlot/} @psfiles ;
		$plot=@TWPlots[$n_tw];
	    }
	    $plot=&GZipIt(".",$plot) ;
	    if ( $plot ne "" ) {
		print HTML "<td align=center><a href=$plot>Plots</a></td>\n" ;
	    }
	    else {
		print HTML "<td align=center>&nbsp;</td>\n" ;
	    }
	    $n_tw++;
	}
    }
# end
    print HTML "</table>\n" ;
    print HTML "<P>\n" ;

}

sub PrintXMLAndLogFiles {
    if ($#xmlfiles>-1) {
	print HTML "<P>\n" ;
	print HTML "<h3><a name=XMLS>XML config files</A></h3>\n" ;
	foreach $xmlf (@xmlfiles) {
	    print HTML "<a href=$xmlf>Config file</A><br>\n" ;
	}
    }
    print HTML "<P>\n" ;
    print HTML "<h3><a name=LOGS>Test log output files</A></h3>\n" ;
    foreach $logf (@maintxt) {
	my $date=(split(/\./,(split(/_/,$logf))[1]))[0] ;
	print HTML "<a href=$logf>Results file $date</A><br>\n" ;
    }
}

sub PrintDefectTables {
    print HTML "<H3><A NAME=DEFECTS>Defective channels</A></H3>\n" ;

    &GetDefectRuns ;

    $totaldefch=$NumberDefectiveChannels+$NumberTrimDefectOnlyChannels ;
    $trimtoo=$NumberTrimDefectChannels - $NumberTrimDefectOnlyChannels ;
    $nivd=$#IVDefect+1 ;
    print HTML "<TABLE BORDER=1>\n" ;
    if ($AnyIVTest) {
	print HTML "<TR><TD ALIGN=LEFT>Number of IV defects</TD><TD ALIGN=RIGHT WIDTH=30>$nivd</TD></TR>\n" ;
    }
    print HTML "<TR><TD ALIGN=LEFT>Channels with any defect(s)</TD><TD ALIGN=RIGHT WIDTH=30>$totaldefch</TD></TR>\n" ;
    print HTML "<TR><TD ALIGN=LEFT>Channels with non-trim defect(s)</TD><TD ALIGN=RIGHT WIDTH=30>$NumberDefectiveChannels</TD></TR>\n" ;
    print HTML "<TR><TD ALIGN=LEFT>Channels with trim defect(s)</TD><TD ALIGN=RIGHT WIDTH=30>$NumberTrimDefectChannels</TD></TR>\n" ;
    print HTML "<TR><TD ALIGN=LEFT>Channels with non-trim and trim defect(s)</TD><TD ALIGN=RIGHT WIDTH=30>$trimtoo</TD></TR>\n" ;
    print HTML "<TR><TD ALIGN=LEFT>Max consecutive bad channels (non-trim defects only)</TD><TD ALIGN=RIGHT WIDTH=30>$MaxRunNoT</TD></TR>\n" ;
    print HTML "<TR><TD ALIGN=LEFT>Max consecutive bad channels (any defect)</TD><TD ALIGN=RIGHT WIDTH=30>$MaxRunAny</TD></TR>\n" ;
    print HTML "</TABLE>" ;

    if ($AnyIVTest) {
	print HTML "<H4>IV Test defects</H4>\n" ;    
	if ($nivd>0) {
	    print "No IV test defects\n" ;
	}
	else {
	    for ($ivd=0;$ivd<$nivd;$ivd++) {
		print "<PRE>$IVDefect[$ivd]</PRE><BR>\n" ;
	    }
	}
    }

    print HTML "<H4>Non-trim defects</H4>\n" ;    

    if ($NumberDefectiveChannels<1) {
	print HTML "No defective channels\n" ;
    }
    else {
	print HTML "<table border=1>\n" ;
	print HTML "<tr><th>Channel(s)</th><th>Defects</th></tr>\n" ;
	for($ic=0;$ic<1536;$ic++) {
	    if ($ChannelDefects[$ic]) {
		print HTML "<tr><td>$ic</td><td>" ;
		@All=split('\n',$ChannelDefects[$ic]) ;
		@Types=split('\n',$ChannelDefectTests[$ic]) ;
		for($d=0;$d<$#All+1;$d++) {
		    print HTML "$All[$d]/$Types[$d] " ;		
		}
		print HTML "</td></tr>\n" ;
	    }
	}
	print HTML "</table>\n" ;
    }

    print HTML "<P>" ;

    print HTML "<H4><A NAME=TRIMDEFECTS>Trim defects</A></H4>\n" ;

    if ($NumberTrimDefectChannels<1) {
	print HTML "No channels have trim defects\n" ;
    }
    else {
	print HTML "<p>\n" ;	
	print HTML "<table border=1>\n" ;
	print HTML "<tr><th>Channel(s)</th><th>Trim defects</th></tr>\n" ;
	for($ic=0;$ic<1536;$ic++) {
	    if ($ChannelTrimDefects[$ic]) {
		print HTML "<tr><td>$ic" ;
		print HTML "<sup>*</sup>" if $ChannelDefects[$ic] ;
		print HTML "</td><td>" ;
	    @All=split('\n',$ChannelTrimDefects[$ic]) ;
		for($d=0;$d<$#All+1;$d++) {
		    print HTML "$All[$d] " ;		
		}
		print HTML "</td></tr>\n" ;
	    }
	}
	print HTML "</table>\n" ;
    }
}

sub GetDefectRuns {
    $MaxRunNoT=-1 ;
    $MaxRunAny=-1 ;
    $firstbadnot=-1 ;
    $firstbadany=-1 ;
    for($ic=0;$ic<769;$ic++) {
	if ($ic<768 && $ChannelDefects[$ic]) {
	    $firstbadnot=$ic if $firstbadnot<0 ;
	}
	elsif ($firstbadnot>-1) {
	    $runlength=$ic-$firstbadnot ;
	    if ($runlength>$MaxRunNoT) {
		$FirstInMaxRunNoT=$firstbadnot ;
		$MaxRunNoT=$runlength ;
	    }
	    $firstbadnot=-1 ;
	}
	if ($ic<768&&($ChannelDefects[$ic]||$ChannelTrimDefects[$ic])) {
	    $firstbadany=$ic if $firstbadany<0 ;
	}
	elsif ($firstbadany>-1) {
	    $runlength=$ic-$firstbadany ;
	    if ($runlength>$MaxRunAny) {
		$FirstInMaxRunAny=$firstbadany ;
		$MaxRunAny=$runlength ;
	    }
	    $firstbadany=-1 ;
	}
    }
    $firstbadnot=-1 ;
    $firstbadany=-1 ;
    for($ic=768;$ic<1537;$ic++) {
	if ($ic<1536 && $ChannelDefects[$ic]) {
	    $firstbadnot=$ic if $firstbadnot<0 ;
	}
	elsif ($firstbadnot>-1) {
	    $runlength=$ic-$firstbadnot ;
	    if ($runlength>$MaxRunNoT) {
		$FirstInMaxRunNoT=$firstbadnot ;
		$MaxRunNoT=$runlength ;
	    }
	    $firstbadnot=-1 ;
	}
	if ($ic<1536&&($ChannelDefects[$ic]||$ChannelTrimDefects[$ic])) {
	    $firstbadany=$ic if $firstbadany<0 ;
	}
	elsif ($firstbadany>-1) {
	    $runlength=$ic-$firstbadany ;
	    if ($runlength>$MaxRunAny) {
		$FirstInMaxRunAny=$firstbadany ;
		$MaxRunAny=$runlength ;
	    }
	    $firstbadany=-1 ;
	}
    }
    $MaxRunNoT=0 if $MaxRunNoT<0 ;
    $MaxRunAny=0 if $MaxRunAny<0 ;
}

sub AnalyseDefects {

    for($ic=0;$ic<1536;$ic++) {
	$ChannelDefects[$ic]="" ;
	$ChannelTrimDefects[$ic]="" ;
    }

    for ($d=0;$d<$#Defect+1;$d++) {
	($type,$range)=split(' ',$Defect[$d]) ;
	($first,$last)=split('-',$range) ;
	$trimdef=&IsATrimDefect($type) ;
	for ($ic=$first;$ic<$last+1;$ic++) {
	    if (!$trimdef) {
		$ChannelDefects[$ic].="$type\n" ;
		$ChannelDefectTests[$ic].="$TestType[$DefectInTest[$d]]\n" ;
	    }
	    else {
		$ChannelTrimDefects[$ic].="$type\n" ;
	    }
	}
    }

    $NumberDefectiveChannels=0 ;
    $NumberTrimDefectChannels=0 ;
    $NumberTrimDefectOnlyChannels=0 ;
    for($ic=0;$ic<1536;$ic++) {
	$NumberDefectiveChannels++ if $ChannelDefects[$ic] ;
	$NumberTrimDefectChannels++ if $ChannelTrimDefects[$ic] ;
	$NumberTrimDefectOnlyChannels++ if $ChannelTrimDefects[$ic] && !$ChannelDefects[$ic] ;
    }

}

sub IsATrimDefect {
    my $defect=$_[0] ;
    my $stem,$range ;
    ($stem,$range)=split(/\(/,$defect) ;
    $range=(split(/\)/,$range))[0] ;
    return ($stem eq "TR_RANGE" || $stem eq "TR_STEP" || $stem eq "TR_OFFSET" || $stem eq "TR_NOTRIM" && $range>-1) ;
}

sub GetIVData {
    my @data=split('\n',$_[0]) ;
    my $i=-1 ;
    $i150=$i350=$i500=0 ;
    foreach $d (@data) {
	$i++ ;
	$i150=(split(/:/,$d))[1] if $d=~/^I LEAK 150     :/ ;
	$i350=(split(/:/,$d))[1] if $d=~/^I LEAK 350     :/ ;
	$i500=(split(/:/,$d))[1] if $d=~/I LEAK 500     :/ ;
	$Temperature=substr($d,index($d,':')+2) if $d=~/^TEMPERATURE    :/ ;
    }
}

sub GetIVMaxV {
    my $module=$_[0] ;
    my $seq=$_[1] ;
    my $RawFile=(split('\n',$_[2]))[0] ;
    $RawFile=substr($RawFile,rindex($RawFile,'\\')+1) ;
#    print "$archive/$module/$seq/$RawFile\n" ;
    open(IVRAWFILE,"$archive/$module/$seq/$RawFile") ;
    my $intable=0 ;
    my $v ;
    my $ivmaxv=-1 ;
    while (<IVRAWFILE>) {
	&MyChomp ;
	$intable=1 if /^#V/ ;
	next if /^#/ ;
	if ($intable) {
	    $v=(split(' ',$_))[0] ;
	    $ivmaxv=$v if $v>$ivmaxv ;
	}
    }
    close(IVRAWFILE) ;
#    print "..$RawFile .\n" ;
    return $ivmaxv ;
}

sub GetStrobeDelaySettings {
    my @data=split('\n',$_[0]) ;
    my $i=-1 ;
    my $ii ;
    my @Delays ;
    foreach $d (@data) {
	$i++ ;
	next if $d ne "#DELAY" ;
	$S1=$data[$i+2] ;
	$S2=$data[$i+5] ;
	@Delays=split(' ',"$S1 $S2") ;
	$maxdelay=-9999. ;
	$mindelay=9999. ;
	for ($ii=0;$ii<$#Delays;$ii++) {
	    $maxdelay=$Delays[$ii] if $Delays[$ii]>$maxdelay ; 
	    $mindelay=$Delays[$ii] if $Delays[$ii]<$mindelay ; 
	}
    }
}

sub GetGainRange {
    my @data=split('\n',$_[0]) ;
    my $i=-1 ;
    my $cid ;
    foreach $d (@data) {
	$i++ ;
	next if !($d=~/vt50/ && $d=~/innse/) ;
	$minnse=99999 ;
	$maxnse=0 ;
	$mingain=999999.9 ;
	$maxgain=0.0 ;
	for ($cid=0;$cid<12;$cid++) {
	    $innse=(split(' ',$data[$i+2*($cid+1)]))[7] ;
	    $maxnse=$innse if $innse>$maxnse ;
	    $minnse=$innse if $innse<$minnse ;
	    $gain=(split(' ',$data[$i+2*($cid+1)]))[2] ;
	    $maxgain=$gain if $gain>$maxgain ;
	    $mingain=$gain if $gain<$mingain ;
	}
    }
}

sub GetNoiseRange {
    my @data=split('\n',$_[0]) ;
    my $i=-1 ;
    my $cid ;
    foreach $d (@data) {
	$i++ ;
	next if !($d=~/MeanOcc/ && $d=~/EstENC/) ;
	$minno= 99999 ;
	$maxno=-99999 ;
	$minenc= 99999 ;
	$maxenc=-99999 ;
	for ($cid=0;$cid<12;$cid++) {
	    $enc=(split(' ',$data[$i+2*($cid+1)]))[3] ;
	    $maxenc=$enc if $enc>$maxenc ;
	    $minenc=$enc if $enc<$minenc ;
	    $no=(split(' ',$data[$i+2*($cid+1)]))[1] ;
	    $maxno=$no if $no>$maxno ;
	    $minno=$no if $no<$minno ;
	}
    }
}

sub GetTimewalkRange {
    my @data=split('\n',$_[0]) ;
    my $i=-1 ;
    my $S1,$S2,$ii ;
    foreach $d (@data) {
	$i++ ;
	next if $d ne "#TW" ;
	$mintwalk=99999 ;
	$maxtwalk=0 ;
	$S1=@data[$i+2] ;
	$S2=@data[$i+5] ;
	@Twalks=split(' ',"$S1 $S2") ;
	for ($ii=0;$ii<$#Twalks;$ii++) {
	    $maxtwalk=$Twalks[$ii] if $Twalks[$ii]>$maxtwalk ; 
	    $mintwalk=$Twalks[$ii] if $Twalks[$ii]<$mintwalk ; 
	}
    }
}

sub WriteIndexHTMLTrailer {
    print HTML "</body>\n</html>\n" ;
}

sub FindResultFiles {
    my $DUT=$_[0] ;
    my $dir=$_[1] ;
    opendir(DUTP_H,$dir) ;
    @ivfiles=grep{!/^\./ && /$DUT/ && /\iv$*/ } readdir(DUTP_H) ;
    rewinddir(DUTP_H) ;
    @rcfiles=grep{!/^\./ && /$DUT/ && /\RC$*/ } readdir(DUTP_H) ;
    rewinddir(DUTP_H) ;
    @ldtfiles=grep{/^$DUT\_LDT[0-9_]+\.txt$/ } readdir(DUTP_H) ;
    rewinddir(DUTP_H) ;
    @maintxt=grep{ /^$DUT[0-9_]+\.txt$/ } sort readdir(DUTP_H) ;
    rewinddir(DUTP_H) ;
    @maskfiles=grep{!/^\./ && /$DUT/ && /\.mask$/ } readdir(DUTP_H) ;
    rewinddir(DUTP_H) ;
    @trimfiles=grep{!/^\./ && /$DUT/ && /\.trim$/ } readdir(DUTP_H) ;
    rewinddir(DUTP_H) ;
    @xmlfiles=grep{!/^\./ && /$DUT/ && /\.xml$/ } readdir(DUTP_H) ;
    &SortXMLFiles ;
    closedir(DUTP_H) ;
    $LTT=0 ;
    $LTT=1 if $#ldtfiles>-1 ;
}

sub FindPSFiles {
    my $DUT=$_[0] ;
    my $dir=$_[1] ;
    opendir(DUTP_H,$dir) ;
    @psfiles=grep{!/^\./ && ( /\.ps$/ || /\.ps.gz$/)  } sort readdir(DUTP_H) ;
    closedir(DUTP_H) ;
}

sub GetLogFiles {
    my ($dir,$DUT,@logs) ;
    $DUT=$_[0] ;
    $dir=$_[1] ;
    opendir(LOG_D,"$dir") ;
    @logs=grep{/^$DUT[0-9_]+\.txt$/} sort readdir(LOG_D) ;
    closedir(LOG_D) ;
    return @logs ;
}

sub GetXMLFiles {
    my ($dir,$DUT,@xmls) ;
    $DUT=$_[0] ;
    $dir=$_[1] ;
    opendir(LOG_D,"$dir") ;
    @xmls=grep{/^$DUT[0-9_]+\.xml$/} sort readdir(LOG_D) ;
    closedir(LOG_D) ;
    return @xmls ;
}

sub NumberOfLinesInFile {
    open(DUMFILE,$_[0]) ;
    my $n=0 ;
    while(<DUMFILE>) {
	$n++ ;
    }
    close(DUMFILE) ;
    return $n ;
}

sub MyChomp {
    my $input=$_ ;
    chomp $input ;
    chop $input if substr($input,-1) eq "\r" ;
    $_=$input ;
    return ;
}

sub GetDCSInfo {
# Requires @maintxt
# Sets @DCSMax,@DCSMin,$MeanDT,$AnyT0,$AnyT1
    my $i ;
    my $SumDT, $NumDT ;
    for($i=0;$i<8;$i++) {
	$DCSMax[$i]=-9999.9 ;
    	$DCSMin[$i]=9999.9 ;
    }
    $SumT=0 ;
    $SumDT=0 ;
    $NumDT=0 ;
    $AnyT0=0 ;
    $AnyT1=0 ;
    foreach $logf (@maintxt) {
	&GetDCSInfoFromFile("$logf") ;	
	for($i=0;$i<8;$i++) {
	    $DCSMax[$i]=$DCSMaxInFile[$i] if $DCSMaxInFile[$i]>$DCSMax[$i] ;
	    $DCSMin[$i]=$DCSMinInFile[$i] if $DCSMinInFile[$i]<$DCSMin[$i] ;
	}
	$SumT+=$SumTInFile ;
	$SumDT+=$SumDTInFile ;
	$NumDT+=$NumDTInFile ;
    }
    $MeanDT=$SumDT/$NumDT ;
}

sub GetDCSInfoFromFile {
    my $logf=$_[0] ;
    my @x,$i ;
    for($i=0;$i<8;$i++) {
	$DCSMaxInFile[$i]=-9999.9 ;
    	$DCSMinInFile[$i]=9999.9 ;
    }
    $SumTInFile=0 ;
    $SumDTInFile=0 ;
    $NumDTInFile=0 ;
    open(LOGF,"$logf") ;
    while (<LOGF>) {
	if (/^%DCS_INFO/) {
	    $#DCS=-1 ;
	    $_=<LOGF> ;
	    $_=<LOGF> ;
	    $_=<LOGF> ;
	    @x=split(' ',$_) ;
	    push @DCS,@x ;
	    $_=<LOGF> ;
	    $_=<LOGF> ;
	    @x=split(' ',$_) ;
	    push @DCS,@x ;
	    $_=<LOGF> ;
	    $_=<LOGF> ;
	    @x=split(' ',$_) ;
	    push @DCS,@x ;
	    $_=<LOGF> ;
	    $_=<LOGF> ;
	    @x=split(' ',$_) ;
	    push @DCS,@x ;
	    for($i=0;$i<8;$i++) {
		$DCSMaxInFile[$i]=$DCS[$i] if $DCS[$i]>$DCSMaxInFile[$i] ;
		$DCSMinInFile[$i]=$DCS[$i] if $DCS[$i]<$DCSMinInFile[$i] ;
	    }
	    $AnyT0=1 if $DCS[0]>-128 ;
	    $AnyT1=1 if $DCS[1]>-128 ;
	    $SumTInFile+=0.5*($DCS[0]+$DCS[1]) ;
	    $SumDTInFile+=($DCS[0]-$DCS[1]) ;
	    $TestDCS[$NumDTInFile]=join(' ',@DCS) ;
	    $NumDTInFile++ ;
	}
    }
    close (LOGF) ;
#    for($i=0;$i<8;$i++) {
#	print "DCS parameter $i Max: $DCSMaxInFile[$i] Min: $DCSMinInFile[$i]\n" ;
#    }
#    print "Mean delta-T:" . $SumDTInFile/$NumDTInFile . "\n" ;
}

sub PrintDCSTable {

    print HTML "<H3><a name=DCS>DCS Summary</A></H3>\n" ;
    print HTML "<table border=1>\n" ;

    print HTML "<tr>\n" ;
    print HTML "<th width=80>Parameter</th>\n" ;
    print HTML "<th width=80>Minimum</th>\n";
    print HTML "<th width=80>Maximum</th>\n" ;
    print HTML "<th width=80>Final</th>\n" ;
    print HTML "<th width=80>Unit</th>\n" ;
    print HTML "</tr>\n" ;

    my $i ;
    for($i=0;$i<8;$i++) {
	print HTML "<tr>\n" ;
	print HTML "<th>$DCSVariables[$i]</th>\n" ;
	print HTML "<td align=center>$DCSMin[$i]</td>\n" ;
	print HTML "<td align=center>$DCSMax[$i]</td>\n" ;
	print HTML "<td align=center>$DCS[$i] </td>\n" ;
	print HTML "<th>$DCSUnits[$i]</th>\n" ;
	print HTML "</tr>\n" ;
    }
    print HTML "</table>\n" ;

    print HTML "<P>\n" ;
    if ($AnyT0 && $AnyT1) {
	printf HTML "Mean difference between thermistor temperatures %1.2f deg. C", $MeanDT ;
    }

    print HTML "<P>\n" ;
}

sub GetAllTestsInfo {
# Requires @maintxt
    my $logf ;
    my $dstr,$df ;
    $NumTests=-1 ;
    $#Defect=-1 ;
    $#IVDefect=-1 ;
    $File=-1 ;
    $MinimumVersion=99999.9 ;
    $MaximumVersion=-1 ;
    $AnyIVTest=0 ;
    foreach $logf (@maintxt) {
	$File++ ;
	$Line=-1 ;
#	print "Analysing results file $logf\n" ;
	open(LOGF,"$logf") ;
      LOGFLOOP: 
	while (<LOGF>) {
	    $Line++ ;
	    &MyChomp ;
	    if (/^%NewTest/) {
		$NumTests++ ;
		# New test starts - clear everything
		# Note we can assume we always get this line before a test
		$SerialNum[$NumTests]=-1 ;
		$Initials[$NumTests]='' ;
		$Location[$NumTests]='Unknown' ;
		$RunNum[$NumTests]=-1 ;
		$ScanNum[$NumTests]=-1 ;
		$DateStamp[$NumTests]=-1 ;
		$Pass[$NumTests]='Unknown' ;
		$Problem[$NumTests]='Unknown' ;
		$Host[$NumTests]='' ;
		$Version[$NumTests]='' ;
		$DUTType[$NumTests]='' ;
		$TimeStamp[$NumTests]=-1 ;
		$TestType[$NumTests]='' ;
		$NumDefects[$NumTests]=0 ;
		$FirstDefect[$NumTests]=-1 ;
		$LastDefect[$NumTests]=-1 ;
		$TrimRange[$NumTests]=-2 ;
		$DBComments[$NumTests]="" ;
		$URL[$NumTests]="" ;
		$RawData[$NumTests]="" ;
		$FirstLine[$NumTests]=$Line ;
		$LastLine[$NumTests-1]=$Line-1 if $NumTests>0;
	    }
	    $known=0 ;
	    foreach $t (@KnownTests) {
		$known=1 if /^%$t/ ; 
	    }
	    if ($known) {
		$TestType[$NumTests]=join(" ",split(' ',substr($_,1))) ;
		$testoutputdata=1 ;
		$TestData="$_\n" ;
		$AnyIVTest=1 if $TestType[$NumTests] eq "DetModIV" || $TestType[$NumTests] eq "ModIVScan" ;
		next LOGFLOOP ;
	    }
	    if (/^SERIAL NUMBER  :/) {
		$SerialNum[$NumTests]=(split(' ',$_))[3] ;
		next LOGFLOOP ;
	    }
	    if (/^TEST MADE BY   :/) {
		$Initials[$NumTests]=(split(' ',$_))[4] ;
		next LOGFLOOP ;
	    }
	    if (/^LOCATION NAME  :/) {
		$Location[$NumTests]=(split(' ',$_))[3] ;
		next LOGFLOOP ;
	    }
	    if (/^Run number     :/) {
		$RunNum[$NumTests]=(split(/-/,(split(' ',$_))[3]))[0] ;
		$ScanNum[$NumTests]=(split(/-/,$_))[1] ;
		next LOGFLOOP ;
	    }
	    if (/^TEST_DATE      :/) {
		$dstr=(split(/:/,$_))[1] ;
		$dstr=(split(' ',$dstr))[0] ;
		$df=(split(/\//,$dstr))[2] . (split(/\//,$dstr))[1] . (split(/\//,$dstr))[0] ;
		$DateStamp[$NumTests]=$df ;
		next LOGFLOOP ;
	    }
	    if (/^PASSED         :/) {
		$Pass[$NumTests]=(split(' ',$_))[2] ;
		next LOGFLOOP ;
	    }
	    if (/^PROBLEM        :/) {
		$Problem[$NumTests]=(split(' ',$_))[2] ;
		next LOGFLOOP ;
	    }
	    if (/^%DAQ_INFO/) {
		$_=<LOGF> ;
		$_=<LOGF> ;
		$_=<LOGF> ;
		&MyChomp ;
		$Host[$NumTests]=(split("\"",$_))[1] ;
		$_=<LOGF> ;
		$_=<LOGF> ;
		&MyChomp ;
		$Version[$NumTests]=(split("\"",$_))[1] ;
		$MaximumVersion=$Version[$NumTests] if $Version[$NumTests]>$MaximumVersion ;
		$MinimumVersion=$Version[$NumTests] if $Version[$NumTests]<$MinimumVersion ;
		$_=<LOGF> ;
		$_=<LOGF> ;
		&MyChomp ;
		$DUTType[$NumTests]=(split("\"",$_))[1] ;
		$_=<LOGF> ;
		$_=<LOGF> ;
		$tf=(split(/\:/,$_))[0] . (split(/\:/,$_))[1] . (split(/\:/,$_))[2] ;
		$tf6=substr($tf,1,6) ;
		if ($tf6=~/^[0-9]+$/) {
		    $TimeStamp[$NumTests]=$tf6 ;
		}
		$Line+=9 ;
		next LOGFLOOP ;
	    }
	    if (/^#No defects found!/) {
		$NumDefects[$NumTests]=0 ;
		$testoutputdata=0 ;
		next LOGFLOOP ;
	    }
	    if (/^%Defect/) {
		$testoutputdata=0 ;
		$NumDefects[$NumTests]++ ;
		$_=<LOGF> ;
		&MyChomp ;
		$DefectType=substr($_,17) ;
		if ($TestType[$NumTests]=~/^Trim/) {
		    $DefectType.="($TrimRange[$NumTests])" ;
		}
		$_=<LOGF> ;
		&MyChomp ;
		$DefectFirst=substr($_,17) ;
		$_=<LOGF> ;
		&MyChomp ;
		$DefectLast=substr($_,17) ;
		if ($TestType[$NumTests] eq "DetModIV" || $TestType[$NumTests] eq "ModIVScan") {
		    $DefectFirst=$DefectLast=9999 ;
		    push @IVDefect,"$DefectType" ;
		}
		push @Defect,"$DefectType $DefectFirst-$DefectLast" ;
		$DefectInTest[$#Defect]=$NumTests ;
		$FirstDefect[$NumTests]=$#Defect if $FirstDefect[$NumTests]<0 ;
		$LastDefect[$NumTests]=$#Defect ;
		$Line+=3 ;
		next LOGFLOOP ;
	    }
	    if (/^COMMENT        :/) {
		my $DBComm=substr($_,index($_,':')+2) ;
		$DBComments[$NumTests].="$DBComm\n" ;
		next LOGFLOOP ;
	    }
	    if (/^URL            :/) {
		$URL[$NumTests].=substr($_,index($_,':')+2) . "\n" ;
		next LOGFLOOP ;
	    }
	    if (/^FILENAME       :/) {
		$RawData[$NumTests].=substr($_,index($_,':')+2) . "\n" ;
		next LOGFLOOP ;
	    }
	    if ($testoutputdata) {
		$TestData[$NumTests].="$_\n" ;
	    }
	    if (/^#TRIM/) {
# Trim: this needs all sorts of special actions (yuk)!
		$_=<LOGF> ;
		$Line++ ;
		$TrimRange[$NumTests]=(split(' ',$_))[1] ;
# Note this kludge in particular!!!!!
		if ($TrimRange[$NumTests]==-1) {
		    $TestType[$NumTests]="TrimRangeScan" ;
		}
		next LOGFLOOP ;
	    }
	}
	close (LOGF) ;
    }
    $LastLine[$NumTests]=$Line ;
}

sub PrintAllTestsInfo {
    print "\n\nThere are $NumTests +1 tests...\n\n" ;
    for($i=0;$i<$NumTests+1;$i++) {
	printf "%3d ",$i ;
	printf "%-16s ",$TestType[$i] ;
	printf "%2d ",$TrimRange[$i] ;
	printf "%5d %4d ",$RunNum[$i],$ScanNum[$i] ;
	printf "%14s ",$SerialNum[$i] ;
	printf "%6d %6d ",$DateStamp[$i],$TimeStamp[$i] ;
	printf "%3s %3s ",$Pass[$i],$Problem[$i] ;
	printf "%-10s %4s ",$Location[$i],$Initials[$i] ;
	printf "%8s %6.2f %16s ",$Host[$i],$Version[$i],$DUTType[$i] ;
	printf "%4d %4d %4d ",$NumDefects[$i],$FirstDefect[$i],$LastDefect[$i] ;
	print "\n" ;
#	if ($DBComments[$i] ne "") {
#	    print $DBComments[$i] ;
#	}
#	print $TestData[$i] ;
    }

    print "\nand there are " . ($#Defect+1) . " defects...\n" ;
    for ($i=0;$i<$#Defect+1;$i++) {
	print "$i $Defect[$i] $DefectInTest[$i]\n" ; 
    }
}

sub SortXMLFiles {
    my @xmlrs ;
    my ($r,$s,$dum) ;
    my $i=0 ;
    my $x ;
    foreach $x (@xmlfiles) {
	($dum,$r,$s)=split('\_',$x) ;
	$s=substr($s,0,index('\.',$s)-1) ;
	$xmlrs[$i++]=$r*100000+$s ;
    }
    @xmlrs=sort @xmlrs ;
    $i=0 ;
    foreach $x (@xmlrs) {
	$s=$x%100000 ;
	$r=($x-$s)/100000 ;
	$xmlfiles[$i++]="$dum\_$r\_$s\.xml" ;
    }
}
