chiark / gitweb /
Prefer short trades, using distance table
[ypp-sc-tools.main.git] / yarrg / web / routetrade
index e200aa5cfd78e7643297dfb350f73f2320b0b640..8d425375fe76bbc4544bacfa9bf7172eb937caf0 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
+
+16:39 <ceb> Also, maybe colour to highlight the suggested trades?
+
+16:40 <ceb> columns should be sortable with the small arrows as before
+
+16:46 <ceb> Also trading plan not functional but I guess you know that :-)
+
+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
+
+16:38 <ceb> I don't know how hard this is, but can you show only the suggested 
+            trades to start ith and have a button to show all?
+========== TODO ==========
+
 </%doc>
 <%args>
 $dbh
@@ -41,6 +62,8 @@ $qa
 </%args>
 <%perl>
 
+my $loss_per_league= 1e-7;
+
 my @flow_conds;
 my @query_params;
 
@@ -116,6 +139,7 @@ my $stmt= "
                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
@@ -126,6 +150,7 @@ my $stmt= "
        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)."
@@ -142,16 +167,31 @@ my $sth= $dbh->prepare($stmt);
 $sth->execute(@query_params);
 my @flows;
 
-my @columns;
+my @cols;
+
+my $addcols= sub {
+       my $base= shift @_;
+       foreach my $name (@_) {
+               push @cols, { Name => $name, %$base };
+       }
+};
+
 if ($qa->{ShowStalls}) {
-       push @columns,       qw(org_name org_stallname dst_name dst_stallname);
+       $addcols->({ Text => 1 }, qw(
+               org_name org_stallname
+               dst_name dst_stallname
+       ));
 } else {
-       push @columns,       qw(org_name dst_name);
+       $addcols->({Text => 1 }, qw(
+               org_name dst_name
+       ));
 }
-push @columns,              qw(commodname
-                               org_price org_qty dst_price dst_qty
-                               unitprofit PctProfit
-                               MaxQty MaxCapital MaxProfit);
+$addcols->({ Text => 1 }, qw(commodname));
+$addcols->({},
+       qw(     org_price org_qty dst_price dst_qty
+               Margin unitprofit MaxQty
+               MaxCapital MaxProfit
+       ));
 
 </%perl>
 
@@ -176,12 +216,16 @@ push @columns,                 qw(commodname
        $f->{MaxProfit}= $f->{MaxQty} * $f->{'unitprofit'};
        $f->{MaxCapital}= $f->{MaxQty} * $f->{'org_price'};
 
-       $f->{PctProfit}= sprintf "%3.1f%%",
+       $f->{Margin}= sprintf "%3.1f%%",
                $f->{'dst_price'} * 100.0 / $f->{'org_price'} - 100.0;
 
        $f->{"org_stallid"}= $f->{"dst_stallid"}= 'all'
                if !$qa->{ShowStalls};
 
+       $f->{ExpectedUnitProfit}=
+               $f->{'dst_price'} * (1.0 - $loss_per_league) ** $f->{'dist'}
+               - $f->{'src_price'};
+
        my @uid= $f->{commodid};
        foreach my $od (qw(org dst)) {
                push @uid,
@@ -245,7 +289,8 @@ die "$cmpu $uue ?" if length $cmpu > 20;
                        die "$f->{UidLong} = $f->{UidShort} = $recons_long ?";
        }
 
-       if ($qa->{"R$f->{UidShort}"} && !$qa->{"T$f->{UidShort}"}) {
+       if (defined $qa->{"R$f->{UidShort}"} &&
+           !defined $qa->{"T$f->{UidShort}"}) {
                $f->{Suppress}= 1;
        }
 
@@ -281,7 +326,9 @@ Maximize
 
   totalprofit:
                   ".(join " +
-                  ", map { "$_->{unitprofit} $_->{Var}" } @flows)."
+                  ", map {
+                       sprintf "%.20f %s", $_->{ExpectedUnitProfit}, $_->{Var}
+                       } @flows)."
 
 Subject To
 ";
@@ -364,7 +411,12 @@ if ($qa->{'debug'}) {
        die unless $found_section;
 };
 
