10 my $widists= Graph::Undirected->new();
11 my $wiarchs= Graph::Undirected->new(unionfind => 1);
19 my $dbdists= Graph::Undirected->new();
25 print STDERR "warning: $m\n";
31 print STDERR "error: $m\n";
35 #open PO, ">/dev/null" or die $!;
36 open PO, ">&STDOUT" or die $!;
43 my $tp= (0+$x ^ 0+$y) & 1;
44 defined $parity or $parity=$tp;
45 $tp==$parity or warning("line $.: parity error $x,$y is $tp not $parity");
47 $winode2lines{$n}{$.}++;
51 sub parse_yppedia_map () {
52 # We don't even bother with tag soup; instead we do line-oriented parsing.
56 s/^\s*//; chomp; s/\s+$//; s/\s+/ /g;
58 s/\{\{Chart\ style\|[^{}]*\}\}//g;
59 next unless m/\{\{/; # only interested in chart template stuff
61 my ($x,$y, $arch,$island,$solid,$dirn);
62 my $nn= sub { return nn_xy($x,$y) };
65 m/^\{\{ chart\ label \|(\d+)\|(\d+)\| .*
66 \'\[\[ [^][\']* \| (\S+)\ archipelago \]\]\'*\}\}$/xi) {
67 printf PO "%d,%d arch %s\n", $x,$y,$arch;
68 push @wiarchlabels, [ $x,$y,$arch ];
69 } elsif (($x,$y,$island) =
70 m/^\{\{ chart\ island\ icon \|(\d+)\|(\d+)\|
71 ([^| ][^|]*[^| ]) \| .*\}\}$/xi) {
73 $wiisland2node{$island}= $n;
74 $winode2island{$n}= $island;
75 $widists->add_vertex($n);
76 $wiarchs->add_vertex($n);
77 printf PO "%d,%d island %s\n", $x,$y,$island;
78 } elsif (($solid,$x,$y,$dirn) =
79 m/^\{\{ chart\ league((?:\ solid)?) \|(\d+)\|(\d+)\|
80 ([-\/\\o]) \| .*\}\}$/xi) {
83 my ($bx,$by) = ($x,$y);
84 if ($dirn eq '-') { $bx+=2; }
85 elsif ($dirn eq '\\') { $bx++; $by++; }
86 elsif ($dirn eq '/') { $x++; $by++; }
89 $widists->add_weighted_edge($nn->(), nn_xy($bx,$by), 1);
90 $wiarchs->add_edge($nn->(), nn_xy($bx,$by)) if $solid;
92 printf PO "%d,%d league %s %s \n", $x,$y,
93 $solid?'solid':'dotted', $dirn;
95 m/^\{\{ chart\ head \}\}$/xi
99 warning("line $.: ignoring incomprehensible: $_");
104 sub parse_database_map () {
106 $sth= $dbh->prepare('SELECT islandname, archipelago FROM islands');
108 foreach $row ($sth->fetchrow_hashref) {
109 $dbisland2arch{$row->{'islandname'}}= $row->{'archipelago'};
111 $sth= $dbh->prepare('SELECT dist, a.islandname a, b.islandname b
113 JOIN islands AS a ON dists.aiid==a.islandid
114 JOIN islands AS b ON dists.biid==b.islandid');
116 foreach $row ($sth->fetchrow_hashref) {
117 $dbdists->add_weighted_edge($row->{'a'}, $row->{'b'}, $row->{'dist'});
121 sub process_yppedia_graphs () {
122 # Prune the LP database by eliminating boring intermediate vertices
123 foreach my $delete ($widists->vertices()) {
124 next if exists $winode2island{$delete};
125 my @neigh= $widists->neighbours($delete);
126 next unless @neigh==2;
127 # my @aneigh= $wiarchs->has_vertex($delete)
128 # ? $wiarchs->neighbours($delete) : ();
129 # next unless @aneigh==0 || @aneigh==2;
131 map { $weight += $widists->get_edge_weight($delete, $_) } @neigh;
132 $widists->add_weighted_edge(@neigh, $weight);
133 $widists->delete_vertex($delete);
134 # print PO "$delete elide $weight\n";
137 # Check that it's connected.
138 foreach my $cc ($widists->connected_components()) {
139 next if 2*@$cc > $widists->vertices();
140 my $m= "disconnected league point(s):";
141 foreach my $n (@$cc) {
142 $m .= "\n LP $n, def. yppedia line(s): ".
143 join(',', sort keys %{ $winode2lines{$n} });
148 # Compute all-pairs-shortest-paths on dist, which is the
149 # actual distances between all LPs.
150 my $wialldists= $widists->APSP_Floyd_Warshall();
153 foreach my $label (@wiarchlabels) {
154 my ($ax,$ay,$arch) = @$label;
157 foreach my $vertex ($wiarchs->vertices()) {
158 next unless exists $winode2island{$vertex};
159 my ($vx,$vy) = split /,/, $vertex;
160 my $d2= ($vx-$ax)*($vx-$ax) + ($vy-$ay)*($vy-$ay);
161 next unless $d2 < $d2best;
165 die 'no island vertices?!' unless defined $best;
166 printf PO "%d,%d arch-select-island %s %s\n",
167 $ax,$ay, $arch, $winode2island{$best};
168 my $ccix= $wiarchs->connected_component_by_vertex($best);
169 my $desc= join "\n", map {
170 my $in= $winode2island{$_};
171 " LP $_". (defined $in ? ", $in" : "");
172 } sort $wiarchs->connected_component_by_index($ccix);
174 if (exists $wiccix2arch{$ccix}) {
175 error("architecture determination failed:\n".
176 " archipelago $arch\n".
177 " archipelago $wiccix2arch{$ccix}\n".
181 $wiccix2arch{$ccix}= $arch;
182 print "$ccix $arch ::\n$desc\n";
186 sub compare_island_lists () {
187 # foreach my $island (keys %dbisland2arch) {
188 # next if exists $winode2island
192 db_setocean('Midnight');
195 parse_database_map();
196 process_yppedia_graphs();
197 compare_island_lists();
199 printf "%d %d %d %d\n", $wiarchs->has_edge('32,17','33,18'),
200 $wiarchs->connected_component_by_vertex('32,17'),
201 $wiarchs->connected_component_by_vertex('33,18'),
202 $wiarchs->same_connected_components('32,17','33,18');