#! /usr/bin/perl

use Math::RandomOrg qw(randnum randbyte);
use DBD::mysql;

# The database schema for the dice table is:
# create table Dice (
#     die_id              int not null,
#     value               tinyint not null,
#     primary key (die_id)
# )

my $DEBUG = 0;
my $LOW_MARK = 10000;
my $CHUNK_SIZE = 10;

if ($DEBUG) {
    print "Check DB size and shift dice...\n";
}

my $dbh = DBI->connect("DBI:mysql:bg", "bg", "");
$dbh->do("LOCK TABLES Dice WRITE") || die "LOCK TABLES failed";
my $stmt = $dbh->prepare("SELECT MIN(die_id), MAX(die_id) FROM Dice");

$stmt->execute || die "Query failed: $stmt->errstr";
my ($min_die, $max_die) = $stmt->fetchrow_array;
my $entries = $max_die - $min_die;

# Shift the dice down, but only if there is room to prevent us from
# stomping on ourselves.
if ($min_die > $entries) {
    $dbh->do("UPDATE Dice SET die_id=die_id-$min_die+1") || die "Shift Dice Failed";
}
$dbh->do("UNLOCK TABLES") || die "Unlock failed";

if ($entries > $LOW_MARK) {
    if ($DEBUG) {
	print "Table has $entries already... do nothing\n";
	exit;
    }
}

if ($DEBUG) {
    print "Get dice from random.org...\n";
}
my $x = randbyte(16384) || die "randbyte failed\n";
my @dice = ();
foreach my $c (split //,$x) {
    my $val = ord($c);
    my $mix = int(rand 256);

    my $byte = $val ^ $mix;

    if ($byte > 252) {
	next;
    }

    my $d1 = 1 + $byte % 6;
    my $d2 = 1 + ($byte % 36 - $d1 + 1) / 6;

    push @dice, "$d1$d2";
}

if ($DEBUG) {
    my $numdice = $#dice + 1;
    print "Got $numdice dice...\n";
}


while (@dice)
{
    my @chunk = ();
    my $i = 0;
    while (@dice && $i < $CHUNK_SIZE) {
	my $die = shift @dice;
	push @chunk, $die;
	$i++;
    }

    $dbh->do("LOCK TABLES Dice WRITE") || die "LOCK TABLES failed";
    $stmt = $dbh->prepare("SELECT MAX(die_id) FROM Dice");
    $stmt->execute || die "Query failed: $stmt->errstr";
    (my $max_id) = $stmt->fetchrow_array;

    my @VALUES = ();
    foreach my $val (@chunk) {
	$max_id++;
	push @VALUES, "($max_id, $val)";
    }
    my $sql = "INSERT Dice (die_id, value) VALUES " . join(',', @VALUES);

    $dbh->do($sql) || die "INSERT DICE failed";
    $dbh->do("UNLOCK TABLES") || die "UNLOCK TABLES failed";
}