-push @columns, qw(OptQty OptCapital OptProfit);
+$addcols->({}, qw(
+               OptQty
+       ));
+$addcols->({ Total => 0 }, qw(
+               OptCapital OptProfit
+       ));
 
 </%perl>
 
@@ -373,7 +425,18 @@ push @columns, qw(OptQty OptCapital OptProfit);
 % {
 %      my $cdspan= $qa->{ShowStalls} ? ' colspan=2' : '';
 %      my $cdstall= $qa->{ShowStalls} ? '<th>Stall</th>' : '';
-<table>
+<table rules=groups>
+<colgroup span=1>
+<colgroup span=2>
+<% $qa->{ShowStalls} ? '<colgroup span=2>' : '' %>
+<colgroup span=1>
+<colgroup span=2>
+<colgroup span=2>
+<colgroup span=2>
+<colgroup span=3>
+%      if ($optimise) {
+<colgroup span=3>
+%      }
 <tr>
 <th>
 <th<% $cdspan %>>Collect
@@ -384,7 +447,7 @@ push @columns, qw(OptQty OptCapital OptProfit);
 <th colspan=2>Profit
 <th colspan=3>Max
 %      if ($optimise) {
-<th colspan=3>Suggested
+<th colspan=3>Planned
 %      }
 
 <tr>
@@ -396,8 +459,8 @@ push @columns, qw(OptQty OptCapital OptProfit);
 <th>Qty
 <th>Price
 <th>Qty
-<th>Unit
 <th>Margin
+<th>Unit
 <th>Qty
 <th>Capital
 <th>Profit
@@ -413,14 +476,63 @@ push @columns, qw(OptQty OptCapital OptProfit);
 <td><input type=hidden   name=R<% $flow->{UidShort} %> value="">
     <input type=checkbox name=T<% $flow->{UidShort} %> value=""
        <% $flow->{Suppress} ? '' : 'checked' %> >
-%      foreach my $col (@columns) {
-<td><% $flow->{$col} |h %>
+%      foreach my $ci (0..$#cols) {
+%              my $col= $cols[$ci];
+%              my $v= $flow->{$col->{Name}};
+%              $col->{Total} += $v if defined $col->{Total};
+%              $v='' if !$col->{Text} && !$v;
+<td <% $col->{Text} ? '' : 'align=right' %>><% $v |h %>
+%      }
+% }
+<tr>
+<th>
+<th colspan=2>Total
+% foreach my $ci (2..$#cols) {
+%      my $col= $cols[$ci];
+<td align=right>
+%      if (defined $col->{Total}) {
+<% $col->{Total} |h %>
 %      }
 % }
 </table>
 
 <input type=submit name=update value="Update">
 
+% if ($optimise) { # ========== TRADING PLAN ==========
+%
+% my $iquery= $dbh->prepare('SELECT islandname FROM islands
+%                              WHERE islandid = ?');
+%
+<h1>Voyage trading plan</h1>
+<table>
+% foreach my $i (0..$#islandids) {
+<tr><td colspan=4><strong>
+%      $iquery->execute($islandids[$i]);
+%      my ($islandname) = $iquery->fetchrow_array();
+%      if (!$i) {
+Start at <% $islandname |h %>
+%      } else {
+Sail to <% $islandname |h %>
+%      }
+</strong>
+%    foreach my $od (qw(dst org)) {
+%      my $sign= $od eq 'dst' ? -1 : +1;
+%      foreach my $f (sort {
+%                      $a->{'commodname'} cmp $b->{'commodname'}
+%              or $sign * ($a->{"${od}_price"} <=> $b->{"${od}_price"})
+%              or      $a->{"${od}_stallname"} cmp $b->{"${od}_stallname"}
+%              } @flows) {
+%              next if $f->{Suppress};
+%              next unless $f->{"${od}_id"} == $islandids[$i];
+%              next unless $f->{OptQty};
+<tr>Buy or sell flow 
+%      }
+%    }
+% }
+</table>
+%
+% } # ========== TRADING PLAN ==========
+
 <%init>
 use CommodsWeb;
 use Commods;