chiark / gitweb /
Fix up search too long error message - really fix up
[ypp-sc-tools.main.git] / yarrg / web / routetrade
index 59a856631b5a1cfdc042664a3d7c67815453c61f..59b02674f1034bb82c983f803afa44e54600075b 100644 (file)
@@ -39,6 +39,8 @@ $dbh
 @archipelagoes
 $qa
 $routeparams
+$reset_suppressions
+$quri
 </%args>
 <& query_age:pageload &>
 
@@ -47,6 +49,9 @@ $routeparams
 my $loss_per_league= defined $routeparams->{LossPerLeaguePct}
        ? $routeparams->{LossPerLeaguePct}*0.01 : 1e-7;
 my $loss_per_delay_slot= 1e-8;
+my $max_gems= 24;
+
+my $minprofit= $routeparams->{MinProfit} || 0;
 
 my $now= time;
 
@@ -143,6 +148,7 @@ my $stmt= "
                commods.ordval                                  ordval,
                commods.posinclass                              posinclass,
                commods.commodclassid                           commodclassid,
+               commods.flags                                   flags,
                dist                                            dist,
                buy.price - sell.price                          unitprofit
        FROM commods
@@ -275,13 +281,21 @@ Searched for arbitrage trades only, in <% $archipelagoes[0] |h %>
 
 <%perl>
 
-my @sail_total;
-
 if (!@flows) {
        print 'No profitable trading opportunities were found.';
        return;
 }
 
