chiark / gitweb /
new --stdin-chart for testing yppedia-chart-parser
[ypp-sc-tools.db-live.git] / yarrg / yppedia-chart-parser
index 8eafa4c..44a143b 100755 (executable)
@@ -73,17 +73,26 @@ sub print_messages () {
 }
 sub progress ($) { print "($_[0])\n"; }
 
-if (@ARGV && $ARGV[0] eq '--debug') {
-    shift @ARGV;
-    open DEBUG, ">&STDOUT" or die $!;
-    select(DEBUG); $|=1;
-} else {
-    open DEBUG, ">/dev/null" or die $!;
+my $stdin_chart=0;
+
+open DEBUG, ">/dev/null" or die $!;
+
+while (@ARGV) {
+    last unless $ARGV[0] =~ m/^-/;
+    $_= shift @ARGV;
+    last if m/^--$/;
+    if ($_ eq '--debug') {
+       open DEBUG, ">&STDOUT" or die $!;
+       select(DEBUG); $|=1; select(STDOUT);
+    } elsif ($_ eq '--stdin-chart') {
+       $stdin_chart=1;
+    } else {
+       die;
+    }
 }
-select(STDOUT); $|=1;
+$|=1;
 
 @ARGV==1 or die;
-$ARGV[0] =~ m/^\-/ and die;
 my $ocean= shift @ARGV;
 
 
@@ -381,11 +390,13 @@ sub compare_island_lists () {
     foreach my $island (sort keys %wiisland2node) {
        my $wtarch= $wtisland2arch{$island};
        my $wiarch= wiisland2arch($island);
-       if (!defined $wtarch) {
-           error("island from chart not found on ocean page: $island");
-       } elsif (defined $wiarch and $wtarch ne $wiarch) {
-           error("island in $wtarch on ocean page but".
-                 " concluded $wiarch from chart: $island");
+       if (!$stdin_chart) {
+           if (!defined $wtarch) {
+               error("island from chart not found on ocean page: $island");
+           } elsif (defined $wiarch and $wtarch ne $wiarch) {
+               error("island in $wtarch on ocean page but".
+                     " concluded $wiarch from chart: $island");
+           }
        }
 
        my $dbarch= $dbisland2arch{$island};
@@ -399,10 +410,12 @@ sub compare_island_lists () {
            change("island new in $wiarch: $island");
        }
     }
-    foreach my $island (sort keys %wtisland2arch) {
-       my $node= $wiisland2node{$island};
-       next if defined $node;
-       error("island on ocean page but not in chart: $island");
+    if (!$stdin_chart) {
+       foreach my $island (sort keys %wtisland2arch) {
+           my $node= $wiisland2node{$island};
+           next if defined $node;
+           error("island on ocean page but not in chart: $island");
+       }
     }
 }
 
@@ -423,7 +436,8 @@ sub shortest_path_reduction ($$) {
 
     1. F is an undirected weighted graph with positive edge weights.
 
-    2. All graphs we will consider have the same vertices as F.
+    2. All graphs we will consider have the same vertices as F
+       and none have self-edges.
 
     3. G = Closure(F) is the graph of cliques whose edge weights
        are the shortest paths in F, one clique for each connected
@@ -480,6 +494,7 @@ END
 
     my $result= Graph::Undirected->new();
     foreach my $edge_ac ($g->edges()) {
+        next if $edge_ac->[0] eq $edge_ac->[1];
        my $edgename_ac= join ' .. ', @$edge_ac;
        printf DEBUG "spr %s edge %s\n", $what, $edgename_ac;
        my $w_ac= $g->get_edge_weight(@$edge_ac);
@@ -544,9 +559,14 @@ sub yppedia_ocean_fetch_done () {
 }
 
 sub yppedia_ocean_fetch_chart () {
-    yppedia_ocean_fetch_start(1);
-    yppedia_chart_parse();
-    yppedia_ocean_fetch_done();
+    if ($stdin_chart) {
+       open OCEAN, "<& STDIN" or die $!;
+       yppedia_chart_parse();
+    } else {
+       yppedia_ocean_fetch_start(1);
+       yppedia_chart_parse();
+       yppedia_ocean_fetch_done();
+    }
 }
 
 sub yppedia_ocean_fetch_text () {
@@ -619,6 +639,82 @@ sub database_graph_spr () {
     $dbspr= shortest_path_reduction('db',$dbdists);
 }
 
+sub database_do_updates () {
+    my $addisland= $dbh->prepare(<<'END')
+ INSERT OR IGNORE INTO islands (islandname, archipelago) VALUES (?, ?);
+END
+    ;
+    foreach my $island (sort keys %wiisland2node) {
+       my $wiarch= wiisland2arch($island);
+       $addisland->execute($island, $wiarch);
+    }
+
+    db_doall(<<END)
+ DELETE FROM dists;
+ DELETE FROM routes;
+END
+    ;
+    my $adddist= $dbh->prepare(<<'END')
+ INSERT INTO dists VALUES
+       ((SELECT islandid FROM islands WHERE islandname == ?),
+        (SELECT islandid FROM islands WHERE islandname == ?),
+        ?);
+END
+    ;
+    my $addroute= $dbh->prepare(<<'END')
+ INSERT INTO routes VALUES
+       ((SELECT islandid FROM islands WHERE islandname == ?),
+        (SELECT islandid FROM islands WHERE islandname == ?),
+        ?);
+END
+    ;
+    foreach my $ia (sort keys %wiisland2node) {
+       my $na= $wiisland2node{$ia};
+       foreach my $ib (sort keys %wiisland2node) {
+           my $nb= $wiisland2node{$ib};
+           my $apdist= $ia eq $ib ? 0 : widist($na,$nb);
+           die "$ia $ib" unless defined $apdist;
+           my $sprdist= $wispr->get_edge_weight($ia,$ib);
+           die "$ia $ib $apdist $sprdist" if
+               defined($sprdist) && $sprdist != $apdist;
+
+           $adddist->execute($ia,$ib,$apdist);
+           $addroute->execute($ia,$ib,$sprdist) if defined $sprdist;
+       }
+    }
+
+    # select ia.islandname, ib.islandname, d.dist from dists as d, islands as ia on d.aiid = ia.islandid, islands as ib on d.biid = ib.islandid order by ia.islandname, ib.islandname;
+    
+}
+
+#========== update _ocean-*.txt ==========
+
+our $localtopo_path;
+
+sub localtopo_rewrite () {
+    $localtopo_path= '_ocean-'.(lc $ocean).'.txt';
+    my $fh= new IO::File "$localtopo_path.tmp", 'w';
+    print $fh "# autogenerated - do not edit\n" or die $!;
+    print $fh "ocean $ocean\n" or die $!;
+    my %arches;
+    foreach my $isle (sort keys %wtisland2arch) {
+       my $arch= $wtisland2arch{$isle};
+       push @{ $arches{$arch} }, $isle;
+    }
+    foreach my $arch (sort keys %arches) {
+       print $fh " $arch\n" or die $!;
+       foreach my $isle (@{ $arches{$arch} }) {
+           print $fh "  $isle\n" or die $!;
+       }
+    }
+    print $fh "\n" or die $!;
+    close $fh or die $!;
+}
+
+sub localtopo_commit () {
+    rename "$localtopo_path.tmp", $localtopo_path or die $!;
+}
+
 #========== main program ==========
 
 parse_info_serverside();
@@ -632,7 +728,10 @@ progress("computing shortest paths");       yppedia_graph_shortest_paths();
 progress("setting archs from labels");      yppedia_archs_chart_labels();
 progress("setting archs from nearby");      yppedia_archs_fillbynearest();
 progress("computing yppedia spr");          yppedia_graph_spr();
-progress("fetching yppedia ocean text");    yppedia_ocean_fetch_text();
+
+if (!$stdin_chart) {
+    progress("fetching yppedia ocean text");    yppedia_ocean_fetch_text();
+}
 
 db_setocean($ocean);
 db_connect();
@@ -662,15 +761,24 @@ for (;;) {
     if (!%msgkindprinted) {
        progress("updating database");         database_do_updates();
        progress("updating _ocean-*.txt");     localtopo_rewrite();
+       if ($stdin_chart) {
+           print STDERR "*** --stdin-chart, aborting!\n";
+           exit 1;
+       }
        progress("committing database");       $dbh->commit();
        progress("committing _ocean-*.txt");   localtopo_commit();
        exit 0;
     }
     $dbh->rollback();
-    
+
     my $default= !$msgkindprinted{'warning'};
     printf STDERR "*** confirm update %s ? ", $default?'(y/n)':'(n/y)';
 
+    if ($stdin_chart) {
+       printf STDERR "[--stdin-chart]\n";
+       exit 1;
+    }
+
     $!=0; my $result= <STDIN>;  defined $result or die $!;
     $result =~ s/\s//g;
     $result= $default?'y':'n' if !length $result;