#! /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"; }