#! /usr/bin/perl
use DBI;
use strict;
use warnings;
no warnings qw(once);
use POSIX;
require './config.pm';

# Find last completely done season 
sub find_last_season {
	my $dbh = shift;
	my $ref = $dbh->selectrow_hashref('SELECT sesong FROM fotballserier GROUP BY sesong HAVING COUNT(*)=COUNT(avgjort=1 OR NULL) ORDER BY sesong DESC LIMIT 1');
	return $ref->{'sesong'};
}

sub fetch_games {
	my ($dbh, $last_season, $games, $ids) = @_;
	my $q = $dbh->prepare('
SELECT
  deltager1.id as p1, deltager2.id as p2, maalfor, maalmot, least(pow(2.0, (sesong - ? + 3) / 3.0), 1.0) AS vekt
FROM
  Fotballresultater resultater
  JOIN Fotballdeltagere deltager1 ON resultater.Lagrecno=deltager1.Nr AND resultater.Serie=deltager1.Serie
  JOIN Fotballdeltagere deltager2 ON resultater.Motstander=deltager2.Nr AND resultater.Serie=deltager2.Serie
  JOIN Fotballserier serier on resultater.Serie=serier.Nr
WHERE deltager1.Nr > deltager2.nr
	');
	$q->execute($last_season);

	while (my $ref = $q->fetchrow_hashref) {
		next if ($ref->{'maalfor'} == 150 && $ref->{'maalmot'} == 0);
		next if ($ref->{'maalfor'} == 0 && $ref->{'maalmot'} == 150);
		next if ($ref->{'maalfor'} == 150 && $ref->{'maalmot'} == 150);
		next if ($ref->{'maalfor'} == 0 && $ref->{'maalmot'} == 0);
		push @$games, { %$ref };
		$ids->{$ref->{'p1'}} = 1;
		$ids->{$ref->{'p2'}} = 1;
	}
}

sub output_to_file {
	my ($games, $ids) = @_;

	my $tmpnam = POSIX::tmpnam();
	open DATA, ">", $tmpnam
		or die "$tmpnam: $!";

	printf DATA "%d\n", scalar keys %$ids;
	for my $id (keys %$ids) {
		printf DATA "%d\n", $id;
	}
	for my $ref (@$games) {
		printf DATA "%d %d %d %d %f\n", $ref->{'p1'}, $ref->{'p2'}, $ref->{'maalfor'}, $ref->{'maalmot'}, $ref->{'vekt'};
	}
	close DATA;

	return $tmpnam;
}

sub train_model {
	my ($filename, $ratings, $covariances, $aux_params) = @_;

	open RATINGS, "$config::base_dir/bayeswf < $filename |"
		or die "bayeswf: $!";
	while (<RATINGS>) {
		chomp;
		my @x = split;
		if ($x[0] eq 'covariance') {
			push @$covariances, (join("\t", @x[1..3]));
		} elsif ($x[0] eq 'aux_param') {
			push @$aux_params, ("nb-NO" .  "\t" . $x[1] . "\t" . $x[2]);
		} else {
			push @$ratings, ($x[2] . "\t" . $x[0] . "\t" . $x[1]);
		}
	}

	close RATINGS;
}

my $dbh = DBI->connect($config::local_connstr, $config::local_username, $config::local_password)
	or die "connect: " . $DBI::errstr;
$dbh->{AutoCommit} = 0;
$dbh->{RaiseError} = 1;

$dbh->do('SET client_min_messages TO WARNING');

my $last_season = find_last_season($dbh);
my @games = ();
my %ids = ();
fetch_games($dbh, $last_season, \@games, \%ids);
my $tmpnam = output_to_file(\@games, \%ids);

my @ratings = ();
my @covariances = ();
my @aux_params = ();
train_model($tmpnam, \@ratings, \@covariances, \@aux_params);
unlink($tmpnam);

$dbh->do('TRUNCATE aux_params');
$dbh->do('COPY aux_params ( kultur, id, value ) FROM STDIN');
$dbh->pg_putcopydata(join("\n", @aux_params));
$dbh->pg_putcopyend();

$dbh->do('TRUNCATE ratings');
$dbh->do('COPY ratings ( id, rating, rating_stddev ) FROM STDIN');
$dbh->pg_putcopydata(join("\n", @ratings));
$dbh->pg_putcopyend();

$dbh->do('CREATE TABLE new_covariance ( player1 smallint NOT NULL, player2 smallint NOT NULL, cov float NOT NULL )');
$dbh->do('COPY new_covariance ( player1, player2, cov ) FROM STDIN');
$dbh->pg_putcopydata(join("\n", @covariances));
$dbh->pg_putcopyend();
$dbh->do('ALTER TABLE new_covariance ADD PRIMARY KEY ( player1, player2 );');
$dbh->do('DROP TABLE IF EXISTS covariance');
$dbh->do('ALTER TABLE new_covariance RENAME TO covariance');

$dbh->commit;
