chiark / gitweb /
34fbc22e38d25584a078afd1caf05b78ed1b7497
[ypp-sc-tools.main.git] / yarrg / web / query_routesearch
1 <%doc>
2
3  This is part of the YARRG website.  YARRG is a tool and website
4  for assisting players of Yohoho Puzzle Pirates.
5
6  Copyright (C) 2009 Ian Jackson <ijackson@chiark.greenend.org.uk>
7  Copyright (C) 2009 Clare Boothby
8
9   YARRG's client code etc. is covered by the ordinary GNU GPL (v3 or later).
10   The YARRG website is covered by the GNU Affero GPL v3 or later, which
11    basically means that every installation of the website will let you
12    download the source.
13
14  This program is free software: you can redistribute it and/or modify
15  it under the terms of the GNU Affero General Public License as
16  published by the Free Software Foundation, either version 3 of the
17  License, or (at your option) any later version.
18
19  This program is distributed in the hope that it will be useful,
20  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  GNU Affero General Public License for more details.
23
24  You should have received a copy of the GNU Affero General Public License
25  along with this program.  If not, see <http://www.gnu.org/licenses/>.
26
27  Yohoho and Puzzle Pirates are probably trademarks of Three Rings and
28  are used without permission.  This program is not endorsed or
29  sponsored by Three Rings.
30
31
32  This Mason component generates the core of the `routesearch' query.
33
34
35 </%doc>
36 <%args>
37 $quri
38 $dbh
39 $islandstring => '';
40 $capacitystring => '';
41 $lossperleague => '';
42 $capitalstring => '';
43 $distance => '';
44 $someresults
45 $emsgokorprint
46 </%args>
47
48 <%perl>
49 use BSD::Resource;
50
51 my $emsg;
52 my @warningfs;
53 my @islandids;
54
55 my $qa= \%ARGS;
56 my $routeparams= { EmsgRef => \$emsg, SayRequiredCapacity => 1 };
57 my $maxdist;
58 my $maxcountea=10;
59
60 </%perl>
61
62 <h1>Find most profitable routes and trades</h1>
63
64 % if ($qa->{Dropdowns}) {
65 This feature is not available from the "drop down menus" interface.
66 % } else {
67
68 <form action="<% $quri->() |h %>" method="get">
69
70 <& enter_route, qa=>$qa, dbh=>$dbh, emsg_r=>\$emsg, warningfs_r=>\@warningfs,
71         enterwhat => 'Enter starting point(s)',
72         islandids_r => \@islandids, archipelagoes_r => undef
73  &>
74
75 <&| enter_advrouteopts, qa=>$qa, dbh=>$dbh, routeparams=>$routeparams &>
76 <td>
77 &nbsp;
78 &nbsp;
79 <td>
80  Maximum distance:
81  <&| qtextstring, qa => $qa, dbh => $dbh, prefix => 'ml',
82     thingstring => 'distance', emsgstore => \$emsg,
83     onresults => sub { ($maxdist)= @_; } &>
84    size=10
85  </&>
86 </&>
87
88 <input type=submit name=submit value="Go">
89 % my $ours= sub { $_[0] =~ m/^lossperleague|^islandstring|^capitalstring|^capacitystring|^distance/; };
90 <& "lookup:formhidden", ours => $ours &>
91
92 % }
93
94 </form>
95 <%perl>
96
97 if (!$emsg && $maxdist > 30) {
98         $emsg= "Searching for routes of more than 30 leagues is not".
99                 " supported, sorry.";
100 }
101
102 $emsgokorprint->($emsg) or return;
103 @islandids or return;
104 defined $routeparams->{MaxMass} or defined $routeparams->{MaxVolume} or return;
105
106 #---------- prepare island names ----------
107
108 my $islandname_stmt= $dbh->prepare(<<END);
109         SELECT islandname, archipelago
110           FROM islands
111          WHERE islandid = ?
112 END
113
114 my $isleinfo = sub {
115         my ($id) = @_;
116         $islandname_stmt->execute($id);
117         my $row= $islandname_stmt->fetchrow_hashref();
118         local $_= $row->{'islandname'};
119         s/ Island$//;
120         return $_, $row->{'archipelago'};
121 };
122
123 #---------- compute the results ----------
124
125 my @rsargs;
126
127 foreach my $k (qw(MaxMass MaxVolume MaxCapital)) {
128         my $v= $routeparams->{$k};
129         push @rsargs, (defined $v ? $v : -1);
130 }
131 push @rsargs, defined $routeparams->{LossPerLeaguePct}
132         ? $routeparams->{LossPerLeaguePct}*0.01 : 1e-9;
133 push @rsargs, 'search', $maxcountea,$maxcountea, $maxdist, 'any', @islandids;
134
135 m/[^-.0-9a-zA-Z]/ and die "$_ $& ?" foreach @rsargs;
136
137 unshift @rsargs, dbw_filename($qa->{'Ocean'});
138 unshift @rsargs, qw(-DN);
139
140 if ($qa->{'debug'}) {
141 </%perl>
142 [[ <% "@rsargs" |h %> ]]<br><pre>
143 <%perl>
144 }
145
146 unshift @rsargs, sourcebasedir().'/yarrg/routesearch';
147
148 my %results; # $results{$ap}{"5 6 9 10"} = { stuff }
149
150 my $fh= new IO::File;
151 my $child= $fh->open("-|"); defined $child or die $!;
152 if (!$child) {
153         my $cpu= BSD::Resource::RLIMIT_CPU;
154         my ($soft,$hard)= getrlimit($cpu);
155         my $max=10;
156         setrlimit($cpu,$max,$hard) or die $! if $soft>$max;
157         exec @rsargs;
158         die $!;
159 }
160
161 while (<$fh>) {
162         chomp;
163         if ($qa->{'debug'}) {
164 </%perl>
165 <% $_ |h %>
166 <%perl>
167         }
168         next unless
169   m/^ \@ *\d+ ([ap])\# *\d+ \|.*\| *\d+ +(\d+) +(\d+) *\| ([0-9 ]+)$/;
170         my ($ap,$isles) = (uc $1,$4);
171         next if $results{$ap} && %{$results{$ap}} >= $maxcountea;
172         my $item= { A => $2, P => $3 };
173         my (@i, @a);
174         foreach (split / /, $isles) {
175                 my ($name,$arch)= $isleinfo->($_);
176                 push @i, $name;
177                 push @a, $arch unless @a && $a[-1] eq $arch;
178         }
179         $item->{Isles}= [ @i ];
180         $item->{Archs}= [ @a ];
181         $item->{Start}= $i[0];
182         $item->{Finish}= $i[-1];
183         $item->{Vias}= [ ];
184         my $i;
185         for ($i=1; $i < @i-1; $i++) {
186                 push @{ $item->{Vias} }, $i[$i];
187         }
188         $results{$ap}{$isles}= $item;
189 }
190
191 if ($qa->{'debug'}) {
192         print "</pre>\n";
193 }
194
195 </%perl>
196 % foreach my $ap (qw(A P)) {
197 <h2>ap=<% $ap %></h2>
198 <table rules=groups>
199 <colgroup span=2>
200 <colgroup span=1>
201 <colgroup span=3>
202 <tbody>
203 <tr>
204 <th colspan=2>Profit
205 <th>Archipelagoes
206 <th colspan=3>Route
207 <tr>
208 <th>Abs.
209 <th>Per.lg.
210 <th>
211 <th>Start
212 <th>Via
213 <th>Finish
214 <tbody>
215 %       my $datarow=0;
216 %       foreach my $isles (sort {
217 %                       $results{$ap}{$b}{$ap} <=>
218 %                       $results{$ap}{$a}{$ap}
219 %               } keys %{$results{$ap}}) {
220 %               my $item= $results{$ap}{$isles};
221 <tr class="datarow<% $datarow %>">
222 <td align=right><% $item->{A} |h %>
223 <td align=right><% $item->{P} |h %>
224 <td align=left><% join ', ', @{ $item->{Archs} } |h %>
225 <td align=left><% $item->{Start} |h %>, 
226 <td align=left><% join ' ', map { $_.',' } @{ $item->{Vias} } |h %>
227 <td align=left><% $item->{Finish} |h %>
228 </td>
229 %               $datarow ^= 1;
230 %       } # $isles
231 </table>
232 % } # $ap
233 <%perl>
234
235
236 </%perl>