+% {
+<& dumptable:start, qa => $qa, sth => $sth &>
+% my $flow;
+% while ($flow= $sth->fetchrow_hashref()) {
+% $flow->{Ix}= @flows;
+% $flow->{Var}= "f$flow->{Ix}";
+% push @flows, $flow;
+<& dumptable:row, qa => $qa, sth => $sth, row => $flow &>
+% }
+<& dumptable:end, qa => $qa &>
+% }
+
+% my $optimise= $specific && !$confusing && @islandids>1;
+% if (!$optimise) {
+
+<p>
+% if (@islandids<=1) {
+Route is trivial.
+% }
+% if (!$specific) {
+Route contains archipelago(es), not just specific islands.
+% }
+% if ($confusing) {
+Route is complex - it visits the same island several times
+and isn't a simple loop.
+% }
+Therefore, optimal trade pattern not calculated.
+
+% } else { # ========== OPTMISATION ==========
+<%perl>
+
+my $cplex= "
+Maximize
+
+ totalprofit:
+ ".(join " +
+ ", map { "$_->{unit_profit} $_->{Var}" } @flows)."
+
+Subject To
+";
+
+my %avail_csts;
+foreach my $flow (@flows) {
+ foreach my $od (qw(org dst)) {
+ my $cstname= join '_',
+ 'avail',
+ $flow->{'commodid'},
+ $od,
+ $flow->{"${od}_id"},
+ $flow->{"${od}_price"};
+ push @{ $avail_csts{$cstname}{Flows} }, $flow->{Var};
+ $avail_csts{$cstname}{Qty}= $flow->{"${od}_qty"};
+ }
+}
+foreach my $cstname (sort keys %avail_csts) {
+ my $c= $avail_csts{$cstname};
+ $cplex .= "
+ ". sprintf("%-30s","$cstname:")." ".
+ join("+", @{ $c->{Flows} }).
+ " <= ".$c->{Qty}."\n";
+}
+
+$cplex.= "
+Bounds
+ ".(join "
+ ", map { "$_->{Var} >= 0" } @flows)."
+
+End
+";
+
+if ($qa->{'debug'}) {
+</%perl>
+<pre>
+<% $cplex |h %>
+</pre>
+<%perl>
+}
+
+{
+ my $input= pipethrough_prep();
+ print $input $cplex or die $!;
+ my $output= pipethrough_run_along($input, undef, 'glpsol',
+ qw(glpsol --cpxlp /dev/stdin -o /dev/stdout));
+ print "<pre>\n" if $qa->{'debug'};
+ my $found_section= 0;
+ while (<$output>) {
+ print encode_entities($_) if $qa->{'debug'};
+ if (m/^\s*No\.\s+Column name\s+St\s+Activity\s/) {
+ die if $found_section>0;
+ $found_section= 1;
+ next;
+ }
+ next unless $found_section==1;
+ next if m/^[- ]+$/;
+ if (!/\S/) {
+ $found_section= 2;
+ next;
+ }
+ my ($ix, $qty) =
+ m/^\s*\d+\s+f(\d+)\s+\S+\s+(\d+)\s/ or die "$_ ?";
+ my $flow= $flows[$ix] or die;
+ $flow->{OptQty}= $qty;
+ $flow->{OptProfit}= $flow->{'unitprofit'} * $qty;
+ $flow->{OptCapital}= $flow->{OptQty} * $flow->{'org_price'};
+ }
+ print "</pre>\n" if $qa->{'debug'};
+ pipethrough_run_finish($output, 'glpsol');
+ die unless $found_section;
+};
+
+print join ' ', map { $_->{Optimal} } @flows;
+
+push @columns, qw(OptQty OptCapital OptProfit);
+
+</%perl>
+
+% } # ========== OPTIMISATION ==========
+
+% {
+% my $cdspan= $qa->{ShowStalls} ? ' colspan=2' : '';
+% my $cdstall= $qa->{ShowStalls} ? '<th>Stall</th>' : '';
+<table>
+<tr>
+<th<% $cdspan %>>Collect
+<th<% $cdspan %>>Deliver
+<th>
+<th colspan=2>Collect
+<th colspan=2>Deliver
+<th colspan=2>Profit
+<th colspan=3>Max
+% if ($optimise) {
+<th colspan=3>Suggested
+% }
+
+<tr>
+<th>Island <% $cdstall %>
+<th>Island <% $cdstall %>
+<th>Commodity
+<th>Price
+<th>Qty
+<th>Price
+<th>Qty
+<th>Unit
+<th>Margin
+<th>Qty
+<th>Capital
+<th>Profit
+% if ($optimise) {
+<th>Qty
+<th>Capital
+<th>Profit
+% }
+% }
+
+% foreach my $flow (@flows) {
+<tr>
+% foreach my $col (@columns) {
+% $flow->{MaxQty}= $flow->{'org_qty'} < $flow->{'dst_qty'}
+% ? $flow->{'org_qty'} : $flow->{'dst_qty'};
+% $flow->{MaxProfit}= $flow->{MaxQty} * $flow->{'unitprofit'};
+% $flow->{PctProfit}= sprintf "%3.1f%%",
+% $flow->{'dst_price'} * 100.0 / $flow->{'org_price'}
+% - 100.0;
+% $flow->{MaxCapital}= $flow->{MaxQty} * $flow->{'org_price'};
+<td><% $flow->{$col} |h %>
+% }
+% }
+</table>