chiark / gitweb /
Much tidying; preserve query type etc. in query_commod
[ypp-sc-tools.db-live.git] / yarrg / db-idempotent-populate
1 #!/usr/bin/perl -w
2 #
3 # usage: ./db-idempotent-populate <Oceanname>
4 #  creates or updates OCEAN-Oceanname.db
5 #  from master-master.txt
6
7 # This is part of ypp-sc-tools, a set of third-party tools for assisting
8 # players of Yohoho Puzzle Pirates.
9 #
10 # Copyright (C) 2009 Ian Jackson <ijackson@chiark.greenend.org.uk>
11 #
12 # This program is free software: you can redistribute it and/or modify
13 # it under the terms of the GNU General Public License as published by
14 # the Free Software Foundation, either version 3 of the License, or
15 # (at your option) any later version.
16 #
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 # GNU General Public License for more details.
21 #
22 # You should have received a copy of the GNU General Public License
23 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 #
25 # Yohoho and Puzzle Pirates are probably trademarks of Three Rings and
26 # are used without permission.  This program is not endorsed or
27 # sponsored by Three Rings.
28
29 use strict (qw(vars));
30
31 use DBI;
32
33 use Commods;
34 use CommodsDatabase;
35
36 @ARGV==1 or die;
37 my ($oceanname) = @ARGV;
38
39 #---------- setup ----------
40
41 parse_info_serverside();
42 parse_info_serverside_ocean($oceanname);
43 our $ocean= $oceans{$oceanname};
44
45 db_setocean($oceanname);
46 db_writer();
47 db_connect();
48
49 #---------- schema ----------
50
51 foreach my $bs (qw(buy sell)) {
52     db_doall(<<END)
53  CREATE TABLE IF NOT EXISTS $bs (
54         commodid        INTEGER                 NOT NULL,
55         islandid        INTEGER                 NOT NULL,
56         stallid         INTEGER                 NOT NULL,
57         price           INTEGER                 NOT NULL,
58         qty             INTEGER                 NOT NULL,
59         PRIMARY KEY (commodid, islandid, stallid)
60  );
61  CREATE INDEX IF NOT EXISTS ${bs}_by_island ON $bs (commodid, islandid, price);
62  CREATE INDEX IF NOT EXISTS ${bs}_by_price  ON $bs (commodid, price, islandid);
63 END
64     ;
65 }
66
67 db_doall(<<END)
68  CREATE TABLE IF NOT EXISTS commods (
69         commodid        INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
70         commodname      TEXT    UNIQUE          NOT NULL,
71         unitmass        INTEGER,
72         unitvolume      INTEGER
73  );
74  CREATE TABLE IF NOT EXISTS islands (
75         islandid        INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
76         islandname      TEXT    UNIQUE          NOT NULL,
77         archipelago     TEXT                    NOT NULL
78  );
79  CREATE TABLE IF NOT EXISTS stalls (
80         stallid         INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
81         islandid        INTEGER                 NOT NULL,
82         stallname       TEXT                    NOT NULL,
83         UNIQUE (islandid, stallname)
84  );
85  CREATE TABLE IF NOT EXISTS uploads (
86         islandid        INTEGER PRIMARY KEY     NOT NULL,
87         timestamp       INTEGER                 NOT NULL,
88         message         TEXT                    NOT NULL,
89         clientspec      TEXT                    NOT NULL,
90         serverspec      TEXT                    NOT NULL
91  );
92  CREATE TABLE IF NOT EXISTS dists (
93         aiid            INTEGER                 NOT NULL,
94         biid            INTEGER                 NOT NULL,
95         dist            INTEGER                 NOT NULL,
96         PRIMARY KEY (aiid, biid)
97  );
98 END
99     ;
100
101 $dbh->commit;
102
103 #---------- commodity list ----------
104
105 {
106     my $sth= $dbh->prepare(<<'END')
107  INSERT OR IGNORE INTO commods (commodname) VALUES (?);
108 END
109     ;
110     foreach my $commod (sort keys %commods) {
111         $sth->execute($commod);
112     }
113     $dbh->commit;
114 }
115
116 #---------- island list ----------
117
118 {
119     my $sth= $dbh->prepare(<<'END')
120  INSERT OR IGNORE INTO islands (islandname, archipelago) VALUES (?, ?);
121 END
122     ;
123     foreach my $archname (sort keys %$ocean) {
124         my $arch= $ocean->{$archname};
125         foreach my $islandname (sort keys %$arch) {
126             $sth->execute($islandname, $archname);
127         }
128     }
129     $dbh->commit;
130 }
131
132 #---------- routes ----------
133
134 {
135     foreach my $islandname (sort keys %{ $route_mysteries{$oceanname} }) {
136         warn "$route_mysteries{$oceanname}{$islandname} routes".
137             " for unknown island $islandname\n";
138     }
139
140     my $allroutes= $routes{$oceanname};
141
142     my @propqueue= ();
143
144     sub distance_set_propagate ($$$$) {
145         my ($lev, $start, $upto, $start2upto) = @_;
146         $allroutes->{$start}{$upto}= $start2upto;
147         push @propqueue, [ $lev, $start, $upto ];
148     }
149
150     sub distance_propagate_now {
151         my ($lev, $start, $upto) = @_;
152         my $startref= $allroutes->{$start};
153         my $start2upto= $startref->{$upto};
154         my $uptoref=  $allroutes->{$upto};
155
156         for my $next (keys %$uptoref) {
157             next if $next eq $upto;
158             my $unext= $uptoref->{$next};
159             next unless defined $unext;
160             distance_update("${lev}p", $start, $next, $start2upto + $unext);
161         }
162     }
163
164     sub distance_update ($$$$) {
165         my ($lev, $x, $y, $newdist) = @_;
166         distance_update_one("${lev}x",$x,$y,$newdist);
167         distance_update_one("${lev}y",$y,$x,$newdist);
168     }
169
170     sub distance_update_one ($$$$) {
171         my ($lev, $x, $y, $newdist) = @_;
172         my $xref= $allroutes->{$x};
173         my $currently= $xref->{$y};
174         return if defined($currently) and $currently <= $newdist;
175         distance_set_propagate("${lev}o",$x,$y,$newdist);
176     }
177
178     foreach my $xn (keys %$allroutes) {
179         my $routes= $allroutes->{$xn};
180         distance_set_propagate('0', $xn, $xn, 0);
181         foreach my $yn (keys %$routes) {
182             distance_set_propagate('0', $yn, $yn, 0);
183             distance_set_propagate('X', $xn, $yn, $routes->{$yn});
184             distance_set_propagate('Y', $yn, $xn, $routes->{$yn});
185         }
186     }
187     my $ref;
188     while ($ref= shift @propqueue) {
189         distance_propagate_now(@$ref);
190     }
191
192     db_doall(<<END)
193  DELETE FROM dists;
194 END
195     ;
196     my $sth= $dbh->prepare(<<'END')
197  INSERT INTO dists VALUES
198         ((SELECT islandid FROM islands WHERE islandname == ?),
199          (SELECT islandid FROM islands WHERE islandname == ?),
200          ?);
201 END
202     ;
203     foreach my $xn (keys %$allroutes) {
204         my $routes= $allroutes->{$xn};
205         foreach my $yn (keys %$routes) {
206             $sth->execute($xn, $yn, $routes->{$yn});
207         }
208     }
209     $dbh->commit();
210
211     # select ia.islandname, ib.islandname,dists.dist from dists, islands as ia on dists.aiid = ia.islandid, islands as ib on dists.biid = ib.islandid order by ia.islandname, ib.islandname;
212 }
213
214 __DATA__