screp --act to create an animated image of replay actions
[perl/schtarr.git] / screp
diff --git a/screp b/screp
index 910f3d2f5ad4bc465805883e2b9589d1f641aa65..5e754adaaa9e34826c4f31262a4b63be9e7d4cee 100755 (executable)
--- a/screp
+++ b/screp
@@ -4,10 +4,14 @@ use warnings;
 use Data::Dumper;
 
 my $SHOWWARN = 0;
+my $ACTGIF = undef;
+my $APMSVG = undef;
 
 use Getopt::Long;
 GetOptions(
        "verbose|v!" => \$SHOWWARN,
+       "apm|a=s" => \$APMSVG,
+       "act" => \$ACTGIF,
 );
 
 use constant { APM_FIRSTFRAME => 80 / .042 };
@@ -557,3 +561,106 @@ for my $player (sort keys %stats) {
        ) if 0;
 }
 
+if ($ACTGIF) {
+       open my $imgfile, '>', "test.gif" or die;
+       binmode $imgfile;
+       select $imgfile;
+
+       use GD;
+       my $ani = GD::Image->new($head->{width}, $head->{height});
+       my $bg = $ani->colorAllocate(0, 0, 0);
+       my @plot = (
+               $ani->colorAllocate(255, 0, 0),
+               $ani->colorAllocate(255, 255, 0),
+               $ani->colorAllocate(0, 255, 0),
+               $ani->colorAllocate(0, 255, 255),
+               $ani->colorAllocate(0, 0, 255),
+               $ani->colorAllocate(255, 0, 255),
+       );
+
+       print $ani->gifanimbegin;
+#      print $ani->gifanimadd;
+       {
+               my $frame = GD::Image->new($ani->getBounds);
+               print $frame->gifanimadd;
+               my $length = 30 / .042;
+               my $last = 0;
+               for (@$map) {
+                       my ($time, $player, $cmd, @data) = @$_;
+#$time < $length * 10 or last;
+                       while ($time > $last + $length) {
+                               $last += $length;
+                               print $frame->gifanimadd(0, 0, 0, 32);
+#                              $frame = GD::Image->new($ani->getBounds);
+                       }
+                       if ($cmd eq "build") {
+                               $frame->setPixel($data[1]>>5, $data[2]>>5, $plot[$player]);
+                       }
+                       elsif ($cmd eq "move" or $cmd eq "attack") {
+                               $frame->setPixel($data[0]>>5, $data[1]>>5, $plot[$player]);
+#                                      if $data[2] == 0xFFFF_FFFF;
+                       }
+               }
+#              add_frame_data($frame);
+               print $frame->gifanimadd;
+       }
+       print $ani->gifanimend;
+       select STDOUT;
+}
+
+if ($APMSVG) {
+       my @seq;  # player => time (s) => actions
+       $seq[$_->[1]][$_->[0] * .042]++ for @$map;
+       my $flatten = 120;
+       my @apm;
+       for my $player (0 .. $#seq) {
+               my $range = 0;
+                  $range += $seq[$player][$_] || 0 for 0 .. $flatten - 1;
+               my $leadfill = $range / $flatten;
+               for my $frame (0 .. $#{$seq[$player]}) {
+                       $range += $seq[$player][$frame] || 0;
+                       $range -= $frame < $flatten ? $leadfill :
+                               $seq[$player][$frame - $flatten] || 0;
+                       $apm[$player][$frame] = $range / $flatten;
+               }
+       }
+
+       BEGIN { unshift @INC, '.' }
+       use SVG::TT::Graph::TimeSeries;
+       my $graph = SVG::TT::Graph::TimeSeries->new({
+               height => 1200,
+               width => 1600,
+               style_sheet => "apm.css",
+               show_data_values => 0,
+               show_data_points => 0,
+               x_label_format => '%k:%M',
+               key => 1,
+               timescale_divisions => "5 minutes",
+       #       compress => 1,
+       });
+
+       for my $player (0 .. $#apm) {
+               $graph->add_data({
+                       data => [map {
+                               time2str('%Y-%m-%d %X', 946681200 + $_),
+                               $apm[$player][$_] * 60
+                       } 0 .. $#{$apm[$player]} ],
+                       title => showplayer($player),
+               });
+       }
+
+       my ($name) = $APMSVG =~ /([^.]+)/;
+       my $title = "APM timeline" . ($name && " for $name");
+       my $lead = sprintf "\n<title>%s</title>", $title;
+
+       my $svg = $graph->burn();
+       s/^[ \t\r]+\n//gm,  # remove lines with only whitespace (many useless ^M)
+       s/[ \t\r]+$//gm,    # trailing whitespace
+       s/ {4}\r*/\t/g,     # tabs for indenting
+       s/^(<svg width=")1600(" height=")1200("[^>]*>)/${1}100%${2}100%$3$lead/m,
+               for $svg; # cleanup xml
+
+       open my $apmfile, '>', "$APMSVG.svg";
+       print $apmfile $svg;
+}
+