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 print "\$g->add_vertex('$n');\n";
78 printf PO "%d,%d island %s\n", $x,$y,$island;
79 } elsif (($solid,$x,$y,$dirn) =
80 m/^\{\{ chart\ league((?:\ solid)?) \|(\d+)\|(\d+)\|
81 ([-\/\\o]) \| .*\}\}$/xi) {
84 my ($bx,$by) = ($x,$y);
85 if ($dirn eq '-') { $bx+=2; }
86 elsif ($dirn eq '\\') { $bx++; $by++; }
87 elsif ($dirn eq '/') { $x++; $by++; }
90 $widists->add_weighted_edge($nn->(), nn_xy($bx,$by), 1);
91 $wiarchs->add_edge($nn->(), nn_xy($bx,$by)) if $solid;
92 $wiarchs->add_edge($nn->(), nn_xy($bx,$by)) if $solid;
93 print "\$g->add_edge('".$nn->()."','".nn_xy($bx,$by)."');\n" if $solid;
95 printf PO "%d,%d league %s %s \n", $x,$y,
96 $solid?'solid':'dotted', $dirn;
98 m/^\{\{ chart\ head \}\}$/xi
102 warning("line $.: ignoring incomprehensible: $_");
107 sub parse_database_map () {
109 $sth= $dbh->prepare('SELECT islandname, archipelago FROM islands');
111 foreach $row ($sth->fetchrow_hashref) {
112 $dbisland2arch{$row->{'islandname'}}= $row->{'archipelago'};
114 $sth= $dbh->prepare('SELECT dist, a.islandname a, b.islandname b
116 JOIN islands AS a ON dists.aiid==a.islandid
117 JOIN islands AS b ON dists.biid==b.islandid');
119 foreach $row ($sth->fetchrow_hashref) {
120 $dbdists->add_weighted_edge($row->{'a'}, $row->{'b'}, $row->{'dist'});
124 sub process_yppedia_graphs () {
125 # Prune the LP database by eliminating boring intermediate vertices
126 foreach my $delete ($widists->vertices()) {
127 next if exists $winode2island{$delete};
128 my @neigh= $widists->neighbours($delete);
129 next unless @neigh==2;
130 # my @aneigh= $wiarchs->has_vertex($delete)
131 # ? $wiarchs->neighbours($delete) : ();
132 # next unless @aneigh==0 || @aneigh==2;
134 map { $weight += $widists->get_edge_weight($delete, $_) } @neigh;
135 $widists->add_weighted_edge(@neigh, $weight);
136 $widists->delete_vertex($delete);
137 # print PO "$delete elide $weight\n";
140 # Check that it's connected.
141 foreach my $cc ($widists->connected_components()) {
142 next if 2*@$cc > $widists->vertices();
143 my $m= "disconnected league point(s):";
144 foreach my $n (@$cc) {
145 $m .= "\n LP $n, def. yppedia line(s): ".
146 join(',', sort keys %{ $winode2lines{$n} });
151 # Compute all-pairs-shortest-paths on dist, which is the
152 # actual distances between all LPs.
153 my $wialldists= $widists->APSP_Floyd_Warshall();
156 foreach my $label (@wiarchlabels) {
157 my ($ax,$ay,$arch) = @$label;
160 foreach my $vertex ($wiarchs->vertices()) {
161 next unless exists $winode2island{$vertex};
162 my ($vx,$vy) = split /,/, $vertex;
163 my $d2= ($vx-$ax)*($vx-$ax) + ($vy-$ay)*($vy-$ay);
164 next unless $d2 < $d2best;
168 die 'no island vertices?!' unless defined $best;
169 printf PO "%d,%d arch-select-island %s %s\n",
170 $ax,$ay, $arch, $winode2island{$best};
171 my $ccix= $wiarchs->connected_component_by_vertex($best);
172 my $desc= join "\n", map {
173 my $in= $winode2island{$_};
174 " LP $_". (defined $in ? ", $in" : "");
175 } sort $wiarchs->connected_component_by_index($ccix);
177 if (exists $wiccix2arch{$ccix}) {
178 error("architecture determination failed:\n".
179 " archipelago $arch\n".
180 " archipelago $wiccix2arch{$ccix}\n".
184 $wiccix2arch{$ccix}= $arch;
185 # print "$ccix $arch ::\n$desc\n";
189 sub compare_island_lists () {
190 # foreach my $island (keys %dbisland2arch) {
191 # next if exists $winode2island
195 db_setocean('Midnight');
198 parse_database_map();
199 process_yppedia_graphs();
200 compare_island_lists();
202 printf "%d %d %d %d\n", $wiarchs->has_edge('32,17','33,18'),
203 $wiarchs->connected_component_by_vertex('32,17'),
204 $wiarchs->connected_component_by_vertex('33,18'),
205 $wiarchs->same_connected_components('32,17','33,18');