#!/usr/bin/perl

use Data::Dumper;
use Time::Local;
use DateTime;
use List::Util qw(min max);
use Image::Magick;
use Math::Trig;

$pngfile = "buffer.png";

$scalefactor=4;
$width=1920*$scalefactor;
$height=1080*$scalefactor;
$width4=$width/4;
$height4=$height/4;

sub AV
{
  my $i=$_[0];
  my $scale=$_[1];
  my $av=$scale->{"min"}+($scale->{"max"}-$scale->{"min"})/$scale->{"ntic"}*$i;
  if(abs($av)<($scale->{"max"}-$scale->{"min"})*1e-7)
  {
    $av=0;
  }
  return $av;
}

sub SCALE
{
  my $min=$_[0];
  my $max=$_[1];
  my $ntic=$_[2];
#   print "min: $min max: $max ntic: $ntic\n";
  sub NDIG
  {
    my $x=$_[0];
    $x=1 if($x==0);
    return(POSIX::floor(log($x)/log(10)+1.0000001));
  }
  my $d=($max-$min)/$ntic;
  my $ld=log($d)/log(10);
  my $ild=POSIX::floor($ld);
  my $fld=10.0**($ld-$ild);
  my $tic=10.0**$ild;
  if($fld>5)
  {
    $tic = $tic*10;
  }
  elsif($fld>2)
  {
    $tic = $tic*5;
  }
  elsif($fld>1)
  {
    $tic = $tic*2;
  }
  $min = POSIX::floor($min/$tic)*$tic;
  $max = POSIX::floor($max/$tic+0.999999)*$tic;
  $ntic = POSIX::floor(($max-$min)/$tic+0.000001);
  my $dig1 = max(1,NDIG(max(abs($min),abs($max))));
  my $dig2 = max(1-NDIG($tic),0);
  my $r;
  $r->{"min"} = $min;
  $r->{"max"} = $max;
  $r->{"tic"} = $tic;
  $r->{"ntic"} = $ntic;
  $r->{"dig1"} = $dig1;
  $r->{"dig2"} = $dig2;
#   print Dumper($r);
  return $r;
}

sub WRITE
{
  my $x = $_[0];
  my $dig1 = $_[1];
  my $dig2 = $_[2];
  my $s = "";
  my $first=1;
  my $origx = $x;
  if($x<0)
  {
    $x=-$x;
    $s="-";
  }
  $x = ($x*10**$dig2+0.5)*10**(1-$dig1-$dig2);
  for(my $i=-$dig1; $i<=$dig2; $i++)
  {
    $first=0 if($i==-1);
    if($i==0)
    {
      $s .= "." if($dig2>0);
    }
    else
    {
      my $ch=POSIX::floor($x);
      $first=0 if($ch>0);
      $x = ($x-$ch)*10;
      $s .= $ch if($ch>0 || !$first);
    }
  }
  return $s;
}

sub textBB
{
  my $fsize=$_[0];
  my $txt=$_[1];
  (my $x_ppem, my $y_ppem, my $ascender, my $descender, my $width, my $height, my $max_advance) =
  $im->QueryFontMetrics(
	font      => "Arial",
	pointsize => $fsize,
	text      => $txt
);

  my $dx = $width;
  my $dy = $ascender;
  return ($dx,$dy);
}


open IN,"buffer.log";

$serial = 0;
$maxtime = 0;
$maxtapeid = 0;

while($l = <IN>)
{
  chomp($l);
  if($l =~ /\s*([0-9.]+)(	+)(.*)$/)
  {
    $sec[$serial] = $1;
    $maxtime = $1 if($1>$maxtime);
    $tapeid[$serial] = length($2);
    $maxtapeid = $tapeid[$serial] if($tapeid[$serial]>$maxtapeid);
    $r = $3;
    if($r =~ /^write (\d+) word/)
    {
      $operation[$serial] = $1;
    }
    elsif($r =~ /^read (\d+) word/)
    {
      $operation[$serial] = -$1;
    }
    else
    {
      next;
    }
    $serial++;
  }
}

#for($i=0;$i<$serial;$i++)
#{
#  print $sec[$i]."\t";
#  print $tapeid[$i]."\t";
#  print $operation[$i]."\n";
#}

$im = Image::Magick->new(size=>"${width}x${height}",antialias=>True);

$im->ReadImage('canvas:white');
$y1min=0;
$y1max=$maxtapeid;
$ny1tic=10;
$nxtic=20;

$tapespeed = 36.0*0.0254; # m/s
$gap = 0.75*0.0254;
$wordlen = 7.0/200.0*0.0254;

$axisfontsize=20*$scalefactor;
$axistitlefontsize=30*$scalefactor;
$titlefontsize=40*$scalefactor;
$subtitlefontsize=30*$scalefactor;
$minorticksize=3*$scalefactor;
$majorticksize=5*$scalefactor;
$y1color="#FF0000";
$readcolor="#00FF00";
$barheight=40*$scalefactor;
$writecolor="#FF0000";
$black="#000000";
$xcolor=$black;
$white="#FFFFFF";
$linewidth=1;

$fontfile = "Arial";
$boldfontfile = "Arial-Bold";

print "y1min: $y1min y1max: $y1max\n";

$y1scale = SCALE($y1min, $y1max, $ny1tic);
print "maxtime: $maxtime\n";
$xscale = SCALE(0, $maxtime, $nxtic);

