chiark / gitweb /
WIP database populate before perl route calc
[ypp-sc-tools.db-live.git] / pctb / db-idempotent-populate
index 1b0ef02214a005d834ac20dbe5b50960eb1bb757..ccc79be3609a42fb0c6197839980f2641a7fcdef 100755 (executable)
@@ -33,9 +33,9 @@ use DBI;
 use Commods;
 
 @ARGV==1 or die;
-my ($ocean) = @ARGV;
+my ($oceanname) = @ARGV;
 
-my $dbfn= "OCEAN-$ocean.db";
+my $dbfn= "OCEAN-$oceanname.db";
 
 our $dbh;
 
@@ -45,20 +45,27 @@ sub dbdoall ($) {
     }
 }
 
+#---------- setup ----------
+
+parse_masters_ocean($oceanname);
+our $ocean= $oceans{$oceanname};
+
 $dbh= DBI->connect("dbi:SQLite:$dbfn",'','',
                   { AutoCommit=>0,
                     RaiseError=>1, ShowErrorStatement=>1,
                     unicode=>1 })
     or die "$dbfn $DBI::errstr ?";
 
+#---------- schema ----------
+
 foreach my $bs (qw(buy sell)) {
     dbdoall(<<END)
  CREATE TABLE IF NOT EXISTS $bs (
        commodid        INTEGER                 NOT NULL,
        islandid        INTEGER                 NOT NULL,
        stallid         INTEGER                 NOT NULL,
-       price           INTEGER,
-       qty             INTEGER,
+       price           INTEGER                 NOT NULL,
+       qty             INTEGER                 NOT NULL,
        PRIMARY KEY (commodid, islandid, stallid)
  );
  CREATE INDEX IF NOT EXISTS ${bs}_by_island ON $bs (commodid, islandid, price);
@@ -68,7 +75,7 @@ END
 }
 
 dbdoall(<<END)
- CREATE TABLE IF NOT EXISTS commodities (
+ CREATE TABLE IF NOT EXISTS commods (
        commodid        INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
        commodname      TEXT    UNIQUE          NOT NULL,
        unitmass        INTEGER,
@@ -91,10 +98,10 @@ dbdoall(<<END)
        clientspec      TEXT                    NOT NULL,
        serverspec      TEXT                    NOT NULL
  );
- CREATE TABLE IF NOT EXISTS distances (
+ CREATE TABLE IF NOT EXISTS dists (
        aiid            INTEGER                 NOT NULL,
        biid            INTEGER                 NOT NULL,
-       distance        INTEGER                 NOT NULL,
+       dist            INTEGER                 NOT NULL,
        PRIMARY KEY (aiid, biid)
  );
 END
@@ -102,11 +109,11 @@ END
 
 $dbh->commit;
 
-parse_masters();
+#---------- commodity list ----------
 
 {
     my $sth= $dbh->prepare(<<'END')
- INSERT OR IGNORE INTO commodities (commodname) values (?);
+ INSERT OR IGNORE INTO commods (commodname) VALUES (?);
 END
     ;
     foreach my $commod (sort keys %commods) {
@@ -114,3 +121,98 @@ END
     }
     $dbh->commit;
 }
+
+#---------- island list ----------
+
+{
+    my $sth= $dbh->prepare(<<'END')
+ INSERT OR IGNORE INTO islands (islandname, archipelago) VALUES (?, ?);
+END
+    ;
+    foreach my $archname (sort keys %$ocean) {
+       my $arch= $ocean->{$archname};
+       foreach my $islandname (sort keys %$arch) {
+           $sth->execute($islandname, $archname);
+       }
+    }
+    $dbh->commit;
+}
+
+#---------- routes ----------
+
+{
+    foreach my $islandname (sort keys %{ $route_mysteries{$oceanname} }) {
+       warn "$route_mysteries{$oceanname}{$islandname} routes".
+           " for unknown island $islandname\n";
+    }
+
+    dbdoall(<<END)
+ CREATE TEMPORARY TABLE newdists (
+       aiid            INTEGER                 NOT NULL,
+       biid            INTEGER                 NOT NULL,
+       dist            INTEGER                 NOT NULL
+ );
+ INSERT INTO newdists SELECT (aiid,biid,dist) FROM dists;
+ INSERT INTO newdists SELECT (biid,aiid,dist) FROM dists;
+ INSERT INTO newdists SELECT (islandid,islandid,0) FROM islands;
+END
+    ;
+
+    my $sth= $dbh->prepare(<<'END')
+ INSERT INTO newdists VALUES
+       ((SELECT islandid FROM islands WHERE islandname == ?),
+        (SELECT islandid FROM islands WHERE islandname == ?),
+        ?);
+END
+    ;
+    my $allroutes= $routes{$oceanname};
+    foreach my $an (keys %$allroutes) {
+       my $routes= $allroutes->{$an};
+       foreach my $bn (keys %$routes) {
+           $sth->execute($an, $bn, $routes->{$bn});
+       }
+    }
+
+    my $stmt_updatemain= $dbh->prepare(<<'END')
+ UPDATE dists SET dist = (
+       SELECT min(dist) FROM newdists
+       WHERE dists.aiid == newdists.aiid
+         AND dists.biid == newdists.biid
+         AND NOT dists.dist <= newdists.dist
+ );
+END
+
+    my $stmt_removeredund= $dbh->prepare(<<'END')
+ DELETE FROM newdists
+       WHERE dist > (
+               SELECT dists.dist
+               WHERE dists.aiid == newdists.aiid
+                 AND dists.aiid == newdists.aiid
+ );
+END
+    ;
+
+    my $stmt_gennew= $dbh->prepare(<<'END')
+ INSERT INTO newdists (
+       SELECT src.aiid, dst.biid, min(src.dist + dst.dist)
+       FROM dists AS src, dists AS dst ON src.biid == dst.aiid
+       GROUP BY src.aiid, dst.biid
+ );
+END
+    ;
+    
+    for (;;) {
+       $ar= $dbh->selectall_arrayref("select ia.islandname, ib.islandname,newdists.dist from newdists, islands as ia on newdists.aiid = ia.islandid, islands as ib on newdists.biid = ib.islandid;");
+       print Dumper($ar);
+
+       my $affected= $stmt_updatemain->execute();
+       last unless $affected;
+
+       $stmt_
+       
+}
+
+#use Data::Dumper;
+#print Dumper(\%routes);
+
+__DATA__