From: Ian Jackson Date: Thu, 24 Sep 2009 18:11:13 +0000 (+0100) Subject: Merge branch 'stable-3.x' X-Git-Tag: 5.0^2~105 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~yarrgweb/git?p=ypp-sc-tools.db-live.git;a=commitdiff_plain;h=872e647cac241531e4599c8b8b330d8772020253;hp=8198bdb1afdf8ebedb130006e3af2af6b11045ab Merge branch 'stable-3.x' --- diff --git a/yarrg/Commods.pm b/yarrg/Commods.pm index 59ad3e1..372fe16 100644 --- a/yarrg/Commods.pm +++ b/yarrg/Commods.pm @@ -36,7 +36,8 @@ BEGIN { @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 @@ -54,8 +55,10 @@ our $masterinfoversion= 2; # version we understand 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 @@ -104,11 +107,24 @@ sub parse_info1 ($$$) { $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; @@ -163,22 +179,6 @@ sub parse_info1 ($$$) { } }; 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 () { @@ -203,21 +203,6 @@ sub fetch_with_rsync ($) { 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',0); } diff --git a/yarrg/CommodsWeb.pm b/yarrg/CommodsWeb.pm index 198185d..adcff34 100644 --- a/yarrg/CommodsWeb.pm +++ b/yarrg/CommodsWeb.pm @@ -51,6 +51,7 @@ BEGIN { @EXPORT = qw(&dbw_connect &ocean_list &sourcebasedir &to_json_shim &to_json_protecttags &set_ctype_utf8 + &expected_error &dbw_lookup_string &prettyprint_age &meta_prettyprint_age); %EXPORT_TAGS = ( ); @@ -151,4 +152,48 @@ BEGIN { eval ' } +sub dbw_lookup_string ($$$$$$$$) { # => ( $emsg, @dbresults ) + my ($each, + $sth, $stmt_nqs, $abbrev_initials, $maxambig, + $em_nomatch, $em_manyambig, $emf_ambiguous) = @_; + + $each =~ s/^\s*//; $each =~ s/\s*$//; $each =~ s/\s+/ /g; + my %m; + my $results; + my @pats= ("$each", "$each \%", "$each\%", "\%$each\%"); + if ($abbrev_initials) { + push @pats, join ' ', map { "$_%" } split //, $each; + } + foreach my $pat (@pats) { + $sth->execute(($pat) x $stmt_nqs); + $results= $sth->fetchall_arrayref(); + last if @$results==1; + $m{ $_->[0] }=1 for @$results; + $results= undef; + } + if (!$results) { + if (!%m) { + return $em_nomatch; + } elsif (keys(%m) > $maxambig) { + return $em_manyambig; + } else { + return $emf_ambiguous->($each, join(', ', sort keys %m)); + } + } + return (undef, @{ $results->[0] }); +} + +sub expected_error ($) { + my $r= { Emsg => $_[0] }; + bless $r, 'CommodsWeb::ExpectedError'; + die $r; +} + +package CommodsWeb::ExpectedError; + +sub emsg ($) { + my ($self) = @_; + return $self->{Emsg}; +} + 1; diff --git a/yarrg/README b/yarrg/README index 39c6090..b542a1c 100644 --- a/yarrg/README +++ b/yarrg/README @@ -172,6 +172,7 @@ for assisting players of Yohoho Puzzle Pirates. ypp-sc-tools and YARRG are Copyright (C) 2009 Ian Jackson Copyright (C) 2009 Clare Boothby +Copyright (C) 2009 Steve Early This program is free software: you can redistribute it and/or modify it under the terms of diff --git a/yarrg/TODO b/yarrg/TODO index 6b227eb..817ac0e 100644 --- a/yarrg/TODO +++ b/yarrg/TODO @@ -1,56 +1,31 @@ UPLOADER -------- - sometimes fails to work on Sage - sunshine widget resets or something +detect all unexpected mouse movements - detect all unexpected mouse movements +more flexible installation arrangements - more flexible installation arrangements +figure out why pctb.ilk.org isn't working - W windows uploader +windows uploader DATABASE/DICTIONARY MANAGER --------------------------- - commodity mass/volume in live database - eliminate black dye from live database +eliminate black dye from live database - when update rejected print better error message including - broken commodity name +when update rejected print better error message including + broken commodity name - notice commodities deleted from source-info and warn about them +notice commodities deleted from source-info and warn about them - support Opal and Jade (currently there are some unicode problems) +support Opal and Jade (currently there are some unicode problems) WEBSITE ------- - multi-visit routes / circular routes +allow unticking based on minimum margin or minimum profit - adjustable potential cost of losses (rather than fixed - 1e-BIG per league) - use power formula (compound interest) - suggest 0.5% +initial/final stocks feature - initial/final stocks feature - - max volume/mass - - max capital - - better documentation - - printable voyage trading plan - - -KEYLETTERS ----------- - -P needed before public release -O needed before public release to support multiple oceans - -C needs ypp client and network connection -N needs network connection -W needs to be done by someone with Windows - -D dependencies unsatisfied +printable voyage trading plan diff --git a/yarrg/db-idempotent-populate b/yarrg/db-idempotent-populate index 143e2ef..1d106f2 100755 --- a/yarrg/db-idempotent-populate +++ b/yarrg/db-idempotent-populate @@ -102,6 +102,13 @@ db_doall(<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; +} diff --git a/yarrg/ocean-topology-graph b/yarrg/ocean-topology-graph index 55d15d9..e609e35 100755 --- a/yarrg/ocean-topology-graph +++ b/yarrg/ocean-topology-graph @@ -20,7 +20,9 @@ $dbh->disconnect(); #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; @@ -29,8 +31,8 @@ foreach my $row (@$islands) { } 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).", } diff --git a/yarrg/source-info.txt b/yarrg/source-info.txt index b7d285b..88b9311 100644 --- a/yarrg/source-info.txt +++ b/yarrg/source-info.txt @@ -1,4 +1,36 @@ +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 diff --git a/yarrg/update-master-info b/yarrg/update-master-info index c0bbbff..e2b0973 100755 --- a/yarrg/update-master-info +++ b/yarrg/update-master-info @@ -95,7 +95,7 @@ sub process_some_info ($$$) { 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 $!; } diff --git a/yarrg/web/check_capacitystring b/yarrg/web/check_capacitystring index 3d8f7a5..a79b6f1 100644 --- a/yarrg/web/check_capacitystring +++ b/yarrg/web/check_capacitystring @@ -32,57 +32,159 @@ This Mason component simply defines how to interpret capacities. - -<%attr> - - -<%method preparse> +<%method execute> <%args> -$h +$string +$dbh +$debugf <%perl> -my $def= sub { - my ($what,$val) = @_; - if (defined $h->{$what}) { - $h->{Emsg}= "Multiple definitions of maximum $what."; +my $commodsth; + +my @mv_names= qw(mass volume); +my @mv_units= qw(kg l); + +my (@mv)= (undef,undef); +return ('',@mv) unless $string =~ m/\S/; + +my @canon= (); +my ($signum,$signopstr)= (+1,undef); +my $show_answer=0; +my $first_term=1; +my $last_signopstr= 'NONE'; + +my $canon_numeric= sub { + my ($val,$mvi) = @_; + sprintf "%g%s", $val, $mv_units[$mvi]; +}; + +my $parse_values= sub { + local ($_) = @_; + $debugf->("TERM VALUES '$_'"); + $_ .= ' '; + my $def= sub { + my ($mvi,$val) = @_; + if ($first_term) { + expected_error("Initial term specifies". + " $mv_names[$mvi] more than once.") + if defined $mv[$mvi]; + $mv[$mvi]= $val; + } else { + expected_error("Cannot add or subtract mass to/from volume") + unless defined $mv[$mvi]; + $mv[$mvi] += $signum * $val; + } + push @canon, $canon_numeric->($val,$mvi); + }; + while (m/\S/) { + $debugf->("VALUE '$_'"); + my $iqtyrex= '[1-9] \d{0,8}'; + my $fqtyrex= '\d{1,9} \. \d{0,3} |' . $iqtyrex; + if (s/^( $fqtyrex ) \s* kg \s+ //xo) { $def->(0, $1 ); } + elsif (s/^( $fqtyrex ) \s* t \s+ //xo) { $def->(0, $1 * 1000.0 ); } + elsif (s/^( $fqtyrex ) \s* l \s+ //xo) { $def->(1, $1 ); } + elsif (s/^( $fqtyrex ) \s* kl \s+ //xo) { $def->(1, $1 * 1000.0 ); } + elsif (s/^( $iqtyrex ) \s* ([a-z ]+) \s+ //xo) { + my ($qty,$spec) = ($1,$2); + $debugf->("VALUE COMMOD $qty '$spec'"); + expected_error("Capacity specification must start with". + " ship size or amount with units") + if $first_term; + $commodsth ||= + $dbh->prepare("SELECT commodname,unitmass,unitvolume + FROM commods WHERE commodname LIKE ?"); + my ($emsg,$commod,@umv)= + dbw_lookup_string($spec,$commodsth,1,0,0, + "No commodity or unit matches \`$spec'", + "Ambiguous commodity (or unit) \`$spec'", + undef); + expected_error($emsg) if defined $emsg; + $debugf->("VALUE COMMOD FOUND '$commod' @umv"); + foreach my $mvi (0,1) { + next unless defined $mv[$mvi]; + $mv[$mvi] += $signum * $qty * $umv[$mvi] * 0.001; + } + push @canon, sprintf "%d", $qty; + push @canon, $commod; + } else { + s/\s+$//; + expected_error("Did not understand value \`$_'"); } - print STDERR "SET $what $val\n"; - $h->{$what}= $val; + } }; -foreach $_ (split /\s+/, ${ $h->{String} }) { - print STDERR "ITEM \`$_'\n"; - next unless length; - if (m/^([1-9]\d{0,8})l$/) { - $def->('volume', $1); - } elsif (m/^([1-9]\d{0,8})kg$/) { - $def->('mass', $1); - } elsif (m/^([1-9]\d{0,5}(?:\.\d{0,3})?)kl/) { - $def->('volume', $1 * 1000); - } elsif (m/^([1-9]\d{0,5}(?:\.\d{0,3})?)t/) { - $def->('mass', $1 * 1000); +my $parse_term= sub { + local ($_) = @_; + $debugf->("TERM '$_' signum=$signum"); + s/^\s+//; s/\s+$//; + expected_error("empty term in capacity") unless m/\S/; + if (m/^\s*(\d{1,2}(?:\.\d{0,4})?)\%\s*$/) { + $debugf->("TERM PERCENT $1"); + expected_error("percentage may not be first item") + if $first_term; + my $pct= 100.0 + $signum * $1; + foreach (@mv) { + next unless defined; + $_ *= $pct / 100.0; + } + push @canon, sprintf "%g%%", $pct; + } elsif (!m/[^a-z]/) { + $debugf->("TERM NAME"); + expected_error("Name (should be unit or commodity) \`$_'". + " without preceding quantity") + unless $first_term; + my $sth= $dbh->prepare("SELECT name,mass,volume". + " FROM vessels WHERE name LIKE ?"); + my ($emsg,$ship,@smv)= + dbw_lookup_string($_,$sth,1,1,2, + "Ship name `$_' not understood.", + "Too many matching ship types.", + sub { "Ambiguous - could be $_[0]" }); + expected_error($emsg) if defined $emsg; + $debugf->("TERM NAME SHIP '$ship' @smv"); + $show_answer= 1; + @mv = @smv; + push @canon, $ship; } else { - ${ $h->{Emsg} }= "Cannot understand capacity \`$_'."; - last; + $parse_values->($_); } + $first_term= 0; +}; + +while ($string =~ s/^(.*?)(\bminus\b|-|\bplus\b|\+)//) { + my ($lhs)= ($1); + my @nextsign= $2 =~ m/^p|^\+/ ? (+1,'+') : (-1,'-'); + $show_answer= 1; + $debugf->("GROUP S='$2'"); + $parse_term->($lhs); + ($signum,$signopstr)= @nextsign; + push @canon, ($last_signopstr=$signopstr) + if $signopstr ne $last_signopstr; } - - +$parse_term->($string); -<%method postquery> -<%args> -$h - -<%perl> +my $canon= join ' ', @canon; -if (defined $h->{'mass'} or defined $h->{'volume'}) { - @{ $h->{Results} } = [ $h->{'mass'}, $h->{'volume'} ]; +if ($show_answer) { + $canon .= " [="; + foreach my $mvi (0,1) { + next unless defined $mv[$mvi]; + $canon .= ' '.$canon_numeric->($mv[$mvi], $mvi); + } + $canon .= "]"; +} - ${ $h->{Canon} }= - 'mass limit: '.(defined $h->{'mass'} ? $h->{'mass'} .'kg' : 'none').'; '. - 'volume limit: '.(defined $h->{'volume'} ? $h->{'volume'} .'l' : 'none').'.'; +$debugf->("FINISHING canon='$canon'"); + +foreach my $mvi (0,1) { + next unless defined $mv[$mvi]; + next if $mv[$mvi] >= 0; + expected_error(sprintf "%s limit is negative: %s", + ucfirst($mv_names[$mvi]), $canon_numeric->($mv[$mvi], $mvi)); } +return ($canon, @mv); + diff --git a/yarrg/web/check_capitalstring b/yarrg/web/check_capitalstring new file mode 100644 index 0000000..53aceec --- /dev/null +++ b/yarrg/web/check_capitalstring @@ -0,0 +1,62 @@ +<%doc> + + This is part of the YARRG website. YARRG is a tool and website + for assisting players of Yohoho Puzzle Pirates. + + Copyright (C) 2009 Ian Jackson + Copyright (C) 2009 Clare Boothby + + YARRG's client code etc. is covered by the ordinary GNU GPL (v3 or later). + The YARRG website is covered by the GNU Affero GPL v3 or later, which + basically means that every installation of the website will let you + download the source. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + + Yohoho and Puzzle Pirates are probably trademarks of Three Rings and + are used without permission. This program is not endorsed or + sponsored by Three Rings. + + + This Mason component simply defines how to interpret capital. + + + +<%method execute> +<%args> +$string +$dbh +$debugf + +<%perl> + +$_= $string; +s/^\s+//; s/\s+$//; + +my $capital; +my $canon; + +if (!m/\S/) { + $canon= ''; +} elsif (m/^([1-9]\d*)( PoE)?$/i) { + $capital= $1; + $canon= "$capital PoE"; +} else { + expected_error("Cannot understand capital \`$_'."); +} + +return ($canon,$capital); + + + diff --git a/yarrg/web/check_lossperleague b/yarrg/web/check_lossperleague index 5994f6f..9375355 100644 --- a/yarrg/web/check_lossperleague +++ b/yarrg/web/check_lossperleague @@ -29,37 +29,35 @@ sponsored by Three Rings. - This Mason component simply defines how to interpret capacities. + This Mason component simply defines how to interpret losses per league. - -<%attr> - - -<%method preparse> +<%method execute> <%args> -$h +$string +$dbh +$debugf <%perl> -$_= ${ $h->{String} }; +$_= $string; s/^\s+//; s/\s+$//; -my $res= sub { - my ($pct,$str) = @_; - push @{ $h->{Results} }, [ $pct ]; - ${ $h->{Canon} }= "$str per league"; -}; +my ($pct,$str); if (!m/\S/) { + $str= ''; } elsif (m/^(\d{1,2}(?:\.\d{0,5})?)\%$/) { - $res->( $1 * 1.0, sprintf("%g%%", $1) ); + $pct= $1 * 1.0; + $str= sprintf("%g%%", $1); } elsif (m/^1\s*\/\s*([1-9]\d{0,4})/) { - $res->( 100.0/$1, sprintf("1/%d", $1) ); + $pct= 100.0/$1; + $str= sprintf("1/%d", $1); } else { - ${ $h->{Emsg} }= "Cannot understand loss per league \`$_'."; - return; + expected_error("Cannot understand loss per league \`$_'."); } +return ("$str per league", $pct); + diff --git a/yarrg/web/copyrightdate b/yarrg/web/copyrightdate index e7d2dc8..6af4e75 100644 --- a/yarrg/web/copyrightdate +++ b/yarrg/web/copyrightdate @@ -1 +1 @@ -Copyright 2009 Ian Jackson, Clare Boothby \ No newline at end of file +Copyright 2009 Ian Jackson, Clare Boothby, Steve Early \ No newline at end of file diff --git a/yarrg/web/devel b/yarrg/web/devel index 513d50b..fecd77d 100755 --- a/yarrg/web/devel +++ b/yarrg/web/devel @@ -33,17 +33,18 @@ -YARRG (Yet Another Revenue Research Gatherer) + +YARRG (Yet Another Revenue Research Gatherer) YARRG - Yet Another Revenue Research Gatherer | -development -| introduction | documentation +| +development

YARRG development, contribution and troubleshooting

@@ -53,7 +54,7 @@ YARRG is Free Software - you may share and modify it. See the licences for details. Not only the client but also the website code is Free. The yarrg client, support files, and so forth are under the GNU GPL (v3 or later); the website is under the GNU Affero GPL (v3 -or later).

+or later).

