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?hp=19491e04143fd9b9ef5ebe209550bfb4e1f6c61c 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 %] + + + +