chiark / gitweb /
export some more stuff from Parse
[pandemic-rising-tide.git] / Parse.pm
1
2 package Parse;
3
4 use strict;
5 use Carp;
6 use Graph;
7
8 use Exporter;
9
10 our @ISA = qw(Exporter);
11 our @EXPORT = qw(parse_input_graph o plag_prs %region %adj);
12
13 our %region;
14 # $region{NAME}{Colour}
15 # $region{NAME}{Water}
16 # $region{NAME}{L} # line number
17 # $region{NAME}{Adj}[]{Name}
18 # $region{NAME}{Adj}[]{Pattern}
19 # $region{NAME}{Adj}[]{Regexp}
20 # $region{NAME}{Adj}[]{Dikes}
21 # $region{NAME}{Adj}[]{L}
22
23 our %adj;
24 # $adj{EARLIER}{LATER}{Dikes}
25 # $adj{EARLIER}{LATER}{L}[]
26 # $adj{EARLIER}{LATER}{T}[]
27
28 sub read_in () {
29   my $ccolour;
30   my $cregion;
31
32   while (<>) {
33     next if m{^\s*\#};
34     next unless m{\S};
35     s{\s+$}{} or confess;
36     if (m{^\w+}) {
37       $ccolour = $&;
38       next;
39     }
40     if (my ($name, $water) = m{^\t(\S.*\w|L)(?: \[(\d+)\])?$}) {
41       confess unless defined $ccolour;
42       confess "$name ?" if $region{$name};
43       $region{$name}{Colour} = $ccolour;
44       $region{$name}{Water} = $water;
45       $region{$name}{L} = $.;
46       $cregion = $name;
47       next;
48     }
49     if (my ($aref, $adikes) = m{^\t\t(\S.*[A-Za-z.]|L)(?: (\+\+?))?$}) {
50       my $adj = { Dikes => (length $adikes // 0), L => $. };
51       if ($aref =~ m{\.}) {
52         $adj->{Pattern} = $aref;
53         $aref =~ s{\-}{[^- ]*-}g;
54         $aref =~ s{\.+}{
55             length $& eq 1 ? qr{[^- ]* ?} :
56             length $& eq 2 ? qr{.*}       : confess "$aref"
57         }ge;
58         $adj->{Regexp} = $aref;
59       } else {
60         $adj->{Name} = $aref;
61       }
62       push @{ $region{$cregion}{Adj} }, $adj;
63       next;
64     }
65     confess "$_ ?";
66   }
67 }
68
69 sub unique_aref ($$) {
70   my ($ra, $adja) = @_;
71   my $re = $adja->{Regexp};
72   return $adja->{Name} unless defined $re;
73   my @cands;
74   foreach my $rb (sort keys %region) {
75     #print STDERR "?? $ra -> $re $rb ?\n";
76     foreach my $adjb (@{ $region{$rb}{Adj} }) {
77       my $adjbn = $adjb->{Name};
78       next unless defined $adjbn;
79       #print STDERR "?? $ra -> $re $rb ?? $adjbn\n";
80       next unless $adjbn eq $ra;
81       push @cands, [ $rb, "$region{$rb}{L},$adjb->{L}" ];
82     }
83   }
84   my @found = grep { $_->[0] =~ m{^$re$} } @cands;
85   my $pr = sub {
86     join ' / ', map { "$_->[0] ($_->[1])" } @_;
87   };
88   confess "$adja->{L} $adja->{Pattern} /$re/ | ".$pr->(@cands)
89       ." | ".$pr->(@found)." | ?"
90       unless @found==1;
91   my $r = $found[0][0];
92   #print STDERR "resolve $ra -> $adja->{Pattern} = $r\n";
93   return $r;
94 }
95
96 sub region_cmp {
97   ($a eq 'L' ) <=> ($b eq 'L' ) or
98   ($a eq 'NZ') <=> ($b eq 'NZ') or
99    $a          cmp  $b
100 }
101
102 sub resolve_arefs () {
103   #print Dumper(\%region);
104   foreach my $ra (sort keys %region) {
105     foreach my $adj (@{ $region{$ra}{Adj} }) {
106       next if defined $adj->{Name};
107       $adj->{ProspectiveName} = unique_aref $ra, $adj;
108     }
109   }
110   foreach my $ra (sort keys %region) {
111     foreach my $adj (@{ $region{$ra}{Adj} }) {
112       $adj->{Name} //= $adj->{ProspectiveName};
113     }
114   }
115   foreach my $ra (sort keys %region) {
116     foreach my $adj (@{ $region{$ra}{Adj} }) {
117       confess unless $adj->{Name} eq unique_aref $ra, $adj;
118     }
119   }
120 }
121
122 sub adjacencies () {
123   foreach my $ra (sort keys %region) {
124     my $adjs = $region{$ra}{Adj};
125     foreach my $adji (0..$#$adjs) {
126       my $adja = $adjs->[$adji];
127       my $rb = $adja->{Name};
128       my ($r0,$r1) = sort region_cmp ($ra,$rb);
129       push @{ $adj{$r0}{$r1}{L} }, $adja->{L};
130       push @{ $adj{$r0}{$r1}{T} }, substr($ra,0,1)."#".$adji;
131       my $e = $adj{$r0}{$r1};
132       $e->{Dikes} //= $adja->{Dikes};
133       confess "$r0 - $r1 | @{ $e->{L} } | $e->{Dikes} $adja->{Dikes} ?"
134           unless $e->{Dikes} == $adja->{Dikes};
135     }
136   }
137   my $ndikes = 0;
138   foreach my $r0 (sort keys %adj) {
139     foreach my $r1 (sort keys %{ $adj{$r0} }) {
140       my $e = $adj{$r0}{$r1};
141       confess "$r0 / $r1 : @{ $e->{L} } ?" unless @{ $e->{L} } == 2;
142       $ndikes += $e->{Dikes};
143     }
144   }
145   #print STDERR "total $ndikes dikes\n";
146 }
147
148 sub edge_id_to_other_id ($$) {
149   my ($ra, $adjia) = @_;
150   my $adjsa = $region{$ra}{Adj};
151   my $adja = $adjsa->[$adjia];
152   my $rb = $adja->{Name};
153   my $adjsb = $region{$rb}{Adj};
154   foreach my $adjib (0..$#$adjsb) {
155     my $adjb = $adjsb->[$adjib];
156     next unless $adjb->{Name} eq $ra;
157     # $adjb is the same edge seen from the other side
158     return ($rb, $adjib);
159   }
160   confess "$ra $adjia ?";
161 }
162
163 sub o { print @_ or die $!; }
164
165 sub plag_prs ($) {
166     my ($t) = @_;
167     $t = $` if $t =~ m/\n/;
168     $t =~ s/ //g;
169     $t =~ s/-//g;
170     return "$t";
171 }
172
173 sub parse_input_graph () {
174   read_in();
175   resolve_arefs();
176   adjacencies();
177 }
178
179 1;