X-Git-Url: http://git.shiar.nl/perl/schtarr.git/blobdiff_plain/c65ad507429caa59eaab5161062b3f2704d8d77b..be195d9afe05fc615f9c0aeb77837adfee4b434f:/screp diff --git a/screp b/screp index 1922415..7bf178f 100755 --- a/screp +++ b/screp @@ -10,6 +10,8 @@ GetOptions( "verbose|v!" => \$SHOWWARN, ); +use constant { APM_FIRSTFRAME => 80 / .042 }; + { package Data::StarCraft::Replay; @@ -310,6 +312,7 @@ my %cmdread = ( 0x18 => ["cancel"], 0x19 => ["cancel hatch"], 0x1A => ["stop", 1], +# 0x1B => ["move-thing??"], # tim: after hotkey (unit, reaver??) select; soon after reselected and moved 0x1E => ["return cargo", 1], 0x1F => ["train", 2, \%unit], 0x20 => ["cancel train", 2], # == 254 @@ -417,6 +420,53 @@ sub showtime { return sprintf "%d:%04.1f", $minutes, $time - $minutes * 60; } +sub unpackhash { + my ($template, $expr, @elements) = @_; + my @data = unpack $template, $expr; + my %map; + $map{$_} = shift @data for @elements; + return (\%map, @data); +} + +local $_ = Data::StarCraft::Replay::_read(undef, \*STDIN, 633) + and my ($head, @headdata) = unpackhash("CVa3Va12Z28v2Z16Z24CZ26a38a*", $_, qw( + engine frames mag1 time mag2 name width height + unknown1 creator unknown2 map unknown3 + )) + or die "Couldn't read replay header\n"; + +$_ eq "\0\0\110" or warn sprintf( + "Mismatch in first header constant: %s\n", + join ",", map ord, split //, $_ +) for $head->{mag1}; +$_ eq "\10"x8 . "\0"x4 or warn sprintf( + "Mismatch in second header constant: %s\n", + join ",", map ord, split //, $_ +) for $head->{mag2}; +delete $head->{$_} for qw(mag1 mag2 unknown1 unknown2); + +my @playdata = unpack "a36"x12 . "V8C8", $headdata[0] + or die "Couldn't parse player data in replay header\n"; + +my @player; +push @player, unpackhash("x11Z25", shift @playdata, qw/name/) for 0 .. 11; +$player[$_]->{color} = shift @playdata for 0 .. 7; +$player[$_]->{index} = shift @playdata for 0 .. 7; + +printf "%s: %s\n", $_, $head->{$_} for qw(name creator); +use Date::Format; +printf "created: %s\n", time2str('%Y-%m-%d %X', $_) for $head->{time}; +printf "map: %s (%dx%d)\n", map $head->{$_}, qw(map width height); +printf "frames: %s (%s)\n", $_, showtime($_) for $head->{frames}; +print "\n"; + +if ($SHOWWARN) { + print Dumper $head; + print Dumper \@player; + #printf ":%s\n", join ",", map sprintf('%X', ord $_), split // for @headdata; + print "\n"; +} + my $map = Data::StarCraft::Replay->new->open(\*STDIN); if ($SHOWWARN) { @@ -428,8 +478,6 @@ if ($SHOWWARN) { } } -printf "duration: %s\n", showtime($map->[-1][0]); - my %cmdmacro = map {$_ => 1} ( (map {$_, "cancel $_"} qw/train build hatch research upgrade arm/, @@ -441,7 +489,7 @@ my %cmdmacro = map {$_ => 1} ( my %stats; # player => count for (@$map) { $stats{$_->[1]}{actions}++; - $stats{$_->[1]}{gameactions}++ if $_->[0] > 80 / .042; + $stats{$_->[1]}{gameactions}++ if $_->[0] >= APM_FIRSTFRAME; $stats{$_->[1]}{last} = $_->[0] if $_->[2] eq "part"; $stats{$_->[1]}{$cmdmacro{$_->[2]} ? "macro" : "micro"}++; $stats{$_->[1]}{count}{$_->[2]}++; @@ -451,13 +499,12 @@ for my $player (sort keys %stats) { my $row = $stats{$player}; $row->{last} ||= $map->[-1][0]; # printf("%d:%6d actions (%3d micro,%4d macro);%4d APM\n", - printf("%d:%6d actions;%4d APM\n", - $player, - $row->{actions}, + printf("%d:%6d actions in%7d frames (%s) = %d APM\n", + $player, $row->{actions}, $row->{last}, + showtime($row->{last}), # $row->{micro} / $row->{last} * 60 / .042 * 1.05, # $row->{macro} / $row->{last} * 60 / .042 * 1.05, - $row->{gameactions} / $row->{last} * 60 / .042 * 1.042, - # $row->{gameactions} / $map->[-1][0] * 60 / .042, + $row->{gameactions} / ($row->{last} - APM_FIRSTFRAME) * 60 / .042, ); if (0) {