From: Shiar Date: Wed, 6 Feb 2008 21:39:30 +0000 (+0100) Subject: graphplay to draw SVG graphs of gameplay statistics X-Git-Url: http://git.shiar.net/perl/schtarr.git/commitdiff_plain/acea822c3a40b7e74b8d390f6c4d497eface0b56 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). --- 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 %] + + + +