#!/usr/local/bin/perl

##########################################################################
#                                                                        #
#  This script was written by S.Nazin (http://xray.sai.msu.su/~leng/)    #
#  Sternberg Astronomical Institute, Moscow University.                  #
#                                                                        #
##########################################################################

use GD;

##########################################################################
#                                                                        #
#                     USER  DEFINED  VARIABLES                           #
#                                                                        #
##########################################################################

$titleFont    = gdLargeFont;
$textFont     = gdMediumBoldFont;
$smallFont    = gdSmallFont;
$tinyFont     = gdTinyFont;

$topmargin    = 3;
@geometry     = ( 640, 480 );
$graphLmargin = 70;
$graphRmargin = 125;
$graphTmargin = 23;
$graphBmargin = 50;
$XTics        = 8;
$YTics        = 10;
$TicLI        = 0;
$TicLO        = 5;
$maxSize      = 0;


##########################################################################
#                                                                        #
#            PRECALCULATED VARIABLES  (DON'T CHANGE THEM)                #
#                                                                        #
##########################################################################

$graphL   = $graphLmargin;
$graphR   = $geometry[0]-$graphRmargin;
$graphT   = $graphTmargin;
$graphB   = $geometry[1]-$graphBmargin;
$graphW   = $graphR - $graphL;
$graphH   = $graphB - $graphT;

%Monthes = ( 
  'Jan' => 0,
  'Feb' => 31,
  'Mar' => 59,
  'Apr' => 90,
  'May' => 120,
  'Jun' => 151,
  'Jul' => 181,
  'Aug' => 212,
  'Sep' => 243,
  'Oct' => 273,
  'Nov' => 304,
  'Dec' => 334,
);

%DoNotPlot = (
  'population' => 1,
  'iauc'       => 1,
);

##########################################################################
#                                                                        #
#                            M A I N                                     #
#                                                                        #
##########################################################################

$params = $ENV{'QUERY_STRING'};
$Iam    = $ENV{'SCRIPT_NAME'};

foreach (split( /&/, $params )){
   ($key,$val) = split( /=/, $_ );
   $params{$key} = $val;
}

unless( exists $params{'img'} ){
   print "Content-type: text/html\n\n";
   print qq'
<HTML><HEAD><TITLE>Disk usage by user</TITLE></HEAD>
<BODY bgcolor="#ffffd0">
<center>
<IMG USEMAP="#map" ISMAP SRC="$Iam?img=&$params" WIDTH="$geometry[0]" HEIGHT="$geometry[1]" BORDER=0>
<MAP NAME="map">';

   &GetDU();
   $imax = scalar( @TimeStamps ) - 1;
   foreach $user (sort {${$b}[$imax] <=> ${$a}[$imax]} keys %Users){
      next if( $DoNotPlot{$user} );
      &WriteMapElement( $user );
   }

   print qq'
<AREA SHAPE="default" NOHREF>
</MAP>
<hr noshade>
<a href="/~leng/diskusage/">Go to frame version</a>
</center>
</BODY></HTML>
';
   exit;
}

##########################################################################
#                                                                        #
#                          Image Creation                                #
#                                                                        #
##########################################################################

    $im = new GD::Image(@geometry);

    $white  = $im->colorAllocate(255, 255, 255);
    $yellow = $im->colorAllocate(255,255,208);
    $blue = $im->colorAllocate(0,0,208);
    $black  = $im->colorAllocate(0,0,0);

    @colors = ( 
        $im->colorAllocate(224,0,0),
        $im->colorAllocate(0,224,0),
        $im->colorAllocate(0,0,224),
        $im->colorAllocate(224,0,224),
        $im->colorAllocate(112,0,0),
        $im->colorAllocate(0,112,0),
        $im->colorAllocate(112,112,0),
        $im->colorAllocate(224,112,0),
        $im->colorAllocate(112,0,224),
        $im->colorAllocate(112,112,112),
    );

    $im->fill(1,1,$yellow);

    $str = &GetDU();
    $imax = scalar( @TimeStamps ) - 1;
    $RealMax  = &FindMax();

    $maxSize  = $params{'scale'}*1000;
    $maxSize  = $RealMax if( not $maxSize or $maxSize > $RealMax );
    $maxSize  = 10000 if( $maxSize < 10000 );
    $SizeStep = $maxSize/$YTics/1000;
    $TimeStep = ($TimeStamps[$imax]-$TimeStamps[1])/$XTics;

    $im->string($titleFont,$graphL+($graphW-45*$titleFont->width)/2,
                $topmargin,"Last updated at: $str",$black);

    $im->rectangle( $graphL, $graphT, $graphR, $graphB, $black );

    for( $i=0; $i<=$XTics; $i++ ){
       $im->line( $graphL+$i*$graphW/$XTics, $graphB-$TicLI,
                  $graphL+$i*$graphW/$XTics, $graphB+$TicLO, $black );
       $curTime = $TimeStamps[1]+$i*$TimeStep;
       $date = int( $curTime/24/3600 );
       $time = int(($curTime-24*3600*$date)/60);
       $h = int($time/60);
       $m = $time - 60*$h;
       $date = $date - 365*int($date/365);
       foreach (sort {$Monthes{$b} <=> $Monthes{$a}} keys %Monthes){
          $month = $_;
          last if( $date > $Monthes{$_} );
       }
       $date = $date - $Monthes{$month};

       $im->string($smallFont,
                   $graphL+$i*$graphW/$XTics-3*$smallFont->width,
                   $graphB+$TicLO+5,
                   "$date $month", $black);
       $im->string($tinyFont,
                   $graphL+$i*$graphW/$XTics-2.5*$tinyFont->width,
                   $graphB+$TicLO+5+$smallFont->height+2,
                   sprintf("%02d:%02d",$h,$m), $black);
    }
    for( $i=0; $i<=$YTics; $i++ ){
       $im->line( $graphL-$TicLO, $graphB-$i*$graphH/$YTics,
                  $graphL+$TicLI, $graphB-$i*$graphH/$YTics, $black );
       $im->dashedLine( $graphL, $graphB-$i*$graphH/$YTics,
                  $graphR, $graphB-$i*$graphH/$YTics, $black );

       $color = $black;
       $color = $blue if( $i*$SizeStep >= 10 );
       $im->string($textFont,$graphL-$TicLO-8*$textFont->width,
                             $graphB-$i*$graphH/$YTics-$textFont->height/2,
                             sprintf( "%4d Mb", $i*$SizeStep ), $color );
    }

    $im->string($textFont,$graphR+($graphRmargin-15*$textFont->width)/2,
                $graphT,"on off",$black);

    foreach $user (sort {${$b}[$imax] <=> ${$a}[$imax]} keys %Users){
       next if( $DoNotPlot{$user} );
       $color = shift @colors;
       push @colors, $color;
       &PlotLegend( $user, $color );
       &PlotUser( $user, $color ) unless($params{$user} eq 'off');
    }

    print  "Content-type: image/gif\nPragma: no-cache\n\n";
    print $im->gif;