+my @sail_total;
+my %opportunity_value;
+
+my $oppo_key= sub {
+       my ($f) = @_;
+       return join '_', map { $f->{$_} } qw(org_id dst_id commodid);
+};
+
+my $any_previous_suppression= 0;
+
 foreach my $f (@flows) {
 
        $f->{MaxQty}= $f->{'org_qty_agg'} < $f->{'dst_qty_agg'}
@@ -306,6 +320,8 @@ foreach my $f (@flows) {
 
        $dists{'org_id'}{'dst_id'}= $f->{'dist'};
 
+       $opportunity_value{ $oppo_key->($f) } += $f->{MaxProfit};
+
        my @uid= $f->{commodid};
        foreach my $od (qw(org dst)) {
                push @uid,
@@ -368,11 +384,21 @@ foreach my $f (@flows) {
                $f->{UidLong} eq $recons_long or
                        die "$f->{UidLong} = $f->{UidShort} = $recons_long ?";
        }
+}
+
+foreach my $f (@flows) {
 
-       if (defined $qa->{"R$f->{UidShort}"} &&
-           !defined $qa->{"T$f->{UidShort}"}) {
-               $f->{Suppress}= 1;
+       if ($reset_suppressions || !defined $qa->{"R$f->{UidShort}"}) {
+               if ($opportunity_value{ $oppo_key->($f) } < $minprofit) {
+                       $f->{Suppress}= 1;
+               }
        } else {
+               if (!defined $qa->{"T$f->{UidShort}"}) {
+                       $any_previous_suppression= 1;
+                       $f->{Suppress}= 1;
+               }
+       }
+       if (!$f->{Suppress}) {
                my $sfis= $ipair2subflowinfs{$f->{'org_id'},$f->{'dst_id'}};
                foreach my $sfi (@$sfis) {
                        my $subflow= {
@@ -392,13 +418,24 @@ foreach my $f (@flows) {
 }
 </%perl>
 
-% my $optimise= $specific;
-% if (!$optimise) {
+% my $optimise= 1;
 
-<p>
 % if (!$specific) {
+%      $optimise= 0;
 Route contains archipelago(es), not just specific islands.
+% } elsif (!@subflows) {
+%      $optimise= 0;
+%      if ($any_previous_suppression) {
+All available trades deselected.
+%      } else {
+No available trades meet the specified minimum trade value, so
+all available trades deselected.
+%      }
 % }
+
+% if (!$optimise) {
+
+<p>
 Therefore, optimal voyage trade plan not calculated.
 
 % } else { # ========== OPTMISATION ==========
@@ -410,11 +447,17 @@ Maximize
   totalprofit:
 ";
 
+my %stall_poe_limits;
+
 foreach my $sf (@subflows) {
        my $eup= $sf->{Flow}{ExpectedUnitProfit};
        $eup *= (1.0-$loss_per_delay_slot) ** $sf->{Org};
        $cplex .= sprintf "
                %+.20f %s", $eup, $sf->{Var};
+       if ($qa->{ShowStalls}>=2) {
+               my $stall= $sf->{Flow}{'dst_stallid'};
+               push @{ $stall_poe_limits{$stall} }, $sf;
+       }
 }
 $cplex .= "
 
@@ -485,6 +528,32 @@ foreach my $ci (0..($#islandids-1)) {
        $applylimit->('mass',    sub { $_[0]{'unitmass'}  *1e-3 });
        $applylimit->('volume',  sub { $_[0]{'unitvolume'}*1e-3 });
        $applylimit->('capital', sub { $_[0]{'org_price'}       });
+
+       my @gem_subflows= grep { $_->{Flow}{flags} =~ m/g/ } @rel_subflows;
+       if (@gem_subflows) {
+               $cplex .= "
+   ". sprintf("%-10s","gems_$ci:")." ".
+               join(" + ", map { $_->{Var} } @gem_subflows). " <= $max_gems";
+       }
+
+       $cplex.= "\n";
+}
+
+if ($qa->{ShowStalls}>=2) {
+       my $stallpoe= $dbh->prepare(<<END);
+SELECT max(qty*price) FROM buy WHERE stallid=?
+END
+       foreach my $stallid (sort { $a <=> $b } keys %stall_poe_limits) {
+               $stallpoe->execute($stallid);
+               my ($lim)= $stallpoe->fetchrow_array();
+               $stallpoe->finish();
+               $cplex.= "
+    ". sprintf("%-15s","poe_$stallid:")." ".
+               join(" + ", map {
+                       sprintf "%d %s", $_->{Flow}{'dst_price'}, $_->{Var};
+               } @{ $stall_poe_limits{$stallid} }).
+               " <= $lim";
+       }
        $cplex.= "\n";
 }
 
@@ -515,7 +584,7 @@ if ($qa->{'debug'}) {
        my $input= pipethrough_prep();
        print $input $cplex or die $!;
        my $output= pipethrough_run_along($input, undef, 'glpsol',
-               qw(glpsol --tmlim 2 --memlim 5 --intopt --cuts --bfs
+               qw(glpsol --tmlim 5 --memlim 5 --intopt --cuts --bfs
                          --cpxlp /dev/stdin -o /dev/stdout));
        print "<pre>\n" if $qa->{'debug'};
        my $found_section= 0;
@@ -691,6 +760,7 @@ Generated by YARRG at <strong><%
                        orgArbitrage => 0,
                        dstArbitrage => 0,
                } unless $$todo;
+               $$todo->{'commodid'}= $f->{'commodid'};
                $$todo->{'commodname'}= $f->{'commodname'};
                $$todo->{'posinclass'}= '';
                my $incl= $f->{'posinclass'};
@@ -778,9 +848,13 @@ END
 %              $total += $t->{Total};
 %              my $span= 0 + keys %{ $t->{Stalls} };
 %              my $td= "td rowspan=$span";
+%              my %linkqf= (%{ $qa->{'baseqf'} }, %{ $qa->{'queryqf'} });
+%              $linkqf{'query'}= 'commod';
+%              $linkqf{'commodstring'}= $t->{'commodname'};
+%              $linkqf{'commodid'}= $t->{'commodid'};
 % tr_datarow($m,$dline);
 <<% $td %>><% $collectdeliver %>
-<<% $td %>><% $t->{'commodname'} |h %>
+<<% $td %>><a href="<% $quri->(%linkqf) %>"><% $t->{'commodname'} |h %></a>
 <<% $td %>><% $t->{'posinclass'} %>
 %
 %              my @stalls= sort keys %{ $t->{Stalls} };