#!/usr/bin/perl

$event_filter = "[rs-]";
@ptype_filter = ("tcp", "cbr", "exp");

# trace MAC instead of AGT
# (ns doesn't install trace objects at the ports of all Mobile Nodes!)
$ttype_filter = "MAC";

if (@ARGV < 1) {
    printf "usage plot_tp.pl [-s size] <trace file> [node1, ...]\n";
    exit;
}

$on_top = 1;
$max_tp = 0; # max. throughput for scaling of plot
$y_size = 0; # "height" of each subgraph

%packet_source = ();
$granularity = 1.0;
@p_data = ();
@s_data = ();
@p_time = ();
@trace_list = ();
@trace_type = ();

if ($ARGV[0] =~ /^-[sS]/) {
    $y_size = $ARGV[1];
    shift; shift;
}
$tracename = shift;
if ($tracename =~ /(.+)\.tr/) {
    $outname = $1 . ".ps";
} else {
    $outname = $tracename . ".ps";
}

open(infile, $tracename) or die "couldn't open $tracename";
while ($line = <infile>) {
    ++$line_no;

    next if ($line !~ /^$event_filter/);
    $cont = 0;
    foreach $t (@ptype_filter) {
        if ($line =~ /$t/) {
	    $cont = 1;
	    last;
	}
    }
    next unless ($cont);

    @entry = split(/[\s\(\)\[\]]+/, $line);

    $event = $entry[0];
    $time = $entry[1];

    # check for trace format and parse entry
    if ($entry[2] =~ /_+(\d+)_+/) { # mobile
	$to = $1;
	next if ($entry[3] ne $ttype_filter);
	$pktid = $entry[5];

	if ($event ne "r") {
	    $packet_source{$pktid} = $to;
	    next;
	}

	die "packet error $pktid (line $line_no)" if ($packet_source{$pktid} == undef);
	$from = $packet_source{$pktid};
	$type = $entry[6];
	$size = $entry[7];
	$packet_source{$pktid} = $to;
    } else {                        # standard
	$to = $entry[3];
	$pktid = $entry[11];

	if ($event ne "r") {
	    $packet_source{$pktid} = $to;
	    next;
	}

	$from = $entry[2];
	$type = $entry[4];
	$size = $entry[5];
	$packet_source{$pktid} = $to;
    }
    
    foreach $tnode ($to, $from) {
	if ($outfile[$tnode] eq "") {
	    $outfile[$tnode] = $fh++;
	    open($outfile[$tnode], ">recv$tnode.log") or die "couldn't open recv$tnode.log";
	    $sndfile[$tnode] = $fh++;
	    open($sndfile[$tnode], ">send$tnode.log") or die "couldn't open recv$tnode.log";

	    push @trace_list, $tnode;
	    $trace_type[$tnode] = "$type";
	    $p_time[$tnode] = 0.0;
	    $p_data[$tnode] = 0;
	    $s_data[$tnode] = 0;
	    printf { $outfile[$tnode] } "0.0 0\n";
	    printf { $sndfile[$tnode] } "0.0 0\n";
	}
    }

    foreach $tnode ($to, $from) {
	while ($time > $p_time[$tnode] + $granularity) {
	    $p_time[$tnode] += $granularity;
	    printf { $outfile[$tnode] } "%08.4f %i\n", $p_time[$tnode], $p_data[$tnode] / $granularity;
	    printf { $sndfile[$tnode] } "%08.4f %i\n", $p_time[$tnode], $s_data[$tnode] / $granularity;
	    $max_tp = $p_data[$tnode] if ($max_tp < $p_data[$tnode]);
	    $max_tp = $s_data[$tnode] if ($max_tp < $s_data[$tnode]);
	    $p_data[$tnode] = 0;
	    $s_data[$tnode] = 0;
	}
    }

    $p_data[$to] += $size;
    $s_data[$from] += $size;
}
close(infile);
$max_tp *= 8.0 / 1000.0 / $granularity; # adjust to KBit/s and granularity

if ($on_top) {
    if ($y_size == 0) {
	$y_size = (int($max_tp / 50) + 1) * 50 ;
    }
    $y_dist = $y_size * 1.5;
} else {
    $y_size = 0;
    $y_dist = 0;
}


foreach $tnode (@trace_list) {
    while ($time >= $p_time[$tnode] + $granularity) { # fill rest with 0
	$p_time[$tnode] += $granularity;
	printf { $outfile[$tnode] } "%08.4f %i\n", $p_time[$tnode], $p_data[$tnode] / $granularity;
	printf { $sndfile[$tnode] } "%08.4f %i\n", $p_time[$tnode], $s_data[$tnode] / $granularity;
	$p_data[$tnode] = 0;
	$s_data[$tnode] = 0;
    }
    close($outfile[$tnode]);
    close($sndfile[$tnode]);
}


#determine nodes to plot
@plot_list = ();
if (@ARGV > 0) {
    foreach $a (@ARGV) {
	$add = 0;
	foreach $b (@trace_list) {
	    if ($a == $b) {
		$add = 1;
		last;
	    }
	}
	push @plot_list, $a if ($add);
    }
} else {
    @plot_list = @trace_list;
}

@plot_list = sort { $a <=> $b } @plot_list;

#plot
die "no nodes to plot" if (@plot_list == 0);

open(cmd, ">cmd.tmp");
#print cmd "set term post eps color solid 16\n";
print cmd "set term post portrait color solid 16\n";
print cmd "set output \"$outname\"\n";
print cmd "set key top left", ($on_top) ? " outside" : "", "\n";
#print cmd "set size 1.0,0.4\n";
print cmd "set xlabel \"Time (s)\"\n";
print cmd "set xrange [0:$time]\n";
print cmd "set ylabel \"Throughput (KBit/s)\"\n";
if ($on_top) {
    print cmd "set yrange [-10:", $y_dist * @plot_list, "]\n";
    print cmd "set ytics border nomirror norotate (";
    for ($i = 0; $i < @plot_list; ++$i) {
	print cmd ", " if ($i > 0);
	print cmd "\"0\" ", $y_dist * $i,
	          ", \"", $y_size / 2, "\" ", $y_dist * $i + $y_size / 2,
	          ", \"$y_size\" ", $y_dist * $i + $y_size;
    }
    print cmd ")\n";
} else {
    print cmd "set yrange [0:]\n";
}
$nr = 0;
foreach $node (@plot_list) {
    # labels
    print cmd "set label \"node $node\" at ", $time + 2, ",",
              ($#plot_list - $nr + 0.35) * $y_dist, "\n";
    ++$nr;
}
$nr = 0;
print cmd "plot ";
foreach $node (@plot_list) {
    # delimiting line
    if ($nr > 0) {
	print cmd ", ";
	print cmd $nr * $y_dist - ($y_dist - $y_size) / 2, " not w l 0, " if ($on_top);
    }
    # send + receive graph
    print cmd "\"send$node.log\" u 1:(\$2*8/1000+", ($#plot_list - $nr) * $y_dist,
              ") not w l ",
	      ($trace_type[$node] eq "tcp") ? 1 : 4;
    print cmd ", \"recv$node.log\" u 1:(\$2*8/1000+", ($#plot_list - $nr) * $y_dist,
              ") not w l ",
	      ($trace_type[$node] eq "tcp") ? 2 : 3;
    ++$nr;
}
print cmd "\n";
close(cmd);
system "gnuplot cmd.tmp; rm -f cmd.tmp";

