#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
our $DBG = 0;
our $TEST = 0;
sub reporthead {
my ($reportfile) = @_;
my %report;
while (defined ($_ = readline $reportfile)) {
# empty line = end of head
/\S/ or last;
# strip first key=val pair
s{
^\s* ([a-zA-Z]+) = ("(?: [^"\\] | \\. )*" | \S*)
}{}x or chomp, warn("Unknown pvpgn report header line: $_\n"), next;
my ($key, $val) = ($1, $2);
$val =~ s/^"(.*)"$/$1/ and $val =~ s/\\(.)/$1/g; # unquote
$report{$key} = $val;
redo if /\S/; # other pairs on this line
}
return \%report;
}
sub reportplayers {
my ($reportfile) = @_;
my @player;
while (defined ($_ = readline $reportfile)) {
# ignore leading empty lines; stop if trailing
/\S/ or @player ? last : next;
my ($name, $result) = /^ (.*?) \s+ ([A-Z]+) \s*$/x
or chomp, warn("Unknown pvpgn report player line: $_\n");
push @player, {name => $name, result => $result};
}
my $i = -1;
while (defined ($_ = readline $reportfile)) {
m{([^<]+)} or next;
while (1) {
defined $player[++$i]
or die("More entries than $i found players\n");
last unless $player[$i]->{result} eq "DISCONNECT";
}
$player[$i]->{race}= $1;
}
return \@player;
}
my $name = $ARGV[0] or die "Usage: $0 FILE\n";
open my $reportfile, '<', "$name.txt" or die "No report file: $!\n";
my $report = reporthead($reportfile);
print Dumper $report if $DBG;
my $players = reportplayers($reportfile);
my %resultdelta = qw(WIN 1 DISCONNECT 0 DRAW 0 LOSS -1);
for (@$players) {
defined $resultdelta{ $_->{result} }
or die "Invalid player result '$_->{result}' for $_->{name}\n";
$_->{delta} = $resultdelta{ $_->{result} };
}
print Dumper $players if $DBG;
my %placetxt = (
bn => "bnet",
gr => "groningen",
md => "mdhq",
);
my ($placeid) = $name =~ /.*([a-z]{2})/;
my $place = $placetxt{$placeid} or die "Unknown place id: $placeid\n";
print "Resolved place '$placeid' to $place\n" if $DBG;
use DBIx::Simple;
my @dbinfo = do "dbinfo.inc.pl";
my $Db = DBIx::Simple->connect(@dbinfo, {pg_enable_utf8 => 1})
or die "No database: $DBI::errstr\n";
$TEST and exit;
$Db->begin;
use Date::Parse;
my ($start, $end) = map str2time($report->{$_}), qw(started ended);
use Date::Format;
$Db->insert("game", {
name => $name,
place => $place,
map => $report->{mapfile},
type => $report->{type},
start => time2str('%Y-%m-%d %X', $start),
duration => sprintf('%d seconds', $end - $start),
})->rows or die "Game insert failed: ".$Db->error."\n";
my $gameid = $Db->last_insert_id((undef) x 4, {sequence => "game_id_seq"});
$Db->insert("play", {
game => $gameid,
slot => $_,
name => $players->[$_]->{name},
account => $players->[$_]->{name},
result => $players->[$_]->{delta},
race => substr($players->[$_]->{race}, 0, 1),
})->rows or die "Player insert failed: ".$Db->error."\n"
for 0 .. $#$players;
$Db->commit;