+my %islandpair;
+# $islandpair{$a,$b}= [ $start_island_ix, $end_island_ix ]
+
+my $specific= !grep { !defined $_ } @islandids;
+my $confusing= 0;
+
+foreach my $src_i (0..$#islandids) {
+ my $src_isle= $islandids[$src_i];
+ my $src_cond= $sd_condition->('sell',$src_i);
+ my @dst_conds;
+ foreach my $dst_i ($src_i..$#islandids) {
+ my $dst_isle= $islandids[$dst_i];
+ my $dst_cond= $sd_condition->('buy',$dst_i);
+ if ($dst_i==$src_i and !defined $src_isle) {
+ # we always want arbitrage, but mentioning an arch
+ # once shouldn't produce intra-arch trades
+ $dst_cond=
+ "($dst_cond AND sell.islandid = buy.islandid)";
+ }
+ push @dst_conds, $dst_cond;
+
+ if ($specific && !$confusing &&
+ # With a circular route, do not carry goods round the loop
+ !($src_i==0 && $dst_i==$#islandids &&
+ $src_isle == $islandids[$dst_i])) {
+ if ($islandpair{$src_isle,$dst_isle}) {
+ $confusing= 1;
+ } else {
+ $islandpair{$src_isle,$dst_isle}=
+ [ $src_i, $dst_i ];
+ }
+ }
+ }
+ push @flow_conds, "$src_cond AND (
+ ".join("
+ OR ",@dst_conds)."
+ )";
+}
+
+my $stmt= "
+ SELECT sell_islands.islandname org_name,
+ sell_islands.islandid org_id,
+ sell.price org_price,
+ buy_islands.islandname dst_name,
+ buy_islands.islandid dst_id,
+ buy.price dst_price,
+".($qa->{ShowStalls} ? "
+ sell.stallid org_stallid,
+ sell_stalls.stallname org_stallname,
+ sell.qty org_qty,
+ buy.stallid dst_stallid,
+ buy_stalls.stallname dst_stallname,
+ buy.qty dst_qty,
+" : "
+ sum(sell.qty) org_qty,
+ sum(buy.qty) dst_qty,
+")."
+ commods.commodname commodname,
+ commods.commodid commodid,
+ commods.unitmass unitmass,
+ commods.unitvolume unitvolume,
+ dist dist,
+ buy.price - sell.price unitprofit
+ FROM commods
+ JOIN buy on commods.commodid = buy.commodid
+ JOIN sell on commods.commodid = sell.commodid
+ JOIN islands as sell_islands on sell.islandid = sell_islands.islandid
+ JOIN islands as buy_islands on buy.islandid = buy_islands.islandid
+".($qa->{ShowStalls} ? "
+ JOIN stalls as sell_stalls on sell.stallid = sell_stalls.stallid
+ JOIN stalls as buy_stalls on buy.stallid = buy_stalls.stallid
+" : "")."
+ JOIN dists on aiid = sell.islandid AND biid = buy.islandid
+ WHERE (
+ ".join("
+ OR ", @flow_conds)."
+ )
+ AND buy.price > sell.price
+".($qa->{ShowStalls} ? "" : "
+ GROUP BY commods.commodid, org_id, org_price, dst_id, dst_price
+")."
+ ORDER BY org_name, dst_name, commodname, unitprofit DESC,
+ org_price, dst_price DESC
+ ";
+
+my $sth= $dbh->prepare($stmt);
+$sth->execute(@query_params);
+my @flows;
+
+my @cols= ({ NoSort => 1 });
+
+my $addcols= sub {
+ my $base= shift @_;
+ foreach my $name (@_) {
+ my $col= { Name => $name, %$base };
+ $col->{Numeric}=1 if !$col->{Text};
+ push @cols, $col;
+ }
+};
+
+if ($qa->{ShowStalls}) {
+ $addcols->({ Text => 1 }, qw(
+ org_name org_stallname
+ dst_name dst_stallname
+ ));
+} else {
+ $addcols->({Text => 1 }, qw(
+ org_name dst_name
+ ));
+}
+$addcols->({ Text => 1 }, qw(commodname));
+$addcols->({ DoReverse => 1 },
+ qw( org_price org_qty dst_price dst_qty
+ Margin unitprofit MaxQty
+ MaxCapital MaxProfit
+ ));
+
+</%perl>
+
+% if ($qa->{'debug'}) {