X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~yarrgweb/git?p=ypp-sc-tools.db-live.git;a=blobdiff_plain;f=yarrg%2Fweb%2Froutetrade;h=eadc473d4b23dac47885d569b89a79d12a741ae5;hp=7d9dd8be7dc94c3e8af01de38968a1a51ef4dd33;hb=880b063ca880504e85bbeba2e37fc8faa187947e;hpb=ef57d601849ccb26cd6a69684be7aec261d7c5be diff --git a/yarrg/web/routetrade b/yarrg/web/routetrade index 7d9dd8b..eadc473 100644 --- a/yarrg/web/routetrade +++ b/yarrg/web/routetrade @@ -35,39 +35,13 @@ ========== TODO ========== 16:36 alpha,byrne,papaya,turtle,jorvik,luthien is my example -16:37 if tehre are 2 rows which take the same object and sell it for the - same profit at two other islands, choose the shortest route as the - preferred one -16:37 coconut buy 10 sell 16, at luthien or jorvik, in that example -16:38 Do you see what I mean? - -16:38 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? -16:39 Also, maybe colour to highlight the suggested trades? - -16:40 can it give a total investment/profit for the suggested trades? -16:40 columns should be sortable with the small arrows as before - -16:46 Oh the unticking has become broken. - -16:51 YPP interfaces have price then qty. You have qty then price. This - is confusing! -16:51 the max column ordering is OK -16:51 (alo profit and suggested are OK) -16:52 Err, you want qty on the left in those two but on the right in - collect and deliver ? -16:53 Yes (price and capital are not the same thing) -16:53 OK -16:53 for max the order in which you want to think about it is 'I need to - buy ten of them and that will cost me $total price) -16:54 s/)/'/ - -16:46 Also trading plan not functional but I guess you know that :-) - -Also: -- potential cost of losses -- max volume/mass -- use POST for update. Hrrm. +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 ========== @@ -78,8 +52,15 @@ $dbh @archipelagoes $qa +<&| script &> + da_pageload= Date.now(); + + <%perl> +my $now= time; +my $loss_per_league= 1e-7; + my @flow_conds; my @query_params; @@ -137,56 +118,68 @@ my $stmt= " SELECT sell_islands.islandname org_name, sell_islands.islandid org_id, sell.price org_price, + sell.qty org_qty_stall, + sell_stalls.stallname org_stallname, + sell.stallid org_stallid, + sell_uploads.timestamp org_timestamp, buy_islands.islandname dst_name, buy_islands.islandid dst_id, buy.price dst_price, -".($qa->{ShowStalls} ? " - sell.stallid org_stallid, - sell_stalls.stallname org_stallname, - sell.qty org_qty, - buy.stallid dst_stallid, + buy.qty dst_qty_stall, buy_stalls.stallname dst_stallname, - buy.qty dst_qty, + buy.stallid dst_stallid, + buy_uploads.timestamp dst_timestamp, +".($qa->{ShowStalls} ? " + sell.qty org_qty_agg, + buy.qty dst_qty_agg, " : " - sum(sell.qty) org_qty, - sum(buy.qty) dst_qty, + (SELECT sum(qty) FROM sell AS sell_agg + WHERE sell_agg.commodid = commods.commodid + AND sell_agg.islandid = sell.islandid + AND sell_agg.price = sell.price) org_qty_agg, + (SELECT sum(qty) FROM buy AS buy_agg + WHERE buy_agg.commodid = commods.commodid + AND buy_agg.islandid = buy.islandid + AND buy_agg.price = buy.price) dst_qty_agg, ")." commods.commodname commodname, 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 - JOIN sell on commods.commodid = sell.commodid - JOIN islands as sell_islands on sell.islandid = sell_islands.islandid - JOIN islands as buy_islands on buy.islandid = buy_islands.islandid -".($qa->{ShowStalls} ? " - JOIN stalls as sell_stalls on sell.stallid = sell_stalls.stallid - JOIN stalls as buy_stalls on buy.stallid = buy_stalls.stallid -" : "")." + JOIN sell ON commods.commodid = sell.commodid + JOIN buy ON commods.commodid = buy.commodid + JOIN islands AS sell_islands ON sell.islandid = sell_islands.islandid + JOIN islands AS buy_islands ON buy.islandid = buy_islands.islandid + JOIN uploads AS sell_uploads ON sell.islandid = sell_uploads.islandid + JOIN uploads AS buy_uploads ON buy.islandid = buy_uploads.islandid + 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)." ) AND buy.price > sell.price -".($qa->{ShowStalls} ? "" : " - GROUP BY commods.commodid, org_id, org_price, dst_id, dst_price -")." ORDER BY org_name, dst_name, commodname, unitprofit DESC, - org_price, dst_price DESC + org_price, dst_price DESC, + org_stallname, dst_stallname "; my $sth= $dbh->prepare($stmt); $sth->execute(@query_params); my @flows; -my @cols; +my @cols= ({ NoSort => 1 }); my $addcols= sub { my $base= shift @_; foreach my $name (@_) { - push @cols, { Name => $name, %$base }; + my $col= { Name => $name, %$base }; + $col->{Numeric}=1 if !$col->{Text}; + push @cols, $col; } }; @@ -201,9 +194,14 @@ if ($qa->{ShowStalls}) { )); } $addcols->({ Text => 1 }, qw(commodname)); -$addcols->({}, - qw( org_qty org_price dst_qty dst_price - Margin unitprofit MaxQty +$addcols->({ DoReverse => 1 }, + qw( org_price org_qty_agg dst_price dst_qty_agg + )); +$addcols->({ DoReverse => 1, SortColKey => 'MarginSortKey' }, + qw( Margin + )); +$addcols->({ DoReverse => 1 }, + qw( unitprofit MaxQty MaxCapital MaxProfit )); @@ -218,23 +216,57 @@ $addcols->({}, <& dumptable:start, qa => $qa, sth => $sth &> % { -% my $f; -% while ($f= $sth->fetchrow_hashref()) { +% my $got; +% while ($got= $sth->fetchrow_hashref()) { <%perl> - $f->{Ix}= @flows; - $f->{Var}= "f$f->{Ix}"; + my $f= $flows[$#flows]; + if ( !$f || + $qa->{ShowStalls} || + grep { $f->{$_} ne $got->{$_} } + qw(org_id org_price dst_id dst_price commodid) + ) { + # Make a new flow rather than adding to the existing one + + $f= { + Ix => scalar(@flows), + Var => "f".@flows, + %$got + }; + $f->{"org_stallid"}= $f->{"dst_stallid"}= 'all' + if !$qa->{ShowStalls}; + push @flows, $f; + } + foreach my $od (qw(org dst)) { + $f->{"${od}Stalls"}{ + $got->{"${od}_stallname"} + } = + $got->{"${od}_qty_stall"} + ; + } + + +<& dumptable:row, qa => $qa, sth => $sth, row => $f &> +% } +<& dumptable:end, qa => $qa &> +% } + +<%perl> +foreach my $f (@flows) { - $f->{MaxQty}= $f->{'org_qty'} < $f->{'dst_qty'} - ? $f->{'org_qty'} : $f->{'dst_qty'}; + $f->{MaxQty}= $f->{'org_qty_agg'} < $f->{'dst_qty_agg'} + ? $f->{'org_qty_agg'} : $f->{'dst_qty_agg'}; $f->{MaxProfit}= $f->{MaxQty} * $f->{'unitprofit'}; $f->{MaxCapital}= $f->{MaxQty} * $f->{'org_price'}; + $f->{MarginSortKey}= sprintf "%d", + $f->{'dst_price'} * 10000 / $f->{'org_price'}; $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->{'org_price'}; my @uid= $f->{commodid}; foreach my $od (qw(org dst)) { @@ -299,17 +331,13 @@ 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; } - push @flows, $f; - +} -<& dumptable:row, qa => $qa, sth => $sth, row => $f &> -% } -<& dumptable:end, qa => $qa &> -% } % my $optimise= $specific && !$confusing && @islandids>1; % if (!$optimise) { @@ -335,7 +363,9 @@ Maximize totalprofit: ".(join " + - ", map { "$_->{unitprofit} $_->{Var}" } @flows)." + ", map { + sprintf "%.20f %s", $_->{ExpectedUnitProfit}, $_->{Var} + } @flows)." Subject To "; @@ -359,7 +389,7 @@ foreach my $flow (@flows) { ); push @{ $avail_csts{$cstname}{Flows} }, $flow->{Var}; - $avail_csts{$cstname}{Qty}= $flow->{"${od}_qty"}; + $avail_csts{$cstname}{Qty}= $flow->{"${od}_qty_agg"}; } } foreach my $cstname (sort keys %avail_csts) { @@ -418,10 +448,10 @@ if ($qa->{'debug'}) { die unless $found_section; }; -$addcols->({}, qw( +$addcols->({ DoReverse => 1 }, qw( OptQty )); -$addcols->({ Total => 0 }, qw( +$addcols->({ Total => 0, DoReverse => 1 }, qw( OptCapital OptProfit )); @@ -429,10 +459,11 @@ $addcols->({ Total => 0 }, qw( % } # ========== OPTIMISATION ========== +% my %ts_sortkeys; % { % my $cdspan= $qa->{ShowStalls} ? ' colspan=2' : ''; % my $cdstall= $qa->{ShowStalls} ? 'Stall' : ''; - +
<% $qa->{ShowStalls} ? '' : '' %> @@ -444,7 +475,7 @@ $addcols->({ Total => 0 }, qw( % if ($optimise) { % } - + @@ -462,10 +493,10 @@ $addcols->({ Total => 0 }, qw( + +% foreach my $col (@cols) { + +
>Collect >Deliver @@ -454,7 +485,7 @@ $addcols->({ Total => 0 }, qw( Profit Max % if ($optimise) { -Suggested +Planned % }
Island <% $cdstall %> Island <% $cdstall %> Commodity -Qty Price Qty Price +Qty Margin Unit Qty @@ -478,23 +509,33 @@ $addcols->({ Total => 0 }, qw( % } % } -% foreach my $flow (@flows) { -
+% } + +% foreach my $flowix (0..$#flows) { +% my $flow= $flows[$flowix]; +% my $rowid= "id_row_$flow->{UidShort}"; +
{UidShort} %> value=""> {UidShort} %> value="" <% $flow->{Suppress} ? '' : 'checked' %> > -% foreach my $ci (0..$#cols) { +% foreach my $ci (1..$#cols) { % my $col= $cols[$ci]; % my $v= $flow->{$col->{Name}}; % $col->{Total} += $v if defined $col->{Total}; % $v='' if !$col->{Text} && !$v; +% my $sortkey= $col->{SortColKey} ? +% $flow->{$col->{SortColKey}} : $v; +% $ts_sortkeys{$ci}{$rowid}= $sortkey; {Text} ? '' : 'align=right' %>><% $v |h %> % } % } -
Total -% foreach my $ci (2..$#cols) { +% foreach my $ci (3..$#cols) { % my $col= $cols[$ci]; % if (defined $col->{Total}) { @@ -503,17 +544,29 @@ $addcols->({ Total => 0 }, qw( % }
+<& tabsort, cols => \@cols, table => 'trades', rowclass => 'datarow', + throw => 'trades_sort', tbrow => 'trades_total' &> +<&| script &> + ts_sortkeys= <% to_json_protecttags(\%ts_sortkeys) %>; + function all_onload() { + ts_onload__trades(); + } + window.onload= all_onload; + + % if ($optimise) { # ========== TRADING PLAN ========== % % my $iquery= $dbh->prepare('SELECT islandname FROM islands % WHERE islandid = ?'); +% my %da_ages; %

Voyage trading plan

- +
% foreach my $i (0..$#islandids) { - +Buy or sell flow +<%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 $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"}; + if ($f->{'org_id'} == $f->{'dst_id'}) { + $$todo->{"${od}Arbitrage"}= 1; + } + } + } + + my $total; + my $dline= 0; + 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; +% if (!$age_reported++) { +% my $age= $now - $t->{Timestamp}; +% my $cellid= "da_${i}"; +% $da_ages{$cellid}= $age; + +% } +% $total += $t->{Total}; +% my $span= 0 + keys %{ $t->{Stalls} }; +% my $td= "td rowspan=$span"; + +<<% $td %>><% $collectdeliver %> +<<% $td %>><% $t->{'commodname'} |h %> +% +% my @stalls= sort keys %{ $t->{Stalls} }; +% my $pstall= sub { +% my $name= $stalls[$_[0]]; + +% $pstall->($stallix); +% } +% +% $dline ^= 1; % } -% } -% } +% }; +% my $show_total= sub { +% my ($totaldesc)= @_; +% if (defined $total) { + +
+
% $iquery->execute($islandids[$i]); % my ($islandname) = $iquery->fetchrow_array(); % if (!$i) { @@ -522,21 +575,109 @@ Start at <% $islandname |h %> Sail to <% $islandname |h %> % } -% 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}; -
\ +(Data age: <% prettyprint_age($age) %>) +% } elsif (!defined $total) { +% $total= 0; +
<% $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) { +
+<% $totaldesc %> +<% $total |h %> total +% } +% $total= undef; +% $dline= 0; +<%perl> + }; + + $show_flows->('dst',0,'Deliver'); $show_total->('Proceeds'); + $show_flows->('org',1,'Collect'); $show_total->('(Arbitrage) outlay'); + $show_flows->('dst',1,'Deliver'); $show_total->('(Arbitrage) proceeds'); + $show_flows->('org',0,'Collect'); $show_total->('Outlay'); + +} +
+<& query_age:dataages, id2age => \%da_ages &> % % } # ========== TRADING PLAN ==========