From acea822c3a40b7e74b8d390f6c4d497eface0b56 Mon Sep 17 00:00:00 2001 From: Shiar Date: Wed, 6 Feb 2008 22:39:30 +0100 Subject: [PATCH] graphplay to draw SVG graphs of gameplay statistics Parses game stats output of capture script, and draws progression of minerals, gas, and units over time per player. SVG is simple enough to write manually (template at *DATA), but produces essentially the same as SVG::TT::Graph::TimeSeries would (except much faster and easier to understand/modify). --- graphplay | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100755 graphplay diff --git a/graphplay b/graphplay new file mode 100755 index 0000000..d6baebf --- /dev/null +++ b/graphplay @@ -0,0 +1,132 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use Template; +use List::Util; +use Data::Dumper; + +my %area = ( + fieldxmin => 45, + fieldxmax => 1590, + fieldymin => 10, + fieldymax => 575, + xmax => 1600, + ymax => 600, +); +$area{fieldxsize} = $area{fieldxmax} - $area{fieldxmin}; +$area{fieldysize} = $area{fieldymax} - $area{fieldymin}; + +my @lines; +my @max = (0) x 4; +my $maxtime = 0; +my $player = 0; + +for my $input (@ARGV) { + open my $datafile, '<', $input or next; + my @data; + my $lasttime; + while (defined ($_ = readline $datafile)) { + my ($frame, $time, @vars) = split /\t/, $_; + $frame =~ /^\d+:$/ or next; + if ($time !~ /^\d+$/) { + defined $lasttime or next; + $time = $lasttime + 1; + $lasttime = undef; + } else { + $lasttime = $time; + } + /^\d+$/ or $_ = undef for @vars; + push @{$data[$time]} => \@vars; + defined $vars[$_] and $vars[$_] > $max[$_] and $max[$_] = $vars[$_] + for 0 .. $#vars; + } + $maxtime = $#data if $#data > $maxtime; + close $datafile; + + for my $time (0 .. $#data) { + my $vals = $data[$time]; + for my $subtime (0 .. $#$vals) { + defined $vals->[$subtime]->[$_] and push @{$lines[$_][$player]} => [ + ($time + $subtime/@$vals), # x + $vals->[$subtime]->[$_] # y + ] for 0 .. 3; + } + } + + $player++; +} + +my @norm = ((map {$area{fieldysize} / $_} @max), $area{fieldxsize} / $maxtime); + +my $xsteps = 25; +my $xstep = $maxtime / $xsteps; +my @xaxis = map [$area{fieldxmin} + $_ * $norm[4], sprintf '%d:%02d', $_/3600, $_/60%60], + map $_*$xstep, 0 .. $xsteps-1; + +my $ysteps = 10; +my @yaxis; +for my $i (0 .. 3) { + my $ystep = $max[$i] / $ysteps; + $ystep = 10 ** int (log($ystep * 4) / log(10)); + $ystep /= 2 while $ystep * $ysteps > $max[$i]; + $yaxis[$i] = [ + map [$area{fieldymax} - $_ * $norm[$i], $_], + map $_*$ystep, 0 .. int $max[$i] / $ystep + ]; +} + +undef $/; +my $svg = Template->new({POST_CHOMP => 1, BLOCKS => {timeline => readline DATA}}); + +for ([0 => "min", "Minerals"], [1 => "gas", "Gas"], [2 => "unit", "Units"]) { + my ($line, $filename, $title) = @$_; + open my $output, '>', "$filename.svg"; + $svg->process('timeline', { + title => "$title timeline for /replay/20080201md4x4", + paths => [ + map { "\n\tM " . join "\tL ", map sprintf("%s %s\n", + $area{fieldxmin} + $_->[0] * $norm[4], + $area{fieldymax} - $_->[1] * $norm[$line] + ), grep defined, @$_ } @{$lines[$line]} + ], + xaxis => \@xaxis, + yaxis => $yaxis[$line], + area => \%area, + }, $output) or die $svg->error; +} + +__DATA__ + + + + + + +[% title %] + + + + + +[% FOREACH entry = xaxis %] + [% entry.1 %] +[% END %] + + +[% FOREACH entry = yaxis %] + +[% entry.1 %] +[% END %] + + +[% count = 0 %] +[% FOREACH path = paths %][% count = count + 1 %] + +[% END %] + + + + -- 2.30.0