chiark / gitweb /
Fix circular routes (including arbitrage complications)
[ypp-sc-tools.db-live.git] / yarrg / web / routetrade
index e4e583a83a190f1f33a77411c8533fdf50b505a8..80fc2b13d5e8cf78f5ba1c61d0310e5de0280318 100644 (file)
  This Mason component is the core trade planner for a specific route.
 
 
-========== TODO ==========
-16:36 <ceb> alpha,byrne,papaya,turtle,jorvik,luthien is my example
-
-use POST for update.  Hrrm.
-
-LATER OR NOT AT ALL
-
-adjustable potential cost of losses (rather than fixed 1e-BIG per league)
-
-max volume/mass
-
-========== TODO ==========
-
 </%doc>
 <%args>
 $dbh
@@ -98,10 +85,12 @@ foreach my $src_i (0..$#islandids) {
 
                if ($specific && !$confusing &&
                    # With a circular route, do not carry goods round the loop
-                   !($src_i==0 && $dst_i==$#islandids &&
+                   !(($src_i==0 || $src_i==$#islandids) &&
+                     $dst_i==$#islandids &&
                      $src_isle == $islandids[$dst_i])) {
                        if ($islandpair{$src_isle,$dst_isle}) {
                                $confusing= 1;
+print "confusing $src_i $src_isle  $dst_i $dst_isle\n";
                        } else {
                                $islandpair{$src_isle,$dst_isle}=
                                        [ $src_i, $dst_i ];
@@ -252,6 +241,12 @@ $addcols->({ DoReverse => 1 },
 % }
 
 <%perl>
+
+if (!@flows) {
+       print 'No profitable trading opportunities were found.';
+       return;
+}
+
 foreach my $f (@flows) {
 
        $f->{MaxQty}= $f->{'org_qty_agg'} < $f->{'dst_qty_agg'}
@@ -353,7 +348,7 @@ Route contains archipelago(es), not just specific islands.
 Route is complex - it visits the same island several times
 and isn't a simple loop.
 % }
-Therefore, optimal trade pattern not calculated.
+Therefore, optimal voyage trade plan not calculated.
 
 % } else { # ========== OPTMISATION ==========
 <%perl>
@@ -423,7 +418,9 @@ if ($qa->{'debug'}) {
                qw(glpsol --cpxlp /dev/stdin -o /dev/stdout));
        print "<pre>\n" if $qa->{'debug'};
        my $found_section= 0;
+       my $glpsol_out= '';
        while (<$output>) {
+               $glpsol_out.= $_;
                print encode_entities($_) if $qa->{'debug'};
                if (m/^\s*No\.\s+Column name\s+St\s+Activity\s/) {
                        die if $found_section>0;
@@ -444,8 +441,9 @@ if ($qa->{'debug'}) {
                $flow->{OptCapital}= $flow->{OptQty} * $flow->{'org_price'};
        }
        print "</pre>\n" if $qa->{'debug'};
-       pipethrough_run_finish($output, 'glpsol');
-       die unless $found_section;
+       my $prerr= "\n=====\n$cplex\n=====\n$glpsol_out\n=====\n ";
+       pipethrough_run_finish($output,$prerr);
+       die $prerr unless $found_section;
 };
 
 $addcols->({ DoReverse => 1 }, qw(
@@ -561,6 +559,7 @@ $addcols->({ Total => 0, DoReverse => 1 }, qw(
 % my $iquery= $dbh->prepare('SELECT islandname FROM islands
 %                              WHERE islandid = ?');
 % my %da_ages;
+% my $total_total= 0;
 %
 <h1>Voyage trading plan</h1>
 <table rules=groups>
@@ -583,11 +582,17 @@ Sail to <% $islandname |h %>
                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", $price),
+                               (sprintf "%07d", ($od eq 'dst' ?
+                                               9999999-$price : $price)),
                                $stallname
                        };
                $$todo= {
@@ -602,9 +607,7 @@ Sail to <% $islandname |h %>
                $$todo->{Qty} += $f->{OptQty};
                $$todo->{Total}= $$todo->{Price} * $$todo->{Qty};
                $$todo->{Stalls}= $f->{"${od}Stalls"};
-               if ($f->{'org_id'} == $f->{'dst_id'}) {
-                       $$todo->{"${od}Arbitrage"}= 1;
-               }
+               $$todo->{"${od}Arbitrage"}= 1 if $arbitrage;
        }
      }
 
@@ -656,25 +659,32 @@ Sail to <% $islandname |h %>
 %      }
 %    };
 %    my $show_total= sub {
-%      my ($totaldesc)= @_;
+%      my ($totaldesc, $sign)= @_;
 %      if (defined $total) {
 <tr>
 <td colspan=3>
 <td colspan=2 align=right><% $totaldesc %>
 <td align=right><% $total |h %> total
+%              $total_total += $sign * $total;
 %      }
 %      $total= undef;
 %      $dline= 0;
 <%perl>
      };
 
-     $show_flows->('org',1,'Collect');  $show_total->('(Arbitrage) outlay');
-     $show_flows->('dst',1,'Deliver');
-     $show_flows->('dst',0,'Deliver');  $show_total->('Proceeds');
-     $show_flows->('org',0,'Collect');  $show_total->('Outlay');
+     $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);
 
 }
 </%perl>
+<tbody><tr>
+<td colspan=2>
+<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 &>
 %