########################################################################
sub GetDU{
  my( $date_str, $time );
  my $i = 0;

  open( FIN, "<diskusage" );
  while(<FIN>){
     next if( /^-/ );
     if( /^(\d+)\s+\/.1\/home\/(\w+)\s*$/ ){
        ${$2}[$i] = $1;
        $Users{$2} = 1;
     }elsif( /^\w{3}\s+(\w{3})\s+(\d+)\s+(\d+):(\d+):(\d+)\s+\S+\s+(\d+)\s*$/ ){
        $date_str = $_;
        $time = $5+60*($4+60*($3+24*($2+$Monthes{$1}+365*($6-1997))));
        $i++;
        $TimeStamps[$i] = $time;
     }else{
     }
  }
  close( FIN );
  return( $date_str );
}

########################################################################
sub FindMax {
   my $max = 0;
   my $user, $i;

   foreach $user (keys %Users){
      next if( $DoNotPlot{$user} or ($params{$user} eq 'off') );
      for( $i = 1; $i<=$imax; $i++ ){
         $max = ${$user}[$i] if( $max < ${$user}[$i] );
      }
   }
   $max  = (int($max/50000)+1)*50000;
   return $max;
}

########################################################################
sub PlotUser {
    my( $user, $color ) = @_;

    my $prevX = 0; 
    my $prevY = $graphH*${$user}[1]/$maxSize;
    $prevY    = $graphH-1 if( $prevY >= $graphH );

    for( $i = 2; $i<=$imax; $i++ ){
       $newX = $graphW*($i-1)/($imax-1);
       $newY = $graphH*${$user}[$i]/$maxSize;
       $newY = $graphH-1 if( $newY >= $graphH );
       $im->line( $graphL+$prevX, $graphB-$prevY, 
                  $graphL+$newX,  $graphB-$newY, $color );
       $prevX = $newX;
       $prevY = $newY;
    }
}

########################################################################
sub PlotLegend {
    my( $user, $color ) = @_;

    $userNo++;
    $im->string($textFont,$graphR+($graphRmargin-$textFont->width)/2,
                $graphT+($userNo)*$textFont->height,$user,$color);

    $crossL = $graphR+($graphRmargin-14*$textFont->width)/2;
    $crossR = $graphR+($graphRmargin-12*$textFont->width)/2;
    $crossT = $graphT+($userNo+1)*$textFont->height-$textFont->width-2;
    $crossB = $graphT+($userNo+1)*$textFont->height-2;

    $im->rectangle( $crossL, $crossT, $crossR, $crossB, $black );
    $im->line( $crossL, $crossT, $crossR, $crossB, $black ) unless( $params{$user} eq 'off' );
    $im->line( $crossL, $crossB, $crossR, $crossT, $black ) unless( $params{$user} eq 'off' );

    $crossL += 3.5*$textFont->width;
    $crossR += 3.5*$textFont->width;

    $im->rectangle( $crossL, $crossT, $crossR, $crossB, $black );
    $im->line( $crossL, $crossT, $crossR, $crossB, $black ) if( $params{$user} eq 'off' );
    $im->line( $crossL, $crossB, $crossR, $crossT, $black ) if( $params{$user} eq 'off' );
}

sub WriteMapElement {
    my $user = $_[0];

    $userNo++;

    $crossT = $graphT+($userNo+1)*$textFont->height-$textFont->width-2;
    $crossB = $graphT+($userNo+1)*$textFont->height-2;
    $crossL = $graphR+($graphRmargin-14*$textFont->width)/2;
    $crossR = $graphR+($graphRmargin-12*$textFont->width)/2;
    $crossL += 3.5*$textFont->width unless( $params{$user} eq 'off' );
    $crossR += 3.5*$textFont->width unless( $params{$user} eq 'off' );
    $crossL = int($crossL);
    $crossR = int($crossR);

    $newparams = $params;
    if( $params{$user} eq 'off' ){
       $newparams =~ s/(&$user=off|$user=off&|\A$user=off\Z)//;
    }else{
       $newparams .= '&' if( $params );
       $newparams .= "$user=off";
    }
    $newparams = '?'.$newparams if( $newparams );
    print qq'
<AREA SHAPE="rect" COORDS="$crossL,$crossT,$crossR,$crossB" HREF="$Iam$newparams">';
}

__END__
