+% if ($optimise) { # ========== TRADING PLAN ==========
+%
+% my $iquery= $dbh->prepare('SELECT islandname FROM islands
+% WHERE islandid = ?');
+% my %da_ages;
+% my $total_total= 0;
+% my $total_dist= 0;
+%
+<h1>Voyage trading plan</h1>
+<table rules=groups>
+% foreach my $i (0..$#islandids) {
+<tbody>
+<tr><td colspan=3>
+% $iquery->execute($islandids[$i]);
+% my ($islandname) = $iquery->fetchrow_array();
+% if (!$i) {
+<strong>Start at <% $islandname |h %></strong>
+% } else {
+% my $this_dist= $distance->($islandids[$i-1],$islandids[$i]);
+% $total_dist += $this_dist;
+<strong>Sail to <% $islandname |h %></strong>
+- <% $this_dist |h %> leagues </td>
+% }
+<%perl>
+ my $age_reported= 0;
+ my %flowlists;
+ foreach my $od (qw(org dst)) {
+ foreach my $f (@flows) {
+ next if $f->{Suppress};
+ next unless $f->{"${od}_id"} == $islandids[$i];
+ next unless $f->{OptQty};
+ my $arbitrage= $f->{'org_id'} == $f->{'dst_id'};
+ my $loop= $islandids[0] == $islandids[-1] &&
+ ($i==0 || $i==$#islandids);
+ next if $loop and ($arbitrage ? $i :
+ !!$i == !!($od eq 'org'));
+ my $price= $f->{"${od}_price"};
+ my $stallname= $f->{"${od}_stallname"};
+ my $todo= \$flowlists{$od}{
+ $f->{'commodname'},
+ (sprintf "%07d", ($od eq 'dst' ?
+ 9999999-$price : $price)),
+ $stallname
+ };
+ $$todo= {
+ Qty => 0,
+ orgArbitrage => 0,
+ dstArbitrage => 0,
+ } unless $$todo;
+ $$todo->{'commodname'}= $f->{'commodname'};
+ $$todo->{'stallname'}= $stallname;
+ $$todo->{Price}= $price;
+ $$todo->{Timestamp}= $f->{"${od}_timestamp"};
+ $$todo->{Qty} += $f->{OptQty};
+ $$todo->{Total}= $$todo->{Price} * $$todo->{Qty};
+ $$todo->{Stalls}= $f->{"${od}Stalls"};
+ $$todo->{"${od}Arbitrage"}= 1 if $arbitrage;
+ }
+ }
+
+ my ($total, $total_to_show);
+ my $dline= 0;
+ my $show_total= sub {
+ my ($totaldesc, $sign) = @_;
+ if (defined $total) {
+ die if defined $total_to_show;
+ $total_total += $sign * $total;
+ $total_to_show= [ $totaldesc, $total ];
+ $total= undef;
+ }
+ $dline= 0;
+ };
+ my $show_total_now= sub {
+ my ($xinfo) = @_;
+ return unless defined $total_to_show;
+ my ($totaldesc,$totalwas) = @$total_to_show;
+</%perl>
+<tr>
+<td colspan=1>
+<td colspan=2><% $xinfo %>
+<td colspan=2 align=right><% $totaldesc %>
+<td align=right><% $totalwas |h %> total
+<%perl>
+ $total_to_show= undef;
+ };
+</%perl>
+% my $show_flows= sub {
+% my ($od,$arbitrage,$collectdeliver) = @_;
+% my $todo= $flowlists{$od};
+% return unless $todo;
+% foreach my $tkey (sort keys %$todo) {
+% my $t= $todo->{$tkey};
+% next if $t->{"${od}Arbitrage"} != $arbitrage;
+% $show_total_now->('');
+% if (!$age_reported++) {
+% my $age= $now - $t->{Timestamp};
+% my $cellid= "da_${i}";
+% $da_ages{$cellid}= $age;
+<td colspan=3>\
+(Data age: <span id="<% $cellid %>"><% prettyprint_age($age) %></span>)
+% } elsif (!defined $total) {
+% $total= 0;
+<tbody>
+% }
+% $total += $t->{Total};
+% my $span= 0 + keys %{ $t->{Stalls} };
+% my $td= "td rowspan=$span";
+<tr class="datarow<% $dline %>">
+<<% $td %>><% $collectdeliver %>
+<<% $td %>><% $t->{'commodname'} |h %>
+%
+% my @stalls= sort keys %{ $t->{Stalls} };
+% my $pstall= sub {
+% my $name= $stalls[$_[0]];
+<td><% $name |h %>
+% };
+%
+% $pstall->(0);
+<<% $td %> align=right><% $t->{Price} |h %> poe ea.
+<<% $td %> align=right><% $t->{Qty} |h %> unit(s)
+<<% $td %> align=right><% $t->{Total} |h %> total
+%
+% foreach my $stallix (1..$#stalls) {
+<tr class="datarow<% $dline %>">
+% $pstall->($stallix);
+% }
+%
+% $dline ^= 1;
+% }
+% };
+<%perl>
+
+ $show_flows->('dst',0,'Deliver'); $show_total->('Proceeds',1);
+ $show_flows->('org',1,'Collect'); $show_total->('(Arbitrage) outlay',-1);
+ $show_flows->('dst',1,'Deliver'); $show_total->('(Arbitrage) proceeds',1);
+ $show_flows->('org',0,'Collect'); $show_total->('Outlay',-1);
+ my $totals= '';
+ if ($i < $#islandids) {
+ $totals .= "In hold $total_massvol[$i]{mass} kg,".
+ " $total_massvol[$i]{volume} l";
+ my $delim= '; spare ';
+ my $domv= sub {
+ my ($max, $got, $units) = @_;
+ return unless defined $max;
+ $totals .= $delim;
+ $totals .= sprintf "%g %s", ($max-$got), $units;
+ $delim= ', ';
+ };
+ $domv->($max_mass, $total_massvol[$i]{mass}, 'kg');
+ $domv->($max_volume, $total_massvol[$i]{volume}, 'l');
+ $totals .= ".\n";
+ }
+ $show_total_now->($totals);
+}
+</%perl>
+<tbody><tr>
+<td colspan=2>Total distance: <% $total_dist %> leagues.
+<td colspan=3 align=right>Overall net cash flow
+<td align=right><strong><%
+ $total_total < 0 ? -$total_total." loss" : $total_total." gain"
+ %></strong>
+</table>
+<& query_age:dataages, id2age => \%da_ages &>
+%
+% } # ========== TRADING PLAN ==========
+