@@ -123,9 +124,9 @@ has the specification of the mechanism and format for uploading to YARRG. If you would like to run a (perhaps modified) copy of the YARRG website it would be very easy for us to make our system send you copies of updates submitted by users of the official YARRG client, in -the format expected by the YARRG code. Please just ask us - it's just -a matter of us adding your database instance's special email address -to our alias file. +the format expected by the YARRG code. Please just ask us - at our +end it's just a matter of us adding your database instance's special +email address to our alias file.

diff --git a/yarrg/web/docs b/yarrg/web/docs index cbb1c0d..c211683 100755 --- a/yarrg/web/docs +++ b/yarrg/web/docs @@ -33,17 +33,17 @@ -Website documentation - YARRG +Website documentation - YARRG YARRG - Yet Another Revenue Research Gatherer | -development -| introduction | documentation +| +development

Looking up data in YARRG

@@ -101,7 +101,7 @@ After getting the results, you can untick various trades individually, and select `Update' to get a new plan. The unticked trades will be excluded from the voyage plan (if any) and also from the totals. -

Vessel capacity

+

Vessel capacity

If you don't specify a vessel or a vessel capacity, the trading plan will not take into account the fact that your voyage will be on a ship @@ -110,13 +110,41 @@ which trades excessively cumbersome goods (eg. hemp, wood, iron).

-So you should specify your vessel capacity. Currently you must -specify the actual mass and volume, as two numbers each with units. -The system understands the units t (tonnes), kg, l and kl -(kilolitres). There should be a space between the two limits, and no -space before the unit. +So you should specify your vessel capacity. You can enter things +like: +

+
sloop +
The capacity of a sloop, leaving no allowance for rum and shot +
wb - 1% +
The capacity of a war brig minus 1% +
13t 20kl +
13 tonnes (13,000kg), 20 kilolitres (20,000l) +
sloop - 10 small 40 rum +
The capacity of a sloop which remains after + 10 small shot and 40 rum are loaded +
2t plus 500kg minus 200kg +
2300kg, with no limit on volume +
+Evaluation is strictly from left to right. + +

+ +More formally: +

+ capacity-string := [ first-term term* ]
+ term := ('+' | '-' | 'plus' | 'minus') (value+ | number'%')
+ value := mass | volume
+        | integer commodity-name-or-abbreviation
+ mass := number ('t' | 'kg')
+ volume := number ('kl' | 'l')
+ first-term := mass | volume | mass volume | volume mass
+             | ship-name-or-abbreviation
+
-

Expected losses

+If the first term specifies only one of mass or volume, all the +subsequent terms may only adjust that same value. + +

Expected losses

In theory if you were guaranteed to have a trouble-free voyage it would be worth trading goods at very low margins. However, in @@ -134,25 +162,44 @@ to do.

-Trades whose margin is less than the expected loss are never selected. -For example, if you select 1% loss per league, and plan a voyage of 5 -leagues, then any trade with a margin of less than 5.15% would be -completely excluded (5.15% not 5% because the loss works like compound -interest). Theoretically very profitable trades which are close to -the expected break-even point because of the distance can also be -rejected by the optimiser in favour of shorter distance trades with -theoretically smaller margins. +Trades whose margin is less than the expected loss are never included +in the suggested plan. For example, if you select 1% loss per league, +and plan a voyage of 5 leagues, then any trade with a margin of less +than 5.15% would be completely excluded (5.15% not 5% because the loss +works like compound interest). Theoretically very profitable trades +which are close to the expected break-even point because of the +distance can also be rejected by the optimiser in favour of shorter +distance trades with theoretically smaller margins, if it's not +possible to do both.

-As a guide: you may expect to lose between 0.1% and 1% per league. -0.1% would correspond, for example, to losing one fight to brigands -every ten 10-league voyages. +As a guide: you may expect to lose between 0.01% and 1% per league. +For example 0.1% would correspond to losing one fight to brigands (who +take 10% if they win) for every 100 leagues sailed.

You can enter the value in the box either as a percentage, or as a -fraction 1/divisor, eg 1/200 is the same as 0.5%; in each +fraction 1/divisor, eg 1/2000 is the same as 0.05%; in each case it is taken as the loss for each league of the voyage. +

Available capital

+ +If you don't specify the amount of capital you have available to +invest in the voyage, the trading plan will assume that your capital +is unlimited. If you specify an amount in PoE here, the trading plan +will never require you to spend more than that amount on commodities. + +

+ +The trading plan does not take into account accumulated profits from +each leg of the journey when applying the available capital +constraint. For example, if you specify a journey from A to B to C +and a capital limit of 10000 PoE, the trading plan will not tell you +to buy 1000 peas at A for 10 PoE each, sail them to B and sell all of +them for 20 PoE each, and then buy 2000 beans at B for 10 PoE each and +sail them to C to sell for 20 PoE each even if such a trade would in +fact be possible. In practice this is unlikely to be a problem! + <& footer &> diff --git a/yarrg/web/dumptable b/yarrg/web/dumptable index e60415c..739f14d 100644 --- a/yarrg/web/dumptable +++ b/yarrg/web/dumptable @@ -31,7 +31,7 @@ This Mason component is helpful for debugging and developing. It outputs plain HTML tables eg for SQL query results. You can either: - <& dumptable, sth = $executed_statement_handle &> + <& dumptable, sth => $executed_statement_handle &> in which case it will consume the results of the statement and print them unconditionally, or do the equivalent of: <& dumptable:start, sth => $sth, [ qa => $qa ] &> or diff --git a/yarrg/web/enter_commod b/yarrg/web/enter_commod new file mode 100644 index 0000000..c3f5553 --- /dev/null +++ b/yarrg/web/enter_commod @@ -0,0 +1,73 @@ +<%doc> + + This is part of the YARRG website. YARRG is a tool and website + for assisting players of Yohoho Puzzle Pirates. + + Copyright (C) 2009 Ian Jackson + Copyright (C) 2009 Clare Boothby + + YARRG's client code etc. is covered by the ordinary GNU GPL (v3 or later). + The YARRG website is covered by the GNU Affero GPL v3 or later, which + basically means that every installation of the website will let you + download the source. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + + Yohoho and Puzzle Pirates are probably trademarks of Three Rings and + are used without permission. This program is not endorsed or + sponsored by Three Rings. + + + This Mason component generates form contents for selecting a commodity. + + + +<%args> +$qa +$dbh +$emsg_r + +$commodname_r +$cmid_r + + +%#---------- textbox, user enters commodity as string ---------- +% if (!$qa->{Dropdowns}) { + +Enter commodity (abbreviations are OK):
+ +<&| qtextstring, qa => $qa, dbh => $dbh, emsgstore => $emsg_r, + thingstring => 'commodstring', prefix => 'cm', + onresults => sub { ($$commodname_r,$$cmid_r)= @{ $_[0] } if @_ } + &> + size=80 + + +% } else { #---------- dropdowns, user selects from menus ---------- + +% my $sth= $dbh->prepare("SELECT commodname,commodid FROM commods +% ORDER BY commodname"); +% $sth->execute(); +% my $row; + +

+ +% } #---------- end of dropdowns, now common middle of page code ---------- diff --git a/yarrg/web/enter_route b/yarrg/web/enter_route new file mode 100644 index 0000000..c21d967 --- /dev/null +++ b/yarrg/web/enter_route @@ -0,0 +1,191 @@ +<%doc> + + This is part of the YARRG website. YARRG is a tool and website + for assisting players of Yohoho Puzzle Pirates. + + Copyright (C) 2009 Ian Jackson + Copyright (C) 2009 Clare Boothby + + YARRG's client code etc. is covered by the ordinary GNU GPL (v3 or later). + The YARRG website is covered by the GNU Affero GPL v3 or later, which + basically means that every installation of the website will let you + download the source. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + + Yohoho and Puzzle Pirates are probably trademarks of Three Rings and + are used without permission. This program is not endorsed or + sponsored by Three Rings. + + + This Mason component generates form contents for selecting a list + of locations (eg, a route). + + + +<%args> +$qa +$dbh +$emsg_r +$warningfs_r + +$enterwhat +$islandids_r +$archipelagoes_r + + +%#---------- textbox, user enters route as string ---------- +% if (!$qa->{Dropdowns}) { + +<% $enterwhat %> (islands, or archipelagoes, separated by |s or commas; + abbreviations are OK):
+ +<&| qtextstring, qa => $qa, dbh => $dbh, emsgstore => $emsg_r, + thingstring => 'routestring', prefix => 'rl', + onresults => sub { + foreach (@_) { + my ($canonname, $island, $arch) = @$_; + push @$islandids_r, $island; + push @$archipelagoes_r, defined $island ? undef : $arch; + } + } + &> + size=80 + + +% } else { #---------- dropdowns, user selects from menus ---------- + +<%perl> +my %islandid2; +my ($sth,$row); +my @archlistdata; +my %islandlistdata; +$islandlistdata{'none'}= [ [ "none", "Select island..." ] ]; + +my $optionlistmap= sub { + my ($optlist, $selected) = @_; + my $out=''; + foreach my $entry (@$optlist) { + $out.= sprintf('', + encode_entities($entry->[0]), + defined $selected && $entry->[0] eq $selected + ? 'selected' : '', + encode_entities($entry->[1])); + } + return $out; +}; + +$sth= $dbh->prepare("SELECT DISTINCT archipelago FROM islands + ORDER BY archipelago;"); +$sth->execute(); + +while ($row=$sth->fetchrow_arrayref) { + my ($arch)= @$row; + push @archlistdata, [ $arch, $arch ]; + $islandlistdata{$arch}= [ [ "none", "Whole arch" ] ]; +} + +$sth= $dbh->prepare("SELECT islandid,islandname,archipelago + FROM islands + ORDER BY islandname;"); +$sth->execute(); + +while ($row=$sth->fetchrow_arrayref) { + my $arch= $row->[2]; + push @{ $islandlistdata{'none'} }, [ @$row ]; + push @{ $islandlistdata{$arch} }, [ @$row ]; + $islandid2{$row->[0]}= { Name => $row->[1], Arch => $arch }; +} + +my %resetislandlistdata; +foreach my $arch (keys %islandlistdata) { + $resetislandlistdata{$arch}= + $optionlistmap->($islandlistdata{$arch}, ''); +} + + + +<&| script &> +ms_lists= <% to_json_protecttags(\%resetislandlistdata) %>; +function ms_Setarch(dd) { + debug('ms_SetArch '+dd+' arch='+arch); + var arch= document.getElementsByName('archipelago'+dd).item(0).value; + var got= ms_lists[arch]; + if (got == undefined) return; // unknown arch ? hrm + debug('ms_SetArch '+dd+' arch='+arch+' got ok'); + var select= document.getElementsByName('islandid'+dd).item(0); + select.innerHTML= got; + debug('ms_SetArch '+dd+' arch='+arch+' innerHTML set'); +} + + + + + +% for my $dd (0..$qa->{Dropdowns}-1) { + +% } + + + +% for my $dd (0..$qa->{Dropdowns}-1) { +% my $arch= $qa->{"archipelago$dd"}; +% $arch= 'none' if !defined $arch; + +% } + + +
+
+
+ +<%perl> + +my $argorundef= sub { + my ($dd,$base) = @_; + my $thing= $qa->{"${base}${dd}"}; + $thing= undef if defined $thing and $thing eq 'none'; + return $thing; +}; + +for my $dd (0..$qa->{Dropdowns}-1) { + my $arch= $argorundef->($dd,'archipelago'); + my $island= $argorundef->($dd,'islandid'); + next unless defined $arch or defined $island; + if (defined $island and defined $arch) { + my $ii= $islandid2{$island}; + my $iarch= $ii->{Arch}; + if ($iarch ne $arch) { + push @$warningfs_r, sub { + + Specified archipelago <% $arch %> but + island <% $ii->{Name} %> + which is in <% $iarch %>; using the island.

+<%perl> + }; + } + $arch= undef; + } + push @$archipelagoes_r, $arch; + push @$islandids_r, $island; +} + + +

+ +% } diff --git a/yarrg/web/footer b/yarrg/web/footer index 9837d53..75fcd15 100644 --- a/yarrg/web/footer +++ b/yarrg/web/footer @@ -47,6 +47,7 @@ YARRG is Free Software. You may share and modify the code and the website, according to the terms of the GNU General Public Licence and the GNU Affero General Public Licence respectively (v3 or later). +Note that there is NO WARRANTY. % if (!$isdevel) { Please see the YARRG Development webpage for details of how to obtain the client and server code and full details diff --git a/yarrg/web/intro b/yarrg/web/intro index c77f183..467de52 100755 --- a/yarrg/web/intro +++ b/yarrg/web/intro @@ -33,17 +33,18 @@ -YARRG (Yet Another Revenue Research Gatherer) + +YARRG (Yet Another Revenue Research Gatherer) YARRG - Yet Another Revenue Research Gatherer | -development -| introduction | documentation +| +development

Introduction to YARRG

@@ -68,7 +69,7 @@ website.

Uploading from Linux

The YARRG upload client uploads both to YARRG and to the -PCTB testing server. +PCTB testing server.

diff --git a/yarrg/web/lookup b/yarrg/web/lookup index 7b3100e..7af431c 100755 --- a/yarrg/web/lookup +++ b/yarrg/web/lookup @@ -57,6 +57,7 @@ my %styles; Before => 'Query: ', Values => [ [ 'route', 'Trades for route' ], [ 'commod', 'Prices for commodity' ], + [ 'offers', 'Offers at location' ], [ 'age', 'Data age' ] ] }, { Name => 'BuySell', Before => '', @@ -118,7 +119,7 @@ $ours % } -<% ucfirst $ahtml{Query} %> - YARRG +<% ucfirst $ahtml{Query} %> - YARRG