$txt ="Tape I/O";
($twidth,$theight) = textBB($titlefontsize, $txt);
$im->Annotate(text=>$txt, fill=>$black, stroke=>'none', font=>$fontfile,
              pointsize=>$titlefontsize, x=>$width/2-$twidth/2, y=>$titlefontsize*2);


my $vxmin=0.01*$width;
my $vxmax=$width-0.01*$width;
my $vymin=5*$scalefactor+3*$titlefontsize;
my $vymax=$height-$axisfontsize*3-30*$scalefactor;

my $maxy1width=0;
for($i=0; $i<=$y1scale->{"ntic"};$i++)
{
  my $y0=AV($i, $y1scale);
  my $ytext=WRITE(AV($i,$y1scale),$y1scale->{"dig1"},$y1scale->{"dig2"});
  ($twidth,$theight) = textBB($axisfontsize, $ytext);
  $y1width[$i]=$twidth;
  $y1height[$i]=$theight;
  $maxy1width = $twidth if($twidth>$maxy1width);
}
$vxmin+=$maxy1width+2*$axistitlefontsize;
for($i=0; $i<=$y1scale->{"ntic"};$i++)
{
  my $y0=AV($i, $y1scale);
  my $y=$vymax-($vymax-$vymin)/($y1scale->{"max"}-$y1scale->{"min"})*($y0-$y1scale->{"min"});
  $ytext=WRITE(AV($i,$y1scale),$y1scale->{"dig1"},$y1scale->{"dig2"});
  $im->Annotate(text=>$ytext, fill=>$y1color, stroke=>'none', font=>$fontfile,
	    pointsize=>$axisfontsize,
	    x=>$vxmin-$y1width[$i]-$majorticksize, y=>$y+$y1height[$i]/2);
  $im->Draw(stroke=>$y1color, primitive=>'line', strokewidth=>$scalefactor*$linewidth, points=>$vxmin-$majorticksize.",$y $vxmin,$y");
}
$im->Draw(stroke=>$y1color, primitive=>'line', strokewidth=>$scalefactor*$linewidth, points=>"$vxmin, $vymin $vxmin, $vymax");
$txt = "Tape station number";
($twidth,$theight) = textBB($axistitlefontsize, $txt);
$im->Annotate(text=>$txt, fill=>$y1color, stroke=>'none', font=>$fontfile, rotate=>-90,
              pointsize=>$axistitlefontsize,
	      x=>$vxmin-$maxy1width-1*$axistitlefontsize,
	      y=>($vymax+$vymin)/2+$twidth/2);

$readlist = "";
$writelist = "";
for($i=0;$i<$serial;$i++)
{
  $tapespeed = 36.0*0.0254; # m/s
  $gap = 0.75*0.0254;
  $wordlen = 7.0/200.0*0.0254;
  $w = $operation[$i];
  $width = (abs($w)*$wordlen+$gap)/$tapespeed;
  $vwidth = POSIX::floor(($vymax-$vymin)/($y1scale->{"max"}-$y1scale->{"min"})*$width+0.5);
  $x=$sec[$i];
  $vx = POSIX::floor($vxmin+($vxmax-$vxmin)/($xscale->{"max"}-$xscale->{"min"})*($x-$xscale->{"min"})+0.5);
  $y=$tapeid[$i];
  $vy = POSIX::floor($vymax-($vymax-$vymin)/($y1scale->{"max"}-$y1scale->{"min"})*($y-$y1scale->{"min"})+0.5);
  print "vx: $vx vwidth: $vwidth vy: $vy barheight: $barheight\n";
  $point = "$vx,$vy ".($vx+$vwidth).",".($vy+$barheight);
  if($w<0)
  {
    $im->Draw(fill=>$readcolor, primitive=>'rectangle', points=>"$point");
  }
  else
  {
    $im->Draw(fill=>$writecolor, primitive=>'rectangle', points=>"$point");
  }
   
}
#print "$readlist\n";
#print "$writelist\n";
for($i=0; $i<=$xscale->{"ntic"};$i++)
{
  my $x=AV($i, $xscale);
  my $vx=$vxmin+($vxmax-$vxmin)/($xscale->{"max"}-$xscale->{"min"})*($x-$xscale->{"min"});
  $xtext=WRITE($x,$xscale->{"dig1"},$xscale->{"dig2"});
  ($twidth,$theight) = textBB($axisfontsize, $xtext);
  $im->Annotate(text=>$xtext, fill=>$xcolor, stroke=>'none', font=>$fontfile,
	    pointsize=>$axisfontsize,
	    x=>($vx-$twidth/2), y=>$vymax+$axisfontsize);
  $im->Draw(stroke=>$xcolor, primitive=>'line', strokewidth=>$scalefactor*$linewidth,
            points=>"$vx,$vymax $vx,".($vymax+$majorticksize));
}
$im->Draw(stroke=>$xcolor, primitive=>'line', strokewidth=>$scalefactor*$linewidth, points=>"$vxmin, $vymax $vxmax, $vymax");
$txt = "Time";
($twidth,$theight) = textBB($axistitlefontsize, $txt);
$im->Annotate(text=>$txt, fill=>$xcolor, stroke=>'none', font=>$fontfile,
              pointsize=>$axisfontsize,
	      x=>($vxmax+$vxmin)/2-$twidth/2,
	      y=>$vymax+1*$axisfontsize+2*$axistitlefontsize);


$im->Scale(geometry=>"${width4}x${height4}");
$im->Write($pngfile);

