chiark / gitweb /
b6d543fae1c7c122c72485a36c5bf30146f4505b
[ypp-sc-tools.db-live.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 $maxmaxdist=35;
56 my $maxcpu=90;
57
58 my $qa= \%ARGS;
59 my $routeparams= { EmsgRef => \$emsg, SayRequiredCapacity => 1 };
60 my $maxdist;
61 my $maxcountea=10;
62
63 </%perl>
64
65 <h1>Find most profitable routes and trades</h1>
66
67 % if ($qa->{Dropdowns}) {
68 This feature is not available from the "drop down menus" interface.
69 % } else {
70
71 <form action="<% $quri->() |h %>" method="get">
72
73 <& enter_route, qa=>$qa, dbh=>$dbh, emsg_r=>\$emsg, warningfs_r=>\@warningfs,
74         enterwhat => 'Enter starting point(s)',
75         islandids_r => \@islandids, archipelagoes_r => undef
76  &>
77
78 <&| enter_advrouteopts, qa=>$qa, dbh=>$dbh, routeparams=>$routeparams &>
79 <td>
80 &nbsp;
81 &nbsp;
82 <td>
83  Maximum distance:
84  <&| qtextstring, qa => $qa, dbh => $dbh, prefix => 'ml',
85     thingstring => 'distance', emsgstore => \$emsg,
86     onresults => sub { ($maxdist)= @_; } &>
87    size=10
88  </&>
89 </&>
90
91 <input type=submit name=submit value="Go">
92 % my $ours= sub { $_[0] =~ m/^lossperleague|^islandstring|^capitalstring|^capacitystring|^distance/; };
93 <& "lookup:formhidden", ours => $ours &>
94
95 % }
96
97 </form>
98 <%perl>
99
100 if (!$emsg && $maxdist > $maxmaxdist) {
101         $emsg= "Searching for routes of more than $maxmaxdist leagues is not".
102                 " supported, sorry.";
103 }
104
105 $emsgokorprint->($emsg) or return;
106 @islandids or return;
107 defined $routeparams->{MaxMass} or defined $routeparams->{MaxVolume} or return;
108
109 #---------- prepare island names ----------
110
111 my $islandname_stmt= $dbh->prepare(<<END);
112         SELECT islandname, archipelago
113           FROM islands
114          WHERE islandid = ?
115 END
116
117 my $isleinfo = sub {
118         my ($id) = @_;
119         $islandname_stmt->execute($id);
120         my $row= $islandname_stmt->fetchrow_hashref();
121         local $_= $row->{'islandname'};
122         s/ Island$//;
123         return $_, $row->{'archipelago'};
124 };
125
126 #---------- compute the results ----------
127
128 my @rsargs= qw(-DN);
129
130 foreach my $k (qw(MaxMass MaxVolume MaxCapital)) {
131         my $v= $routeparams->{$k};
132         push @rsargs, (defined $v ? $v : -1);
133 }
134 push @rsargs, defined $routeparams->{LossPerLeaguePct}
135         ? $routeparams->{LossPerLeaguePct}*0.01 : 1e-9;
136 push @rsargs, '0';
137 push @rsargs, 'search',$maxdist, $maxcountea,$maxcountea, 'any', @islandids;
138
139 m/[^-.0-9a-zA-Z]/ and die "$_ $& ?" foreach @rsargs;
140
141 if ($qa->{'debug'}) {
142 </%perl>
143 [[ <% "@rsargs" |h %> ]]<br><pre>
144 <%perl>
145 }
146
147 unshift @rsargs, sourcebasedir().'/yarrg/routesearch',
148         '-d', dbw_filename($qa->{'Ocean'});
149
150 my %results; # $results{$ap}{"5 6 9 10"} = { stuff }
151
152 my $fh= new IO::File;
153 my $child= $fh->open("-|"); defined $child or die $!;
154 if (!$child) {
155         my $cpu= BSD::Resource::RLIMIT_CPU;
156         my ($soft,$hard)= getrlimit($cpu);
157         setrlimit($cpu,$maxcpu,$hard) or die $! if $hard<=$maxcpu;
158         exec @rsargs;
159         die $!;
160 }
161
162 while (<$fh>) {
163         chomp;
164         if ($qa->{'debug'}) {
165 </%perl>
166 <% $_ |h %>
167 <%perl>
168         }
169         next unless
170   m/^ \@ *\d+ ([ap])\# *\d+ \|.*\| *\d+ +(\d+) +(\d+) *\| ([0-9 ]+)$/;
171         my ($ap,$isles) = (uc $1,$4);
172         next if $results{$ap} && %{$results{$ap}} >= $maxcountea;
173         my $item= { A => $2, P => $3 };
174         my (@i, @a);
175         foreach (split / /, $isles) {
176                 my ($name,$arch)= $isleinfo->($_);
177                 push @i, $name;
178                 push @a, $arch unless @a && $a[-1] eq $arch;
179         }
180         $item->{Isles}= [ @i ];
181         $item->{Archs}= [ @a ];
182         $item->{Start}= $i[0];
183         $item->{Finish}= $i[-1];
184         $item->{Vias}= [ ];
185         my $i;
186         for ($i=1; $i < @i-1; $i++) {
187                 push @{ $item->{Vias} }, $i[$i];
188         }
189         $results{$ap}{$isles}= $item;
190 }
191
192 if ($qa->{'debug'}) {
193         print "</pre>\n";
194 }
195
196 </%perl>
197 % foreach my $ap (qw(A P)) {
198 <h2>ap=<% $ap %></h2>
199 <table rules=groups>
200 <colgroup span=2>
201 <colgroup span=1>
202 <colgroup span=3>
203 <tbody>
204 <tr>
205 <th colspan=2>Profit
206 <th>Archipelagoes
207 <th colspan=3>Route
208 <tr>
209 <th>Abs.
210 <th>Per.lg.
211 <th>
212 <th>Start
213 <th>Via
214 <th>Finish
215 <tbody>
216 %       my $datarow=0;
217 %       foreach my $isles (sort {
218 %                       $results{$ap}{$b}{$ap} <=>
219 %                       $results{$ap}{$a}{$ap}
220 %               } keys %{$results{$ap}}) {
221 %               my $item= $results{$ap}{$isles};
222 <tr class="datarow<% $datarow %>">
223 <td align=right><% $item->{A} |h %>
224 <td align=right><% $item->{P} |h %>
225 <td align=left><% join ', ', @{ $item->{Archs} } |h %>
226 <td align=left><% $item->{Start} |h %>,
227 <td align=left><% join ' ', map { $_.',' } @{ $item->{Vias} } |h %>
228 <td align=left><% $item->{Finish} |h %>
229 </td>
230 %               $datarow ^= 1;
231 %       } # $isles
232 </table>
233 % } # $ap
234 <%perl>
235
236
237 </%perl>