@ISA = qw(Exporter);
@EXPORT = qw(&parse_info_clientside &fetch_with_rsync
&parse_info_serverside &parse_info_serverside_ocean
- %oceans %commods %clients %routes %route_mysteries
+ %oceans %commods %clients
+ %vessels %shotname2damage
&parse_pctb_commodmap %pctb_commodmap @pctb_commodmap
&get_our_version &check_tsv_line
&pipethrough_prep &pipethrough_run
our %oceans; # eg $oceans{'Midnight'}{'Ruby'}{'Eta Island'}= $sources;
our %clients; # eg $clients{'ypp-sc-tools'}= [ qw(last-page) ];
-our %routes; # eg $routes{'Midnight'}{'Orca'}{'Tinga'}= $sources NB abbrevs!
-our %route_mysteries; # eg $route_mysteries{'Midnight'}{'Norse'}= 3
+our %vessels; # eg $vessels{'War Brig'}{Shot}='medium'
+ # $vessels{'War Brig'}{Volume}= 81000
+ # $vessels{'War Brig'}{Mass}= 54000
+our %shotname2damage; # eg $shotname2damage{'medium'}= 3;
# $sources = 's[l]b';
# 's' = Special Circumstances; 'l' = local ; B = with Bleach
$oceans{$ocean}{$arch}{$_} .= $src;
};
});
- } elsif (m/^routes (\w+)$/) {
- my $ocean= $1;
+ } elsif (m/^vessels$/) {
+ @ctx= (sub {
+ return if m/^[-+|]+$/;
+ m/^ \| \s* ([A-Z][a-z\ ]+[a-z]) \s*
+ \| \s* (small|medium|large) \s*
+ \| \s* ([1-9][0-9,]+) \s*
+ \| \s* ([1-9][0-9,]+) \s*
+ \| $/x
+ or die;
+ my $name= $1;
+ my $v= { Shot => $2, Volume => $3, Mass => $4 };
+ foreach my $vm (qw(Volume Mass)) { $v->{$vm} =~ s/,//g; }
+ $vessels{$name}= $v;
+ });
+ } elsif (m/^shot$/) {
@ctx= (sub {
- m/^(\S[^\t]*\S),\s*(\S[^\t]*\S),\s*([1-9][0-9]{0,2})$/ or die;
- $routes{$ocean}{$1}{$2}= $3;
+ m/^ ([a-z]+) \s+ (\d+) $/x or die;
+ $shotname2damage{$1}= $2;
});
} elsif (m/^client (\S+.*\S)$/) {
my $client= $1;
}
};
foreach (@rawcm) { &$ca($_,$src); }
-
- foreach my $on (keys %routes) {
- my $routes= $routes{$on};
- my $ocean= $oceans{$on};
- die unless defined $ocean;
-
- my @allislands;
- foreach my $an (sort keys %$ocean) {
- my $arch= $ocean->{$an};
- push @allislands, sort keys %$arch;
- }
- parse_info_maproutes($on, \@allislands, $routes);
- foreach my $route (values %$routes) {
- parse_info_maproutes($on, \@allislands, $route);
- }
- }
}
sub parse_info_clientside () {
return $local;
}
-sub parse_info_maproutes ($$$) {
- my ($on, $allislands, $routemap) = @_;;
- foreach my $k (sort keys %$routemap) {
- my @ok= grep { index($_,$k) >= 0 } @$allislands;
- die "ambiguous $k" if @ok>1;
- if (!@ok) {
- $route_mysteries{$on}{$k}++;
- delete $routemap->{$k};
- } elsif ($ok[0] ne $k) {
- $routemap->{$ok[0]}= $routemap->{$k};
- delete $routemap->{$k};
- }
- }
-}
-
sub parse_info_serverside () {
parse_info1('source-info.txt','s');
}
initial/final stocks feature
- max volume/mass
-
max capital
better documentation
dist INTEGER NOT NULL,
PRIMARY KEY (aiid, biid)
);
+ CREATE TABLE IF NOT EXISTS vessels (
+ name TEXT NOT NULL,
+ mass INTEGER NOT NULL,
+ volume INTEGER NOT NULL,
+ shot INTEGER NOT NULL,
+ PRIMARY KEY (name)
+ );
END
;
$dbh->commit;
}
-#---------- island list ----------
-#---------- routes ----------
-# now done by yppedia-chart-parser
-
-__DATA__
+#---------- vessel types ----------
+{
+ my $idempotent= $dbh->prepare(<<'END')
+ INSERT OR REPLACE INTO vessels (name, shot, mass, volume)
+ VALUES (?,?,?,?)
+END
+ ;
+ foreach my $name (sort keys %vessels) {
+ my $v= $vessels{$name};
+ my $shotdamage= $shotname2damage{$v->{Shot}};
+ die "no shot damage for shot $v->{Shot} for vessel $name"
+ unless defined $shotdamage;
+ my @qa= ($name, $shotdamage, map { $v->{$_} } qw(Mass Volume));
+ $idempotent->execute(@qa);
+ }
+ $dbh->commit;
+}
#print Dumper($results);
print "strict graph $ocean {\n";
-#print " nodesep=10;\n";
+print " splines=true;\n";
+print " nslimit=10;\n";
+print " mclimit=10;\n";
foreach my $row (@$islands) {
my ($id,$str) = @$row;
}
foreach my $row (@$routes) {
my ($ia,$ib,$dist) = @$row;
- print " n$ia -- n$ib [ len=2, label=$dist ];\n";
- #len=$dist, minlen=$dist, weight=".(1.0/$dist).", len=".($dist*0.25+1).",
+ print " n$ia -- n$ib [ w=".(1.0/($dist*$dist)).", len=".(0.5*$dist+1).", label=$dist ];\n";
+ #len=$dist, minlen=$dist, , ,
#w=".(1.0/$dist).",
}
+vessels
+#| Ship Name |Gun Size|Volume | Mass |
+ |Sloop |small |20,250 |13,500 |
+ |----------------+--------+-------+-------|
+ |Cutter |small |60,750 |40,500 |
+ |----------------+--------+-------+-------|
+ |Dhow |medium |20,250 |13,500 |
+ |----------------+--------+-------+-------|
+ |Longship |small |20,250 |13,500 |
+ |----------------+--------+-------+-------|
+ |Baghlah |medium |27,000 |18,000 |
+ |----------------+--------+-------+-------|
+ |Merchant brig |medium |135,000|90,000 |
+ |----------------+--------+-------+-------|
+ |War brig |medium |81,000 |54,000 |
+ |----------------+--------+-------+-------|
+ |Merchant galleon|large |405,000|270,000|
+ |----------------+--------+-------+-------|
+ |Xebec |medium |182,250|121,500|
+ |----------------+--------+-------+-------|
+ |War frigate |large |324,000|216,000|
+ |----------------+--------+-------+-------|
+ |Grand frigate |large |810,000|540,000|
+# From http://yppedia.puzzlepirates.com/Ship; when updating,
+# delete unused columns and check heading is the same as above.
+# If fields reordered must change parser in Commods.pm.
+
+shot
+ small 2
+ medium 3
+ large 4
+
commods
kraken's blood 1kg
%c dye 1kg
next if $h =~ m/^nocommods/;
}
next if $sfn =~ m/source-info/ && $h =~ m/^ocean\b/;
- next if $h =~ m/^client\b/;
+ next if $h =~ m/^client|^vessels|^shot\b/;
print $df $_, "\n" or die $!;
}
<%perl>
+my @total_massvol;
+
if (!@flows) {
print 'No profitable trading opportunities were found.';
return;
foreach my $mv (qw(mass volume)) {
my $max_vn= "max_$mv";
my $max= $mv eq 'mass' ? $max_mass : $max_volume;
- next unless defined $max;
+ $max= 1e9 unless defined $max;
#print " DEFINED MAX $mv $max ";
$cplex .= "
". sprintf("%-10s","${mv}_$ci:")." ".
print "<pre>\n" if $qa->{'debug'};
my $found_section= 0;
my $glpsol_out= '';
+ my $continuation='';
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;
+ if (m/^\s*No\.\s+(Row|Column) name\s+(?:St\s+)?Activity\s/) {
+ die "$_ $found_section ?" if $found_section>0;
$found_section= 1;
next;
}
next unless $found_section==1;
- next if m/^[- ]+$/;
- if (!/\S/) {
- $found_section= 2;
- next;
+ if (!length $continuation) {
+ next if !$continuation && m/^[- ]+$/;
+ if (!/\S/) {
+ $found_section= 0;
+ next;
+ }
+ if (m/^ \s* \d+ \s+ \w+ $/x) {
+ $continuation= $&;
+ next;
+ }
+ }
+ $_= $continuation.$_;
+ $continuation= '';
+ my ($varname, $qty) = m/^
+ \s* \d+ \s+
+ (\w+) \s+ (?: [A-Z*]+ \s+ )?
+ ([0-9.]+) \s
+ /x or die "$_ ?";
+ if ($varname =~ m/^f(\d+)$/) {
+ my ($ix) = $1;
+ my $flow= $flows[$ix] or die;
+ $flow->{OptQty}= $qty;
+ $flow->{OptProfit}= $flow->{'unitprofit'} * $qty;
+ $flow->{OptCapital}= $flow->{OptQty} *
+ $flow->{'org_price'};
+ } elsif ($varname =~ m/^(mass|volume)_(\d+)$/) {
+ my ($mv,$ix) = ($1,$2);
+ $total_massvol[$ix]{$mv}= $qty;
}
- my ($ix, $qty) =
- m/^\s*\d+\s+f(\d+)\s+\S+\s+(\d+)\s/ or die "$_ ?";
- my $flow= $flows[$ix] or die;
- $flow->{OptQty}= $qty;
- $flow->{OptProfit}= $flow->{'unitprofit'} * $qty;
- $flow->{OptCapital}= $flow->{OptQty} * $flow->{'org_price'};
}
print "</pre>\n" if $qa->{'debug'};
my $prerr= "\n=====\n$cplex\n=====\n$glpsol_out\n=====\n ";
pipethrough_run_finish($output,$prerr);
- die $prerr unless $found_section;
+ map { defined $_->{OptQty} or die "$prerr $_->{Ix}" } @flows;
+# map { defined
+# die $prerr if grep { ! } @flows;
+# map { die
+# die $prerr if map {
};
$addcols->({ DoReverse => 1, Special => sub {
}
}
- my $total;
+ my ($total, $total_to_show);
my $dline= 0;
- my $show_flows= sub {
- my ($od,$arbitrage,$collectdeliver) = @_;
+ my $show_total= sub {
+ my ($totaldesc, $sign) = @_;
+ if (defined $total) {
+ die if defined $total_to_show;
+ $total_total += $sign * $total;
+ $total_to_show= [ $totaldesc, $total ];
+ $total= undef;
+ }
+ $dline= 0;
+ };
+ my $show_total_now= sub {
+ my ($xinfo) = @_;
+ return unless defined $total_to_show;
+ my ($totaldesc,$totalwas) = @$total_to_show;
</%perl>
-%
+<tr>
+<td colspan=1>
+<td colspan=2><% $xinfo %>
+<td colspan=2 align=right><% $totaldesc %>
+<td align=right><% $totalwas |h %> total
+<%perl>
+ $total_to_show= undef;
+ };
+</%perl>
+% 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;
+% $show_total_now->('');
% if (!$age_reported++) {
% my $age= $now - $t->{Timestamp};
% my $cellid= "da_${i}";
% $dline ^= 1;
% }
% };
-% my $show_total= sub {
-% 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->('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);
-
+ my $totals= '';
+ if ($i < $#islandids) {
+ $totals .= "In hold $total_massvol[$i]{mass} kg,".
+ " $total_massvol[$i]{volume} l";
+ my $delim= '; spare ';
+ my $domv= sub {
+ my ($max, $got, $units) = @_;
+ return unless defined $max;
+ $totals .= $delim;
+ $totals .= sprintf "%g %s", ($max-$got), $units;
+ $delim= ', ';
+ };
+ $domv->($max_mass, $total_massvol[$i]{mass}, 'kg');
+ $domv->($max_volume, $total_massvol[$i]{volume}, 'l');
+ $totals .= ".\n";
+ }
+ $show_total_now->($totals);
}
</%perl>
<tbody><tr>