8 .../ypp-restock-rum [<information> ...]
10 where <information> is
12 have [<swill> <grog>] <fine> [<hold_shot>+<loaded_shot>]
13 want [<swill> <grog>] <fine> [<shot>]
14 price <swill> <grog> <fine> [<shot>]
16 Each of which may appear only once, except \`have' which may appear
17 more than once which case we calculate the differences and the profit
20 If /<shot> is not specified at all, relevant information about shot is
21 not reported. For have and want, specifying an empty string means
22 zero. Entirely Missing <swill>/<grog>/ is taken as if both were
25 In price, missing entries mean the commodity is unavailable.
29 our (@kinds) = qw(Swill Grog Fine Shot);
30 our (@proofs) = qw(40 60 100);
32 sub parse_info ($$$\@$) {
33 my ($omitswgok,$default,$multishot, $storeary, $what) = @_;
34 @ARGV or badusage("missing value for information argument \`$_'");
35 badusage("$what: specified more than once")
36 if defined $storeary->[2];
38 while (@ARGV and $ARGV[0] =~ m/^\d/) {
43 badusage("$what: swill and grog amounts must be specified")
45 @v=($default,$default,@v);
47 if ($multishot and @v==4 and length $v[3]) {
48 $v[3] =~ m/^0*(\d+)\+0*(\d+)$/ or
49 badusage("$what: shot must be specified as <hold>+<loaded>");
56 badusage("$what: invalid syntax (wrong number of /s)");
60 $_ = $default if !length;
61 m/^0*(\d+)$/ or badusage("$what: $kinds[$i] \`$_': bad syntax");
68 our (@have,@want,@price);
71 @ARGV or badusage("need some information to go on");
75 parse_info(1,0,1, @{ $have[@have] }, 'have');
77 parse_info(1,0,0, @want, 'want');
78 } elsif (m/^price$/) {
79 parse_info(0,1e7,0, @price, 'price');
81 badusage("unknown information argument \`$_'");
88 print STDERR "\nbad usage: $m\n\n$usage\n";
96 defined $x and $x and $x<1e5;
100 my ($what, $format, $ary, $unit) = @_;
101 printf("%-25s", "$what:");
102 for my $i (qw(0 1 2 3)) {
104 my $y= valid($x) ? sprintf $format, $x : ' ';
107 printf " %s\n", $unit;
111 my ($what, $ary, $unit) = @_;
112 prvff($what, '%4d ', @$ary, $unit);
116 my ($what, $ary, $unit) = @_;
117 prvff($what, $ff, @$ary, $unit);
122 printf "%-20s %s\n", "$k:", $v;
124 sub fmt_stock_index ($) {
126 @have==1 ? '' : ' #'.$si;
132 foreach my $i (qw(0 1 2)) {
133 $total += $rums->[$i] * $proofs[$i] / 100;
139 our ($best, $best_norm_price);
141 sub print_inputs () {
143 map { printf " %5s ", $_ } @kinds;
145 pr('prices', @price, 'poe ea.') if valid(@price);
146 pr('target stocks', @want, 'units') if valid(@want);
147 my $si=0; for my $stocks (@have) {
148 pr('actual stocks'.fmt_stock_index(++$si),
154 sub compute_cheapest_rum() {
155 return unless @price;
157 my (@perorder) = map { $_*10 } @price;
158 prf('equiv. ordering price', @perorder, 'poe/order');
161 $best_norm_price= 1e6;
162 for my $i (qw(0 1 2)) {
163 next unless $price[$i];
164 $norm_price[$i] = $price[$i] * 100 / $proofs[$i];
165 if ($norm_price[$i] <= $best_norm_price) {
167 $best_norm_price= $norm_price[$i];
170 prf('normalised prices', @norm_price, 'poe/fine');
173 printf "best is %-10s%*s^^\n",
176 my (@bestperorder) = map {
177 $best_norm_price * $proofs[$_] / 100 * 10;
179 #push @bestperorder, $perorder[3];
180 prf('best is equiv. ordering', @bestperorder, 'poe/order');
194 sub compute_stock_values() {
197 Rum Rum Shot Shot total Profit Profit
198 equiv. value stocks value value this leg total
204 my $si=0; for my $stocks (@have) {
205 my $stock_rum = rum_total(@$stocks);
206 my $rum_value= defined($best) ? $stock_rum * $best_norm_price : 0;
207 my $shot_value= valid($price[3]) ? $stocks->[3] * $price[3] : 0;
208 my $total_value= $rum_value + $shot_value;
210 printf "%-10s ", 'stocks'.fmt_stock_index(++$si).':';
213 printf "%6d", $stocks->[3];
217 if (defined $last_value) {
218 printf(" %10.1f %10.1f",
219 $total_value - $last_value,
220 $total_value - $initial_value);
222 $initial_value= $total_value unless defined $initial_value;
223 $last_value= $total_value;
227 fine poe units poe poe delta-poe poe
234 my ($k,$v1,$v2) = @_;
235 printf "%-20s %-23s %s\n", "$k:", $v1, $v2;
239 my ($k,$v1,$v2,$v3) = @_;
240 printf "%-20s %-23s %-20s %s\n", "$k:", $v1, $v2, $v3;
244 my ($k,$rum,$shot) = @_;
246 valid($rum) ? sprintf("%12.1f fine equiv", $rum) : '',
247 valid($shot) ? sprintf("%10d shot", $shot) : '');
250 sub compute_restock_requirements () {
253 my $rum_want= rum_total(@want);
255 my $stocks= @have ? $have[-1] : [qw(0 0 0 0)];
256 my $rum_have= rum_total(@$stocks);
258 pr2rs('desired stock level', $rum_want, $want[3]);
260 my $rum_need = $rum_want - $rum_have;
261 my $shot_need = $want[3] - $stocks->[3];
264 pr2rs('current stock', $rum_have, $stocks->[3]);
265 pr2rs('restock requirement', $rum_need, $shot_need);
270 my ($rum_buy,$shot_buy) = ('','');
271 my ($rum_bill,$shot_bill) = qw(0 0);
272 if (defined $best and $rum_need > 0) {
273 my $rum_qty= $rum_need * 100 / $proofs[$best];
274 $rum_qty= ceil($rum_qty);
275 $rum_buy= sprintf('%12s %-11s ',"** $rum_qty","$kinds[$best] **");
276 $rum_bill= $rum_qty * $price[$best];
278 if ($shot_need > 0 and valid($price[3])) {
279 $shot_buy= sprintf('%7s shot **', "** $shot_need");
280 $shot_bill= $shot_need * $price[3];
282 if (length($rum_buy) or length($shot_buy)) {
284 $rum_bill ? sprintf("%12d poe ", $rum_bill) : '',
285 $shot_bill ? sprintf("%10d poe", $shot_bill) : '',
286 sprintf("%7d total", $rum_bill + $shot_bill));
287 pr2('BUY', $rum_buy, $shot_buy);
289 print "stocks are sufficient.\n";
297 compute_cheapest_rum();
298 compute_stock_values();
299 compute_restock_requirements();
303 # if (defined $price{Swill}) {
304 # map { $price{$_}= undef if $price{$_} eq 'x' } @rums;
306 # if (defined $have{Swill}) {
308 # map { $have_proof += $have{$_} * $proof{$_} } @rums;
315 our ($need_proof, %need, %buy);
318 sub compute_restock_cheapest_rum() {
321 $bill{$_} = $buy{$_} * $price{$_} if defined $price{$_};
323 prf('nominal bill', %bill, 'poe');
325 if ($need_proof < 0) {
326 printf "stocks are sufficient";
328 my $buy= ceil($buy{$best});
329 printf "buy %d %s at %d poe each for %d poe",
330 $buy, $best, $price{$best}, $buy * $price{$best};